162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/* Copyright (c) 2018, Intel Corporation. */
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci#include "ice_common.h"
562306a36Sopenharmony_ci#include "ice_sched.h"
662306a36Sopenharmony_ci#include "ice_adminq_cmd.h"
762306a36Sopenharmony_ci#include "ice_flow.h"
862306a36Sopenharmony_ci#include "ice_ptp_hw.h"
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#define ICE_PF_RESET_WAIT_COUNT	300
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_cistatic const char * const ice_link_mode_str_low[] = {
1362306a36Sopenharmony_ci	[0] = "100BASE_TX",
1462306a36Sopenharmony_ci	[1] = "100M_SGMII",
1562306a36Sopenharmony_ci	[2] = "1000BASE_T",
1662306a36Sopenharmony_ci	[3] = "1000BASE_SX",
1762306a36Sopenharmony_ci	[4] = "1000BASE_LX",
1862306a36Sopenharmony_ci	[5] = "1000BASE_KX",
1962306a36Sopenharmony_ci	[6] = "1G_SGMII",
2062306a36Sopenharmony_ci	[7] = "2500BASE_T",
2162306a36Sopenharmony_ci	[8] = "2500BASE_X",
2262306a36Sopenharmony_ci	[9] = "2500BASE_KX",
2362306a36Sopenharmony_ci	[10] = "5GBASE_T",
2462306a36Sopenharmony_ci	[11] = "5GBASE_KR",
2562306a36Sopenharmony_ci	[12] = "10GBASE_T",
2662306a36Sopenharmony_ci	[13] = "10G_SFI_DA",
2762306a36Sopenharmony_ci	[14] = "10GBASE_SR",
2862306a36Sopenharmony_ci	[15] = "10GBASE_LR",
2962306a36Sopenharmony_ci	[16] = "10GBASE_KR_CR1",
3062306a36Sopenharmony_ci	[17] = "10G_SFI_AOC_ACC",
3162306a36Sopenharmony_ci	[18] = "10G_SFI_C2C",
3262306a36Sopenharmony_ci	[19] = "25GBASE_T",
3362306a36Sopenharmony_ci	[20] = "25GBASE_CR",
3462306a36Sopenharmony_ci	[21] = "25GBASE_CR_S",
3562306a36Sopenharmony_ci	[22] = "25GBASE_CR1",
3662306a36Sopenharmony_ci	[23] = "25GBASE_SR",
3762306a36Sopenharmony_ci	[24] = "25GBASE_LR",
3862306a36Sopenharmony_ci	[25] = "25GBASE_KR",
3962306a36Sopenharmony_ci	[26] = "25GBASE_KR_S",
4062306a36Sopenharmony_ci	[27] = "25GBASE_KR1",
4162306a36Sopenharmony_ci	[28] = "25G_AUI_AOC_ACC",
4262306a36Sopenharmony_ci	[29] = "25G_AUI_C2C",
4362306a36Sopenharmony_ci	[30] = "40GBASE_CR4",
4462306a36Sopenharmony_ci	[31] = "40GBASE_SR4",
4562306a36Sopenharmony_ci	[32] = "40GBASE_LR4",
4662306a36Sopenharmony_ci	[33] = "40GBASE_KR4",
4762306a36Sopenharmony_ci	[34] = "40G_XLAUI_AOC_ACC",
4862306a36Sopenharmony_ci	[35] = "40G_XLAUI",
4962306a36Sopenharmony_ci	[36] = "50GBASE_CR2",
5062306a36Sopenharmony_ci	[37] = "50GBASE_SR2",
5162306a36Sopenharmony_ci	[38] = "50GBASE_LR2",
5262306a36Sopenharmony_ci	[39] = "50GBASE_KR2",
5362306a36Sopenharmony_ci	[40] = "50G_LAUI2_AOC_ACC",
5462306a36Sopenharmony_ci	[41] = "50G_LAUI2",
5562306a36Sopenharmony_ci	[42] = "50G_AUI2_AOC_ACC",
5662306a36Sopenharmony_ci	[43] = "50G_AUI2",
5762306a36Sopenharmony_ci	[44] = "50GBASE_CP",
5862306a36Sopenharmony_ci	[45] = "50GBASE_SR",
5962306a36Sopenharmony_ci	[46] = "50GBASE_FR",
6062306a36Sopenharmony_ci	[47] = "50GBASE_LR",
6162306a36Sopenharmony_ci	[48] = "50GBASE_KR_PAM4",
6262306a36Sopenharmony_ci	[49] = "50G_AUI1_AOC_ACC",
6362306a36Sopenharmony_ci	[50] = "50G_AUI1",
6462306a36Sopenharmony_ci	[51] = "100GBASE_CR4",
6562306a36Sopenharmony_ci	[52] = "100GBASE_SR4",
6662306a36Sopenharmony_ci	[53] = "100GBASE_LR4",
6762306a36Sopenharmony_ci	[54] = "100GBASE_KR4",
6862306a36Sopenharmony_ci	[55] = "100G_CAUI4_AOC_ACC",
6962306a36Sopenharmony_ci	[56] = "100G_CAUI4",
7062306a36Sopenharmony_ci	[57] = "100G_AUI4_AOC_ACC",
7162306a36Sopenharmony_ci	[58] = "100G_AUI4",
7262306a36Sopenharmony_ci	[59] = "100GBASE_CR_PAM4",
7362306a36Sopenharmony_ci	[60] = "100GBASE_KR_PAM4",
7462306a36Sopenharmony_ci	[61] = "100GBASE_CP2",
7562306a36Sopenharmony_ci	[62] = "100GBASE_SR2",
7662306a36Sopenharmony_ci	[63] = "100GBASE_DR",
7762306a36Sopenharmony_ci};
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_cistatic const char * const ice_link_mode_str_high[] = {
8062306a36Sopenharmony_ci	[0] = "100GBASE_KR2_PAM4",
8162306a36Sopenharmony_ci	[1] = "100G_CAUI2_AOC_ACC",
8262306a36Sopenharmony_ci	[2] = "100G_CAUI2",
8362306a36Sopenharmony_ci	[3] = "100G_AUI2_AOC_ACC",
8462306a36Sopenharmony_ci	[4] = "100G_AUI2",
8562306a36Sopenharmony_ci};
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci/**
8862306a36Sopenharmony_ci * ice_dump_phy_type - helper function to dump phy_type
8962306a36Sopenharmony_ci * @hw: pointer to the HW structure
9062306a36Sopenharmony_ci * @low: 64 bit value for phy_type_low
9162306a36Sopenharmony_ci * @high: 64 bit value for phy_type_high
9262306a36Sopenharmony_ci * @prefix: prefix string to differentiate multiple dumps
9362306a36Sopenharmony_ci */
9462306a36Sopenharmony_cistatic void
9562306a36Sopenharmony_ciice_dump_phy_type(struct ice_hw *hw, u64 low, u64 high, const char *prefix)
9662306a36Sopenharmony_ci{
9762306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_PHY, "%s: phy_type_low: 0x%016llx\n", prefix, low);
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci	for (u32 i = 0; i < BITS_PER_TYPE(typeof(low)); i++) {
10062306a36Sopenharmony_ci		if (low & BIT_ULL(i))
10162306a36Sopenharmony_ci			ice_debug(hw, ICE_DBG_PHY, "%s:   bit(%d): %s\n",
10262306a36Sopenharmony_ci				  prefix, i, ice_link_mode_str_low[i]);
10362306a36Sopenharmony_ci	}
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_PHY, "%s: phy_type_high: 0x%016llx\n", prefix, high);
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci	for (u32 i = 0; i < BITS_PER_TYPE(typeof(high)); i++) {
10862306a36Sopenharmony_ci		if (high & BIT_ULL(i))
10962306a36Sopenharmony_ci			ice_debug(hw, ICE_DBG_PHY, "%s:   bit(%d): %s\n",
11062306a36Sopenharmony_ci				  prefix, i, ice_link_mode_str_high[i]);
11162306a36Sopenharmony_ci	}
11262306a36Sopenharmony_ci}
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci/**
11562306a36Sopenharmony_ci * ice_set_mac_type - Sets MAC type
11662306a36Sopenharmony_ci * @hw: pointer to the HW structure
11762306a36Sopenharmony_ci *
11862306a36Sopenharmony_ci * This function sets the MAC type of the adapter based on the
11962306a36Sopenharmony_ci * vendor ID and device ID stored in the HW structure.
12062306a36Sopenharmony_ci */
12162306a36Sopenharmony_cistatic int ice_set_mac_type(struct ice_hw *hw)
12262306a36Sopenharmony_ci{
12362306a36Sopenharmony_ci	if (hw->vendor_id != PCI_VENDOR_ID_INTEL)
12462306a36Sopenharmony_ci		return -ENODEV;
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci	switch (hw->device_id) {
12762306a36Sopenharmony_ci	case ICE_DEV_ID_E810C_BACKPLANE:
12862306a36Sopenharmony_ci	case ICE_DEV_ID_E810C_QSFP:
12962306a36Sopenharmony_ci	case ICE_DEV_ID_E810C_SFP:
13062306a36Sopenharmony_ci	case ICE_DEV_ID_E810_XXV_BACKPLANE:
13162306a36Sopenharmony_ci	case ICE_DEV_ID_E810_XXV_QSFP:
13262306a36Sopenharmony_ci	case ICE_DEV_ID_E810_XXV_SFP:
13362306a36Sopenharmony_ci		hw->mac_type = ICE_MAC_E810;
13462306a36Sopenharmony_ci		break;
13562306a36Sopenharmony_ci	case ICE_DEV_ID_E823C_10G_BASE_T:
13662306a36Sopenharmony_ci	case ICE_DEV_ID_E823C_BACKPLANE:
13762306a36Sopenharmony_ci	case ICE_DEV_ID_E823C_QSFP:
13862306a36Sopenharmony_ci	case ICE_DEV_ID_E823C_SFP:
13962306a36Sopenharmony_ci	case ICE_DEV_ID_E823C_SGMII:
14062306a36Sopenharmony_ci	case ICE_DEV_ID_E822C_10G_BASE_T:
14162306a36Sopenharmony_ci	case ICE_DEV_ID_E822C_BACKPLANE:
14262306a36Sopenharmony_ci	case ICE_DEV_ID_E822C_QSFP:
14362306a36Sopenharmony_ci	case ICE_DEV_ID_E822C_SFP:
14462306a36Sopenharmony_ci	case ICE_DEV_ID_E822C_SGMII:
14562306a36Sopenharmony_ci	case ICE_DEV_ID_E822L_10G_BASE_T:
14662306a36Sopenharmony_ci	case ICE_DEV_ID_E822L_BACKPLANE:
14762306a36Sopenharmony_ci	case ICE_DEV_ID_E822L_SFP:
14862306a36Sopenharmony_ci	case ICE_DEV_ID_E822L_SGMII:
14962306a36Sopenharmony_ci	case ICE_DEV_ID_E823L_10G_BASE_T:
15062306a36Sopenharmony_ci	case ICE_DEV_ID_E823L_1GBE:
15162306a36Sopenharmony_ci	case ICE_DEV_ID_E823L_BACKPLANE:
15262306a36Sopenharmony_ci	case ICE_DEV_ID_E823L_QSFP:
15362306a36Sopenharmony_ci	case ICE_DEV_ID_E823L_SFP:
15462306a36Sopenharmony_ci		hw->mac_type = ICE_MAC_GENERIC;
15562306a36Sopenharmony_ci		break;
15662306a36Sopenharmony_ci	default:
15762306a36Sopenharmony_ci		hw->mac_type = ICE_MAC_UNKNOWN;
15862306a36Sopenharmony_ci		break;
15962306a36Sopenharmony_ci	}
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_INIT, "mac_type: %d\n", hw->mac_type);
16262306a36Sopenharmony_ci	return 0;
16362306a36Sopenharmony_ci}
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci/**
16662306a36Sopenharmony_ci * ice_is_e810
16762306a36Sopenharmony_ci * @hw: pointer to the hardware structure
16862306a36Sopenharmony_ci *
16962306a36Sopenharmony_ci * returns true if the device is E810 based, false if not.
17062306a36Sopenharmony_ci */
17162306a36Sopenharmony_cibool ice_is_e810(struct ice_hw *hw)
17262306a36Sopenharmony_ci{
17362306a36Sopenharmony_ci	return hw->mac_type == ICE_MAC_E810;
17462306a36Sopenharmony_ci}
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci/**
17762306a36Sopenharmony_ci * ice_is_e810t
17862306a36Sopenharmony_ci * @hw: pointer to the hardware structure
17962306a36Sopenharmony_ci *
18062306a36Sopenharmony_ci * returns true if the device is E810T based, false if not.
18162306a36Sopenharmony_ci */
18262306a36Sopenharmony_cibool ice_is_e810t(struct ice_hw *hw)
18362306a36Sopenharmony_ci{
18462306a36Sopenharmony_ci	switch (hw->device_id) {
18562306a36Sopenharmony_ci	case ICE_DEV_ID_E810C_SFP:
18662306a36Sopenharmony_ci		switch (hw->subsystem_device_id) {
18762306a36Sopenharmony_ci		case ICE_SUBDEV_ID_E810T:
18862306a36Sopenharmony_ci		case ICE_SUBDEV_ID_E810T2:
18962306a36Sopenharmony_ci		case ICE_SUBDEV_ID_E810T3:
19062306a36Sopenharmony_ci		case ICE_SUBDEV_ID_E810T4:
19162306a36Sopenharmony_ci		case ICE_SUBDEV_ID_E810T6:
19262306a36Sopenharmony_ci		case ICE_SUBDEV_ID_E810T7:
19362306a36Sopenharmony_ci			return true;
19462306a36Sopenharmony_ci		}
19562306a36Sopenharmony_ci		break;
19662306a36Sopenharmony_ci	case ICE_DEV_ID_E810C_QSFP:
19762306a36Sopenharmony_ci		switch (hw->subsystem_device_id) {
19862306a36Sopenharmony_ci		case ICE_SUBDEV_ID_E810T2:
19962306a36Sopenharmony_ci		case ICE_SUBDEV_ID_E810T3:
20062306a36Sopenharmony_ci		case ICE_SUBDEV_ID_E810T5:
20162306a36Sopenharmony_ci			return true;
20262306a36Sopenharmony_ci		}
20362306a36Sopenharmony_ci		break;
20462306a36Sopenharmony_ci	default:
20562306a36Sopenharmony_ci		break;
20662306a36Sopenharmony_ci	}
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci	return false;
20962306a36Sopenharmony_ci}
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci/**
21262306a36Sopenharmony_ci * ice_is_e823
21362306a36Sopenharmony_ci * @hw: pointer to the hardware structure
21462306a36Sopenharmony_ci *
21562306a36Sopenharmony_ci * returns true if the device is E823-L or E823-C based, false if not.
21662306a36Sopenharmony_ci */
21762306a36Sopenharmony_cibool ice_is_e823(struct ice_hw *hw)
21862306a36Sopenharmony_ci{
21962306a36Sopenharmony_ci	switch (hw->device_id) {
22062306a36Sopenharmony_ci	case ICE_DEV_ID_E823L_BACKPLANE:
22162306a36Sopenharmony_ci	case ICE_DEV_ID_E823L_SFP:
22262306a36Sopenharmony_ci	case ICE_DEV_ID_E823L_10G_BASE_T:
22362306a36Sopenharmony_ci	case ICE_DEV_ID_E823L_1GBE:
22462306a36Sopenharmony_ci	case ICE_DEV_ID_E823L_QSFP:
22562306a36Sopenharmony_ci	case ICE_DEV_ID_E823C_BACKPLANE:
22662306a36Sopenharmony_ci	case ICE_DEV_ID_E823C_QSFP:
22762306a36Sopenharmony_ci	case ICE_DEV_ID_E823C_SFP:
22862306a36Sopenharmony_ci	case ICE_DEV_ID_E823C_10G_BASE_T:
22962306a36Sopenharmony_ci	case ICE_DEV_ID_E823C_SGMII:
23062306a36Sopenharmony_ci		return true;
23162306a36Sopenharmony_ci	default:
23262306a36Sopenharmony_ci		return false;
23362306a36Sopenharmony_ci	}
23462306a36Sopenharmony_ci}
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_ci/**
23762306a36Sopenharmony_ci * ice_clear_pf_cfg - Clear PF configuration
23862306a36Sopenharmony_ci * @hw: pointer to the hardware structure
23962306a36Sopenharmony_ci *
24062306a36Sopenharmony_ci * Clears any existing PF configuration (VSIs, VSI lists, switch rules, port
24162306a36Sopenharmony_ci * configuration, flow director filters, etc.).
24262306a36Sopenharmony_ci */
24362306a36Sopenharmony_ciint ice_clear_pf_cfg(struct ice_hw *hw)
24462306a36Sopenharmony_ci{
24562306a36Sopenharmony_ci	struct ice_aq_desc desc;
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ci	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_clear_pf_cfg);
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
25062306a36Sopenharmony_ci}
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ci/**
25362306a36Sopenharmony_ci * ice_aq_manage_mac_read - manage MAC address read command
25462306a36Sopenharmony_ci * @hw: pointer to the HW struct
25562306a36Sopenharmony_ci * @buf: a virtual buffer to hold the manage MAC read response
25662306a36Sopenharmony_ci * @buf_size: Size of the virtual buffer
25762306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL
25862306a36Sopenharmony_ci *
25962306a36Sopenharmony_ci * This function is used to return per PF station MAC address (0x0107).
26062306a36Sopenharmony_ci * NOTE: Upon successful completion of this command, MAC address information
26162306a36Sopenharmony_ci * is returned in user specified buffer. Please interpret user specified
26262306a36Sopenharmony_ci * buffer as "manage_mac_read" response.
26362306a36Sopenharmony_ci * Response such as various MAC addresses are stored in HW struct (port.mac)
26462306a36Sopenharmony_ci * ice_discover_dev_caps is expected to be called before this function is
26562306a36Sopenharmony_ci * called.
26662306a36Sopenharmony_ci */
26762306a36Sopenharmony_cistatic int
26862306a36Sopenharmony_ciice_aq_manage_mac_read(struct ice_hw *hw, void *buf, u16 buf_size,
26962306a36Sopenharmony_ci		       struct ice_sq_cd *cd)
27062306a36Sopenharmony_ci{
27162306a36Sopenharmony_ci	struct ice_aqc_manage_mac_read_resp *resp;
27262306a36Sopenharmony_ci	struct ice_aqc_manage_mac_read *cmd;
27362306a36Sopenharmony_ci	struct ice_aq_desc desc;
27462306a36Sopenharmony_ci	int status;
27562306a36Sopenharmony_ci	u16 flags;
27662306a36Sopenharmony_ci	u8 i;
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci	cmd = &desc.params.mac_read;
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_ci	if (buf_size < sizeof(*resp))
28162306a36Sopenharmony_ci		return -EINVAL;
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_ci	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_manage_mac_read);
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_ci	status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
28662306a36Sopenharmony_ci	if (status)
28762306a36Sopenharmony_ci		return status;
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_ci	resp = buf;
29062306a36Sopenharmony_ci	flags = le16_to_cpu(cmd->flags) & ICE_AQC_MAN_MAC_READ_M;
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ci	if (!(flags & ICE_AQC_MAN_MAC_LAN_ADDR_VALID)) {
29362306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_LAN, "got invalid MAC address\n");
29462306a36Sopenharmony_ci		return -EIO;
29562306a36Sopenharmony_ci	}
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_ci	/* A single port can report up to two (LAN and WoL) addresses */
29862306a36Sopenharmony_ci	for (i = 0; i < cmd->num_addr; i++)
29962306a36Sopenharmony_ci		if (resp[i].addr_type == ICE_AQC_MAN_MAC_ADDR_TYPE_LAN) {
30062306a36Sopenharmony_ci			ether_addr_copy(hw->port_info->mac.lan_addr,
30162306a36Sopenharmony_ci					resp[i].mac_addr);
30262306a36Sopenharmony_ci			ether_addr_copy(hw->port_info->mac.perm_addr,
30362306a36Sopenharmony_ci					resp[i].mac_addr);
30462306a36Sopenharmony_ci			break;
30562306a36Sopenharmony_ci		}
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_ci	return 0;
30862306a36Sopenharmony_ci}
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_ci/**
31162306a36Sopenharmony_ci * ice_aq_get_phy_caps - returns PHY capabilities
31262306a36Sopenharmony_ci * @pi: port information structure
31362306a36Sopenharmony_ci * @qual_mods: report qualified modules
31462306a36Sopenharmony_ci * @report_mode: report mode capabilities
31562306a36Sopenharmony_ci * @pcaps: structure for PHY capabilities to be filled
31662306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL
31762306a36Sopenharmony_ci *
31862306a36Sopenharmony_ci * Returns the various PHY capabilities supported on the Port (0x0600)
31962306a36Sopenharmony_ci */
32062306a36Sopenharmony_ciint
32162306a36Sopenharmony_ciice_aq_get_phy_caps(struct ice_port_info *pi, bool qual_mods, u8 report_mode,
32262306a36Sopenharmony_ci		    struct ice_aqc_get_phy_caps_data *pcaps,
32362306a36Sopenharmony_ci		    struct ice_sq_cd *cd)
32462306a36Sopenharmony_ci{
32562306a36Sopenharmony_ci	struct ice_aqc_get_phy_caps *cmd;
32662306a36Sopenharmony_ci	u16 pcaps_size = sizeof(*pcaps);
32762306a36Sopenharmony_ci	struct ice_aq_desc desc;
32862306a36Sopenharmony_ci	const char *prefix;
32962306a36Sopenharmony_ci	struct ice_hw *hw;
33062306a36Sopenharmony_ci	int status;
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_ci	cmd = &desc.params.get_phy;
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci	if (!pcaps || (report_mode & ~ICE_AQC_REPORT_MODE_M) || !pi)
33562306a36Sopenharmony_ci		return -EINVAL;
33662306a36Sopenharmony_ci	hw = pi->hw;
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_ci	if (report_mode == ICE_AQC_REPORT_DFLT_CFG &&
33962306a36Sopenharmony_ci	    !ice_fw_supports_report_dflt_cfg(hw))
34062306a36Sopenharmony_ci		return -EINVAL;
34162306a36Sopenharmony_ci
34262306a36Sopenharmony_ci	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_phy_caps);
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ci	if (qual_mods)
34562306a36Sopenharmony_ci		cmd->param0 |= cpu_to_le16(ICE_AQC_GET_PHY_RQM);
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_ci	cmd->param0 |= cpu_to_le16(report_mode);
34862306a36Sopenharmony_ci	status = ice_aq_send_cmd(hw, &desc, pcaps, pcaps_size, cd);
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_LINK, "get phy caps dump\n");
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_ci	switch (report_mode) {
35362306a36Sopenharmony_ci	case ICE_AQC_REPORT_TOPO_CAP_MEDIA:
35462306a36Sopenharmony_ci		prefix = "phy_caps_media";
35562306a36Sopenharmony_ci		break;
35662306a36Sopenharmony_ci	case ICE_AQC_REPORT_TOPO_CAP_NO_MEDIA:
35762306a36Sopenharmony_ci		prefix = "phy_caps_no_media";
35862306a36Sopenharmony_ci		break;
35962306a36Sopenharmony_ci	case ICE_AQC_REPORT_ACTIVE_CFG:
36062306a36Sopenharmony_ci		prefix = "phy_caps_active";
36162306a36Sopenharmony_ci		break;
36262306a36Sopenharmony_ci	case ICE_AQC_REPORT_DFLT_CFG:
36362306a36Sopenharmony_ci		prefix = "phy_caps_default";
36462306a36Sopenharmony_ci		break;
36562306a36Sopenharmony_ci	default:
36662306a36Sopenharmony_ci		prefix = "phy_caps_invalid";
36762306a36Sopenharmony_ci	}
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_ci	ice_dump_phy_type(hw, le64_to_cpu(pcaps->phy_type_low),
37062306a36Sopenharmony_ci			  le64_to_cpu(pcaps->phy_type_high), prefix);
37162306a36Sopenharmony_ci
37262306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_LINK, "%s: report_mode = 0x%x\n",
37362306a36Sopenharmony_ci		  prefix, report_mode);
37462306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_LINK, "%s: caps = 0x%x\n", prefix, pcaps->caps);
37562306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_LINK, "%s: low_power_ctrl_an = 0x%x\n", prefix,
37662306a36Sopenharmony_ci		  pcaps->low_power_ctrl_an);
37762306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_LINK, "%s: eee_cap = 0x%x\n", prefix,
37862306a36Sopenharmony_ci		  pcaps->eee_cap);
37962306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_LINK, "%s: eeer_value = 0x%x\n", prefix,
38062306a36Sopenharmony_ci		  pcaps->eeer_value);
38162306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_LINK, "%s: link_fec_options = 0x%x\n", prefix,
38262306a36Sopenharmony_ci		  pcaps->link_fec_options);
38362306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_LINK, "%s: module_compliance_enforcement = 0x%x\n",
38462306a36Sopenharmony_ci		  prefix, pcaps->module_compliance_enforcement);
38562306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_LINK, "%s: extended_compliance_code = 0x%x\n",
38662306a36Sopenharmony_ci		  prefix, pcaps->extended_compliance_code);
38762306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_LINK, "%s: module_type[0] = 0x%x\n", prefix,
38862306a36Sopenharmony_ci		  pcaps->module_type[0]);
38962306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_LINK, "%s: module_type[1] = 0x%x\n", prefix,
39062306a36Sopenharmony_ci		  pcaps->module_type[1]);
39162306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_LINK, "%s: module_type[2] = 0x%x\n", prefix,
39262306a36Sopenharmony_ci		  pcaps->module_type[2]);
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_ci	if (!status && report_mode == ICE_AQC_REPORT_TOPO_CAP_MEDIA) {
39562306a36Sopenharmony_ci		pi->phy.phy_type_low = le64_to_cpu(pcaps->phy_type_low);
39662306a36Sopenharmony_ci		pi->phy.phy_type_high = le64_to_cpu(pcaps->phy_type_high);
39762306a36Sopenharmony_ci		memcpy(pi->phy.link_info.module_type, &pcaps->module_type,
39862306a36Sopenharmony_ci		       sizeof(pi->phy.link_info.module_type));
39962306a36Sopenharmony_ci	}
40062306a36Sopenharmony_ci
40162306a36Sopenharmony_ci	return status;
40262306a36Sopenharmony_ci}
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_ci/**
40562306a36Sopenharmony_ci * ice_aq_get_link_topo_handle - get link topology node return status
40662306a36Sopenharmony_ci * @pi: port information structure
40762306a36Sopenharmony_ci * @node_type: requested node type
40862306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL
40962306a36Sopenharmony_ci *
41062306a36Sopenharmony_ci * Get link topology node return status for specified node type (0x06E0)
41162306a36Sopenharmony_ci *
41262306a36Sopenharmony_ci * Node type cage can be used to determine if cage is present. If AQC
41362306a36Sopenharmony_ci * returns error (ENOENT), then no cage present. If no cage present, then
41462306a36Sopenharmony_ci * connection type is backplane or BASE-T.
41562306a36Sopenharmony_ci */
41662306a36Sopenharmony_cistatic int
41762306a36Sopenharmony_ciice_aq_get_link_topo_handle(struct ice_port_info *pi, u8 node_type,
41862306a36Sopenharmony_ci			    struct ice_sq_cd *cd)
41962306a36Sopenharmony_ci{
42062306a36Sopenharmony_ci	struct ice_aqc_get_link_topo *cmd;
42162306a36Sopenharmony_ci	struct ice_aq_desc desc;
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ci	cmd = &desc.params.get_link_topo;
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_ci	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_link_topo);
42662306a36Sopenharmony_ci
42762306a36Sopenharmony_ci	cmd->addr.topo_params.node_type_ctx =
42862306a36Sopenharmony_ci		(ICE_AQC_LINK_TOPO_NODE_CTX_PORT <<
42962306a36Sopenharmony_ci		 ICE_AQC_LINK_TOPO_NODE_CTX_S);
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_ci	/* set node type */
43262306a36Sopenharmony_ci	cmd->addr.topo_params.node_type_ctx |=
43362306a36Sopenharmony_ci		(ICE_AQC_LINK_TOPO_NODE_TYPE_M & node_type);
43462306a36Sopenharmony_ci
43562306a36Sopenharmony_ci	return ice_aq_send_cmd(pi->hw, &desc, NULL, 0, cd);
43662306a36Sopenharmony_ci}
43762306a36Sopenharmony_ci
43862306a36Sopenharmony_ci/**
43962306a36Sopenharmony_ci * ice_is_media_cage_present
44062306a36Sopenharmony_ci * @pi: port information structure
44162306a36Sopenharmony_ci *
44262306a36Sopenharmony_ci * Returns true if media cage is present, else false. If no cage, then
44362306a36Sopenharmony_ci * media type is backplane or BASE-T.
44462306a36Sopenharmony_ci */
44562306a36Sopenharmony_cistatic bool ice_is_media_cage_present(struct ice_port_info *pi)
44662306a36Sopenharmony_ci{
44762306a36Sopenharmony_ci	/* Node type cage can be used to determine if cage is present. If AQC
44862306a36Sopenharmony_ci	 * returns error (ENOENT), then no cage present. If no cage present then
44962306a36Sopenharmony_ci	 * connection type is backplane or BASE-T.
45062306a36Sopenharmony_ci	 */
45162306a36Sopenharmony_ci	return !ice_aq_get_link_topo_handle(pi,
45262306a36Sopenharmony_ci					    ICE_AQC_LINK_TOPO_NODE_TYPE_CAGE,
45362306a36Sopenharmony_ci					    NULL);
45462306a36Sopenharmony_ci}
45562306a36Sopenharmony_ci
45662306a36Sopenharmony_ci/**
45762306a36Sopenharmony_ci * ice_get_media_type - Gets media type
45862306a36Sopenharmony_ci * @pi: port information structure
45962306a36Sopenharmony_ci */
46062306a36Sopenharmony_cistatic enum ice_media_type ice_get_media_type(struct ice_port_info *pi)
46162306a36Sopenharmony_ci{
46262306a36Sopenharmony_ci	struct ice_link_status *hw_link_info;
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_ci	if (!pi)
46562306a36Sopenharmony_ci		return ICE_MEDIA_UNKNOWN;
46662306a36Sopenharmony_ci
46762306a36Sopenharmony_ci	hw_link_info = &pi->phy.link_info;
46862306a36Sopenharmony_ci	if (hw_link_info->phy_type_low && hw_link_info->phy_type_high)
46962306a36Sopenharmony_ci		/* If more than one media type is selected, report unknown */
47062306a36Sopenharmony_ci		return ICE_MEDIA_UNKNOWN;
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_ci	if (hw_link_info->phy_type_low) {
47362306a36Sopenharmony_ci		/* 1G SGMII is a special case where some DA cable PHYs
47462306a36Sopenharmony_ci		 * may show this as an option when it really shouldn't
47562306a36Sopenharmony_ci		 * be since SGMII is meant to be between a MAC and a PHY
47662306a36Sopenharmony_ci		 * in a backplane. Try to detect this case and handle it
47762306a36Sopenharmony_ci		 */
47862306a36Sopenharmony_ci		if (hw_link_info->phy_type_low == ICE_PHY_TYPE_LOW_1G_SGMII &&
47962306a36Sopenharmony_ci		    (hw_link_info->module_type[ICE_AQC_MOD_TYPE_IDENT] ==
48062306a36Sopenharmony_ci		    ICE_AQC_MOD_TYPE_BYTE1_SFP_PLUS_CU_ACTIVE ||
48162306a36Sopenharmony_ci		    hw_link_info->module_type[ICE_AQC_MOD_TYPE_IDENT] ==
48262306a36Sopenharmony_ci		    ICE_AQC_MOD_TYPE_BYTE1_SFP_PLUS_CU_PASSIVE))
48362306a36Sopenharmony_ci			return ICE_MEDIA_DA;
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_ci		switch (hw_link_info->phy_type_low) {
48662306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_1000BASE_SX:
48762306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_1000BASE_LX:
48862306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_10GBASE_SR:
48962306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_10GBASE_LR:
49062306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_10G_SFI_C2C:
49162306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_25GBASE_SR:
49262306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_25GBASE_LR:
49362306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_40GBASE_SR4:
49462306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_40GBASE_LR4:
49562306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_50GBASE_SR2:
49662306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_50GBASE_LR2:
49762306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_50GBASE_SR:
49862306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_50GBASE_FR:
49962306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_50GBASE_LR:
50062306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_100GBASE_SR4:
50162306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_100GBASE_LR4:
50262306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_100GBASE_SR2:
50362306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_100GBASE_DR:
50462306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_10G_SFI_AOC_ACC:
50562306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_25G_AUI_AOC_ACC:
50662306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_40G_XLAUI_AOC_ACC:
50762306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_50G_LAUI2_AOC_ACC:
50862306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_50G_AUI2_AOC_ACC:
50962306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_50G_AUI1_AOC_ACC:
51062306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_100G_CAUI4_AOC_ACC:
51162306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_100G_AUI4_AOC_ACC:
51262306a36Sopenharmony_ci			return ICE_MEDIA_FIBER;
51362306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_100BASE_TX:
51462306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_1000BASE_T:
51562306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_2500BASE_T:
51662306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_5GBASE_T:
51762306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_10GBASE_T:
51862306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_25GBASE_T:
51962306a36Sopenharmony_ci			return ICE_MEDIA_BASET;
52062306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_10G_SFI_DA:
52162306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_25GBASE_CR:
52262306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_25GBASE_CR_S:
52362306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_25GBASE_CR1:
52462306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_40GBASE_CR4:
52562306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_50GBASE_CR2:
52662306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_50GBASE_CP:
52762306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_100GBASE_CR4:
52862306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_100GBASE_CR_PAM4:
52962306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_100GBASE_CP2:
53062306a36Sopenharmony_ci			return ICE_MEDIA_DA;
53162306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_25G_AUI_C2C:
53262306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_40G_XLAUI:
53362306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_50G_LAUI2:
53462306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_50G_AUI2:
53562306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_50G_AUI1:
53662306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_100G_AUI4:
53762306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_100G_CAUI4:
53862306a36Sopenharmony_ci			if (ice_is_media_cage_present(pi))
53962306a36Sopenharmony_ci				return ICE_MEDIA_DA;
54062306a36Sopenharmony_ci			fallthrough;
54162306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_1000BASE_KX:
54262306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_2500BASE_KX:
54362306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_2500BASE_X:
54462306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_5GBASE_KR:
54562306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_10GBASE_KR_CR1:
54662306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_25GBASE_KR:
54762306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_25GBASE_KR1:
54862306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_25GBASE_KR_S:
54962306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_40GBASE_KR4:
55062306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4:
55162306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_50GBASE_KR2:
55262306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_100GBASE_KR4:
55362306a36Sopenharmony_ci		case ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4:
55462306a36Sopenharmony_ci			return ICE_MEDIA_BACKPLANE;
55562306a36Sopenharmony_ci		}
55662306a36Sopenharmony_ci	} else {
55762306a36Sopenharmony_ci		switch (hw_link_info->phy_type_high) {
55862306a36Sopenharmony_ci		case ICE_PHY_TYPE_HIGH_100G_AUI2:
55962306a36Sopenharmony_ci		case ICE_PHY_TYPE_HIGH_100G_CAUI2:
56062306a36Sopenharmony_ci			if (ice_is_media_cage_present(pi))
56162306a36Sopenharmony_ci				return ICE_MEDIA_DA;
56262306a36Sopenharmony_ci			fallthrough;
56362306a36Sopenharmony_ci		case ICE_PHY_TYPE_HIGH_100GBASE_KR2_PAM4:
56462306a36Sopenharmony_ci			return ICE_MEDIA_BACKPLANE;
56562306a36Sopenharmony_ci		case ICE_PHY_TYPE_HIGH_100G_CAUI2_AOC_ACC:
56662306a36Sopenharmony_ci		case ICE_PHY_TYPE_HIGH_100G_AUI2_AOC_ACC:
56762306a36Sopenharmony_ci			return ICE_MEDIA_FIBER;
56862306a36Sopenharmony_ci		}
56962306a36Sopenharmony_ci	}
57062306a36Sopenharmony_ci	return ICE_MEDIA_UNKNOWN;
57162306a36Sopenharmony_ci}
57262306a36Sopenharmony_ci
57362306a36Sopenharmony_ci/**
57462306a36Sopenharmony_ci * ice_aq_get_link_info
57562306a36Sopenharmony_ci * @pi: port information structure
57662306a36Sopenharmony_ci * @ena_lse: enable/disable LinkStatusEvent reporting
57762306a36Sopenharmony_ci * @link: pointer to link status structure - optional
57862306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL
57962306a36Sopenharmony_ci *
58062306a36Sopenharmony_ci * Get Link Status (0x607). Returns the link status of the adapter.
58162306a36Sopenharmony_ci */
58262306a36Sopenharmony_ciint
58362306a36Sopenharmony_ciice_aq_get_link_info(struct ice_port_info *pi, bool ena_lse,
58462306a36Sopenharmony_ci		     struct ice_link_status *link, struct ice_sq_cd *cd)
58562306a36Sopenharmony_ci{
58662306a36Sopenharmony_ci	struct ice_aqc_get_link_status_data link_data = { 0 };
58762306a36Sopenharmony_ci	struct ice_aqc_get_link_status *resp;
58862306a36Sopenharmony_ci	struct ice_link_status *li_old, *li;
58962306a36Sopenharmony_ci	enum ice_media_type *hw_media_type;
59062306a36Sopenharmony_ci	struct ice_fc_info *hw_fc_info;
59162306a36Sopenharmony_ci	bool tx_pause, rx_pause;
59262306a36Sopenharmony_ci	struct ice_aq_desc desc;
59362306a36Sopenharmony_ci	struct ice_hw *hw;
59462306a36Sopenharmony_ci	u16 cmd_flags;
59562306a36Sopenharmony_ci	int status;
59662306a36Sopenharmony_ci
59762306a36Sopenharmony_ci	if (!pi)
59862306a36Sopenharmony_ci		return -EINVAL;
59962306a36Sopenharmony_ci	hw = pi->hw;
60062306a36Sopenharmony_ci	li_old = &pi->phy.link_info_old;
60162306a36Sopenharmony_ci	hw_media_type = &pi->phy.media_type;
60262306a36Sopenharmony_ci	li = &pi->phy.link_info;
60362306a36Sopenharmony_ci	hw_fc_info = &pi->fc;
60462306a36Sopenharmony_ci
60562306a36Sopenharmony_ci	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_link_status);
60662306a36Sopenharmony_ci	cmd_flags = (ena_lse) ? ICE_AQ_LSE_ENA : ICE_AQ_LSE_DIS;
60762306a36Sopenharmony_ci	resp = &desc.params.get_link_status;
60862306a36Sopenharmony_ci	resp->cmd_flags = cpu_to_le16(cmd_flags);
60962306a36Sopenharmony_ci	resp->lport_num = pi->lport;
61062306a36Sopenharmony_ci
61162306a36Sopenharmony_ci	status = ice_aq_send_cmd(hw, &desc, &link_data, sizeof(link_data), cd);
61262306a36Sopenharmony_ci
61362306a36Sopenharmony_ci	if (status)
61462306a36Sopenharmony_ci		return status;
61562306a36Sopenharmony_ci
61662306a36Sopenharmony_ci	/* save off old link status information */
61762306a36Sopenharmony_ci	*li_old = *li;
61862306a36Sopenharmony_ci
61962306a36Sopenharmony_ci	/* update current link status information */
62062306a36Sopenharmony_ci	li->link_speed = le16_to_cpu(link_data.link_speed);
62162306a36Sopenharmony_ci	li->phy_type_low = le64_to_cpu(link_data.phy_type_low);
62262306a36Sopenharmony_ci	li->phy_type_high = le64_to_cpu(link_data.phy_type_high);
62362306a36Sopenharmony_ci	*hw_media_type = ice_get_media_type(pi);
62462306a36Sopenharmony_ci	li->link_info = link_data.link_info;
62562306a36Sopenharmony_ci	li->link_cfg_err = link_data.link_cfg_err;
62662306a36Sopenharmony_ci	li->an_info = link_data.an_info;
62762306a36Sopenharmony_ci	li->ext_info = link_data.ext_info;
62862306a36Sopenharmony_ci	li->max_frame_size = le16_to_cpu(link_data.max_frame_size);
62962306a36Sopenharmony_ci	li->fec_info = link_data.cfg & ICE_AQ_FEC_MASK;
63062306a36Sopenharmony_ci	li->topo_media_conflict = link_data.topo_media_conflict;
63162306a36Sopenharmony_ci	li->pacing = link_data.cfg & (ICE_AQ_CFG_PACING_M |
63262306a36Sopenharmony_ci				      ICE_AQ_CFG_PACING_TYPE_M);
63362306a36Sopenharmony_ci
63462306a36Sopenharmony_ci	/* update fc info */
63562306a36Sopenharmony_ci	tx_pause = !!(link_data.an_info & ICE_AQ_LINK_PAUSE_TX);
63662306a36Sopenharmony_ci	rx_pause = !!(link_data.an_info & ICE_AQ_LINK_PAUSE_RX);
63762306a36Sopenharmony_ci	if (tx_pause && rx_pause)
63862306a36Sopenharmony_ci		hw_fc_info->current_mode = ICE_FC_FULL;
63962306a36Sopenharmony_ci	else if (tx_pause)
64062306a36Sopenharmony_ci		hw_fc_info->current_mode = ICE_FC_TX_PAUSE;
64162306a36Sopenharmony_ci	else if (rx_pause)
64262306a36Sopenharmony_ci		hw_fc_info->current_mode = ICE_FC_RX_PAUSE;
64362306a36Sopenharmony_ci	else
64462306a36Sopenharmony_ci		hw_fc_info->current_mode = ICE_FC_NONE;
64562306a36Sopenharmony_ci
64662306a36Sopenharmony_ci	li->lse_ena = !!(resp->cmd_flags & cpu_to_le16(ICE_AQ_LSE_IS_ENABLED));
64762306a36Sopenharmony_ci
64862306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_LINK, "get link info\n");
64962306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_LINK, "	link_speed = 0x%x\n", li->link_speed);
65062306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_LINK, "	phy_type_low = 0x%llx\n",
65162306a36Sopenharmony_ci		  (unsigned long long)li->phy_type_low);
65262306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_LINK, "	phy_type_high = 0x%llx\n",
65362306a36Sopenharmony_ci		  (unsigned long long)li->phy_type_high);
65462306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_LINK, "	media_type = 0x%x\n", *hw_media_type);
65562306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_LINK, "	link_info = 0x%x\n", li->link_info);
65662306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_LINK, "	link_cfg_err = 0x%x\n", li->link_cfg_err);
65762306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_LINK, "	an_info = 0x%x\n", li->an_info);
65862306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_LINK, "	ext_info = 0x%x\n", li->ext_info);
65962306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_LINK, "	fec_info = 0x%x\n", li->fec_info);
66062306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_LINK, "	lse_ena = 0x%x\n", li->lse_ena);
66162306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_LINK, "	max_frame = 0x%x\n",
66262306a36Sopenharmony_ci		  li->max_frame_size);
66362306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_LINK, "	pacing = 0x%x\n", li->pacing);
66462306a36Sopenharmony_ci
66562306a36Sopenharmony_ci	/* save link status information */
66662306a36Sopenharmony_ci	if (link)
66762306a36Sopenharmony_ci		*link = *li;
66862306a36Sopenharmony_ci
66962306a36Sopenharmony_ci	/* flag cleared so calling functions don't call AQ again */
67062306a36Sopenharmony_ci	pi->phy.get_link_info = false;
67162306a36Sopenharmony_ci
67262306a36Sopenharmony_ci	return 0;
67362306a36Sopenharmony_ci}
67462306a36Sopenharmony_ci
67562306a36Sopenharmony_ci/**
67662306a36Sopenharmony_ci * ice_fill_tx_timer_and_fc_thresh
67762306a36Sopenharmony_ci * @hw: pointer to the HW struct
67862306a36Sopenharmony_ci * @cmd: pointer to MAC cfg structure
67962306a36Sopenharmony_ci *
68062306a36Sopenharmony_ci * Add Tx timer and FC refresh threshold info to Set MAC Config AQ command
68162306a36Sopenharmony_ci * descriptor
68262306a36Sopenharmony_ci */
68362306a36Sopenharmony_cistatic void
68462306a36Sopenharmony_ciice_fill_tx_timer_and_fc_thresh(struct ice_hw *hw,
68562306a36Sopenharmony_ci				struct ice_aqc_set_mac_cfg *cmd)
68662306a36Sopenharmony_ci{
68762306a36Sopenharmony_ci	u16 fc_thres_val, tx_timer_val;
68862306a36Sopenharmony_ci	u32 val;
68962306a36Sopenharmony_ci
69062306a36Sopenharmony_ci	/* We read back the transmit timer and FC threshold value of
69162306a36Sopenharmony_ci	 * LFC. Thus, we will use index =
69262306a36Sopenharmony_ci	 * PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_MAX_INDEX.
69362306a36Sopenharmony_ci	 *
69462306a36Sopenharmony_ci	 * Also, because we are operating on transmit timer and FC
69562306a36Sopenharmony_ci	 * threshold of LFC, we don't turn on any bit in tx_tmr_priority
69662306a36Sopenharmony_ci	 */
69762306a36Sopenharmony_ci#define IDX_OF_LFC PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_MAX_INDEX
69862306a36Sopenharmony_ci
69962306a36Sopenharmony_ci	/* Retrieve the transmit timer */
70062306a36Sopenharmony_ci	val = rd32(hw, PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA(IDX_OF_LFC));
70162306a36Sopenharmony_ci	tx_timer_val = val &
70262306a36Sopenharmony_ci		PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_HSEC_CTL_TX_PAUSE_QUANTA_M;
70362306a36Sopenharmony_ci	cmd->tx_tmr_value = cpu_to_le16(tx_timer_val);
70462306a36Sopenharmony_ci
70562306a36Sopenharmony_ci	/* Retrieve the FC threshold */
70662306a36Sopenharmony_ci	val = rd32(hw, PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER(IDX_OF_LFC));
70762306a36Sopenharmony_ci	fc_thres_val = val & PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_M;
70862306a36Sopenharmony_ci
70962306a36Sopenharmony_ci	cmd->fc_refresh_threshold = cpu_to_le16(fc_thres_val);
71062306a36Sopenharmony_ci}
71162306a36Sopenharmony_ci
71262306a36Sopenharmony_ci/**
71362306a36Sopenharmony_ci * ice_aq_set_mac_cfg
71462306a36Sopenharmony_ci * @hw: pointer to the HW struct
71562306a36Sopenharmony_ci * @max_frame_size: Maximum Frame Size to be supported
71662306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL
71762306a36Sopenharmony_ci *
71862306a36Sopenharmony_ci * Set MAC configuration (0x0603)
71962306a36Sopenharmony_ci */
72062306a36Sopenharmony_ciint
72162306a36Sopenharmony_ciice_aq_set_mac_cfg(struct ice_hw *hw, u16 max_frame_size, struct ice_sq_cd *cd)
72262306a36Sopenharmony_ci{
72362306a36Sopenharmony_ci	struct ice_aqc_set_mac_cfg *cmd;
72462306a36Sopenharmony_ci	struct ice_aq_desc desc;
72562306a36Sopenharmony_ci
72662306a36Sopenharmony_ci	cmd = &desc.params.set_mac_cfg;
72762306a36Sopenharmony_ci
72862306a36Sopenharmony_ci	if (max_frame_size == 0)
72962306a36Sopenharmony_ci		return -EINVAL;
73062306a36Sopenharmony_ci
73162306a36Sopenharmony_ci	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_mac_cfg);
73262306a36Sopenharmony_ci
73362306a36Sopenharmony_ci	cmd->max_frame_size = cpu_to_le16(max_frame_size);
73462306a36Sopenharmony_ci
73562306a36Sopenharmony_ci	ice_fill_tx_timer_and_fc_thresh(hw, cmd);
73662306a36Sopenharmony_ci
73762306a36Sopenharmony_ci	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
73862306a36Sopenharmony_ci}
73962306a36Sopenharmony_ci
74062306a36Sopenharmony_ci/**
74162306a36Sopenharmony_ci * ice_init_fltr_mgmt_struct - initializes filter management list and locks
74262306a36Sopenharmony_ci * @hw: pointer to the HW struct
74362306a36Sopenharmony_ci */
74462306a36Sopenharmony_cistatic int ice_init_fltr_mgmt_struct(struct ice_hw *hw)
74562306a36Sopenharmony_ci{
74662306a36Sopenharmony_ci	struct ice_switch_info *sw;
74762306a36Sopenharmony_ci	int status;
74862306a36Sopenharmony_ci
74962306a36Sopenharmony_ci	hw->switch_info = devm_kzalloc(ice_hw_to_dev(hw),
75062306a36Sopenharmony_ci				       sizeof(*hw->switch_info), GFP_KERNEL);
75162306a36Sopenharmony_ci	sw = hw->switch_info;
75262306a36Sopenharmony_ci
75362306a36Sopenharmony_ci	if (!sw)
75462306a36Sopenharmony_ci		return -ENOMEM;
75562306a36Sopenharmony_ci
75662306a36Sopenharmony_ci	INIT_LIST_HEAD(&sw->vsi_list_map_head);
75762306a36Sopenharmony_ci	sw->prof_res_bm_init = 0;
75862306a36Sopenharmony_ci
75962306a36Sopenharmony_ci	status = ice_init_def_sw_recp(hw);
76062306a36Sopenharmony_ci	if (status) {
76162306a36Sopenharmony_ci		devm_kfree(ice_hw_to_dev(hw), hw->switch_info);
76262306a36Sopenharmony_ci		return status;
76362306a36Sopenharmony_ci	}
76462306a36Sopenharmony_ci	return 0;
76562306a36Sopenharmony_ci}
76662306a36Sopenharmony_ci
76762306a36Sopenharmony_ci/**
76862306a36Sopenharmony_ci * ice_cleanup_fltr_mgmt_struct - cleanup filter management list and locks
76962306a36Sopenharmony_ci * @hw: pointer to the HW struct
77062306a36Sopenharmony_ci */
77162306a36Sopenharmony_cistatic void ice_cleanup_fltr_mgmt_struct(struct ice_hw *hw)
77262306a36Sopenharmony_ci{
77362306a36Sopenharmony_ci	struct ice_switch_info *sw = hw->switch_info;
77462306a36Sopenharmony_ci	struct ice_vsi_list_map_info *v_pos_map;
77562306a36Sopenharmony_ci	struct ice_vsi_list_map_info *v_tmp_map;
77662306a36Sopenharmony_ci	struct ice_sw_recipe *recps;
77762306a36Sopenharmony_ci	u8 i;
77862306a36Sopenharmony_ci
77962306a36Sopenharmony_ci	list_for_each_entry_safe(v_pos_map, v_tmp_map, &sw->vsi_list_map_head,
78062306a36Sopenharmony_ci				 list_entry) {
78162306a36Sopenharmony_ci		list_del(&v_pos_map->list_entry);
78262306a36Sopenharmony_ci		devm_kfree(ice_hw_to_dev(hw), v_pos_map);
78362306a36Sopenharmony_ci	}
78462306a36Sopenharmony_ci	recps = sw->recp_list;
78562306a36Sopenharmony_ci	for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
78662306a36Sopenharmony_ci		struct ice_recp_grp_entry *rg_entry, *tmprg_entry;
78762306a36Sopenharmony_ci
78862306a36Sopenharmony_ci		recps[i].root_rid = i;
78962306a36Sopenharmony_ci		list_for_each_entry_safe(rg_entry, tmprg_entry,
79062306a36Sopenharmony_ci					 &recps[i].rg_list, l_entry) {
79162306a36Sopenharmony_ci			list_del(&rg_entry->l_entry);
79262306a36Sopenharmony_ci			devm_kfree(ice_hw_to_dev(hw), rg_entry);
79362306a36Sopenharmony_ci		}
79462306a36Sopenharmony_ci
79562306a36Sopenharmony_ci		if (recps[i].adv_rule) {
79662306a36Sopenharmony_ci			struct ice_adv_fltr_mgmt_list_entry *tmp_entry;
79762306a36Sopenharmony_ci			struct ice_adv_fltr_mgmt_list_entry *lst_itr;
79862306a36Sopenharmony_ci
79962306a36Sopenharmony_ci			mutex_destroy(&recps[i].filt_rule_lock);
80062306a36Sopenharmony_ci			list_for_each_entry_safe(lst_itr, tmp_entry,
80162306a36Sopenharmony_ci						 &recps[i].filt_rules,
80262306a36Sopenharmony_ci						 list_entry) {
80362306a36Sopenharmony_ci				list_del(&lst_itr->list_entry);
80462306a36Sopenharmony_ci				devm_kfree(ice_hw_to_dev(hw), lst_itr->lkups);
80562306a36Sopenharmony_ci				devm_kfree(ice_hw_to_dev(hw), lst_itr);
80662306a36Sopenharmony_ci			}
80762306a36Sopenharmony_ci		} else {
80862306a36Sopenharmony_ci			struct ice_fltr_mgmt_list_entry *lst_itr, *tmp_entry;
80962306a36Sopenharmony_ci
81062306a36Sopenharmony_ci			mutex_destroy(&recps[i].filt_rule_lock);
81162306a36Sopenharmony_ci			list_for_each_entry_safe(lst_itr, tmp_entry,
81262306a36Sopenharmony_ci						 &recps[i].filt_rules,
81362306a36Sopenharmony_ci						 list_entry) {
81462306a36Sopenharmony_ci				list_del(&lst_itr->list_entry);
81562306a36Sopenharmony_ci				devm_kfree(ice_hw_to_dev(hw), lst_itr);
81662306a36Sopenharmony_ci			}
81762306a36Sopenharmony_ci		}
81862306a36Sopenharmony_ci		devm_kfree(ice_hw_to_dev(hw), recps[i].root_buf);
81962306a36Sopenharmony_ci	}
82062306a36Sopenharmony_ci	ice_rm_all_sw_replay_rule_info(hw);
82162306a36Sopenharmony_ci	devm_kfree(ice_hw_to_dev(hw), sw->recp_list);
82262306a36Sopenharmony_ci	devm_kfree(ice_hw_to_dev(hw), sw);
82362306a36Sopenharmony_ci}
82462306a36Sopenharmony_ci
82562306a36Sopenharmony_ci/**
82662306a36Sopenharmony_ci * ice_get_fw_log_cfg - get FW logging configuration
82762306a36Sopenharmony_ci * @hw: pointer to the HW struct
82862306a36Sopenharmony_ci */
82962306a36Sopenharmony_cistatic int ice_get_fw_log_cfg(struct ice_hw *hw)
83062306a36Sopenharmony_ci{
83162306a36Sopenharmony_ci	struct ice_aq_desc desc;
83262306a36Sopenharmony_ci	__le16 *config;
83362306a36Sopenharmony_ci	int status;
83462306a36Sopenharmony_ci	u16 size;
83562306a36Sopenharmony_ci
83662306a36Sopenharmony_ci	size = sizeof(*config) * ICE_AQC_FW_LOG_ID_MAX;
83762306a36Sopenharmony_ci	config = kzalloc(size, GFP_KERNEL);
83862306a36Sopenharmony_ci	if (!config)
83962306a36Sopenharmony_ci		return -ENOMEM;
84062306a36Sopenharmony_ci
84162306a36Sopenharmony_ci	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_fw_logging_info);
84262306a36Sopenharmony_ci
84362306a36Sopenharmony_ci	status = ice_aq_send_cmd(hw, &desc, config, size, NULL);
84462306a36Sopenharmony_ci	if (!status) {
84562306a36Sopenharmony_ci		u16 i;
84662306a36Sopenharmony_ci
84762306a36Sopenharmony_ci		/* Save FW logging information into the HW structure */
84862306a36Sopenharmony_ci		for (i = 0; i < ICE_AQC_FW_LOG_ID_MAX; i++) {
84962306a36Sopenharmony_ci			u16 v, m, flgs;
85062306a36Sopenharmony_ci
85162306a36Sopenharmony_ci			v = le16_to_cpu(config[i]);
85262306a36Sopenharmony_ci			m = (v & ICE_AQC_FW_LOG_ID_M) >> ICE_AQC_FW_LOG_ID_S;
85362306a36Sopenharmony_ci			flgs = (v & ICE_AQC_FW_LOG_EN_M) >> ICE_AQC_FW_LOG_EN_S;
85462306a36Sopenharmony_ci
85562306a36Sopenharmony_ci			if (m < ICE_AQC_FW_LOG_ID_MAX)
85662306a36Sopenharmony_ci				hw->fw_log.evnts[m].cur = flgs;
85762306a36Sopenharmony_ci		}
85862306a36Sopenharmony_ci	}
85962306a36Sopenharmony_ci
86062306a36Sopenharmony_ci	kfree(config);
86162306a36Sopenharmony_ci
86262306a36Sopenharmony_ci	return status;
86362306a36Sopenharmony_ci}
86462306a36Sopenharmony_ci
86562306a36Sopenharmony_ci/**
86662306a36Sopenharmony_ci * ice_cfg_fw_log - configure FW logging
86762306a36Sopenharmony_ci * @hw: pointer to the HW struct
86862306a36Sopenharmony_ci * @enable: enable certain FW logging events if true, disable all if false
86962306a36Sopenharmony_ci *
87062306a36Sopenharmony_ci * This function enables/disables the FW logging via Rx CQ events and a UART
87162306a36Sopenharmony_ci * port based on predetermined configurations. FW logging via the Rx CQ can be
87262306a36Sopenharmony_ci * enabled/disabled for individual PF's. However, FW logging via the UART can
87362306a36Sopenharmony_ci * only be enabled/disabled for all PFs on the same device.
87462306a36Sopenharmony_ci *
87562306a36Sopenharmony_ci * To enable overall FW logging, the "cq_en" and "uart_en" enable bits in
87662306a36Sopenharmony_ci * hw->fw_log need to be set accordingly, e.g. based on user-provided input,
87762306a36Sopenharmony_ci * before initializing the device.
87862306a36Sopenharmony_ci *
87962306a36Sopenharmony_ci * When re/configuring FW logging, callers need to update the "cfg" elements of
88062306a36Sopenharmony_ci * the hw->fw_log.evnts array with the desired logging event configurations for
88162306a36Sopenharmony_ci * modules of interest. When disabling FW logging completely, the callers can
88262306a36Sopenharmony_ci * just pass false in the "enable" parameter. On completion, the function will
88362306a36Sopenharmony_ci * update the "cur" element of the hw->fw_log.evnts array with the resulting
88462306a36Sopenharmony_ci * logging event configurations of the modules that are being re/configured. FW
88562306a36Sopenharmony_ci * logging modules that are not part of a reconfiguration operation retain their
88662306a36Sopenharmony_ci * previous states.
88762306a36Sopenharmony_ci *
88862306a36Sopenharmony_ci * Before resetting the device, it is recommended that the driver disables FW
88962306a36Sopenharmony_ci * logging before shutting down the control queue. When disabling FW logging
89062306a36Sopenharmony_ci * ("enable" = false), the latest configurations of FW logging events stored in
89162306a36Sopenharmony_ci * hw->fw_log.evnts[] are not overridden to allow them to be reconfigured after
89262306a36Sopenharmony_ci * a device reset.
89362306a36Sopenharmony_ci *
89462306a36Sopenharmony_ci * When enabling FW logging to emit log messages via the Rx CQ during the
89562306a36Sopenharmony_ci * device's initialization phase, a mechanism alternative to interrupt handlers
89662306a36Sopenharmony_ci * needs to be used to extract FW log messages from the Rx CQ periodically and
89762306a36Sopenharmony_ci * to prevent the Rx CQ from being full and stalling other types of control
89862306a36Sopenharmony_ci * messages from FW to SW. Interrupts are typically disabled during the device's
89962306a36Sopenharmony_ci * initialization phase.
90062306a36Sopenharmony_ci */
90162306a36Sopenharmony_cistatic int ice_cfg_fw_log(struct ice_hw *hw, bool enable)
90262306a36Sopenharmony_ci{
90362306a36Sopenharmony_ci	struct ice_aqc_fw_logging *cmd;
90462306a36Sopenharmony_ci	u16 i, chgs = 0, len = 0;
90562306a36Sopenharmony_ci	struct ice_aq_desc desc;
90662306a36Sopenharmony_ci	__le16 *data = NULL;
90762306a36Sopenharmony_ci	u8 actv_evnts = 0;
90862306a36Sopenharmony_ci	void *buf = NULL;
90962306a36Sopenharmony_ci	int status = 0;
91062306a36Sopenharmony_ci
91162306a36Sopenharmony_ci	if (!hw->fw_log.cq_en && !hw->fw_log.uart_en)
91262306a36Sopenharmony_ci		return 0;
91362306a36Sopenharmony_ci
91462306a36Sopenharmony_ci	/* Disable FW logging only when the control queue is still responsive */
91562306a36Sopenharmony_ci	if (!enable &&
91662306a36Sopenharmony_ci	    (!hw->fw_log.actv_evnts || !ice_check_sq_alive(hw, &hw->adminq)))
91762306a36Sopenharmony_ci		return 0;
91862306a36Sopenharmony_ci
91962306a36Sopenharmony_ci	/* Get current FW log settings */
92062306a36Sopenharmony_ci	status = ice_get_fw_log_cfg(hw);
92162306a36Sopenharmony_ci	if (status)
92262306a36Sopenharmony_ci		return status;
92362306a36Sopenharmony_ci
92462306a36Sopenharmony_ci	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_fw_logging);
92562306a36Sopenharmony_ci	cmd = &desc.params.fw_logging;
92662306a36Sopenharmony_ci
92762306a36Sopenharmony_ci	/* Indicate which controls are valid */
92862306a36Sopenharmony_ci	if (hw->fw_log.cq_en)
92962306a36Sopenharmony_ci		cmd->log_ctrl_valid |= ICE_AQC_FW_LOG_AQ_VALID;
93062306a36Sopenharmony_ci
93162306a36Sopenharmony_ci	if (hw->fw_log.uart_en)
93262306a36Sopenharmony_ci		cmd->log_ctrl_valid |= ICE_AQC_FW_LOG_UART_VALID;
93362306a36Sopenharmony_ci
93462306a36Sopenharmony_ci	if (enable) {
93562306a36Sopenharmony_ci		/* Fill in an array of entries with FW logging modules and
93662306a36Sopenharmony_ci		 * logging events being reconfigured.
93762306a36Sopenharmony_ci		 */
93862306a36Sopenharmony_ci		for (i = 0; i < ICE_AQC_FW_LOG_ID_MAX; i++) {
93962306a36Sopenharmony_ci			u16 val;
94062306a36Sopenharmony_ci
94162306a36Sopenharmony_ci			/* Keep track of enabled event types */
94262306a36Sopenharmony_ci			actv_evnts |= hw->fw_log.evnts[i].cfg;
94362306a36Sopenharmony_ci
94462306a36Sopenharmony_ci			if (hw->fw_log.evnts[i].cfg == hw->fw_log.evnts[i].cur)
94562306a36Sopenharmony_ci				continue;
94662306a36Sopenharmony_ci
94762306a36Sopenharmony_ci			if (!data) {
94862306a36Sopenharmony_ci				data = devm_kcalloc(ice_hw_to_dev(hw),
94962306a36Sopenharmony_ci						    ICE_AQC_FW_LOG_ID_MAX,
95062306a36Sopenharmony_ci						    sizeof(*data),
95162306a36Sopenharmony_ci						    GFP_KERNEL);
95262306a36Sopenharmony_ci				if (!data)
95362306a36Sopenharmony_ci					return -ENOMEM;
95462306a36Sopenharmony_ci			}
95562306a36Sopenharmony_ci
95662306a36Sopenharmony_ci			val = i << ICE_AQC_FW_LOG_ID_S;
95762306a36Sopenharmony_ci			val |= hw->fw_log.evnts[i].cfg << ICE_AQC_FW_LOG_EN_S;
95862306a36Sopenharmony_ci			data[chgs++] = cpu_to_le16(val);
95962306a36Sopenharmony_ci		}
96062306a36Sopenharmony_ci
96162306a36Sopenharmony_ci		/* Only enable FW logging if at least one module is specified.
96262306a36Sopenharmony_ci		 * If FW logging is currently enabled but all modules are not
96362306a36Sopenharmony_ci		 * enabled to emit log messages, disable FW logging altogether.
96462306a36Sopenharmony_ci		 */
96562306a36Sopenharmony_ci		if (actv_evnts) {
96662306a36Sopenharmony_ci			/* Leave if there is effectively no change */
96762306a36Sopenharmony_ci			if (!chgs)
96862306a36Sopenharmony_ci				goto out;
96962306a36Sopenharmony_ci
97062306a36Sopenharmony_ci			if (hw->fw_log.cq_en)
97162306a36Sopenharmony_ci				cmd->log_ctrl |= ICE_AQC_FW_LOG_AQ_EN;
97262306a36Sopenharmony_ci
97362306a36Sopenharmony_ci			if (hw->fw_log.uart_en)
97462306a36Sopenharmony_ci				cmd->log_ctrl |= ICE_AQC_FW_LOG_UART_EN;
97562306a36Sopenharmony_ci
97662306a36Sopenharmony_ci			buf = data;
97762306a36Sopenharmony_ci			len = sizeof(*data) * chgs;
97862306a36Sopenharmony_ci			desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
97962306a36Sopenharmony_ci		}
98062306a36Sopenharmony_ci	}
98162306a36Sopenharmony_ci
98262306a36Sopenharmony_ci	status = ice_aq_send_cmd(hw, &desc, buf, len, NULL);
98362306a36Sopenharmony_ci	if (!status) {
98462306a36Sopenharmony_ci		/* Update the current configuration to reflect events enabled.
98562306a36Sopenharmony_ci		 * hw->fw_log.cq_en and hw->fw_log.uart_en indicate if the FW
98662306a36Sopenharmony_ci		 * logging mode is enabled for the device. They do not reflect
98762306a36Sopenharmony_ci		 * actual modules being enabled to emit log messages. So, their
98862306a36Sopenharmony_ci		 * values remain unchanged even when all modules are disabled.
98962306a36Sopenharmony_ci		 */
99062306a36Sopenharmony_ci		u16 cnt = enable ? chgs : (u16)ICE_AQC_FW_LOG_ID_MAX;
99162306a36Sopenharmony_ci
99262306a36Sopenharmony_ci		hw->fw_log.actv_evnts = actv_evnts;
99362306a36Sopenharmony_ci		for (i = 0; i < cnt; i++) {
99462306a36Sopenharmony_ci			u16 v, m;
99562306a36Sopenharmony_ci
99662306a36Sopenharmony_ci			if (!enable) {
99762306a36Sopenharmony_ci				/* When disabling all FW logging events as part
99862306a36Sopenharmony_ci				 * of device's de-initialization, the original
99962306a36Sopenharmony_ci				 * configurations are retained, and can be used
100062306a36Sopenharmony_ci				 * to reconfigure FW logging later if the device
100162306a36Sopenharmony_ci				 * is re-initialized.
100262306a36Sopenharmony_ci				 */
100362306a36Sopenharmony_ci				hw->fw_log.evnts[i].cur = 0;
100462306a36Sopenharmony_ci				continue;
100562306a36Sopenharmony_ci			}
100662306a36Sopenharmony_ci
100762306a36Sopenharmony_ci			v = le16_to_cpu(data[i]);
100862306a36Sopenharmony_ci			m = (v & ICE_AQC_FW_LOG_ID_M) >> ICE_AQC_FW_LOG_ID_S;
100962306a36Sopenharmony_ci			hw->fw_log.evnts[m].cur = hw->fw_log.evnts[m].cfg;
101062306a36Sopenharmony_ci		}
101162306a36Sopenharmony_ci	}
101262306a36Sopenharmony_ci
101362306a36Sopenharmony_ciout:
101462306a36Sopenharmony_ci	devm_kfree(ice_hw_to_dev(hw), data);
101562306a36Sopenharmony_ci
101662306a36Sopenharmony_ci	return status;
101762306a36Sopenharmony_ci}
101862306a36Sopenharmony_ci
101962306a36Sopenharmony_ci/**
102062306a36Sopenharmony_ci * ice_output_fw_log
102162306a36Sopenharmony_ci * @hw: pointer to the HW struct
102262306a36Sopenharmony_ci * @desc: pointer to the AQ message descriptor
102362306a36Sopenharmony_ci * @buf: pointer to the buffer accompanying the AQ message
102462306a36Sopenharmony_ci *
102562306a36Sopenharmony_ci * Formats a FW Log message and outputs it via the standard driver logs.
102662306a36Sopenharmony_ci */
102762306a36Sopenharmony_civoid ice_output_fw_log(struct ice_hw *hw, struct ice_aq_desc *desc, void *buf)
102862306a36Sopenharmony_ci{
102962306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_FW_LOG, "[ FW Log Msg Start ]\n");
103062306a36Sopenharmony_ci	ice_debug_array(hw, ICE_DBG_FW_LOG, 16, 1, (u8 *)buf,
103162306a36Sopenharmony_ci			le16_to_cpu(desc->datalen));
103262306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_FW_LOG, "[ FW Log Msg End ]\n");
103362306a36Sopenharmony_ci}
103462306a36Sopenharmony_ci
103562306a36Sopenharmony_ci/**
103662306a36Sopenharmony_ci * ice_get_itr_intrl_gran
103762306a36Sopenharmony_ci * @hw: pointer to the HW struct
103862306a36Sopenharmony_ci *
103962306a36Sopenharmony_ci * Determines the ITR/INTRL granularities based on the maximum aggregate
104062306a36Sopenharmony_ci * bandwidth according to the device's configuration during power-on.
104162306a36Sopenharmony_ci */
104262306a36Sopenharmony_cistatic void ice_get_itr_intrl_gran(struct ice_hw *hw)
104362306a36Sopenharmony_ci{
104462306a36Sopenharmony_ci	u8 max_agg_bw = (rd32(hw, GL_PWR_MODE_CTL) &
104562306a36Sopenharmony_ci			 GL_PWR_MODE_CTL_CAR_MAX_BW_M) >>
104662306a36Sopenharmony_ci			GL_PWR_MODE_CTL_CAR_MAX_BW_S;
104762306a36Sopenharmony_ci
104862306a36Sopenharmony_ci	switch (max_agg_bw) {
104962306a36Sopenharmony_ci	case ICE_MAX_AGG_BW_200G:
105062306a36Sopenharmony_ci	case ICE_MAX_AGG_BW_100G:
105162306a36Sopenharmony_ci	case ICE_MAX_AGG_BW_50G:
105262306a36Sopenharmony_ci		hw->itr_gran = ICE_ITR_GRAN_ABOVE_25;
105362306a36Sopenharmony_ci		hw->intrl_gran = ICE_INTRL_GRAN_ABOVE_25;
105462306a36Sopenharmony_ci		break;
105562306a36Sopenharmony_ci	case ICE_MAX_AGG_BW_25G:
105662306a36Sopenharmony_ci		hw->itr_gran = ICE_ITR_GRAN_MAX_25;
105762306a36Sopenharmony_ci		hw->intrl_gran = ICE_INTRL_GRAN_MAX_25;
105862306a36Sopenharmony_ci		break;
105962306a36Sopenharmony_ci	}
106062306a36Sopenharmony_ci}
106162306a36Sopenharmony_ci
106262306a36Sopenharmony_ci/**
106362306a36Sopenharmony_ci * ice_init_hw - main hardware initialization routine
106462306a36Sopenharmony_ci * @hw: pointer to the hardware structure
106562306a36Sopenharmony_ci */
106662306a36Sopenharmony_ciint ice_init_hw(struct ice_hw *hw)
106762306a36Sopenharmony_ci{
106862306a36Sopenharmony_ci	struct ice_aqc_get_phy_caps_data *pcaps;
106962306a36Sopenharmony_ci	u16 mac_buf_len;
107062306a36Sopenharmony_ci	void *mac_buf;
107162306a36Sopenharmony_ci	int status;
107262306a36Sopenharmony_ci
107362306a36Sopenharmony_ci	/* Set MAC type based on DeviceID */
107462306a36Sopenharmony_ci	status = ice_set_mac_type(hw);
107562306a36Sopenharmony_ci	if (status)
107662306a36Sopenharmony_ci		return status;
107762306a36Sopenharmony_ci
107862306a36Sopenharmony_ci	hw->pf_id = (u8)(rd32(hw, PF_FUNC_RID) &
107962306a36Sopenharmony_ci			 PF_FUNC_RID_FUNC_NUM_M) >>
108062306a36Sopenharmony_ci		PF_FUNC_RID_FUNC_NUM_S;
108162306a36Sopenharmony_ci
108262306a36Sopenharmony_ci	status = ice_reset(hw, ICE_RESET_PFR);
108362306a36Sopenharmony_ci	if (status)
108462306a36Sopenharmony_ci		return status;
108562306a36Sopenharmony_ci
108662306a36Sopenharmony_ci	ice_get_itr_intrl_gran(hw);
108762306a36Sopenharmony_ci
108862306a36Sopenharmony_ci	status = ice_create_all_ctrlq(hw);
108962306a36Sopenharmony_ci	if (status)
109062306a36Sopenharmony_ci		goto err_unroll_cqinit;
109162306a36Sopenharmony_ci
109262306a36Sopenharmony_ci	/* Enable FW logging. Not fatal if this fails. */
109362306a36Sopenharmony_ci	status = ice_cfg_fw_log(hw, true);
109462306a36Sopenharmony_ci	if (status)
109562306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_INIT, "Failed to enable FW logging.\n");
109662306a36Sopenharmony_ci
109762306a36Sopenharmony_ci	status = ice_clear_pf_cfg(hw);
109862306a36Sopenharmony_ci	if (status)
109962306a36Sopenharmony_ci		goto err_unroll_cqinit;
110062306a36Sopenharmony_ci
110162306a36Sopenharmony_ci	/* Set bit to enable Flow Director filters */
110262306a36Sopenharmony_ci	wr32(hw, PFQF_FD_ENA, PFQF_FD_ENA_FD_ENA_M);
110362306a36Sopenharmony_ci	INIT_LIST_HEAD(&hw->fdir_list_head);
110462306a36Sopenharmony_ci
110562306a36Sopenharmony_ci	ice_clear_pxe_mode(hw);
110662306a36Sopenharmony_ci
110762306a36Sopenharmony_ci	status = ice_init_nvm(hw);
110862306a36Sopenharmony_ci	if (status)
110962306a36Sopenharmony_ci		goto err_unroll_cqinit;
111062306a36Sopenharmony_ci
111162306a36Sopenharmony_ci	status = ice_get_caps(hw);
111262306a36Sopenharmony_ci	if (status)
111362306a36Sopenharmony_ci		goto err_unroll_cqinit;
111462306a36Sopenharmony_ci
111562306a36Sopenharmony_ci	if (!hw->port_info)
111662306a36Sopenharmony_ci		hw->port_info = devm_kzalloc(ice_hw_to_dev(hw),
111762306a36Sopenharmony_ci					     sizeof(*hw->port_info),
111862306a36Sopenharmony_ci					     GFP_KERNEL);
111962306a36Sopenharmony_ci	if (!hw->port_info) {
112062306a36Sopenharmony_ci		status = -ENOMEM;
112162306a36Sopenharmony_ci		goto err_unroll_cqinit;
112262306a36Sopenharmony_ci	}
112362306a36Sopenharmony_ci
112462306a36Sopenharmony_ci	/* set the back pointer to HW */
112562306a36Sopenharmony_ci	hw->port_info->hw = hw;
112662306a36Sopenharmony_ci
112762306a36Sopenharmony_ci	/* Initialize port_info struct with switch configuration data */
112862306a36Sopenharmony_ci	status = ice_get_initial_sw_cfg(hw);
112962306a36Sopenharmony_ci	if (status)
113062306a36Sopenharmony_ci		goto err_unroll_alloc;
113162306a36Sopenharmony_ci
113262306a36Sopenharmony_ci	hw->evb_veb = true;
113362306a36Sopenharmony_ci
113462306a36Sopenharmony_ci	/* init xarray for identifying scheduling nodes uniquely */
113562306a36Sopenharmony_ci	xa_init_flags(&hw->port_info->sched_node_ids, XA_FLAGS_ALLOC);
113662306a36Sopenharmony_ci
113762306a36Sopenharmony_ci	/* Query the allocated resources for Tx scheduler */
113862306a36Sopenharmony_ci	status = ice_sched_query_res_alloc(hw);
113962306a36Sopenharmony_ci	if (status) {
114062306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_SCHED, "Failed to get scheduler allocated resources\n");
114162306a36Sopenharmony_ci		goto err_unroll_alloc;
114262306a36Sopenharmony_ci	}
114362306a36Sopenharmony_ci	ice_sched_get_psm_clk_freq(hw);
114462306a36Sopenharmony_ci
114562306a36Sopenharmony_ci	/* Initialize port_info struct with scheduler data */
114662306a36Sopenharmony_ci	status = ice_sched_init_port(hw->port_info);
114762306a36Sopenharmony_ci	if (status)
114862306a36Sopenharmony_ci		goto err_unroll_sched;
114962306a36Sopenharmony_ci
115062306a36Sopenharmony_ci	pcaps = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*pcaps), GFP_KERNEL);
115162306a36Sopenharmony_ci	if (!pcaps) {
115262306a36Sopenharmony_ci		status = -ENOMEM;
115362306a36Sopenharmony_ci		goto err_unroll_sched;
115462306a36Sopenharmony_ci	}
115562306a36Sopenharmony_ci
115662306a36Sopenharmony_ci	/* Initialize port_info struct with PHY capabilities */
115762306a36Sopenharmony_ci	status = ice_aq_get_phy_caps(hw->port_info, false,
115862306a36Sopenharmony_ci				     ICE_AQC_REPORT_TOPO_CAP_MEDIA, pcaps,
115962306a36Sopenharmony_ci				     NULL);
116062306a36Sopenharmony_ci	devm_kfree(ice_hw_to_dev(hw), pcaps);
116162306a36Sopenharmony_ci	if (status)
116262306a36Sopenharmony_ci		dev_warn(ice_hw_to_dev(hw), "Get PHY capabilities failed status = %d, continuing anyway\n",
116362306a36Sopenharmony_ci			 status);
116462306a36Sopenharmony_ci
116562306a36Sopenharmony_ci	/* Initialize port_info struct with link information */
116662306a36Sopenharmony_ci	status = ice_aq_get_link_info(hw->port_info, false, NULL, NULL);
116762306a36Sopenharmony_ci	if (status)
116862306a36Sopenharmony_ci		goto err_unroll_sched;
116962306a36Sopenharmony_ci
117062306a36Sopenharmony_ci	/* need a valid SW entry point to build a Tx tree */
117162306a36Sopenharmony_ci	if (!hw->sw_entry_point_layer) {
117262306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_SCHED, "invalid sw entry point\n");
117362306a36Sopenharmony_ci		status = -EIO;
117462306a36Sopenharmony_ci		goto err_unroll_sched;
117562306a36Sopenharmony_ci	}
117662306a36Sopenharmony_ci	INIT_LIST_HEAD(&hw->agg_list);
117762306a36Sopenharmony_ci	/* Initialize max burst size */
117862306a36Sopenharmony_ci	if (!hw->max_burst_size)
117962306a36Sopenharmony_ci		ice_cfg_rl_burst_size(hw, ICE_SCHED_DFLT_BURST_SIZE);
118062306a36Sopenharmony_ci
118162306a36Sopenharmony_ci	status = ice_init_fltr_mgmt_struct(hw);
118262306a36Sopenharmony_ci	if (status)
118362306a36Sopenharmony_ci		goto err_unroll_sched;
118462306a36Sopenharmony_ci
118562306a36Sopenharmony_ci	/* Get MAC information */
118662306a36Sopenharmony_ci	/* A single port can report up to two (LAN and WoL) addresses */
118762306a36Sopenharmony_ci	mac_buf = devm_kcalloc(ice_hw_to_dev(hw), 2,
118862306a36Sopenharmony_ci			       sizeof(struct ice_aqc_manage_mac_read_resp),
118962306a36Sopenharmony_ci			       GFP_KERNEL);
119062306a36Sopenharmony_ci	mac_buf_len = 2 * sizeof(struct ice_aqc_manage_mac_read_resp);
119162306a36Sopenharmony_ci
119262306a36Sopenharmony_ci	if (!mac_buf) {
119362306a36Sopenharmony_ci		status = -ENOMEM;
119462306a36Sopenharmony_ci		goto err_unroll_fltr_mgmt_struct;
119562306a36Sopenharmony_ci	}
119662306a36Sopenharmony_ci
119762306a36Sopenharmony_ci	status = ice_aq_manage_mac_read(hw, mac_buf, mac_buf_len, NULL);
119862306a36Sopenharmony_ci	devm_kfree(ice_hw_to_dev(hw), mac_buf);
119962306a36Sopenharmony_ci
120062306a36Sopenharmony_ci	if (status)
120162306a36Sopenharmony_ci		goto err_unroll_fltr_mgmt_struct;
120262306a36Sopenharmony_ci	/* enable jumbo frame support at MAC level */
120362306a36Sopenharmony_ci	status = ice_aq_set_mac_cfg(hw, ICE_AQ_SET_MAC_FRAME_SIZE_MAX, NULL);
120462306a36Sopenharmony_ci	if (status)
120562306a36Sopenharmony_ci		goto err_unroll_fltr_mgmt_struct;
120662306a36Sopenharmony_ci	/* Obtain counter base index which would be used by flow director */
120762306a36Sopenharmony_ci	status = ice_alloc_fd_res_cntr(hw, &hw->fd_ctr_base);
120862306a36Sopenharmony_ci	if (status)
120962306a36Sopenharmony_ci		goto err_unroll_fltr_mgmt_struct;
121062306a36Sopenharmony_ci	status = ice_init_hw_tbls(hw);
121162306a36Sopenharmony_ci	if (status)
121262306a36Sopenharmony_ci		goto err_unroll_fltr_mgmt_struct;
121362306a36Sopenharmony_ci	mutex_init(&hw->tnl_lock);
121462306a36Sopenharmony_ci	return 0;
121562306a36Sopenharmony_ci
121662306a36Sopenharmony_cierr_unroll_fltr_mgmt_struct:
121762306a36Sopenharmony_ci	ice_cleanup_fltr_mgmt_struct(hw);
121862306a36Sopenharmony_cierr_unroll_sched:
121962306a36Sopenharmony_ci	ice_sched_cleanup_all(hw);
122062306a36Sopenharmony_cierr_unroll_alloc:
122162306a36Sopenharmony_ci	devm_kfree(ice_hw_to_dev(hw), hw->port_info);
122262306a36Sopenharmony_cierr_unroll_cqinit:
122362306a36Sopenharmony_ci	ice_destroy_all_ctrlq(hw);
122462306a36Sopenharmony_ci	return status;
122562306a36Sopenharmony_ci}
122662306a36Sopenharmony_ci
122762306a36Sopenharmony_ci/**
122862306a36Sopenharmony_ci * ice_deinit_hw - unroll initialization operations done by ice_init_hw
122962306a36Sopenharmony_ci * @hw: pointer to the hardware structure
123062306a36Sopenharmony_ci *
123162306a36Sopenharmony_ci * This should be called only during nominal operation, not as a result of
123262306a36Sopenharmony_ci * ice_init_hw() failing since ice_init_hw() will take care of unrolling
123362306a36Sopenharmony_ci * applicable initializations if it fails for any reason.
123462306a36Sopenharmony_ci */
123562306a36Sopenharmony_civoid ice_deinit_hw(struct ice_hw *hw)
123662306a36Sopenharmony_ci{
123762306a36Sopenharmony_ci	ice_free_fd_res_cntr(hw, hw->fd_ctr_base);
123862306a36Sopenharmony_ci	ice_cleanup_fltr_mgmt_struct(hw);
123962306a36Sopenharmony_ci
124062306a36Sopenharmony_ci	ice_sched_cleanup_all(hw);
124162306a36Sopenharmony_ci	ice_sched_clear_agg(hw);
124262306a36Sopenharmony_ci	ice_free_seg(hw);
124362306a36Sopenharmony_ci	ice_free_hw_tbls(hw);
124462306a36Sopenharmony_ci	mutex_destroy(&hw->tnl_lock);
124562306a36Sopenharmony_ci
124662306a36Sopenharmony_ci	/* Attempt to disable FW logging before shutting down control queues */
124762306a36Sopenharmony_ci	ice_cfg_fw_log(hw, false);
124862306a36Sopenharmony_ci	ice_destroy_all_ctrlq(hw);
124962306a36Sopenharmony_ci
125062306a36Sopenharmony_ci	/* Clear VSI contexts if not already cleared */
125162306a36Sopenharmony_ci	ice_clear_all_vsi_ctx(hw);
125262306a36Sopenharmony_ci}
125362306a36Sopenharmony_ci
125462306a36Sopenharmony_ci/**
125562306a36Sopenharmony_ci * ice_check_reset - Check to see if a global reset is complete
125662306a36Sopenharmony_ci * @hw: pointer to the hardware structure
125762306a36Sopenharmony_ci */
125862306a36Sopenharmony_ciint ice_check_reset(struct ice_hw *hw)
125962306a36Sopenharmony_ci{
126062306a36Sopenharmony_ci	u32 cnt, reg = 0, grst_timeout, uld_mask;
126162306a36Sopenharmony_ci
126262306a36Sopenharmony_ci	/* Poll for Device Active state in case a recent CORER, GLOBR,
126362306a36Sopenharmony_ci	 * or EMPR has occurred. The grst delay value is in 100ms units.
126462306a36Sopenharmony_ci	 * Add 1sec for outstanding AQ commands that can take a long time.
126562306a36Sopenharmony_ci	 */
126662306a36Sopenharmony_ci	grst_timeout = ((rd32(hw, GLGEN_RSTCTL) & GLGEN_RSTCTL_GRSTDEL_M) >>
126762306a36Sopenharmony_ci			GLGEN_RSTCTL_GRSTDEL_S) + 10;
126862306a36Sopenharmony_ci
126962306a36Sopenharmony_ci	for (cnt = 0; cnt < grst_timeout; cnt++) {
127062306a36Sopenharmony_ci		mdelay(100);
127162306a36Sopenharmony_ci		reg = rd32(hw, GLGEN_RSTAT);
127262306a36Sopenharmony_ci		if (!(reg & GLGEN_RSTAT_DEVSTATE_M))
127362306a36Sopenharmony_ci			break;
127462306a36Sopenharmony_ci	}
127562306a36Sopenharmony_ci
127662306a36Sopenharmony_ci	if (cnt == grst_timeout) {
127762306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_INIT, "Global reset polling failed to complete.\n");
127862306a36Sopenharmony_ci		return -EIO;
127962306a36Sopenharmony_ci	}
128062306a36Sopenharmony_ci
128162306a36Sopenharmony_ci#define ICE_RESET_DONE_MASK	(GLNVM_ULD_PCIER_DONE_M |\
128262306a36Sopenharmony_ci				 GLNVM_ULD_PCIER_DONE_1_M |\
128362306a36Sopenharmony_ci				 GLNVM_ULD_CORER_DONE_M |\
128462306a36Sopenharmony_ci				 GLNVM_ULD_GLOBR_DONE_M |\
128562306a36Sopenharmony_ci				 GLNVM_ULD_POR_DONE_M |\
128662306a36Sopenharmony_ci				 GLNVM_ULD_POR_DONE_1_M |\
128762306a36Sopenharmony_ci				 GLNVM_ULD_PCIER_DONE_2_M)
128862306a36Sopenharmony_ci
128962306a36Sopenharmony_ci	uld_mask = ICE_RESET_DONE_MASK | (hw->func_caps.common_cap.rdma ?
129062306a36Sopenharmony_ci					  GLNVM_ULD_PE_DONE_M : 0);
129162306a36Sopenharmony_ci
129262306a36Sopenharmony_ci	/* Device is Active; check Global Reset processes are done */
129362306a36Sopenharmony_ci	for (cnt = 0; cnt < ICE_PF_RESET_WAIT_COUNT; cnt++) {
129462306a36Sopenharmony_ci		reg = rd32(hw, GLNVM_ULD) & uld_mask;
129562306a36Sopenharmony_ci		if (reg == uld_mask) {
129662306a36Sopenharmony_ci			ice_debug(hw, ICE_DBG_INIT, "Global reset processes done. %d\n", cnt);
129762306a36Sopenharmony_ci			break;
129862306a36Sopenharmony_ci		}
129962306a36Sopenharmony_ci		mdelay(10);
130062306a36Sopenharmony_ci	}
130162306a36Sopenharmony_ci
130262306a36Sopenharmony_ci	if (cnt == ICE_PF_RESET_WAIT_COUNT) {
130362306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_INIT, "Wait for Reset Done timed out. GLNVM_ULD = 0x%x\n",
130462306a36Sopenharmony_ci			  reg);
130562306a36Sopenharmony_ci		return -EIO;
130662306a36Sopenharmony_ci	}
130762306a36Sopenharmony_ci
130862306a36Sopenharmony_ci	return 0;
130962306a36Sopenharmony_ci}
131062306a36Sopenharmony_ci
131162306a36Sopenharmony_ci/**
131262306a36Sopenharmony_ci * ice_pf_reset - Reset the PF
131362306a36Sopenharmony_ci * @hw: pointer to the hardware structure
131462306a36Sopenharmony_ci *
131562306a36Sopenharmony_ci * If a global reset has been triggered, this function checks
131662306a36Sopenharmony_ci * for its completion and then issues the PF reset
131762306a36Sopenharmony_ci */
131862306a36Sopenharmony_cistatic int ice_pf_reset(struct ice_hw *hw)
131962306a36Sopenharmony_ci{
132062306a36Sopenharmony_ci	u32 cnt, reg;
132162306a36Sopenharmony_ci
132262306a36Sopenharmony_ci	/* If at function entry a global reset was already in progress, i.e.
132362306a36Sopenharmony_ci	 * state is not 'device active' or any of the reset done bits are not
132462306a36Sopenharmony_ci	 * set in GLNVM_ULD, there is no need for a PF Reset; poll until the
132562306a36Sopenharmony_ci	 * global reset is done.
132662306a36Sopenharmony_ci	 */
132762306a36Sopenharmony_ci	if ((rd32(hw, GLGEN_RSTAT) & GLGEN_RSTAT_DEVSTATE_M) ||
132862306a36Sopenharmony_ci	    (rd32(hw, GLNVM_ULD) & ICE_RESET_DONE_MASK) ^ ICE_RESET_DONE_MASK) {
132962306a36Sopenharmony_ci		/* poll on global reset currently in progress until done */
133062306a36Sopenharmony_ci		if (ice_check_reset(hw))
133162306a36Sopenharmony_ci			return -EIO;
133262306a36Sopenharmony_ci
133362306a36Sopenharmony_ci		return 0;
133462306a36Sopenharmony_ci	}
133562306a36Sopenharmony_ci
133662306a36Sopenharmony_ci	/* Reset the PF */
133762306a36Sopenharmony_ci	reg = rd32(hw, PFGEN_CTRL);
133862306a36Sopenharmony_ci
133962306a36Sopenharmony_ci	wr32(hw, PFGEN_CTRL, (reg | PFGEN_CTRL_PFSWR_M));
134062306a36Sopenharmony_ci
134162306a36Sopenharmony_ci	/* Wait for the PFR to complete. The wait time is the global config lock
134262306a36Sopenharmony_ci	 * timeout plus the PFR timeout which will account for a possible reset
134362306a36Sopenharmony_ci	 * that is occurring during a download package operation.
134462306a36Sopenharmony_ci	 */
134562306a36Sopenharmony_ci	for (cnt = 0; cnt < ICE_GLOBAL_CFG_LOCK_TIMEOUT +
134662306a36Sopenharmony_ci	     ICE_PF_RESET_WAIT_COUNT; cnt++) {
134762306a36Sopenharmony_ci		reg = rd32(hw, PFGEN_CTRL);
134862306a36Sopenharmony_ci		if (!(reg & PFGEN_CTRL_PFSWR_M))
134962306a36Sopenharmony_ci			break;
135062306a36Sopenharmony_ci
135162306a36Sopenharmony_ci		mdelay(1);
135262306a36Sopenharmony_ci	}
135362306a36Sopenharmony_ci
135462306a36Sopenharmony_ci	if (cnt == ICE_PF_RESET_WAIT_COUNT) {
135562306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_INIT, "PF reset polling failed to complete.\n");
135662306a36Sopenharmony_ci		return -EIO;
135762306a36Sopenharmony_ci	}
135862306a36Sopenharmony_ci
135962306a36Sopenharmony_ci	return 0;
136062306a36Sopenharmony_ci}
136162306a36Sopenharmony_ci
136262306a36Sopenharmony_ci/**
136362306a36Sopenharmony_ci * ice_reset - Perform different types of reset
136462306a36Sopenharmony_ci * @hw: pointer to the hardware structure
136562306a36Sopenharmony_ci * @req: reset request
136662306a36Sopenharmony_ci *
136762306a36Sopenharmony_ci * This function triggers a reset as specified by the req parameter.
136862306a36Sopenharmony_ci *
136962306a36Sopenharmony_ci * Note:
137062306a36Sopenharmony_ci * If anything other than a PF reset is triggered, PXE mode is restored.
137162306a36Sopenharmony_ci * This has to be cleared using ice_clear_pxe_mode again, once the AQ
137262306a36Sopenharmony_ci * interface has been restored in the rebuild flow.
137362306a36Sopenharmony_ci */
137462306a36Sopenharmony_ciint ice_reset(struct ice_hw *hw, enum ice_reset_req req)
137562306a36Sopenharmony_ci{
137662306a36Sopenharmony_ci	u32 val = 0;
137762306a36Sopenharmony_ci
137862306a36Sopenharmony_ci	switch (req) {
137962306a36Sopenharmony_ci	case ICE_RESET_PFR:
138062306a36Sopenharmony_ci		return ice_pf_reset(hw);
138162306a36Sopenharmony_ci	case ICE_RESET_CORER:
138262306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_INIT, "CoreR requested\n");
138362306a36Sopenharmony_ci		val = GLGEN_RTRIG_CORER_M;
138462306a36Sopenharmony_ci		break;
138562306a36Sopenharmony_ci	case ICE_RESET_GLOBR:
138662306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_INIT, "GlobalR requested\n");
138762306a36Sopenharmony_ci		val = GLGEN_RTRIG_GLOBR_M;
138862306a36Sopenharmony_ci		break;
138962306a36Sopenharmony_ci	default:
139062306a36Sopenharmony_ci		return -EINVAL;
139162306a36Sopenharmony_ci	}
139262306a36Sopenharmony_ci
139362306a36Sopenharmony_ci	val |= rd32(hw, GLGEN_RTRIG);
139462306a36Sopenharmony_ci	wr32(hw, GLGEN_RTRIG, val);
139562306a36Sopenharmony_ci	ice_flush(hw);
139662306a36Sopenharmony_ci
139762306a36Sopenharmony_ci	/* wait for the FW to be ready */
139862306a36Sopenharmony_ci	return ice_check_reset(hw);
139962306a36Sopenharmony_ci}
140062306a36Sopenharmony_ci
140162306a36Sopenharmony_ci/**
140262306a36Sopenharmony_ci * ice_copy_rxq_ctx_to_hw
140362306a36Sopenharmony_ci * @hw: pointer to the hardware structure
140462306a36Sopenharmony_ci * @ice_rxq_ctx: pointer to the rxq context
140562306a36Sopenharmony_ci * @rxq_index: the index of the Rx queue
140662306a36Sopenharmony_ci *
140762306a36Sopenharmony_ci * Copies rxq context from dense structure to HW register space
140862306a36Sopenharmony_ci */
140962306a36Sopenharmony_cistatic int
141062306a36Sopenharmony_ciice_copy_rxq_ctx_to_hw(struct ice_hw *hw, u8 *ice_rxq_ctx, u32 rxq_index)
141162306a36Sopenharmony_ci{
141262306a36Sopenharmony_ci	u8 i;
141362306a36Sopenharmony_ci
141462306a36Sopenharmony_ci	if (!ice_rxq_ctx)
141562306a36Sopenharmony_ci		return -EINVAL;
141662306a36Sopenharmony_ci
141762306a36Sopenharmony_ci	if (rxq_index > QRX_CTRL_MAX_INDEX)
141862306a36Sopenharmony_ci		return -EINVAL;
141962306a36Sopenharmony_ci
142062306a36Sopenharmony_ci	/* Copy each dword separately to HW */
142162306a36Sopenharmony_ci	for (i = 0; i < ICE_RXQ_CTX_SIZE_DWORDS; i++) {
142262306a36Sopenharmony_ci		wr32(hw, QRX_CONTEXT(i, rxq_index),
142362306a36Sopenharmony_ci		     *((u32 *)(ice_rxq_ctx + (i * sizeof(u32)))));
142462306a36Sopenharmony_ci
142562306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_QCTX, "qrxdata[%d]: %08X\n", i,
142662306a36Sopenharmony_ci			  *((u32 *)(ice_rxq_ctx + (i * sizeof(u32)))));
142762306a36Sopenharmony_ci	}
142862306a36Sopenharmony_ci
142962306a36Sopenharmony_ci	return 0;
143062306a36Sopenharmony_ci}
143162306a36Sopenharmony_ci
143262306a36Sopenharmony_ci/* LAN Rx Queue Context */
143362306a36Sopenharmony_cistatic const struct ice_ctx_ele ice_rlan_ctx_info[] = {
143462306a36Sopenharmony_ci	/* Field		Width	LSB */
143562306a36Sopenharmony_ci	ICE_CTX_STORE(ice_rlan_ctx, head,		13,	0),
143662306a36Sopenharmony_ci	ICE_CTX_STORE(ice_rlan_ctx, cpuid,		8,	13),
143762306a36Sopenharmony_ci	ICE_CTX_STORE(ice_rlan_ctx, base,		57,	32),
143862306a36Sopenharmony_ci	ICE_CTX_STORE(ice_rlan_ctx, qlen,		13,	89),
143962306a36Sopenharmony_ci	ICE_CTX_STORE(ice_rlan_ctx, dbuf,		7,	102),
144062306a36Sopenharmony_ci	ICE_CTX_STORE(ice_rlan_ctx, hbuf,		5,	109),
144162306a36Sopenharmony_ci	ICE_CTX_STORE(ice_rlan_ctx, dtype,		2,	114),
144262306a36Sopenharmony_ci	ICE_CTX_STORE(ice_rlan_ctx, dsize,		1,	116),
144362306a36Sopenharmony_ci	ICE_CTX_STORE(ice_rlan_ctx, crcstrip,		1,	117),
144462306a36Sopenharmony_ci	ICE_CTX_STORE(ice_rlan_ctx, l2tsel,		1,	119),
144562306a36Sopenharmony_ci	ICE_CTX_STORE(ice_rlan_ctx, hsplit_0,		4,	120),
144662306a36Sopenharmony_ci	ICE_CTX_STORE(ice_rlan_ctx, hsplit_1,		2,	124),
144762306a36Sopenharmony_ci	ICE_CTX_STORE(ice_rlan_ctx, showiv,		1,	127),
144862306a36Sopenharmony_ci	ICE_CTX_STORE(ice_rlan_ctx, rxmax,		14,	174),
144962306a36Sopenharmony_ci	ICE_CTX_STORE(ice_rlan_ctx, tphrdesc_ena,	1,	193),
145062306a36Sopenharmony_ci	ICE_CTX_STORE(ice_rlan_ctx, tphwdesc_ena,	1,	194),
145162306a36Sopenharmony_ci	ICE_CTX_STORE(ice_rlan_ctx, tphdata_ena,	1,	195),
145262306a36Sopenharmony_ci	ICE_CTX_STORE(ice_rlan_ctx, tphhead_ena,	1,	196),
145362306a36Sopenharmony_ci	ICE_CTX_STORE(ice_rlan_ctx, lrxqthresh,		3,	198),
145462306a36Sopenharmony_ci	ICE_CTX_STORE(ice_rlan_ctx, prefena,		1,	201),
145562306a36Sopenharmony_ci	{ 0 }
145662306a36Sopenharmony_ci};
145762306a36Sopenharmony_ci
145862306a36Sopenharmony_ci/**
145962306a36Sopenharmony_ci * ice_write_rxq_ctx
146062306a36Sopenharmony_ci * @hw: pointer to the hardware structure
146162306a36Sopenharmony_ci * @rlan_ctx: pointer to the rxq context
146262306a36Sopenharmony_ci * @rxq_index: the index of the Rx queue
146362306a36Sopenharmony_ci *
146462306a36Sopenharmony_ci * Converts rxq context from sparse to dense structure and then writes
146562306a36Sopenharmony_ci * it to HW register space and enables the hardware to prefetch descriptors
146662306a36Sopenharmony_ci * instead of only fetching them on demand
146762306a36Sopenharmony_ci */
146862306a36Sopenharmony_ciint
146962306a36Sopenharmony_ciice_write_rxq_ctx(struct ice_hw *hw, struct ice_rlan_ctx *rlan_ctx,
147062306a36Sopenharmony_ci		  u32 rxq_index)
147162306a36Sopenharmony_ci{
147262306a36Sopenharmony_ci	u8 ctx_buf[ICE_RXQ_CTX_SZ] = { 0 };
147362306a36Sopenharmony_ci
147462306a36Sopenharmony_ci	if (!rlan_ctx)
147562306a36Sopenharmony_ci		return -EINVAL;
147662306a36Sopenharmony_ci
147762306a36Sopenharmony_ci	rlan_ctx->prefena = 1;
147862306a36Sopenharmony_ci
147962306a36Sopenharmony_ci	ice_set_ctx(hw, (u8 *)rlan_ctx, ctx_buf, ice_rlan_ctx_info);
148062306a36Sopenharmony_ci	return ice_copy_rxq_ctx_to_hw(hw, ctx_buf, rxq_index);
148162306a36Sopenharmony_ci}
148262306a36Sopenharmony_ci
148362306a36Sopenharmony_ci/* LAN Tx Queue Context */
148462306a36Sopenharmony_ciconst struct ice_ctx_ele ice_tlan_ctx_info[] = {
148562306a36Sopenharmony_ci				    /* Field			Width	LSB */
148662306a36Sopenharmony_ci	ICE_CTX_STORE(ice_tlan_ctx, base,			57,	0),
148762306a36Sopenharmony_ci	ICE_CTX_STORE(ice_tlan_ctx, port_num,			3,	57),
148862306a36Sopenharmony_ci	ICE_CTX_STORE(ice_tlan_ctx, cgd_num,			5,	60),
148962306a36Sopenharmony_ci	ICE_CTX_STORE(ice_tlan_ctx, pf_num,			3,	65),
149062306a36Sopenharmony_ci	ICE_CTX_STORE(ice_tlan_ctx, vmvf_num,			10,	68),
149162306a36Sopenharmony_ci	ICE_CTX_STORE(ice_tlan_ctx, vmvf_type,			2,	78),
149262306a36Sopenharmony_ci	ICE_CTX_STORE(ice_tlan_ctx, src_vsi,			10,	80),
149362306a36Sopenharmony_ci	ICE_CTX_STORE(ice_tlan_ctx, tsyn_ena,			1,	90),
149462306a36Sopenharmony_ci	ICE_CTX_STORE(ice_tlan_ctx, internal_usage_flag,	1,	91),
149562306a36Sopenharmony_ci	ICE_CTX_STORE(ice_tlan_ctx, alt_vlan,			1,	92),
149662306a36Sopenharmony_ci	ICE_CTX_STORE(ice_tlan_ctx, cpuid,			8,	93),
149762306a36Sopenharmony_ci	ICE_CTX_STORE(ice_tlan_ctx, wb_mode,			1,	101),
149862306a36Sopenharmony_ci	ICE_CTX_STORE(ice_tlan_ctx, tphrd_desc,			1,	102),
149962306a36Sopenharmony_ci	ICE_CTX_STORE(ice_tlan_ctx, tphrd,			1,	103),
150062306a36Sopenharmony_ci	ICE_CTX_STORE(ice_tlan_ctx, tphwr_desc,			1,	104),
150162306a36Sopenharmony_ci	ICE_CTX_STORE(ice_tlan_ctx, cmpq_id,			9,	105),
150262306a36Sopenharmony_ci	ICE_CTX_STORE(ice_tlan_ctx, qnum_in_func,		14,	114),
150362306a36Sopenharmony_ci	ICE_CTX_STORE(ice_tlan_ctx, itr_notification_mode,	1,	128),
150462306a36Sopenharmony_ci	ICE_CTX_STORE(ice_tlan_ctx, adjust_prof_id,		6,	129),
150562306a36Sopenharmony_ci	ICE_CTX_STORE(ice_tlan_ctx, qlen,			13,	135),
150662306a36Sopenharmony_ci	ICE_CTX_STORE(ice_tlan_ctx, quanta_prof_idx,		4,	148),
150762306a36Sopenharmony_ci	ICE_CTX_STORE(ice_tlan_ctx, tso_ena,			1,	152),
150862306a36Sopenharmony_ci	ICE_CTX_STORE(ice_tlan_ctx, tso_qnum,			11,	153),
150962306a36Sopenharmony_ci	ICE_CTX_STORE(ice_tlan_ctx, legacy_int,			1,	164),
151062306a36Sopenharmony_ci	ICE_CTX_STORE(ice_tlan_ctx, drop_ena,			1,	165),
151162306a36Sopenharmony_ci	ICE_CTX_STORE(ice_tlan_ctx, cache_prof_idx,		2,	166),
151262306a36Sopenharmony_ci	ICE_CTX_STORE(ice_tlan_ctx, pkt_shaper_prof_idx,	3,	168),
151362306a36Sopenharmony_ci	ICE_CTX_STORE(ice_tlan_ctx, int_q_state,		122,	171),
151462306a36Sopenharmony_ci	{ 0 }
151562306a36Sopenharmony_ci};
151662306a36Sopenharmony_ci
151762306a36Sopenharmony_ci/* Sideband Queue command wrappers */
151862306a36Sopenharmony_ci
151962306a36Sopenharmony_ci/**
152062306a36Sopenharmony_ci * ice_sbq_send_cmd - send Sideband Queue command to Sideband Queue
152162306a36Sopenharmony_ci * @hw: pointer to the HW struct
152262306a36Sopenharmony_ci * @desc: descriptor describing the command
152362306a36Sopenharmony_ci * @buf: buffer to use for indirect commands (NULL for direct commands)
152462306a36Sopenharmony_ci * @buf_size: size of buffer for indirect commands (0 for direct commands)
152562306a36Sopenharmony_ci * @cd: pointer to command details structure
152662306a36Sopenharmony_ci */
152762306a36Sopenharmony_cistatic int
152862306a36Sopenharmony_ciice_sbq_send_cmd(struct ice_hw *hw, struct ice_sbq_cmd_desc *desc,
152962306a36Sopenharmony_ci		 void *buf, u16 buf_size, struct ice_sq_cd *cd)
153062306a36Sopenharmony_ci{
153162306a36Sopenharmony_ci	return ice_sq_send_cmd(hw, ice_get_sbq(hw),
153262306a36Sopenharmony_ci			       (struct ice_aq_desc *)desc, buf, buf_size, cd);
153362306a36Sopenharmony_ci}
153462306a36Sopenharmony_ci
153562306a36Sopenharmony_ci/**
153662306a36Sopenharmony_ci * ice_sbq_rw_reg - Fill Sideband Queue command
153762306a36Sopenharmony_ci * @hw: pointer to the HW struct
153862306a36Sopenharmony_ci * @in: message info to be filled in descriptor
153962306a36Sopenharmony_ci */
154062306a36Sopenharmony_ciint ice_sbq_rw_reg(struct ice_hw *hw, struct ice_sbq_msg_input *in)
154162306a36Sopenharmony_ci{
154262306a36Sopenharmony_ci	struct ice_sbq_cmd_desc desc = {0};
154362306a36Sopenharmony_ci	struct ice_sbq_msg_req msg = {0};
154462306a36Sopenharmony_ci	u16 msg_len;
154562306a36Sopenharmony_ci	int status;
154662306a36Sopenharmony_ci
154762306a36Sopenharmony_ci	msg_len = sizeof(msg);
154862306a36Sopenharmony_ci
154962306a36Sopenharmony_ci	msg.dest_dev = in->dest_dev;
155062306a36Sopenharmony_ci	msg.opcode = in->opcode;
155162306a36Sopenharmony_ci	msg.flags = ICE_SBQ_MSG_FLAGS;
155262306a36Sopenharmony_ci	msg.sbe_fbe = ICE_SBQ_MSG_SBE_FBE;
155362306a36Sopenharmony_ci	msg.msg_addr_low = cpu_to_le16(in->msg_addr_low);
155462306a36Sopenharmony_ci	msg.msg_addr_high = cpu_to_le32(in->msg_addr_high);
155562306a36Sopenharmony_ci
155662306a36Sopenharmony_ci	if (in->opcode)
155762306a36Sopenharmony_ci		msg.data = cpu_to_le32(in->data);
155862306a36Sopenharmony_ci	else
155962306a36Sopenharmony_ci		/* data read comes back in completion, so shorten the struct by
156062306a36Sopenharmony_ci		 * sizeof(msg.data)
156162306a36Sopenharmony_ci		 */
156262306a36Sopenharmony_ci		msg_len -= sizeof(msg.data);
156362306a36Sopenharmony_ci
156462306a36Sopenharmony_ci	desc.flags = cpu_to_le16(ICE_AQ_FLAG_RD);
156562306a36Sopenharmony_ci	desc.opcode = cpu_to_le16(ice_sbq_opc_neigh_dev_req);
156662306a36Sopenharmony_ci	desc.param0.cmd_len = cpu_to_le16(msg_len);
156762306a36Sopenharmony_ci	status = ice_sbq_send_cmd(hw, &desc, &msg, msg_len, NULL);
156862306a36Sopenharmony_ci	if (!status && !in->opcode)
156962306a36Sopenharmony_ci		in->data = le32_to_cpu
157062306a36Sopenharmony_ci			(((struct ice_sbq_msg_cmpl *)&msg)->data);
157162306a36Sopenharmony_ci	return status;
157262306a36Sopenharmony_ci}
157362306a36Sopenharmony_ci
157462306a36Sopenharmony_ci/* FW Admin Queue command wrappers */
157562306a36Sopenharmony_ci
157662306a36Sopenharmony_ci/* Software lock/mutex that is meant to be held while the Global Config Lock
157762306a36Sopenharmony_ci * in firmware is acquired by the software to prevent most (but not all) types
157862306a36Sopenharmony_ci * of AQ commands from being sent to FW
157962306a36Sopenharmony_ci */
158062306a36Sopenharmony_ciDEFINE_MUTEX(ice_global_cfg_lock_sw);
158162306a36Sopenharmony_ci
158262306a36Sopenharmony_ci/**
158362306a36Sopenharmony_ci * ice_should_retry_sq_send_cmd
158462306a36Sopenharmony_ci * @opcode: AQ opcode
158562306a36Sopenharmony_ci *
158662306a36Sopenharmony_ci * Decide if we should retry the send command routine for the ATQ, depending
158762306a36Sopenharmony_ci * on the opcode.
158862306a36Sopenharmony_ci */
158962306a36Sopenharmony_cistatic bool ice_should_retry_sq_send_cmd(u16 opcode)
159062306a36Sopenharmony_ci{
159162306a36Sopenharmony_ci	switch (opcode) {
159262306a36Sopenharmony_ci	case ice_aqc_opc_get_link_topo:
159362306a36Sopenharmony_ci	case ice_aqc_opc_lldp_stop:
159462306a36Sopenharmony_ci	case ice_aqc_opc_lldp_start:
159562306a36Sopenharmony_ci	case ice_aqc_opc_lldp_filter_ctrl:
159662306a36Sopenharmony_ci		return true;
159762306a36Sopenharmony_ci	}
159862306a36Sopenharmony_ci
159962306a36Sopenharmony_ci	return false;
160062306a36Sopenharmony_ci}
160162306a36Sopenharmony_ci
160262306a36Sopenharmony_ci/**
160362306a36Sopenharmony_ci * ice_sq_send_cmd_retry - send command to Control Queue (ATQ)
160462306a36Sopenharmony_ci * @hw: pointer to the HW struct
160562306a36Sopenharmony_ci * @cq: pointer to the specific Control queue
160662306a36Sopenharmony_ci * @desc: prefilled descriptor describing the command
160762306a36Sopenharmony_ci * @buf: buffer to use for indirect commands (or NULL for direct commands)
160862306a36Sopenharmony_ci * @buf_size: size of buffer for indirect commands (or 0 for direct commands)
160962306a36Sopenharmony_ci * @cd: pointer to command details structure
161062306a36Sopenharmony_ci *
161162306a36Sopenharmony_ci * Retry sending the FW Admin Queue command, multiple times, to the FW Admin
161262306a36Sopenharmony_ci * Queue if the EBUSY AQ error is returned.
161362306a36Sopenharmony_ci */
161462306a36Sopenharmony_cistatic int
161562306a36Sopenharmony_ciice_sq_send_cmd_retry(struct ice_hw *hw, struct ice_ctl_q_info *cq,
161662306a36Sopenharmony_ci		      struct ice_aq_desc *desc, void *buf, u16 buf_size,
161762306a36Sopenharmony_ci		      struct ice_sq_cd *cd)
161862306a36Sopenharmony_ci{
161962306a36Sopenharmony_ci	struct ice_aq_desc desc_cpy;
162062306a36Sopenharmony_ci	bool is_cmd_for_retry;
162162306a36Sopenharmony_ci	u8 idx = 0;
162262306a36Sopenharmony_ci	u16 opcode;
162362306a36Sopenharmony_ci	int status;
162462306a36Sopenharmony_ci
162562306a36Sopenharmony_ci	opcode = le16_to_cpu(desc->opcode);
162662306a36Sopenharmony_ci	is_cmd_for_retry = ice_should_retry_sq_send_cmd(opcode);
162762306a36Sopenharmony_ci	memset(&desc_cpy, 0, sizeof(desc_cpy));
162862306a36Sopenharmony_ci
162962306a36Sopenharmony_ci	if (is_cmd_for_retry) {
163062306a36Sopenharmony_ci		/* All retryable cmds are direct, without buf. */
163162306a36Sopenharmony_ci		WARN_ON(buf);
163262306a36Sopenharmony_ci
163362306a36Sopenharmony_ci		memcpy(&desc_cpy, desc, sizeof(desc_cpy));
163462306a36Sopenharmony_ci	}
163562306a36Sopenharmony_ci
163662306a36Sopenharmony_ci	do {
163762306a36Sopenharmony_ci		status = ice_sq_send_cmd(hw, cq, desc, buf, buf_size, cd);
163862306a36Sopenharmony_ci
163962306a36Sopenharmony_ci		if (!is_cmd_for_retry || !status ||
164062306a36Sopenharmony_ci		    hw->adminq.sq_last_status != ICE_AQ_RC_EBUSY)
164162306a36Sopenharmony_ci			break;
164262306a36Sopenharmony_ci
164362306a36Sopenharmony_ci		memcpy(desc, &desc_cpy, sizeof(desc_cpy));
164462306a36Sopenharmony_ci
164562306a36Sopenharmony_ci		msleep(ICE_SQ_SEND_DELAY_TIME_MS);
164662306a36Sopenharmony_ci
164762306a36Sopenharmony_ci	} while (++idx < ICE_SQ_SEND_MAX_EXECUTE);
164862306a36Sopenharmony_ci
164962306a36Sopenharmony_ci	return status;
165062306a36Sopenharmony_ci}
165162306a36Sopenharmony_ci
165262306a36Sopenharmony_ci/**
165362306a36Sopenharmony_ci * ice_aq_send_cmd - send FW Admin Queue command to FW Admin Queue
165462306a36Sopenharmony_ci * @hw: pointer to the HW struct
165562306a36Sopenharmony_ci * @desc: descriptor describing the command
165662306a36Sopenharmony_ci * @buf: buffer to use for indirect commands (NULL for direct commands)
165762306a36Sopenharmony_ci * @buf_size: size of buffer for indirect commands (0 for direct commands)
165862306a36Sopenharmony_ci * @cd: pointer to command details structure
165962306a36Sopenharmony_ci *
166062306a36Sopenharmony_ci * Helper function to send FW Admin Queue commands to the FW Admin Queue.
166162306a36Sopenharmony_ci */
166262306a36Sopenharmony_ciint
166362306a36Sopenharmony_ciice_aq_send_cmd(struct ice_hw *hw, struct ice_aq_desc *desc, void *buf,
166462306a36Sopenharmony_ci		u16 buf_size, struct ice_sq_cd *cd)
166562306a36Sopenharmony_ci{
166662306a36Sopenharmony_ci	struct ice_aqc_req_res *cmd = &desc->params.res_owner;
166762306a36Sopenharmony_ci	bool lock_acquired = false;
166862306a36Sopenharmony_ci	int status;
166962306a36Sopenharmony_ci
167062306a36Sopenharmony_ci	/* When a package download is in process (i.e. when the firmware's
167162306a36Sopenharmony_ci	 * Global Configuration Lock resource is held), only the Download
167262306a36Sopenharmony_ci	 * Package, Get Version, Get Package Info List, Upload Section,
167362306a36Sopenharmony_ci	 * Update Package, Set Port Parameters, Get/Set VLAN Mode Parameters,
167462306a36Sopenharmony_ci	 * Add Recipe, Set Recipes to Profile Association, Get Recipe, and Get
167562306a36Sopenharmony_ci	 * Recipes to Profile Association, and Release Resource (with resource
167662306a36Sopenharmony_ci	 * ID set to Global Config Lock) AdminQ commands are allowed; all others
167762306a36Sopenharmony_ci	 * must block until the package download completes and the Global Config
167862306a36Sopenharmony_ci	 * Lock is released.  See also ice_acquire_global_cfg_lock().
167962306a36Sopenharmony_ci	 */
168062306a36Sopenharmony_ci	switch (le16_to_cpu(desc->opcode)) {
168162306a36Sopenharmony_ci	case ice_aqc_opc_download_pkg:
168262306a36Sopenharmony_ci	case ice_aqc_opc_get_pkg_info_list:
168362306a36Sopenharmony_ci	case ice_aqc_opc_get_ver:
168462306a36Sopenharmony_ci	case ice_aqc_opc_upload_section:
168562306a36Sopenharmony_ci	case ice_aqc_opc_update_pkg:
168662306a36Sopenharmony_ci	case ice_aqc_opc_set_port_params:
168762306a36Sopenharmony_ci	case ice_aqc_opc_get_vlan_mode_parameters:
168862306a36Sopenharmony_ci	case ice_aqc_opc_set_vlan_mode_parameters:
168962306a36Sopenharmony_ci	case ice_aqc_opc_add_recipe:
169062306a36Sopenharmony_ci	case ice_aqc_opc_recipe_to_profile:
169162306a36Sopenharmony_ci	case ice_aqc_opc_get_recipe:
169262306a36Sopenharmony_ci	case ice_aqc_opc_get_recipe_to_profile:
169362306a36Sopenharmony_ci		break;
169462306a36Sopenharmony_ci	case ice_aqc_opc_release_res:
169562306a36Sopenharmony_ci		if (le16_to_cpu(cmd->res_id) == ICE_AQC_RES_ID_GLBL_LOCK)
169662306a36Sopenharmony_ci			break;
169762306a36Sopenharmony_ci		fallthrough;
169862306a36Sopenharmony_ci	default:
169962306a36Sopenharmony_ci		mutex_lock(&ice_global_cfg_lock_sw);
170062306a36Sopenharmony_ci		lock_acquired = true;
170162306a36Sopenharmony_ci		break;
170262306a36Sopenharmony_ci	}
170362306a36Sopenharmony_ci
170462306a36Sopenharmony_ci	status = ice_sq_send_cmd_retry(hw, &hw->adminq, desc, buf, buf_size, cd);
170562306a36Sopenharmony_ci	if (lock_acquired)
170662306a36Sopenharmony_ci		mutex_unlock(&ice_global_cfg_lock_sw);
170762306a36Sopenharmony_ci
170862306a36Sopenharmony_ci	return status;
170962306a36Sopenharmony_ci}
171062306a36Sopenharmony_ci
171162306a36Sopenharmony_ci/**
171262306a36Sopenharmony_ci * ice_aq_get_fw_ver
171362306a36Sopenharmony_ci * @hw: pointer to the HW struct
171462306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL
171562306a36Sopenharmony_ci *
171662306a36Sopenharmony_ci * Get the firmware version (0x0001) from the admin queue commands
171762306a36Sopenharmony_ci */
171862306a36Sopenharmony_ciint ice_aq_get_fw_ver(struct ice_hw *hw, struct ice_sq_cd *cd)
171962306a36Sopenharmony_ci{
172062306a36Sopenharmony_ci	struct ice_aqc_get_ver *resp;
172162306a36Sopenharmony_ci	struct ice_aq_desc desc;
172262306a36Sopenharmony_ci	int status;
172362306a36Sopenharmony_ci
172462306a36Sopenharmony_ci	resp = &desc.params.get_ver;
172562306a36Sopenharmony_ci
172662306a36Sopenharmony_ci	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_ver);
172762306a36Sopenharmony_ci
172862306a36Sopenharmony_ci	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
172962306a36Sopenharmony_ci
173062306a36Sopenharmony_ci	if (!status) {
173162306a36Sopenharmony_ci		hw->fw_branch = resp->fw_branch;
173262306a36Sopenharmony_ci		hw->fw_maj_ver = resp->fw_major;
173362306a36Sopenharmony_ci		hw->fw_min_ver = resp->fw_minor;
173462306a36Sopenharmony_ci		hw->fw_patch = resp->fw_patch;
173562306a36Sopenharmony_ci		hw->fw_build = le32_to_cpu(resp->fw_build);
173662306a36Sopenharmony_ci		hw->api_branch = resp->api_branch;
173762306a36Sopenharmony_ci		hw->api_maj_ver = resp->api_major;
173862306a36Sopenharmony_ci		hw->api_min_ver = resp->api_minor;
173962306a36Sopenharmony_ci		hw->api_patch = resp->api_patch;
174062306a36Sopenharmony_ci	}
174162306a36Sopenharmony_ci
174262306a36Sopenharmony_ci	return status;
174362306a36Sopenharmony_ci}
174462306a36Sopenharmony_ci
174562306a36Sopenharmony_ci/**
174662306a36Sopenharmony_ci * ice_aq_send_driver_ver
174762306a36Sopenharmony_ci * @hw: pointer to the HW struct
174862306a36Sopenharmony_ci * @dv: driver's major, minor version
174962306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL
175062306a36Sopenharmony_ci *
175162306a36Sopenharmony_ci * Send the driver version (0x0002) to the firmware
175262306a36Sopenharmony_ci */
175362306a36Sopenharmony_ciint
175462306a36Sopenharmony_ciice_aq_send_driver_ver(struct ice_hw *hw, struct ice_driver_ver *dv,
175562306a36Sopenharmony_ci		       struct ice_sq_cd *cd)
175662306a36Sopenharmony_ci{
175762306a36Sopenharmony_ci	struct ice_aqc_driver_ver *cmd;
175862306a36Sopenharmony_ci	struct ice_aq_desc desc;
175962306a36Sopenharmony_ci	u16 len;
176062306a36Sopenharmony_ci
176162306a36Sopenharmony_ci	cmd = &desc.params.driver_ver;
176262306a36Sopenharmony_ci
176362306a36Sopenharmony_ci	if (!dv)
176462306a36Sopenharmony_ci		return -EINVAL;
176562306a36Sopenharmony_ci
176662306a36Sopenharmony_ci	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_driver_ver);
176762306a36Sopenharmony_ci
176862306a36Sopenharmony_ci	desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
176962306a36Sopenharmony_ci	cmd->major_ver = dv->major_ver;
177062306a36Sopenharmony_ci	cmd->minor_ver = dv->minor_ver;
177162306a36Sopenharmony_ci	cmd->build_ver = dv->build_ver;
177262306a36Sopenharmony_ci	cmd->subbuild_ver = dv->subbuild_ver;
177362306a36Sopenharmony_ci
177462306a36Sopenharmony_ci	len = 0;
177562306a36Sopenharmony_ci	while (len < sizeof(dv->driver_string) &&
177662306a36Sopenharmony_ci	       isascii(dv->driver_string[len]) && dv->driver_string[len])
177762306a36Sopenharmony_ci		len++;
177862306a36Sopenharmony_ci
177962306a36Sopenharmony_ci	return ice_aq_send_cmd(hw, &desc, dv->driver_string, len, cd);
178062306a36Sopenharmony_ci}
178162306a36Sopenharmony_ci
178262306a36Sopenharmony_ci/**
178362306a36Sopenharmony_ci * ice_aq_q_shutdown
178462306a36Sopenharmony_ci * @hw: pointer to the HW struct
178562306a36Sopenharmony_ci * @unloading: is the driver unloading itself
178662306a36Sopenharmony_ci *
178762306a36Sopenharmony_ci * Tell the Firmware that we're shutting down the AdminQ and whether
178862306a36Sopenharmony_ci * or not the driver is unloading as well (0x0003).
178962306a36Sopenharmony_ci */
179062306a36Sopenharmony_ciint ice_aq_q_shutdown(struct ice_hw *hw, bool unloading)
179162306a36Sopenharmony_ci{
179262306a36Sopenharmony_ci	struct ice_aqc_q_shutdown *cmd;
179362306a36Sopenharmony_ci	struct ice_aq_desc desc;
179462306a36Sopenharmony_ci
179562306a36Sopenharmony_ci	cmd = &desc.params.q_shutdown;
179662306a36Sopenharmony_ci
179762306a36Sopenharmony_ci	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_q_shutdown);
179862306a36Sopenharmony_ci
179962306a36Sopenharmony_ci	if (unloading)
180062306a36Sopenharmony_ci		cmd->driver_unloading = ICE_AQC_DRIVER_UNLOADING;
180162306a36Sopenharmony_ci
180262306a36Sopenharmony_ci	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
180362306a36Sopenharmony_ci}
180462306a36Sopenharmony_ci
180562306a36Sopenharmony_ci/**
180662306a36Sopenharmony_ci * ice_aq_req_res
180762306a36Sopenharmony_ci * @hw: pointer to the HW struct
180862306a36Sopenharmony_ci * @res: resource ID
180962306a36Sopenharmony_ci * @access: access type
181062306a36Sopenharmony_ci * @sdp_number: resource number
181162306a36Sopenharmony_ci * @timeout: the maximum time in ms that the driver may hold the resource
181262306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL
181362306a36Sopenharmony_ci *
181462306a36Sopenharmony_ci * Requests common resource using the admin queue commands (0x0008).
181562306a36Sopenharmony_ci * When attempting to acquire the Global Config Lock, the driver can
181662306a36Sopenharmony_ci * learn of three states:
181762306a36Sopenharmony_ci *  1) 0 -         acquired lock, and can perform download package
181862306a36Sopenharmony_ci *  2) -EIO -      did not get lock, driver should fail to load
181962306a36Sopenharmony_ci *  3) -EALREADY - did not get lock, but another driver has
182062306a36Sopenharmony_ci *                 successfully downloaded the package; the driver does
182162306a36Sopenharmony_ci *                 not have to download the package and can continue
182262306a36Sopenharmony_ci *                 loading
182362306a36Sopenharmony_ci *
182462306a36Sopenharmony_ci * Note that if the caller is in an acquire lock, perform action, release lock
182562306a36Sopenharmony_ci * phase of operation, it is possible that the FW may detect a timeout and issue
182662306a36Sopenharmony_ci * a CORER. In this case, the driver will receive a CORER interrupt and will
182762306a36Sopenharmony_ci * have to determine its cause. The calling thread that is handling this flow
182862306a36Sopenharmony_ci * will likely get an error propagated back to it indicating the Download
182962306a36Sopenharmony_ci * Package, Update Package or the Release Resource AQ commands timed out.
183062306a36Sopenharmony_ci */
183162306a36Sopenharmony_cistatic int
183262306a36Sopenharmony_ciice_aq_req_res(struct ice_hw *hw, enum ice_aq_res_ids res,
183362306a36Sopenharmony_ci	       enum ice_aq_res_access_type access, u8 sdp_number, u32 *timeout,
183462306a36Sopenharmony_ci	       struct ice_sq_cd *cd)
183562306a36Sopenharmony_ci{
183662306a36Sopenharmony_ci	struct ice_aqc_req_res *cmd_resp;
183762306a36Sopenharmony_ci	struct ice_aq_desc desc;
183862306a36Sopenharmony_ci	int status;
183962306a36Sopenharmony_ci
184062306a36Sopenharmony_ci	cmd_resp = &desc.params.res_owner;
184162306a36Sopenharmony_ci
184262306a36Sopenharmony_ci	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_req_res);
184362306a36Sopenharmony_ci
184462306a36Sopenharmony_ci	cmd_resp->res_id = cpu_to_le16(res);
184562306a36Sopenharmony_ci	cmd_resp->access_type = cpu_to_le16(access);
184662306a36Sopenharmony_ci	cmd_resp->res_number = cpu_to_le32(sdp_number);
184762306a36Sopenharmony_ci	cmd_resp->timeout = cpu_to_le32(*timeout);
184862306a36Sopenharmony_ci	*timeout = 0;
184962306a36Sopenharmony_ci
185062306a36Sopenharmony_ci	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
185162306a36Sopenharmony_ci
185262306a36Sopenharmony_ci	/* The completion specifies the maximum time in ms that the driver
185362306a36Sopenharmony_ci	 * may hold the resource in the Timeout field.
185462306a36Sopenharmony_ci	 */
185562306a36Sopenharmony_ci
185662306a36Sopenharmony_ci	/* Global config lock response utilizes an additional status field.
185762306a36Sopenharmony_ci	 *
185862306a36Sopenharmony_ci	 * If the Global config lock resource is held by some other driver, the
185962306a36Sopenharmony_ci	 * command completes with ICE_AQ_RES_GLBL_IN_PROG in the status field
186062306a36Sopenharmony_ci	 * and the timeout field indicates the maximum time the current owner
186162306a36Sopenharmony_ci	 * of the resource has to free it.
186262306a36Sopenharmony_ci	 */
186362306a36Sopenharmony_ci	if (res == ICE_GLOBAL_CFG_LOCK_RES_ID) {
186462306a36Sopenharmony_ci		if (le16_to_cpu(cmd_resp->status) == ICE_AQ_RES_GLBL_SUCCESS) {
186562306a36Sopenharmony_ci			*timeout = le32_to_cpu(cmd_resp->timeout);
186662306a36Sopenharmony_ci			return 0;
186762306a36Sopenharmony_ci		} else if (le16_to_cpu(cmd_resp->status) ==
186862306a36Sopenharmony_ci			   ICE_AQ_RES_GLBL_IN_PROG) {
186962306a36Sopenharmony_ci			*timeout = le32_to_cpu(cmd_resp->timeout);
187062306a36Sopenharmony_ci			return -EIO;
187162306a36Sopenharmony_ci		} else if (le16_to_cpu(cmd_resp->status) ==
187262306a36Sopenharmony_ci			   ICE_AQ_RES_GLBL_DONE) {
187362306a36Sopenharmony_ci			return -EALREADY;
187462306a36Sopenharmony_ci		}
187562306a36Sopenharmony_ci
187662306a36Sopenharmony_ci		/* invalid FW response, force a timeout immediately */
187762306a36Sopenharmony_ci		*timeout = 0;
187862306a36Sopenharmony_ci		return -EIO;
187962306a36Sopenharmony_ci	}
188062306a36Sopenharmony_ci
188162306a36Sopenharmony_ci	/* If the resource is held by some other driver, the command completes
188262306a36Sopenharmony_ci	 * with a busy return value and the timeout field indicates the maximum
188362306a36Sopenharmony_ci	 * time the current owner of the resource has to free it.
188462306a36Sopenharmony_ci	 */
188562306a36Sopenharmony_ci	if (!status || hw->adminq.sq_last_status == ICE_AQ_RC_EBUSY)
188662306a36Sopenharmony_ci		*timeout = le32_to_cpu(cmd_resp->timeout);
188762306a36Sopenharmony_ci
188862306a36Sopenharmony_ci	return status;
188962306a36Sopenharmony_ci}
189062306a36Sopenharmony_ci
189162306a36Sopenharmony_ci/**
189262306a36Sopenharmony_ci * ice_aq_release_res
189362306a36Sopenharmony_ci * @hw: pointer to the HW struct
189462306a36Sopenharmony_ci * @res: resource ID
189562306a36Sopenharmony_ci * @sdp_number: resource number
189662306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL
189762306a36Sopenharmony_ci *
189862306a36Sopenharmony_ci * release common resource using the admin queue commands (0x0009)
189962306a36Sopenharmony_ci */
190062306a36Sopenharmony_cistatic int
190162306a36Sopenharmony_ciice_aq_release_res(struct ice_hw *hw, enum ice_aq_res_ids res, u8 sdp_number,
190262306a36Sopenharmony_ci		   struct ice_sq_cd *cd)
190362306a36Sopenharmony_ci{
190462306a36Sopenharmony_ci	struct ice_aqc_req_res *cmd;
190562306a36Sopenharmony_ci	struct ice_aq_desc desc;
190662306a36Sopenharmony_ci
190762306a36Sopenharmony_ci	cmd = &desc.params.res_owner;
190862306a36Sopenharmony_ci
190962306a36Sopenharmony_ci	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_release_res);
191062306a36Sopenharmony_ci
191162306a36Sopenharmony_ci	cmd->res_id = cpu_to_le16(res);
191262306a36Sopenharmony_ci	cmd->res_number = cpu_to_le32(sdp_number);
191362306a36Sopenharmony_ci
191462306a36Sopenharmony_ci	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
191562306a36Sopenharmony_ci}
191662306a36Sopenharmony_ci
191762306a36Sopenharmony_ci/**
191862306a36Sopenharmony_ci * ice_acquire_res
191962306a36Sopenharmony_ci * @hw: pointer to the HW structure
192062306a36Sopenharmony_ci * @res: resource ID
192162306a36Sopenharmony_ci * @access: access type (read or write)
192262306a36Sopenharmony_ci * @timeout: timeout in milliseconds
192362306a36Sopenharmony_ci *
192462306a36Sopenharmony_ci * This function will attempt to acquire the ownership of a resource.
192562306a36Sopenharmony_ci */
192662306a36Sopenharmony_ciint
192762306a36Sopenharmony_ciice_acquire_res(struct ice_hw *hw, enum ice_aq_res_ids res,
192862306a36Sopenharmony_ci		enum ice_aq_res_access_type access, u32 timeout)
192962306a36Sopenharmony_ci{
193062306a36Sopenharmony_ci#define ICE_RES_POLLING_DELAY_MS	10
193162306a36Sopenharmony_ci	u32 delay = ICE_RES_POLLING_DELAY_MS;
193262306a36Sopenharmony_ci	u32 time_left = timeout;
193362306a36Sopenharmony_ci	int status;
193462306a36Sopenharmony_ci
193562306a36Sopenharmony_ci	status = ice_aq_req_res(hw, res, access, 0, &time_left, NULL);
193662306a36Sopenharmony_ci
193762306a36Sopenharmony_ci	/* A return code of -EALREADY means that another driver has
193862306a36Sopenharmony_ci	 * previously acquired the resource and performed any necessary updates;
193962306a36Sopenharmony_ci	 * in this case the caller does not obtain the resource and has no
194062306a36Sopenharmony_ci	 * further work to do.
194162306a36Sopenharmony_ci	 */
194262306a36Sopenharmony_ci	if (status == -EALREADY)
194362306a36Sopenharmony_ci		goto ice_acquire_res_exit;
194462306a36Sopenharmony_ci
194562306a36Sopenharmony_ci	if (status)
194662306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_RES, "resource %d acquire type %d failed.\n", res, access);
194762306a36Sopenharmony_ci
194862306a36Sopenharmony_ci	/* If necessary, poll until the current lock owner timeouts */
194962306a36Sopenharmony_ci	timeout = time_left;
195062306a36Sopenharmony_ci	while (status && timeout && time_left) {
195162306a36Sopenharmony_ci		mdelay(delay);
195262306a36Sopenharmony_ci		timeout = (timeout > delay) ? timeout - delay : 0;
195362306a36Sopenharmony_ci		status = ice_aq_req_res(hw, res, access, 0, &time_left, NULL);
195462306a36Sopenharmony_ci
195562306a36Sopenharmony_ci		if (status == -EALREADY)
195662306a36Sopenharmony_ci			/* lock free, but no work to do */
195762306a36Sopenharmony_ci			break;
195862306a36Sopenharmony_ci
195962306a36Sopenharmony_ci		if (!status)
196062306a36Sopenharmony_ci			/* lock acquired */
196162306a36Sopenharmony_ci			break;
196262306a36Sopenharmony_ci	}
196362306a36Sopenharmony_ci	if (status && status != -EALREADY)
196462306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_RES, "resource acquire timed out.\n");
196562306a36Sopenharmony_ci
196662306a36Sopenharmony_ciice_acquire_res_exit:
196762306a36Sopenharmony_ci	if (status == -EALREADY) {
196862306a36Sopenharmony_ci		if (access == ICE_RES_WRITE)
196962306a36Sopenharmony_ci			ice_debug(hw, ICE_DBG_RES, "resource indicates no work to do.\n");
197062306a36Sopenharmony_ci		else
197162306a36Sopenharmony_ci			ice_debug(hw, ICE_DBG_RES, "Warning: -EALREADY not expected\n");
197262306a36Sopenharmony_ci	}
197362306a36Sopenharmony_ci	return status;
197462306a36Sopenharmony_ci}
197562306a36Sopenharmony_ci
197662306a36Sopenharmony_ci/**
197762306a36Sopenharmony_ci * ice_release_res
197862306a36Sopenharmony_ci * @hw: pointer to the HW structure
197962306a36Sopenharmony_ci * @res: resource ID
198062306a36Sopenharmony_ci *
198162306a36Sopenharmony_ci * This function will release a resource using the proper Admin Command.
198262306a36Sopenharmony_ci */
198362306a36Sopenharmony_civoid ice_release_res(struct ice_hw *hw, enum ice_aq_res_ids res)
198462306a36Sopenharmony_ci{
198562306a36Sopenharmony_ci	unsigned long timeout;
198662306a36Sopenharmony_ci	int status;
198762306a36Sopenharmony_ci
198862306a36Sopenharmony_ci	/* there are some rare cases when trying to release the resource
198962306a36Sopenharmony_ci	 * results in an admin queue timeout, so handle them correctly
199062306a36Sopenharmony_ci	 */
199162306a36Sopenharmony_ci	timeout = jiffies + 10 * ICE_CTL_Q_SQ_CMD_TIMEOUT;
199262306a36Sopenharmony_ci	do {
199362306a36Sopenharmony_ci		status = ice_aq_release_res(hw, res, 0, NULL);
199462306a36Sopenharmony_ci		if (status != -EIO)
199562306a36Sopenharmony_ci			break;
199662306a36Sopenharmony_ci		usleep_range(1000, 2000);
199762306a36Sopenharmony_ci	} while (time_before(jiffies, timeout));
199862306a36Sopenharmony_ci}
199962306a36Sopenharmony_ci
200062306a36Sopenharmony_ci/**
200162306a36Sopenharmony_ci * ice_aq_alloc_free_res - command to allocate/free resources
200262306a36Sopenharmony_ci * @hw: pointer to the HW struct
200362306a36Sopenharmony_ci * @buf: Indirect buffer to hold data parameters and response
200462306a36Sopenharmony_ci * @buf_size: size of buffer for indirect commands
200562306a36Sopenharmony_ci * @opc: pass in the command opcode
200662306a36Sopenharmony_ci *
200762306a36Sopenharmony_ci * Helper function to allocate/free resources using the admin queue commands
200862306a36Sopenharmony_ci */
200962306a36Sopenharmony_ciint ice_aq_alloc_free_res(struct ice_hw *hw,
201062306a36Sopenharmony_ci			  struct ice_aqc_alloc_free_res_elem *buf, u16 buf_size,
201162306a36Sopenharmony_ci			  enum ice_adminq_opc opc)
201262306a36Sopenharmony_ci{
201362306a36Sopenharmony_ci	struct ice_aqc_alloc_free_res_cmd *cmd;
201462306a36Sopenharmony_ci	struct ice_aq_desc desc;
201562306a36Sopenharmony_ci
201662306a36Sopenharmony_ci	cmd = &desc.params.sw_res_ctrl;
201762306a36Sopenharmony_ci
201862306a36Sopenharmony_ci	if (!buf || buf_size < flex_array_size(buf, elem, 1))
201962306a36Sopenharmony_ci		return -EINVAL;
202062306a36Sopenharmony_ci
202162306a36Sopenharmony_ci	ice_fill_dflt_direct_cmd_desc(&desc, opc);
202262306a36Sopenharmony_ci
202362306a36Sopenharmony_ci	desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
202462306a36Sopenharmony_ci
202562306a36Sopenharmony_ci	cmd->num_entries = cpu_to_le16(1);
202662306a36Sopenharmony_ci
202762306a36Sopenharmony_ci	return ice_aq_send_cmd(hw, &desc, buf, buf_size, NULL);
202862306a36Sopenharmony_ci}
202962306a36Sopenharmony_ci
203062306a36Sopenharmony_ci/**
203162306a36Sopenharmony_ci * ice_alloc_hw_res - allocate resource
203262306a36Sopenharmony_ci * @hw: pointer to the HW struct
203362306a36Sopenharmony_ci * @type: type of resource
203462306a36Sopenharmony_ci * @num: number of resources to allocate
203562306a36Sopenharmony_ci * @btm: allocate from bottom
203662306a36Sopenharmony_ci * @res: pointer to array that will receive the resources
203762306a36Sopenharmony_ci */
203862306a36Sopenharmony_ciint
203962306a36Sopenharmony_ciice_alloc_hw_res(struct ice_hw *hw, u16 type, u16 num, bool btm, u16 *res)
204062306a36Sopenharmony_ci{
204162306a36Sopenharmony_ci	struct ice_aqc_alloc_free_res_elem *buf;
204262306a36Sopenharmony_ci	u16 buf_len;
204362306a36Sopenharmony_ci	int status;
204462306a36Sopenharmony_ci
204562306a36Sopenharmony_ci	buf_len = struct_size(buf, elem, num);
204662306a36Sopenharmony_ci	buf = kzalloc(buf_len, GFP_KERNEL);
204762306a36Sopenharmony_ci	if (!buf)
204862306a36Sopenharmony_ci		return -ENOMEM;
204962306a36Sopenharmony_ci
205062306a36Sopenharmony_ci	/* Prepare buffer to allocate resource. */
205162306a36Sopenharmony_ci	buf->num_elems = cpu_to_le16(num);
205262306a36Sopenharmony_ci	buf->res_type = cpu_to_le16(type | ICE_AQC_RES_TYPE_FLAG_DEDICATED |
205362306a36Sopenharmony_ci				    ICE_AQC_RES_TYPE_FLAG_IGNORE_INDEX);
205462306a36Sopenharmony_ci	if (btm)
205562306a36Sopenharmony_ci		buf->res_type |= cpu_to_le16(ICE_AQC_RES_TYPE_FLAG_SCAN_BOTTOM);
205662306a36Sopenharmony_ci
205762306a36Sopenharmony_ci	status = ice_aq_alloc_free_res(hw, buf, buf_len, ice_aqc_opc_alloc_res);
205862306a36Sopenharmony_ci	if (status)
205962306a36Sopenharmony_ci		goto ice_alloc_res_exit;
206062306a36Sopenharmony_ci
206162306a36Sopenharmony_ci	memcpy(res, buf->elem, sizeof(*buf->elem) * num);
206262306a36Sopenharmony_ci
206362306a36Sopenharmony_ciice_alloc_res_exit:
206462306a36Sopenharmony_ci	kfree(buf);
206562306a36Sopenharmony_ci	return status;
206662306a36Sopenharmony_ci}
206762306a36Sopenharmony_ci
206862306a36Sopenharmony_ci/**
206962306a36Sopenharmony_ci * ice_free_hw_res - free allocated HW resource
207062306a36Sopenharmony_ci * @hw: pointer to the HW struct
207162306a36Sopenharmony_ci * @type: type of resource to free
207262306a36Sopenharmony_ci * @num: number of resources
207362306a36Sopenharmony_ci * @res: pointer to array that contains the resources to free
207462306a36Sopenharmony_ci */
207562306a36Sopenharmony_ciint ice_free_hw_res(struct ice_hw *hw, u16 type, u16 num, u16 *res)
207662306a36Sopenharmony_ci{
207762306a36Sopenharmony_ci	struct ice_aqc_alloc_free_res_elem *buf;
207862306a36Sopenharmony_ci	u16 buf_len;
207962306a36Sopenharmony_ci	int status;
208062306a36Sopenharmony_ci
208162306a36Sopenharmony_ci	buf_len = struct_size(buf, elem, num);
208262306a36Sopenharmony_ci	buf = kzalloc(buf_len, GFP_KERNEL);
208362306a36Sopenharmony_ci	if (!buf)
208462306a36Sopenharmony_ci		return -ENOMEM;
208562306a36Sopenharmony_ci
208662306a36Sopenharmony_ci	/* Prepare buffer to free resource. */
208762306a36Sopenharmony_ci	buf->num_elems = cpu_to_le16(num);
208862306a36Sopenharmony_ci	buf->res_type = cpu_to_le16(type);
208962306a36Sopenharmony_ci	memcpy(buf->elem, res, sizeof(*buf->elem) * num);
209062306a36Sopenharmony_ci
209162306a36Sopenharmony_ci	status = ice_aq_alloc_free_res(hw, buf, buf_len, ice_aqc_opc_free_res);
209262306a36Sopenharmony_ci	if (status)
209362306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_SW, "CQ CMD Buffer:\n");
209462306a36Sopenharmony_ci
209562306a36Sopenharmony_ci	kfree(buf);
209662306a36Sopenharmony_ci	return status;
209762306a36Sopenharmony_ci}
209862306a36Sopenharmony_ci
209962306a36Sopenharmony_ci/**
210062306a36Sopenharmony_ci * ice_get_num_per_func - determine number of resources per PF
210162306a36Sopenharmony_ci * @hw: pointer to the HW structure
210262306a36Sopenharmony_ci * @max: value to be evenly split between each PF
210362306a36Sopenharmony_ci *
210462306a36Sopenharmony_ci * Determine the number of valid functions by going through the bitmap returned
210562306a36Sopenharmony_ci * from parsing capabilities and use this to calculate the number of resources
210662306a36Sopenharmony_ci * per PF based on the max value passed in.
210762306a36Sopenharmony_ci */
210862306a36Sopenharmony_cistatic u32 ice_get_num_per_func(struct ice_hw *hw, u32 max)
210962306a36Sopenharmony_ci{
211062306a36Sopenharmony_ci	u8 funcs;
211162306a36Sopenharmony_ci
211262306a36Sopenharmony_ci#define ICE_CAPS_VALID_FUNCS_M	0xFF
211362306a36Sopenharmony_ci	funcs = hweight8(hw->dev_caps.common_cap.valid_functions &
211462306a36Sopenharmony_ci			 ICE_CAPS_VALID_FUNCS_M);
211562306a36Sopenharmony_ci
211662306a36Sopenharmony_ci	if (!funcs)
211762306a36Sopenharmony_ci		return 0;
211862306a36Sopenharmony_ci
211962306a36Sopenharmony_ci	return max / funcs;
212062306a36Sopenharmony_ci}
212162306a36Sopenharmony_ci
212262306a36Sopenharmony_ci/**
212362306a36Sopenharmony_ci * ice_parse_common_caps - parse common device/function capabilities
212462306a36Sopenharmony_ci * @hw: pointer to the HW struct
212562306a36Sopenharmony_ci * @caps: pointer to common capabilities structure
212662306a36Sopenharmony_ci * @elem: the capability element to parse
212762306a36Sopenharmony_ci * @prefix: message prefix for tracing capabilities
212862306a36Sopenharmony_ci *
212962306a36Sopenharmony_ci * Given a capability element, extract relevant details into the common
213062306a36Sopenharmony_ci * capability structure.
213162306a36Sopenharmony_ci *
213262306a36Sopenharmony_ci * Returns: true if the capability matches one of the common capability ids,
213362306a36Sopenharmony_ci * false otherwise.
213462306a36Sopenharmony_ci */
213562306a36Sopenharmony_cistatic bool
213662306a36Sopenharmony_ciice_parse_common_caps(struct ice_hw *hw, struct ice_hw_common_caps *caps,
213762306a36Sopenharmony_ci		      struct ice_aqc_list_caps_elem *elem, const char *prefix)
213862306a36Sopenharmony_ci{
213962306a36Sopenharmony_ci	u32 logical_id = le32_to_cpu(elem->logical_id);
214062306a36Sopenharmony_ci	u32 phys_id = le32_to_cpu(elem->phys_id);
214162306a36Sopenharmony_ci	u32 number = le32_to_cpu(elem->number);
214262306a36Sopenharmony_ci	u16 cap = le16_to_cpu(elem->cap);
214362306a36Sopenharmony_ci	bool found = true;
214462306a36Sopenharmony_ci
214562306a36Sopenharmony_ci	switch (cap) {
214662306a36Sopenharmony_ci	case ICE_AQC_CAPS_VALID_FUNCTIONS:
214762306a36Sopenharmony_ci		caps->valid_functions = number;
214862306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_INIT, "%s: valid_functions (bitmap) = %d\n", prefix,
214962306a36Sopenharmony_ci			  caps->valid_functions);
215062306a36Sopenharmony_ci		break;
215162306a36Sopenharmony_ci	case ICE_AQC_CAPS_SRIOV:
215262306a36Sopenharmony_ci		caps->sr_iov_1_1 = (number == 1);
215362306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_INIT, "%s: sr_iov_1_1 = %d\n", prefix,
215462306a36Sopenharmony_ci			  caps->sr_iov_1_1);
215562306a36Sopenharmony_ci		break;
215662306a36Sopenharmony_ci	case ICE_AQC_CAPS_DCB:
215762306a36Sopenharmony_ci		caps->dcb = (number == 1);
215862306a36Sopenharmony_ci		caps->active_tc_bitmap = logical_id;
215962306a36Sopenharmony_ci		caps->maxtc = phys_id;
216062306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_INIT, "%s: dcb = %d\n", prefix, caps->dcb);
216162306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_INIT, "%s: active_tc_bitmap = %d\n", prefix,
216262306a36Sopenharmony_ci			  caps->active_tc_bitmap);
216362306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_INIT, "%s: maxtc = %d\n", prefix, caps->maxtc);
216462306a36Sopenharmony_ci		break;
216562306a36Sopenharmony_ci	case ICE_AQC_CAPS_RSS:
216662306a36Sopenharmony_ci		caps->rss_table_size = number;
216762306a36Sopenharmony_ci		caps->rss_table_entry_width = logical_id;
216862306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_INIT, "%s: rss_table_size = %d\n", prefix,
216962306a36Sopenharmony_ci			  caps->rss_table_size);
217062306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_INIT, "%s: rss_table_entry_width = %d\n", prefix,
217162306a36Sopenharmony_ci			  caps->rss_table_entry_width);
217262306a36Sopenharmony_ci		break;
217362306a36Sopenharmony_ci	case ICE_AQC_CAPS_RXQS:
217462306a36Sopenharmony_ci		caps->num_rxq = number;
217562306a36Sopenharmony_ci		caps->rxq_first_id = phys_id;
217662306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_INIT, "%s: num_rxq = %d\n", prefix,
217762306a36Sopenharmony_ci			  caps->num_rxq);
217862306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_INIT, "%s: rxq_first_id = %d\n", prefix,
217962306a36Sopenharmony_ci			  caps->rxq_first_id);
218062306a36Sopenharmony_ci		break;
218162306a36Sopenharmony_ci	case ICE_AQC_CAPS_TXQS:
218262306a36Sopenharmony_ci		caps->num_txq = number;
218362306a36Sopenharmony_ci		caps->txq_first_id = phys_id;
218462306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_INIT, "%s: num_txq = %d\n", prefix,
218562306a36Sopenharmony_ci			  caps->num_txq);
218662306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_INIT, "%s: txq_first_id = %d\n", prefix,
218762306a36Sopenharmony_ci			  caps->txq_first_id);
218862306a36Sopenharmony_ci		break;
218962306a36Sopenharmony_ci	case ICE_AQC_CAPS_MSIX:
219062306a36Sopenharmony_ci		caps->num_msix_vectors = number;
219162306a36Sopenharmony_ci		caps->msix_vector_first_id = phys_id;
219262306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_INIT, "%s: num_msix_vectors = %d\n", prefix,
219362306a36Sopenharmony_ci			  caps->num_msix_vectors);
219462306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_INIT, "%s: msix_vector_first_id = %d\n", prefix,
219562306a36Sopenharmony_ci			  caps->msix_vector_first_id);
219662306a36Sopenharmony_ci		break;
219762306a36Sopenharmony_ci	case ICE_AQC_CAPS_PENDING_NVM_VER:
219862306a36Sopenharmony_ci		caps->nvm_update_pending_nvm = true;
219962306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_INIT, "%s: update_pending_nvm\n", prefix);
220062306a36Sopenharmony_ci		break;
220162306a36Sopenharmony_ci	case ICE_AQC_CAPS_PENDING_OROM_VER:
220262306a36Sopenharmony_ci		caps->nvm_update_pending_orom = true;
220362306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_INIT, "%s: update_pending_orom\n", prefix);
220462306a36Sopenharmony_ci		break;
220562306a36Sopenharmony_ci	case ICE_AQC_CAPS_PENDING_NET_VER:
220662306a36Sopenharmony_ci		caps->nvm_update_pending_netlist = true;
220762306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_INIT, "%s: update_pending_netlist\n", prefix);
220862306a36Sopenharmony_ci		break;
220962306a36Sopenharmony_ci	case ICE_AQC_CAPS_NVM_MGMT:
221062306a36Sopenharmony_ci		caps->nvm_unified_update =
221162306a36Sopenharmony_ci			(number & ICE_NVM_MGMT_UNIFIED_UPD_SUPPORT) ?
221262306a36Sopenharmony_ci			true : false;
221362306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_INIT, "%s: nvm_unified_update = %d\n", prefix,
221462306a36Sopenharmony_ci			  caps->nvm_unified_update);
221562306a36Sopenharmony_ci		break;
221662306a36Sopenharmony_ci	case ICE_AQC_CAPS_RDMA:
221762306a36Sopenharmony_ci		caps->rdma = (number == 1);
221862306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_INIT, "%s: rdma = %d\n", prefix, caps->rdma);
221962306a36Sopenharmony_ci		break;
222062306a36Sopenharmony_ci	case ICE_AQC_CAPS_MAX_MTU:
222162306a36Sopenharmony_ci		caps->max_mtu = number;
222262306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_INIT, "%s: max_mtu = %d\n",
222362306a36Sopenharmony_ci			  prefix, caps->max_mtu);
222462306a36Sopenharmony_ci		break;
222562306a36Sopenharmony_ci	case ICE_AQC_CAPS_PCIE_RESET_AVOIDANCE:
222662306a36Sopenharmony_ci		caps->pcie_reset_avoidance = (number > 0);
222762306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_INIT,
222862306a36Sopenharmony_ci			  "%s: pcie_reset_avoidance = %d\n", prefix,
222962306a36Sopenharmony_ci			  caps->pcie_reset_avoidance);
223062306a36Sopenharmony_ci		break;
223162306a36Sopenharmony_ci	case ICE_AQC_CAPS_POST_UPDATE_RESET_RESTRICT:
223262306a36Sopenharmony_ci		caps->reset_restrict_support = (number == 1);
223362306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_INIT,
223462306a36Sopenharmony_ci			  "%s: reset_restrict_support = %d\n", prefix,
223562306a36Sopenharmony_ci			  caps->reset_restrict_support);
223662306a36Sopenharmony_ci		break;
223762306a36Sopenharmony_ci	case ICE_AQC_CAPS_FW_LAG_SUPPORT:
223862306a36Sopenharmony_ci		caps->roce_lag = !!(number & ICE_AQC_BIT_ROCEV2_LAG);
223962306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_INIT, "%s: roce_lag = %u\n",
224062306a36Sopenharmony_ci			  prefix, caps->roce_lag);
224162306a36Sopenharmony_ci		caps->sriov_lag = !!(number & ICE_AQC_BIT_SRIOV_LAG);
224262306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_INIT, "%s: sriov_lag = %u\n",
224362306a36Sopenharmony_ci			  prefix, caps->sriov_lag);
224462306a36Sopenharmony_ci		break;
224562306a36Sopenharmony_ci	default:
224662306a36Sopenharmony_ci		/* Not one of the recognized common capabilities */
224762306a36Sopenharmony_ci		found = false;
224862306a36Sopenharmony_ci	}
224962306a36Sopenharmony_ci
225062306a36Sopenharmony_ci	return found;
225162306a36Sopenharmony_ci}
225262306a36Sopenharmony_ci
225362306a36Sopenharmony_ci/**
225462306a36Sopenharmony_ci * ice_recalc_port_limited_caps - Recalculate port limited capabilities
225562306a36Sopenharmony_ci * @hw: pointer to the HW structure
225662306a36Sopenharmony_ci * @caps: pointer to capabilities structure to fix
225762306a36Sopenharmony_ci *
225862306a36Sopenharmony_ci * Re-calculate the capabilities that are dependent on the number of physical
225962306a36Sopenharmony_ci * ports; i.e. some features are not supported or function differently on
226062306a36Sopenharmony_ci * devices with more than 4 ports.
226162306a36Sopenharmony_ci */
226262306a36Sopenharmony_cistatic void
226362306a36Sopenharmony_ciice_recalc_port_limited_caps(struct ice_hw *hw, struct ice_hw_common_caps *caps)
226462306a36Sopenharmony_ci{
226562306a36Sopenharmony_ci	/* This assumes device capabilities are always scanned before function
226662306a36Sopenharmony_ci	 * capabilities during the initialization flow.
226762306a36Sopenharmony_ci	 */
226862306a36Sopenharmony_ci	if (hw->dev_caps.num_funcs > 4) {
226962306a36Sopenharmony_ci		/* Max 4 TCs per port */
227062306a36Sopenharmony_ci		caps->maxtc = 4;
227162306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_INIT, "reducing maxtc to %d (based on #ports)\n",
227262306a36Sopenharmony_ci			  caps->maxtc);
227362306a36Sopenharmony_ci		if (caps->rdma) {
227462306a36Sopenharmony_ci			ice_debug(hw, ICE_DBG_INIT, "forcing RDMA off\n");
227562306a36Sopenharmony_ci			caps->rdma = 0;
227662306a36Sopenharmony_ci		}
227762306a36Sopenharmony_ci
227862306a36Sopenharmony_ci		/* print message only when processing device capabilities
227962306a36Sopenharmony_ci		 * during initialization.
228062306a36Sopenharmony_ci		 */
228162306a36Sopenharmony_ci		if (caps == &hw->dev_caps.common_cap)
228262306a36Sopenharmony_ci			dev_info(ice_hw_to_dev(hw), "RDMA functionality is not available with the current device configuration.\n");
228362306a36Sopenharmony_ci	}
228462306a36Sopenharmony_ci}
228562306a36Sopenharmony_ci
228662306a36Sopenharmony_ci/**
228762306a36Sopenharmony_ci * ice_parse_vf_func_caps - Parse ICE_AQC_CAPS_VF function caps
228862306a36Sopenharmony_ci * @hw: pointer to the HW struct
228962306a36Sopenharmony_ci * @func_p: pointer to function capabilities structure
229062306a36Sopenharmony_ci * @cap: pointer to the capability element to parse
229162306a36Sopenharmony_ci *
229262306a36Sopenharmony_ci * Extract function capabilities for ICE_AQC_CAPS_VF.
229362306a36Sopenharmony_ci */
229462306a36Sopenharmony_cistatic void
229562306a36Sopenharmony_ciice_parse_vf_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_p,
229662306a36Sopenharmony_ci		       struct ice_aqc_list_caps_elem *cap)
229762306a36Sopenharmony_ci{
229862306a36Sopenharmony_ci	u32 logical_id = le32_to_cpu(cap->logical_id);
229962306a36Sopenharmony_ci	u32 number = le32_to_cpu(cap->number);
230062306a36Sopenharmony_ci
230162306a36Sopenharmony_ci	func_p->num_allocd_vfs = number;
230262306a36Sopenharmony_ci	func_p->vf_base_id = logical_id;
230362306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_INIT, "func caps: num_allocd_vfs = %d\n",
230462306a36Sopenharmony_ci		  func_p->num_allocd_vfs);
230562306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_INIT, "func caps: vf_base_id = %d\n",
230662306a36Sopenharmony_ci		  func_p->vf_base_id);
230762306a36Sopenharmony_ci}
230862306a36Sopenharmony_ci
230962306a36Sopenharmony_ci/**
231062306a36Sopenharmony_ci * ice_parse_vsi_func_caps - Parse ICE_AQC_CAPS_VSI function caps
231162306a36Sopenharmony_ci * @hw: pointer to the HW struct
231262306a36Sopenharmony_ci * @func_p: pointer to function capabilities structure
231362306a36Sopenharmony_ci * @cap: pointer to the capability element to parse
231462306a36Sopenharmony_ci *
231562306a36Sopenharmony_ci * Extract function capabilities for ICE_AQC_CAPS_VSI.
231662306a36Sopenharmony_ci */
231762306a36Sopenharmony_cistatic void
231862306a36Sopenharmony_ciice_parse_vsi_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_p,
231962306a36Sopenharmony_ci			struct ice_aqc_list_caps_elem *cap)
232062306a36Sopenharmony_ci{
232162306a36Sopenharmony_ci	func_p->guar_num_vsi = ice_get_num_per_func(hw, ICE_MAX_VSI);
232262306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_INIT, "func caps: guar_num_vsi (fw) = %d\n",
232362306a36Sopenharmony_ci		  le32_to_cpu(cap->number));
232462306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_INIT, "func caps: guar_num_vsi = %d\n",
232562306a36Sopenharmony_ci		  func_p->guar_num_vsi);
232662306a36Sopenharmony_ci}
232762306a36Sopenharmony_ci
232862306a36Sopenharmony_ci/**
232962306a36Sopenharmony_ci * ice_parse_1588_func_caps - Parse ICE_AQC_CAPS_1588 function caps
233062306a36Sopenharmony_ci * @hw: pointer to the HW struct
233162306a36Sopenharmony_ci * @func_p: pointer to function capabilities structure
233262306a36Sopenharmony_ci * @cap: pointer to the capability element to parse
233362306a36Sopenharmony_ci *
233462306a36Sopenharmony_ci * Extract function capabilities for ICE_AQC_CAPS_1588.
233562306a36Sopenharmony_ci */
233662306a36Sopenharmony_cistatic void
233762306a36Sopenharmony_ciice_parse_1588_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_p,
233862306a36Sopenharmony_ci			 struct ice_aqc_list_caps_elem *cap)
233962306a36Sopenharmony_ci{
234062306a36Sopenharmony_ci	struct ice_ts_func_info *info = &func_p->ts_func_info;
234162306a36Sopenharmony_ci	u32 number = le32_to_cpu(cap->number);
234262306a36Sopenharmony_ci
234362306a36Sopenharmony_ci	info->ena = ((number & ICE_TS_FUNC_ENA_M) != 0);
234462306a36Sopenharmony_ci	func_p->common_cap.ieee_1588 = info->ena;
234562306a36Sopenharmony_ci
234662306a36Sopenharmony_ci	info->src_tmr_owned = ((number & ICE_TS_SRC_TMR_OWND_M) != 0);
234762306a36Sopenharmony_ci	info->tmr_ena = ((number & ICE_TS_TMR_ENA_M) != 0);
234862306a36Sopenharmony_ci	info->tmr_index_owned = ((number & ICE_TS_TMR_IDX_OWND_M) != 0);
234962306a36Sopenharmony_ci	info->tmr_index_assoc = ((number & ICE_TS_TMR_IDX_ASSOC_M) != 0);
235062306a36Sopenharmony_ci
235162306a36Sopenharmony_ci	info->clk_freq = (number & ICE_TS_CLK_FREQ_M) >> ICE_TS_CLK_FREQ_S;
235262306a36Sopenharmony_ci	info->clk_src = ((number & ICE_TS_CLK_SRC_M) != 0);
235362306a36Sopenharmony_ci
235462306a36Sopenharmony_ci	if (info->clk_freq < NUM_ICE_TIME_REF_FREQ) {
235562306a36Sopenharmony_ci		info->time_ref = (enum ice_time_ref_freq)info->clk_freq;
235662306a36Sopenharmony_ci	} else {
235762306a36Sopenharmony_ci		/* Unknown clock frequency, so assume a (probably incorrect)
235862306a36Sopenharmony_ci		 * default to avoid out-of-bounds look ups of frequency
235962306a36Sopenharmony_ci		 * related information.
236062306a36Sopenharmony_ci		 */
236162306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_INIT, "1588 func caps: unknown clock frequency %u\n",
236262306a36Sopenharmony_ci			  info->clk_freq);
236362306a36Sopenharmony_ci		info->time_ref = ICE_TIME_REF_FREQ_25_000;
236462306a36Sopenharmony_ci	}
236562306a36Sopenharmony_ci
236662306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_INIT, "func caps: ieee_1588 = %u\n",
236762306a36Sopenharmony_ci		  func_p->common_cap.ieee_1588);
236862306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_INIT, "func caps: src_tmr_owned = %u\n",
236962306a36Sopenharmony_ci		  info->src_tmr_owned);
237062306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_INIT, "func caps: tmr_ena = %u\n",
237162306a36Sopenharmony_ci		  info->tmr_ena);
237262306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_INIT, "func caps: tmr_index_owned = %u\n",
237362306a36Sopenharmony_ci		  info->tmr_index_owned);
237462306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_INIT, "func caps: tmr_index_assoc = %u\n",
237562306a36Sopenharmony_ci		  info->tmr_index_assoc);
237662306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_INIT, "func caps: clk_freq = %u\n",
237762306a36Sopenharmony_ci		  info->clk_freq);
237862306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_INIT, "func caps: clk_src = %u\n",
237962306a36Sopenharmony_ci		  info->clk_src);
238062306a36Sopenharmony_ci}
238162306a36Sopenharmony_ci
238262306a36Sopenharmony_ci/**
238362306a36Sopenharmony_ci * ice_parse_fdir_func_caps - Parse ICE_AQC_CAPS_FD function caps
238462306a36Sopenharmony_ci * @hw: pointer to the HW struct
238562306a36Sopenharmony_ci * @func_p: pointer to function capabilities structure
238662306a36Sopenharmony_ci *
238762306a36Sopenharmony_ci * Extract function capabilities for ICE_AQC_CAPS_FD.
238862306a36Sopenharmony_ci */
238962306a36Sopenharmony_cistatic void
239062306a36Sopenharmony_ciice_parse_fdir_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_p)
239162306a36Sopenharmony_ci{
239262306a36Sopenharmony_ci	u32 reg_val, val;
239362306a36Sopenharmony_ci
239462306a36Sopenharmony_ci	reg_val = rd32(hw, GLQF_FD_SIZE);
239562306a36Sopenharmony_ci	val = (reg_val & GLQF_FD_SIZE_FD_GSIZE_M) >>
239662306a36Sopenharmony_ci		GLQF_FD_SIZE_FD_GSIZE_S;
239762306a36Sopenharmony_ci	func_p->fd_fltr_guar =
239862306a36Sopenharmony_ci		ice_get_num_per_func(hw, val);
239962306a36Sopenharmony_ci	val = (reg_val & GLQF_FD_SIZE_FD_BSIZE_M) >>
240062306a36Sopenharmony_ci		GLQF_FD_SIZE_FD_BSIZE_S;
240162306a36Sopenharmony_ci	func_p->fd_fltr_best_effort = val;
240262306a36Sopenharmony_ci
240362306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_INIT, "func caps: fd_fltr_guar = %d\n",
240462306a36Sopenharmony_ci		  func_p->fd_fltr_guar);
240562306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_INIT, "func caps: fd_fltr_best_effort = %d\n",
240662306a36Sopenharmony_ci		  func_p->fd_fltr_best_effort);
240762306a36Sopenharmony_ci}
240862306a36Sopenharmony_ci
240962306a36Sopenharmony_ci/**
241062306a36Sopenharmony_ci * ice_parse_func_caps - Parse function capabilities
241162306a36Sopenharmony_ci * @hw: pointer to the HW struct
241262306a36Sopenharmony_ci * @func_p: pointer to function capabilities structure
241362306a36Sopenharmony_ci * @buf: buffer containing the function capability records
241462306a36Sopenharmony_ci * @cap_count: the number of capabilities
241562306a36Sopenharmony_ci *
241662306a36Sopenharmony_ci * Helper function to parse function (0x000A) capabilities list. For
241762306a36Sopenharmony_ci * capabilities shared between device and function, this relies on
241862306a36Sopenharmony_ci * ice_parse_common_caps.
241962306a36Sopenharmony_ci *
242062306a36Sopenharmony_ci * Loop through the list of provided capabilities and extract the relevant
242162306a36Sopenharmony_ci * data into the function capabilities structured.
242262306a36Sopenharmony_ci */
242362306a36Sopenharmony_cistatic void
242462306a36Sopenharmony_ciice_parse_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_p,
242562306a36Sopenharmony_ci		    void *buf, u32 cap_count)
242662306a36Sopenharmony_ci{
242762306a36Sopenharmony_ci	struct ice_aqc_list_caps_elem *cap_resp;
242862306a36Sopenharmony_ci	u32 i;
242962306a36Sopenharmony_ci
243062306a36Sopenharmony_ci	cap_resp = buf;
243162306a36Sopenharmony_ci
243262306a36Sopenharmony_ci	memset(func_p, 0, sizeof(*func_p));
243362306a36Sopenharmony_ci
243462306a36Sopenharmony_ci	for (i = 0; i < cap_count; i++) {
243562306a36Sopenharmony_ci		u16 cap = le16_to_cpu(cap_resp[i].cap);
243662306a36Sopenharmony_ci		bool found;
243762306a36Sopenharmony_ci
243862306a36Sopenharmony_ci		found = ice_parse_common_caps(hw, &func_p->common_cap,
243962306a36Sopenharmony_ci					      &cap_resp[i], "func caps");
244062306a36Sopenharmony_ci
244162306a36Sopenharmony_ci		switch (cap) {
244262306a36Sopenharmony_ci		case ICE_AQC_CAPS_VF:
244362306a36Sopenharmony_ci			ice_parse_vf_func_caps(hw, func_p, &cap_resp[i]);
244462306a36Sopenharmony_ci			break;
244562306a36Sopenharmony_ci		case ICE_AQC_CAPS_VSI:
244662306a36Sopenharmony_ci			ice_parse_vsi_func_caps(hw, func_p, &cap_resp[i]);
244762306a36Sopenharmony_ci			break;
244862306a36Sopenharmony_ci		case ICE_AQC_CAPS_1588:
244962306a36Sopenharmony_ci			ice_parse_1588_func_caps(hw, func_p, &cap_resp[i]);
245062306a36Sopenharmony_ci			break;
245162306a36Sopenharmony_ci		case ICE_AQC_CAPS_FD:
245262306a36Sopenharmony_ci			ice_parse_fdir_func_caps(hw, func_p);
245362306a36Sopenharmony_ci			break;
245462306a36Sopenharmony_ci		default:
245562306a36Sopenharmony_ci			/* Don't list common capabilities as unknown */
245662306a36Sopenharmony_ci			if (!found)
245762306a36Sopenharmony_ci				ice_debug(hw, ICE_DBG_INIT, "func caps: unknown capability[%d]: 0x%x\n",
245862306a36Sopenharmony_ci					  i, cap);
245962306a36Sopenharmony_ci			break;
246062306a36Sopenharmony_ci		}
246162306a36Sopenharmony_ci	}
246262306a36Sopenharmony_ci
246362306a36Sopenharmony_ci	ice_recalc_port_limited_caps(hw, &func_p->common_cap);
246462306a36Sopenharmony_ci}
246562306a36Sopenharmony_ci
246662306a36Sopenharmony_ci/**
246762306a36Sopenharmony_ci * ice_parse_valid_functions_cap - Parse ICE_AQC_CAPS_VALID_FUNCTIONS caps
246862306a36Sopenharmony_ci * @hw: pointer to the HW struct
246962306a36Sopenharmony_ci * @dev_p: pointer to device capabilities structure
247062306a36Sopenharmony_ci * @cap: capability element to parse
247162306a36Sopenharmony_ci *
247262306a36Sopenharmony_ci * Parse ICE_AQC_CAPS_VALID_FUNCTIONS for device capabilities.
247362306a36Sopenharmony_ci */
247462306a36Sopenharmony_cistatic void
247562306a36Sopenharmony_ciice_parse_valid_functions_cap(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
247662306a36Sopenharmony_ci			      struct ice_aqc_list_caps_elem *cap)
247762306a36Sopenharmony_ci{
247862306a36Sopenharmony_ci	u32 number = le32_to_cpu(cap->number);
247962306a36Sopenharmony_ci
248062306a36Sopenharmony_ci	dev_p->num_funcs = hweight32(number);
248162306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_INIT, "dev caps: num_funcs = %d\n",
248262306a36Sopenharmony_ci		  dev_p->num_funcs);
248362306a36Sopenharmony_ci}
248462306a36Sopenharmony_ci
248562306a36Sopenharmony_ci/**
248662306a36Sopenharmony_ci * ice_parse_vf_dev_caps - Parse ICE_AQC_CAPS_VF device caps
248762306a36Sopenharmony_ci * @hw: pointer to the HW struct
248862306a36Sopenharmony_ci * @dev_p: pointer to device capabilities structure
248962306a36Sopenharmony_ci * @cap: capability element to parse
249062306a36Sopenharmony_ci *
249162306a36Sopenharmony_ci * Parse ICE_AQC_CAPS_VF for device capabilities.
249262306a36Sopenharmony_ci */
249362306a36Sopenharmony_cistatic void
249462306a36Sopenharmony_ciice_parse_vf_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
249562306a36Sopenharmony_ci		      struct ice_aqc_list_caps_elem *cap)
249662306a36Sopenharmony_ci{
249762306a36Sopenharmony_ci	u32 number = le32_to_cpu(cap->number);
249862306a36Sopenharmony_ci
249962306a36Sopenharmony_ci	dev_p->num_vfs_exposed = number;
250062306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_INIT, "dev_caps: num_vfs_exposed = %d\n",
250162306a36Sopenharmony_ci		  dev_p->num_vfs_exposed);
250262306a36Sopenharmony_ci}
250362306a36Sopenharmony_ci
250462306a36Sopenharmony_ci/**
250562306a36Sopenharmony_ci * ice_parse_vsi_dev_caps - Parse ICE_AQC_CAPS_VSI device caps
250662306a36Sopenharmony_ci * @hw: pointer to the HW struct
250762306a36Sopenharmony_ci * @dev_p: pointer to device capabilities structure
250862306a36Sopenharmony_ci * @cap: capability element to parse
250962306a36Sopenharmony_ci *
251062306a36Sopenharmony_ci * Parse ICE_AQC_CAPS_VSI for device capabilities.
251162306a36Sopenharmony_ci */
251262306a36Sopenharmony_cistatic void
251362306a36Sopenharmony_ciice_parse_vsi_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
251462306a36Sopenharmony_ci		       struct ice_aqc_list_caps_elem *cap)
251562306a36Sopenharmony_ci{
251662306a36Sopenharmony_ci	u32 number = le32_to_cpu(cap->number);
251762306a36Sopenharmony_ci
251862306a36Sopenharmony_ci	dev_p->num_vsi_allocd_to_host = number;
251962306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_INIT, "dev caps: num_vsi_allocd_to_host = %d\n",
252062306a36Sopenharmony_ci		  dev_p->num_vsi_allocd_to_host);
252162306a36Sopenharmony_ci}
252262306a36Sopenharmony_ci
252362306a36Sopenharmony_ci/**
252462306a36Sopenharmony_ci * ice_parse_1588_dev_caps - Parse ICE_AQC_CAPS_1588 device caps
252562306a36Sopenharmony_ci * @hw: pointer to the HW struct
252662306a36Sopenharmony_ci * @dev_p: pointer to device capabilities structure
252762306a36Sopenharmony_ci * @cap: capability element to parse
252862306a36Sopenharmony_ci *
252962306a36Sopenharmony_ci * Parse ICE_AQC_CAPS_1588 for device capabilities.
253062306a36Sopenharmony_ci */
253162306a36Sopenharmony_cistatic void
253262306a36Sopenharmony_ciice_parse_1588_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
253362306a36Sopenharmony_ci			struct ice_aqc_list_caps_elem *cap)
253462306a36Sopenharmony_ci{
253562306a36Sopenharmony_ci	struct ice_ts_dev_info *info = &dev_p->ts_dev_info;
253662306a36Sopenharmony_ci	u32 logical_id = le32_to_cpu(cap->logical_id);
253762306a36Sopenharmony_ci	u32 phys_id = le32_to_cpu(cap->phys_id);
253862306a36Sopenharmony_ci	u32 number = le32_to_cpu(cap->number);
253962306a36Sopenharmony_ci
254062306a36Sopenharmony_ci	info->ena = ((number & ICE_TS_DEV_ENA_M) != 0);
254162306a36Sopenharmony_ci	dev_p->common_cap.ieee_1588 = info->ena;
254262306a36Sopenharmony_ci
254362306a36Sopenharmony_ci	info->tmr0_owner = number & ICE_TS_TMR0_OWNR_M;
254462306a36Sopenharmony_ci	info->tmr0_owned = ((number & ICE_TS_TMR0_OWND_M) != 0);
254562306a36Sopenharmony_ci	info->tmr0_ena = ((number & ICE_TS_TMR0_ENA_M) != 0);
254662306a36Sopenharmony_ci
254762306a36Sopenharmony_ci	info->tmr1_owner = (number & ICE_TS_TMR1_OWNR_M) >> ICE_TS_TMR1_OWNR_S;
254862306a36Sopenharmony_ci	info->tmr1_owned = ((number & ICE_TS_TMR1_OWND_M) != 0);
254962306a36Sopenharmony_ci	info->tmr1_ena = ((number & ICE_TS_TMR1_ENA_M) != 0);
255062306a36Sopenharmony_ci
255162306a36Sopenharmony_ci	info->ts_ll_read = ((number & ICE_TS_LL_TX_TS_READ_M) != 0);
255262306a36Sopenharmony_ci
255362306a36Sopenharmony_ci	info->ena_ports = logical_id;
255462306a36Sopenharmony_ci	info->tmr_own_map = phys_id;
255562306a36Sopenharmony_ci
255662306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_INIT, "dev caps: ieee_1588 = %u\n",
255762306a36Sopenharmony_ci		  dev_p->common_cap.ieee_1588);
255862306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_INIT, "dev caps: tmr0_owner = %u\n",
255962306a36Sopenharmony_ci		  info->tmr0_owner);
256062306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_INIT, "dev caps: tmr0_owned = %u\n",
256162306a36Sopenharmony_ci		  info->tmr0_owned);
256262306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_INIT, "dev caps: tmr0_ena = %u\n",
256362306a36Sopenharmony_ci		  info->tmr0_ena);
256462306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_INIT, "dev caps: tmr1_owner = %u\n",
256562306a36Sopenharmony_ci		  info->tmr1_owner);
256662306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_INIT, "dev caps: tmr1_owned = %u\n",
256762306a36Sopenharmony_ci		  info->tmr1_owned);
256862306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_INIT, "dev caps: tmr1_ena = %u\n",
256962306a36Sopenharmony_ci		  info->tmr1_ena);
257062306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_INIT, "dev caps: ts_ll_read = %u\n",
257162306a36Sopenharmony_ci		  info->ts_ll_read);
257262306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_INIT, "dev caps: ieee_1588 ena_ports = %u\n",
257362306a36Sopenharmony_ci		  info->ena_ports);
257462306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_INIT, "dev caps: tmr_own_map = %u\n",
257562306a36Sopenharmony_ci		  info->tmr_own_map);
257662306a36Sopenharmony_ci}
257762306a36Sopenharmony_ci
257862306a36Sopenharmony_ci/**
257962306a36Sopenharmony_ci * ice_parse_fdir_dev_caps - Parse ICE_AQC_CAPS_FD device caps
258062306a36Sopenharmony_ci * @hw: pointer to the HW struct
258162306a36Sopenharmony_ci * @dev_p: pointer to device capabilities structure
258262306a36Sopenharmony_ci * @cap: capability element to parse
258362306a36Sopenharmony_ci *
258462306a36Sopenharmony_ci * Parse ICE_AQC_CAPS_FD for device capabilities.
258562306a36Sopenharmony_ci */
258662306a36Sopenharmony_cistatic void
258762306a36Sopenharmony_ciice_parse_fdir_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
258862306a36Sopenharmony_ci			struct ice_aqc_list_caps_elem *cap)
258962306a36Sopenharmony_ci{
259062306a36Sopenharmony_ci	u32 number = le32_to_cpu(cap->number);
259162306a36Sopenharmony_ci
259262306a36Sopenharmony_ci	dev_p->num_flow_director_fltr = number;
259362306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_INIT, "dev caps: num_flow_director_fltr = %d\n",
259462306a36Sopenharmony_ci		  dev_p->num_flow_director_fltr);
259562306a36Sopenharmony_ci}
259662306a36Sopenharmony_ci
259762306a36Sopenharmony_ci/**
259862306a36Sopenharmony_ci * ice_parse_dev_caps - Parse device capabilities
259962306a36Sopenharmony_ci * @hw: pointer to the HW struct
260062306a36Sopenharmony_ci * @dev_p: pointer to device capabilities structure
260162306a36Sopenharmony_ci * @buf: buffer containing the device capability records
260262306a36Sopenharmony_ci * @cap_count: the number of capabilities
260362306a36Sopenharmony_ci *
260462306a36Sopenharmony_ci * Helper device to parse device (0x000B) capabilities list. For
260562306a36Sopenharmony_ci * capabilities shared between device and function, this relies on
260662306a36Sopenharmony_ci * ice_parse_common_caps.
260762306a36Sopenharmony_ci *
260862306a36Sopenharmony_ci * Loop through the list of provided capabilities and extract the relevant
260962306a36Sopenharmony_ci * data into the device capabilities structured.
261062306a36Sopenharmony_ci */
261162306a36Sopenharmony_cistatic void
261262306a36Sopenharmony_ciice_parse_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
261362306a36Sopenharmony_ci		   void *buf, u32 cap_count)
261462306a36Sopenharmony_ci{
261562306a36Sopenharmony_ci	struct ice_aqc_list_caps_elem *cap_resp;
261662306a36Sopenharmony_ci	u32 i;
261762306a36Sopenharmony_ci
261862306a36Sopenharmony_ci	cap_resp = buf;
261962306a36Sopenharmony_ci
262062306a36Sopenharmony_ci	memset(dev_p, 0, sizeof(*dev_p));
262162306a36Sopenharmony_ci
262262306a36Sopenharmony_ci	for (i = 0; i < cap_count; i++) {
262362306a36Sopenharmony_ci		u16 cap = le16_to_cpu(cap_resp[i].cap);
262462306a36Sopenharmony_ci		bool found;
262562306a36Sopenharmony_ci
262662306a36Sopenharmony_ci		found = ice_parse_common_caps(hw, &dev_p->common_cap,
262762306a36Sopenharmony_ci					      &cap_resp[i], "dev caps");
262862306a36Sopenharmony_ci
262962306a36Sopenharmony_ci		switch (cap) {
263062306a36Sopenharmony_ci		case ICE_AQC_CAPS_VALID_FUNCTIONS:
263162306a36Sopenharmony_ci			ice_parse_valid_functions_cap(hw, dev_p, &cap_resp[i]);
263262306a36Sopenharmony_ci			break;
263362306a36Sopenharmony_ci		case ICE_AQC_CAPS_VF:
263462306a36Sopenharmony_ci			ice_parse_vf_dev_caps(hw, dev_p, &cap_resp[i]);
263562306a36Sopenharmony_ci			break;
263662306a36Sopenharmony_ci		case ICE_AQC_CAPS_VSI:
263762306a36Sopenharmony_ci			ice_parse_vsi_dev_caps(hw, dev_p, &cap_resp[i]);
263862306a36Sopenharmony_ci			break;
263962306a36Sopenharmony_ci		case ICE_AQC_CAPS_1588:
264062306a36Sopenharmony_ci			ice_parse_1588_dev_caps(hw, dev_p, &cap_resp[i]);
264162306a36Sopenharmony_ci			break;
264262306a36Sopenharmony_ci		case  ICE_AQC_CAPS_FD:
264362306a36Sopenharmony_ci			ice_parse_fdir_dev_caps(hw, dev_p, &cap_resp[i]);
264462306a36Sopenharmony_ci			break;
264562306a36Sopenharmony_ci		default:
264662306a36Sopenharmony_ci			/* Don't list common capabilities as unknown */
264762306a36Sopenharmony_ci			if (!found)
264862306a36Sopenharmony_ci				ice_debug(hw, ICE_DBG_INIT, "dev caps: unknown capability[%d]: 0x%x\n",
264962306a36Sopenharmony_ci					  i, cap);
265062306a36Sopenharmony_ci			break;
265162306a36Sopenharmony_ci		}
265262306a36Sopenharmony_ci	}
265362306a36Sopenharmony_ci
265462306a36Sopenharmony_ci	ice_recalc_port_limited_caps(hw, &dev_p->common_cap);
265562306a36Sopenharmony_ci}
265662306a36Sopenharmony_ci
265762306a36Sopenharmony_ci/**
265862306a36Sopenharmony_ci * ice_aq_get_netlist_node
265962306a36Sopenharmony_ci * @hw: pointer to the hw struct
266062306a36Sopenharmony_ci * @cmd: get_link_topo AQ structure
266162306a36Sopenharmony_ci * @node_part_number: output node part number if node found
266262306a36Sopenharmony_ci * @node_handle: output node handle parameter if node found
266362306a36Sopenharmony_ci */
266462306a36Sopenharmony_cistatic int
266562306a36Sopenharmony_ciice_aq_get_netlist_node(struct ice_hw *hw, struct ice_aqc_get_link_topo *cmd,
266662306a36Sopenharmony_ci			u8 *node_part_number, u16 *node_handle)
266762306a36Sopenharmony_ci{
266862306a36Sopenharmony_ci	struct ice_aq_desc desc;
266962306a36Sopenharmony_ci
267062306a36Sopenharmony_ci	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_link_topo);
267162306a36Sopenharmony_ci	desc.params.get_link_topo = *cmd;
267262306a36Sopenharmony_ci
267362306a36Sopenharmony_ci	if (ice_aq_send_cmd(hw, &desc, NULL, 0, NULL))
267462306a36Sopenharmony_ci		return -EIO;
267562306a36Sopenharmony_ci
267662306a36Sopenharmony_ci	if (node_handle)
267762306a36Sopenharmony_ci		*node_handle = le16_to_cpu(desc.params.get_link_topo.addr.handle);
267862306a36Sopenharmony_ci	if (node_part_number)
267962306a36Sopenharmony_ci		*node_part_number = desc.params.get_link_topo.node_part_num;
268062306a36Sopenharmony_ci
268162306a36Sopenharmony_ci	return 0;
268262306a36Sopenharmony_ci}
268362306a36Sopenharmony_ci
268462306a36Sopenharmony_ci/**
268562306a36Sopenharmony_ci * ice_is_pf_c827 - check if pf contains c827 phy
268662306a36Sopenharmony_ci * @hw: pointer to the hw struct
268762306a36Sopenharmony_ci */
268862306a36Sopenharmony_cibool ice_is_pf_c827(struct ice_hw *hw)
268962306a36Sopenharmony_ci{
269062306a36Sopenharmony_ci	struct ice_aqc_get_link_topo cmd = {};
269162306a36Sopenharmony_ci	u8 node_part_number;
269262306a36Sopenharmony_ci	u16 node_handle;
269362306a36Sopenharmony_ci	int status;
269462306a36Sopenharmony_ci
269562306a36Sopenharmony_ci	if (hw->mac_type != ICE_MAC_E810)
269662306a36Sopenharmony_ci		return false;
269762306a36Sopenharmony_ci
269862306a36Sopenharmony_ci	if (hw->device_id != ICE_DEV_ID_E810C_QSFP)
269962306a36Sopenharmony_ci		return true;
270062306a36Sopenharmony_ci
270162306a36Sopenharmony_ci	cmd.addr.topo_params.node_type_ctx =
270262306a36Sopenharmony_ci		FIELD_PREP(ICE_AQC_LINK_TOPO_NODE_TYPE_M, ICE_AQC_LINK_TOPO_NODE_TYPE_PHY) |
270362306a36Sopenharmony_ci		FIELD_PREP(ICE_AQC_LINK_TOPO_NODE_CTX_M, ICE_AQC_LINK_TOPO_NODE_CTX_PORT);
270462306a36Sopenharmony_ci	cmd.addr.topo_params.index = 0;
270562306a36Sopenharmony_ci
270662306a36Sopenharmony_ci	status = ice_aq_get_netlist_node(hw, &cmd, &node_part_number,
270762306a36Sopenharmony_ci					 &node_handle);
270862306a36Sopenharmony_ci
270962306a36Sopenharmony_ci	if (status || node_part_number != ICE_AQC_GET_LINK_TOPO_NODE_NR_C827)
271062306a36Sopenharmony_ci		return false;
271162306a36Sopenharmony_ci
271262306a36Sopenharmony_ci	if (node_handle == E810C_QSFP_C827_0_HANDLE || node_handle == E810C_QSFP_C827_1_HANDLE)
271362306a36Sopenharmony_ci		return true;
271462306a36Sopenharmony_ci
271562306a36Sopenharmony_ci	return false;
271662306a36Sopenharmony_ci}
271762306a36Sopenharmony_ci
271862306a36Sopenharmony_ci/**
271962306a36Sopenharmony_ci * ice_aq_list_caps - query function/device capabilities
272062306a36Sopenharmony_ci * @hw: pointer to the HW struct
272162306a36Sopenharmony_ci * @buf: a buffer to hold the capabilities
272262306a36Sopenharmony_ci * @buf_size: size of the buffer
272362306a36Sopenharmony_ci * @cap_count: if not NULL, set to the number of capabilities reported
272462306a36Sopenharmony_ci * @opc: capabilities type to discover, device or function
272562306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL
272662306a36Sopenharmony_ci *
272762306a36Sopenharmony_ci * Get the function (0x000A) or device (0x000B) capabilities description from
272862306a36Sopenharmony_ci * firmware and store it in the buffer.
272962306a36Sopenharmony_ci *
273062306a36Sopenharmony_ci * If the cap_count pointer is not NULL, then it is set to the number of
273162306a36Sopenharmony_ci * capabilities firmware will report. Note that if the buffer size is too
273262306a36Sopenharmony_ci * small, it is possible the command will return ICE_AQ_ERR_ENOMEM. The
273362306a36Sopenharmony_ci * cap_count will still be updated in this case. It is recommended that the
273462306a36Sopenharmony_ci * buffer size be set to ICE_AQ_MAX_BUF_LEN (the largest possible buffer that
273562306a36Sopenharmony_ci * firmware could return) to avoid this.
273662306a36Sopenharmony_ci */
273762306a36Sopenharmony_ciint
273862306a36Sopenharmony_ciice_aq_list_caps(struct ice_hw *hw, void *buf, u16 buf_size, u32 *cap_count,
273962306a36Sopenharmony_ci		 enum ice_adminq_opc opc, struct ice_sq_cd *cd)
274062306a36Sopenharmony_ci{
274162306a36Sopenharmony_ci	struct ice_aqc_list_caps *cmd;
274262306a36Sopenharmony_ci	struct ice_aq_desc desc;
274362306a36Sopenharmony_ci	int status;
274462306a36Sopenharmony_ci
274562306a36Sopenharmony_ci	cmd = &desc.params.get_cap;
274662306a36Sopenharmony_ci
274762306a36Sopenharmony_ci	if (opc != ice_aqc_opc_list_func_caps &&
274862306a36Sopenharmony_ci	    opc != ice_aqc_opc_list_dev_caps)
274962306a36Sopenharmony_ci		return -EINVAL;
275062306a36Sopenharmony_ci
275162306a36Sopenharmony_ci	ice_fill_dflt_direct_cmd_desc(&desc, opc);
275262306a36Sopenharmony_ci	status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
275362306a36Sopenharmony_ci
275462306a36Sopenharmony_ci	if (cap_count)
275562306a36Sopenharmony_ci		*cap_count = le32_to_cpu(cmd->count);
275662306a36Sopenharmony_ci
275762306a36Sopenharmony_ci	return status;
275862306a36Sopenharmony_ci}
275962306a36Sopenharmony_ci
276062306a36Sopenharmony_ci/**
276162306a36Sopenharmony_ci * ice_discover_dev_caps - Read and extract device capabilities
276262306a36Sopenharmony_ci * @hw: pointer to the hardware structure
276362306a36Sopenharmony_ci * @dev_caps: pointer to device capabilities structure
276462306a36Sopenharmony_ci *
276562306a36Sopenharmony_ci * Read the device capabilities and extract them into the dev_caps structure
276662306a36Sopenharmony_ci * for later use.
276762306a36Sopenharmony_ci */
276862306a36Sopenharmony_ciint
276962306a36Sopenharmony_ciice_discover_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_caps)
277062306a36Sopenharmony_ci{
277162306a36Sopenharmony_ci	u32 cap_count = 0;
277262306a36Sopenharmony_ci	void *cbuf;
277362306a36Sopenharmony_ci	int status;
277462306a36Sopenharmony_ci
277562306a36Sopenharmony_ci	cbuf = kzalloc(ICE_AQ_MAX_BUF_LEN, GFP_KERNEL);
277662306a36Sopenharmony_ci	if (!cbuf)
277762306a36Sopenharmony_ci		return -ENOMEM;
277862306a36Sopenharmony_ci
277962306a36Sopenharmony_ci	/* Although the driver doesn't know the number of capabilities the
278062306a36Sopenharmony_ci	 * device will return, we can simply send a 4KB buffer, the maximum
278162306a36Sopenharmony_ci	 * possible size that firmware can return.
278262306a36Sopenharmony_ci	 */
278362306a36Sopenharmony_ci	cap_count = ICE_AQ_MAX_BUF_LEN / sizeof(struct ice_aqc_list_caps_elem);
278462306a36Sopenharmony_ci
278562306a36Sopenharmony_ci	status = ice_aq_list_caps(hw, cbuf, ICE_AQ_MAX_BUF_LEN, &cap_count,
278662306a36Sopenharmony_ci				  ice_aqc_opc_list_dev_caps, NULL);
278762306a36Sopenharmony_ci	if (!status)
278862306a36Sopenharmony_ci		ice_parse_dev_caps(hw, dev_caps, cbuf, cap_count);
278962306a36Sopenharmony_ci	kfree(cbuf);
279062306a36Sopenharmony_ci
279162306a36Sopenharmony_ci	return status;
279262306a36Sopenharmony_ci}
279362306a36Sopenharmony_ci
279462306a36Sopenharmony_ci/**
279562306a36Sopenharmony_ci * ice_discover_func_caps - Read and extract function capabilities
279662306a36Sopenharmony_ci * @hw: pointer to the hardware structure
279762306a36Sopenharmony_ci * @func_caps: pointer to function capabilities structure
279862306a36Sopenharmony_ci *
279962306a36Sopenharmony_ci * Read the function capabilities and extract them into the func_caps structure
280062306a36Sopenharmony_ci * for later use.
280162306a36Sopenharmony_ci */
280262306a36Sopenharmony_cistatic int
280362306a36Sopenharmony_ciice_discover_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_caps)
280462306a36Sopenharmony_ci{
280562306a36Sopenharmony_ci	u32 cap_count = 0;
280662306a36Sopenharmony_ci	void *cbuf;
280762306a36Sopenharmony_ci	int status;
280862306a36Sopenharmony_ci
280962306a36Sopenharmony_ci	cbuf = kzalloc(ICE_AQ_MAX_BUF_LEN, GFP_KERNEL);
281062306a36Sopenharmony_ci	if (!cbuf)
281162306a36Sopenharmony_ci		return -ENOMEM;
281262306a36Sopenharmony_ci
281362306a36Sopenharmony_ci	/* Although the driver doesn't know the number of capabilities the
281462306a36Sopenharmony_ci	 * device will return, we can simply send a 4KB buffer, the maximum
281562306a36Sopenharmony_ci	 * possible size that firmware can return.
281662306a36Sopenharmony_ci	 */
281762306a36Sopenharmony_ci	cap_count = ICE_AQ_MAX_BUF_LEN / sizeof(struct ice_aqc_list_caps_elem);
281862306a36Sopenharmony_ci
281962306a36Sopenharmony_ci	status = ice_aq_list_caps(hw, cbuf, ICE_AQ_MAX_BUF_LEN, &cap_count,
282062306a36Sopenharmony_ci				  ice_aqc_opc_list_func_caps, NULL);
282162306a36Sopenharmony_ci	if (!status)
282262306a36Sopenharmony_ci		ice_parse_func_caps(hw, func_caps, cbuf, cap_count);
282362306a36Sopenharmony_ci	kfree(cbuf);
282462306a36Sopenharmony_ci
282562306a36Sopenharmony_ci	return status;
282662306a36Sopenharmony_ci}
282762306a36Sopenharmony_ci
282862306a36Sopenharmony_ci/**
282962306a36Sopenharmony_ci * ice_set_safe_mode_caps - Override dev/func capabilities when in safe mode
283062306a36Sopenharmony_ci * @hw: pointer to the hardware structure
283162306a36Sopenharmony_ci */
283262306a36Sopenharmony_civoid ice_set_safe_mode_caps(struct ice_hw *hw)
283362306a36Sopenharmony_ci{
283462306a36Sopenharmony_ci	struct ice_hw_func_caps *func_caps = &hw->func_caps;
283562306a36Sopenharmony_ci	struct ice_hw_dev_caps *dev_caps = &hw->dev_caps;
283662306a36Sopenharmony_ci	struct ice_hw_common_caps cached_caps;
283762306a36Sopenharmony_ci	u32 num_funcs;
283862306a36Sopenharmony_ci
283962306a36Sopenharmony_ci	/* cache some func_caps values that should be restored after memset */
284062306a36Sopenharmony_ci	cached_caps = func_caps->common_cap;
284162306a36Sopenharmony_ci
284262306a36Sopenharmony_ci	/* unset func capabilities */
284362306a36Sopenharmony_ci	memset(func_caps, 0, sizeof(*func_caps));
284462306a36Sopenharmony_ci
284562306a36Sopenharmony_ci#define ICE_RESTORE_FUNC_CAP(name) \
284662306a36Sopenharmony_ci	func_caps->common_cap.name = cached_caps.name
284762306a36Sopenharmony_ci
284862306a36Sopenharmony_ci	/* restore cached values */
284962306a36Sopenharmony_ci	ICE_RESTORE_FUNC_CAP(valid_functions);
285062306a36Sopenharmony_ci	ICE_RESTORE_FUNC_CAP(txq_first_id);
285162306a36Sopenharmony_ci	ICE_RESTORE_FUNC_CAP(rxq_first_id);
285262306a36Sopenharmony_ci	ICE_RESTORE_FUNC_CAP(msix_vector_first_id);
285362306a36Sopenharmony_ci	ICE_RESTORE_FUNC_CAP(max_mtu);
285462306a36Sopenharmony_ci	ICE_RESTORE_FUNC_CAP(nvm_unified_update);
285562306a36Sopenharmony_ci	ICE_RESTORE_FUNC_CAP(nvm_update_pending_nvm);
285662306a36Sopenharmony_ci	ICE_RESTORE_FUNC_CAP(nvm_update_pending_orom);
285762306a36Sopenharmony_ci	ICE_RESTORE_FUNC_CAP(nvm_update_pending_netlist);
285862306a36Sopenharmony_ci
285962306a36Sopenharmony_ci	/* one Tx and one Rx queue in safe mode */
286062306a36Sopenharmony_ci	func_caps->common_cap.num_rxq = 1;
286162306a36Sopenharmony_ci	func_caps->common_cap.num_txq = 1;
286262306a36Sopenharmony_ci
286362306a36Sopenharmony_ci	/* two MSIX vectors, one for traffic and one for misc causes */
286462306a36Sopenharmony_ci	func_caps->common_cap.num_msix_vectors = 2;
286562306a36Sopenharmony_ci	func_caps->guar_num_vsi = 1;
286662306a36Sopenharmony_ci
286762306a36Sopenharmony_ci	/* cache some dev_caps values that should be restored after memset */
286862306a36Sopenharmony_ci	cached_caps = dev_caps->common_cap;
286962306a36Sopenharmony_ci	num_funcs = dev_caps->num_funcs;
287062306a36Sopenharmony_ci
287162306a36Sopenharmony_ci	/* unset dev capabilities */
287262306a36Sopenharmony_ci	memset(dev_caps, 0, sizeof(*dev_caps));
287362306a36Sopenharmony_ci
287462306a36Sopenharmony_ci#define ICE_RESTORE_DEV_CAP(name) \
287562306a36Sopenharmony_ci	dev_caps->common_cap.name = cached_caps.name
287662306a36Sopenharmony_ci
287762306a36Sopenharmony_ci	/* restore cached values */
287862306a36Sopenharmony_ci	ICE_RESTORE_DEV_CAP(valid_functions);
287962306a36Sopenharmony_ci	ICE_RESTORE_DEV_CAP(txq_first_id);
288062306a36Sopenharmony_ci	ICE_RESTORE_DEV_CAP(rxq_first_id);
288162306a36Sopenharmony_ci	ICE_RESTORE_DEV_CAP(msix_vector_first_id);
288262306a36Sopenharmony_ci	ICE_RESTORE_DEV_CAP(max_mtu);
288362306a36Sopenharmony_ci	ICE_RESTORE_DEV_CAP(nvm_unified_update);
288462306a36Sopenharmony_ci	ICE_RESTORE_DEV_CAP(nvm_update_pending_nvm);
288562306a36Sopenharmony_ci	ICE_RESTORE_DEV_CAP(nvm_update_pending_orom);
288662306a36Sopenharmony_ci	ICE_RESTORE_DEV_CAP(nvm_update_pending_netlist);
288762306a36Sopenharmony_ci	dev_caps->num_funcs = num_funcs;
288862306a36Sopenharmony_ci
288962306a36Sopenharmony_ci	/* one Tx and one Rx queue per function in safe mode */
289062306a36Sopenharmony_ci	dev_caps->common_cap.num_rxq = num_funcs;
289162306a36Sopenharmony_ci	dev_caps->common_cap.num_txq = num_funcs;
289262306a36Sopenharmony_ci
289362306a36Sopenharmony_ci	/* two MSIX vectors per function */
289462306a36Sopenharmony_ci	dev_caps->common_cap.num_msix_vectors = 2 * num_funcs;
289562306a36Sopenharmony_ci}
289662306a36Sopenharmony_ci
289762306a36Sopenharmony_ci/**
289862306a36Sopenharmony_ci * ice_get_caps - get info about the HW
289962306a36Sopenharmony_ci * @hw: pointer to the hardware structure
290062306a36Sopenharmony_ci */
290162306a36Sopenharmony_ciint ice_get_caps(struct ice_hw *hw)
290262306a36Sopenharmony_ci{
290362306a36Sopenharmony_ci	int status;
290462306a36Sopenharmony_ci
290562306a36Sopenharmony_ci	status = ice_discover_dev_caps(hw, &hw->dev_caps);
290662306a36Sopenharmony_ci	if (status)
290762306a36Sopenharmony_ci		return status;
290862306a36Sopenharmony_ci
290962306a36Sopenharmony_ci	return ice_discover_func_caps(hw, &hw->func_caps);
291062306a36Sopenharmony_ci}
291162306a36Sopenharmony_ci
291262306a36Sopenharmony_ci/**
291362306a36Sopenharmony_ci * ice_aq_manage_mac_write - manage MAC address write command
291462306a36Sopenharmony_ci * @hw: pointer to the HW struct
291562306a36Sopenharmony_ci * @mac_addr: MAC address to be written as LAA/LAA+WoL/Port address
291662306a36Sopenharmony_ci * @flags: flags to control write behavior
291762306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL
291862306a36Sopenharmony_ci *
291962306a36Sopenharmony_ci * This function is used to write MAC address to the NVM (0x0108).
292062306a36Sopenharmony_ci */
292162306a36Sopenharmony_ciint
292262306a36Sopenharmony_ciice_aq_manage_mac_write(struct ice_hw *hw, const u8 *mac_addr, u8 flags,
292362306a36Sopenharmony_ci			struct ice_sq_cd *cd)
292462306a36Sopenharmony_ci{
292562306a36Sopenharmony_ci	struct ice_aqc_manage_mac_write *cmd;
292662306a36Sopenharmony_ci	struct ice_aq_desc desc;
292762306a36Sopenharmony_ci
292862306a36Sopenharmony_ci	cmd = &desc.params.mac_write;
292962306a36Sopenharmony_ci	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_manage_mac_write);
293062306a36Sopenharmony_ci
293162306a36Sopenharmony_ci	cmd->flags = flags;
293262306a36Sopenharmony_ci	ether_addr_copy(cmd->mac_addr, mac_addr);
293362306a36Sopenharmony_ci
293462306a36Sopenharmony_ci	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
293562306a36Sopenharmony_ci}
293662306a36Sopenharmony_ci
293762306a36Sopenharmony_ci/**
293862306a36Sopenharmony_ci * ice_aq_clear_pxe_mode
293962306a36Sopenharmony_ci * @hw: pointer to the HW struct
294062306a36Sopenharmony_ci *
294162306a36Sopenharmony_ci * Tell the firmware that the driver is taking over from PXE (0x0110).
294262306a36Sopenharmony_ci */
294362306a36Sopenharmony_cistatic int ice_aq_clear_pxe_mode(struct ice_hw *hw)
294462306a36Sopenharmony_ci{
294562306a36Sopenharmony_ci	struct ice_aq_desc desc;
294662306a36Sopenharmony_ci
294762306a36Sopenharmony_ci	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_clear_pxe_mode);
294862306a36Sopenharmony_ci	desc.params.clear_pxe.rx_cnt = ICE_AQC_CLEAR_PXE_RX_CNT;
294962306a36Sopenharmony_ci
295062306a36Sopenharmony_ci	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
295162306a36Sopenharmony_ci}
295262306a36Sopenharmony_ci
295362306a36Sopenharmony_ci/**
295462306a36Sopenharmony_ci * ice_clear_pxe_mode - clear pxe operations mode
295562306a36Sopenharmony_ci * @hw: pointer to the HW struct
295662306a36Sopenharmony_ci *
295762306a36Sopenharmony_ci * Make sure all PXE mode settings are cleared, including things
295862306a36Sopenharmony_ci * like descriptor fetch/write-back mode.
295962306a36Sopenharmony_ci */
296062306a36Sopenharmony_civoid ice_clear_pxe_mode(struct ice_hw *hw)
296162306a36Sopenharmony_ci{
296262306a36Sopenharmony_ci	if (ice_check_sq_alive(hw, &hw->adminq))
296362306a36Sopenharmony_ci		ice_aq_clear_pxe_mode(hw);
296462306a36Sopenharmony_ci}
296562306a36Sopenharmony_ci
296662306a36Sopenharmony_ci/**
296762306a36Sopenharmony_ci * ice_aq_set_port_params - set physical port parameters.
296862306a36Sopenharmony_ci * @pi: pointer to the port info struct
296962306a36Sopenharmony_ci * @double_vlan: if set double VLAN is enabled
297062306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL
297162306a36Sopenharmony_ci *
297262306a36Sopenharmony_ci * Set Physical port parameters (0x0203)
297362306a36Sopenharmony_ci */
297462306a36Sopenharmony_ciint
297562306a36Sopenharmony_ciice_aq_set_port_params(struct ice_port_info *pi, bool double_vlan,
297662306a36Sopenharmony_ci		       struct ice_sq_cd *cd)
297762306a36Sopenharmony_ci
297862306a36Sopenharmony_ci{
297962306a36Sopenharmony_ci	struct ice_aqc_set_port_params *cmd;
298062306a36Sopenharmony_ci	struct ice_hw *hw = pi->hw;
298162306a36Sopenharmony_ci	struct ice_aq_desc desc;
298262306a36Sopenharmony_ci	u16 cmd_flags = 0;
298362306a36Sopenharmony_ci
298462306a36Sopenharmony_ci	cmd = &desc.params.set_port_params;
298562306a36Sopenharmony_ci
298662306a36Sopenharmony_ci	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_port_params);
298762306a36Sopenharmony_ci	if (double_vlan)
298862306a36Sopenharmony_ci		cmd_flags |= ICE_AQC_SET_P_PARAMS_DOUBLE_VLAN_ENA;
298962306a36Sopenharmony_ci	cmd->cmd_flags = cpu_to_le16(cmd_flags);
299062306a36Sopenharmony_ci
299162306a36Sopenharmony_ci	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
299262306a36Sopenharmony_ci}
299362306a36Sopenharmony_ci
299462306a36Sopenharmony_ci/**
299562306a36Sopenharmony_ci * ice_is_100m_speed_supported
299662306a36Sopenharmony_ci * @hw: pointer to the HW struct
299762306a36Sopenharmony_ci *
299862306a36Sopenharmony_ci * returns true if 100M speeds are supported by the device,
299962306a36Sopenharmony_ci * false otherwise.
300062306a36Sopenharmony_ci */
300162306a36Sopenharmony_cibool ice_is_100m_speed_supported(struct ice_hw *hw)
300262306a36Sopenharmony_ci{
300362306a36Sopenharmony_ci	switch (hw->device_id) {
300462306a36Sopenharmony_ci	case ICE_DEV_ID_E822C_SGMII:
300562306a36Sopenharmony_ci	case ICE_DEV_ID_E822L_SGMII:
300662306a36Sopenharmony_ci	case ICE_DEV_ID_E823L_1GBE:
300762306a36Sopenharmony_ci	case ICE_DEV_ID_E823C_SGMII:
300862306a36Sopenharmony_ci		return true;
300962306a36Sopenharmony_ci	default:
301062306a36Sopenharmony_ci		return false;
301162306a36Sopenharmony_ci	}
301262306a36Sopenharmony_ci}
301362306a36Sopenharmony_ci
301462306a36Sopenharmony_ci/**
301562306a36Sopenharmony_ci * ice_get_link_speed_based_on_phy_type - returns link speed
301662306a36Sopenharmony_ci * @phy_type_low: lower part of phy_type
301762306a36Sopenharmony_ci * @phy_type_high: higher part of phy_type
301862306a36Sopenharmony_ci *
301962306a36Sopenharmony_ci * This helper function will convert an entry in PHY type structure
302062306a36Sopenharmony_ci * [phy_type_low, phy_type_high] to its corresponding link speed.
302162306a36Sopenharmony_ci * Note: In the structure of [phy_type_low, phy_type_high], there should
302262306a36Sopenharmony_ci * be one bit set, as this function will convert one PHY type to its
302362306a36Sopenharmony_ci * speed.
302462306a36Sopenharmony_ci * If no bit gets set, ICE_AQ_LINK_SPEED_UNKNOWN will be returned
302562306a36Sopenharmony_ci * If more than one bit gets set, ICE_AQ_LINK_SPEED_UNKNOWN will be returned
302662306a36Sopenharmony_ci */
302762306a36Sopenharmony_cistatic u16
302862306a36Sopenharmony_ciice_get_link_speed_based_on_phy_type(u64 phy_type_low, u64 phy_type_high)
302962306a36Sopenharmony_ci{
303062306a36Sopenharmony_ci	u16 speed_phy_type_high = ICE_AQ_LINK_SPEED_UNKNOWN;
303162306a36Sopenharmony_ci	u16 speed_phy_type_low = ICE_AQ_LINK_SPEED_UNKNOWN;
303262306a36Sopenharmony_ci
303362306a36Sopenharmony_ci	switch (phy_type_low) {
303462306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_100BASE_TX:
303562306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_100M_SGMII:
303662306a36Sopenharmony_ci		speed_phy_type_low = ICE_AQ_LINK_SPEED_100MB;
303762306a36Sopenharmony_ci		break;
303862306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_1000BASE_T:
303962306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_1000BASE_SX:
304062306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_1000BASE_LX:
304162306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_1000BASE_KX:
304262306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_1G_SGMII:
304362306a36Sopenharmony_ci		speed_phy_type_low = ICE_AQ_LINK_SPEED_1000MB;
304462306a36Sopenharmony_ci		break;
304562306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_2500BASE_T:
304662306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_2500BASE_X:
304762306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_2500BASE_KX:
304862306a36Sopenharmony_ci		speed_phy_type_low = ICE_AQ_LINK_SPEED_2500MB;
304962306a36Sopenharmony_ci		break;
305062306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_5GBASE_T:
305162306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_5GBASE_KR:
305262306a36Sopenharmony_ci		speed_phy_type_low = ICE_AQ_LINK_SPEED_5GB;
305362306a36Sopenharmony_ci		break;
305462306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_10GBASE_T:
305562306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_10G_SFI_DA:
305662306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_10GBASE_SR:
305762306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_10GBASE_LR:
305862306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_10GBASE_KR_CR1:
305962306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_10G_SFI_AOC_ACC:
306062306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_10G_SFI_C2C:
306162306a36Sopenharmony_ci		speed_phy_type_low = ICE_AQ_LINK_SPEED_10GB;
306262306a36Sopenharmony_ci		break;
306362306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_25GBASE_T:
306462306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_25GBASE_CR:
306562306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_25GBASE_CR_S:
306662306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_25GBASE_CR1:
306762306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_25GBASE_SR:
306862306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_25GBASE_LR:
306962306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_25GBASE_KR:
307062306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_25GBASE_KR_S:
307162306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_25GBASE_KR1:
307262306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_25G_AUI_AOC_ACC:
307362306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_25G_AUI_C2C:
307462306a36Sopenharmony_ci		speed_phy_type_low = ICE_AQ_LINK_SPEED_25GB;
307562306a36Sopenharmony_ci		break;
307662306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_40GBASE_CR4:
307762306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_40GBASE_SR4:
307862306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_40GBASE_LR4:
307962306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_40GBASE_KR4:
308062306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_40G_XLAUI_AOC_ACC:
308162306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_40G_XLAUI:
308262306a36Sopenharmony_ci		speed_phy_type_low = ICE_AQ_LINK_SPEED_40GB;
308362306a36Sopenharmony_ci		break;
308462306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_50GBASE_CR2:
308562306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_50GBASE_SR2:
308662306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_50GBASE_LR2:
308762306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_50GBASE_KR2:
308862306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_50G_LAUI2_AOC_ACC:
308962306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_50G_LAUI2:
309062306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_50G_AUI2_AOC_ACC:
309162306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_50G_AUI2:
309262306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_50GBASE_CP:
309362306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_50GBASE_SR:
309462306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_50GBASE_FR:
309562306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_50GBASE_LR:
309662306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4:
309762306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_50G_AUI1_AOC_ACC:
309862306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_50G_AUI1:
309962306a36Sopenharmony_ci		speed_phy_type_low = ICE_AQ_LINK_SPEED_50GB;
310062306a36Sopenharmony_ci		break;
310162306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_100GBASE_CR4:
310262306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_100GBASE_SR4:
310362306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_100GBASE_LR4:
310462306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_100GBASE_KR4:
310562306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_100G_CAUI4_AOC_ACC:
310662306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_100G_CAUI4:
310762306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_100G_AUI4_AOC_ACC:
310862306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_100G_AUI4:
310962306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_100GBASE_CR_PAM4:
311062306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4:
311162306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_100GBASE_CP2:
311262306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_100GBASE_SR2:
311362306a36Sopenharmony_ci	case ICE_PHY_TYPE_LOW_100GBASE_DR:
311462306a36Sopenharmony_ci		speed_phy_type_low = ICE_AQ_LINK_SPEED_100GB;
311562306a36Sopenharmony_ci		break;
311662306a36Sopenharmony_ci	default:
311762306a36Sopenharmony_ci		speed_phy_type_low = ICE_AQ_LINK_SPEED_UNKNOWN;
311862306a36Sopenharmony_ci		break;
311962306a36Sopenharmony_ci	}
312062306a36Sopenharmony_ci
312162306a36Sopenharmony_ci	switch (phy_type_high) {
312262306a36Sopenharmony_ci	case ICE_PHY_TYPE_HIGH_100GBASE_KR2_PAM4:
312362306a36Sopenharmony_ci	case ICE_PHY_TYPE_HIGH_100G_CAUI2_AOC_ACC:
312462306a36Sopenharmony_ci	case ICE_PHY_TYPE_HIGH_100G_CAUI2:
312562306a36Sopenharmony_ci	case ICE_PHY_TYPE_HIGH_100G_AUI2_AOC_ACC:
312662306a36Sopenharmony_ci	case ICE_PHY_TYPE_HIGH_100G_AUI2:
312762306a36Sopenharmony_ci		speed_phy_type_high = ICE_AQ_LINK_SPEED_100GB;
312862306a36Sopenharmony_ci		break;
312962306a36Sopenharmony_ci	default:
313062306a36Sopenharmony_ci		speed_phy_type_high = ICE_AQ_LINK_SPEED_UNKNOWN;
313162306a36Sopenharmony_ci		break;
313262306a36Sopenharmony_ci	}
313362306a36Sopenharmony_ci
313462306a36Sopenharmony_ci	if (speed_phy_type_low == ICE_AQ_LINK_SPEED_UNKNOWN &&
313562306a36Sopenharmony_ci	    speed_phy_type_high == ICE_AQ_LINK_SPEED_UNKNOWN)
313662306a36Sopenharmony_ci		return ICE_AQ_LINK_SPEED_UNKNOWN;
313762306a36Sopenharmony_ci	else if (speed_phy_type_low != ICE_AQ_LINK_SPEED_UNKNOWN &&
313862306a36Sopenharmony_ci		 speed_phy_type_high != ICE_AQ_LINK_SPEED_UNKNOWN)
313962306a36Sopenharmony_ci		return ICE_AQ_LINK_SPEED_UNKNOWN;
314062306a36Sopenharmony_ci	else if (speed_phy_type_low != ICE_AQ_LINK_SPEED_UNKNOWN &&
314162306a36Sopenharmony_ci		 speed_phy_type_high == ICE_AQ_LINK_SPEED_UNKNOWN)
314262306a36Sopenharmony_ci		return speed_phy_type_low;
314362306a36Sopenharmony_ci	else
314462306a36Sopenharmony_ci		return speed_phy_type_high;
314562306a36Sopenharmony_ci}
314662306a36Sopenharmony_ci
314762306a36Sopenharmony_ci/**
314862306a36Sopenharmony_ci * ice_update_phy_type
314962306a36Sopenharmony_ci * @phy_type_low: pointer to the lower part of phy_type
315062306a36Sopenharmony_ci * @phy_type_high: pointer to the higher part of phy_type
315162306a36Sopenharmony_ci * @link_speeds_bitmap: targeted link speeds bitmap
315262306a36Sopenharmony_ci *
315362306a36Sopenharmony_ci * Note: For the link_speeds_bitmap structure, you can check it at
315462306a36Sopenharmony_ci * [ice_aqc_get_link_status->link_speed]. Caller can pass in
315562306a36Sopenharmony_ci * link_speeds_bitmap include multiple speeds.
315662306a36Sopenharmony_ci *
315762306a36Sopenharmony_ci * Each entry in this [phy_type_low, phy_type_high] structure will
315862306a36Sopenharmony_ci * present a certain link speed. This helper function will turn on bits
315962306a36Sopenharmony_ci * in [phy_type_low, phy_type_high] structure based on the value of
316062306a36Sopenharmony_ci * link_speeds_bitmap input parameter.
316162306a36Sopenharmony_ci */
316262306a36Sopenharmony_civoid
316362306a36Sopenharmony_ciice_update_phy_type(u64 *phy_type_low, u64 *phy_type_high,
316462306a36Sopenharmony_ci		    u16 link_speeds_bitmap)
316562306a36Sopenharmony_ci{
316662306a36Sopenharmony_ci	u64 pt_high;
316762306a36Sopenharmony_ci	u64 pt_low;
316862306a36Sopenharmony_ci	int index;
316962306a36Sopenharmony_ci	u16 speed;
317062306a36Sopenharmony_ci
317162306a36Sopenharmony_ci	/* We first check with low part of phy_type */
317262306a36Sopenharmony_ci	for (index = 0; index <= ICE_PHY_TYPE_LOW_MAX_INDEX; index++) {
317362306a36Sopenharmony_ci		pt_low = BIT_ULL(index);
317462306a36Sopenharmony_ci		speed = ice_get_link_speed_based_on_phy_type(pt_low, 0);
317562306a36Sopenharmony_ci
317662306a36Sopenharmony_ci		if (link_speeds_bitmap & speed)
317762306a36Sopenharmony_ci			*phy_type_low |= BIT_ULL(index);
317862306a36Sopenharmony_ci	}
317962306a36Sopenharmony_ci
318062306a36Sopenharmony_ci	/* We then check with high part of phy_type */
318162306a36Sopenharmony_ci	for (index = 0; index <= ICE_PHY_TYPE_HIGH_MAX_INDEX; index++) {
318262306a36Sopenharmony_ci		pt_high = BIT_ULL(index);
318362306a36Sopenharmony_ci		speed = ice_get_link_speed_based_on_phy_type(0, pt_high);
318462306a36Sopenharmony_ci
318562306a36Sopenharmony_ci		if (link_speeds_bitmap & speed)
318662306a36Sopenharmony_ci			*phy_type_high |= BIT_ULL(index);
318762306a36Sopenharmony_ci	}
318862306a36Sopenharmony_ci}
318962306a36Sopenharmony_ci
319062306a36Sopenharmony_ci/**
319162306a36Sopenharmony_ci * ice_aq_set_phy_cfg
319262306a36Sopenharmony_ci * @hw: pointer to the HW struct
319362306a36Sopenharmony_ci * @pi: port info structure of the interested logical port
319462306a36Sopenharmony_ci * @cfg: structure with PHY configuration data to be set
319562306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL
319662306a36Sopenharmony_ci *
319762306a36Sopenharmony_ci * Set the various PHY configuration parameters supported on the Port.
319862306a36Sopenharmony_ci * One or more of the Set PHY config parameters may be ignored in an MFP
319962306a36Sopenharmony_ci * mode as the PF may not have the privilege to set some of the PHY Config
320062306a36Sopenharmony_ci * parameters. This status will be indicated by the command response (0x0601).
320162306a36Sopenharmony_ci */
320262306a36Sopenharmony_ciint
320362306a36Sopenharmony_ciice_aq_set_phy_cfg(struct ice_hw *hw, struct ice_port_info *pi,
320462306a36Sopenharmony_ci		   struct ice_aqc_set_phy_cfg_data *cfg, struct ice_sq_cd *cd)
320562306a36Sopenharmony_ci{
320662306a36Sopenharmony_ci	struct ice_aq_desc desc;
320762306a36Sopenharmony_ci	int status;
320862306a36Sopenharmony_ci
320962306a36Sopenharmony_ci	if (!cfg)
321062306a36Sopenharmony_ci		return -EINVAL;
321162306a36Sopenharmony_ci
321262306a36Sopenharmony_ci	/* Ensure that only valid bits of cfg->caps can be turned on. */
321362306a36Sopenharmony_ci	if (cfg->caps & ~ICE_AQ_PHY_ENA_VALID_MASK) {
321462306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_PHY, "Invalid bit is set in ice_aqc_set_phy_cfg_data->caps : 0x%x\n",
321562306a36Sopenharmony_ci			  cfg->caps);
321662306a36Sopenharmony_ci
321762306a36Sopenharmony_ci		cfg->caps &= ICE_AQ_PHY_ENA_VALID_MASK;
321862306a36Sopenharmony_ci	}
321962306a36Sopenharmony_ci
322062306a36Sopenharmony_ci	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_phy_cfg);
322162306a36Sopenharmony_ci	desc.params.set_phy.lport_num = pi->lport;
322262306a36Sopenharmony_ci	desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
322362306a36Sopenharmony_ci
322462306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_LINK, "set phy cfg\n");
322562306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_LINK, "	phy_type_low = 0x%llx\n",
322662306a36Sopenharmony_ci		  (unsigned long long)le64_to_cpu(cfg->phy_type_low));
322762306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_LINK, "	phy_type_high = 0x%llx\n",
322862306a36Sopenharmony_ci		  (unsigned long long)le64_to_cpu(cfg->phy_type_high));
322962306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_LINK, "	caps = 0x%x\n", cfg->caps);
323062306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_LINK, "	low_power_ctrl_an = 0x%x\n",
323162306a36Sopenharmony_ci		  cfg->low_power_ctrl_an);
323262306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_LINK, "	eee_cap = 0x%x\n", cfg->eee_cap);
323362306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_LINK, "	eeer_value = 0x%x\n", cfg->eeer_value);
323462306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_LINK, "	link_fec_opt = 0x%x\n",
323562306a36Sopenharmony_ci		  cfg->link_fec_opt);
323662306a36Sopenharmony_ci
323762306a36Sopenharmony_ci	status = ice_aq_send_cmd(hw, &desc, cfg, sizeof(*cfg), cd);
323862306a36Sopenharmony_ci	if (hw->adminq.sq_last_status == ICE_AQ_RC_EMODE)
323962306a36Sopenharmony_ci		status = 0;
324062306a36Sopenharmony_ci
324162306a36Sopenharmony_ci	if (!status)
324262306a36Sopenharmony_ci		pi->phy.curr_user_phy_cfg = *cfg;
324362306a36Sopenharmony_ci
324462306a36Sopenharmony_ci	return status;
324562306a36Sopenharmony_ci}
324662306a36Sopenharmony_ci
324762306a36Sopenharmony_ci/**
324862306a36Sopenharmony_ci * ice_update_link_info - update status of the HW network link
324962306a36Sopenharmony_ci * @pi: port info structure of the interested logical port
325062306a36Sopenharmony_ci */
325162306a36Sopenharmony_ciint ice_update_link_info(struct ice_port_info *pi)
325262306a36Sopenharmony_ci{
325362306a36Sopenharmony_ci	struct ice_link_status *li;
325462306a36Sopenharmony_ci	int status;
325562306a36Sopenharmony_ci
325662306a36Sopenharmony_ci	if (!pi)
325762306a36Sopenharmony_ci		return -EINVAL;
325862306a36Sopenharmony_ci
325962306a36Sopenharmony_ci	li = &pi->phy.link_info;
326062306a36Sopenharmony_ci
326162306a36Sopenharmony_ci	status = ice_aq_get_link_info(pi, true, NULL, NULL);
326262306a36Sopenharmony_ci	if (status)
326362306a36Sopenharmony_ci		return status;
326462306a36Sopenharmony_ci
326562306a36Sopenharmony_ci	if (li->link_info & ICE_AQ_MEDIA_AVAILABLE) {
326662306a36Sopenharmony_ci		struct ice_aqc_get_phy_caps_data *pcaps;
326762306a36Sopenharmony_ci		struct ice_hw *hw;
326862306a36Sopenharmony_ci
326962306a36Sopenharmony_ci		hw = pi->hw;
327062306a36Sopenharmony_ci		pcaps = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*pcaps),
327162306a36Sopenharmony_ci				     GFP_KERNEL);
327262306a36Sopenharmony_ci		if (!pcaps)
327362306a36Sopenharmony_ci			return -ENOMEM;
327462306a36Sopenharmony_ci
327562306a36Sopenharmony_ci		status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_TOPO_CAP_MEDIA,
327662306a36Sopenharmony_ci					     pcaps, NULL);
327762306a36Sopenharmony_ci
327862306a36Sopenharmony_ci		devm_kfree(ice_hw_to_dev(hw), pcaps);
327962306a36Sopenharmony_ci	}
328062306a36Sopenharmony_ci
328162306a36Sopenharmony_ci	return status;
328262306a36Sopenharmony_ci}
328362306a36Sopenharmony_ci
328462306a36Sopenharmony_ci/**
328562306a36Sopenharmony_ci * ice_cache_phy_user_req
328662306a36Sopenharmony_ci * @pi: port information structure
328762306a36Sopenharmony_ci * @cache_data: PHY logging data
328862306a36Sopenharmony_ci * @cache_mode: PHY logging mode
328962306a36Sopenharmony_ci *
329062306a36Sopenharmony_ci * Log the user request on (FC, FEC, SPEED) for later use.
329162306a36Sopenharmony_ci */
329262306a36Sopenharmony_cistatic void
329362306a36Sopenharmony_ciice_cache_phy_user_req(struct ice_port_info *pi,
329462306a36Sopenharmony_ci		       struct ice_phy_cache_mode_data cache_data,
329562306a36Sopenharmony_ci		       enum ice_phy_cache_mode cache_mode)
329662306a36Sopenharmony_ci{
329762306a36Sopenharmony_ci	if (!pi)
329862306a36Sopenharmony_ci		return;
329962306a36Sopenharmony_ci
330062306a36Sopenharmony_ci	switch (cache_mode) {
330162306a36Sopenharmony_ci	case ICE_FC_MODE:
330262306a36Sopenharmony_ci		pi->phy.curr_user_fc_req = cache_data.data.curr_user_fc_req;
330362306a36Sopenharmony_ci		break;
330462306a36Sopenharmony_ci	case ICE_SPEED_MODE:
330562306a36Sopenharmony_ci		pi->phy.curr_user_speed_req =
330662306a36Sopenharmony_ci			cache_data.data.curr_user_speed_req;
330762306a36Sopenharmony_ci		break;
330862306a36Sopenharmony_ci	case ICE_FEC_MODE:
330962306a36Sopenharmony_ci		pi->phy.curr_user_fec_req = cache_data.data.curr_user_fec_req;
331062306a36Sopenharmony_ci		break;
331162306a36Sopenharmony_ci	default:
331262306a36Sopenharmony_ci		break;
331362306a36Sopenharmony_ci	}
331462306a36Sopenharmony_ci}
331562306a36Sopenharmony_ci
331662306a36Sopenharmony_ci/**
331762306a36Sopenharmony_ci * ice_caps_to_fc_mode
331862306a36Sopenharmony_ci * @caps: PHY capabilities
331962306a36Sopenharmony_ci *
332062306a36Sopenharmony_ci * Convert PHY FC capabilities to ice FC mode
332162306a36Sopenharmony_ci */
332262306a36Sopenharmony_cienum ice_fc_mode ice_caps_to_fc_mode(u8 caps)
332362306a36Sopenharmony_ci{
332462306a36Sopenharmony_ci	if (caps & ICE_AQC_PHY_EN_TX_LINK_PAUSE &&
332562306a36Sopenharmony_ci	    caps & ICE_AQC_PHY_EN_RX_LINK_PAUSE)
332662306a36Sopenharmony_ci		return ICE_FC_FULL;
332762306a36Sopenharmony_ci
332862306a36Sopenharmony_ci	if (caps & ICE_AQC_PHY_EN_TX_LINK_PAUSE)
332962306a36Sopenharmony_ci		return ICE_FC_TX_PAUSE;
333062306a36Sopenharmony_ci
333162306a36Sopenharmony_ci	if (caps & ICE_AQC_PHY_EN_RX_LINK_PAUSE)
333262306a36Sopenharmony_ci		return ICE_FC_RX_PAUSE;
333362306a36Sopenharmony_ci
333462306a36Sopenharmony_ci	return ICE_FC_NONE;
333562306a36Sopenharmony_ci}
333662306a36Sopenharmony_ci
333762306a36Sopenharmony_ci/**
333862306a36Sopenharmony_ci * ice_caps_to_fec_mode
333962306a36Sopenharmony_ci * @caps: PHY capabilities
334062306a36Sopenharmony_ci * @fec_options: Link FEC options
334162306a36Sopenharmony_ci *
334262306a36Sopenharmony_ci * Convert PHY FEC capabilities to ice FEC mode
334362306a36Sopenharmony_ci */
334462306a36Sopenharmony_cienum ice_fec_mode ice_caps_to_fec_mode(u8 caps, u8 fec_options)
334562306a36Sopenharmony_ci{
334662306a36Sopenharmony_ci	if (caps & ICE_AQC_PHY_EN_AUTO_FEC)
334762306a36Sopenharmony_ci		return ICE_FEC_AUTO;
334862306a36Sopenharmony_ci
334962306a36Sopenharmony_ci	if (fec_options & (ICE_AQC_PHY_FEC_10G_KR_40G_KR4_EN |
335062306a36Sopenharmony_ci			   ICE_AQC_PHY_FEC_10G_KR_40G_KR4_REQ |
335162306a36Sopenharmony_ci			   ICE_AQC_PHY_FEC_25G_KR_CLAUSE74_EN |
335262306a36Sopenharmony_ci			   ICE_AQC_PHY_FEC_25G_KR_REQ))
335362306a36Sopenharmony_ci		return ICE_FEC_BASER;
335462306a36Sopenharmony_ci
335562306a36Sopenharmony_ci	if (fec_options & (ICE_AQC_PHY_FEC_25G_RS_528_REQ |
335662306a36Sopenharmony_ci			   ICE_AQC_PHY_FEC_25G_RS_544_REQ |
335762306a36Sopenharmony_ci			   ICE_AQC_PHY_FEC_25G_RS_CLAUSE91_EN))
335862306a36Sopenharmony_ci		return ICE_FEC_RS;
335962306a36Sopenharmony_ci
336062306a36Sopenharmony_ci	return ICE_FEC_NONE;
336162306a36Sopenharmony_ci}
336262306a36Sopenharmony_ci
336362306a36Sopenharmony_ci/**
336462306a36Sopenharmony_ci * ice_cfg_phy_fc - Configure PHY FC data based on FC mode
336562306a36Sopenharmony_ci * @pi: port information structure
336662306a36Sopenharmony_ci * @cfg: PHY configuration data to set FC mode
336762306a36Sopenharmony_ci * @req_mode: FC mode to configure
336862306a36Sopenharmony_ci */
336962306a36Sopenharmony_ciint
337062306a36Sopenharmony_ciice_cfg_phy_fc(struct ice_port_info *pi, struct ice_aqc_set_phy_cfg_data *cfg,
337162306a36Sopenharmony_ci	       enum ice_fc_mode req_mode)
337262306a36Sopenharmony_ci{
337362306a36Sopenharmony_ci	struct ice_phy_cache_mode_data cache_data;
337462306a36Sopenharmony_ci	u8 pause_mask = 0x0;
337562306a36Sopenharmony_ci
337662306a36Sopenharmony_ci	if (!pi || !cfg)
337762306a36Sopenharmony_ci		return -EINVAL;
337862306a36Sopenharmony_ci
337962306a36Sopenharmony_ci	switch (req_mode) {
338062306a36Sopenharmony_ci	case ICE_FC_FULL:
338162306a36Sopenharmony_ci		pause_mask |= ICE_AQC_PHY_EN_TX_LINK_PAUSE;
338262306a36Sopenharmony_ci		pause_mask |= ICE_AQC_PHY_EN_RX_LINK_PAUSE;
338362306a36Sopenharmony_ci		break;
338462306a36Sopenharmony_ci	case ICE_FC_RX_PAUSE:
338562306a36Sopenharmony_ci		pause_mask |= ICE_AQC_PHY_EN_RX_LINK_PAUSE;
338662306a36Sopenharmony_ci		break;
338762306a36Sopenharmony_ci	case ICE_FC_TX_PAUSE:
338862306a36Sopenharmony_ci		pause_mask |= ICE_AQC_PHY_EN_TX_LINK_PAUSE;
338962306a36Sopenharmony_ci		break;
339062306a36Sopenharmony_ci	default:
339162306a36Sopenharmony_ci		break;
339262306a36Sopenharmony_ci	}
339362306a36Sopenharmony_ci
339462306a36Sopenharmony_ci	/* clear the old pause settings */
339562306a36Sopenharmony_ci	cfg->caps &= ~(ICE_AQC_PHY_EN_TX_LINK_PAUSE |
339662306a36Sopenharmony_ci		ICE_AQC_PHY_EN_RX_LINK_PAUSE);
339762306a36Sopenharmony_ci
339862306a36Sopenharmony_ci	/* set the new capabilities */
339962306a36Sopenharmony_ci	cfg->caps |= pause_mask;
340062306a36Sopenharmony_ci
340162306a36Sopenharmony_ci	/* Cache user FC request */
340262306a36Sopenharmony_ci	cache_data.data.curr_user_fc_req = req_mode;
340362306a36Sopenharmony_ci	ice_cache_phy_user_req(pi, cache_data, ICE_FC_MODE);
340462306a36Sopenharmony_ci
340562306a36Sopenharmony_ci	return 0;
340662306a36Sopenharmony_ci}
340762306a36Sopenharmony_ci
340862306a36Sopenharmony_ci/**
340962306a36Sopenharmony_ci * ice_set_fc
341062306a36Sopenharmony_ci * @pi: port information structure
341162306a36Sopenharmony_ci * @aq_failures: pointer to status code, specific to ice_set_fc routine
341262306a36Sopenharmony_ci * @ena_auto_link_update: enable automatic link update
341362306a36Sopenharmony_ci *
341462306a36Sopenharmony_ci * Set the requested flow control mode.
341562306a36Sopenharmony_ci */
341662306a36Sopenharmony_ciint
341762306a36Sopenharmony_ciice_set_fc(struct ice_port_info *pi, u8 *aq_failures, bool ena_auto_link_update)
341862306a36Sopenharmony_ci{
341962306a36Sopenharmony_ci	struct ice_aqc_set_phy_cfg_data cfg = { 0 };
342062306a36Sopenharmony_ci	struct ice_aqc_get_phy_caps_data *pcaps;
342162306a36Sopenharmony_ci	struct ice_hw *hw;
342262306a36Sopenharmony_ci	int status;
342362306a36Sopenharmony_ci
342462306a36Sopenharmony_ci	if (!pi || !aq_failures)
342562306a36Sopenharmony_ci		return -EINVAL;
342662306a36Sopenharmony_ci
342762306a36Sopenharmony_ci	*aq_failures = 0;
342862306a36Sopenharmony_ci	hw = pi->hw;
342962306a36Sopenharmony_ci
343062306a36Sopenharmony_ci	pcaps = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*pcaps), GFP_KERNEL);
343162306a36Sopenharmony_ci	if (!pcaps)
343262306a36Sopenharmony_ci		return -ENOMEM;
343362306a36Sopenharmony_ci
343462306a36Sopenharmony_ci	/* Get the current PHY config */
343562306a36Sopenharmony_ci	status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_ACTIVE_CFG,
343662306a36Sopenharmony_ci				     pcaps, NULL);
343762306a36Sopenharmony_ci	if (status) {
343862306a36Sopenharmony_ci		*aq_failures = ICE_SET_FC_AQ_FAIL_GET;
343962306a36Sopenharmony_ci		goto out;
344062306a36Sopenharmony_ci	}
344162306a36Sopenharmony_ci
344262306a36Sopenharmony_ci	ice_copy_phy_caps_to_cfg(pi, pcaps, &cfg);
344362306a36Sopenharmony_ci
344462306a36Sopenharmony_ci	/* Configure the set PHY data */
344562306a36Sopenharmony_ci	status = ice_cfg_phy_fc(pi, &cfg, pi->fc.req_mode);
344662306a36Sopenharmony_ci	if (status)
344762306a36Sopenharmony_ci		goto out;
344862306a36Sopenharmony_ci
344962306a36Sopenharmony_ci	/* If the capabilities have changed, then set the new config */
345062306a36Sopenharmony_ci	if (cfg.caps != pcaps->caps) {
345162306a36Sopenharmony_ci		int retry_count, retry_max = 10;
345262306a36Sopenharmony_ci
345362306a36Sopenharmony_ci		/* Auto restart link so settings take effect */
345462306a36Sopenharmony_ci		if (ena_auto_link_update)
345562306a36Sopenharmony_ci			cfg.caps |= ICE_AQ_PHY_ENA_AUTO_LINK_UPDT;
345662306a36Sopenharmony_ci
345762306a36Sopenharmony_ci		status = ice_aq_set_phy_cfg(hw, pi, &cfg, NULL);
345862306a36Sopenharmony_ci		if (status) {
345962306a36Sopenharmony_ci			*aq_failures = ICE_SET_FC_AQ_FAIL_SET;
346062306a36Sopenharmony_ci			goto out;
346162306a36Sopenharmony_ci		}
346262306a36Sopenharmony_ci
346362306a36Sopenharmony_ci		/* Update the link info
346462306a36Sopenharmony_ci		 * It sometimes takes a really long time for link to
346562306a36Sopenharmony_ci		 * come back from the atomic reset. Thus, we wait a
346662306a36Sopenharmony_ci		 * little bit.
346762306a36Sopenharmony_ci		 */
346862306a36Sopenharmony_ci		for (retry_count = 0; retry_count < retry_max; retry_count++) {
346962306a36Sopenharmony_ci			status = ice_update_link_info(pi);
347062306a36Sopenharmony_ci
347162306a36Sopenharmony_ci			if (!status)
347262306a36Sopenharmony_ci				break;
347362306a36Sopenharmony_ci
347462306a36Sopenharmony_ci			mdelay(100);
347562306a36Sopenharmony_ci		}
347662306a36Sopenharmony_ci
347762306a36Sopenharmony_ci		if (status)
347862306a36Sopenharmony_ci			*aq_failures = ICE_SET_FC_AQ_FAIL_UPDATE;
347962306a36Sopenharmony_ci	}
348062306a36Sopenharmony_ci
348162306a36Sopenharmony_ciout:
348262306a36Sopenharmony_ci	devm_kfree(ice_hw_to_dev(hw), pcaps);
348362306a36Sopenharmony_ci	return status;
348462306a36Sopenharmony_ci}
348562306a36Sopenharmony_ci
348662306a36Sopenharmony_ci/**
348762306a36Sopenharmony_ci * ice_phy_caps_equals_cfg
348862306a36Sopenharmony_ci * @phy_caps: PHY capabilities
348962306a36Sopenharmony_ci * @phy_cfg: PHY configuration
349062306a36Sopenharmony_ci *
349162306a36Sopenharmony_ci * Helper function to determine if PHY capabilities matches PHY
349262306a36Sopenharmony_ci * configuration
349362306a36Sopenharmony_ci */
349462306a36Sopenharmony_cibool
349562306a36Sopenharmony_ciice_phy_caps_equals_cfg(struct ice_aqc_get_phy_caps_data *phy_caps,
349662306a36Sopenharmony_ci			struct ice_aqc_set_phy_cfg_data *phy_cfg)
349762306a36Sopenharmony_ci{
349862306a36Sopenharmony_ci	u8 caps_mask, cfg_mask;
349962306a36Sopenharmony_ci
350062306a36Sopenharmony_ci	if (!phy_caps || !phy_cfg)
350162306a36Sopenharmony_ci		return false;
350262306a36Sopenharmony_ci
350362306a36Sopenharmony_ci	/* These bits are not common between capabilities and configuration.
350462306a36Sopenharmony_ci	 * Do not use them to determine equality.
350562306a36Sopenharmony_ci	 */
350662306a36Sopenharmony_ci	caps_mask = ICE_AQC_PHY_CAPS_MASK & ~(ICE_AQC_PHY_AN_MODE |
350762306a36Sopenharmony_ci					      ICE_AQC_GET_PHY_EN_MOD_QUAL);
350862306a36Sopenharmony_ci	cfg_mask = ICE_AQ_PHY_ENA_VALID_MASK & ~ICE_AQ_PHY_ENA_AUTO_LINK_UPDT;
350962306a36Sopenharmony_ci
351062306a36Sopenharmony_ci	if (phy_caps->phy_type_low != phy_cfg->phy_type_low ||
351162306a36Sopenharmony_ci	    phy_caps->phy_type_high != phy_cfg->phy_type_high ||
351262306a36Sopenharmony_ci	    ((phy_caps->caps & caps_mask) != (phy_cfg->caps & cfg_mask)) ||
351362306a36Sopenharmony_ci	    phy_caps->low_power_ctrl_an != phy_cfg->low_power_ctrl_an ||
351462306a36Sopenharmony_ci	    phy_caps->eee_cap != phy_cfg->eee_cap ||
351562306a36Sopenharmony_ci	    phy_caps->eeer_value != phy_cfg->eeer_value ||
351662306a36Sopenharmony_ci	    phy_caps->link_fec_options != phy_cfg->link_fec_opt)
351762306a36Sopenharmony_ci		return false;
351862306a36Sopenharmony_ci
351962306a36Sopenharmony_ci	return true;
352062306a36Sopenharmony_ci}
352162306a36Sopenharmony_ci
352262306a36Sopenharmony_ci/**
352362306a36Sopenharmony_ci * ice_copy_phy_caps_to_cfg - Copy PHY ability data to configuration data
352462306a36Sopenharmony_ci * @pi: port information structure
352562306a36Sopenharmony_ci * @caps: PHY ability structure to copy date from
352662306a36Sopenharmony_ci * @cfg: PHY configuration structure to copy data to
352762306a36Sopenharmony_ci *
352862306a36Sopenharmony_ci * Helper function to copy AQC PHY get ability data to PHY set configuration
352962306a36Sopenharmony_ci * data structure
353062306a36Sopenharmony_ci */
353162306a36Sopenharmony_civoid
353262306a36Sopenharmony_ciice_copy_phy_caps_to_cfg(struct ice_port_info *pi,
353362306a36Sopenharmony_ci			 struct ice_aqc_get_phy_caps_data *caps,
353462306a36Sopenharmony_ci			 struct ice_aqc_set_phy_cfg_data *cfg)
353562306a36Sopenharmony_ci{
353662306a36Sopenharmony_ci	if (!pi || !caps || !cfg)
353762306a36Sopenharmony_ci		return;
353862306a36Sopenharmony_ci
353962306a36Sopenharmony_ci	memset(cfg, 0, sizeof(*cfg));
354062306a36Sopenharmony_ci	cfg->phy_type_low = caps->phy_type_low;
354162306a36Sopenharmony_ci	cfg->phy_type_high = caps->phy_type_high;
354262306a36Sopenharmony_ci	cfg->caps = caps->caps;
354362306a36Sopenharmony_ci	cfg->low_power_ctrl_an = caps->low_power_ctrl_an;
354462306a36Sopenharmony_ci	cfg->eee_cap = caps->eee_cap;
354562306a36Sopenharmony_ci	cfg->eeer_value = caps->eeer_value;
354662306a36Sopenharmony_ci	cfg->link_fec_opt = caps->link_fec_options;
354762306a36Sopenharmony_ci	cfg->module_compliance_enforcement =
354862306a36Sopenharmony_ci		caps->module_compliance_enforcement;
354962306a36Sopenharmony_ci}
355062306a36Sopenharmony_ci
355162306a36Sopenharmony_ci/**
355262306a36Sopenharmony_ci * ice_cfg_phy_fec - Configure PHY FEC data based on FEC mode
355362306a36Sopenharmony_ci * @pi: port information structure
355462306a36Sopenharmony_ci * @cfg: PHY configuration data to set FEC mode
355562306a36Sopenharmony_ci * @fec: FEC mode to configure
355662306a36Sopenharmony_ci */
355762306a36Sopenharmony_ciint
355862306a36Sopenharmony_ciice_cfg_phy_fec(struct ice_port_info *pi, struct ice_aqc_set_phy_cfg_data *cfg,
355962306a36Sopenharmony_ci		enum ice_fec_mode fec)
356062306a36Sopenharmony_ci{
356162306a36Sopenharmony_ci	struct ice_aqc_get_phy_caps_data *pcaps;
356262306a36Sopenharmony_ci	struct ice_hw *hw;
356362306a36Sopenharmony_ci	int status;
356462306a36Sopenharmony_ci
356562306a36Sopenharmony_ci	if (!pi || !cfg)
356662306a36Sopenharmony_ci		return -EINVAL;
356762306a36Sopenharmony_ci
356862306a36Sopenharmony_ci	hw = pi->hw;
356962306a36Sopenharmony_ci
357062306a36Sopenharmony_ci	pcaps = kzalloc(sizeof(*pcaps), GFP_KERNEL);
357162306a36Sopenharmony_ci	if (!pcaps)
357262306a36Sopenharmony_ci		return -ENOMEM;
357362306a36Sopenharmony_ci
357462306a36Sopenharmony_ci	status = ice_aq_get_phy_caps(pi, false,
357562306a36Sopenharmony_ci				     (ice_fw_supports_report_dflt_cfg(hw) ?
357662306a36Sopenharmony_ci				      ICE_AQC_REPORT_DFLT_CFG :
357762306a36Sopenharmony_ci				      ICE_AQC_REPORT_TOPO_CAP_MEDIA), pcaps, NULL);
357862306a36Sopenharmony_ci	if (status)
357962306a36Sopenharmony_ci		goto out;
358062306a36Sopenharmony_ci
358162306a36Sopenharmony_ci	cfg->caps |= pcaps->caps & ICE_AQC_PHY_EN_AUTO_FEC;
358262306a36Sopenharmony_ci	cfg->link_fec_opt = pcaps->link_fec_options;
358362306a36Sopenharmony_ci
358462306a36Sopenharmony_ci	switch (fec) {
358562306a36Sopenharmony_ci	case ICE_FEC_BASER:
358662306a36Sopenharmony_ci		/* Clear RS bits, and AND BASE-R ability
358762306a36Sopenharmony_ci		 * bits and OR request bits.
358862306a36Sopenharmony_ci		 */
358962306a36Sopenharmony_ci		cfg->link_fec_opt &= ICE_AQC_PHY_FEC_10G_KR_40G_KR4_EN |
359062306a36Sopenharmony_ci			ICE_AQC_PHY_FEC_25G_KR_CLAUSE74_EN;
359162306a36Sopenharmony_ci		cfg->link_fec_opt |= ICE_AQC_PHY_FEC_10G_KR_40G_KR4_REQ |
359262306a36Sopenharmony_ci			ICE_AQC_PHY_FEC_25G_KR_REQ;
359362306a36Sopenharmony_ci		break;
359462306a36Sopenharmony_ci	case ICE_FEC_RS:
359562306a36Sopenharmony_ci		/* Clear BASE-R bits, and AND RS ability
359662306a36Sopenharmony_ci		 * bits and OR request bits.
359762306a36Sopenharmony_ci		 */
359862306a36Sopenharmony_ci		cfg->link_fec_opt &= ICE_AQC_PHY_FEC_25G_RS_CLAUSE91_EN;
359962306a36Sopenharmony_ci		cfg->link_fec_opt |= ICE_AQC_PHY_FEC_25G_RS_528_REQ |
360062306a36Sopenharmony_ci			ICE_AQC_PHY_FEC_25G_RS_544_REQ;
360162306a36Sopenharmony_ci		break;
360262306a36Sopenharmony_ci	case ICE_FEC_NONE:
360362306a36Sopenharmony_ci		/* Clear all FEC option bits. */
360462306a36Sopenharmony_ci		cfg->link_fec_opt &= ~ICE_AQC_PHY_FEC_MASK;
360562306a36Sopenharmony_ci		break;
360662306a36Sopenharmony_ci	case ICE_FEC_AUTO:
360762306a36Sopenharmony_ci		/* AND auto FEC bit, and all caps bits. */
360862306a36Sopenharmony_ci		cfg->caps &= ICE_AQC_PHY_CAPS_MASK;
360962306a36Sopenharmony_ci		cfg->link_fec_opt |= pcaps->link_fec_options;
361062306a36Sopenharmony_ci		break;
361162306a36Sopenharmony_ci	default:
361262306a36Sopenharmony_ci		status = -EINVAL;
361362306a36Sopenharmony_ci		break;
361462306a36Sopenharmony_ci	}
361562306a36Sopenharmony_ci
361662306a36Sopenharmony_ci	if (fec == ICE_FEC_AUTO && ice_fw_supports_link_override(hw) &&
361762306a36Sopenharmony_ci	    !ice_fw_supports_report_dflt_cfg(hw)) {
361862306a36Sopenharmony_ci		struct ice_link_default_override_tlv tlv = { 0 };
361962306a36Sopenharmony_ci
362062306a36Sopenharmony_ci		status = ice_get_link_default_override(&tlv, pi);
362162306a36Sopenharmony_ci		if (status)
362262306a36Sopenharmony_ci			goto out;
362362306a36Sopenharmony_ci
362462306a36Sopenharmony_ci		if (!(tlv.options & ICE_LINK_OVERRIDE_STRICT_MODE) &&
362562306a36Sopenharmony_ci		    (tlv.options & ICE_LINK_OVERRIDE_EN))
362662306a36Sopenharmony_ci			cfg->link_fec_opt = tlv.fec_options;
362762306a36Sopenharmony_ci	}
362862306a36Sopenharmony_ci
362962306a36Sopenharmony_ciout:
363062306a36Sopenharmony_ci	kfree(pcaps);
363162306a36Sopenharmony_ci
363262306a36Sopenharmony_ci	return status;
363362306a36Sopenharmony_ci}
363462306a36Sopenharmony_ci
363562306a36Sopenharmony_ci/**
363662306a36Sopenharmony_ci * ice_get_link_status - get status of the HW network link
363762306a36Sopenharmony_ci * @pi: port information structure
363862306a36Sopenharmony_ci * @link_up: pointer to bool (true/false = linkup/linkdown)
363962306a36Sopenharmony_ci *
364062306a36Sopenharmony_ci * Variable link_up is true if link is up, false if link is down.
364162306a36Sopenharmony_ci * The variable link_up is invalid if status is non zero. As a
364262306a36Sopenharmony_ci * result of this call, link status reporting becomes enabled
364362306a36Sopenharmony_ci */
364462306a36Sopenharmony_ciint ice_get_link_status(struct ice_port_info *pi, bool *link_up)
364562306a36Sopenharmony_ci{
364662306a36Sopenharmony_ci	struct ice_phy_info *phy_info;
364762306a36Sopenharmony_ci	int status = 0;
364862306a36Sopenharmony_ci
364962306a36Sopenharmony_ci	if (!pi || !link_up)
365062306a36Sopenharmony_ci		return -EINVAL;
365162306a36Sopenharmony_ci
365262306a36Sopenharmony_ci	phy_info = &pi->phy;
365362306a36Sopenharmony_ci
365462306a36Sopenharmony_ci	if (phy_info->get_link_info) {
365562306a36Sopenharmony_ci		status = ice_update_link_info(pi);
365662306a36Sopenharmony_ci
365762306a36Sopenharmony_ci		if (status)
365862306a36Sopenharmony_ci			ice_debug(pi->hw, ICE_DBG_LINK, "get link status error, status = %d\n",
365962306a36Sopenharmony_ci				  status);
366062306a36Sopenharmony_ci	}
366162306a36Sopenharmony_ci
366262306a36Sopenharmony_ci	*link_up = phy_info->link_info.link_info & ICE_AQ_LINK_UP;
366362306a36Sopenharmony_ci
366462306a36Sopenharmony_ci	return status;
366562306a36Sopenharmony_ci}
366662306a36Sopenharmony_ci
366762306a36Sopenharmony_ci/**
366862306a36Sopenharmony_ci * ice_aq_set_link_restart_an
366962306a36Sopenharmony_ci * @pi: pointer to the port information structure
367062306a36Sopenharmony_ci * @ena_link: if true: enable link, if false: disable link
367162306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL
367262306a36Sopenharmony_ci *
367362306a36Sopenharmony_ci * Sets up the link and restarts the Auto-Negotiation over the link.
367462306a36Sopenharmony_ci */
367562306a36Sopenharmony_ciint
367662306a36Sopenharmony_ciice_aq_set_link_restart_an(struct ice_port_info *pi, bool ena_link,
367762306a36Sopenharmony_ci			   struct ice_sq_cd *cd)
367862306a36Sopenharmony_ci{
367962306a36Sopenharmony_ci	struct ice_aqc_restart_an *cmd;
368062306a36Sopenharmony_ci	struct ice_aq_desc desc;
368162306a36Sopenharmony_ci
368262306a36Sopenharmony_ci	cmd = &desc.params.restart_an;
368362306a36Sopenharmony_ci
368462306a36Sopenharmony_ci	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_restart_an);
368562306a36Sopenharmony_ci
368662306a36Sopenharmony_ci	cmd->cmd_flags = ICE_AQC_RESTART_AN_LINK_RESTART;
368762306a36Sopenharmony_ci	cmd->lport_num = pi->lport;
368862306a36Sopenharmony_ci	if (ena_link)
368962306a36Sopenharmony_ci		cmd->cmd_flags |= ICE_AQC_RESTART_AN_LINK_ENABLE;
369062306a36Sopenharmony_ci	else
369162306a36Sopenharmony_ci		cmd->cmd_flags &= ~ICE_AQC_RESTART_AN_LINK_ENABLE;
369262306a36Sopenharmony_ci
369362306a36Sopenharmony_ci	return ice_aq_send_cmd(pi->hw, &desc, NULL, 0, cd);
369462306a36Sopenharmony_ci}
369562306a36Sopenharmony_ci
369662306a36Sopenharmony_ci/**
369762306a36Sopenharmony_ci * ice_aq_set_event_mask
369862306a36Sopenharmony_ci * @hw: pointer to the HW struct
369962306a36Sopenharmony_ci * @port_num: port number of the physical function
370062306a36Sopenharmony_ci * @mask: event mask to be set
370162306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL
370262306a36Sopenharmony_ci *
370362306a36Sopenharmony_ci * Set event mask (0x0613)
370462306a36Sopenharmony_ci */
370562306a36Sopenharmony_ciint
370662306a36Sopenharmony_ciice_aq_set_event_mask(struct ice_hw *hw, u8 port_num, u16 mask,
370762306a36Sopenharmony_ci		      struct ice_sq_cd *cd)
370862306a36Sopenharmony_ci{
370962306a36Sopenharmony_ci	struct ice_aqc_set_event_mask *cmd;
371062306a36Sopenharmony_ci	struct ice_aq_desc desc;
371162306a36Sopenharmony_ci
371262306a36Sopenharmony_ci	cmd = &desc.params.set_event_mask;
371362306a36Sopenharmony_ci
371462306a36Sopenharmony_ci	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_event_mask);
371562306a36Sopenharmony_ci
371662306a36Sopenharmony_ci	cmd->lport_num = port_num;
371762306a36Sopenharmony_ci
371862306a36Sopenharmony_ci	cmd->event_mask = cpu_to_le16(mask);
371962306a36Sopenharmony_ci	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
372062306a36Sopenharmony_ci}
372162306a36Sopenharmony_ci
372262306a36Sopenharmony_ci/**
372362306a36Sopenharmony_ci * ice_aq_set_mac_loopback
372462306a36Sopenharmony_ci * @hw: pointer to the HW struct
372562306a36Sopenharmony_ci * @ena_lpbk: Enable or Disable loopback
372662306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL
372762306a36Sopenharmony_ci *
372862306a36Sopenharmony_ci * Enable/disable loopback on a given port
372962306a36Sopenharmony_ci */
373062306a36Sopenharmony_ciint
373162306a36Sopenharmony_ciice_aq_set_mac_loopback(struct ice_hw *hw, bool ena_lpbk, struct ice_sq_cd *cd)
373262306a36Sopenharmony_ci{
373362306a36Sopenharmony_ci	struct ice_aqc_set_mac_lb *cmd;
373462306a36Sopenharmony_ci	struct ice_aq_desc desc;
373562306a36Sopenharmony_ci
373662306a36Sopenharmony_ci	cmd = &desc.params.set_mac_lb;
373762306a36Sopenharmony_ci
373862306a36Sopenharmony_ci	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_mac_lb);
373962306a36Sopenharmony_ci	if (ena_lpbk)
374062306a36Sopenharmony_ci		cmd->lb_mode = ICE_AQ_MAC_LB_EN;
374162306a36Sopenharmony_ci
374262306a36Sopenharmony_ci	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
374362306a36Sopenharmony_ci}
374462306a36Sopenharmony_ci
374562306a36Sopenharmony_ci/**
374662306a36Sopenharmony_ci * ice_aq_set_port_id_led
374762306a36Sopenharmony_ci * @pi: pointer to the port information
374862306a36Sopenharmony_ci * @is_orig_mode: is this LED set to original mode (by the net-list)
374962306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL
375062306a36Sopenharmony_ci *
375162306a36Sopenharmony_ci * Set LED value for the given port (0x06e9)
375262306a36Sopenharmony_ci */
375362306a36Sopenharmony_ciint
375462306a36Sopenharmony_ciice_aq_set_port_id_led(struct ice_port_info *pi, bool is_orig_mode,
375562306a36Sopenharmony_ci		       struct ice_sq_cd *cd)
375662306a36Sopenharmony_ci{
375762306a36Sopenharmony_ci	struct ice_aqc_set_port_id_led *cmd;
375862306a36Sopenharmony_ci	struct ice_hw *hw = pi->hw;
375962306a36Sopenharmony_ci	struct ice_aq_desc desc;
376062306a36Sopenharmony_ci
376162306a36Sopenharmony_ci	cmd = &desc.params.set_port_id_led;
376262306a36Sopenharmony_ci
376362306a36Sopenharmony_ci	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_port_id_led);
376462306a36Sopenharmony_ci
376562306a36Sopenharmony_ci	if (is_orig_mode)
376662306a36Sopenharmony_ci		cmd->ident_mode = ICE_AQC_PORT_IDENT_LED_ORIG;
376762306a36Sopenharmony_ci	else
376862306a36Sopenharmony_ci		cmd->ident_mode = ICE_AQC_PORT_IDENT_LED_BLINK;
376962306a36Sopenharmony_ci
377062306a36Sopenharmony_ci	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
377162306a36Sopenharmony_ci}
377262306a36Sopenharmony_ci
377362306a36Sopenharmony_ci/**
377462306a36Sopenharmony_ci * ice_aq_get_port_options
377562306a36Sopenharmony_ci * @hw: pointer to the HW struct
377662306a36Sopenharmony_ci * @options: buffer for the resultant port options
377762306a36Sopenharmony_ci * @option_count: input - size of the buffer in port options structures,
377862306a36Sopenharmony_ci *                output - number of returned port options
377962306a36Sopenharmony_ci * @lport: logical port to call the command with (optional)
378062306a36Sopenharmony_ci * @lport_valid: when false, FW uses port owned by the PF instead of lport,
378162306a36Sopenharmony_ci *               when PF owns more than 1 port it must be true
378262306a36Sopenharmony_ci * @active_option_idx: index of active port option in returned buffer
378362306a36Sopenharmony_ci * @active_option_valid: active option in returned buffer is valid
378462306a36Sopenharmony_ci * @pending_option_idx: index of pending port option in returned buffer
378562306a36Sopenharmony_ci * @pending_option_valid: pending option in returned buffer is valid
378662306a36Sopenharmony_ci *
378762306a36Sopenharmony_ci * Calls Get Port Options AQC (0x06ea) and verifies result.
378862306a36Sopenharmony_ci */
378962306a36Sopenharmony_ciint
379062306a36Sopenharmony_ciice_aq_get_port_options(struct ice_hw *hw,
379162306a36Sopenharmony_ci			struct ice_aqc_get_port_options_elem *options,
379262306a36Sopenharmony_ci			u8 *option_count, u8 lport, bool lport_valid,
379362306a36Sopenharmony_ci			u8 *active_option_idx, bool *active_option_valid,
379462306a36Sopenharmony_ci			u8 *pending_option_idx, bool *pending_option_valid)
379562306a36Sopenharmony_ci{
379662306a36Sopenharmony_ci	struct ice_aqc_get_port_options *cmd;
379762306a36Sopenharmony_ci	struct ice_aq_desc desc;
379862306a36Sopenharmony_ci	int status;
379962306a36Sopenharmony_ci	u8 i;
380062306a36Sopenharmony_ci
380162306a36Sopenharmony_ci	/* options buffer shall be able to hold max returned options */
380262306a36Sopenharmony_ci	if (*option_count < ICE_AQC_PORT_OPT_COUNT_M)
380362306a36Sopenharmony_ci		return -EINVAL;
380462306a36Sopenharmony_ci
380562306a36Sopenharmony_ci	cmd = &desc.params.get_port_options;
380662306a36Sopenharmony_ci	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_port_options);
380762306a36Sopenharmony_ci
380862306a36Sopenharmony_ci	if (lport_valid)
380962306a36Sopenharmony_ci		cmd->lport_num = lport;
381062306a36Sopenharmony_ci	cmd->lport_num_valid = lport_valid;
381162306a36Sopenharmony_ci
381262306a36Sopenharmony_ci	status = ice_aq_send_cmd(hw, &desc, options,
381362306a36Sopenharmony_ci				 *option_count * sizeof(*options), NULL);
381462306a36Sopenharmony_ci	if (status)
381562306a36Sopenharmony_ci		return status;
381662306a36Sopenharmony_ci
381762306a36Sopenharmony_ci	/* verify direct FW response & set output parameters */
381862306a36Sopenharmony_ci	*option_count = FIELD_GET(ICE_AQC_PORT_OPT_COUNT_M,
381962306a36Sopenharmony_ci				  cmd->port_options_count);
382062306a36Sopenharmony_ci	ice_debug(hw, ICE_DBG_PHY, "options: %x\n", *option_count);
382162306a36Sopenharmony_ci	*active_option_valid = FIELD_GET(ICE_AQC_PORT_OPT_VALID,
382262306a36Sopenharmony_ci					 cmd->port_options);
382362306a36Sopenharmony_ci	if (*active_option_valid) {
382462306a36Sopenharmony_ci		*active_option_idx = FIELD_GET(ICE_AQC_PORT_OPT_ACTIVE_M,
382562306a36Sopenharmony_ci					       cmd->port_options);
382662306a36Sopenharmony_ci		if (*active_option_idx > (*option_count - 1))
382762306a36Sopenharmony_ci			return -EIO;
382862306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_PHY, "active idx: %x\n",
382962306a36Sopenharmony_ci			  *active_option_idx);
383062306a36Sopenharmony_ci	}
383162306a36Sopenharmony_ci
383262306a36Sopenharmony_ci	*pending_option_valid = FIELD_GET(ICE_AQC_PENDING_PORT_OPT_VALID,
383362306a36Sopenharmony_ci					  cmd->pending_port_option_status);
383462306a36Sopenharmony_ci	if (*pending_option_valid) {
383562306a36Sopenharmony_ci		*pending_option_idx = FIELD_GET(ICE_AQC_PENDING_PORT_OPT_IDX_M,
383662306a36Sopenharmony_ci						cmd->pending_port_option_status);
383762306a36Sopenharmony_ci		if (*pending_option_idx > (*option_count - 1))
383862306a36Sopenharmony_ci			return -EIO;
383962306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_PHY, "pending idx: %x\n",
384062306a36Sopenharmony_ci			  *pending_option_idx);
384162306a36Sopenharmony_ci	}
384262306a36Sopenharmony_ci
384362306a36Sopenharmony_ci	/* mask output options fields */
384462306a36Sopenharmony_ci	for (i = 0; i < *option_count; i++) {
384562306a36Sopenharmony_ci		options[i].pmd = FIELD_GET(ICE_AQC_PORT_OPT_PMD_COUNT_M,
384662306a36Sopenharmony_ci					   options[i].pmd);
384762306a36Sopenharmony_ci		options[i].max_lane_speed = FIELD_GET(ICE_AQC_PORT_OPT_MAX_LANE_M,
384862306a36Sopenharmony_ci						      options[i].max_lane_speed);
384962306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_PHY, "pmds: %x max speed: %x\n",
385062306a36Sopenharmony_ci			  options[i].pmd, options[i].max_lane_speed);
385162306a36Sopenharmony_ci	}
385262306a36Sopenharmony_ci
385362306a36Sopenharmony_ci	return 0;
385462306a36Sopenharmony_ci}
385562306a36Sopenharmony_ci
385662306a36Sopenharmony_ci/**
385762306a36Sopenharmony_ci * ice_aq_set_port_option
385862306a36Sopenharmony_ci * @hw: pointer to the HW struct
385962306a36Sopenharmony_ci * @lport: logical port to call the command with
386062306a36Sopenharmony_ci * @lport_valid: when false, FW uses port owned by the PF instead of lport,
386162306a36Sopenharmony_ci *               when PF owns more than 1 port it must be true
386262306a36Sopenharmony_ci * @new_option: new port option to be written
386362306a36Sopenharmony_ci *
386462306a36Sopenharmony_ci * Calls Set Port Options AQC (0x06eb).
386562306a36Sopenharmony_ci */
386662306a36Sopenharmony_ciint
386762306a36Sopenharmony_ciice_aq_set_port_option(struct ice_hw *hw, u8 lport, u8 lport_valid,
386862306a36Sopenharmony_ci		       u8 new_option)
386962306a36Sopenharmony_ci{
387062306a36Sopenharmony_ci	struct ice_aqc_set_port_option *cmd;
387162306a36Sopenharmony_ci	struct ice_aq_desc desc;
387262306a36Sopenharmony_ci
387362306a36Sopenharmony_ci	if (new_option > ICE_AQC_PORT_OPT_COUNT_M)
387462306a36Sopenharmony_ci		return -EINVAL;
387562306a36Sopenharmony_ci
387662306a36Sopenharmony_ci	cmd = &desc.params.set_port_option;
387762306a36Sopenharmony_ci	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_port_option);
387862306a36Sopenharmony_ci
387962306a36Sopenharmony_ci	if (lport_valid)
388062306a36Sopenharmony_ci		cmd->lport_num = lport;
388162306a36Sopenharmony_ci
388262306a36Sopenharmony_ci	cmd->lport_num_valid = lport_valid;
388362306a36Sopenharmony_ci	cmd->selected_port_option = new_option;
388462306a36Sopenharmony_ci
388562306a36Sopenharmony_ci	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
388662306a36Sopenharmony_ci}
388762306a36Sopenharmony_ci
388862306a36Sopenharmony_ci/**
388962306a36Sopenharmony_ci * ice_aq_sff_eeprom
389062306a36Sopenharmony_ci * @hw: pointer to the HW struct
389162306a36Sopenharmony_ci * @lport: bits [7:0] = logical port, bit [8] = logical port valid
389262306a36Sopenharmony_ci * @bus_addr: I2C bus address of the eeprom (typically 0xA0, 0=topo default)
389362306a36Sopenharmony_ci * @mem_addr: I2C offset. lower 8 bits for address, 8 upper bits zero padding.
389462306a36Sopenharmony_ci * @page: QSFP page
389562306a36Sopenharmony_ci * @set_page: set or ignore the page
389662306a36Sopenharmony_ci * @data: pointer to data buffer to be read/written to the I2C device.
389762306a36Sopenharmony_ci * @length: 1-16 for read, 1 for write.
389862306a36Sopenharmony_ci * @write: 0 read, 1 for write.
389962306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL
390062306a36Sopenharmony_ci *
390162306a36Sopenharmony_ci * Read/Write SFF EEPROM (0x06EE)
390262306a36Sopenharmony_ci */
390362306a36Sopenharmony_ciint
390462306a36Sopenharmony_ciice_aq_sff_eeprom(struct ice_hw *hw, u16 lport, u8 bus_addr,
390562306a36Sopenharmony_ci		  u16 mem_addr, u8 page, u8 set_page, u8 *data, u8 length,
390662306a36Sopenharmony_ci		  bool write, struct ice_sq_cd *cd)
390762306a36Sopenharmony_ci{
390862306a36Sopenharmony_ci	struct ice_aqc_sff_eeprom *cmd;
390962306a36Sopenharmony_ci	struct ice_aq_desc desc;
391062306a36Sopenharmony_ci	int status;
391162306a36Sopenharmony_ci
391262306a36Sopenharmony_ci	if (!data || (mem_addr & 0xff00))
391362306a36Sopenharmony_ci		return -EINVAL;
391462306a36Sopenharmony_ci
391562306a36Sopenharmony_ci	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_sff_eeprom);
391662306a36Sopenharmony_ci	cmd = &desc.params.read_write_sff_param;
391762306a36Sopenharmony_ci	desc.flags = cpu_to_le16(ICE_AQ_FLAG_RD);
391862306a36Sopenharmony_ci	cmd->lport_num = (u8)(lport & 0xff);
391962306a36Sopenharmony_ci	cmd->lport_num_valid = (u8)((lport >> 8) & 0x01);
392062306a36Sopenharmony_ci	cmd->i2c_bus_addr = cpu_to_le16(((bus_addr >> 1) &
392162306a36Sopenharmony_ci					 ICE_AQC_SFF_I2CBUS_7BIT_M) |
392262306a36Sopenharmony_ci					((set_page <<
392362306a36Sopenharmony_ci					  ICE_AQC_SFF_SET_EEPROM_PAGE_S) &
392462306a36Sopenharmony_ci					 ICE_AQC_SFF_SET_EEPROM_PAGE_M));
392562306a36Sopenharmony_ci	cmd->i2c_mem_addr = cpu_to_le16(mem_addr & 0xff);
392662306a36Sopenharmony_ci	cmd->eeprom_page = cpu_to_le16((u16)page << ICE_AQC_SFF_EEPROM_PAGE_S);
392762306a36Sopenharmony_ci	if (write)
392862306a36Sopenharmony_ci		cmd->i2c_bus_addr |= cpu_to_le16(ICE_AQC_SFF_IS_WRITE);
392962306a36Sopenharmony_ci
393062306a36Sopenharmony_ci	status = ice_aq_send_cmd(hw, &desc, data, length, cd);
393162306a36Sopenharmony_ci	return status;
393262306a36Sopenharmony_ci}
393362306a36Sopenharmony_ci
393462306a36Sopenharmony_cistatic enum ice_lut_size ice_lut_type_to_size(enum ice_lut_type type)
393562306a36Sopenharmony_ci{
393662306a36Sopenharmony_ci	switch (type) {
393762306a36Sopenharmony_ci	case ICE_LUT_VSI:
393862306a36Sopenharmony_ci		return ICE_LUT_VSI_SIZE;
393962306a36Sopenharmony_ci	case ICE_LUT_GLOBAL:
394062306a36Sopenharmony_ci		return ICE_LUT_GLOBAL_SIZE;
394162306a36Sopenharmony_ci	case ICE_LUT_PF:
394262306a36Sopenharmony_ci		return ICE_LUT_PF_SIZE;
394362306a36Sopenharmony_ci	}
394462306a36Sopenharmony_ci	WARN_ONCE(1, "incorrect type passed");
394562306a36Sopenharmony_ci	return ICE_LUT_VSI_SIZE;
394662306a36Sopenharmony_ci}
394762306a36Sopenharmony_ci
394862306a36Sopenharmony_cistatic enum ice_aqc_lut_flags ice_lut_size_to_flag(enum ice_lut_size size)
394962306a36Sopenharmony_ci{
395062306a36Sopenharmony_ci	switch (size) {
395162306a36Sopenharmony_ci	case ICE_LUT_VSI_SIZE:
395262306a36Sopenharmony_ci		return ICE_AQC_LUT_SIZE_SMALL;
395362306a36Sopenharmony_ci	case ICE_LUT_GLOBAL_SIZE:
395462306a36Sopenharmony_ci		return ICE_AQC_LUT_SIZE_512;
395562306a36Sopenharmony_ci	case ICE_LUT_PF_SIZE:
395662306a36Sopenharmony_ci		return ICE_AQC_LUT_SIZE_2K;
395762306a36Sopenharmony_ci	}
395862306a36Sopenharmony_ci	WARN_ONCE(1, "incorrect size passed");
395962306a36Sopenharmony_ci	return 0;
396062306a36Sopenharmony_ci}
396162306a36Sopenharmony_ci
396262306a36Sopenharmony_ci/**
396362306a36Sopenharmony_ci * __ice_aq_get_set_rss_lut
396462306a36Sopenharmony_ci * @hw: pointer to the hardware structure
396562306a36Sopenharmony_ci * @params: RSS LUT parameters
396662306a36Sopenharmony_ci * @set: set true to set the table, false to get the table
396762306a36Sopenharmony_ci *
396862306a36Sopenharmony_ci * Internal function to get (0x0B05) or set (0x0B03) RSS look up table
396962306a36Sopenharmony_ci */
397062306a36Sopenharmony_cistatic int
397162306a36Sopenharmony_ci__ice_aq_get_set_rss_lut(struct ice_hw *hw,
397262306a36Sopenharmony_ci			 struct ice_aq_get_set_rss_lut_params *params, bool set)
397362306a36Sopenharmony_ci{
397462306a36Sopenharmony_ci	u16 opcode, vsi_id, vsi_handle = params->vsi_handle, glob_lut_idx = 0;
397562306a36Sopenharmony_ci	enum ice_lut_type lut_type = params->lut_type;
397662306a36Sopenharmony_ci	struct ice_aqc_get_set_rss_lut *desc_params;
397762306a36Sopenharmony_ci	enum ice_aqc_lut_flags flags;
397862306a36Sopenharmony_ci	enum ice_lut_size lut_size;
397962306a36Sopenharmony_ci	struct ice_aq_desc desc;
398062306a36Sopenharmony_ci	u8 *lut = params->lut;
398162306a36Sopenharmony_ci
398262306a36Sopenharmony_ci
398362306a36Sopenharmony_ci	if (!lut || !ice_is_vsi_valid(hw, vsi_handle))
398462306a36Sopenharmony_ci		return -EINVAL;
398562306a36Sopenharmony_ci
398662306a36Sopenharmony_ci	lut_size = ice_lut_type_to_size(lut_type);
398762306a36Sopenharmony_ci	if (lut_size > params->lut_size)
398862306a36Sopenharmony_ci		return -EINVAL;
398962306a36Sopenharmony_ci	else if (set && lut_size != params->lut_size)
399062306a36Sopenharmony_ci		return -EINVAL;
399162306a36Sopenharmony_ci
399262306a36Sopenharmony_ci	opcode = set ? ice_aqc_opc_set_rss_lut : ice_aqc_opc_get_rss_lut;
399362306a36Sopenharmony_ci	ice_fill_dflt_direct_cmd_desc(&desc, opcode);
399462306a36Sopenharmony_ci	if (set)
399562306a36Sopenharmony_ci		desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
399662306a36Sopenharmony_ci
399762306a36Sopenharmony_ci	desc_params = &desc.params.get_set_rss_lut;
399862306a36Sopenharmony_ci	vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
399962306a36Sopenharmony_ci	desc_params->vsi_id = cpu_to_le16(vsi_id | ICE_AQC_RSS_VSI_VALID);
400062306a36Sopenharmony_ci
400162306a36Sopenharmony_ci	if (lut_type == ICE_LUT_GLOBAL)
400262306a36Sopenharmony_ci		glob_lut_idx = FIELD_PREP(ICE_AQC_LUT_GLOBAL_IDX,
400362306a36Sopenharmony_ci					  params->global_lut_id);
400462306a36Sopenharmony_ci
400562306a36Sopenharmony_ci	flags = lut_type | glob_lut_idx | ice_lut_size_to_flag(lut_size);
400662306a36Sopenharmony_ci	desc_params->flags = cpu_to_le16(flags);
400762306a36Sopenharmony_ci
400862306a36Sopenharmony_ci	return ice_aq_send_cmd(hw, &desc, lut, lut_size, NULL);
400962306a36Sopenharmony_ci}
401062306a36Sopenharmony_ci
401162306a36Sopenharmony_ci/**
401262306a36Sopenharmony_ci * ice_aq_get_rss_lut
401362306a36Sopenharmony_ci * @hw: pointer to the hardware structure
401462306a36Sopenharmony_ci * @get_params: RSS LUT parameters used to specify which RSS LUT to get
401562306a36Sopenharmony_ci *
401662306a36Sopenharmony_ci * get the RSS lookup table, PF or VSI type
401762306a36Sopenharmony_ci */
401862306a36Sopenharmony_ciint
401962306a36Sopenharmony_ciice_aq_get_rss_lut(struct ice_hw *hw, struct ice_aq_get_set_rss_lut_params *get_params)
402062306a36Sopenharmony_ci{
402162306a36Sopenharmony_ci	return __ice_aq_get_set_rss_lut(hw, get_params, false);
402262306a36Sopenharmony_ci}
402362306a36Sopenharmony_ci
402462306a36Sopenharmony_ci/**
402562306a36Sopenharmony_ci * ice_aq_set_rss_lut
402662306a36Sopenharmony_ci * @hw: pointer to the hardware structure
402762306a36Sopenharmony_ci * @set_params: RSS LUT parameters used to specify how to set the RSS LUT
402862306a36Sopenharmony_ci *
402962306a36Sopenharmony_ci * set the RSS lookup table, PF or VSI type
403062306a36Sopenharmony_ci */
403162306a36Sopenharmony_ciint
403262306a36Sopenharmony_ciice_aq_set_rss_lut(struct ice_hw *hw, struct ice_aq_get_set_rss_lut_params *set_params)
403362306a36Sopenharmony_ci{
403462306a36Sopenharmony_ci	return __ice_aq_get_set_rss_lut(hw, set_params, true);
403562306a36Sopenharmony_ci}
403662306a36Sopenharmony_ci
403762306a36Sopenharmony_ci/**
403862306a36Sopenharmony_ci * __ice_aq_get_set_rss_key
403962306a36Sopenharmony_ci * @hw: pointer to the HW struct
404062306a36Sopenharmony_ci * @vsi_id: VSI FW index
404162306a36Sopenharmony_ci * @key: pointer to key info struct
404262306a36Sopenharmony_ci * @set: set true to set the key, false to get the key
404362306a36Sopenharmony_ci *
404462306a36Sopenharmony_ci * get (0x0B04) or set (0x0B02) the RSS key per VSI
404562306a36Sopenharmony_ci */
404662306a36Sopenharmony_cistatic int
404762306a36Sopenharmony_ci__ice_aq_get_set_rss_key(struct ice_hw *hw, u16 vsi_id,
404862306a36Sopenharmony_ci			 struct ice_aqc_get_set_rss_keys *key, bool set)
404962306a36Sopenharmony_ci{
405062306a36Sopenharmony_ci	struct ice_aqc_get_set_rss_key *desc_params;
405162306a36Sopenharmony_ci	u16 key_size = sizeof(*key);
405262306a36Sopenharmony_ci	struct ice_aq_desc desc;
405362306a36Sopenharmony_ci
405462306a36Sopenharmony_ci	if (set) {
405562306a36Sopenharmony_ci		ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_rss_key);
405662306a36Sopenharmony_ci		desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
405762306a36Sopenharmony_ci	} else {
405862306a36Sopenharmony_ci		ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_rss_key);
405962306a36Sopenharmony_ci	}
406062306a36Sopenharmony_ci
406162306a36Sopenharmony_ci	desc_params = &desc.params.get_set_rss_key;
406262306a36Sopenharmony_ci	desc_params->vsi_id = cpu_to_le16(vsi_id | ICE_AQC_RSS_VSI_VALID);
406362306a36Sopenharmony_ci
406462306a36Sopenharmony_ci	return ice_aq_send_cmd(hw, &desc, key, key_size, NULL);
406562306a36Sopenharmony_ci}
406662306a36Sopenharmony_ci
406762306a36Sopenharmony_ci/**
406862306a36Sopenharmony_ci * ice_aq_get_rss_key
406962306a36Sopenharmony_ci * @hw: pointer to the HW struct
407062306a36Sopenharmony_ci * @vsi_handle: software VSI handle
407162306a36Sopenharmony_ci * @key: pointer to key info struct
407262306a36Sopenharmony_ci *
407362306a36Sopenharmony_ci * get the RSS key per VSI
407462306a36Sopenharmony_ci */
407562306a36Sopenharmony_ciint
407662306a36Sopenharmony_ciice_aq_get_rss_key(struct ice_hw *hw, u16 vsi_handle,
407762306a36Sopenharmony_ci		   struct ice_aqc_get_set_rss_keys *key)
407862306a36Sopenharmony_ci{
407962306a36Sopenharmony_ci	if (!ice_is_vsi_valid(hw, vsi_handle) || !key)
408062306a36Sopenharmony_ci		return -EINVAL;
408162306a36Sopenharmony_ci
408262306a36Sopenharmony_ci	return __ice_aq_get_set_rss_key(hw, ice_get_hw_vsi_num(hw, vsi_handle),
408362306a36Sopenharmony_ci					key, false);
408462306a36Sopenharmony_ci}
408562306a36Sopenharmony_ci
408662306a36Sopenharmony_ci/**
408762306a36Sopenharmony_ci * ice_aq_set_rss_key
408862306a36Sopenharmony_ci * @hw: pointer to the HW struct
408962306a36Sopenharmony_ci * @vsi_handle: software VSI handle
409062306a36Sopenharmony_ci * @keys: pointer to key info struct
409162306a36Sopenharmony_ci *
409262306a36Sopenharmony_ci * set the RSS key per VSI
409362306a36Sopenharmony_ci */
409462306a36Sopenharmony_ciint
409562306a36Sopenharmony_ciice_aq_set_rss_key(struct ice_hw *hw, u16 vsi_handle,
409662306a36Sopenharmony_ci		   struct ice_aqc_get_set_rss_keys *keys)
409762306a36Sopenharmony_ci{
409862306a36Sopenharmony_ci	if (!ice_is_vsi_valid(hw, vsi_handle) || !keys)
409962306a36Sopenharmony_ci		return -EINVAL;
410062306a36Sopenharmony_ci
410162306a36Sopenharmony_ci	return __ice_aq_get_set_rss_key(hw, ice_get_hw_vsi_num(hw, vsi_handle),
410262306a36Sopenharmony_ci					keys, true);
410362306a36Sopenharmony_ci}
410462306a36Sopenharmony_ci
410562306a36Sopenharmony_ci/**
410662306a36Sopenharmony_ci * ice_aq_add_lan_txq
410762306a36Sopenharmony_ci * @hw: pointer to the hardware structure
410862306a36Sopenharmony_ci * @num_qgrps: Number of added queue groups
410962306a36Sopenharmony_ci * @qg_list: list of queue groups to be added
411062306a36Sopenharmony_ci * @buf_size: size of buffer for indirect command
411162306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL
411262306a36Sopenharmony_ci *
411362306a36Sopenharmony_ci * Add Tx LAN queue (0x0C30)
411462306a36Sopenharmony_ci *
411562306a36Sopenharmony_ci * NOTE:
411662306a36Sopenharmony_ci * Prior to calling add Tx LAN queue:
411762306a36Sopenharmony_ci * Initialize the following as part of the Tx queue context:
411862306a36Sopenharmony_ci * Completion queue ID if the queue uses Completion queue, Quanta profile,
411962306a36Sopenharmony_ci * Cache profile and Packet shaper profile.
412062306a36Sopenharmony_ci *
412162306a36Sopenharmony_ci * After add Tx LAN queue AQ command is completed:
412262306a36Sopenharmony_ci * Interrupts should be associated with specific queues,
412362306a36Sopenharmony_ci * Association of Tx queue to Doorbell queue is not part of Add LAN Tx queue
412462306a36Sopenharmony_ci * flow.
412562306a36Sopenharmony_ci */
412662306a36Sopenharmony_cistatic int
412762306a36Sopenharmony_ciice_aq_add_lan_txq(struct ice_hw *hw, u8 num_qgrps,
412862306a36Sopenharmony_ci		   struct ice_aqc_add_tx_qgrp *qg_list, u16 buf_size,
412962306a36Sopenharmony_ci		   struct ice_sq_cd *cd)
413062306a36Sopenharmony_ci{
413162306a36Sopenharmony_ci	struct ice_aqc_add_tx_qgrp *list;
413262306a36Sopenharmony_ci	struct ice_aqc_add_txqs *cmd;
413362306a36Sopenharmony_ci	struct ice_aq_desc desc;
413462306a36Sopenharmony_ci	u16 i, sum_size = 0;
413562306a36Sopenharmony_ci
413662306a36Sopenharmony_ci	cmd = &desc.params.add_txqs;
413762306a36Sopenharmony_ci
413862306a36Sopenharmony_ci	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_txqs);
413962306a36Sopenharmony_ci
414062306a36Sopenharmony_ci	if (!qg_list)
414162306a36Sopenharmony_ci		return -EINVAL;
414262306a36Sopenharmony_ci
414362306a36Sopenharmony_ci	if (num_qgrps > ICE_LAN_TXQ_MAX_QGRPS)
414462306a36Sopenharmony_ci		return -EINVAL;
414562306a36Sopenharmony_ci
414662306a36Sopenharmony_ci	for (i = 0, list = qg_list; i < num_qgrps; i++) {
414762306a36Sopenharmony_ci		sum_size += struct_size(list, txqs, list->num_txqs);
414862306a36Sopenharmony_ci		list = (struct ice_aqc_add_tx_qgrp *)(list->txqs +
414962306a36Sopenharmony_ci						      list->num_txqs);
415062306a36Sopenharmony_ci	}
415162306a36Sopenharmony_ci
415262306a36Sopenharmony_ci	if (buf_size != sum_size)
415362306a36Sopenharmony_ci		return -EINVAL;
415462306a36Sopenharmony_ci
415562306a36Sopenharmony_ci	desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
415662306a36Sopenharmony_ci
415762306a36Sopenharmony_ci	cmd->num_qgrps = num_qgrps;
415862306a36Sopenharmony_ci
415962306a36Sopenharmony_ci	return ice_aq_send_cmd(hw, &desc, qg_list, buf_size, cd);
416062306a36Sopenharmony_ci}
416162306a36Sopenharmony_ci
416262306a36Sopenharmony_ci/**
416362306a36Sopenharmony_ci * ice_aq_dis_lan_txq
416462306a36Sopenharmony_ci * @hw: pointer to the hardware structure
416562306a36Sopenharmony_ci * @num_qgrps: number of groups in the list
416662306a36Sopenharmony_ci * @qg_list: the list of groups to disable
416762306a36Sopenharmony_ci * @buf_size: the total size of the qg_list buffer in bytes
416862306a36Sopenharmony_ci * @rst_src: if called due to reset, specifies the reset source
416962306a36Sopenharmony_ci * @vmvf_num: the relative VM or VF number that is undergoing the reset
417062306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL
417162306a36Sopenharmony_ci *
417262306a36Sopenharmony_ci * Disable LAN Tx queue (0x0C31)
417362306a36Sopenharmony_ci */
417462306a36Sopenharmony_cistatic int
417562306a36Sopenharmony_ciice_aq_dis_lan_txq(struct ice_hw *hw, u8 num_qgrps,
417662306a36Sopenharmony_ci		   struct ice_aqc_dis_txq_item *qg_list, u16 buf_size,
417762306a36Sopenharmony_ci		   enum ice_disq_rst_src rst_src, u16 vmvf_num,
417862306a36Sopenharmony_ci		   struct ice_sq_cd *cd)
417962306a36Sopenharmony_ci{
418062306a36Sopenharmony_ci	struct ice_aqc_dis_txq_item *item;
418162306a36Sopenharmony_ci	struct ice_aqc_dis_txqs *cmd;
418262306a36Sopenharmony_ci	struct ice_aq_desc desc;
418362306a36Sopenharmony_ci	u16 i, sz = 0;
418462306a36Sopenharmony_ci	int status;
418562306a36Sopenharmony_ci
418662306a36Sopenharmony_ci	cmd = &desc.params.dis_txqs;
418762306a36Sopenharmony_ci	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_dis_txqs);
418862306a36Sopenharmony_ci
418962306a36Sopenharmony_ci	/* qg_list can be NULL only in VM/VF reset flow */
419062306a36Sopenharmony_ci	if (!qg_list && !rst_src)
419162306a36Sopenharmony_ci		return -EINVAL;
419262306a36Sopenharmony_ci
419362306a36Sopenharmony_ci	if (num_qgrps > ICE_LAN_TXQ_MAX_QGRPS)
419462306a36Sopenharmony_ci		return -EINVAL;
419562306a36Sopenharmony_ci
419662306a36Sopenharmony_ci	cmd->num_entries = num_qgrps;
419762306a36Sopenharmony_ci
419862306a36Sopenharmony_ci	cmd->vmvf_and_timeout = cpu_to_le16((5 << ICE_AQC_Q_DIS_TIMEOUT_S) &
419962306a36Sopenharmony_ci					    ICE_AQC_Q_DIS_TIMEOUT_M);
420062306a36Sopenharmony_ci
420162306a36Sopenharmony_ci	switch (rst_src) {
420262306a36Sopenharmony_ci	case ICE_VM_RESET:
420362306a36Sopenharmony_ci		cmd->cmd_type = ICE_AQC_Q_DIS_CMD_VM_RESET;
420462306a36Sopenharmony_ci		cmd->vmvf_and_timeout |=
420562306a36Sopenharmony_ci			cpu_to_le16(vmvf_num & ICE_AQC_Q_DIS_VMVF_NUM_M);
420662306a36Sopenharmony_ci		break;
420762306a36Sopenharmony_ci	case ICE_VF_RESET:
420862306a36Sopenharmony_ci		cmd->cmd_type = ICE_AQC_Q_DIS_CMD_VF_RESET;
420962306a36Sopenharmony_ci		/* In this case, FW expects vmvf_num to be absolute VF ID */
421062306a36Sopenharmony_ci		cmd->vmvf_and_timeout |=
421162306a36Sopenharmony_ci			cpu_to_le16((vmvf_num + hw->func_caps.vf_base_id) &
421262306a36Sopenharmony_ci				    ICE_AQC_Q_DIS_VMVF_NUM_M);
421362306a36Sopenharmony_ci		break;
421462306a36Sopenharmony_ci	case ICE_NO_RESET:
421562306a36Sopenharmony_ci	default:
421662306a36Sopenharmony_ci		break;
421762306a36Sopenharmony_ci	}
421862306a36Sopenharmony_ci
421962306a36Sopenharmony_ci	/* flush pipe on time out */
422062306a36Sopenharmony_ci	cmd->cmd_type |= ICE_AQC_Q_DIS_CMD_FLUSH_PIPE;
422162306a36Sopenharmony_ci	/* If no queue group info, we are in a reset flow. Issue the AQ */
422262306a36Sopenharmony_ci	if (!qg_list)
422362306a36Sopenharmony_ci		goto do_aq;
422462306a36Sopenharmony_ci
422562306a36Sopenharmony_ci	/* set RD bit to indicate that command buffer is provided by the driver
422662306a36Sopenharmony_ci	 * and it needs to be read by the firmware
422762306a36Sopenharmony_ci	 */
422862306a36Sopenharmony_ci	desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
422962306a36Sopenharmony_ci
423062306a36Sopenharmony_ci	for (i = 0, item = qg_list; i < num_qgrps; i++) {
423162306a36Sopenharmony_ci		u16 item_size = struct_size(item, q_id, item->num_qs);
423262306a36Sopenharmony_ci
423362306a36Sopenharmony_ci		/* If the num of queues is even, add 2 bytes of padding */
423462306a36Sopenharmony_ci		if ((item->num_qs % 2) == 0)
423562306a36Sopenharmony_ci			item_size += 2;
423662306a36Sopenharmony_ci
423762306a36Sopenharmony_ci		sz += item_size;
423862306a36Sopenharmony_ci
423962306a36Sopenharmony_ci		item = (struct ice_aqc_dis_txq_item *)((u8 *)item + item_size);
424062306a36Sopenharmony_ci	}
424162306a36Sopenharmony_ci
424262306a36Sopenharmony_ci	if (buf_size != sz)
424362306a36Sopenharmony_ci		return -EINVAL;
424462306a36Sopenharmony_ci
424562306a36Sopenharmony_cido_aq:
424662306a36Sopenharmony_ci	status = ice_aq_send_cmd(hw, &desc, qg_list, buf_size, cd);
424762306a36Sopenharmony_ci	if (status) {
424862306a36Sopenharmony_ci		if (!qg_list)
424962306a36Sopenharmony_ci			ice_debug(hw, ICE_DBG_SCHED, "VM%d disable failed %d\n",
425062306a36Sopenharmony_ci				  vmvf_num, hw->adminq.sq_last_status);
425162306a36Sopenharmony_ci		else
425262306a36Sopenharmony_ci			ice_debug(hw, ICE_DBG_SCHED, "disable queue %d failed %d\n",
425362306a36Sopenharmony_ci				  le16_to_cpu(qg_list[0].q_id[0]),
425462306a36Sopenharmony_ci				  hw->adminq.sq_last_status);
425562306a36Sopenharmony_ci	}
425662306a36Sopenharmony_ci	return status;
425762306a36Sopenharmony_ci}
425862306a36Sopenharmony_ci
425962306a36Sopenharmony_ci/**
426062306a36Sopenharmony_ci * ice_aq_cfg_lan_txq
426162306a36Sopenharmony_ci * @hw: pointer to the hardware structure
426262306a36Sopenharmony_ci * @buf: buffer for command
426362306a36Sopenharmony_ci * @buf_size: size of buffer in bytes
426462306a36Sopenharmony_ci * @num_qs: number of queues being configured
426562306a36Sopenharmony_ci * @oldport: origination lport
426662306a36Sopenharmony_ci * @newport: destination lport
426762306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL
426862306a36Sopenharmony_ci *
426962306a36Sopenharmony_ci * Move/Configure LAN Tx queue (0x0C32)
427062306a36Sopenharmony_ci *
427162306a36Sopenharmony_ci * There is a better AQ command to use for moving nodes, so only coding
427262306a36Sopenharmony_ci * this one for configuring the node.
427362306a36Sopenharmony_ci */
427462306a36Sopenharmony_ciint
427562306a36Sopenharmony_ciice_aq_cfg_lan_txq(struct ice_hw *hw, struct ice_aqc_cfg_txqs_buf *buf,
427662306a36Sopenharmony_ci		   u16 buf_size, u16 num_qs, u8 oldport, u8 newport,
427762306a36Sopenharmony_ci		   struct ice_sq_cd *cd)
427862306a36Sopenharmony_ci{
427962306a36Sopenharmony_ci	struct ice_aqc_cfg_txqs *cmd;
428062306a36Sopenharmony_ci	struct ice_aq_desc desc;
428162306a36Sopenharmony_ci	int status;
428262306a36Sopenharmony_ci
428362306a36Sopenharmony_ci	cmd = &desc.params.cfg_txqs;
428462306a36Sopenharmony_ci	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_cfg_txqs);
428562306a36Sopenharmony_ci	desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
428662306a36Sopenharmony_ci
428762306a36Sopenharmony_ci	if (!buf)
428862306a36Sopenharmony_ci		return -EINVAL;
428962306a36Sopenharmony_ci
429062306a36Sopenharmony_ci	cmd->cmd_type = ICE_AQC_Q_CFG_TC_CHNG;
429162306a36Sopenharmony_ci	cmd->num_qs = num_qs;
429262306a36Sopenharmony_ci	cmd->port_num_chng = (oldport & ICE_AQC_Q_CFG_SRC_PRT_M);
429362306a36Sopenharmony_ci	cmd->port_num_chng |= (newport << ICE_AQC_Q_CFG_DST_PRT_S) &
429462306a36Sopenharmony_ci			      ICE_AQC_Q_CFG_DST_PRT_M;
429562306a36Sopenharmony_ci	cmd->time_out = (5 << ICE_AQC_Q_CFG_TIMEOUT_S) &
429662306a36Sopenharmony_ci			ICE_AQC_Q_CFG_TIMEOUT_M;
429762306a36Sopenharmony_ci	cmd->blocked_cgds = 0;
429862306a36Sopenharmony_ci
429962306a36Sopenharmony_ci	status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
430062306a36Sopenharmony_ci	if (status)
430162306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_SCHED, "Failed to reconfigure nodes %d\n",
430262306a36Sopenharmony_ci			  hw->adminq.sq_last_status);
430362306a36Sopenharmony_ci	return status;
430462306a36Sopenharmony_ci}
430562306a36Sopenharmony_ci
430662306a36Sopenharmony_ci/**
430762306a36Sopenharmony_ci * ice_aq_add_rdma_qsets
430862306a36Sopenharmony_ci * @hw: pointer to the hardware structure
430962306a36Sopenharmony_ci * @num_qset_grps: Number of RDMA Qset groups
431062306a36Sopenharmony_ci * @qset_list: list of Qset groups to be added
431162306a36Sopenharmony_ci * @buf_size: size of buffer for indirect command
431262306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL
431362306a36Sopenharmony_ci *
431462306a36Sopenharmony_ci * Add Tx RDMA Qsets (0x0C33)
431562306a36Sopenharmony_ci */
431662306a36Sopenharmony_cistatic int
431762306a36Sopenharmony_ciice_aq_add_rdma_qsets(struct ice_hw *hw, u8 num_qset_grps,
431862306a36Sopenharmony_ci		      struct ice_aqc_add_rdma_qset_data *qset_list,
431962306a36Sopenharmony_ci		      u16 buf_size, struct ice_sq_cd *cd)
432062306a36Sopenharmony_ci{
432162306a36Sopenharmony_ci	struct ice_aqc_add_rdma_qset_data *list;
432262306a36Sopenharmony_ci	struct ice_aqc_add_rdma_qset *cmd;
432362306a36Sopenharmony_ci	struct ice_aq_desc desc;
432462306a36Sopenharmony_ci	u16 i, sum_size = 0;
432562306a36Sopenharmony_ci
432662306a36Sopenharmony_ci	cmd = &desc.params.add_rdma_qset;
432762306a36Sopenharmony_ci
432862306a36Sopenharmony_ci	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_rdma_qset);
432962306a36Sopenharmony_ci
433062306a36Sopenharmony_ci	if (num_qset_grps > ICE_LAN_TXQ_MAX_QGRPS)
433162306a36Sopenharmony_ci		return -EINVAL;
433262306a36Sopenharmony_ci
433362306a36Sopenharmony_ci	for (i = 0, list = qset_list; i < num_qset_grps; i++) {
433462306a36Sopenharmony_ci		u16 num_qsets = le16_to_cpu(list->num_qsets);
433562306a36Sopenharmony_ci
433662306a36Sopenharmony_ci		sum_size += struct_size(list, rdma_qsets, num_qsets);
433762306a36Sopenharmony_ci		list = (struct ice_aqc_add_rdma_qset_data *)(list->rdma_qsets +
433862306a36Sopenharmony_ci							     num_qsets);
433962306a36Sopenharmony_ci	}
434062306a36Sopenharmony_ci
434162306a36Sopenharmony_ci	if (buf_size != sum_size)
434262306a36Sopenharmony_ci		return -EINVAL;
434362306a36Sopenharmony_ci
434462306a36Sopenharmony_ci	desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
434562306a36Sopenharmony_ci
434662306a36Sopenharmony_ci	cmd->num_qset_grps = num_qset_grps;
434762306a36Sopenharmony_ci
434862306a36Sopenharmony_ci	return ice_aq_send_cmd(hw, &desc, qset_list, buf_size, cd);
434962306a36Sopenharmony_ci}
435062306a36Sopenharmony_ci
435162306a36Sopenharmony_ci/* End of FW Admin Queue command wrappers */
435262306a36Sopenharmony_ci
435362306a36Sopenharmony_ci/**
435462306a36Sopenharmony_ci * ice_write_byte - write a byte to a packed context structure
435562306a36Sopenharmony_ci * @src_ctx:  the context structure to read from
435662306a36Sopenharmony_ci * @dest_ctx: the context to be written to
435762306a36Sopenharmony_ci * @ce_info:  a description of the struct to be filled
435862306a36Sopenharmony_ci */
435962306a36Sopenharmony_cistatic void
436062306a36Sopenharmony_ciice_write_byte(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
436162306a36Sopenharmony_ci{
436262306a36Sopenharmony_ci	u8 src_byte, dest_byte, mask;
436362306a36Sopenharmony_ci	u8 *from, *dest;
436462306a36Sopenharmony_ci	u16 shift_width;
436562306a36Sopenharmony_ci
436662306a36Sopenharmony_ci	/* copy from the next struct field */
436762306a36Sopenharmony_ci	from = src_ctx + ce_info->offset;
436862306a36Sopenharmony_ci
436962306a36Sopenharmony_ci	/* prepare the bits and mask */
437062306a36Sopenharmony_ci	shift_width = ce_info->lsb % 8;
437162306a36Sopenharmony_ci	mask = (u8)(BIT(ce_info->width) - 1);
437262306a36Sopenharmony_ci
437362306a36Sopenharmony_ci	src_byte = *from;
437462306a36Sopenharmony_ci	src_byte &= mask;
437562306a36Sopenharmony_ci
437662306a36Sopenharmony_ci	/* shift to correct alignment */
437762306a36Sopenharmony_ci	mask <<= shift_width;
437862306a36Sopenharmony_ci	src_byte <<= shift_width;
437962306a36Sopenharmony_ci
438062306a36Sopenharmony_ci	/* get the current bits from the target bit string */
438162306a36Sopenharmony_ci	dest = dest_ctx + (ce_info->lsb / 8);
438262306a36Sopenharmony_ci
438362306a36Sopenharmony_ci	memcpy(&dest_byte, dest, sizeof(dest_byte));
438462306a36Sopenharmony_ci
438562306a36Sopenharmony_ci	dest_byte &= ~mask;	/* get the bits not changing */
438662306a36Sopenharmony_ci	dest_byte |= src_byte;	/* add in the new bits */
438762306a36Sopenharmony_ci
438862306a36Sopenharmony_ci	/* put it all back */
438962306a36Sopenharmony_ci	memcpy(dest, &dest_byte, sizeof(dest_byte));
439062306a36Sopenharmony_ci}
439162306a36Sopenharmony_ci
439262306a36Sopenharmony_ci/**
439362306a36Sopenharmony_ci * ice_write_word - write a word to a packed context structure
439462306a36Sopenharmony_ci * @src_ctx:  the context structure to read from
439562306a36Sopenharmony_ci * @dest_ctx: the context to be written to
439662306a36Sopenharmony_ci * @ce_info:  a description of the struct to be filled
439762306a36Sopenharmony_ci */
439862306a36Sopenharmony_cistatic void
439962306a36Sopenharmony_ciice_write_word(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
440062306a36Sopenharmony_ci{
440162306a36Sopenharmony_ci	u16 src_word, mask;
440262306a36Sopenharmony_ci	__le16 dest_word;
440362306a36Sopenharmony_ci	u8 *from, *dest;
440462306a36Sopenharmony_ci	u16 shift_width;
440562306a36Sopenharmony_ci
440662306a36Sopenharmony_ci	/* copy from the next struct field */
440762306a36Sopenharmony_ci	from = src_ctx + ce_info->offset;
440862306a36Sopenharmony_ci
440962306a36Sopenharmony_ci	/* prepare the bits and mask */
441062306a36Sopenharmony_ci	shift_width = ce_info->lsb % 8;
441162306a36Sopenharmony_ci	mask = BIT(ce_info->width) - 1;
441262306a36Sopenharmony_ci
441362306a36Sopenharmony_ci	/* don't swizzle the bits until after the mask because the mask bits
441462306a36Sopenharmony_ci	 * will be in a different bit position on big endian machines
441562306a36Sopenharmony_ci	 */
441662306a36Sopenharmony_ci	src_word = *(u16 *)from;
441762306a36Sopenharmony_ci	src_word &= mask;
441862306a36Sopenharmony_ci
441962306a36Sopenharmony_ci	/* shift to correct alignment */
442062306a36Sopenharmony_ci	mask <<= shift_width;
442162306a36Sopenharmony_ci	src_word <<= shift_width;
442262306a36Sopenharmony_ci
442362306a36Sopenharmony_ci	/* get the current bits from the target bit string */
442462306a36Sopenharmony_ci	dest = dest_ctx + (ce_info->lsb / 8);
442562306a36Sopenharmony_ci
442662306a36Sopenharmony_ci	memcpy(&dest_word, dest, sizeof(dest_word));
442762306a36Sopenharmony_ci
442862306a36Sopenharmony_ci	dest_word &= ~(cpu_to_le16(mask));	/* get the bits not changing */
442962306a36Sopenharmony_ci	dest_word |= cpu_to_le16(src_word);	/* add in the new bits */
443062306a36Sopenharmony_ci
443162306a36Sopenharmony_ci	/* put it all back */
443262306a36Sopenharmony_ci	memcpy(dest, &dest_word, sizeof(dest_word));
443362306a36Sopenharmony_ci}
443462306a36Sopenharmony_ci
443562306a36Sopenharmony_ci/**
443662306a36Sopenharmony_ci * ice_write_dword - write a dword to a packed context structure
443762306a36Sopenharmony_ci * @src_ctx:  the context structure to read from
443862306a36Sopenharmony_ci * @dest_ctx: the context to be written to
443962306a36Sopenharmony_ci * @ce_info:  a description of the struct to be filled
444062306a36Sopenharmony_ci */
444162306a36Sopenharmony_cistatic void
444262306a36Sopenharmony_ciice_write_dword(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
444362306a36Sopenharmony_ci{
444462306a36Sopenharmony_ci	u32 src_dword, mask;
444562306a36Sopenharmony_ci	__le32 dest_dword;
444662306a36Sopenharmony_ci	u8 *from, *dest;
444762306a36Sopenharmony_ci	u16 shift_width;
444862306a36Sopenharmony_ci
444962306a36Sopenharmony_ci	/* copy from the next struct field */
445062306a36Sopenharmony_ci	from = src_ctx + ce_info->offset;
445162306a36Sopenharmony_ci
445262306a36Sopenharmony_ci	/* prepare the bits and mask */
445362306a36Sopenharmony_ci	shift_width = ce_info->lsb % 8;
445462306a36Sopenharmony_ci
445562306a36Sopenharmony_ci	/* if the field width is exactly 32 on an x86 machine, then the shift
445662306a36Sopenharmony_ci	 * operation will not work because the SHL instructions count is masked
445762306a36Sopenharmony_ci	 * to 5 bits so the shift will do nothing
445862306a36Sopenharmony_ci	 */
445962306a36Sopenharmony_ci	if (ce_info->width < 32)
446062306a36Sopenharmony_ci		mask = BIT(ce_info->width) - 1;
446162306a36Sopenharmony_ci	else
446262306a36Sopenharmony_ci		mask = (u32)~0;
446362306a36Sopenharmony_ci
446462306a36Sopenharmony_ci	/* don't swizzle the bits until after the mask because the mask bits
446562306a36Sopenharmony_ci	 * will be in a different bit position on big endian machines
446662306a36Sopenharmony_ci	 */
446762306a36Sopenharmony_ci	src_dword = *(u32 *)from;
446862306a36Sopenharmony_ci	src_dword &= mask;
446962306a36Sopenharmony_ci
447062306a36Sopenharmony_ci	/* shift to correct alignment */
447162306a36Sopenharmony_ci	mask <<= shift_width;
447262306a36Sopenharmony_ci	src_dword <<= shift_width;
447362306a36Sopenharmony_ci
447462306a36Sopenharmony_ci	/* get the current bits from the target bit string */
447562306a36Sopenharmony_ci	dest = dest_ctx + (ce_info->lsb / 8);
447662306a36Sopenharmony_ci
447762306a36Sopenharmony_ci	memcpy(&dest_dword, dest, sizeof(dest_dword));
447862306a36Sopenharmony_ci
447962306a36Sopenharmony_ci	dest_dword &= ~(cpu_to_le32(mask));	/* get the bits not changing */
448062306a36Sopenharmony_ci	dest_dword |= cpu_to_le32(src_dword);	/* add in the new bits */
448162306a36Sopenharmony_ci
448262306a36Sopenharmony_ci	/* put it all back */
448362306a36Sopenharmony_ci	memcpy(dest, &dest_dword, sizeof(dest_dword));
448462306a36Sopenharmony_ci}
448562306a36Sopenharmony_ci
448662306a36Sopenharmony_ci/**
448762306a36Sopenharmony_ci * ice_write_qword - write a qword to a packed context structure
448862306a36Sopenharmony_ci * @src_ctx:  the context structure to read from
448962306a36Sopenharmony_ci * @dest_ctx: the context to be written to
449062306a36Sopenharmony_ci * @ce_info:  a description of the struct to be filled
449162306a36Sopenharmony_ci */
449262306a36Sopenharmony_cistatic void
449362306a36Sopenharmony_ciice_write_qword(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
449462306a36Sopenharmony_ci{
449562306a36Sopenharmony_ci	u64 src_qword, mask;
449662306a36Sopenharmony_ci	__le64 dest_qword;
449762306a36Sopenharmony_ci	u8 *from, *dest;
449862306a36Sopenharmony_ci	u16 shift_width;
449962306a36Sopenharmony_ci
450062306a36Sopenharmony_ci	/* copy from the next struct field */
450162306a36Sopenharmony_ci	from = src_ctx + ce_info->offset;
450262306a36Sopenharmony_ci
450362306a36Sopenharmony_ci	/* prepare the bits and mask */
450462306a36Sopenharmony_ci	shift_width = ce_info->lsb % 8;
450562306a36Sopenharmony_ci
450662306a36Sopenharmony_ci	/* if the field width is exactly 64 on an x86 machine, then the shift
450762306a36Sopenharmony_ci	 * operation will not work because the SHL instructions count is masked
450862306a36Sopenharmony_ci	 * to 6 bits so the shift will do nothing
450962306a36Sopenharmony_ci	 */
451062306a36Sopenharmony_ci	if (ce_info->width < 64)
451162306a36Sopenharmony_ci		mask = BIT_ULL(ce_info->width) - 1;
451262306a36Sopenharmony_ci	else
451362306a36Sopenharmony_ci		mask = (u64)~0;
451462306a36Sopenharmony_ci
451562306a36Sopenharmony_ci	/* don't swizzle the bits until after the mask because the mask bits
451662306a36Sopenharmony_ci	 * will be in a different bit position on big endian machines
451762306a36Sopenharmony_ci	 */
451862306a36Sopenharmony_ci	src_qword = *(u64 *)from;
451962306a36Sopenharmony_ci	src_qword &= mask;
452062306a36Sopenharmony_ci
452162306a36Sopenharmony_ci	/* shift to correct alignment */
452262306a36Sopenharmony_ci	mask <<= shift_width;
452362306a36Sopenharmony_ci	src_qword <<= shift_width;
452462306a36Sopenharmony_ci
452562306a36Sopenharmony_ci	/* get the current bits from the target bit string */
452662306a36Sopenharmony_ci	dest = dest_ctx + (ce_info->lsb / 8);
452762306a36Sopenharmony_ci
452862306a36Sopenharmony_ci	memcpy(&dest_qword, dest, sizeof(dest_qword));
452962306a36Sopenharmony_ci
453062306a36Sopenharmony_ci	dest_qword &= ~(cpu_to_le64(mask));	/* get the bits not changing */
453162306a36Sopenharmony_ci	dest_qword |= cpu_to_le64(src_qword);	/* add in the new bits */
453262306a36Sopenharmony_ci
453362306a36Sopenharmony_ci	/* put it all back */
453462306a36Sopenharmony_ci	memcpy(dest, &dest_qword, sizeof(dest_qword));
453562306a36Sopenharmony_ci}
453662306a36Sopenharmony_ci
453762306a36Sopenharmony_ci/**
453862306a36Sopenharmony_ci * ice_set_ctx - set context bits in packed structure
453962306a36Sopenharmony_ci * @hw: pointer to the hardware structure
454062306a36Sopenharmony_ci * @src_ctx:  pointer to a generic non-packed context structure
454162306a36Sopenharmony_ci * @dest_ctx: pointer to memory for the packed structure
454262306a36Sopenharmony_ci * @ce_info:  a description of the structure to be transformed
454362306a36Sopenharmony_ci */
454462306a36Sopenharmony_ciint
454562306a36Sopenharmony_ciice_set_ctx(struct ice_hw *hw, u8 *src_ctx, u8 *dest_ctx,
454662306a36Sopenharmony_ci	    const struct ice_ctx_ele *ce_info)
454762306a36Sopenharmony_ci{
454862306a36Sopenharmony_ci	int f;
454962306a36Sopenharmony_ci
455062306a36Sopenharmony_ci	for (f = 0; ce_info[f].width; f++) {
455162306a36Sopenharmony_ci		/* We have to deal with each element of the FW response
455262306a36Sopenharmony_ci		 * using the correct size so that we are correct regardless
455362306a36Sopenharmony_ci		 * of the endianness of the machine.
455462306a36Sopenharmony_ci		 */
455562306a36Sopenharmony_ci		if (ce_info[f].width > (ce_info[f].size_of * BITS_PER_BYTE)) {
455662306a36Sopenharmony_ci			ice_debug(hw, ICE_DBG_QCTX, "Field %d width of %d bits larger than size of %d byte(s) ... skipping write\n",
455762306a36Sopenharmony_ci				  f, ce_info[f].width, ce_info[f].size_of);
455862306a36Sopenharmony_ci			continue;
455962306a36Sopenharmony_ci		}
456062306a36Sopenharmony_ci		switch (ce_info[f].size_of) {
456162306a36Sopenharmony_ci		case sizeof(u8):
456262306a36Sopenharmony_ci			ice_write_byte(src_ctx, dest_ctx, &ce_info[f]);
456362306a36Sopenharmony_ci			break;
456462306a36Sopenharmony_ci		case sizeof(u16):
456562306a36Sopenharmony_ci			ice_write_word(src_ctx, dest_ctx, &ce_info[f]);
456662306a36Sopenharmony_ci			break;
456762306a36Sopenharmony_ci		case sizeof(u32):
456862306a36Sopenharmony_ci			ice_write_dword(src_ctx, dest_ctx, &ce_info[f]);
456962306a36Sopenharmony_ci			break;
457062306a36Sopenharmony_ci		case sizeof(u64):
457162306a36Sopenharmony_ci			ice_write_qword(src_ctx, dest_ctx, &ce_info[f]);
457262306a36Sopenharmony_ci			break;
457362306a36Sopenharmony_ci		default:
457462306a36Sopenharmony_ci			return -EINVAL;
457562306a36Sopenharmony_ci		}
457662306a36Sopenharmony_ci	}
457762306a36Sopenharmony_ci
457862306a36Sopenharmony_ci	return 0;
457962306a36Sopenharmony_ci}
458062306a36Sopenharmony_ci
458162306a36Sopenharmony_ci/**
458262306a36Sopenharmony_ci * ice_get_lan_q_ctx - get the LAN queue context for the given VSI and TC
458362306a36Sopenharmony_ci * @hw: pointer to the HW struct
458462306a36Sopenharmony_ci * @vsi_handle: software VSI handle
458562306a36Sopenharmony_ci * @tc: TC number
458662306a36Sopenharmony_ci * @q_handle: software queue handle
458762306a36Sopenharmony_ci */
458862306a36Sopenharmony_cistruct ice_q_ctx *
458962306a36Sopenharmony_ciice_get_lan_q_ctx(struct ice_hw *hw, u16 vsi_handle, u8 tc, u16 q_handle)
459062306a36Sopenharmony_ci{
459162306a36Sopenharmony_ci	struct ice_vsi_ctx *vsi;
459262306a36Sopenharmony_ci	struct ice_q_ctx *q_ctx;
459362306a36Sopenharmony_ci
459462306a36Sopenharmony_ci	vsi = ice_get_vsi_ctx(hw, vsi_handle);
459562306a36Sopenharmony_ci	if (!vsi)
459662306a36Sopenharmony_ci		return NULL;
459762306a36Sopenharmony_ci	if (q_handle >= vsi->num_lan_q_entries[tc])
459862306a36Sopenharmony_ci		return NULL;
459962306a36Sopenharmony_ci	if (!vsi->lan_q_ctx[tc])
460062306a36Sopenharmony_ci		return NULL;
460162306a36Sopenharmony_ci	q_ctx = vsi->lan_q_ctx[tc];
460262306a36Sopenharmony_ci	return &q_ctx[q_handle];
460362306a36Sopenharmony_ci}
460462306a36Sopenharmony_ci
460562306a36Sopenharmony_ci/**
460662306a36Sopenharmony_ci * ice_ena_vsi_txq
460762306a36Sopenharmony_ci * @pi: port information structure
460862306a36Sopenharmony_ci * @vsi_handle: software VSI handle
460962306a36Sopenharmony_ci * @tc: TC number
461062306a36Sopenharmony_ci * @q_handle: software queue handle
461162306a36Sopenharmony_ci * @num_qgrps: Number of added queue groups
461262306a36Sopenharmony_ci * @buf: list of queue groups to be added
461362306a36Sopenharmony_ci * @buf_size: size of buffer for indirect command
461462306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL
461562306a36Sopenharmony_ci *
461662306a36Sopenharmony_ci * This function adds one LAN queue
461762306a36Sopenharmony_ci */
461862306a36Sopenharmony_ciint
461962306a36Sopenharmony_ciice_ena_vsi_txq(struct ice_port_info *pi, u16 vsi_handle, u8 tc, u16 q_handle,
462062306a36Sopenharmony_ci		u8 num_qgrps, struct ice_aqc_add_tx_qgrp *buf, u16 buf_size,
462162306a36Sopenharmony_ci		struct ice_sq_cd *cd)
462262306a36Sopenharmony_ci{
462362306a36Sopenharmony_ci	struct ice_aqc_txsched_elem_data node = { 0 };
462462306a36Sopenharmony_ci	struct ice_sched_node *parent;
462562306a36Sopenharmony_ci	struct ice_q_ctx *q_ctx;
462662306a36Sopenharmony_ci	struct ice_hw *hw;
462762306a36Sopenharmony_ci	int status;
462862306a36Sopenharmony_ci
462962306a36Sopenharmony_ci	if (!pi || pi->port_state != ICE_SCHED_PORT_STATE_READY)
463062306a36Sopenharmony_ci		return -EIO;
463162306a36Sopenharmony_ci
463262306a36Sopenharmony_ci	if (num_qgrps > 1 || buf->num_txqs > 1)
463362306a36Sopenharmony_ci		return -ENOSPC;
463462306a36Sopenharmony_ci
463562306a36Sopenharmony_ci	hw = pi->hw;
463662306a36Sopenharmony_ci
463762306a36Sopenharmony_ci	if (!ice_is_vsi_valid(hw, vsi_handle))
463862306a36Sopenharmony_ci		return -EINVAL;
463962306a36Sopenharmony_ci
464062306a36Sopenharmony_ci	mutex_lock(&pi->sched_lock);
464162306a36Sopenharmony_ci
464262306a36Sopenharmony_ci	q_ctx = ice_get_lan_q_ctx(hw, vsi_handle, tc, q_handle);
464362306a36Sopenharmony_ci	if (!q_ctx) {
464462306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_SCHED, "Enaq: invalid queue handle %d\n",
464562306a36Sopenharmony_ci			  q_handle);
464662306a36Sopenharmony_ci		status = -EINVAL;
464762306a36Sopenharmony_ci		goto ena_txq_exit;
464862306a36Sopenharmony_ci	}
464962306a36Sopenharmony_ci
465062306a36Sopenharmony_ci	/* find a parent node */
465162306a36Sopenharmony_ci	parent = ice_sched_get_free_qparent(pi, vsi_handle, tc,
465262306a36Sopenharmony_ci					    ICE_SCHED_NODE_OWNER_LAN);
465362306a36Sopenharmony_ci	if (!parent) {
465462306a36Sopenharmony_ci		status = -EINVAL;
465562306a36Sopenharmony_ci		goto ena_txq_exit;
465662306a36Sopenharmony_ci	}
465762306a36Sopenharmony_ci
465862306a36Sopenharmony_ci	buf->parent_teid = parent->info.node_teid;
465962306a36Sopenharmony_ci	node.parent_teid = parent->info.node_teid;
466062306a36Sopenharmony_ci	/* Mark that the values in the "generic" section as valid. The default
466162306a36Sopenharmony_ci	 * value in the "generic" section is zero. This means that :
466262306a36Sopenharmony_ci	 * - Scheduling mode is Bytes Per Second (BPS), indicated by Bit 0.
466362306a36Sopenharmony_ci	 * - 0 priority among siblings, indicated by Bit 1-3.
466462306a36Sopenharmony_ci	 * - WFQ, indicated by Bit 4.
466562306a36Sopenharmony_ci	 * - 0 Adjustment value is used in PSM credit update flow, indicated by
466662306a36Sopenharmony_ci	 * Bit 5-6.
466762306a36Sopenharmony_ci	 * - Bit 7 is reserved.
466862306a36Sopenharmony_ci	 * Without setting the generic section as valid in valid_sections, the
466962306a36Sopenharmony_ci	 * Admin queue command will fail with error code ICE_AQ_RC_EINVAL.
467062306a36Sopenharmony_ci	 */
467162306a36Sopenharmony_ci	buf->txqs[0].info.valid_sections =
467262306a36Sopenharmony_ci		ICE_AQC_ELEM_VALID_GENERIC | ICE_AQC_ELEM_VALID_CIR |
467362306a36Sopenharmony_ci		ICE_AQC_ELEM_VALID_EIR;
467462306a36Sopenharmony_ci	buf->txqs[0].info.generic = 0;
467562306a36Sopenharmony_ci	buf->txqs[0].info.cir_bw.bw_profile_idx =
467662306a36Sopenharmony_ci		cpu_to_le16(ICE_SCHED_DFLT_RL_PROF_ID);
467762306a36Sopenharmony_ci	buf->txqs[0].info.cir_bw.bw_alloc =
467862306a36Sopenharmony_ci		cpu_to_le16(ICE_SCHED_DFLT_BW_WT);
467962306a36Sopenharmony_ci	buf->txqs[0].info.eir_bw.bw_profile_idx =
468062306a36Sopenharmony_ci		cpu_to_le16(ICE_SCHED_DFLT_RL_PROF_ID);
468162306a36Sopenharmony_ci	buf->txqs[0].info.eir_bw.bw_alloc =
468262306a36Sopenharmony_ci		cpu_to_le16(ICE_SCHED_DFLT_BW_WT);
468362306a36Sopenharmony_ci
468462306a36Sopenharmony_ci	/* add the LAN queue */
468562306a36Sopenharmony_ci	status = ice_aq_add_lan_txq(hw, num_qgrps, buf, buf_size, cd);
468662306a36Sopenharmony_ci	if (status) {
468762306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_SCHED, "enable queue %d failed %d\n",
468862306a36Sopenharmony_ci			  le16_to_cpu(buf->txqs[0].txq_id),
468962306a36Sopenharmony_ci			  hw->adminq.sq_last_status);
469062306a36Sopenharmony_ci		goto ena_txq_exit;
469162306a36Sopenharmony_ci	}
469262306a36Sopenharmony_ci
469362306a36Sopenharmony_ci	node.node_teid = buf->txqs[0].q_teid;
469462306a36Sopenharmony_ci	node.data.elem_type = ICE_AQC_ELEM_TYPE_LEAF;
469562306a36Sopenharmony_ci	q_ctx->q_handle = q_handle;
469662306a36Sopenharmony_ci	q_ctx->q_teid = le32_to_cpu(node.node_teid);
469762306a36Sopenharmony_ci
469862306a36Sopenharmony_ci	/* add a leaf node into scheduler tree queue layer */
469962306a36Sopenharmony_ci	status = ice_sched_add_node(pi, hw->num_tx_sched_layers - 1, &node, NULL);
470062306a36Sopenharmony_ci	if (!status)
470162306a36Sopenharmony_ci		status = ice_sched_replay_q_bw(pi, q_ctx);
470262306a36Sopenharmony_ci
470362306a36Sopenharmony_ciena_txq_exit:
470462306a36Sopenharmony_ci	mutex_unlock(&pi->sched_lock);
470562306a36Sopenharmony_ci	return status;
470662306a36Sopenharmony_ci}
470762306a36Sopenharmony_ci
470862306a36Sopenharmony_ci/**
470962306a36Sopenharmony_ci * ice_dis_vsi_txq
471062306a36Sopenharmony_ci * @pi: port information structure
471162306a36Sopenharmony_ci * @vsi_handle: software VSI handle
471262306a36Sopenharmony_ci * @tc: TC number
471362306a36Sopenharmony_ci * @num_queues: number of queues
471462306a36Sopenharmony_ci * @q_handles: pointer to software queue handle array
471562306a36Sopenharmony_ci * @q_ids: pointer to the q_id array
471662306a36Sopenharmony_ci * @q_teids: pointer to queue node teids
471762306a36Sopenharmony_ci * @rst_src: if called due to reset, specifies the reset source
471862306a36Sopenharmony_ci * @vmvf_num: the relative VM or VF number that is undergoing the reset
471962306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL
472062306a36Sopenharmony_ci *
472162306a36Sopenharmony_ci * This function removes queues and their corresponding nodes in SW DB
472262306a36Sopenharmony_ci */
472362306a36Sopenharmony_ciint
472462306a36Sopenharmony_ciice_dis_vsi_txq(struct ice_port_info *pi, u16 vsi_handle, u8 tc, u8 num_queues,
472562306a36Sopenharmony_ci		u16 *q_handles, u16 *q_ids, u32 *q_teids,
472662306a36Sopenharmony_ci		enum ice_disq_rst_src rst_src, u16 vmvf_num,
472762306a36Sopenharmony_ci		struct ice_sq_cd *cd)
472862306a36Sopenharmony_ci{
472962306a36Sopenharmony_ci	struct ice_aqc_dis_txq_item *qg_list;
473062306a36Sopenharmony_ci	struct ice_q_ctx *q_ctx;
473162306a36Sopenharmony_ci	int status = -ENOENT;
473262306a36Sopenharmony_ci	struct ice_hw *hw;
473362306a36Sopenharmony_ci	u16 i, buf_size;
473462306a36Sopenharmony_ci
473562306a36Sopenharmony_ci	if (!pi || pi->port_state != ICE_SCHED_PORT_STATE_READY)
473662306a36Sopenharmony_ci		return -EIO;
473762306a36Sopenharmony_ci
473862306a36Sopenharmony_ci	hw = pi->hw;
473962306a36Sopenharmony_ci
474062306a36Sopenharmony_ci	if (!num_queues) {
474162306a36Sopenharmony_ci		/* if queue is disabled already yet the disable queue command
474262306a36Sopenharmony_ci		 * has to be sent to complete the VF reset, then call
474362306a36Sopenharmony_ci		 * ice_aq_dis_lan_txq without any queue information
474462306a36Sopenharmony_ci		 */
474562306a36Sopenharmony_ci		if (rst_src)
474662306a36Sopenharmony_ci			return ice_aq_dis_lan_txq(hw, 0, NULL, 0, rst_src,
474762306a36Sopenharmony_ci						  vmvf_num, NULL);
474862306a36Sopenharmony_ci		return -EIO;
474962306a36Sopenharmony_ci	}
475062306a36Sopenharmony_ci
475162306a36Sopenharmony_ci	buf_size = struct_size(qg_list, q_id, 1);
475262306a36Sopenharmony_ci	qg_list = kzalloc(buf_size, GFP_KERNEL);
475362306a36Sopenharmony_ci	if (!qg_list)
475462306a36Sopenharmony_ci		return -ENOMEM;
475562306a36Sopenharmony_ci
475662306a36Sopenharmony_ci	mutex_lock(&pi->sched_lock);
475762306a36Sopenharmony_ci
475862306a36Sopenharmony_ci	for (i = 0; i < num_queues; i++) {
475962306a36Sopenharmony_ci		struct ice_sched_node *node;
476062306a36Sopenharmony_ci
476162306a36Sopenharmony_ci		node = ice_sched_find_node_by_teid(pi->root, q_teids[i]);
476262306a36Sopenharmony_ci		if (!node)
476362306a36Sopenharmony_ci			continue;
476462306a36Sopenharmony_ci		q_ctx = ice_get_lan_q_ctx(hw, vsi_handle, tc, q_handles[i]);
476562306a36Sopenharmony_ci		if (!q_ctx) {
476662306a36Sopenharmony_ci			ice_debug(hw, ICE_DBG_SCHED, "invalid queue handle%d\n",
476762306a36Sopenharmony_ci				  q_handles[i]);
476862306a36Sopenharmony_ci			continue;
476962306a36Sopenharmony_ci		}
477062306a36Sopenharmony_ci		if (q_ctx->q_handle != q_handles[i]) {
477162306a36Sopenharmony_ci			ice_debug(hw, ICE_DBG_SCHED, "Err:handles %d %d\n",
477262306a36Sopenharmony_ci				  q_ctx->q_handle, q_handles[i]);
477362306a36Sopenharmony_ci			continue;
477462306a36Sopenharmony_ci		}
477562306a36Sopenharmony_ci		qg_list->parent_teid = node->info.parent_teid;
477662306a36Sopenharmony_ci		qg_list->num_qs = 1;
477762306a36Sopenharmony_ci		qg_list->q_id[0] = cpu_to_le16(q_ids[i]);
477862306a36Sopenharmony_ci		status = ice_aq_dis_lan_txq(hw, 1, qg_list, buf_size, rst_src,
477962306a36Sopenharmony_ci					    vmvf_num, cd);
478062306a36Sopenharmony_ci
478162306a36Sopenharmony_ci		if (status)
478262306a36Sopenharmony_ci			break;
478362306a36Sopenharmony_ci		ice_free_sched_node(pi, node);
478462306a36Sopenharmony_ci		q_ctx->q_handle = ICE_INVAL_Q_HANDLE;
478562306a36Sopenharmony_ci		q_ctx->q_teid = ICE_INVAL_TEID;
478662306a36Sopenharmony_ci	}
478762306a36Sopenharmony_ci	mutex_unlock(&pi->sched_lock);
478862306a36Sopenharmony_ci	kfree(qg_list);
478962306a36Sopenharmony_ci	return status;
479062306a36Sopenharmony_ci}
479162306a36Sopenharmony_ci
479262306a36Sopenharmony_ci/**
479362306a36Sopenharmony_ci * ice_cfg_vsi_qs - configure the new/existing VSI queues
479462306a36Sopenharmony_ci * @pi: port information structure
479562306a36Sopenharmony_ci * @vsi_handle: software VSI handle
479662306a36Sopenharmony_ci * @tc_bitmap: TC bitmap
479762306a36Sopenharmony_ci * @maxqs: max queues array per TC
479862306a36Sopenharmony_ci * @owner: LAN or RDMA
479962306a36Sopenharmony_ci *
480062306a36Sopenharmony_ci * This function adds/updates the VSI queues per TC.
480162306a36Sopenharmony_ci */
480262306a36Sopenharmony_cistatic int
480362306a36Sopenharmony_ciice_cfg_vsi_qs(struct ice_port_info *pi, u16 vsi_handle, u8 tc_bitmap,
480462306a36Sopenharmony_ci	       u16 *maxqs, u8 owner)
480562306a36Sopenharmony_ci{
480662306a36Sopenharmony_ci	int status = 0;
480762306a36Sopenharmony_ci	u8 i;
480862306a36Sopenharmony_ci
480962306a36Sopenharmony_ci	if (!pi || pi->port_state != ICE_SCHED_PORT_STATE_READY)
481062306a36Sopenharmony_ci		return -EIO;
481162306a36Sopenharmony_ci
481262306a36Sopenharmony_ci	if (!ice_is_vsi_valid(pi->hw, vsi_handle))
481362306a36Sopenharmony_ci		return -EINVAL;
481462306a36Sopenharmony_ci
481562306a36Sopenharmony_ci	mutex_lock(&pi->sched_lock);
481662306a36Sopenharmony_ci
481762306a36Sopenharmony_ci	ice_for_each_traffic_class(i) {
481862306a36Sopenharmony_ci		/* configuration is possible only if TC node is present */
481962306a36Sopenharmony_ci		if (!ice_sched_get_tc_node(pi, i))
482062306a36Sopenharmony_ci			continue;
482162306a36Sopenharmony_ci
482262306a36Sopenharmony_ci		status = ice_sched_cfg_vsi(pi, vsi_handle, i, maxqs[i], owner,
482362306a36Sopenharmony_ci					   ice_is_tc_ena(tc_bitmap, i));
482462306a36Sopenharmony_ci		if (status)
482562306a36Sopenharmony_ci			break;
482662306a36Sopenharmony_ci	}
482762306a36Sopenharmony_ci
482862306a36Sopenharmony_ci	mutex_unlock(&pi->sched_lock);
482962306a36Sopenharmony_ci	return status;
483062306a36Sopenharmony_ci}
483162306a36Sopenharmony_ci
483262306a36Sopenharmony_ci/**
483362306a36Sopenharmony_ci * ice_cfg_vsi_lan - configure VSI LAN queues
483462306a36Sopenharmony_ci * @pi: port information structure
483562306a36Sopenharmony_ci * @vsi_handle: software VSI handle
483662306a36Sopenharmony_ci * @tc_bitmap: TC bitmap
483762306a36Sopenharmony_ci * @max_lanqs: max LAN queues array per TC
483862306a36Sopenharmony_ci *
483962306a36Sopenharmony_ci * This function adds/updates the VSI LAN queues per TC.
484062306a36Sopenharmony_ci */
484162306a36Sopenharmony_ciint
484262306a36Sopenharmony_ciice_cfg_vsi_lan(struct ice_port_info *pi, u16 vsi_handle, u8 tc_bitmap,
484362306a36Sopenharmony_ci		u16 *max_lanqs)
484462306a36Sopenharmony_ci{
484562306a36Sopenharmony_ci	return ice_cfg_vsi_qs(pi, vsi_handle, tc_bitmap, max_lanqs,
484662306a36Sopenharmony_ci			      ICE_SCHED_NODE_OWNER_LAN);
484762306a36Sopenharmony_ci}
484862306a36Sopenharmony_ci
484962306a36Sopenharmony_ci/**
485062306a36Sopenharmony_ci * ice_cfg_vsi_rdma - configure the VSI RDMA queues
485162306a36Sopenharmony_ci * @pi: port information structure
485262306a36Sopenharmony_ci * @vsi_handle: software VSI handle
485362306a36Sopenharmony_ci * @tc_bitmap: TC bitmap
485462306a36Sopenharmony_ci * @max_rdmaqs: max RDMA queues array per TC
485562306a36Sopenharmony_ci *
485662306a36Sopenharmony_ci * This function adds/updates the VSI RDMA queues per TC.
485762306a36Sopenharmony_ci */
485862306a36Sopenharmony_ciint
485962306a36Sopenharmony_ciice_cfg_vsi_rdma(struct ice_port_info *pi, u16 vsi_handle, u16 tc_bitmap,
486062306a36Sopenharmony_ci		 u16 *max_rdmaqs)
486162306a36Sopenharmony_ci{
486262306a36Sopenharmony_ci	return ice_cfg_vsi_qs(pi, vsi_handle, tc_bitmap, max_rdmaqs,
486362306a36Sopenharmony_ci			      ICE_SCHED_NODE_OWNER_RDMA);
486462306a36Sopenharmony_ci}
486562306a36Sopenharmony_ci
486662306a36Sopenharmony_ci/**
486762306a36Sopenharmony_ci * ice_ena_vsi_rdma_qset
486862306a36Sopenharmony_ci * @pi: port information structure
486962306a36Sopenharmony_ci * @vsi_handle: software VSI handle
487062306a36Sopenharmony_ci * @tc: TC number
487162306a36Sopenharmony_ci * @rdma_qset: pointer to RDMA Qset
487262306a36Sopenharmony_ci * @num_qsets: number of RDMA Qsets
487362306a36Sopenharmony_ci * @qset_teid: pointer to Qset node TEIDs
487462306a36Sopenharmony_ci *
487562306a36Sopenharmony_ci * This function adds RDMA Qset
487662306a36Sopenharmony_ci */
487762306a36Sopenharmony_ciint
487862306a36Sopenharmony_ciice_ena_vsi_rdma_qset(struct ice_port_info *pi, u16 vsi_handle, u8 tc,
487962306a36Sopenharmony_ci		      u16 *rdma_qset, u16 num_qsets, u32 *qset_teid)
488062306a36Sopenharmony_ci{
488162306a36Sopenharmony_ci	struct ice_aqc_txsched_elem_data node = { 0 };
488262306a36Sopenharmony_ci	struct ice_aqc_add_rdma_qset_data *buf;
488362306a36Sopenharmony_ci	struct ice_sched_node *parent;
488462306a36Sopenharmony_ci	struct ice_hw *hw;
488562306a36Sopenharmony_ci	u16 i, buf_size;
488662306a36Sopenharmony_ci	int ret;
488762306a36Sopenharmony_ci
488862306a36Sopenharmony_ci	if (!pi || pi->port_state != ICE_SCHED_PORT_STATE_READY)
488962306a36Sopenharmony_ci		return -EIO;
489062306a36Sopenharmony_ci	hw = pi->hw;
489162306a36Sopenharmony_ci
489262306a36Sopenharmony_ci	if (!ice_is_vsi_valid(hw, vsi_handle))
489362306a36Sopenharmony_ci		return -EINVAL;
489462306a36Sopenharmony_ci
489562306a36Sopenharmony_ci	buf_size = struct_size(buf, rdma_qsets, num_qsets);
489662306a36Sopenharmony_ci	buf = kzalloc(buf_size, GFP_KERNEL);
489762306a36Sopenharmony_ci	if (!buf)
489862306a36Sopenharmony_ci		return -ENOMEM;
489962306a36Sopenharmony_ci	mutex_lock(&pi->sched_lock);
490062306a36Sopenharmony_ci
490162306a36Sopenharmony_ci	parent = ice_sched_get_free_qparent(pi, vsi_handle, tc,
490262306a36Sopenharmony_ci					    ICE_SCHED_NODE_OWNER_RDMA);
490362306a36Sopenharmony_ci	if (!parent) {
490462306a36Sopenharmony_ci		ret = -EINVAL;
490562306a36Sopenharmony_ci		goto rdma_error_exit;
490662306a36Sopenharmony_ci	}
490762306a36Sopenharmony_ci	buf->parent_teid = parent->info.node_teid;
490862306a36Sopenharmony_ci	node.parent_teid = parent->info.node_teid;
490962306a36Sopenharmony_ci
491062306a36Sopenharmony_ci	buf->num_qsets = cpu_to_le16(num_qsets);
491162306a36Sopenharmony_ci	for (i = 0; i < num_qsets; i++) {
491262306a36Sopenharmony_ci		buf->rdma_qsets[i].tx_qset_id = cpu_to_le16(rdma_qset[i]);
491362306a36Sopenharmony_ci		buf->rdma_qsets[i].info.valid_sections =
491462306a36Sopenharmony_ci			ICE_AQC_ELEM_VALID_GENERIC | ICE_AQC_ELEM_VALID_CIR |
491562306a36Sopenharmony_ci			ICE_AQC_ELEM_VALID_EIR;
491662306a36Sopenharmony_ci		buf->rdma_qsets[i].info.generic = 0;
491762306a36Sopenharmony_ci		buf->rdma_qsets[i].info.cir_bw.bw_profile_idx =
491862306a36Sopenharmony_ci			cpu_to_le16(ICE_SCHED_DFLT_RL_PROF_ID);
491962306a36Sopenharmony_ci		buf->rdma_qsets[i].info.cir_bw.bw_alloc =
492062306a36Sopenharmony_ci			cpu_to_le16(ICE_SCHED_DFLT_BW_WT);
492162306a36Sopenharmony_ci		buf->rdma_qsets[i].info.eir_bw.bw_profile_idx =
492262306a36Sopenharmony_ci			cpu_to_le16(ICE_SCHED_DFLT_RL_PROF_ID);
492362306a36Sopenharmony_ci		buf->rdma_qsets[i].info.eir_bw.bw_alloc =
492462306a36Sopenharmony_ci			cpu_to_le16(ICE_SCHED_DFLT_BW_WT);
492562306a36Sopenharmony_ci	}
492662306a36Sopenharmony_ci	ret = ice_aq_add_rdma_qsets(hw, 1, buf, buf_size, NULL);
492762306a36Sopenharmony_ci	if (ret) {
492862306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_RDMA, "add RDMA qset failed\n");
492962306a36Sopenharmony_ci		goto rdma_error_exit;
493062306a36Sopenharmony_ci	}
493162306a36Sopenharmony_ci	node.data.elem_type = ICE_AQC_ELEM_TYPE_LEAF;
493262306a36Sopenharmony_ci	for (i = 0; i < num_qsets; i++) {
493362306a36Sopenharmony_ci		node.node_teid = buf->rdma_qsets[i].qset_teid;
493462306a36Sopenharmony_ci		ret = ice_sched_add_node(pi, hw->num_tx_sched_layers - 1,
493562306a36Sopenharmony_ci					 &node, NULL);
493662306a36Sopenharmony_ci		if (ret)
493762306a36Sopenharmony_ci			break;
493862306a36Sopenharmony_ci		qset_teid[i] = le32_to_cpu(node.node_teid);
493962306a36Sopenharmony_ci	}
494062306a36Sopenharmony_cirdma_error_exit:
494162306a36Sopenharmony_ci	mutex_unlock(&pi->sched_lock);
494262306a36Sopenharmony_ci	kfree(buf);
494362306a36Sopenharmony_ci	return ret;
494462306a36Sopenharmony_ci}
494562306a36Sopenharmony_ci
494662306a36Sopenharmony_ci/**
494762306a36Sopenharmony_ci * ice_dis_vsi_rdma_qset - free RDMA resources
494862306a36Sopenharmony_ci * @pi: port_info struct
494962306a36Sopenharmony_ci * @count: number of RDMA Qsets to free
495062306a36Sopenharmony_ci * @qset_teid: TEID of Qset node
495162306a36Sopenharmony_ci * @q_id: list of queue IDs being disabled
495262306a36Sopenharmony_ci */
495362306a36Sopenharmony_ciint
495462306a36Sopenharmony_ciice_dis_vsi_rdma_qset(struct ice_port_info *pi, u16 count, u32 *qset_teid,
495562306a36Sopenharmony_ci		      u16 *q_id)
495662306a36Sopenharmony_ci{
495762306a36Sopenharmony_ci	struct ice_aqc_dis_txq_item *qg_list;
495862306a36Sopenharmony_ci	struct ice_hw *hw;
495962306a36Sopenharmony_ci	int status = 0;
496062306a36Sopenharmony_ci	u16 qg_size;
496162306a36Sopenharmony_ci	int i;
496262306a36Sopenharmony_ci
496362306a36Sopenharmony_ci	if (!pi || pi->port_state != ICE_SCHED_PORT_STATE_READY)
496462306a36Sopenharmony_ci		return -EIO;
496562306a36Sopenharmony_ci
496662306a36Sopenharmony_ci	hw = pi->hw;
496762306a36Sopenharmony_ci
496862306a36Sopenharmony_ci	qg_size = struct_size(qg_list, q_id, 1);
496962306a36Sopenharmony_ci	qg_list = kzalloc(qg_size, GFP_KERNEL);
497062306a36Sopenharmony_ci	if (!qg_list)
497162306a36Sopenharmony_ci		return -ENOMEM;
497262306a36Sopenharmony_ci
497362306a36Sopenharmony_ci	mutex_lock(&pi->sched_lock);
497462306a36Sopenharmony_ci
497562306a36Sopenharmony_ci	for (i = 0; i < count; i++) {
497662306a36Sopenharmony_ci		struct ice_sched_node *node;
497762306a36Sopenharmony_ci
497862306a36Sopenharmony_ci		node = ice_sched_find_node_by_teid(pi->root, qset_teid[i]);
497962306a36Sopenharmony_ci		if (!node)
498062306a36Sopenharmony_ci			continue;
498162306a36Sopenharmony_ci
498262306a36Sopenharmony_ci		qg_list->parent_teid = node->info.parent_teid;
498362306a36Sopenharmony_ci		qg_list->num_qs = 1;
498462306a36Sopenharmony_ci		qg_list->q_id[0] =
498562306a36Sopenharmony_ci			cpu_to_le16(q_id[i] |
498662306a36Sopenharmony_ci				    ICE_AQC_Q_DIS_BUF_ELEM_TYPE_RDMA_QSET);
498762306a36Sopenharmony_ci
498862306a36Sopenharmony_ci		status = ice_aq_dis_lan_txq(hw, 1, qg_list, qg_size,
498962306a36Sopenharmony_ci					    ICE_NO_RESET, 0, NULL);
499062306a36Sopenharmony_ci		if (status)
499162306a36Sopenharmony_ci			break;
499262306a36Sopenharmony_ci
499362306a36Sopenharmony_ci		ice_free_sched_node(pi, node);
499462306a36Sopenharmony_ci	}
499562306a36Sopenharmony_ci
499662306a36Sopenharmony_ci	mutex_unlock(&pi->sched_lock);
499762306a36Sopenharmony_ci	kfree(qg_list);
499862306a36Sopenharmony_ci	return status;
499962306a36Sopenharmony_ci}
500062306a36Sopenharmony_ci
500162306a36Sopenharmony_ci/**
500262306a36Sopenharmony_ci * ice_replay_pre_init - replay pre initialization
500362306a36Sopenharmony_ci * @hw: pointer to the HW struct
500462306a36Sopenharmony_ci *
500562306a36Sopenharmony_ci * Initializes required config data for VSI, FD, ACL, and RSS before replay.
500662306a36Sopenharmony_ci */
500762306a36Sopenharmony_cistatic int ice_replay_pre_init(struct ice_hw *hw)
500862306a36Sopenharmony_ci{
500962306a36Sopenharmony_ci	struct ice_switch_info *sw = hw->switch_info;
501062306a36Sopenharmony_ci	u8 i;
501162306a36Sopenharmony_ci
501262306a36Sopenharmony_ci	/* Delete old entries from replay filter list head if there is any */
501362306a36Sopenharmony_ci	ice_rm_all_sw_replay_rule_info(hw);
501462306a36Sopenharmony_ci	/* In start of replay, move entries into replay_rules list, it
501562306a36Sopenharmony_ci	 * will allow adding rules entries back to filt_rules list,
501662306a36Sopenharmony_ci	 * which is operational list.
501762306a36Sopenharmony_ci	 */
501862306a36Sopenharmony_ci	for (i = 0; i < ICE_MAX_NUM_RECIPES; i++)
501962306a36Sopenharmony_ci		list_replace_init(&sw->recp_list[i].filt_rules,
502062306a36Sopenharmony_ci				  &sw->recp_list[i].filt_replay_rules);
502162306a36Sopenharmony_ci	ice_sched_replay_agg_vsi_preinit(hw);
502262306a36Sopenharmony_ci
502362306a36Sopenharmony_ci	return 0;
502462306a36Sopenharmony_ci}
502562306a36Sopenharmony_ci
502662306a36Sopenharmony_ci/**
502762306a36Sopenharmony_ci * ice_replay_vsi - replay VSI configuration
502862306a36Sopenharmony_ci * @hw: pointer to the HW struct
502962306a36Sopenharmony_ci * @vsi_handle: driver VSI handle
503062306a36Sopenharmony_ci *
503162306a36Sopenharmony_ci * Restore all VSI configuration after reset. It is required to call this
503262306a36Sopenharmony_ci * function with main VSI first.
503362306a36Sopenharmony_ci */
503462306a36Sopenharmony_ciint ice_replay_vsi(struct ice_hw *hw, u16 vsi_handle)
503562306a36Sopenharmony_ci{
503662306a36Sopenharmony_ci	int status;
503762306a36Sopenharmony_ci
503862306a36Sopenharmony_ci	if (!ice_is_vsi_valid(hw, vsi_handle))
503962306a36Sopenharmony_ci		return -EINVAL;
504062306a36Sopenharmony_ci
504162306a36Sopenharmony_ci	/* Replay pre-initialization if there is any */
504262306a36Sopenharmony_ci	if (vsi_handle == ICE_MAIN_VSI_HANDLE) {
504362306a36Sopenharmony_ci		status = ice_replay_pre_init(hw);
504462306a36Sopenharmony_ci		if (status)
504562306a36Sopenharmony_ci			return status;
504662306a36Sopenharmony_ci	}
504762306a36Sopenharmony_ci	/* Replay per VSI all RSS configurations */
504862306a36Sopenharmony_ci	status = ice_replay_rss_cfg(hw, vsi_handle);
504962306a36Sopenharmony_ci	if (status)
505062306a36Sopenharmony_ci		return status;
505162306a36Sopenharmony_ci	/* Replay per VSI all filters */
505262306a36Sopenharmony_ci	status = ice_replay_vsi_all_fltr(hw, vsi_handle);
505362306a36Sopenharmony_ci	if (!status)
505462306a36Sopenharmony_ci		status = ice_replay_vsi_agg(hw, vsi_handle);
505562306a36Sopenharmony_ci	return status;
505662306a36Sopenharmony_ci}
505762306a36Sopenharmony_ci
505862306a36Sopenharmony_ci/**
505962306a36Sopenharmony_ci * ice_replay_post - post replay configuration cleanup
506062306a36Sopenharmony_ci * @hw: pointer to the HW struct
506162306a36Sopenharmony_ci *
506262306a36Sopenharmony_ci * Post replay cleanup.
506362306a36Sopenharmony_ci */
506462306a36Sopenharmony_civoid ice_replay_post(struct ice_hw *hw)
506562306a36Sopenharmony_ci{
506662306a36Sopenharmony_ci	/* Delete old entries from replay filter list head */
506762306a36Sopenharmony_ci	ice_rm_all_sw_replay_rule_info(hw);
506862306a36Sopenharmony_ci	ice_sched_replay_agg(hw);
506962306a36Sopenharmony_ci}
507062306a36Sopenharmony_ci
507162306a36Sopenharmony_ci/**
507262306a36Sopenharmony_ci * ice_stat_update40 - read 40 bit stat from the chip and update stat values
507362306a36Sopenharmony_ci * @hw: ptr to the hardware info
507462306a36Sopenharmony_ci * @reg: offset of 64 bit HW register to read from
507562306a36Sopenharmony_ci * @prev_stat_loaded: bool to specify if previous stats are loaded
507662306a36Sopenharmony_ci * @prev_stat: ptr to previous loaded stat value
507762306a36Sopenharmony_ci * @cur_stat: ptr to current stat value
507862306a36Sopenharmony_ci */
507962306a36Sopenharmony_civoid
508062306a36Sopenharmony_ciice_stat_update40(struct ice_hw *hw, u32 reg, bool prev_stat_loaded,
508162306a36Sopenharmony_ci		  u64 *prev_stat, u64 *cur_stat)
508262306a36Sopenharmony_ci{
508362306a36Sopenharmony_ci	u64 new_data = rd64(hw, reg) & (BIT_ULL(40) - 1);
508462306a36Sopenharmony_ci
508562306a36Sopenharmony_ci	/* device stats are not reset at PFR, they likely will not be zeroed
508662306a36Sopenharmony_ci	 * when the driver starts. Thus, save the value from the first read
508762306a36Sopenharmony_ci	 * without adding to the statistic value so that we report stats which
508862306a36Sopenharmony_ci	 * count up from zero.
508962306a36Sopenharmony_ci	 */
509062306a36Sopenharmony_ci	if (!prev_stat_loaded) {
509162306a36Sopenharmony_ci		*prev_stat = new_data;
509262306a36Sopenharmony_ci		return;
509362306a36Sopenharmony_ci	}
509462306a36Sopenharmony_ci
509562306a36Sopenharmony_ci	/* Calculate the difference between the new and old values, and then
509662306a36Sopenharmony_ci	 * add it to the software stat value.
509762306a36Sopenharmony_ci	 */
509862306a36Sopenharmony_ci	if (new_data >= *prev_stat)
509962306a36Sopenharmony_ci		*cur_stat += new_data - *prev_stat;
510062306a36Sopenharmony_ci	else
510162306a36Sopenharmony_ci		/* to manage the potential roll-over */
510262306a36Sopenharmony_ci		*cur_stat += (new_data + BIT_ULL(40)) - *prev_stat;
510362306a36Sopenharmony_ci
510462306a36Sopenharmony_ci	/* Update the previously stored value to prepare for next read */
510562306a36Sopenharmony_ci	*prev_stat = new_data;
510662306a36Sopenharmony_ci}
510762306a36Sopenharmony_ci
510862306a36Sopenharmony_ci/**
510962306a36Sopenharmony_ci * ice_stat_update32 - read 32 bit stat from the chip and update stat values
511062306a36Sopenharmony_ci * @hw: ptr to the hardware info
511162306a36Sopenharmony_ci * @reg: offset of HW register to read from
511262306a36Sopenharmony_ci * @prev_stat_loaded: bool to specify if previous stats are loaded
511362306a36Sopenharmony_ci * @prev_stat: ptr to previous loaded stat value
511462306a36Sopenharmony_ci * @cur_stat: ptr to current stat value
511562306a36Sopenharmony_ci */
511662306a36Sopenharmony_civoid
511762306a36Sopenharmony_ciice_stat_update32(struct ice_hw *hw, u32 reg, bool prev_stat_loaded,
511862306a36Sopenharmony_ci		  u64 *prev_stat, u64 *cur_stat)
511962306a36Sopenharmony_ci{
512062306a36Sopenharmony_ci	u32 new_data;
512162306a36Sopenharmony_ci
512262306a36Sopenharmony_ci	new_data = rd32(hw, reg);
512362306a36Sopenharmony_ci
512462306a36Sopenharmony_ci	/* device stats are not reset at PFR, they likely will not be zeroed
512562306a36Sopenharmony_ci	 * when the driver starts. Thus, save the value from the first read
512662306a36Sopenharmony_ci	 * without adding to the statistic value so that we report stats which
512762306a36Sopenharmony_ci	 * count up from zero.
512862306a36Sopenharmony_ci	 */
512962306a36Sopenharmony_ci	if (!prev_stat_loaded) {
513062306a36Sopenharmony_ci		*prev_stat = new_data;
513162306a36Sopenharmony_ci		return;
513262306a36Sopenharmony_ci	}
513362306a36Sopenharmony_ci
513462306a36Sopenharmony_ci	/* Calculate the difference between the new and old values, and then
513562306a36Sopenharmony_ci	 * add it to the software stat value.
513662306a36Sopenharmony_ci	 */
513762306a36Sopenharmony_ci	if (new_data >= *prev_stat)
513862306a36Sopenharmony_ci		*cur_stat += new_data - *prev_stat;
513962306a36Sopenharmony_ci	else
514062306a36Sopenharmony_ci		/* to manage the potential roll-over */
514162306a36Sopenharmony_ci		*cur_stat += (new_data + BIT_ULL(32)) - *prev_stat;
514262306a36Sopenharmony_ci
514362306a36Sopenharmony_ci	/* Update the previously stored value to prepare for next read */
514462306a36Sopenharmony_ci	*prev_stat = new_data;
514562306a36Sopenharmony_ci}
514662306a36Sopenharmony_ci
514762306a36Sopenharmony_ci/**
514862306a36Sopenharmony_ci * ice_sched_query_elem - query element information from HW
514962306a36Sopenharmony_ci * @hw: pointer to the HW struct
515062306a36Sopenharmony_ci * @node_teid: node TEID to be queried
515162306a36Sopenharmony_ci * @buf: buffer to element information
515262306a36Sopenharmony_ci *
515362306a36Sopenharmony_ci * This function queries HW element information
515462306a36Sopenharmony_ci */
515562306a36Sopenharmony_ciint
515662306a36Sopenharmony_ciice_sched_query_elem(struct ice_hw *hw, u32 node_teid,
515762306a36Sopenharmony_ci		     struct ice_aqc_txsched_elem_data *buf)
515862306a36Sopenharmony_ci{
515962306a36Sopenharmony_ci	u16 buf_size, num_elem_ret = 0;
516062306a36Sopenharmony_ci	int status;
516162306a36Sopenharmony_ci
516262306a36Sopenharmony_ci	buf_size = sizeof(*buf);
516362306a36Sopenharmony_ci	memset(buf, 0, buf_size);
516462306a36Sopenharmony_ci	buf->node_teid = cpu_to_le32(node_teid);
516562306a36Sopenharmony_ci	status = ice_aq_query_sched_elems(hw, 1, buf, buf_size, &num_elem_ret,
516662306a36Sopenharmony_ci					  NULL);
516762306a36Sopenharmony_ci	if (status || num_elem_ret != 1)
516862306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_SCHED, "query element failed\n");
516962306a36Sopenharmony_ci	return status;
517062306a36Sopenharmony_ci}
517162306a36Sopenharmony_ci
517262306a36Sopenharmony_ci/**
517362306a36Sopenharmony_ci * ice_aq_read_i2c
517462306a36Sopenharmony_ci * @hw: pointer to the hw struct
517562306a36Sopenharmony_ci * @topo_addr: topology address for a device to communicate with
517662306a36Sopenharmony_ci * @bus_addr: 7-bit I2C bus address
517762306a36Sopenharmony_ci * @addr: I2C memory address (I2C offset) with up to 16 bits
517862306a36Sopenharmony_ci * @params: I2C parameters: bit [7] - Repeated start,
517962306a36Sopenharmony_ci *			    bits [6:5] data offset size,
518062306a36Sopenharmony_ci *			    bit [4] - I2C address type,
518162306a36Sopenharmony_ci *			    bits [3:0] - data size to read (0-16 bytes)
518262306a36Sopenharmony_ci * @data: pointer to data (0 to 16 bytes) to be read from the I2C device
518362306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL
518462306a36Sopenharmony_ci *
518562306a36Sopenharmony_ci * Read I2C (0x06E2)
518662306a36Sopenharmony_ci */
518762306a36Sopenharmony_ciint
518862306a36Sopenharmony_ciice_aq_read_i2c(struct ice_hw *hw, struct ice_aqc_link_topo_addr topo_addr,
518962306a36Sopenharmony_ci		u16 bus_addr, __le16 addr, u8 params, u8 *data,
519062306a36Sopenharmony_ci		struct ice_sq_cd *cd)
519162306a36Sopenharmony_ci{
519262306a36Sopenharmony_ci	struct ice_aq_desc desc = { 0 };
519362306a36Sopenharmony_ci	struct ice_aqc_i2c *cmd;
519462306a36Sopenharmony_ci	u8 data_size;
519562306a36Sopenharmony_ci	int status;
519662306a36Sopenharmony_ci
519762306a36Sopenharmony_ci	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_read_i2c);
519862306a36Sopenharmony_ci	cmd = &desc.params.read_write_i2c;
519962306a36Sopenharmony_ci
520062306a36Sopenharmony_ci	if (!data)
520162306a36Sopenharmony_ci		return -EINVAL;
520262306a36Sopenharmony_ci
520362306a36Sopenharmony_ci	data_size = FIELD_GET(ICE_AQC_I2C_DATA_SIZE_M, params);
520462306a36Sopenharmony_ci
520562306a36Sopenharmony_ci	cmd->i2c_bus_addr = cpu_to_le16(bus_addr);
520662306a36Sopenharmony_ci	cmd->topo_addr = topo_addr;
520762306a36Sopenharmony_ci	cmd->i2c_params = params;
520862306a36Sopenharmony_ci	cmd->i2c_addr = addr;
520962306a36Sopenharmony_ci
521062306a36Sopenharmony_ci	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
521162306a36Sopenharmony_ci	if (!status) {
521262306a36Sopenharmony_ci		struct ice_aqc_read_i2c_resp *resp;
521362306a36Sopenharmony_ci		u8 i;
521462306a36Sopenharmony_ci
521562306a36Sopenharmony_ci		resp = &desc.params.read_i2c_resp;
521662306a36Sopenharmony_ci		for (i = 0; i < data_size; i++) {
521762306a36Sopenharmony_ci			*data = resp->i2c_data[i];
521862306a36Sopenharmony_ci			data++;
521962306a36Sopenharmony_ci		}
522062306a36Sopenharmony_ci	}
522162306a36Sopenharmony_ci
522262306a36Sopenharmony_ci	return status;
522362306a36Sopenharmony_ci}
522462306a36Sopenharmony_ci
522562306a36Sopenharmony_ci/**
522662306a36Sopenharmony_ci * ice_aq_write_i2c
522762306a36Sopenharmony_ci * @hw: pointer to the hw struct
522862306a36Sopenharmony_ci * @topo_addr: topology address for a device to communicate with
522962306a36Sopenharmony_ci * @bus_addr: 7-bit I2C bus address
523062306a36Sopenharmony_ci * @addr: I2C memory address (I2C offset) with up to 16 bits
523162306a36Sopenharmony_ci * @params: I2C parameters: bit [4] - I2C address type, bits [3:0] - data size to write (0-7 bytes)
523262306a36Sopenharmony_ci * @data: pointer to data (0 to 4 bytes) to be written to the I2C device
523362306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL
523462306a36Sopenharmony_ci *
523562306a36Sopenharmony_ci * Write I2C (0x06E3)
523662306a36Sopenharmony_ci *
523762306a36Sopenharmony_ci * * Return:
523862306a36Sopenharmony_ci * * 0             - Successful write to the i2c device
523962306a36Sopenharmony_ci * * -EINVAL       - Data size greater than 4 bytes
524062306a36Sopenharmony_ci * * -EIO          - FW error
524162306a36Sopenharmony_ci */
524262306a36Sopenharmony_ciint
524362306a36Sopenharmony_ciice_aq_write_i2c(struct ice_hw *hw, struct ice_aqc_link_topo_addr topo_addr,
524462306a36Sopenharmony_ci		 u16 bus_addr, __le16 addr, u8 params, const u8 *data,
524562306a36Sopenharmony_ci		 struct ice_sq_cd *cd)
524662306a36Sopenharmony_ci{
524762306a36Sopenharmony_ci	struct ice_aq_desc desc = { 0 };
524862306a36Sopenharmony_ci	struct ice_aqc_i2c *cmd;
524962306a36Sopenharmony_ci	u8 data_size;
525062306a36Sopenharmony_ci
525162306a36Sopenharmony_ci	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_write_i2c);
525262306a36Sopenharmony_ci	cmd = &desc.params.read_write_i2c;
525362306a36Sopenharmony_ci
525462306a36Sopenharmony_ci	data_size = FIELD_GET(ICE_AQC_I2C_DATA_SIZE_M, params);
525562306a36Sopenharmony_ci
525662306a36Sopenharmony_ci	/* data_size limited to 4 */
525762306a36Sopenharmony_ci	if (data_size > 4)
525862306a36Sopenharmony_ci		return -EINVAL;
525962306a36Sopenharmony_ci
526062306a36Sopenharmony_ci	cmd->i2c_bus_addr = cpu_to_le16(bus_addr);
526162306a36Sopenharmony_ci	cmd->topo_addr = topo_addr;
526262306a36Sopenharmony_ci	cmd->i2c_params = params;
526362306a36Sopenharmony_ci	cmd->i2c_addr = addr;
526462306a36Sopenharmony_ci
526562306a36Sopenharmony_ci	memcpy(cmd->i2c_data, data, data_size);
526662306a36Sopenharmony_ci
526762306a36Sopenharmony_ci	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
526862306a36Sopenharmony_ci}
526962306a36Sopenharmony_ci
527062306a36Sopenharmony_ci/**
527162306a36Sopenharmony_ci * ice_aq_set_driver_param - Set driver parameter to share via firmware
527262306a36Sopenharmony_ci * @hw: pointer to the HW struct
527362306a36Sopenharmony_ci * @idx: parameter index to set
527462306a36Sopenharmony_ci * @value: the value to set the parameter to
527562306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL
527662306a36Sopenharmony_ci *
527762306a36Sopenharmony_ci * Set the value of one of the software defined parameters. All PFs connected
527862306a36Sopenharmony_ci * to this device can read the value using ice_aq_get_driver_param.
527962306a36Sopenharmony_ci *
528062306a36Sopenharmony_ci * Note that firmware provides no synchronization or locking, and will not
528162306a36Sopenharmony_ci * save the parameter value during a device reset. It is expected that
528262306a36Sopenharmony_ci * a single PF will write the parameter value, while all other PFs will only
528362306a36Sopenharmony_ci * read it.
528462306a36Sopenharmony_ci */
528562306a36Sopenharmony_ciint
528662306a36Sopenharmony_ciice_aq_set_driver_param(struct ice_hw *hw, enum ice_aqc_driver_params idx,
528762306a36Sopenharmony_ci			u32 value, struct ice_sq_cd *cd)
528862306a36Sopenharmony_ci{
528962306a36Sopenharmony_ci	struct ice_aqc_driver_shared_params *cmd;
529062306a36Sopenharmony_ci	struct ice_aq_desc desc;
529162306a36Sopenharmony_ci
529262306a36Sopenharmony_ci	if (idx >= ICE_AQC_DRIVER_PARAM_MAX)
529362306a36Sopenharmony_ci		return -EIO;
529462306a36Sopenharmony_ci
529562306a36Sopenharmony_ci	cmd = &desc.params.drv_shared_params;
529662306a36Sopenharmony_ci
529762306a36Sopenharmony_ci	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_driver_shared_params);
529862306a36Sopenharmony_ci
529962306a36Sopenharmony_ci	cmd->set_or_get_op = ICE_AQC_DRIVER_PARAM_SET;
530062306a36Sopenharmony_ci	cmd->param_indx = idx;
530162306a36Sopenharmony_ci	cmd->param_val = cpu_to_le32(value);
530262306a36Sopenharmony_ci
530362306a36Sopenharmony_ci	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
530462306a36Sopenharmony_ci}
530562306a36Sopenharmony_ci
530662306a36Sopenharmony_ci/**
530762306a36Sopenharmony_ci * ice_aq_get_driver_param - Get driver parameter shared via firmware
530862306a36Sopenharmony_ci * @hw: pointer to the HW struct
530962306a36Sopenharmony_ci * @idx: parameter index to set
531062306a36Sopenharmony_ci * @value: storage to return the shared parameter
531162306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL
531262306a36Sopenharmony_ci *
531362306a36Sopenharmony_ci * Get the value of one of the software defined parameters.
531462306a36Sopenharmony_ci *
531562306a36Sopenharmony_ci * Note that firmware provides no synchronization or locking. It is expected
531662306a36Sopenharmony_ci * that only a single PF will write a given parameter.
531762306a36Sopenharmony_ci */
531862306a36Sopenharmony_ciint
531962306a36Sopenharmony_ciice_aq_get_driver_param(struct ice_hw *hw, enum ice_aqc_driver_params idx,
532062306a36Sopenharmony_ci			u32 *value, struct ice_sq_cd *cd)
532162306a36Sopenharmony_ci{
532262306a36Sopenharmony_ci	struct ice_aqc_driver_shared_params *cmd;
532362306a36Sopenharmony_ci	struct ice_aq_desc desc;
532462306a36Sopenharmony_ci	int status;
532562306a36Sopenharmony_ci
532662306a36Sopenharmony_ci	if (idx >= ICE_AQC_DRIVER_PARAM_MAX)
532762306a36Sopenharmony_ci		return -EIO;
532862306a36Sopenharmony_ci
532962306a36Sopenharmony_ci	cmd = &desc.params.drv_shared_params;
533062306a36Sopenharmony_ci
533162306a36Sopenharmony_ci	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_driver_shared_params);
533262306a36Sopenharmony_ci
533362306a36Sopenharmony_ci	cmd->set_or_get_op = ICE_AQC_DRIVER_PARAM_GET;
533462306a36Sopenharmony_ci	cmd->param_indx = idx;
533562306a36Sopenharmony_ci
533662306a36Sopenharmony_ci	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
533762306a36Sopenharmony_ci	if (status)
533862306a36Sopenharmony_ci		return status;
533962306a36Sopenharmony_ci
534062306a36Sopenharmony_ci	*value = le32_to_cpu(cmd->param_val);
534162306a36Sopenharmony_ci
534262306a36Sopenharmony_ci	return 0;
534362306a36Sopenharmony_ci}
534462306a36Sopenharmony_ci
534562306a36Sopenharmony_ci/**
534662306a36Sopenharmony_ci * ice_aq_set_gpio
534762306a36Sopenharmony_ci * @hw: pointer to the hw struct
534862306a36Sopenharmony_ci * @gpio_ctrl_handle: GPIO controller node handle
534962306a36Sopenharmony_ci * @pin_idx: IO Number of the GPIO that needs to be set
535062306a36Sopenharmony_ci * @value: SW provide IO value to set in the LSB
535162306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL
535262306a36Sopenharmony_ci *
535362306a36Sopenharmony_ci * Sends 0x06EC AQ command to set the GPIO pin state that's part of the topology
535462306a36Sopenharmony_ci */
535562306a36Sopenharmony_ciint
535662306a36Sopenharmony_ciice_aq_set_gpio(struct ice_hw *hw, u16 gpio_ctrl_handle, u8 pin_idx, bool value,
535762306a36Sopenharmony_ci		struct ice_sq_cd *cd)
535862306a36Sopenharmony_ci{
535962306a36Sopenharmony_ci	struct ice_aqc_gpio *cmd;
536062306a36Sopenharmony_ci	struct ice_aq_desc desc;
536162306a36Sopenharmony_ci
536262306a36Sopenharmony_ci	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_gpio);
536362306a36Sopenharmony_ci	cmd = &desc.params.read_write_gpio;
536462306a36Sopenharmony_ci	cmd->gpio_ctrl_handle = cpu_to_le16(gpio_ctrl_handle);
536562306a36Sopenharmony_ci	cmd->gpio_num = pin_idx;
536662306a36Sopenharmony_ci	cmd->gpio_val = value ? 1 : 0;
536762306a36Sopenharmony_ci
536862306a36Sopenharmony_ci	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
536962306a36Sopenharmony_ci}
537062306a36Sopenharmony_ci
537162306a36Sopenharmony_ci/**
537262306a36Sopenharmony_ci * ice_aq_get_gpio
537362306a36Sopenharmony_ci * @hw: pointer to the hw struct
537462306a36Sopenharmony_ci * @gpio_ctrl_handle: GPIO controller node handle
537562306a36Sopenharmony_ci * @pin_idx: IO Number of the GPIO that needs to be set
537662306a36Sopenharmony_ci * @value: IO value read
537762306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL
537862306a36Sopenharmony_ci *
537962306a36Sopenharmony_ci * Sends 0x06ED AQ command to get the value of a GPIO signal which is part of
538062306a36Sopenharmony_ci * the topology
538162306a36Sopenharmony_ci */
538262306a36Sopenharmony_ciint
538362306a36Sopenharmony_ciice_aq_get_gpio(struct ice_hw *hw, u16 gpio_ctrl_handle, u8 pin_idx,
538462306a36Sopenharmony_ci		bool *value, struct ice_sq_cd *cd)
538562306a36Sopenharmony_ci{
538662306a36Sopenharmony_ci	struct ice_aqc_gpio *cmd;
538762306a36Sopenharmony_ci	struct ice_aq_desc desc;
538862306a36Sopenharmony_ci	int status;
538962306a36Sopenharmony_ci
539062306a36Sopenharmony_ci	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_gpio);
539162306a36Sopenharmony_ci	cmd = &desc.params.read_write_gpio;
539262306a36Sopenharmony_ci	cmd->gpio_ctrl_handle = cpu_to_le16(gpio_ctrl_handle);
539362306a36Sopenharmony_ci	cmd->gpio_num = pin_idx;
539462306a36Sopenharmony_ci
539562306a36Sopenharmony_ci	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
539662306a36Sopenharmony_ci	if (status)
539762306a36Sopenharmony_ci		return status;
539862306a36Sopenharmony_ci
539962306a36Sopenharmony_ci	*value = !!cmd->gpio_val;
540062306a36Sopenharmony_ci	return 0;
540162306a36Sopenharmony_ci}
540262306a36Sopenharmony_ci
540362306a36Sopenharmony_ci/**
540462306a36Sopenharmony_ci * ice_is_fw_api_min_ver
540562306a36Sopenharmony_ci * @hw: pointer to the hardware structure
540662306a36Sopenharmony_ci * @maj: major version
540762306a36Sopenharmony_ci * @min: minor version
540862306a36Sopenharmony_ci * @patch: patch version
540962306a36Sopenharmony_ci *
541062306a36Sopenharmony_ci * Checks if the firmware API is minimum version
541162306a36Sopenharmony_ci */
541262306a36Sopenharmony_cistatic bool ice_is_fw_api_min_ver(struct ice_hw *hw, u8 maj, u8 min, u8 patch)
541362306a36Sopenharmony_ci{
541462306a36Sopenharmony_ci	if (hw->api_maj_ver == maj) {
541562306a36Sopenharmony_ci		if (hw->api_min_ver > min)
541662306a36Sopenharmony_ci			return true;
541762306a36Sopenharmony_ci		if (hw->api_min_ver == min && hw->api_patch >= patch)
541862306a36Sopenharmony_ci			return true;
541962306a36Sopenharmony_ci	} else if (hw->api_maj_ver > maj) {
542062306a36Sopenharmony_ci		return true;
542162306a36Sopenharmony_ci	}
542262306a36Sopenharmony_ci
542362306a36Sopenharmony_ci	return false;
542462306a36Sopenharmony_ci}
542562306a36Sopenharmony_ci
542662306a36Sopenharmony_ci/**
542762306a36Sopenharmony_ci * ice_fw_supports_link_override
542862306a36Sopenharmony_ci * @hw: pointer to the hardware structure
542962306a36Sopenharmony_ci *
543062306a36Sopenharmony_ci * Checks if the firmware supports link override
543162306a36Sopenharmony_ci */
543262306a36Sopenharmony_cibool ice_fw_supports_link_override(struct ice_hw *hw)
543362306a36Sopenharmony_ci{
543462306a36Sopenharmony_ci	return ice_is_fw_api_min_ver(hw, ICE_FW_API_LINK_OVERRIDE_MAJ,
543562306a36Sopenharmony_ci				     ICE_FW_API_LINK_OVERRIDE_MIN,
543662306a36Sopenharmony_ci				     ICE_FW_API_LINK_OVERRIDE_PATCH);
543762306a36Sopenharmony_ci}
543862306a36Sopenharmony_ci
543962306a36Sopenharmony_ci/**
544062306a36Sopenharmony_ci * ice_get_link_default_override
544162306a36Sopenharmony_ci * @ldo: pointer to the link default override struct
544262306a36Sopenharmony_ci * @pi: pointer to the port info struct
544362306a36Sopenharmony_ci *
544462306a36Sopenharmony_ci * Gets the link default override for a port
544562306a36Sopenharmony_ci */
544662306a36Sopenharmony_ciint
544762306a36Sopenharmony_ciice_get_link_default_override(struct ice_link_default_override_tlv *ldo,
544862306a36Sopenharmony_ci			      struct ice_port_info *pi)
544962306a36Sopenharmony_ci{
545062306a36Sopenharmony_ci	u16 i, tlv, tlv_len, tlv_start, buf, offset;
545162306a36Sopenharmony_ci	struct ice_hw *hw = pi->hw;
545262306a36Sopenharmony_ci	int status;
545362306a36Sopenharmony_ci
545462306a36Sopenharmony_ci	status = ice_get_pfa_module_tlv(hw, &tlv, &tlv_len,
545562306a36Sopenharmony_ci					ICE_SR_LINK_DEFAULT_OVERRIDE_PTR);
545662306a36Sopenharmony_ci	if (status) {
545762306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_INIT, "Failed to read link override TLV.\n");
545862306a36Sopenharmony_ci		return status;
545962306a36Sopenharmony_ci	}
546062306a36Sopenharmony_ci
546162306a36Sopenharmony_ci	/* Each port has its own config; calculate for our port */
546262306a36Sopenharmony_ci	tlv_start = tlv + pi->lport * ICE_SR_PFA_LINK_OVERRIDE_WORDS +
546362306a36Sopenharmony_ci		ICE_SR_PFA_LINK_OVERRIDE_OFFSET;
546462306a36Sopenharmony_ci
546562306a36Sopenharmony_ci	/* link options first */
546662306a36Sopenharmony_ci	status = ice_read_sr_word(hw, tlv_start, &buf);
546762306a36Sopenharmony_ci	if (status) {
546862306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_INIT, "Failed to read override link options.\n");
546962306a36Sopenharmony_ci		return status;
547062306a36Sopenharmony_ci	}
547162306a36Sopenharmony_ci	ldo->options = buf & ICE_LINK_OVERRIDE_OPT_M;
547262306a36Sopenharmony_ci	ldo->phy_config = (buf & ICE_LINK_OVERRIDE_PHY_CFG_M) >>
547362306a36Sopenharmony_ci		ICE_LINK_OVERRIDE_PHY_CFG_S;
547462306a36Sopenharmony_ci
547562306a36Sopenharmony_ci	/* link PHY config */
547662306a36Sopenharmony_ci	offset = tlv_start + ICE_SR_PFA_LINK_OVERRIDE_FEC_OFFSET;
547762306a36Sopenharmony_ci	status = ice_read_sr_word(hw, offset, &buf);
547862306a36Sopenharmony_ci	if (status) {
547962306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_INIT, "Failed to read override phy config.\n");
548062306a36Sopenharmony_ci		return status;
548162306a36Sopenharmony_ci	}
548262306a36Sopenharmony_ci	ldo->fec_options = buf & ICE_LINK_OVERRIDE_FEC_OPT_M;
548362306a36Sopenharmony_ci
548462306a36Sopenharmony_ci	/* PHY types low */
548562306a36Sopenharmony_ci	offset = tlv_start + ICE_SR_PFA_LINK_OVERRIDE_PHY_OFFSET;
548662306a36Sopenharmony_ci	for (i = 0; i < ICE_SR_PFA_LINK_OVERRIDE_PHY_WORDS; i++) {
548762306a36Sopenharmony_ci		status = ice_read_sr_word(hw, (offset + i), &buf);
548862306a36Sopenharmony_ci		if (status) {
548962306a36Sopenharmony_ci			ice_debug(hw, ICE_DBG_INIT, "Failed to read override link options.\n");
549062306a36Sopenharmony_ci			return status;
549162306a36Sopenharmony_ci		}
549262306a36Sopenharmony_ci		/* shift 16 bits at a time to fill 64 bits */
549362306a36Sopenharmony_ci		ldo->phy_type_low |= ((u64)buf << (i * 16));
549462306a36Sopenharmony_ci	}
549562306a36Sopenharmony_ci
549662306a36Sopenharmony_ci	/* PHY types high */
549762306a36Sopenharmony_ci	offset = tlv_start + ICE_SR_PFA_LINK_OVERRIDE_PHY_OFFSET +
549862306a36Sopenharmony_ci		ICE_SR_PFA_LINK_OVERRIDE_PHY_WORDS;
549962306a36Sopenharmony_ci	for (i = 0; i < ICE_SR_PFA_LINK_OVERRIDE_PHY_WORDS; i++) {
550062306a36Sopenharmony_ci		status = ice_read_sr_word(hw, (offset + i), &buf);
550162306a36Sopenharmony_ci		if (status) {
550262306a36Sopenharmony_ci			ice_debug(hw, ICE_DBG_INIT, "Failed to read override link options.\n");
550362306a36Sopenharmony_ci			return status;
550462306a36Sopenharmony_ci		}
550562306a36Sopenharmony_ci		/* shift 16 bits at a time to fill 64 bits */
550662306a36Sopenharmony_ci		ldo->phy_type_high |= ((u64)buf << (i * 16));
550762306a36Sopenharmony_ci	}
550862306a36Sopenharmony_ci
550962306a36Sopenharmony_ci	return status;
551062306a36Sopenharmony_ci}
551162306a36Sopenharmony_ci
551262306a36Sopenharmony_ci/**
551362306a36Sopenharmony_ci * ice_is_phy_caps_an_enabled - check if PHY capabilities autoneg is enabled
551462306a36Sopenharmony_ci * @caps: get PHY capability data
551562306a36Sopenharmony_ci */
551662306a36Sopenharmony_cibool ice_is_phy_caps_an_enabled(struct ice_aqc_get_phy_caps_data *caps)
551762306a36Sopenharmony_ci{
551862306a36Sopenharmony_ci	if (caps->caps & ICE_AQC_PHY_AN_MODE ||
551962306a36Sopenharmony_ci	    caps->low_power_ctrl_an & (ICE_AQC_PHY_AN_EN_CLAUSE28 |
552062306a36Sopenharmony_ci				       ICE_AQC_PHY_AN_EN_CLAUSE73 |
552162306a36Sopenharmony_ci				       ICE_AQC_PHY_AN_EN_CLAUSE37))
552262306a36Sopenharmony_ci		return true;
552362306a36Sopenharmony_ci
552462306a36Sopenharmony_ci	return false;
552562306a36Sopenharmony_ci}
552662306a36Sopenharmony_ci
552762306a36Sopenharmony_ci/**
552862306a36Sopenharmony_ci * ice_aq_set_lldp_mib - Set the LLDP MIB
552962306a36Sopenharmony_ci * @hw: pointer to the HW struct
553062306a36Sopenharmony_ci * @mib_type: Local, Remote or both Local and Remote MIBs
553162306a36Sopenharmony_ci * @buf: pointer to the caller-supplied buffer to store the MIB block
553262306a36Sopenharmony_ci * @buf_size: size of the buffer (in bytes)
553362306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL
553462306a36Sopenharmony_ci *
553562306a36Sopenharmony_ci * Set the LLDP MIB. (0x0A08)
553662306a36Sopenharmony_ci */
553762306a36Sopenharmony_ciint
553862306a36Sopenharmony_ciice_aq_set_lldp_mib(struct ice_hw *hw, u8 mib_type, void *buf, u16 buf_size,
553962306a36Sopenharmony_ci		    struct ice_sq_cd *cd)
554062306a36Sopenharmony_ci{
554162306a36Sopenharmony_ci	struct ice_aqc_lldp_set_local_mib *cmd;
554262306a36Sopenharmony_ci	struct ice_aq_desc desc;
554362306a36Sopenharmony_ci
554462306a36Sopenharmony_ci	cmd = &desc.params.lldp_set_mib;
554562306a36Sopenharmony_ci
554662306a36Sopenharmony_ci	if (buf_size == 0 || !buf)
554762306a36Sopenharmony_ci		return -EINVAL;
554862306a36Sopenharmony_ci
554962306a36Sopenharmony_ci	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_lldp_set_local_mib);
555062306a36Sopenharmony_ci
555162306a36Sopenharmony_ci	desc.flags |= cpu_to_le16((u16)ICE_AQ_FLAG_RD);
555262306a36Sopenharmony_ci	desc.datalen = cpu_to_le16(buf_size);
555362306a36Sopenharmony_ci
555462306a36Sopenharmony_ci	cmd->type = mib_type;
555562306a36Sopenharmony_ci	cmd->length = cpu_to_le16(buf_size);
555662306a36Sopenharmony_ci
555762306a36Sopenharmony_ci	return ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
555862306a36Sopenharmony_ci}
555962306a36Sopenharmony_ci
556062306a36Sopenharmony_ci/**
556162306a36Sopenharmony_ci * ice_fw_supports_lldp_fltr_ctrl - check NVM version supports lldp_fltr_ctrl
556262306a36Sopenharmony_ci * @hw: pointer to HW struct
556362306a36Sopenharmony_ci */
556462306a36Sopenharmony_cibool ice_fw_supports_lldp_fltr_ctrl(struct ice_hw *hw)
556562306a36Sopenharmony_ci{
556662306a36Sopenharmony_ci	if (hw->mac_type != ICE_MAC_E810)
556762306a36Sopenharmony_ci		return false;
556862306a36Sopenharmony_ci
556962306a36Sopenharmony_ci	return ice_is_fw_api_min_ver(hw, ICE_FW_API_LLDP_FLTR_MAJ,
557062306a36Sopenharmony_ci				     ICE_FW_API_LLDP_FLTR_MIN,
557162306a36Sopenharmony_ci				     ICE_FW_API_LLDP_FLTR_PATCH);
557262306a36Sopenharmony_ci}
557362306a36Sopenharmony_ci
557462306a36Sopenharmony_ci/**
557562306a36Sopenharmony_ci * ice_lldp_fltr_add_remove - add or remove a LLDP Rx switch filter
557662306a36Sopenharmony_ci * @hw: pointer to HW struct
557762306a36Sopenharmony_ci * @vsi_num: absolute HW index for VSI
557862306a36Sopenharmony_ci * @add: boolean for if adding or removing a filter
557962306a36Sopenharmony_ci */
558062306a36Sopenharmony_ciint
558162306a36Sopenharmony_ciice_lldp_fltr_add_remove(struct ice_hw *hw, u16 vsi_num, bool add)
558262306a36Sopenharmony_ci{
558362306a36Sopenharmony_ci	struct ice_aqc_lldp_filter_ctrl *cmd;
558462306a36Sopenharmony_ci	struct ice_aq_desc desc;
558562306a36Sopenharmony_ci
558662306a36Sopenharmony_ci	cmd = &desc.params.lldp_filter_ctrl;
558762306a36Sopenharmony_ci
558862306a36Sopenharmony_ci	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_lldp_filter_ctrl);
558962306a36Sopenharmony_ci
559062306a36Sopenharmony_ci	if (add)
559162306a36Sopenharmony_ci		cmd->cmd_flags = ICE_AQC_LLDP_FILTER_ACTION_ADD;
559262306a36Sopenharmony_ci	else
559362306a36Sopenharmony_ci		cmd->cmd_flags = ICE_AQC_LLDP_FILTER_ACTION_DELETE;
559462306a36Sopenharmony_ci
559562306a36Sopenharmony_ci	cmd->vsi_num = cpu_to_le16(vsi_num);
559662306a36Sopenharmony_ci
559762306a36Sopenharmony_ci	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
559862306a36Sopenharmony_ci}
559962306a36Sopenharmony_ci
560062306a36Sopenharmony_ci/**
560162306a36Sopenharmony_ci * ice_lldp_execute_pending_mib - execute LLDP pending MIB request
560262306a36Sopenharmony_ci * @hw: pointer to HW struct
560362306a36Sopenharmony_ci */
560462306a36Sopenharmony_ciint ice_lldp_execute_pending_mib(struct ice_hw *hw)
560562306a36Sopenharmony_ci{
560662306a36Sopenharmony_ci	struct ice_aq_desc desc;
560762306a36Sopenharmony_ci
560862306a36Sopenharmony_ci	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_lldp_execute_pending_mib);
560962306a36Sopenharmony_ci
561062306a36Sopenharmony_ci	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
561162306a36Sopenharmony_ci}
561262306a36Sopenharmony_ci
561362306a36Sopenharmony_ci/**
561462306a36Sopenharmony_ci * ice_fw_supports_report_dflt_cfg
561562306a36Sopenharmony_ci * @hw: pointer to the hardware structure
561662306a36Sopenharmony_ci *
561762306a36Sopenharmony_ci * Checks if the firmware supports report default configuration
561862306a36Sopenharmony_ci */
561962306a36Sopenharmony_cibool ice_fw_supports_report_dflt_cfg(struct ice_hw *hw)
562062306a36Sopenharmony_ci{
562162306a36Sopenharmony_ci	return ice_is_fw_api_min_ver(hw, ICE_FW_API_REPORT_DFLT_CFG_MAJ,
562262306a36Sopenharmony_ci				     ICE_FW_API_REPORT_DFLT_CFG_MIN,
562362306a36Sopenharmony_ci				     ICE_FW_API_REPORT_DFLT_CFG_PATCH);
562462306a36Sopenharmony_ci}
562562306a36Sopenharmony_ci
562662306a36Sopenharmony_ci/* each of the indexes into the following array match the speed of a return
562762306a36Sopenharmony_ci * value from the list of AQ returned speeds like the range:
562862306a36Sopenharmony_ci * ICE_AQ_LINK_SPEED_10MB .. ICE_AQ_LINK_SPEED_100GB excluding
562962306a36Sopenharmony_ci * ICE_AQ_LINK_SPEED_UNKNOWN which is BIT(15) and maps to BIT(14) in this
563062306a36Sopenharmony_ci * array. The array is defined as 15 elements long because the link_speed
563162306a36Sopenharmony_ci * returned by the firmware is a 16 bit * value, but is indexed
563262306a36Sopenharmony_ci * by [fls(speed) - 1]
563362306a36Sopenharmony_ci */
563462306a36Sopenharmony_cistatic const u32 ice_aq_to_link_speed[] = {
563562306a36Sopenharmony_ci	SPEED_10,	/* BIT(0) */
563662306a36Sopenharmony_ci	SPEED_100,
563762306a36Sopenharmony_ci	SPEED_1000,
563862306a36Sopenharmony_ci	SPEED_2500,
563962306a36Sopenharmony_ci	SPEED_5000,
564062306a36Sopenharmony_ci	SPEED_10000,
564162306a36Sopenharmony_ci	SPEED_20000,
564262306a36Sopenharmony_ci	SPEED_25000,
564362306a36Sopenharmony_ci	SPEED_40000,
564462306a36Sopenharmony_ci	SPEED_50000,
564562306a36Sopenharmony_ci	SPEED_100000,	/* BIT(10) */
564662306a36Sopenharmony_ci};
564762306a36Sopenharmony_ci
564862306a36Sopenharmony_ci/**
564962306a36Sopenharmony_ci * ice_get_link_speed - get integer speed from table
565062306a36Sopenharmony_ci * @index: array index from fls(aq speed) - 1
565162306a36Sopenharmony_ci *
565262306a36Sopenharmony_ci * Returns: u32 value containing integer speed
565362306a36Sopenharmony_ci */
565462306a36Sopenharmony_ciu32 ice_get_link_speed(u16 index)
565562306a36Sopenharmony_ci{
565662306a36Sopenharmony_ci	if (index >= ARRAY_SIZE(ice_aq_to_link_speed))
565762306a36Sopenharmony_ci		return 0;
565862306a36Sopenharmony_ci
565962306a36Sopenharmony_ci	return ice_aq_to_link_speed[index];
566062306a36Sopenharmony_ci}
5661