xref: /openbmc/linux/drivers/net/ethernet/intel/ice/ice_common.c (revision 0f9b4c3ca5fdf3e177266ef994071b1a03f07318)
17ec59eeaSAnirudh Venkataramanan // SPDX-License-Identifier: GPL-2.0
2*88f7ac6cSPaul Greenwalt /* Copyright (c) 2018-2023, Intel Corporation. */
37ec59eeaSAnirudh Venkataramanan 
47ec59eeaSAnirudh Venkataramanan #include "ice_common.h"
59c20346bSAnirudh Venkataramanan #include "ice_sched.h"
67ec59eeaSAnirudh Venkataramanan #include "ice_adminq_cmd.h"
7c90ed40cSTony Nguyen #include "ice_flow.h"
8272ad794SKarol Kolacinski #include "ice_ptp_hw.h"
97ec59eeaSAnirudh Venkataramanan 
1071245072SJacob Keller #define ICE_PF_RESET_WAIT_COUNT	300
11f31e4b6fSAnirudh Venkataramanan 
12f8c74ca6SAnirudh Venkataramanan static const char * const ice_link_mode_str_low[] = {
13f8c74ca6SAnirudh Venkataramanan 	[0] = "100BASE_TX",
14f8c74ca6SAnirudh Venkataramanan 	[1] = "100M_SGMII",
15f8c74ca6SAnirudh Venkataramanan 	[2] = "1000BASE_T",
16f8c74ca6SAnirudh Venkataramanan 	[3] = "1000BASE_SX",
17f8c74ca6SAnirudh Venkataramanan 	[4] = "1000BASE_LX",
18f8c74ca6SAnirudh Venkataramanan 	[5] = "1000BASE_KX",
19f8c74ca6SAnirudh Venkataramanan 	[6] = "1G_SGMII",
20f8c74ca6SAnirudh Venkataramanan 	[7] = "2500BASE_T",
21f8c74ca6SAnirudh Venkataramanan 	[8] = "2500BASE_X",
22f8c74ca6SAnirudh Venkataramanan 	[9] = "2500BASE_KX",
23f8c74ca6SAnirudh Venkataramanan 	[10] = "5GBASE_T",
24f8c74ca6SAnirudh Venkataramanan 	[11] = "5GBASE_KR",
25f8c74ca6SAnirudh Venkataramanan 	[12] = "10GBASE_T",
26f8c74ca6SAnirudh Venkataramanan 	[13] = "10G_SFI_DA",
27f8c74ca6SAnirudh Venkataramanan 	[14] = "10GBASE_SR",
28f8c74ca6SAnirudh Venkataramanan 	[15] = "10GBASE_LR",
29f8c74ca6SAnirudh Venkataramanan 	[16] = "10GBASE_KR_CR1",
30f8c74ca6SAnirudh Venkataramanan 	[17] = "10G_SFI_AOC_ACC",
31f8c74ca6SAnirudh Venkataramanan 	[18] = "10G_SFI_C2C",
32f8c74ca6SAnirudh Venkataramanan 	[19] = "25GBASE_T",
33f8c74ca6SAnirudh Venkataramanan 	[20] = "25GBASE_CR",
34f8c74ca6SAnirudh Venkataramanan 	[21] = "25GBASE_CR_S",
35f8c74ca6SAnirudh Venkataramanan 	[22] = "25GBASE_CR1",
36f8c74ca6SAnirudh Venkataramanan 	[23] = "25GBASE_SR",
37f8c74ca6SAnirudh Venkataramanan 	[24] = "25GBASE_LR",
38f8c74ca6SAnirudh Venkataramanan 	[25] = "25GBASE_KR",
39f8c74ca6SAnirudh Venkataramanan 	[26] = "25GBASE_KR_S",
40f8c74ca6SAnirudh Venkataramanan 	[27] = "25GBASE_KR1",
41f8c74ca6SAnirudh Venkataramanan 	[28] = "25G_AUI_AOC_ACC",
42f8c74ca6SAnirudh Venkataramanan 	[29] = "25G_AUI_C2C",
43f8c74ca6SAnirudh Venkataramanan 	[30] = "40GBASE_CR4",
44f8c74ca6SAnirudh Venkataramanan 	[31] = "40GBASE_SR4",
45f8c74ca6SAnirudh Venkataramanan 	[32] = "40GBASE_LR4",
46f8c74ca6SAnirudh Venkataramanan 	[33] = "40GBASE_KR4",
47f8c74ca6SAnirudh Venkataramanan 	[34] = "40G_XLAUI_AOC_ACC",
48f8c74ca6SAnirudh Venkataramanan 	[35] = "40G_XLAUI",
49f8c74ca6SAnirudh Venkataramanan 	[36] = "50GBASE_CR2",
50f8c74ca6SAnirudh Venkataramanan 	[37] = "50GBASE_SR2",
51f8c74ca6SAnirudh Venkataramanan 	[38] = "50GBASE_LR2",
52f8c74ca6SAnirudh Venkataramanan 	[39] = "50GBASE_KR2",
53f8c74ca6SAnirudh Venkataramanan 	[40] = "50G_LAUI2_AOC_ACC",
54f8c74ca6SAnirudh Venkataramanan 	[41] = "50G_LAUI2",
55f8c74ca6SAnirudh Venkataramanan 	[42] = "50G_AUI2_AOC_ACC",
56f8c74ca6SAnirudh Venkataramanan 	[43] = "50G_AUI2",
57f8c74ca6SAnirudh Venkataramanan 	[44] = "50GBASE_CP",
58f8c74ca6SAnirudh Venkataramanan 	[45] = "50GBASE_SR",
59f8c74ca6SAnirudh Venkataramanan 	[46] = "50GBASE_FR",
60f8c74ca6SAnirudh Venkataramanan 	[47] = "50GBASE_LR",
61f8c74ca6SAnirudh Venkataramanan 	[48] = "50GBASE_KR_PAM4",
62f8c74ca6SAnirudh Venkataramanan 	[49] = "50G_AUI1_AOC_ACC",
63f8c74ca6SAnirudh Venkataramanan 	[50] = "50G_AUI1",
64f8c74ca6SAnirudh Venkataramanan 	[51] = "100GBASE_CR4",
65f8c74ca6SAnirudh Venkataramanan 	[52] = "100GBASE_SR4",
66f8c74ca6SAnirudh Venkataramanan 	[53] = "100GBASE_LR4",
67f8c74ca6SAnirudh Venkataramanan 	[54] = "100GBASE_KR4",
68f8c74ca6SAnirudh Venkataramanan 	[55] = "100G_CAUI4_AOC_ACC",
69f8c74ca6SAnirudh Venkataramanan 	[56] = "100G_CAUI4",
70f8c74ca6SAnirudh Venkataramanan 	[57] = "100G_AUI4_AOC_ACC",
71f8c74ca6SAnirudh Venkataramanan 	[58] = "100G_AUI4",
72f8c74ca6SAnirudh Venkataramanan 	[59] = "100GBASE_CR_PAM4",
73f8c74ca6SAnirudh Venkataramanan 	[60] = "100GBASE_KR_PAM4",
74f8c74ca6SAnirudh Venkataramanan 	[61] = "100GBASE_CP2",
75f8c74ca6SAnirudh Venkataramanan 	[62] = "100GBASE_SR2",
76f8c74ca6SAnirudh Venkataramanan 	[63] = "100GBASE_DR",
77f8c74ca6SAnirudh Venkataramanan };
78f8c74ca6SAnirudh Venkataramanan 
79f8c74ca6SAnirudh Venkataramanan static const char * const ice_link_mode_str_high[] = {
80f8c74ca6SAnirudh Venkataramanan 	[0] = "100GBASE_KR2_PAM4",
81f8c74ca6SAnirudh Venkataramanan 	[1] = "100G_CAUI2_AOC_ACC",
82f8c74ca6SAnirudh Venkataramanan 	[2] = "100G_CAUI2",
83f8c74ca6SAnirudh Venkataramanan 	[3] = "100G_AUI2_AOC_ACC",
84f8c74ca6SAnirudh Venkataramanan 	[4] = "100G_AUI2",
85f8c74ca6SAnirudh Venkataramanan };
86f8c74ca6SAnirudh Venkataramanan 
87f8c74ca6SAnirudh Venkataramanan /**
88f8c74ca6SAnirudh Venkataramanan  * ice_dump_phy_type - helper function to dump phy_type
89f8c74ca6SAnirudh Venkataramanan  * @hw: pointer to the HW structure
90f8c74ca6SAnirudh Venkataramanan  * @low: 64 bit value for phy_type_low
91f8c74ca6SAnirudh Venkataramanan  * @high: 64 bit value for phy_type_high
92f8c74ca6SAnirudh Venkataramanan  * @prefix: prefix string to differentiate multiple dumps
93f8c74ca6SAnirudh Venkataramanan  */
94f8c74ca6SAnirudh Venkataramanan static void
ice_dump_phy_type(struct ice_hw * hw,u64 low,u64 high,const char * prefix)95f8c74ca6SAnirudh Venkataramanan ice_dump_phy_type(struct ice_hw *hw, u64 low, u64 high, const char *prefix)
96f8c74ca6SAnirudh Venkataramanan {
97f8c74ca6SAnirudh Venkataramanan 	ice_debug(hw, ICE_DBG_PHY, "%s: phy_type_low: 0x%016llx\n", prefix, low);
98f8c74ca6SAnirudh Venkataramanan 
99f8c74ca6SAnirudh Venkataramanan 	for (u32 i = 0; i < BITS_PER_TYPE(typeof(low)); i++) {
100f8c74ca6SAnirudh Venkataramanan 		if (low & BIT_ULL(i))
101f8c74ca6SAnirudh Venkataramanan 			ice_debug(hw, ICE_DBG_PHY, "%s:   bit(%d): %s\n",
102f8c74ca6SAnirudh Venkataramanan 				  prefix, i, ice_link_mode_str_low[i]);
103f8c74ca6SAnirudh Venkataramanan 	}
104f8c74ca6SAnirudh Venkataramanan 
105f8c74ca6SAnirudh Venkataramanan 	ice_debug(hw, ICE_DBG_PHY, "%s: phy_type_high: 0x%016llx\n", prefix, high);
106f8c74ca6SAnirudh Venkataramanan 
107f8c74ca6SAnirudh Venkataramanan 	for (u32 i = 0; i < BITS_PER_TYPE(typeof(high)); i++) {
108f8c74ca6SAnirudh Venkataramanan 		if (high & BIT_ULL(i))
109f8c74ca6SAnirudh Venkataramanan 			ice_debug(hw, ICE_DBG_PHY, "%s:   bit(%d): %s\n",
110f8c74ca6SAnirudh Venkataramanan 				  prefix, i, ice_link_mode_str_high[i]);
111f8c74ca6SAnirudh Venkataramanan 	}
112f8c74ca6SAnirudh Venkataramanan }
113f8c74ca6SAnirudh Venkataramanan 
114f31e4b6fSAnirudh Venkataramanan /**
115f31e4b6fSAnirudh Venkataramanan  * ice_set_mac_type - Sets MAC type
116f31e4b6fSAnirudh Venkataramanan  * @hw: pointer to the HW structure
117f31e4b6fSAnirudh Venkataramanan  *
118f31e4b6fSAnirudh Venkataramanan  * This function sets the MAC type of the adapter based on the
119f9867df6SAnirudh Venkataramanan  * vendor ID and device ID stored in the HW structure.
120f31e4b6fSAnirudh Venkataramanan  */
ice_set_mac_type(struct ice_hw * hw)1215e24d598STony Nguyen static int ice_set_mac_type(struct ice_hw *hw)
122f31e4b6fSAnirudh Venkataramanan {
123f31e4b6fSAnirudh Venkataramanan 	if (hw->vendor_id != PCI_VENDOR_ID_INTEL)
124d54699e2STony Nguyen 		return -ENODEV;
125f31e4b6fSAnirudh Venkataramanan 
126ea78ce4dSPaul Greenwalt 	switch (hw->device_id) {
127ea78ce4dSPaul Greenwalt 	case ICE_DEV_ID_E810C_BACKPLANE:
128ea78ce4dSPaul Greenwalt 	case ICE_DEV_ID_E810C_QSFP:
129ea78ce4dSPaul Greenwalt 	case ICE_DEV_ID_E810C_SFP:
1307dcf78b8STony Nguyen 	case ICE_DEV_ID_E810_XXV_BACKPLANE:
1317dcf78b8STony Nguyen 	case ICE_DEV_ID_E810_XXV_QSFP:
132ea78ce4dSPaul Greenwalt 	case ICE_DEV_ID_E810_XXV_SFP:
133ea78ce4dSPaul Greenwalt 		hw->mac_type = ICE_MAC_E810;
134ea78ce4dSPaul Greenwalt 		break;
135ea78ce4dSPaul Greenwalt 	case ICE_DEV_ID_E823C_10G_BASE_T:
136ea78ce4dSPaul Greenwalt 	case ICE_DEV_ID_E823C_BACKPLANE:
137ea78ce4dSPaul Greenwalt 	case ICE_DEV_ID_E823C_QSFP:
138ea78ce4dSPaul Greenwalt 	case ICE_DEV_ID_E823C_SFP:
139ea78ce4dSPaul Greenwalt 	case ICE_DEV_ID_E823C_SGMII:
140ea78ce4dSPaul Greenwalt 	case ICE_DEV_ID_E822C_10G_BASE_T:
141ea78ce4dSPaul Greenwalt 	case ICE_DEV_ID_E822C_BACKPLANE:
142ea78ce4dSPaul Greenwalt 	case ICE_DEV_ID_E822C_QSFP:
143ea78ce4dSPaul Greenwalt 	case ICE_DEV_ID_E822C_SFP:
144ea78ce4dSPaul Greenwalt 	case ICE_DEV_ID_E822C_SGMII:
145ea78ce4dSPaul Greenwalt 	case ICE_DEV_ID_E822L_10G_BASE_T:
146ea78ce4dSPaul Greenwalt 	case ICE_DEV_ID_E822L_BACKPLANE:
147ea78ce4dSPaul Greenwalt 	case ICE_DEV_ID_E822L_SFP:
148ea78ce4dSPaul Greenwalt 	case ICE_DEV_ID_E822L_SGMII:
149ea78ce4dSPaul Greenwalt 	case ICE_DEV_ID_E823L_10G_BASE_T:
150ea78ce4dSPaul Greenwalt 	case ICE_DEV_ID_E823L_1GBE:
151ea78ce4dSPaul Greenwalt 	case ICE_DEV_ID_E823L_BACKPLANE:
152ea78ce4dSPaul Greenwalt 	case ICE_DEV_ID_E823L_QSFP:
153ea78ce4dSPaul Greenwalt 	case ICE_DEV_ID_E823L_SFP:
154f31e4b6fSAnirudh Venkataramanan 		hw->mac_type = ICE_MAC_GENERIC;
155ea78ce4dSPaul Greenwalt 		break;
156*88f7ac6cSPaul Greenwalt 	case ICE_DEV_ID_E830_BACKPLANE:
157*88f7ac6cSPaul Greenwalt 	case ICE_DEV_ID_E830_QSFP56:
158*88f7ac6cSPaul Greenwalt 	case ICE_DEV_ID_E830_SFP:
159*88f7ac6cSPaul Greenwalt 	case ICE_DEV_ID_E830_SFP_DD:
160*88f7ac6cSPaul Greenwalt 		hw->mac_type = ICE_MAC_E830;
161*88f7ac6cSPaul Greenwalt 		break;
162ea78ce4dSPaul Greenwalt 	default:
163ea78ce4dSPaul Greenwalt 		hw->mac_type = ICE_MAC_UNKNOWN;
164ea78ce4dSPaul Greenwalt 		break;
165ea78ce4dSPaul Greenwalt 	}
166ea78ce4dSPaul Greenwalt 
167ea78ce4dSPaul Greenwalt 	ice_debug(hw, ICE_DBG_INIT, "mac_type: %d\n", hw->mac_type);
168f31e4b6fSAnirudh Venkataramanan 	return 0;
169f31e4b6fSAnirudh Venkataramanan }
170f31e4b6fSAnirudh Venkataramanan 
171f31e4b6fSAnirudh Venkataramanan /**
17206c16d89SJacob Keller  * ice_is_e810
17306c16d89SJacob Keller  * @hw: pointer to the hardware structure
17406c16d89SJacob Keller  *
17506c16d89SJacob Keller  * returns true if the device is E810 based, false if not.
17606c16d89SJacob Keller  */
ice_is_e810(struct ice_hw * hw)17706c16d89SJacob Keller bool ice_is_e810(struct ice_hw *hw)
17806c16d89SJacob Keller {
17906c16d89SJacob Keller 	return hw->mac_type == ICE_MAC_E810;
18006c16d89SJacob Keller }
18106c16d89SJacob Keller 
18206c16d89SJacob Keller /**
183885fe693SMaciej Machnikowski  * ice_is_e810t
184885fe693SMaciej Machnikowski  * @hw: pointer to the hardware structure
185885fe693SMaciej Machnikowski  *
186885fe693SMaciej Machnikowski  * returns true if the device is E810T based, false if not.
187885fe693SMaciej Machnikowski  */
ice_is_e810t(struct ice_hw * hw)188885fe693SMaciej Machnikowski bool ice_is_e810t(struct ice_hw *hw)
189885fe693SMaciej Machnikowski {
190885fe693SMaciej Machnikowski 	switch (hw->device_id) {
191885fe693SMaciej Machnikowski 	case ICE_DEV_ID_E810C_SFP:
192793189a2SArkadiusz Kubalewski 		switch (hw->subsystem_device_id) {
193793189a2SArkadiusz Kubalewski 		case ICE_SUBDEV_ID_E810T:
194793189a2SArkadiusz Kubalewski 		case ICE_SUBDEV_ID_E810T2:
195793189a2SArkadiusz Kubalewski 		case ICE_SUBDEV_ID_E810T3:
196793189a2SArkadiusz Kubalewski 		case ICE_SUBDEV_ID_E810T4:
197793189a2SArkadiusz Kubalewski 		case ICE_SUBDEV_ID_E810T6:
198793189a2SArkadiusz Kubalewski 		case ICE_SUBDEV_ID_E810T7:
199885fe693SMaciej Machnikowski 			return true;
200793189a2SArkadiusz Kubalewski 		}
201793189a2SArkadiusz Kubalewski 		break;
202793189a2SArkadiusz Kubalewski 	case ICE_DEV_ID_E810C_QSFP:
203793189a2SArkadiusz Kubalewski 		switch (hw->subsystem_device_id) {
204793189a2SArkadiusz Kubalewski 		case ICE_SUBDEV_ID_E810T2:
205793189a2SArkadiusz Kubalewski 		case ICE_SUBDEV_ID_E810T3:
206793189a2SArkadiusz Kubalewski 		case ICE_SUBDEV_ID_E810T5:
207793189a2SArkadiusz Kubalewski 			return true;
208793189a2SArkadiusz Kubalewski 		}
209885fe693SMaciej Machnikowski 		break;
210885fe693SMaciej Machnikowski 	default:
211885fe693SMaciej Machnikowski 		break;
212885fe693SMaciej Machnikowski 	}
213885fe693SMaciej Machnikowski 
214885fe693SMaciej Machnikowski 	return false;
215885fe693SMaciej Machnikowski }
216885fe693SMaciej Machnikowski 
217885fe693SMaciej Machnikowski /**
218634d841dSKarol Kolacinski  * ice_is_e823
219634d841dSKarol Kolacinski  * @hw: pointer to the hardware structure
220634d841dSKarol Kolacinski  *
221634d841dSKarol Kolacinski  * returns true if the device is E823-L or E823-C based, false if not.
222634d841dSKarol Kolacinski  */
ice_is_e823(struct ice_hw * hw)223634d841dSKarol Kolacinski bool ice_is_e823(struct ice_hw *hw)
224634d841dSKarol Kolacinski {
225634d841dSKarol Kolacinski 	switch (hw->device_id) {
226634d841dSKarol Kolacinski 	case ICE_DEV_ID_E823L_BACKPLANE:
227634d841dSKarol Kolacinski 	case ICE_DEV_ID_E823L_SFP:
228634d841dSKarol Kolacinski 	case ICE_DEV_ID_E823L_10G_BASE_T:
229634d841dSKarol Kolacinski 	case ICE_DEV_ID_E823L_1GBE:
230634d841dSKarol Kolacinski 	case ICE_DEV_ID_E823L_QSFP:
231634d841dSKarol Kolacinski 	case ICE_DEV_ID_E823C_BACKPLANE:
232634d841dSKarol Kolacinski 	case ICE_DEV_ID_E823C_QSFP:
233634d841dSKarol Kolacinski 	case ICE_DEV_ID_E823C_SFP:
234634d841dSKarol Kolacinski 	case ICE_DEV_ID_E823C_10G_BASE_T:
235634d841dSKarol Kolacinski 	case ICE_DEV_ID_E823C_SGMII:
236634d841dSKarol Kolacinski 		return true;
237634d841dSKarol Kolacinski 	default:
238634d841dSKarol Kolacinski 		return false;
239634d841dSKarol Kolacinski 	}
240634d841dSKarol Kolacinski }
241634d841dSKarol Kolacinski 
242634d841dSKarol Kolacinski /**
243f31e4b6fSAnirudh Venkataramanan  * ice_clear_pf_cfg - Clear PF configuration
244f31e4b6fSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
2453968540bSAnirudh Venkataramanan  *
2463968540bSAnirudh Venkataramanan  * Clears any existing PF configuration (VSIs, VSI lists, switch rules, port
2473968540bSAnirudh Venkataramanan  * configuration, flow director filters, etc.).
248f31e4b6fSAnirudh Venkataramanan  */
ice_clear_pf_cfg(struct ice_hw * hw)2495e24d598STony Nguyen int ice_clear_pf_cfg(struct ice_hw *hw)
250f31e4b6fSAnirudh Venkataramanan {
251f31e4b6fSAnirudh Venkataramanan 	struct ice_aq_desc desc;
252f31e4b6fSAnirudh Venkataramanan 
253f31e4b6fSAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_clear_pf_cfg);
254f31e4b6fSAnirudh Venkataramanan 
255f31e4b6fSAnirudh Venkataramanan 	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
256f31e4b6fSAnirudh Venkataramanan }
257f31e4b6fSAnirudh Venkataramanan 
258f31e4b6fSAnirudh Venkataramanan /**
259dc49c772SAnirudh Venkataramanan  * ice_aq_manage_mac_read - manage MAC address read command
260f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
261dc49c772SAnirudh Venkataramanan  * @buf: a virtual buffer to hold the manage MAC read response
262dc49c772SAnirudh Venkataramanan  * @buf_size: Size of the virtual buffer
263dc49c772SAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
264dc49c772SAnirudh Venkataramanan  *
265dc49c772SAnirudh Venkataramanan  * This function is used to return per PF station MAC address (0x0107).
266dc49c772SAnirudh Venkataramanan  * NOTE: Upon successful completion of this command, MAC address information
267dc49c772SAnirudh Venkataramanan  * is returned in user specified buffer. Please interpret user specified
268dc49c772SAnirudh Venkataramanan  * buffer as "manage_mac_read" response.
269dc49c772SAnirudh Venkataramanan  * Response such as various MAC addresses are stored in HW struct (port.mac)
27081aed647SJacob Keller  * ice_discover_dev_caps is expected to be called before this function is
27181aed647SJacob Keller  * called.
272dc49c772SAnirudh Venkataramanan  */
2735e24d598STony Nguyen static int
ice_aq_manage_mac_read(struct ice_hw * hw,void * buf,u16 buf_size,struct ice_sq_cd * cd)274dc49c772SAnirudh Venkataramanan ice_aq_manage_mac_read(struct ice_hw *hw, void *buf, u16 buf_size,
275dc49c772SAnirudh Venkataramanan 		       struct ice_sq_cd *cd)
276dc49c772SAnirudh Venkataramanan {
277dc49c772SAnirudh Venkataramanan 	struct ice_aqc_manage_mac_read_resp *resp;
278dc49c772SAnirudh Venkataramanan 	struct ice_aqc_manage_mac_read *cmd;
279dc49c772SAnirudh Venkataramanan 	struct ice_aq_desc desc;
2805e24d598STony Nguyen 	int status;
281dc49c772SAnirudh Venkataramanan 	u16 flags;
282d6fef10cSMd Fahad Iqbal Polash 	u8 i;
283dc49c772SAnirudh Venkataramanan 
284dc49c772SAnirudh Venkataramanan 	cmd = &desc.params.mac_read;
285dc49c772SAnirudh Venkataramanan 
286dc49c772SAnirudh Venkataramanan 	if (buf_size < sizeof(*resp))
287d54699e2STony Nguyen 		return -EINVAL;
288dc49c772SAnirudh Venkataramanan 
289dc49c772SAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_manage_mac_read);
290dc49c772SAnirudh Venkataramanan 
291dc49c772SAnirudh Venkataramanan 	status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
292dc49c772SAnirudh Venkataramanan 	if (status)
293dc49c772SAnirudh Venkataramanan 		return status;
294dc49c772SAnirudh Venkataramanan 
2957a63dae0SBruce Allan 	resp = buf;
296dc49c772SAnirudh Venkataramanan 	flags = le16_to_cpu(cmd->flags) & ICE_AQC_MAN_MAC_READ_M;
297dc49c772SAnirudh Venkataramanan 
298dc49c772SAnirudh Venkataramanan 	if (!(flags & ICE_AQC_MAN_MAC_LAN_ADDR_VALID)) {
299dc49c772SAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_LAN, "got invalid MAC address\n");
300d54699e2STony Nguyen 		return -EIO;
301dc49c772SAnirudh Venkataramanan 	}
302dc49c772SAnirudh Venkataramanan 
303d6fef10cSMd Fahad Iqbal Polash 	/* A single port can report up to two (LAN and WoL) addresses */
304d6fef10cSMd Fahad Iqbal Polash 	for (i = 0; i < cmd->num_addr; i++)
305d6fef10cSMd Fahad Iqbal Polash 		if (resp[i].addr_type == ICE_AQC_MAN_MAC_ADDR_TYPE_LAN) {
306d6fef10cSMd Fahad Iqbal Polash 			ether_addr_copy(hw->port_info->mac.lan_addr,
307d6fef10cSMd Fahad Iqbal Polash 					resp[i].mac_addr);
308d6fef10cSMd Fahad Iqbal Polash 			ether_addr_copy(hw->port_info->mac.perm_addr,
309d6fef10cSMd Fahad Iqbal Polash 					resp[i].mac_addr);
310d6fef10cSMd Fahad Iqbal Polash 			break;
311d6fef10cSMd Fahad Iqbal Polash 		}
312d6fef10cSMd Fahad Iqbal Polash 
313dc49c772SAnirudh Venkataramanan 	return 0;
314dc49c772SAnirudh Venkataramanan }
315dc49c772SAnirudh Venkataramanan 
316dc49c772SAnirudh Venkataramanan /**
317dc49c772SAnirudh Venkataramanan  * ice_aq_get_phy_caps - returns PHY capabilities
318dc49c772SAnirudh Venkataramanan  * @pi: port information structure
319dc49c772SAnirudh Venkataramanan  * @qual_mods: report qualified modules
320dc49c772SAnirudh Venkataramanan  * @report_mode: report mode capabilities
321dc49c772SAnirudh Venkataramanan  * @pcaps: structure for PHY capabilities to be filled
322dc49c772SAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
323dc49c772SAnirudh Venkataramanan  *
324dc49c772SAnirudh Venkataramanan  * Returns the various PHY capabilities supported on the Port (0x0600)
325dc49c772SAnirudh Venkataramanan  */
3265e24d598STony Nguyen int
ice_aq_get_phy_caps(struct ice_port_info * pi,bool qual_mods,u8 report_mode,struct ice_aqc_get_phy_caps_data * pcaps,struct ice_sq_cd * cd)327dc49c772SAnirudh Venkataramanan ice_aq_get_phy_caps(struct ice_port_info *pi, bool qual_mods, u8 report_mode,
328dc49c772SAnirudh Venkataramanan 		    struct ice_aqc_get_phy_caps_data *pcaps,
329dc49c772SAnirudh Venkataramanan 		    struct ice_sq_cd *cd)
330dc49c772SAnirudh Venkataramanan {
331dc49c772SAnirudh Venkataramanan 	struct ice_aqc_get_phy_caps *cmd;
332dc49c772SAnirudh Venkataramanan 	u16 pcaps_size = sizeof(*pcaps);
333dc49c772SAnirudh Venkataramanan 	struct ice_aq_desc desc;
334f8c74ca6SAnirudh Venkataramanan 	const char *prefix;
33555df52a0SPaul Greenwalt 	struct ice_hw *hw;
3365518ac2aSTony Nguyen 	int status;
337dc49c772SAnirudh Venkataramanan 
338dc49c772SAnirudh Venkataramanan 	cmd = &desc.params.get_phy;
339dc49c772SAnirudh Venkataramanan 
340dc49c772SAnirudh Venkataramanan 	if (!pcaps || (report_mode & ~ICE_AQC_REPORT_MODE_M) || !pi)
341d54699e2STony Nguyen 		return -EINVAL;
34255df52a0SPaul Greenwalt 	hw = pi->hw;
343dc49c772SAnirudh Venkataramanan 
3440a02944fSAnirudh Venkataramanan 	if (report_mode == ICE_AQC_REPORT_DFLT_CFG &&
3450a02944fSAnirudh Venkataramanan 	    !ice_fw_supports_report_dflt_cfg(hw))
346d54699e2STony Nguyen 		return -EINVAL;
3470a02944fSAnirudh Venkataramanan 
348dc49c772SAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_phy_caps);
349dc49c772SAnirudh Venkataramanan 
350dc49c772SAnirudh Venkataramanan 	if (qual_mods)
351dc49c772SAnirudh Venkataramanan 		cmd->param0 |= cpu_to_le16(ICE_AQC_GET_PHY_RQM);
352dc49c772SAnirudh Venkataramanan 
353dc49c772SAnirudh Venkataramanan 	cmd->param0 |= cpu_to_le16(report_mode);
35455df52a0SPaul Greenwalt 	status = ice_aq_send_cmd(hw, &desc, pcaps, pcaps_size, cd);
35555df52a0SPaul Greenwalt 
356f8c74ca6SAnirudh Venkataramanan 	ice_debug(hw, ICE_DBG_LINK, "get phy caps dump\n");
357f8c74ca6SAnirudh Venkataramanan 
358f8c74ca6SAnirudh Venkataramanan 	switch (report_mode) {
359f8c74ca6SAnirudh Venkataramanan 	case ICE_AQC_REPORT_TOPO_CAP_MEDIA:
360f8c74ca6SAnirudh Venkataramanan 		prefix = "phy_caps_media";
361f8c74ca6SAnirudh Venkataramanan 		break;
362f8c74ca6SAnirudh Venkataramanan 	case ICE_AQC_REPORT_TOPO_CAP_NO_MEDIA:
363f8c74ca6SAnirudh Venkataramanan 		prefix = "phy_caps_no_media";
364f8c74ca6SAnirudh Venkataramanan 		break;
365f8c74ca6SAnirudh Venkataramanan 	case ICE_AQC_REPORT_ACTIVE_CFG:
366f8c74ca6SAnirudh Venkataramanan 		prefix = "phy_caps_active";
367f8c74ca6SAnirudh Venkataramanan 		break;
368f8c74ca6SAnirudh Venkataramanan 	case ICE_AQC_REPORT_DFLT_CFG:
369f8c74ca6SAnirudh Venkataramanan 		prefix = "phy_caps_default";
370f8c74ca6SAnirudh Venkataramanan 		break;
371f8c74ca6SAnirudh Venkataramanan 	default:
372f8c74ca6SAnirudh Venkataramanan 		prefix = "phy_caps_invalid";
373f8c74ca6SAnirudh Venkataramanan 	}
374f8c74ca6SAnirudh Venkataramanan 
375f8c74ca6SAnirudh Venkataramanan 	ice_dump_phy_type(hw, le64_to_cpu(pcaps->phy_type_low),
376f8c74ca6SAnirudh Venkataramanan 			  le64_to_cpu(pcaps->phy_type_high), prefix);
377f8c74ca6SAnirudh Venkataramanan 
378f8c74ca6SAnirudh Venkataramanan 	ice_debug(hw, ICE_DBG_LINK, "%s: report_mode = 0x%x\n",
379f8c74ca6SAnirudh Venkataramanan 		  prefix, report_mode);
380f8c74ca6SAnirudh Venkataramanan 	ice_debug(hw, ICE_DBG_LINK, "%s: caps = 0x%x\n", prefix, pcaps->caps);
381f8c74ca6SAnirudh Venkataramanan 	ice_debug(hw, ICE_DBG_LINK, "%s: low_power_ctrl_an = 0x%x\n", prefix,
382bdeff971SLev Faerman 		  pcaps->low_power_ctrl_an);
383f8c74ca6SAnirudh Venkataramanan 	ice_debug(hw, ICE_DBG_LINK, "%s: eee_cap = 0x%x\n", prefix,
384f8c74ca6SAnirudh Venkataramanan 		  pcaps->eee_cap);
385f8c74ca6SAnirudh Venkataramanan 	ice_debug(hw, ICE_DBG_LINK, "%s: eeer_value = 0x%x\n", prefix,
38655df52a0SPaul Greenwalt 		  pcaps->eeer_value);
387f8c74ca6SAnirudh Venkataramanan 	ice_debug(hw, ICE_DBG_LINK, "%s: link_fec_options = 0x%x\n", prefix,
38855df52a0SPaul Greenwalt 		  pcaps->link_fec_options);
389f8c74ca6SAnirudh Venkataramanan 	ice_debug(hw, ICE_DBG_LINK, "%s: module_compliance_enforcement = 0x%x\n",
390f8c74ca6SAnirudh Venkataramanan 		  prefix, pcaps->module_compliance_enforcement);
391f8c74ca6SAnirudh Venkataramanan 	ice_debug(hw, ICE_DBG_LINK, "%s: extended_compliance_code = 0x%x\n",
392f8c74ca6SAnirudh Venkataramanan 		  prefix, pcaps->extended_compliance_code);
393f8c74ca6SAnirudh Venkataramanan 	ice_debug(hw, ICE_DBG_LINK, "%s: module_type[0] = 0x%x\n", prefix,
39455df52a0SPaul Greenwalt 		  pcaps->module_type[0]);
395f8c74ca6SAnirudh Venkataramanan 	ice_debug(hw, ICE_DBG_LINK, "%s: module_type[1] = 0x%x\n", prefix,
39655df52a0SPaul Greenwalt 		  pcaps->module_type[1]);
397f8c74ca6SAnirudh Venkataramanan 	ice_debug(hw, ICE_DBG_LINK, "%s: module_type[2] = 0x%x\n", prefix,
39855df52a0SPaul Greenwalt 		  pcaps->module_type[2]);
399dc49c772SAnirudh Venkataramanan 
400d6730a87SAnirudh Venkataramanan 	if (!status && report_mode == ICE_AQC_REPORT_TOPO_CAP_MEDIA) {
401dc49c772SAnirudh Venkataramanan 		pi->phy.phy_type_low = le64_to_cpu(pcaps->phy_type_low);
402aef74145SAnirudh Venkataramanan 		pi->phy.phy_type_high = le64_to_cpu(pcaps->phy_type_high);
403c2b35226SPaul M Stillwell Jr 		memcpy(pi->phy.link_info.module_type, &pcaps->module_type,
404c2b35226SPaul M Stillwell Jr 		       sizeof(pi->phy.link_info.module_type));
405aef74145SAnirudh Venkataramanan 	}
406dc49c772SAnirudh Venkataramanan 
407dc49c772SAnirudh Venkataramanan 	return status;
408dc49c772SAnirudh Venkataramanan }
409dc49c772SAnirudh Venkataramanan 
410dc49c772SAnirudh Venkataramanan /**
4118ea1da59SPaul Greenwalt  * ice_aq_get_link_topo_handle - get link topology node return status
4128ea1da59SPaul Greenwalt  * @pi: port information structure
4138ea1da59SPaul Greenwalt  * @node_type: requested node type
4148ea1da59SPaul Greenwalt  * @cd: pointer to command details structure or NULL
4158ea1da59SPaul Greenwalt  *
4168ea1da59SPaul Greenwalt  * Get link topology node return status for specified node type (0x06E0)
4178ea1da59SPaul Greenwalt  *
4188ea1da59SPaul Greenwalt  * Node type cage can be used to determine if cage is present. If AQC
4198ea1da59SPaul Greenwalt  * returns error (ENOENT), then no cage present. If no cage present, then
4208ea1da59SPaul Greenwalt  * connection type is backplane or BASE-T.
4218ea1da59SPaul Greenwalt  */
4225e24d598STony Nguyen static int
ice_aq_get_link_topo_handle(struct ice_port_info * pi,u8 node_type,struct ice_sq_cd * cd)4238ea1da59SPaul Greenwalt ice_aq_get_link_topo_handle(struct ice_port_info *pi, u8 node_type,
4248ea1da59SPaul Greenwalt 			    struct ice_sq_cd *cd)
4258ea1da59SPaul Greenwalt {
4268ea1da59SPaul Greenwalt 	struct ice_aqc_get_link_topo *cmd;
4278ea1da59SPaul Greenwalt 	struct ice_aq_desc desc;
4288ea1da59SPaul Greenwalt 
4298ea1da59SPaul Greenwalt 	cmd = &desc.params.get_link_topo;
4308ea1da59SPaul Greenwalt 
4318ea1da59SPaul Greenwalt 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_link_topo);
4328ea1da59SPaul Greenwalt 
433e00ae1a2SMaciej Machnikowski 	cmd->addr.topo_params.node_type_ctx =
434e00ae1a2SMaciej Machnikowski 		(ICE_AQC_LINK_TOPO_NODE_CTX_PORT <<
4358ea1da59SPaul Greenwalt 		 ICE_AQC_LINK_TOPO_NODE_CTX_S);
4368ea1da59SPaul Greenwalt 
4378ea1da59SPaul Greenwalt 	/* set node type */
438e00ae1a2SMaciej Machnikowski 	cmd->addr.topo_params.node_type_ctx |=
439e00ae1a2SMaciej Machnikowski 		(ICE_AQC_LINK_TOPO_NODE_TYPE_M & node_type);
4408ea1da59SPaul Greenwalt 
4418ea1da59SPaul Greenwalt 	return ice_aq_send_cmd(pi->hw, &desc, NULL, 0, cd);
4428ea1da59SPaul Greenwalt }
4438ea1da59SPaul Greenwalt 
4448ea1da59SPaul Greenwalt /**
4458ea1da59SPaul Greenwalt  * ice_is_media_cage_present
4468ea1da59SPaul Greenwalt  * @pi: port information structure
4478ea1da59SPaul Greenwalt  *
4488ea1da59SPaul Greenwalt  * Returns true if media cage is present, else false. If no cage, then
4498ea1da59SPaul Greenwalt  * media type is backplane or BASE-T.
4508ea1da59SPaul Greenwalt  */
ice_is_media_cage_present(struct ice_port_info * pi)4518ea1da59SPaul Greenwalt static bool ice_is_media_cage_present(struct ice_port_info *pi)
4528ea1da59SPaul Greenwalt {
4538ea1da59SPaul Greenwalt 	/* Node type cage can be used to determine if cage is present. If AQC
4548ea1da59SPaul Greenwalt 	 * returns error (ENOENT), then no cage present. If no cage present then
4558ea1da59SPaul Greenwalt 	 * connection type is backplane or BASE-T.
4568ea1da59SPaul Greenwalt 	 */
4578ea1da59SPaul Greenwalt 	return !ice_aq_get_link_topo_handle(pi,
4588ea1da59SPaul Greenwalt 					    ICE_AQC_LINK_TOPO_NODE_TYPE_CAGE,
4598ea1da59SPaul Greenwalt 					    NULL);
4608ea1da59SPaul Greenwalt }
4618ea1da59SPaul Greenwalt 
4628ea1da59SPaul Greenwalt /**
463dc49c772SAnirudh Venkataramanan  * ice_get_media_type - Gets media type
464dc49c772SAnirudh Venkataramanan  * @pi: port information structure
465dc49c772SAnirudh Venkataramanan  */
ice_get_media_type(struct ice_port_info * pi)466dc49c772SAnirudh Venkataramanan static enum ice_media_type ice_get_media_type(struct ice_port_info *pi)
467dc49c772SAnirudh Venkataramanan {
468dc49c772SAnirudh Venkataramanan 	struct ice_link_status *hw_link_info;
469dc49c772SAnirudh Venkataramanan 
470dc49c772SAnirudh Venkataramanan 	if (!pi)
471dc49c772SAnirudh Venkataramanan 		return ICE_MEDIA_UNKNOWN;
472dc49c772SAnirudh Venkataramanan 
473dc49c772SAnirudh Venkataramanan 	hw_link_info = &pi->phy.link_info;
474aef74145SAnirudh Venkataramanan 	if (hw_link_info->phy_type_low && hw_link_info->phy_type_high)
475aef74145SAnirudh Venkataramanan 		/* If more than one media type is selected, report unknown */
476aef74145SAnirudh Venkataramanan 		return ICE_MEDIA_UNKNOWN;
477dc49c772SAnirudh Venkataramanan 
478dc49c772SAnirudh Venkataramanan 	if (hw_link_info->phy_type_low) {
479c2b35226SPaul M Stillwell Jr 		/* 1G SGMII is a special case where some DA cable PHYs
480c2b35226SPaul M Stillwell Jr 		 * may show this as an option when it really shouldn't
481c2b35226SPaul M Stillwell Jr 		 * be since SGMII is meant to be between a MAC and a PHY
482c2b35226SPaul M Stillwell Jr 		 * in a backplane. Try to detect this case and handle it
483c2b35226SPaul M Stillwell Jr 		 */
484c2b35226SPaul M Stillwell Jr 		if (hw_link_info->phy_type_low == ICE_PHY_TYPE_LOW_1G_SGMII &&
485c2b35226SPaul M Stillwell Jr 		    (hw_link_info->module_type[ICE_AQC_MOD_TYPE_IDENT] ==
486c2b35226SPaul M Stillwell Jr 		    ICE_AQC_MOD_TYPE_BYTE1_SFP_PLUS_CU_ACTIVE ||
487c2b35226SPaul M Stillwell Jr 		    hw_link_info->module_type[ICE_AQC_MOD_TYPE_IDENT] ==
488c2b35226SPaul M Stillwell Jr 		    ICE_AQC_MOD_TYPE_BYTE1_SFP_PLUS_CU_PASSIVE))
489c2b35226SPaul M Stillwell Jr 			return ICE_MEDIA_DA;
490c2b35226SPaul M Stillwell Jr 
491dc49c772SAnirudh Venkataramanan 		switch (hw_link_info->phy_type_low) {
492dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_1000BASE_SX:
493dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_1000BASE_LX:
494dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_10GBASE_SR:
495dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_10GBASE_LR:
496dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_10G_SFI_C2C:
497dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_25GBASE_SR:
498dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_25GBASE_LR:
499dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_40GBASE_SR4:
500dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_40GBASE_LR4:
501aef74145SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_50GBASE_SR2:
502aef74145SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_50GBASE_LR2:
503aef74145SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_50GBASE_SR:
504aef74145SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_50GBASE_FR:
505aef74145SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_50GBASE_LR:
506aef74145SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_100GBASE_SR4:
507aef74145SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_100GBASE_LR4:
508aef74145SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_100GBASE_SR2:
509aef74145SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_100GBASE_DR:
510c1eb3b6bSDoug Dziggel 		case ICE_PHY_TYPE_LOW_10G_SFI_AOC_ACC:
511c1eb3b6bSDoug Dziggel 		case ICE_PHY_TYPE_LOW_25G_AUI_AOC_ACC:
512c1eb3b6bSDoug Dziggel 		case ICE_PHY_TYPE_LOW_40G_XLAUI_AOC_ACC:
513c1eb3b6bSDoug Dziggel 		case ICE_PHY_TYPE_LOW_50G_LAUI2_AOC_ACC:
514c1eb3b6bSDoug Dziggel 		case ICE_PHY_TYPE_LOW_50G_AUI2_AOC_ACC:
515c1eb3b6bSDoug Dziggel 		case ICE_PHY_TYPE_LOW_50G_AUI1_AOC_ACC:
516c1eb3b6bSDoug Dziggel 		case ICE_PHY_TYPE_LOW_100G_CAUI4_AOC_ACC:
517c1eb3b6bSDoug Dziggel 		case ICE_PHY_TYPE_LOW_100G_AUI4_AOC_ACC:
518dc49c772SAnirudh Venkataramanan 			return ICE_MEDIA_FIBER;
519dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_100BASE_TX:
520dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_1000BASE_T:
521dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_2500BASE_T:
522dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_5GBASE_T:
523dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_10GBASE_T:
524dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_25GBASE_T:
525dc49c772SAnirudh Venkataramanan 			return ICE_MEDIA_BASET;
526dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_10G_SFI_DA:
527dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_25GBASE_CR:
528dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_25GBASE_CR_S:
529dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_25GBASE_CR1:
530dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_40GBASE_CR4:
531aef74145SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_50GBASE_CR2:
532aef74145SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_50GBASE_CP:
533aef74145SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_100GBASE_CR4:
534aef74145SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_100GBASE_CR_PAM4:
535aef74145SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_100GBASE_CP2:
536dc49c772SAnirudh Venkataramanan 			return ICE_MEDIA_DA;
5378ea1da59SPaul Greenwalt 		case ICE_PHY_TYPE_LOW_25G_AUI_C2C:
5388ea1da59SPaul Greenwalt 		case ICE_PHY_TYPE_LOW_40G_XLAUI:
5398ea1da59SPaul Greenwalt 		case ICE_PHY_TYPE_LOW_50G_LAUI2:
5408ea1da59SPaul Greenwalt 		case ICE_PHY_TYPE_LOW_50G_AUI2:
5418ea1da59SPaul Greenwalt 		case ICE_PHY_TYPE_LOW_50G_AUI1:
5428ea1da59SPaul Greenwalt 		case ICE_PHY_TYPE_LOW_100G_AUI4:
5438ea1da59SPaul Greenwalt 		case ICE_PHY_TYPE_LOW_100G_CAUI4:
5448ea1da59SPaul Greenwalt 			if (ice_is_media_cage_present(pi))
5458ea1da59SPaul Greenwalt 				return ICE_MEDIA_DA;
5468ea1da59SPaul Greenwalt 			fallthrough;
547dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_1000BASE_KX:
548dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_2500BASE_KX:
549dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_2500BASE_X:
550dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_5GBASE_KR:
551dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_10GBASE_KR_CR1:
552dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_25GBASE_KR:
553dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_25GBASE_KR1:
554dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_25GBASE_KR_S:
555dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_40GBASE_KR4:
556aef74145SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4:
557aef74145SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_50GBASE_KR2:
558aef74145SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_100GBASE_KR4:
559aef74145SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4:
560aef74145SAnirudh Venkataramanan 			return ICE_MEDIA_BACKPLANE;
561aef74145SAnirudh Venkataramanan 		}
562aef74145SAnirudh Venkataramanan 	} else {
563aef74145SAnirudh Venkataramanan 		switch (hw_link_info->phy_type_high) {
5648ea1da59SPaul Greenwalt 		case ICE_PHY_TYPE_HIGH_100G_AUI2:
5658ea1da59SPaul Greenwalt 		case ICE_PHY_TYPE_HIGH_100G_CAUI2:
5668ea1da59SPaul Greenwalt 			if (ice_is_media_cage_present(pi))
5678ea1da59SPaul Greenwalt 				return ICE_MEDIA_DA;
5688ea1da59SPaul Greenwalt 			fallthrough;
569aef74145SAnirudh Venkataramanan 		case ICE_PHY_TYPE_HIGH_100GBASE_KR2_PAM4:
570dc49c772SAnirudh Venkataramanan 			return ICE_MEDIA_BACKPLANE;
571c1eb3b6bSDoug Dziggel 		case ICE_PHY_TYPE_HIGH_100G_CAUI2_AOC_ACC:
572c1eb3b6bSDoug Dziggel 		case ICE_PHY_TYPE_HIGH_100G_AUI2_AOC_ACC:
573c1eb3b6bSDoug Dziggel 			return ICE_MEDIA_FIBER;
574dc49c772SAnirudh Venkataramanan 		}
575dc49c772SAnirudh Venkataramanan 	}
576dc49c772SAnirudh Venkataramanan 	return ICE_MEDIA_UNKNOWN;
577dc49c772SAnirudh Venkataramanan }
578dc49c772SAnirudh Venkataramanan 
579dc49c772SAnirudh Venkataramanan /**
580dc49c772SAnirudh Venkataramanan  * ice_aq_get_link_info
581dc49c772SAnirudh Venkataramanan  * @pi: port information structure
582dc49c772SAnirudh Venkataramanan  * @ena_lse: enable/disable LinkStatusEvent reporting
583dc49c772SAnirudh Venkataramanan  * @link: pointer to link status structure - optional
584dc49c772SAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
585dc49c772SAnirudh Venkataramanan  *
586dc49c772SAnirudh Venkataramanan  * Get Link Status (0x607). Returns the link status of the adapter.
587dc49c772SAnirudh Venkataramanan  */
5885e24d598STony Nguyen int
ice_aq_get_link_info(struct ice_port_info * pi,bool ena_lse,struct ice_link_status * link,struct ice_sq_cd * cd)589dc49c772SAnirudh Venkataramanan ice_aq_get_link_info(struct ice_port_info *pi, bool ena_lse,
590dc49c772SAnirudh Venkataramanan 		     struct ice_link_status *link, struct ice_sq_cd *cd)
591dc49c772SAnirudh Venkataramanan {
592dc49c772SAnirudh Venkataramanan 	struct ice_aqc_get_link_status_data link_data = { 0 };
593dc49c772SAnirudh Venkataramanan 	struct ice_aqc_get_link_status *resp;
594dc67039bSJesse Brandeburg 	struct ice_link_status *li_old, *li;
595dc49c772SAnirudh Venkataramanan 	enum ice_media_type *hw_media_type;
596dc49c772SAnirudh Venkataramanan 	struct ice_fc_info *hw_fc_info;
597dc49c772SAnirudh Venkataramanan 	bool tx_pause, rx_pause;
598dc49c772SAnirudh Venkataramanan 	struct ice_aq_desc desc;
599dc67039bSJesse Brandeburg 	struct ice_hw *hw;
600dc49c772SAnirudh Venkataramanan 	u16 cmd_flags;
6015518ac2aSTony Nguyen 	int status;
602dc49c772SAnirudh Venkataramanan 
603dc49c772SAnirudh Venkataramanan 	if (!pi)
604d54699e2STony Nguyen 		return -EINVAL;
605dc67039bSJesse Brandeburg 	hw = pi->hw;
606dc67039bSJesse Brandeburg 	li_old = &pi->phy.link_info_old;
607dc49c772SAnirudh Venkataramanan 	hw_media_type = &pi->phy.media_type;
608dc67039bSJesse Brandeburg 	li = &pi->phy.link_info;
609dc49c772SAnirudh Venkataramanan 	hw_fc_info = &pi->fc;
610dc49c772SAnirudh Venkataramanan 
611dc49c772SAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_link_status);
612dc49c772SAnirudh Venkataramanan 	cmd_flags = (ena_lse) ? ICE_AQ_LSE_ENA : ICE_AQ_LSE_DIS;
613dc49c772SAnirudh Venkataramanan 	resp = &desc.params.get_link_status;
614dc49c772SAnirudh Venkataramanan 	resp->cmd_flags = cpu_to_le16(cmd_flags);
615dc49c772SAnirudh Venkataramanan 	resp->lport_num = pi->lport;
616dc49c772SAnirudh Venkataramanan 
617dc67039bSJesse Brandeburg 	status = ice_aq_send_cmd(hw, &desc, &link_data, sizeof(link_data), cd);
618dc49c772SAnirudh Venkataramanan 
619dc49c772SAnirudh Venkataramanan 	if (status)
620dc49c772SAnirudh Venkataramanan 		return status;
621dc49c772SAnirudh Venkataramanan 
622dc49c772SAnirudh Venkataramanan 	/* save off old link status information */
623dc67039bSJesse Brandeburg 	*li_old = *li;
624dc49c772SAnirudh Venkataramanan 
625dc49c772SAnirudh Venkataramanan 	/* update current link status information */
626dc67039bSJesse Brandeburg 	li->link_speed = le16_to_cpu(link_data.link_speed);
627dc67039bSJesse Brandeburg 	li->phy_type_low = le64_to_cpu(link_data.phy_type_low);
628dc67039bSJesse Brandeburg 	li->phy_type_high = le64_to_cpu(link_data.phy_type_high);
629dc49c772SAnirudh Venkataramanan 	*hw_media_type = ice_get_media_type(pi);
630dc67039bSJesse Brandeburg 	li->link_info = link_data.link_info;
631c77849f5SAnirudh Venkataramanan 	li->link_cfg_err = link_data.link_cfg_err;
632dc67039bSJesse Brandeburg 	li->an_info = link_data.an_info;
633dc67039bSJesse Brandeburg 	li->ext_info = link_data.ext_info;
634dc67039bSJesse Brandeburg 	li->max_frame_size = le16_to_cpu(link_data.max_frame_size);
635dc67039bSJesse Brandeburg 	li->fec_info = link_data.cfg & ICE_AQ_FEC_MASK;
636dc67039bSJesse Brandeburg 	li->topo_media_conflict = link_data.topo_media_conflict;
637dc67039bSJesse Brandeburg 	li->pacing = link_data.cfg & (ICE_AQ_CFG_PACING_M |
638dc67039bSJesse Brandeburg 				      ICE_AQ_CFG_PACING_TYPE_M);
639dc49c772SAnirudh Venkataramanan 
640dc49c772SAnirudh Venkataramanan 	/* update fc info */
641dc49c772SAnirudh Venkataramanan 	tx_pause = !!(link_data.an_info & ICE_AQ_LINK_PAUSE_TX);
642dc49c772SAnirudh Venkataramanan 	rx_pause = !!(link_data.an_info & ICE_AQ_LINK_PAUSE_RX);
643dc49c772SAnirudh Venkataramanan 	if (tx_pause && rx_pause)
644dc49c772SAnirudh Venkataramanan 		hw_fc_info->current_mode = ICE_FC_FULL;
645dc49c772SAnirudh Venkataramanan 	else if (tx_pause)
646dc49c772SAnirudh Venkataramanan 		hw_fc_info->current_mode = ICE_FC_TX_PAUSE;
647dc49c772SAnirudh Venkataramanan 	else if (rx_pause)
648dc49c772SAnirudh Venkataramanan 		hw_fc_info->current_mode = ICE_FC_RX_PAUSE;
649dc49c772SAnirudh Venkataramanan 	else
650dc49c772SAnirudh Venkataramanan 		hw_fc_info->current_mode = ICE_FC_NONE;
651dc49c772SAnirudh Venkataramanan 
652dc67039bSJesse Brandeburg 	li->lse_ena = !!(resp->cmd_flags & cpu_to_le16(ICE_AQ_LSE_IS_ENABLED));
653dc67039bSJesse Brandeburg 
65455df52a0SPaul Greenwalt 	ice_debug(hw, ICE_DBG_LINK, "get link info\n");
655dc67039bSJesse Brandeburg 	ice_debug(hw, ICE_DBG_LINK, "	link_speed = 0x%x\n", li->link_speed);
656dc67039bSJesse Brandeburg 	ice_debug(hw, ICE_DBG_LINK, "	phy_type_low = 0x%llx\n",
657dc67039bSJesse Brandeburg 		  (unsigned long long)li->phy_type_low);
658dc67039bSJesse Brandeburg 	ice_debug(hw, ICE_DBG_LINK, "	phy_type_high = 0x%llx\n",
659dc67039bSJesse Brandeburg 		  (unsigned long long)li->phy_type_high);
660dc67039bSJesse Brandeburg 	ice_debug(hw, ICE_DBG_LINK, "	media_type = 0x%x\n", *hw_media_type);
661dc67039bSJesse Brandeburg 	ice_debug(hw, ICE_DBG_LINK, "	link_info = 0x%x\n", li->link_info);
662c77849f5SAnirudh Venkataramanan 	ice_debug(hw, ICE_DBG_LINK, "	link_cfg_err = 0x%x\n", li->link_cfg_err);
663dc67039bSJesse Brandeburg 	ice_debug(hw, ICE_DBG_LINK, "	an_info = 0x%x\n", li->an_info);
664dc67039bSJesse Brandeburg 	ice_debug(hw, ICE_DBG_LINK, "	ext_info = 0x%x\n", li->ext_info);
66555df52a0SPaul Greenwalt 	ice_debug(hw, ICE_DBG_LINK, "	fec_info = 0x%x\n", li->fec_info);
666dc67039bSJesse Brandeburg 	ice_debug(hw, ICE_DBG_LINK, "	lse_ena = 0x%x\n", li->lse_ena);
66755df52a0SPaul Greenwalt 	ice_debug(hw, ICE_DBG_LINK, "	max_frame = 0x%x\n",
66855df52a0SPaul Greenwalt 		  li->max_frame_size);
669dc67039bSJesse Brandeburg 	ice_debug(hw, ICE_DBG_LINK, "	pacing = 0x%x\n", li->pacing);
670dc49c772SAnirudh Venkataramanan 
671dc49c772SAnirudh Venkataramanan 	/* save link status information */
672dc49c772SAnirudh Venkataramanan 	if (link)
673dc67039bSJesse Brandeburg 		*link = *li;
674dc49c772SAnirudh Venkataramanan 
675dc49c772SAnirudh Venkataramanan 	/* flag cleared so calling functions don't call AQ again */
676dc49c772SAnirudh Venkataramanan 	pi->phy.get_link_info = false;
677dc49c772SAnirudh Venkataramanan 
6781b5c19c7SBruce Allan 	return 0;
679dc49c772SAnirudh Venkataramanan }
680dc49c772SAnirudh Venkataramanan 
681dc49c772SAnirudh Venkataramanan /**
68242449105SAnirudh Venkataramanan  * ice_fill_tx_timer_and_fc_thresh
68342449105SAnirudh Venkataramanan  * @hw: pointer to the HW struct
68442449105SAnirudh Venkataramanan  * @cmd: pointer to MAC cfg structure
68542449105SAnirudh Venkataramanan  *
68642449105SAnirudh Venkataramanan  * Add Tx timer and FC refresh threshold info to Set MAC Config AQ command
68742449105SAnirudh Venkataramanan  * descriptor
68842449105SAnirudh Venkataramanan  */
68942449105SAnirudh Venkataramanan static void
ice_fill_tx_timer_and_fc_thresh(struct ice_hw * hw,struct ice_aqc_set_mac_cfg * cmd)69042449105SAnirudh Venkataramanan ice_fill_tx_timer_and_fc_thresh(struct ice_hw *hw,
69142449105SAnirudh Venkataramanan 				struct ice_aqc_set_mac_cfg *cmd)
69242449105SAnirudh Venkataramanan {
693*88f7ac6cSPaul Greenwalt 	u32 val, fc_thres_m;
69442449105SAnirudh Venkataramanan 
69542449105SAnirudh Venkataramanan 	/* We read back the transmit timer and FC threshold value of
69642449105SAnirudh Venkataramanan 	 * LFC. Thus, we will use index =
69742449105SAnirudh Venkataramanan 	 * PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_MAX_INDEX.
69842449105SAnirudh Venkataramanan 	 *
69942449105SAnirudh Venkataramanan 	 * Also, because we are operating on transmit timer and FC
70042449105SAnirudh Venkataramanan 	 * threshold of LFC, we don't turn on any bit in tx_tmr_priority
70142449105SAnirudh Venkataramanan 	 */
702*88f7ac6cSPaul Greenwalt #define E800_IDX_OF_LFC E800_PRTMAC_HSEC_CTL_TX_PS_QNT_MAX
703*88f7ac6cSPaul Greenwalt #define E800_REFRESH_TMR E800_PRTMAC_HSEC_CTL_TX_PS_RFSH_TMR
70442449105SAnirudh Venkataramanan 
705*88f7ac6cSPaul Greenwalt 	if (hw->mac_type == ICE_MAC_E830) {
70642449105SAnirudh Venkataramanan 		/* Retrieve the transmit timer */
707*88f7ac6cSPaul Greenwalt 		val = rd32(hw, E830_PRTMAC_CL01_PS_QNT);
708*88f7ac6cSPaul Greenwalt 		cmd->tx_tmr_value =
709*88f7ac6cSPaul Greenwalt 			le16_encode_bits(val, E830_PRTMAC_CL01_PS_QNT_CL0_M);
71042449105SAnirudh Venkataramanan 
711*88f7ac6cSPaul Greenwalt 		/* Retrieve the fc threshold */
712*88f7ac6cSPaul Greenwalt 		val = rd32(hw, E830_PRTMAC_CL01_QNT_THR);
713*88f7ac6cSPaul Greenwalt 		fc_thres_m = E830_PRTMAC_CL01_QNT_THR_CL0_M;
714*88f7ac6cSPaul Greenwalt 	} else {
715*88f7ac6cSPaul Greenwalt 		/* Retrieve the transmit timer */
716*88f7ac6cSPaul Greenwalt 		val = rd32(hw,
717*88f7ac6cSPaul Greenwalt 			   E800_PRTMAC_HSEC_CTL_TX_PS_QNT(E800_IDX_OF_LFC));
718*88f7ac6cSPaul Greenwalt 		cmd->tx_tmr_value =
719*88f7ac6cSPaul Greenwalt 			le16_encode_bits(val,
720*88f7ac6cSPaul Greenwalt 					 E800_PRTMAC_HSEC_CTL_TX_PS_QNT_M);
72142449105SAnirudh Venkataramanan 
722*88f7ac6cSPaul Greenwalt 		/* Retrieve the fc threshold */
723*88f7ac6cSPaul Greenwalt 		val = rd32(hw,
724*88f7ac6cSPaul Greenwalt 			   E800_REFRESH_TMR(E800_IDX_OF_LFC));
725*88f7ac6cSPaul Greenwalt 		fc_thres_m = E800_PRTMAC_HSEC_CTL_TX_PS_RFSH_TMR_M;
726*88f7ac6cSPaul Greenwalt 	}
727*88f7ac6cSPaul Greenwalt 	cmd->fc_refresh_threshold = le16_encode_bits(val, fc_thres_m);
72842449105SAnirudh Venkataramanan }
72942449105SAnirudh Venkataramanan 
73042449105SAnirudh Venkataramanan /**
73142449105SAnirudh Venkataramanan  * ice_aq_set_mac_cfg
73242449105SAnirudh Venkataramanan  * @hw: pointer to the HW struct
73342449105SAnirudh Venkataramanan  * @max_frame_size: Maximum Frame Size to be supported
73442449105SAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
73542449105SAnirudh Venkataramanan  *
73642449105SAnirudh Venkataramanan  * Set MAC configuration (0x0603)
73742449105SAnirudh Venkataramanan  */
7385e24d598STony Nguyen int
ice_aq_set_mac_cfg(struct ice_hw * hw,u16 max_frame_size,struct ice_sq_cd * cd)73942449105SAnirudh Venkataramanan ice_aq_set_mac_cfg(struct ice_hw *hw, u16 max_frame_size, struct ice_sq_cd *cd)
74042449105SAnirudh Venkataramanan {
74142449105SAnirudh Venkataramanan 	struct ice_aqc_set_mac_cfg *cmd;
74242449105SAnirudh Venkataramanan 	struct ice_aq_desc desc;
74342449105SAnirudh Venkataramanan 
74442449105SAnirudh Venkataramanan 	cmd = &desc.params.set_mac_cfg;
74542449105SAnirudh Venkataramanan 
74642449105SAnirudh Venkataramanan 	if (max_frame_size == 0)
747d54699e2STony Nguyen 		return -EINVAL;
74842449105SAnirudh Venkataramanan 
74942449105SAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_mac_cfg);
75042449105SAnirudh Venkataramanan 
75142449105SAnirudh Venkataramanan 	cmd->max_frame_size = cpu_to_le16(max_frame_size);
75242449105SAnirudh Venkataramanan 
75342449105SAnirudh Venkataramanan 	ice_fill_tx_timer_and_fc_thresh(hw, cmd);
75442449105SAnirudh Venkataramanan 
75542449105SAnirudh Venkataramanan 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
75642449105SAnirudh Venkataramanan }
75742449105SAnirudh Venkataramanan 
75842449105SAnirudh Venkataramanan /**
7599daf8208SAnirudh Venkataramanan  * ice_init_fltr_mgmt_struct - initializes filter management list and locks
760f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
7619daf8208SAnirudh Venkataramanan  */
ice_init_fltr_mgmt_struct(struct ice_hw * hw)7625e24d598STony Nguyen static int ice_init_fltr_mgmt_struct(struct ice_hw *hw)
7639daf8208SAnirudh Venkataramanan {
7649daf8208SAnirudh Venkataramanan 	struct ice_switch_info *sw;
7655e24d598STony Nguyen 	int status;
7669daf8208SAnirudh Venkataramanan 
7679daf8208SAnirudh Venkataramanan 	hw->switch_info = devm_kzalloc(ice_hw_to_dev(hw),
7689daf8208SAnirudh Venkataramanan 				       sizeof(*hw->switch_info), GFP_KERNEL);
7699daf8208SAnirudh Venkataramanan 	sw = hw->switch_info;
7709daf8208SAnirudh Venkataramanan 
7719daf8208SAnirudh Venkataramanan 	if (!sw)
772d54699e2STony Nguyen 		return -ENOMEM;
7739daf8208SAnirudh Venkataramanan 
7749daf8208SAnirudh Venkataramanan 	INIT_LIST_HEAD(&sw->vsi_list_map_head);
7750f94570dSGrishma Kotecha 	sw->prof_res_bm_init = 0;
7769daf8208SAnirudh Venkataramanan 
7771aaef2bcSSurabhi Boob 	status = ice_init_def_sw_recp(hw);
7781aaef2bcSSurabhi Boob 	if (status) {
7791aaef2bcSSurabhi Boob 		devm_kfree(ice_hw_to_dev(hw), hw->switch_info);
7801aaef2bcSSurabhi Boob 		return status;
7811aaef2bcSSurabhi Boob 	}
7821aaef2bcSSurabhi Boob 	return 0;
7839daf8208SAnirudh Venkataramanan }
7849daf8208SAnirudh Venkataramanan 
7859daf8208SAnirudh Venkataramanan /**
7869daf8208SAnirudh Venkataramanan  * ice_cleanup_fltr_mgmt_struct - cleanup filter management list and locks
787f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
7889daf8208SAnirudh Venkataramanan  */
ice_cleanup_fltr_mgmt_struct(struct ice_hw * hw)7899daf8208SAnirudh Venkataramanan static void ice_cleanup_fltr_mgmt_struct(struct ice_hw *hw)
7909daf8208SAnirudh Venkataramanan {
7919daf8208SAnirudh Venkataramanan 	struct ice_switch_info *sw = hw->switch_info;
7929daf8208SAnirudh Venkataramanan 	struct ice_vsi_list_map_info *v_pos_map;
7939daf8208SAnirudh Venkataramanan 	struct ice_vsi_list_map_info *v_tmp_map;
79480d144c9SAnirudh Venkataramanan 	struct ice_sw_recipe *recps;
79580d144c9SAnirudh Venkataramanan 	u8 i;
7969daf8208SAnirudh Venkataramanan 
7979daf8208SAnirudh Venkataramanan 	list_for_each_entry_safe(v_pos_map, v_tmp_map, &sw->vsi_list_map_head,
7989daf8208SAnirudh Venkataramanan 				 list_entry) {
7999daf8208SAnirudh Venkataramanan 		list_del(&v_pos_map->list_entry);
8009daf8208SAnirudh Venkataramanan 		devm_kfree(ice_hw_to_dev(hw), v_pos_map);
8019daf8208SAnirudh Venkataramanan 	}
8028b8ef05bSVictor Raj 	recps = sw->recp_list;
8038b8ef05bSVictor Raj 	for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
8048b8ef05bSVictor Raj 		struct ice_recp_grp_entry *rg_entry, *tmprg_entry;
8059daf8208SAnirudh Venkataramanan 
80680d144c9SAnirudh Venkataramanan 		recps[i].root_rid = i;
8078b8ef05bSVictor Raj 		list_for_each_entry_safe(rg_entry, tmprg_entry,
8088b8ef05bSVictor Raj 					 &recps[i].rg_list, l_entry) {
8098b8ef05bSVictor Raj 			list_del(&rg_entry->l_entry);
8108b8ef05bSVictor Raj 			devm_kfree(ice_hw_to_dev(hw), rg_entry);
8118b8ef05bSVictor Raj 		}
8128b8ef05bSVictor Raj 
8138b8ef05bSVictor Raj 		if (recps[i].adv_rule) {
8148b8ef05bSVictor Raj 			struct ice_adv_fltr_mgmt_list_entry *tmp_entry;
8158b8ef05bSVictor Raj 			struct ice_adv_fltr_mgmt_list_entry *lst_itr;
8168b8ef05bSVictor Raj 
81780d144c9SAnirudh Venkataramanan 			mutex_destroy(&recps[i].filt_rule_lock);
81880d144c9SAnirudh Venkataramanan 			list_for_each_entry_safe(lst_itr, tmp_entry,
8198b8ef05bSVictor Raj 						 &recps[i].filt_rules,
8208b8ef05bSVictor Raj 						 list_entry) {
8218b8ef05bSVictor Raj 				list_del(&lst_itr->list_entry);
8228b8ef05bSVictor Raj 				devm_kfree(ice_hw_to_dev(hw), lst_itr->lkups);
8238b8ef05bSVictor Raj 				devm_kfree(ice_hw_to_dev(hw), lst_itr);
8248b8ef05bSVictor Raj 			}
8258b8ef05bSVictor Raj 		} else {
8268b8ef05bSVictor Raj 			struct ice_fltr_mgmt_list_entry *lst_itr, *tmp_entry;
8278b8ef05bSVictor Raj 
8288b8ef05bSVictor Raj 			mutex_destroy(&recps[i].filt_rule_lock);
8298b8ef05bSVictor Raj 			list_for_each_entry_safe(lst_itr, tmp_entry,
8308b8ef05bSVictor Raj 						 &recps[i].filt_rules,
8318b8ef05bSVictor Raj 						 list_entry) {
83280d144c9SAnirudh Venkataramanan 				list_del(&lst_itr->list_entry);
83380d144c9SAnirudh Venkataramanan 				devm_kfree(ice_hw_to_dev(hw), lst_itr);
83480d144c9SAnirudh Venkataramanan 			}
83580d144c9SAnirudh Venkataramanan 		}
8368b8ef05bSVictor Raj 		devm_kfree(ice_hw_to_dev(hw), recps[i].root_buf);
8378b8ef05bSVictor Raj 	}
838334cb062SAnirudh Venkataramanan 	ice_rm_all_sw_replay_rule_info(hw);
83980d144c9SAnirudh Venkataramanan 	devm_kfree(ice_hw_to_dev(hw), sw->recp_list);
8409daf8208SAnirudh Venkataramanan 	devm_kfree(ice_hw_to_dev(hw), sw);
8419daf8208SAnirudh Venkataramanan }
8429daf8208SAnirudh Venkataramanan 
8438b97ceb1SHieu Tran /**
84411fe1b3aSDan Nowlin  * ice_get_fw_log_cfg - get FW logging configuration
84511fe1b3aSDan Nowlin  * @hw: pointer to the HW struct
84611fe1b3aSDan Nowlin  */
ice_get_fw_log_cfg(struct ice_hw * hw)8475e24d598STony Nguyen static int ice_get_fw_log_cfg(struct ice_hw *hw)
84811fe1b3aSDan Nowlin {
84911fe1b3aSDan Nowlin 	struct ice_aq_desc desc;
850b3c38904SBruce Allan 	__le16 *config;
8515518ac2aSTony Nguyen 	int status;
85211fe1b3aSDan Nowlin 	u16 size;
85311fe1b3aSDan Nowlin 
854b3c38904SBruce Allan 	size = sizeof(*config) * ICE_AQC_FW_LOG_ID_MAX;
8551dacc497SChristophe JAILLET 	config = kzalloc(size, GFP_KERNEL);
85611fe1b3aSDan Nowlin 	if (!config)
857d54699e2STony Nguyen 		return -ENOMEM;
85811fe1b3aSDan Nowlin 
85911fe1b3aSDan Nowlin 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_fw_logging_info);
86011fe1b3aSDan Nowlin 
86111fe1b3aSDan Nowlin 	status = ice_aq_send_cmd(hw, &desc, config, size, NULL);
86211fe1b3aSDan Nowlin 	if (!status) {
86311fe1b3aSDan Nowlin 		u16 i;
86411fe1b3aSDan Nowlin 
8652f2da36eSAnirudh Venkataramanan 		/* Save FW logging information into the HW structure */
86611fe1b3aSDan Nowlin 		for (i = 0; i < ICE_AQC_FW_LOG_ID_MAX; i++) {
86711fe1b3aSDan Nowlin 			u16 v, m, flgs;
86811fe1b3aSDan Nowlin 
869b3c38904SBruce Allan 			v = le16_to_cpu(config[i]);
87011fe1b3aSDan Nowlin 			m = (v & ICE_AQC_FW_LOG_ID_M) >> ICE_AQC_FW_LOG_ID_S;
87111fe1b3aSDan Nowlin 			flgs = (v & ICE_AQC_FW_LOG_EN_M) >> ICE_AQC_FW_LOG_EN_S;
87211fe1b3aSDan Nowlin 
87311fe1b3aSDan Nowlin 			if (m < ICE_AQC_FW_LOG_ID_MAX)
87411fe1b3aSDan Nowlin 				hw->fw_log.evnts[m].cur = flgs;
87511fe1b3aSDan Nowlin 		}
87611fe1b3aSDan Nowlin 	}
87711fe1b3aSDan Nowlin 
8781dacc497SChristophe JAILLET 	kfree(config);
87911fe1b3aSDan Nowlin 
88011fe1b3aSDan Nowlin 	return status;
88111fe1b3aSDan Nowlin }
88211fe1b3aSDan Nowlin 
88311fe1b3aSDan Nowlin /**
8848b97ceb1SHieu Tran  * ice_cfg_fw_log - configure FW logging
885f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
8868b97ceb1SHieu Tran  * @enable: enable certain FW logging events if true, disable all if false
8878b97ceb1SHieu Tran  *
8888b97ceb1SHieu Tran  * This function enables/disables the FW logging via Rx CQ events and a UART
8898b97ceb1SHieu Tran  * port based on predetermined configurations. FW logging via the Rx CQ can be
8908b97ceb1SHieu Tran  * enabled/disabled for individual PF's. However, FW logging via the UART can
8918b97ceb1SHieu Tran  * only be enabled/disabled for all PFs on the same device.
8928b97ceb1SHieu Tran  *
8938b97ceb1SHieu Tran  * To enable overall FW logging, the "cq_en" and "uart_en" enable bits in
8948b97ceb1SHieu Tran  * hw->fw_log need to be set accordingly, e.g. based on user-provided input,
8958b97ceb1SHieu Tran  * before initializing the device.
8968b97ceb1SHieu Tran  *
8978b97ceb1SHieu Tran  * When re/configuring FW logging, callers need to update the "cfg" elements of
8988b97ceb1SHieu Tran  * the hw->fw_log.evnts array with the desired logging event configurations for
8998b97ceb1SHieu Tran  * modules of interest. When disabling FW logging completely, the callers can
9008b97ceb1SHieu Tran  * just pass false in the "enable" parameter. On completion, the function will
9018b97ceb1SHieu Tran  * update the "cur" element of the hw->fw_log.evnts array with the resulting
9028b97ceb1SHieu Tran  * logging event configurations of the modules that are being re/configured. FW
9038b97ceb1SHieu Tran  * logging modules that are not part of a reconfiguration operation retain their
9048b97ceb1SHieu Tran  * previous states.
9058b97ceb1SHieu Tran  *
9068b97ceb1SHieu Tran  * Before resetting the device, it is recommended that the driver disables FW
9078b97ceb1SHieu Tran  * logging before shutting down the control queue. When disabling FW logging
9088b97ceb1SHieu Tran  * ("enable" = false), the latest configurations of FW logging events stored in
9098b97ceb1SHieu Tran  * hw->fw_log.evnts[] are not overridden to allow them to be reconfigured after
9108b97ceb1SHieu Tran  * a device reset.
9118b97ceb1SHieu Tran  *
9128b97ceb1SHieu Tran  * When enabling FW logging to emit log messages via the Rx CQ during the
9138b97ceb1SHieu Tran  * device's initialization phase, a mechanism alternative to interrupt handlers
9148b97ceb1SHieu Tran  * needs to be used to extract FW log messages from the Rx CQ periodically and
9158b97ceb1SHieu Tran  * to prevent the Rx CQ from being full and stalling other types of control
9168b97ceb1SHieu Tran  * messages from FW to SW. Interrupts are typically disabled during the device's
9178b97ceb1SHieu Tran  * initialization phase.
9188b97ceb1SHieu Tran  */
ice_cfg_fw_log(struct ice_hw * hw,bool enable)9195e24d598STony Nguyen static int ice_cfg_fw_log(struct ice_hw *hw, bool enable)
9208b97ceb1SHieu Tran {
9218b97ceb1SHieu Tran 	struct ice_aqc_fw_logging *cmd;
9228b97ceb1SHieu Tran 	u16 i, chgs = 0, len = 0;
9238b97ceb1SHieu Tran 	struct ice_aq_desc desc;
924b3c38904SBruce Allan 	__le16 *data = NULL;
9258b97ceb1SHieu Tran 	u8 actv_evnts = 0;
9268b97ceb1SHieu Tran 	void *buf = NULL;
9275518ac2aSTony Nguyen 	int status = 0;
9288b97ceb1SHieu Tran 
9298b97ceb1SHieu Tran 	if (!hw->fw_log.cq_en && !hw->fw_log.uart_en)
9308b97ceb1SHieu Tran 		return 0;
9318b97ceb1SHieu Tran 
9328b97ceb1SHieu Tran 	/* Disable FW logging only when the control queue is still responsive */
9338b97ceb1SHieu Tran 	if (!enable &&
9348b97ceb1SHieu Tran 	    (!hw->fw_log.actv_evnts || !ice_check_sq_alive(hw, &hw->adminq)))
9358b97ceb1SHieu Tran 		return 0;
9368b97ceb1SHieu Tran 
93711fe1b3aSDan Nowlin 	/* Get current FW log settings */
93811fe1b3aSDan Nowlin 	status = ice_get_fw_log_cfg(hw);
93911fe1b3aSDan Nowlin 	if (status)
94011fe1b3aSDan Nowlin 		return status;
94111fe1b3aSDan Nowlin 
9428b97ceb1SHieu Tran 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_fw_logging);
9438b97ceb1SHieu Tran 	cmd = &desc.params.fw_logging;
9448b97ceb1SHieu Tran 
9458b97ceb1SHieu Tran 	/* Indicate which controls are valid */
9468b97ceb1SHieu Tran 	if (hw->fw_log.cq_en)
9478b97ceb1SHieu Tran 		cmd->log_ctrl_valid |= ICE_AQC_FW_LOG_AQ_VALID;
9488b97ceb1SHieu Tran 
9498b97ceb1SHieu Tran 	if (hw->fw_log.uart_en)
9508b97ceb1SHieu Tran 		cmd->log_ctrl_valid |= ICE_AQC_FW_LOG_UART_VALID;
9518b97ceb1SHieu Tran 
9528b97ceb1SHieu Tran 	if (enable) {
9538b97ceb1SHieu Tran 		/* Fill in an array of entries with FW logging modules and
9548b97ceb1SHieu Tran 		 * logging events being reconfigured.
9558b97ceb1SHieu Tran 		 */
9568b97ceb1SHieu Tran 		for (i = 0; i < ICE_AQC_FW_LOG_ID_MAX; i++) {
9578b97ceb1SHieu Tran 			u16 val;
9588b97ceb1SHieu Tran 
9598b97ceb1SHieu Tran 			/* Keep track of enabled event types */
9608b97ceb1SHieu Tran 			actv_evnts |= hw->fw_log.evnts[i].cfg;
9618b97ceb1SHieu Tran 
9628b97ceb1SHieu Tran 			if (hw->fw_log.evnts[i].cfg == hw->fw_log.evnts[i].cur)
9638b97ceb1SHieu Tran 				continue;
9648b97ceb1SHieu Tran 
9658b97ceb1SHieu Tran 			if (!data) {
966b3c38904SBruce Allan 				data = devm_kcalloc(ice_hw_to_dev(hw),
967b3c38904SBruce Allan 						    ICE_AQC_FW_LOG_ID_MAX,
96859df14f9SBruce Allan 						    sizeof(*data),
9698b97ceb1SHieu Tran 						    GFP_KERNEL);
9708b97ceb1SHieu Tran 				if (!data)
971d54699e2STony Nguyen 					return -ENOMEM;
9728b97ceb1SHieu Tran 			}
9738b97ceb1SHieu Tran 
9748b97ceb1SHieu Tran 			val = i << ICE_AQC_FW_LOG_ID_S;
9758b97ceb1SHieu Tran 			val |= hw->fw_log.evnts[i].cfg << ICE_AQC_FW_LOG_EN_S;
976b3c38904SBruce Allan 			data[chgs++] = cpu_to_le16(val);
9778b97ceb1SHieu Tran 		}
9788b97ceb1SHieu Tran 
9798b97ceb1SHieu Tran 		/* Only enable FW logging if at least one module is specified.
9808b97ceb1SHieu Tran 		 * If FW logging is currently enabled but all modules are not
9818b97ceb1SHieu Tran 		 * enabled to emit log messages, disable FW logging altogether.
9828b97ceb1SHieu Tran 		 */
9838b97ceb1SHieu Tran 		if (actv_evnts) {
9848b97ceb1SHieu Tran 			/* Leave if there is effectively no change */
9858b97ceb1SHieu Tran 			if (!chgs)
9868b97ceb1SHieu Tran 				goto out;
9878b97ceb1SHieu Tran 
9888b97ceb1SHieu Tran 			if (hw->fw_log.cq_en)
9898b97ceb1SHieu Tran 				cmd->log_ctrl |= ICE_AQC_FW_LOG_AQ_EN;
9908b97ceb1SHieu Tran 
9918b97ceb1SHieu Tran 			if (hw->fw_log.uart_en)
9928b97ceb1SHieu Tran 				cmd->log_ctrl |= ICE_AQC_FW_LOG_UART_EN;
9938b97ceb1SHieu Tran 
9948b97ceb1SHieu Tran 			buf = data;
995b3c38904SBruce Allan 			len = sizeof(*data) * chgs;
9968b97ceb1SHieu Tran 			desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
9978b97ceb1SHieu Tran 		}
9988b97ceb1SHieu Tran 	}
9998b97ceb1SHieu Tran 
10008b97ceb1SHieu Tran 	status = ice_aq_send_cmd(hw, &desc, buf, len, NULL);
10018b97ceb1SHieu Tran 	if (!status) {
10028b97ceb1SHieu Tran 		/* Update the current configuration to reflect events enabled.
10038b97ceb1SHieu Tran 		 * hw->fw_log.cq_en and hw->fw_log.uart_en indicate if the FW
10048b97ceb1SHieu Tran 		 * logging mode is enabled for the device. They do not reflect
10058b97ceb1SHieu Tran 		 * actual modules being enabled to emit log messages. So, their
10068b97ceb1SHieu Tran 		 * values remain unchanged even when all modules are disabled.
10078b97ceb1SHieu Tran 		 */
10088b97ceb1SHieu Tran 		u16 cnt = enable ? chgs : (u16)ICE_AQC_FW_LOG_ID_MAX;
10098b97ceb1SHieu Tran 
10108b97ceb1SHieu Tran 		hw->fw_log.actv_evnts = actv_evnts;
10118b97ceb1SHieu Tran 		for (i = 0; i < cnt; i++) {
10128b97ceb1SHieu Tran 			u16 v, m;
10138b97ceb1SHieu Tran 
10148b97ceb1SHieu Tran 			if (!enable) {
10158b97ceb1SHieu Tran 				/* When disabling all FW logging events as part
10168b97ceb1SHieu Tran 				 * of device's de-initialization, the original
10178b97ceb1SHieu Tran 				 * configurations are retained, and can be used
10188b97ceb1SHieu Tran 				 * to reconfigure FW logging later if the device
10198b97ceb1SHieu Tran 				 * is re-initialized.
10208b97ceb1SHieu Tran 				 */
10218b97ceb1SHieu Tran 				hw->fw_log.evnts[i].cur = 0;
10228b97ceb1SHieu Tran 				continue;
10238b97ceb1SHieu Tran 			}
10248b97ceb1SHieu Tran 
1025b3c38904SBruce Allan 			v = le16_to_cpu(data[i]);
10268b97ceb1SHieu Tran 			m = (v & ICE_AQC_FW_LOG_ID_M) >> ICE_AQC_FW_LOG_ID_S;
10278b97ceb1SHieu Tran 			hw->fw_log.evnts[m].cur = hw->fw_log.evnts[m].cfg;
10288b97ceb1SHieu Tran 		}
10298b97ceb1SHieu Tran 	}
10308b97ceb1SHieu Tran 
10318b97ceb1SHieu Tran out:
10328b97ceb1SHieu Tran 	devm_kfree(ice_hw_to_dev(hw), data);
10338b97ceb1SHieu Tran 
10348b97ceb1SHieu Tran 	return status;
10358b97ceb1SHieu Tran }
10368b97ceb1SHieu Tran 
10378b97ceb1SHieu Tran /**
10388b97ceb1SHieu Tran  * ice_output_fw_log
1039f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
10408b97ceb1SHieu Tran  * @desc: pointer to the AQ message descriptor
10418b97ceb1SHieu Tran  * @buf: pointer to the buffer accompanying the AQ message
10428b97ceb1SHieu Tran  *
10438b97ceb1SHieu Tran  * Formats a FW Log message and outputs it via the standard driver logs.
10448b97ceb1SHieu Tran  */
ice_output_fw_log(struct ice_hw * hw,struct ice_aq_desc * desc,void * buf)10458b97ceb1SHieu Tran void ice_output_fw_log(struct ice_hw *hw, struct ice_aq_desc *desc, void *buf)
10468b97ceb1SHieu Tran {
10474f70daa0SJacob Keller 	ice_debug(hw, ICE_DBG_FW_LOG, "[ FW Log Msg Start ]\n");
10484f70daa0SJacob Keller 	ice_debug_array(hw, ICE_DBG_FW_LOG, 16, 1, (u8 *)buf,
10498b97ceb1SHieu Tran 			le16_to_cpu(desc->datalen));
10504f70daa0SJacob Keller 	ice_debug(hw, ICE_DBG_FW_LOG, "[ FW Log Msg End ]\n");
10518b97ceb1SHieu Tran }
10528b97ceb1SHieu Tran 
10539daf8208SAnirudh Venkataramanan /**
10544ee656bbSTony Nguyen  * ice_get_itr_intrl_gran
1055f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
10569e4ab4c2SBrett Creeley  *
10574ee656bbSTony Nguyen  * Determines the ITR/INTRL granularities based on the maximum aggregate
10589e4ab4c2SBrett Creeley  * bandwidth according to the device's configuration during power-on.
10599e4ab4c2SBrett Creeley  */
ice_get_itr_intrl_gran(struct ice_hw * hw)1060fe7219faSBruce Allan static void ice_get_itr_intrl_gran(struct ice_hw *hw)
10619e4ab4c2SBrett Creeley {
10629e4ab4c2SBrett Creeley 	u8 max_agg_bw = (rd32(hw, GL_PWR_MODE_CTL) &
10639e4ab4c2SBrett Creeley 			 GL_PWR_MODE_CTL_CAR_MAX_BW_M) >>
10649e4ab4c2SBrett Creeley 			GL_PWR_MODE_CTL_CAR_MAX_BW_S;
10659e4ab4c2SBrett Creeley 
10669e4ab4c2SBrett Creeley 	switch (max_agg_bw) {
10679e4ab4c2SBrett Creeley 	case ICE_MAX_AGG_BW_200G:
10689e4ab4c2SBrett Creeley 	case ICE_MAX_AGG_BW_100G:
10699e4ab4c2SBrett Creeley 	case ICE_MAX_AGG_BW_50G:
10709e4ab4c2SBrett Creeley 		hw->itr_gran = ICE_ITR_GRAN_ABOVE_25;
10719e4ab4c2SBrett Creeley 		hw->intrl_gran = ICE_INTRL_GRAN_ABOVE_25;
10729e4ab4c2SBrett Creeley 		break;
10739e4ab4c2SBrett Creeley 	case ICE_MAX_AGG_BW_25G:
10749e4ab4c2SBrett Creeley 		hw->itr_gran = ICE_ITR_GRAN_MAX_25;
10759e4ab4c2SBrett Creeley 		hw->intrl_gran = ICE_INTRL_GRAN_MAX_25;
10769e4ab4c2SBrett Creeley 		break;
10779e4ab4c2SBrett Creeley 	}
10789e4ab4c2SBrett Creeley }
10799e4ab4c2SBrett Creeley 
10809e4ab4c2SBrett Creeley /**
1081f31e4b6fSAnirudh Venkataramanan  * ice_init_hw - main hardware initialization routine
1082f31e4b6fSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
1083f31e4b6fSAnirudh Venkataramanan  */
ice_init_hw(struct ice_hw * hw)10845e24d598STony Nguyen int ice_init_hw(struct ice_hw *hw)
1085f31e4b6fSAnirudh Venkataramanan {
1086dc49c772SAnirudh Venkataramanan 	struct ice_aqc_get_phy_caps_data *pcaps;
1087dc49c772SAnirudh Venkataramanan 	u16 mac_buf_len;
1088dc49c772SAnirudh Venkataramanan 	void *mac_buf;
10895518ac2aSTony Nguyen 	int status;
1090f31e4b6fSAnirudh Venkataramanan 
1091f31e4b6fSAnirudh Venkataramanan 	/* Set MAC type based on DeviceID */
1092f31e4b6fSAnirudh Venkataramanan 	status = ice_set_mac_type(hw);
1093f31e4b6fSAnirudh Venkataramanan 	if (status)
1094f31e4b6fSAnirudh Venkataramanan 		return status;
1095f31e4b6fSAnirudh Venkataramanan 
1096f31e4b6fSAnirudh Venkataramanan 	hw->pf_id = (u8)(rd32(hw, PF_FUNC_RID) &
1097f31e4b6fSAnirudh Venkataramanan 			 PF_FUNC_RID_FUNC_NUM_M) >>
1098f31e4b6fSAnirudh Venkataramanan 		PF_FUNC_RID_FUNC_NUM_S;
1099f31e4b6fSAnirudh Venkataramanan 
1100f31e4b6fSAnirudh Venkataramanan 	status = ice_reset(hw, ICE_RESET_PFR);
1101f31e4b6fSAnirudh Venkataramanan 	if (status)
1102f31e4b6fSAnirudh Venkataramanan 		return status;
1103f31e4b6fSAnirudh Venkataramanan 
1104fe7219faSBruce Allan 	ice_get_itr_intrl_gran(hw);
1105940b61afSAnirudh Venkataramanan 
11065c91ecfdSJacob Keller 	status = ice_create_all_ctrlq(hw);
1107f31e4b6fSAnirudh Venkataramanan 	if (status)
1108f31e4b6fSAnirudh Venkataramanan 		goto err_unroll_cqinit;
1109f31e4b6fSAnirudh Venkataramanan 
11108b97ceb1SHieu Tran 	/* Enable FW logging. Not fatal if this fails. */
11118b97ceb1SHieu Tran 	status = ice_cfg_fw_log(hw, true);
11128b97ceb1SHieu Tran 	if (status)
11138b97ceb1SHieu Tran 		ice_debug(hw, ICE_DBG_INIT, "Failed to enable FW logging.\n");
11148b97ceb1SHieu Tran 
1115f31e4b6fSAnirudh Venkataramanan 	status = ice_clear_pf_cfg(hw);
1116f31e4b6fSAnirudh Venkataramanan 	if (status)
1117f31e4b6fSAnirudh Venkataramanan 		goto err_unroll_cqinit;
1118f31e4b6fSAnirudh Venkataramanan 
1119148beb61SHenry Tieman 	/* Set bit to enable Flow Director filters */
1120148beb61SHenry Tieman 	wr32(hw, PFQF_FD_ENA, PFQF_FD_ENA_FD_ENA_M);
1121148beb61SHenry Tieman 	INIT_LIST_HEAD(&hw->fdir_list_head);
1122148beb61SHenry Tieman 
1123f31e4b6fSAnirudh Venkataramanan 	ice_clear_pxe_mode(hw);
1124f31e4b6fSAnirudh Venkataramanan 
1125f31e4b6fSAnirudh Venkataramanan 	status = ice_init_nvm(hw);
1126f31e4b6fSAnirudh Venkataramanan 	if (status)
1127f31e4b6fSAnirudh Venkataramanan 		goto err_unroll_cqinit;
1128f31e4b6fSAnirudh Venkataramanan 
11299c20346bSAnirudh Venkataramanan 	status = ice_get_caps(hw);
11309c20346bSAnirudh Venkataramanan 	if (status)
11319c20346bSAnirudh Venkataramanan 		goto err_unroll_cqinit;
11329c20346bSAnirudh Venkataramanan 
11335b246e53SMichal Swiatkowski 	if (!hw->port_info)
11349c20346bSAnirudh Venkataramanan 		hw->port_info = devm_kzalloc(ice_hw_to_dev(hw),
11355b246e53SMichal Swiatkowski 					     sizeof(*hw->port_info),
11365b246e53SMichal Swiatkowski 					     GFP_KERNEL);
11379c20346bSAnirudh Venkataramanan 	if (!hw->port_info) {
1138d54699e2STony Nguyen 		status = -ENOMEM;
11399c20346bSAnirudh Venkataramanan 		goto err_unroll_cqinit;
11409c20346bSAnirudh Venkataramanan 	}
11419c20346bSAnirudh Venkataramanan 
1142f9867df6SAnirudh Venkataramanan 	/* set the back pointer to HW */
11439c20346bSAnirudh Venkataramanan 	hw->port_info->hw = hw;
11449c20346bSAnirudh Venkataramanan 
11459c20346bSAnirudh Venkataramanan 	/* Initialize port_info struct with switch configuration data */
11469c20346bSAnirudh Venkataramanan 	status = ice_get_initial_sw_cfg(hw);
11479c20346bSAnirudh Venkataramanan 	if (status)
11489c20346bSAnirudh Venkataramanan 		goto err_unroll_alloc;
11499c20346bSAnirudh Venkataramanan 
11509daf8208SAnirudh Venkataramanan 	hw->evb_veb = true;
11519daf8208SAnirudh Venkataramanan 
115216dfa494SMichal Wilczynski 	/* init xarray for identifying scheduling nodes uniquely */
115316dfa494SMichal Wilczynski 	xa_init_flags(&hw->port_info->sched_node_ids, XA_FLAGS_ALLOC);
115416dfa494SMichal Wilczynski 
1155d337f2afSAnirudh Venkataramanan 	/* Query the allocated resources for Tx scheduler */
11569c20346bSAnirudh Venkataramanan 	status = ice_sched_query_res_alloc(hw);
11579c20346bSAnirudh Venkataramanan 	if (status) {
11589228d8b2SJacob Keller 		ice_debug(hw, ICE_DBG_SCHED, "Failed to get scheduler allocated resources\n");
11599c20346bSAnirudh Venkataramanan 		goto err_unroll_alloc;
11609c20346bSAnirudh Venkataramanan 	}
11614f8a1497SBen Shelton 	ice_sched_get_psm_clk_freq(hw);
11629c20346bSAnirudh Venkataramanan 
1163dc49c772SAnirudh Venkataramanan 	/* Initialize port_info struct with scheduler data */
1164dc49c772SAnirudh Venkataramanan 	status = ice_sched_init_port(hw->port_info);
1165dc49c772SAnirudh Venkataramanan 	if (status)
1166dc49c772SAnirudh Venkataramanan 		goto err_unroll_sched;
1167dc49c772SAnirudh Venkataramanan 
1168dc49c772SAnirudh Venkataramanan 	pcaps = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*pcaps), GFP_KERNEL);
1169dc49c772SAnirudh Venkataramanan 	if (!pcaps) {
1170d54699e2STony Nguyen 		status = -ENOMEM;
1171dc49c772SAnirudh Venkataramanan 		goto err_unroll_sched;
1172dc49c772SAnirudh Venkataramanan 	}
1173dc49c772SAnirudh Venkataramanan 
1174dc49c772SAnirudh Venkataramanan 	/* Initialize port_info struct with PHY capabilities */
1175dc49c772SAnirudh Venkataramanan 	status = ice_aq_get_phy_caps(hw->port_info, false,
1176d6730a87SAnirudh Venkataramanan 				     ICE_AQC_REPORT_TOPO_CAP_MEDIA, pcaps,
1177d6730a87SAnirudh Venkataramanan 				     NULL);
1178dc49c772SAnirudh Venkataramanan 	devm_kfree(ice_hw_to_dev(hw), pcaps);
1179dc49c772SAnirudh Venkataramanan 	if (status)
1180f2651a91SPaul M Stillwell Jr 		dev_warn(ice_hw_to_dev(hw), "Get PHY capabilities failed status = %d, continuing anyway\n",
1181f2651a91SPaul M Stillwell Jr 			 status);
1182dc49c772SAnirudh Venkataramanan 
1183dc49c772SAnirudh Venkataramanan 	/* Initialize port_info struct with link information */
1184dc49c772SAnirudh Venkataramanan 	status = ice_aq_get_link_info(hw->port_info, false, NULL, NULL);
1185dc49c772SAnirudh Venkataramanan 	if (status)
1186dc49c772SAnirudh Venkataramanan 		goto err_unroll_sched;
1187dc49c772SAnirudh Venkataramanan 
1188b36c598cSAnirudh Venkataramanan 	/* need a valid SW entry point to build a Tx tree */
1189b36c598cSAnirudh Venkataramanan 	if (!hw->sw_entry_point_layer) {
1190b36c598cSAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_SCHED, "invalid sw entry point\n");
1191d54699e2STony Nguyen 		status = -EIO;
1192b36c598cSAnirudh Venkataramanan 		goto err_unroll_sched;
1193b36c598cSAnirudh Venkataramanan 	}
11949be1d6f8SAnirudh Venkataramanan 	INIT_LIST_HEAD(&hw->agg_list);
11951ddef455SUsha Ketineni 	/* Initialize max burst size */
11961ddef455SUsha Ketineni 	if (!hw->max_burst_size)
11971ddef455SUsha Ketineni 		ice_cfg_rl_burst_size(hw, ICE_SCHED_DFLT_BURST_SIZE);
1198b36c598cSAnirudh Venkataramanan 
11999daf8208SAnirudh Venkataramanan 	status = ice_init_fltr_mgmt_struct(hw);
12009daf8208SAnirudh Venkataramanan 	if (status)
12019daf8208SAnirudh Venkataramanan 		goto err_unroll_sched;
12029daf8208SAnirudh Venkataramanan 
1203d6fef10cSMd Fahad Iqbal Polash 	/* Get MAC information */
1204d6fef10cSMd Fahad Iqbal Polash 	/* A single port can report up to two (LAN and WoL) addresses */
1205d6fef10cSMd Fahad Iqbal Polash 	mac_buf = devm_kcalloc(ice_hw_to_dev(hw), 2,
1206d6fef10cSMd Fahad Iqbal Polash 			       sizeof(struct ice_aqc_manage_mac_read_resp),
1207d6fef10cSMd Fahad Iqbal Polash 			       GFP_KERNEL);
1208d6fef10cSMd Fahad Iqbal Polash 	mac_buf_len = 2 * sizeof(struct ice_aqc_manage_mac_read_resp);
1209dc49c772SAnirudh Venkataramanan 
121063bb4e1eSWei Yongjun 	if (!mac_buf) {
1211d54699e2STony Nguyen 		status = -ENOMEM;
12129daf8208SAnirudh Venkataramanan 		goto err_unroll_fltr_mgmt_struct;
121363bb4e1eSWei Yongjun 	}
1214dc49c772SAnirudh Venkataramanan 
1215dc49c772SAnirudh Venkataramanan 	status = ice_aq_manage_mac_read(hw, mac_buf, mac_buf_len, NULL);
1216dc49c772SAnirudh Venkataramanan 	devm_kfree(ice_hw_to_dev(hw), mac_buf);
1217dc49c772SAnirudh Venkataramanan 
1218dc49c772SAnirudh Venkataramanan 	if (status)
12199daf8208SAnirudh Venkataramanan 		goto err_unroll_fltr_mgmt_struct;
122042449105SAnirudh Venkataramanan 	/* enable jumbo frame support at MAC level */
122142449105SAnirudh Venkataramanan 	status = ice_aq_set_mac_cfg(hw, ICE_AQ_SET_MAC_FRAME_SIZE_MAX, NULL);
122242449105SAnirudh Venkataramanan 	if (status)
122342449105SAnirudh Venkataramanan 		goto err_unroll_fltr_mgmt_struct;
1224148beb61SHenry Tieman 	/* Obtain counter base index which would be used by flow director */
1225148beb61SHenry Tieman 	status = ice_alloc_fd_res_cntr(hw, &hw->fd_ctr_base);
1226148beb61SHenry Tieman 	if (status)
1227148beb61SHenry Tieman 		goto err_unroll_fltr_mgmt_struct;
122832d63fa1STony Nguyen 	status = ice_init_hw_tbls(hw);
122932d63fa1STony Nguyen 	if (status)
123032d63fa1STony Nguyen 		goto err_unroll_fltr_mgmt_struct;
1231a4e82a81STony Nguyen 	mutex_init(&hw->tnl_lock);
1232f31e4b6fSAnirudh Venkataramanan 	return 0;
1233f31e4b6fSAnirudh Venkataramanan 
12349daf8208SAnirudh Venkataramanan err_unroll_fltr_mgmt_struct:
12359daf8208SAnirudh Venkataramanan 	ice_cleanup_fltr_mgmt_struct(hw);
1236dc49c772SAnirudh Venkataramanan err_unroll_sched:
1237dc49c772SAnirudh Venkataramanan 	ice_sched_cleanup_all(hw);
12389c20346bSAnirudh Venkataramanan err_unroll_alloc:
12399c20346bSAnirudh Venkataramanan 	devm_kfree(ice_hw_to_dev(hw), hw->port_info);
1240f31e4b6fSAnirudh Venkataramanan err_unroll_cqinit:
12415c91ecfdSJacob Keller 	ice_destroy_all_ctrlq(hw);
1242f31e4b6fSAnirudh Venkataramanan 	return status;
1243f31e4b6fSAnirudh Venkataramanan }
1244f31e4b6fSAnirudh Venkataramanan 
1245f31e4b6fSAnirudh Venkataramanan /**
1246f31e4b6fSAnirudh Venkataramanan  * ice_deinit_hw - unroll initialization operations done by ice_init_hw
1247f31e4b6fSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
1248ed14245aSAnirudh Venkataramanan  *
1249ed14245aSAnirudh Venkataramanan  * This should be called only during nominal operation, not as a result of
1250ed14245aSAnirudh Venkataramanan  * ice_init_hw() failing since ice_init_hw() will take care of unrolling
1251ed14245aSAnirudh Venkataramanan  * applicable initializations if it fails for any reason.
1252f31e4b6fSAnirudh Venkataramanan  */
ice_deinit_hw(struct ice_hw * hw)1253f31e4b6fSAnirudh Venkataramanan void ice_deinit_hw(struct ice_hw *hw)
1254f31e4b6fSAnirudh Venkataramanan {
1255148beb61SHenry Tieman 	ice_free_fd_res_cntr(hw, hw->fd_ctr_base);
12568b97ceb1SHieu Tran 	ice_cleanup_fltr_mgmt_struct(hw);
12578b97ceb1SHieu Tran 
12589c20346bSAnirudh Venkataramanan 	ice_sched_cleanup_all(hw);
12599be1d6f8SAnirudh Venkataramanan 	ice_sched_clear_agg(hw);
1260c7648810STony Nguyen 	ice_free_seg(hw);
126132d63fa1STony Nguyen 	ice_free_hw_tbls(hw);
1262a4e82a81STony Nguyen 	mutex_destroy(&hw->tnl_lock);
1263dc49c772SAnirudh Venkataramanan 
12648b97ceb1SHieu Tran 	/* Attempt to disable FW logging before shutting down control queues */
12658b97ceb1SHieu Tran 	ice_cfg_fw_log(hw, false);
12665c91ecfdSJacob Keller 	ice_destroy_all_ctrlq(hw);
126733e055fcSVictor Raj 
126833e055fcSVictor Raj 	/* Clear VSI contexts if not already cleared */
126933e055fcSVictor Raj 	ice_clear_all_vsi_ctx(hw);
1270f31e4b6fSAnirudh Venkataramanan }
1271f31e4b6fSAnirudh Venkataramanan 
1272f31e4b6fSAnirudh Venkataramanan /**
1273f31e4b6fSAnirudh Venkataramanan  * ice_check_reset - Check to see if a global reset is complete
1274f31e4b6fSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
1275f31e4b6fSAnirudh Venkataramanan  */
ice_check_reset(struct ice_hw * hw)12765e24d598STony Nguyen int ice_check_reset(struct ice_hw *hw)
1277f31e4b6fSAnirudh Venkataramanan {
1278585cdabdSNick Nunley 	u32 cnt, reg = 0, grst_timeout, uld_mask;
1279f31e4b6fSAnirudh Venkataramanan 
1280f31e4b6fSAnirudh Venkataramanan 	/* Poll for Device Active state in case a recent CORER, GLOBR,
1281f31e4b6fSAnirudh Venkataramanan 	 * or EMPR has occurred. The grst delay value is in 100ms units.
1282f31e4b6fSAnirudh Venkataramanan 	 * Add 1sec for outstanding AQ commands that can take a long time.
1283f31e4b6fSAnirudh Venkataramanan 	 */
1284585cdabdSNick Nunley 	grst_timeout = ((rd32(hw, GLGEN_RSTCTL) & GLGEN_RSTCTL_GRSTDEL_M) >>
1285f31e4b6fSAnirudh Venkataramanan 			GLGEN_RSTCTL_GRSTDEL_S) + 10;
1286f31e4b6fSAnirudh Venkataramanan 
1287585cdabdSNick Nunley 	for (cnt = 0; cnt < grst_timeout; cnt++) {
1288f31e4b6fSAnirudh Venkataramanan 		mdelay(100);
1289f31e4b6fSAnirudh Venkataramanan 		reg = rd32(hw, GLGEN_RSTAT);
1290f31e4b6fSAnirudh Venkataramanan 		if (!(reg & GLGEN_RSTAT_DEVSTATE_M))
1291f31e4b6fSAnirudh Venkataramanan 			break;
1292f31e4b6fSAnirudh Venkataramanan 	}
1293f31e4b6fSAnirudh Venkataramanan 
1294585cdabdSNick Nunley 	if (cnt == grst_timeout) {
12959228d8b2SJacob Keller 		ice_debug(hw, ICE_DBG_INIT, "Global reset polling failed to complete.\n");
1296d54699e2STony Nguyen 		return -EIO;
1297f31e4b6fSAnirudh Venkataramanan 	}
1298f31e4b6fSAnirudh Venkataramanan 
1299cf8fc2a0SBruce Allan #define ICE_RESET_DONE_MASK	(GLNVM_ULD_PCIER_DONE_M |\
1300cf8fc2a0SBruce Allan 				 GLNVM_ULD_PCIER_DONE_1_M |\
1301cf8fc2a0SBruce Allan 				 GLNVM_ULD_CORER_DONE_M |\
1302cf8fc2a0SBruce Allan 				 GLNVM_ULD_GLOBR_DONE_M |\
1303cf8fc2a0SBruce Allan 				 GLNVM_ULD_POR_DONE_M |\
1304cf8fc2a0SBruce Allan 				 GLNVM_ULD_POR_DONE_1_M |\
1305cf8fc2a0SBruce Allan 				 GLNVM_ULD_PCIER_DONE_2_M)
1306cf8fc2a0SBruce Allan 
1307d25a0fc4SDave Ertman 	uld_mask = ICE_RESET_DONE_MASK | (hw->func_caps.common_cap.rdma ?
1308d25a0fc4SDave Ertman 					  GLNVM_ULD_PE_DONE_M : 0);
1309f31e4b6fSAnirudh Venkataramanan 
1310f31e4b6fSAnirudh Venkataramanan 	/* Device is Active; check Global Reset processes are done */
1311f31e4b6fSAnirudh Venkataramanan 	for (cnt = 0; cnt < ICE_PF_RESET_WAIT_COUNT; cnt++) {
1312cf8fc2a0SBruce Allan 		reg = rd32(hw, GLNVM_ULD) & uld_mask;
1313cf8fc2a0SBruce Allan 		if (reg == uld_mask) {
13149228d8b2SJacob Keller 			ice_debug(hw, ICE_DBG_INIT, "Global reset processes done. %d\n", cnt);
1315f31e4b6fSAnirudh Venkataramanan 			break;
1316f31e4b6fSAnirudh Venkataramanan 		}
1317f31e4b6fSAnirudh Venkataramanan 		mdelay(10);
1318f31e4b6fSAnirudh Venkataramanan 	}
1319f31e4b6fSAnirudh Venkataramanan 
1320f31e4b6fSAnirudh Venkataramanan 	if (cnt == ICE_PF_RESET_WAIT_COUNT) {
13219228d8b2SJacob Keller 		ice_debug(hw, ICE_DBG_INIT, "Wait for Reset Done timed out. GLNVM_ULD = 0x%x\n",
1322f31e4b6fSAnirudh Venkataramanan 			  reg);
1323d54699e2STony Nguyen 		return -EIO;
1324f31e4b6fSAnirudh Venkataramanan 	}
1325f31e4b6fSAnirudh Venkataramanan 
1326f31e4b6fSAnirudh Venkataramanan 	return 0;
1327f31e4b6fSAnirudh Venkataramanan }
1328f31e4b6fSAnirudh Venkataramanan 
1329f31e4b6fSAnirudh Venkataramanan /**
1330f31e4b6fSAnirudh Venkataramanan  * ice_pf_reset - Reset the PF
1331f31e4b6fSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
1332f31e4b6fSAnirudh Venkataramanan  *
1333f31e4b6fSAnirudh Venkataramanan  * If a global reset has been triggered, this function checks
1334f31e4b6fSAnirudh Venkataramanan  * for its completion and then issues the PF reset
1335f31e4b6fSAnirudh Venkataramanan  */
ice_pf_reset(struct ice_hw * hw)13365e24d598STony Nguyen static int ice_pf_reset(struct ice_hw *hw)
1337f31e4b6fSAnirudh Venkataramanan {
1338f31e4b6fSAnirudh Venkataramanan 	u32 cnt, reg;
1339f31e4b6fSAnirudh Venkataramanan 
1340f31e4b6fSAnirudh Venkataramanan 	/* If at function entry a global reset was already in progress, i.e.
1341f31e4b6fSAnirudh Venkataramanan 	 * state is not 'device active' or any of the reset done bits are not
1342f31e4b6fSAnirudh Venkataramanan 	 * set in GLNVM_ULD, there is no need for a PF Reset; poll until the
1343f31e4b6fSAnirudh Venkataramanan 	 * global reset is done.
1344f31e4b6fSAnirudh Venkataramanan 	 */
1345f31e4b6fSAnirudh Venkataramanan 	if ((rd32(hw, GLGEN_RSTAT) & GLGEN_RSTAT_DEVSTATE_M) ||
1346f31e4b6fSAnirudh Venkataramanan 	    (rd32(hw, GLNVM_ULD) & ICE_RESET_DONE_MASK) ^ ICE_RESET_DONE_MASK) {
1347f31e4b6fSAnirudh Venkataramanan 		/* poll on global reset currently in progress until done */
1348f31e4b6fSAnirudh Venkataramanan 		if (ice_check_reset(hw))
1349d54699e2STony Nguyen 			return -EIO;
1350f31e4b6fSAnirudh Venkataramanan 
1351f31e4b6fSAnirudh Venkataramanan 		return 0;
1352f31e4b6fSAnirudh Venkataramanan 	}
1353f31e4b6fSAnirudh Venkataramanan 
1354f31e4b6fSAnirudh Venkataramanan 	/* Reset the PF */
1355f31e4b6fSAnirudh Venkataramanan 	reg = rd32(hw, PFGEN_CTRL);
1356f31e4b6fSAnirudh Venkataramanan 
1357f31e4b6fSAnirudh Venkataramanan 	wr32(hw, PFGEN_CTRL, (reg | PFGEN_CTRL_PFSWR_M));
1358f31e4b6fSAnirudh Venkataramanan 
1359c9a12d6dSDan Nowlin 	/* Wait for the PFR to complete. The wait time is the global config lock
1360c9a12d6dSDan Nowlin 	 * timeout plus the PFR timeout which will account for a possible reset
1361c9a12d6dSDan Nowlin 	 * that is occurring during a download package operation.
1362c9a12d6dSDan Nowlin 	 */
1363c9a12d6dSDan Nowlin 	for (cnt = 0; cnt < ICE_GLOBAL_CFG_LOCK_TIMEOUT +
1364c9a12d6dSDan Nowlin 	     ICE_PF_RESET_WAIT_COUNT; cnt++) {
1365f31e4b6fSAnirudh Venkataramanan 		reg = rd32(hw, PFGEN_CTRL);
1366f31e4b6fSAnirudh Venkataramanan 		if (!(reg & PFGEN_CTRL_PFSWR_M))
1367f31e4b6fSAnirudh Venkataramanan 			break;
1368f31e4b6fSAnirudh Venkataramanan 
1369f31e4b6fSAnirudh Venkataramanan 		mdelay(1);
1370f31e4b6fSAnirudh Venkataramanan 	}
1371f31e4b6fSAnirudh Venkataramanan 
1372f31e4b6fSAnirudh Venkataramanan 	if (cnt == ICE_PF_RESET_WAIT_COUNT) {
13739228d8b2SJacob Keller 		ice_debug(hw, ICE_DBG_INIT, "PF reset polling failed to complete.\n");
1374d54699e2STony Nguyen 		return -EIO;
1375f31e4b6fSAnirudh Venkataramanan 	}
1376f31e4b6fSAnirudh Venkataramanan 
1377f31e4b6fSAnirudh Venkataramanan 	return 0;
1378f31e4b6fSAnirudh Venkataramanan }
1379f31e4b6fSAnirudh Venkataramanan 
1380f31e4b6fSAnirudh Venkataramanan /**
1381f31e4b6fSAnirudh Venkataramanan  * ice_reset - Perform different types of reset
1382f31e4b6fSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
1383f31e4b6fSAnirudh Venkataramanan  * @req: reset request
1384f31e4b6fSAnirudh Venkataramanan  *
1385f31e4b6fSAnirudh Venkataramanan  * This function triggers a reset as specified by the req parameter.
1386f31e4b6fSAnirudh Venkataramanan  *
1387f31e4b6fSAnirudh Venkataramanan  * Note:
1388f31e4b6fSAnirudh Venkataramanan  * If anything other than a PF reset is triggered, PXE mode is restored.
1389f31e4b6fSAnirudh Venkataramanan  * This has to be cleared using ice_clear_pxe_mode again, once the AQ
1390f31e4b6fSAnirudh Venkataramanan  * interface has been restored in the rebuild flow.
1391f31e4b6fSAnirudh Venkataramanan  */
ice_reset(struct ice_hw * hw,enum ice_reset_req req)13925e24d598STony Nguyen int ice_reset(struct ice_hw *hw, enum ice_reset_req req)
1393f31e4b6fSAnirudh Venkataramanan {
1394f31e4b6fSAnirudh Venkataramanan 	u32 val = 0;
1395f31e4b6fSAnirudh Venkataramanan 
1396f31e4b6fSAnirudh Venkataramanan 	switch (req) {
1397f31e4b6fSAnirudh Venkataramanan 	case ICE_RESET_PFR:
1398f31e4b6fSAnirudh Venkataramanan 		return ice_pf_reset(hw);
1399f31e4b6fSAnirudh Venkataramanan 	case ICE_RESET_CORER:
1400f31e4b6fSAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_INIT, "CoreR requested\n");
1401f31e4b6fSAnirudh Venkataramanan 		val = GLGEN_RTRIG_CORER_M;
1402f31e4b6fSAnirudh Venkataramanan 		break;
1403f31e4b6fSAnirudh Venkataramanan 	case ICE_RESET_GLOBR:
1404f31e4b6fSAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_INIT, "GlobalR requested\n");
1405f31e4b6fSAnirudh Venkataramanan 		val = GLGEN_RTRIG_GLOBR_M;
1406f31e4b6fSAnirudh Venkataramanan 		break;
14070f9d5027SAnirudh Venkataramanan 	default:
1408d54699e2STony Nguyen 		return -EINVAL;
1409f31e4b6fSAnirudh Venkataramanan 	}
1410f31e4b6fSAnirudh Venkataramanan 
1411f31e4b6fSAnirudh Venkataramanan 	val |= rd32(hw, GLGEN_RTRIG);
1412f31e4b6fSAnirudh Venkataramanan 	wr32(hw, GLGEN_RTRIG, val);
1413f31e4b6fSAnirudh Venkataramanan 	ice_flush(hw);
1414f31e4b6fSAnirudh Venkataramanan 
1415f31e4b6fSAnirudh Venkataramanan 	/* wait for the FW to be ready */
1416f31e4b6fSAnirudh Venkataramanan 	return ice_check_reset(hw);
1417f31e4b6fSAnirudh Venkataramanan }
1418f31e4b6fSAnirudh Venkataramanan 
14197ec59eeaSAnirudh Venkataramanan /**
1420cdedef59SAnirudh Venkataramanan  * ice_copy_rxq_ctx_to_hw
1421cdedef59SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
1422cdedef59SAnirudh Venkataramanan  * @ice_rxq_ctx: pointer to the rxq context
1423d337f2afSAnirudh Venkataramanan  * @rxq_index: the index of the Rx queue
1424cdedef59SAnirudh Venkataramanan  *
1425f9867df6SAnirudh Venkataramanan  * Copies rxq context from dense structure to HW register space
1426cdedef59SAnirudh Venkataramanan  */
14275e24d598STony Nguyen static int
ice_copy_rxq_ctx_to_hw(struct ice_hw * hw,u8 * ice_rxq_ctx,u32 rxq_index)1428cdedef59SAnirudh Venkataramanan ice_copy_rxq_ctx_to_hw(struct ice_hw *hw, u8 *ice_rxq_ctx, u32 rxq_index)
1429cdedef59SAnirudh Venkataramanan {
1430cdedef59SAnirudh Venkataramanan 	u8 i;
1431cdedef59SAnirudh Venkataramanan 
1432cdedef59SAnirudh Venkataramanan 	if (!ice_rxq_ctx)
1433d54699e2STony Nguyen 		return -EINVAL;
1434cdedef59SAnirudh Venkataramanan 
1435cdedef59SAnirudh Venkataramanan 	if (rxq_index > QRX_CTRL_MAX_INDEX)
1436d54699e2STony Nguyen 		return -EINVAL;
1437cdedef59SAnirudh Venkataramanan 
1438f9867df6SAnirudh Venkataramanan 	/* Copy each dword separately to HW */
1439cdedef59SAnirudh Venkataramanan 	for (i = 0; i < ICE_RXQ_CTX_SIZE_DWORDS; i++) {
1440cdedef59SAnirudh Venkataramanan 		wr32(hw, QRX_CONTEXT(i, rxq_index),
1441cdedef59SAnirudh Venkataramanan 		     *((u32 *)(ice_rxq_ctx + (i * sizeof(u32)))));
1442cdedef59SAnirudh Venkataramanan 
1443cdedef59SAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_QCTX, "qrxdata[%d]: %08X\n", i,
1444cdedef59SAnirudh Venkataramanan 			  *((u32 *)(ice_rxq_ctx + (i * sizeof(u32)))));
1445cdedef59SAnirudh Venkataramanan 	}
1446cdedef59SAnirudh Venkataramanan 
1447cdedef59SAnirudh Venkataramanan 	return 0;
1448cdedef59SAnirudh Venkataramanan }
1449cdedef59SAnirudh Venkataramanan 
1450cdedef59SAnirudh Venkataramanan /* LAN Rx Queue Context */
1451cdedef59SAnirudh Venkataramanan static const struct ice_ctx_ele ice_rlan_ctx_info[] = {
1452cdedef59SAnirudh Venkataramanan 	/* Field		Width	LSB */
1453cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_rlan_ctx, head,		13,	0),
1454cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_rlan_ctx, cpuid,		8,	13),
1455cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_rlan_ctx, base,		57,	32),
1456cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_rlan_ctx, qlen,		13,	89),
1457cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_rlan_ctx, dbuf,		7,	102),
1458cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_rlan_ctx, hbuf,		5,	109),
1459cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_rlan_ctx, dtype,		2,	114),
1460cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_rlan_ctx, dsize,		1,	116),
1461cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_rlan_ctx, crcstrip,		1,	117),
1462cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_rlan_ctx, l2tsel,		1,	119),
1463cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_rlan_ctx, hsplit_0,		4,	120),
1464cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_rlan_ctx, hsplit_1,		2,	124),
1465cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_rlan_ctx, showiv,		1,	127),
1466cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_rlan_ctx, rxmax,		14,	174),
1467cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_rlan_ctx, tphrdesc_ena,	1,	193),
1468cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_rlan_ctx, tphwdesc_ena,	1,	194),
1469cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_rlan_ctx, tphdata_ena,	1,	195),
1470cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_rlan_ctx, tphhead_ena,	1,	196),
1471cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_rlan_ctx, lrxqthresh,		3,	198),
1472c31a5c25SBrett Creeley 	ICE_CTX_STORE(ice_rlan_ctx, prefena,		1,	201),
1473cdedef59SAnirudh Venkataramanan 	{ 0 }
1474cdedef59SAnirudh Venkataramanan };
1475cdedef59SAnirudh Venkataramanan 
1476cdedef59SAnirudh Venkataramanan /**
1477cdedef59SAnirudh Venkataramanan  * ice_write_rxq_ctx
1478cdedef59SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
1479cdedef59SAnirudh Venkataramanan  * @rlan_ctx: pointer to the rxq context
1480d337f2afSAnirudh Venkataramanan  * @rxq_index: the index of the Rx queue
1481cdedef59SAnirudh Venkataramanan  *
1482cdedef59SAnirudh Venkataramanan  * Converts rxq context from sparse to dense structure and then writes
1483c31a5c25SBrett Creeley  * it to HW register space and enables the hardware to prefetch descriptors
1484c31a5c25SBrett Creeley  * instead of only fetching them on demand
1485cdedef59SAnirudh Venkataramanan  */
14865e24d598STony Nguyen int
ice_write_rxq_ctx(struct ice_hw * hw,struct ice_rlan_ctx * rlan_ctx,u32 rxq_index)1487cdedef59SAnirudh Venkataramanan ice_write_rxq_ctx(struct ice_hw *hw, struct ice_rlan_ctx *rlan_ctx,
1488cdedef59SAnirudh Venkataramanan 		  u32 rxq_index)
1489cdedef59SAnirudh Venkataramanan {
1490cdedef59SAnirudh Venkataramanan 	u8 ctx_buf[ICE_RXQ_CTX_SZ] = { 0 };
1491cdedef59SAnirudh Venkataramanan 
1492c31a5c25SBrett Creeley 	if (!rlan_ctx)
1493d54699e2STony Nguyen 		return -EINVAL;
1494c31a5c25SBrett Creeley 
1495c31a5c25SBrett Creeley 	rlan_ctx->prefena = 1;
1496c31a5c25SBrett Creeley 
14977e34786aSBruce Allan 	ice_set_ctx(hw, (u8 *)rlan_ctx, ctx_buf, ice_rlan_ctx_info);
1498cdedef59SAnirudh Venkataramanan 	return ice_copy_rxq_ctx_to_hw(hw, ctx_buf, rxq_index);
1499cdedef59SAnirudh Venkataramanan }
1500cdedef59SAnirudh Venkataramanan 
1501cdedef59SAnirudh Venkataramanan /* LAN Tx Queue Context */
1502cdedef59SAnirudh Venkataramanan const struct ice_ctx_ele ice_tlan_ctx_info[] = {
1503cdedef59SAnirudh Venkataramanan 				    /* Field			Width	LSB */
1504cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, base,			57,	0),
1505cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, port_num,			3,	57),
1506cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, cgd_num,			5,	60),
1507cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, pf_num,			3,	65),
1508cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, vmvf_num,			10,	68),
1509cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, vmvf_type,			2,	78),
1510cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, src_vsi,			10,	80),
1511cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, tsyn_ena,			1,	90),
1512201beeb7SAshish Shah 	ICE_CTX_STORE(ice_tlan_ctx, internal_usage_flag,	1,	91),
1513cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, alt_vlan,			1,	92),
1514cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, cpuid,			8,	93),
1515cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, wb_mode,			1,	101),
1516cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, tphrd_desc,			1,	102),
1517cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, tphrd,			1,	103),
1518cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, tphwr_desc,			1,	104),
1519cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, cmpq_id,			9,	105),
1520cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, qnum_in_func,		14,	114),
1521cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, itr_notification_mode,	1,	128),
1522cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, adjust_prof_id,		6,	129),
1523cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, qlen,			13,	135),
1524cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, quanta_prof_idx,		4,	148),
1525cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, tso_ena,			1,	152),
1526cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, tso_qnum,			11,	153),
1527cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, legacy_int,			1,	164),
1528cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, drop_ena,			1,	165),
1529cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, cache_prof_idx,		2,	166),
1530cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, pkt_shaper_prof_idx,	3,	168),
1531201beeb7SAshish Shah 	ICE_CTX_STORE(ice_tlan_ctx, int_q_state,		122,	171),
1532cdedef59SAnirudh Venkataramanan 	{ 0 }
1533cdedef59SAnirudh Venkataramanan };
1534cdedef59SAnirudh Venkataramanan 
15358f5ee3c4SJacob Keller /* Sideband Queue command wrappers */
15368f5ee3c4SJacob Keller 
15378f5ee3c4SJacob Keller /**
15388f5ee3c4SJacob Keller  * ice_sbq_send_cmd - send Sideband Queue command to Sideband Queue
15398f5ee3c4SJacob Keller  * @hw: pointer to the HW struct
15408f5ee3c4SJacob Keller  * @desc: descriptor describing the command
15418f5ee3c4SJacob Keller  * @buf: buffer to use for indirect commands (NULL for direct commands)
15428f5ee3c4SJacob Keller  * @buf_size: size of buffer for indirect commands (0 for direct commands)
15438f5ee3c4SJacob Keller  * @cd: pointer to command details structure
15448f5ee3c4SJacob Keller  */
15458f5ee3c4SJacob Keller static int
ice_sbq_send_cmd(struct ice_hw * hw,struct ice_sbq_cmd_desc * desc,void * buf,u16 buf_size,struct ice_sq_cd * cd)15468f5ee3c4SJacob Keller ice_sbq_send_cmd(struct ice_hw *hw, struct ice_sbq_cmd_desc *desc,
15478f5ee3c4SJacob Keller 		 void *buf, u16 buf_size, struct ice_sq_cd *cd)
15488f5ee3c4SJacob Keller {
1549d54699e2STony Nguyen 	return ice_sq_send_cmd(hw, ice_get_sbq(hw),
1550d54699e2STony Nguyen 			       (struct ice_aq_desc *)desc, buf, buf_size, cd);
15518f5ee3c4SJacob Keller }
15528f5ee3c4SJacob Keller 
15538f5ee3c4SJacob Keller /**
15548f5ee3c4SJacob Keller  * ice_sbq_rw_reg - Fill Sideband Queue command
15558f5ee3c4SJacob Keller  * @hw: pointer to the HW struct
15568f5ee3c4SJacob Keller  * @in: message info to be filled in descriptor
15578f5ee3c4SJacob Keller  */
ice_sbq_rw_reg(struct ice_hw * hw,struct ice_sbq_msg_input * in)15588f5ee3c4SJacob Keller int ice_sbq_rw_reg(struct ice_hw *hw, struct ice_sbq_msg_input *in)
15598f5ee3c4SJacob Keller {
15608f5ee3c4SJacob Keller 	struct ice_sbq_cmd_desc desc = {0};
15618f5ee3c4SJacob Keller 	struct ice_sbq_msg_req msg = {0};
15628f5ee3c4SJacob Keller 	u16 msg_len;
15638f5ee3c4SJacob Keller 	int status;
15648f5ee3c4SJacob Keller 
15658f5ee3c4SJacob Keller 	msg_len = sizeof(msg);
15668f5ee3c4SJacob Keller 
15678f5ee3c4SJacob Keller 	msg.dest_dev = in->dest_dev;
15688f5ee3c4SJacob Keller 	msg.opcode = in->opcode;
15698f5ee3c4SJacob Keller 	msg.flags = ICE_SBQ_MSG_FLAGS;
15708f5ee3c4SJacob Keller 	msg.sbe_fbe = ICE_SBQ_MSG_SBE_FBE;
15718f5ee3c4SJacob Keller 	msg.msg_addr_low = cpu_to_le16(in->msg_addr_low);
15728f5ee3c4SJacob Keller 	msg.msg_addr_high = cpu_to_le32(in->msg_addr_high);
15738f5ee3c4SJacob Keller 
15748f5ee3c4SJacob Keller 	if (in->opcode)
15758f5ee3c4SJacob Keller 		msg.data = cpu_to_le32(in->data);
15768f5ee3c4SJacob Keller 	else
15778f5ee3c4SJacob Keller 		/* data read comes back in completion, so shorten the struct by
15788f5ee3c4SJacob Keller 		 * sizeof(msg.data)
15798f5ee3c4SJacob Keller 		 */
15808f5ee3c4SJacob Keller 		msg_len -= sizeof(msg.data);
15818f5ee3c4SJacob Keller 
15828f5ee3c4SJacob Keller 	desc.flags = cpu_to_le16(ICE_AQ_FLAG_RD);
15838f5ee3c4SJacob Keller 	desc.opcode = cpu_to_le16(ice_sbq_opc_neigh_dev_req);
15848f5ee3c4SJacob Keller 	desc.param0.cmd_len = cpu_to_le16(msg_len);
15858f5ee3c4SJacob Keller 	status = ice_sbq_send_cmd(hw, &desc, &msg, msg_len, NULL);
15868f5ee3c4SJacob Keller 	if (!status && !in->opcode)
15878f5ee3c4SJacob Keller 		in->data = le32_to_cpu
15888f5ee3c4SJacob Keller 			(((struct ice_sbq_msg_cmpl *)&msg)->data);
15898f5ee3c4SJacob Keller 	return status;
15908f5ee3c4SJacob Keller }
15918f5ee3c4SJacob Keller 
15927ec59eeaSAnirudh Venkataramanan /* FW Admin Queue command wrappers */
15937ec59eeaSAnirudh Venkataramanan 
1594c7648810STony Nguyen /* Software lock/mutex that is meant to be held while the Global Config Lock
1595c7648810STony Nguyen  * in firmware is acquired by the software to prevent most (but not all) types
1596c7648810STony Nguyen  * of AQ commands from being sent to FW
1597c7648810STony Nguyen  */
1598c7648810STony Nguyen DEFINE_MUTEX(ice_global_cfg_lock_sw);
1599c7648810STony Nguyen 
16007ec59eeaSAnirudh Venkataramanan /**
16013056df93SChinh T Cao  * ice_should_retry_sq_send_cmd
16023056df93SChinh T Cao  * @opcode: AQ opcode
16033056df93SChinh T Cao  *
16043056df93SChinh T Cao  * Decide if we should retry the send command routine for the ATQ, depending
16053056df93SChinh T Cao  * on the opcode.
16063056df93SChinh T Cao  */
ice_should_retry_sq_send_cmd(u16 opcode)16073056df93SChinh T Cao static bool ice_should_retry_sq_send_cmd(u16 opcode)
16083056df93SChinh T Cao {
16093056df93SChinh T Cao 	switch (opcode) {
16103056df93SChinh T Cao 	case ice_aqc_opc_get_link_topo:
16113056df93SChinh T Cao 	case ice_aqc_opc_lldp_stop:
16123056df93SChinh T Cao 	case ice_aqc_opc_lldp_start:
16133056df93SChinh T Cao 	case ice_aqc_opc_lldp_filter_ctrl:
16143056df93SChinh T Cao 		return true;
16153056df93SChinh T Cao 	}
16163056df93SChinh T Cao 
16173056df93SChinh T Cao 	return false;
16183056df93SChinh T Cao }
16193056df93SChinh T Cao 
16203056df93SChinh T Cao /**
16213056df93SChinh T Cao  * ice_sq_send_cmd_retry - send command to Control Queue (ATQ)
16223056df93SChinh T Cao  * @hw: pointer to the HW struct
16233056df93SChinh T Cao  * @cq: pointer to the specific Control queue
16243056df93SChinh T Cao  * @desc: prefilled descriptor describing the command
16253056df93SChinh T Cao  * @buf: buffer to use for indirect commands (or NULL for direct commands)
16263056df93SChinh T Cao  * @buf_size: size of buffer for indirect commands (or 0 for direct commands)
16273056df93SChinh T Cao  * @cd: pointer to command details structure
16283056df93SChinh T Cao  *
16293056df93SChinh T Cao  * Retry sending the FW Admin Queue command, multiple times, to the FW Admin
16303056df93SChinh T Cao  * Queue if the EBUSY AQ error is returned.
16313056df93SChinh T Cao  */
16325e24d598STony Nguyen static int
ice_sq_send_cmd_retry(struct ice_hw * hw,struct ice_ctl_q_info * cq,struct ice_aq_desc * desc,void * buf,u16 buf_size,struct ice_sq_cd * cd)16333056df93SChinh T Cao ice_sq_send_cmd_retry(struct ice_hw *hw, struct ice_ctl_q_info *cq,
16343056df93SChinh T Cao 		      struct ice_aq_desc *desc, void *buf, u16 buf_size,
16353056df93SChinh T Cao 		      struct ice_sq_cd *cd)
16363056df93SChinh T Cao {
16373056df93SChinh T Cao 	struct ice_aq_desc desc_cpy;
16383056df93SChinh T Cao 	bool is_cmd_for_retry;
16393056df93SChinh T Cao 	u8 idx = 0;
16403056df93SChinh T Cao 	u16 opcode;
16415518ac2aSTony Nguyen 	int status;
16423056df93SChinh T Cao 
16433056df93SChinh T Cao 	opcode = le16_to_cpu(desc->opcode);
16443056df93SChinh T Cao 	is_cmd_for_retry = ice_should_retry_sq_send_cmd(opcode);
16453056df93SChinh T Cao 	memset(&desc_cpy, 0, sizeof(desc_cpy));
16463056df93SChinh T Cao 
16473056df93SChinh T Cao 	if (is_cmd_for_retry) {
164843a630e3SMichal Schmidt 		/* All retryable cmds are direct, without buf. */
164943a630e3SMichal Schmidt 		WARN_ON(buf);
16503056df93SChinh T Cao 
16513056df93SChinh T Cao 		memcpy(&desc_cpy, desc, sizeof(desc_cpy));
16523056df93SChinh T Cao 	}
16533056df93SChinh T Cao 
16543056df93SChinh T Cao 	do {
16553056df93SChinh T Cao 		status = ice_sq_send_cmd(hw, cq, desc, buf, buf_size, cd);
16563056df93SChinh T Cao 
16573056df93SChinh T Cao 		if (!is_cmd_for_retry || !status ||
16583056df93SChinh T Cao 		    hw->adminq.sq_last_status != ICE_AQ_RC_EBUSY)
16593056df93SChinh T Cao 			break;
16603056df93SChinh T Cao 
16613056df93SChinh T Cao 		memcpy(desc, &desc_cpy, sizeof(desc_cpy));
16623056df93SChinh T Cao 
1663b488ae52SMichal Schmidt 		msleep(ICE_SQ_SEND_DELAY_TIME_MS);
16643056df93SChinh T Cao 
16653056df93SChinh T Cao 	} while (++idx < ICE_SQ_SEND_MAX_EXECUTE);
16663056df93SChinh T Cao 
16673056df93SChinh T Cao 	return status;
16683056df93SChinh T Cao }
16693056df93SChinh T Cao 
16703056df93SChinh T Cao /**
16717ec59eeaSAnirudh Venkataramanan  * ice_aq_send_cmd - send FW Admin Queue command to FW Admin Queue
1672f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
16737ec59eeaSAnirudh Venkataramanan  * @desc: descriptor describing the command
16747ec59eeaSAnirudh Venkataramanan  * @buf: buffer to use for indirect commands (NULL for direct commands)
16757ec59eeaSAnirudh Venkataramanan  * @buf_size: size of buffer for indirect commands (0 for direct commands)
16767ec59eeaSAnirudh Venkataramanan  * @cd: pointer to command details structure
16777ec59eeaSAnirudh Venkataramanan  *
16787ec59eeaSAnirudh Venkataramanan  * Helper function to send FW Admin Queue commands to the FW Admin Queue.
16797ec59eeaSAnirudh Venkataramanan  */
16805e24d598STony Nguyen int
ice_aq_send_cmd(struct ice_hw * hw,struct ice_aq_desc * desc,void * buf,u16 buf_size,struct ice_sq_cd * cd)16817ec59eeaSAnirudh Venkataramanan ice_aq_send_cmd(struct ice_hw *hw, struct ice_aq_desc *desc, void *buf,
16827ec59eeaSAnirudh Venkataramanan 		u16 buf_size, struct ice_sq_cd *cd)
16837ec59eeaSAnirudh Venkataramanan {
1684c7648810STony Nguyen 	struct ice_aqc_req_res *cmd = &desc->params.res_owner;
1685c7648810STony Nguyen 	bool lock_acquired = false;
16865e24d598STony Nguyen 	int status;
1687c7648810STony Nguyen 
1688c7648810STony Nguyen 	/* When a package download is in process (i.e. when the firmware's
1689c7648810STony Nguyen 	 * Global Configuration Lock resource is held), only the Download
1690a1ffafb0SBrett Creeley 	 * Package, Get Version, Get Package Info List, Upload Section,
1691a1ffafb0SBrett Creeley 	 * Update Package, Set Port Parameters, Get/Set VLAN Mode Parameters,
1692a1ffafb0SBrett Creeley 	 * Add Recipe, Set Recipes to Profile Association, Get Recipe, and Get
1693a1ffafb0SBrett Creeley 	 * Recipes to Profile Association, and Release Resource (with resource
1694a1ffafb0SBrett Creeley 	 * ID set to Global Config Lock) AdminQ commands are allowed; all others
1695a1ffafb0SBrett Creeley 	 * must block until the package download completes and the Global Config
1696a1ffafb0SBrett Creeley 	 * Lock is released.  See also ice_acquire_global_cfg_lock().
1697c7648810STony Nguyen 	 */
1698c7648810STony Nguyen 	switch (le16_to_cpu(desc->opcode)) {
1699c7648810STony Nguyen 	case ice_aqc_opc_download_pkg:
1700c7648810STony Nguyen 	case ice_aqc_opc_get_pkg_info_list:
1701c7648810STony Nguyen 	case ice_aqc_opc_get_ver:
1702a1ffafb0SBrett Creeley 	case ice_aqc_opc_upload_section:
1703a1ffafb0SBrett Creeley 	case ice_aqc_opc_update_pkg:
1704a1ffafb0SBrett Creeley 	case ice_aqc_opc_set_port_params:
1705a1ffafb0SBrett Creeley 	case ice_aqc_opc_get_vlan_mode_parameters:
1706a1ffafb0SBrett Creeley 	case ice_aqc_opc_set_vlan_mode_parameters:
1707a1ffafb0SBrett Creeley 	case ice_aqc_opc_add_recipe:
1708a1ffafb0SBrett Creeley 	case ice_aqc_opc_recipe_to_profile:
1709a1ffafb0SBrett Creeley 	case ice_aqc_opc_get_recipe:
1710a1ffafb0SBrett Creeley 	case ice_aqc_opc_get_recipe_to_profile:
1711c7648810STony Nguyen 		break;
1712c7648810STony Nguyen 	case ice_aqc_opc_release_res:
1713c7648810STony Nguyen 		if (le16_to_cpu(cmd->res_id) == ICE_AQC_RES_ID_GLBL_LOCK)
1714c7648810STony Nguyen 			break;
17154e83fc93SBruce Allan 		fallthrough;
1716c7648810STony Nguyen 	default:
1717c7648810STony Nguyen 		mutex_lock(&ice_global_cfg_lock_sw);
1718c7648810STony Nguyen 		lock_acquired = true;
1719c7648810STony Nguyen 		break;
1720c7648810STony Nguyen 	}
1721c7648810STony Nguyen 
17223056df93SChinh T Cao 	status = ice_sq_send_cmd_retry(hw, &hw->adminq, desc, buf, buf_size, cd);
1723c7648810STony Nguyen 	if (lock_acquired)
1724c7648810STony Nguyen 		mutex_unlock(&ice_global_cfg_lock_sw);
1725c7648810STony Nguyen 
1726c7648810STony Nguyen 	return status;
17277ec59eeaSAnirudh Venkataramanan }
17287ec59eeaSAnirudh Venkataramanan 
17297ec59eeaSAnirudh Venkataramanan /**
17307ec59eeaSAnirudh Venkataramanan  * ice_aq_get_fw_ver
1731f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
17327ec59eeaSAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
17337ec59eeaSAnirudh Venkataramanan  *
17347ec59eeaSAnirudh Venkataramanan  * Get the firmware version (0x0001) from the admin queue commands
17357ec59eeaSAnirudh Venkataramanan  */
ice_aq_get_fw_ver(struct ice_hw * hw,struct ice_sq_cd * cd)17365e24d598STony Nguyen int ice_aq_get_fw_ver(struct ice_hw *hw, struct ice_sq_cd *cd)
17377ec59eeaSAnirudh Venkataramanan {
17387ec59eeaSAnirudh Venkataramanan 	struct ice_aqc_get_ver *resp;
17397ec59eeaSAnirudh Venkataramanan 	struct ice_aq_desc desc;
17405e24d598STony Nguyen 	int status;
17417ec59eeaSAnirudh Venkataramanan 
17427ec59eeaSAnirudh Venkataramanan 	resp = &desc.params.get_ver;
17437ec59eeaSAnirudh Venkataramanan 
17447ec59eeaSAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_ver);
17457ec59eeaSAnirudh Venkataramanan 
17467ec59eeaSAnirudh Venkataramanan 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
17477ec59eeaSAnirudh Venkataramanan 
17487ec59eeaSAnirudh Venkataramanan 	if (!status) {
17497ec59eeaSAnirudh Venkataramanan 		hw->fw_branch = resp->fw_branch;
17507ec59eeaSAnirudh Venkataramanan 		hw->fw_maj_ver = resp->fw_major;
17517ec59eeaSAnirudh Venkataramanan 		hw->fw_min_ver = resp->fw_minor;
17527ec59eeaSAnirudh Venkataramanan 		hw->fw_patch = resp->fw_patch;
17537ec59eeaSAnirudh Venkataramanan 		hw->fw_build = le32_to_cpu(resp->fw_build);
17547ec59eeaSAnirudh Venkataramanan 		hw->api_branch = resp->api_branch;
17557ec59eeaSAnirudh Venkataramanan 		hw->api_maj_ver = resp->api_major;
17567ec59eeaSAnirudh Venkataramanan 		hw->api_min_ver = resp->api_minor;
17577ec59eeaSAnirudh Venkataramanan 		hw->api_patch = resp->api_patch;
17587ec59eeaSAnirudh Venkataramanan 	}
17597ec59eeaSAnirudh Venkataramanan 
17607ec59eeaSAnirudh Venkataramanan 	return status;
17617ec59eeaSAnirudh Venkataramanan }
17627ec59eeaSAnirudh Venkataramanan 
17637ec59eeaSAnirudh Venkataramanan /**
1764e3710a01SPaul M Stillwell Jr  * ice_aq_send_driver_ver
1765e3710a01SPaul M Stillwell Jr  * @hw: pointer to the HW struct
1766e3710a01SPaul M Stillwell Jr  * @dv: driver's major, minor version
1767e3710a01SPaul M Stillwell Jr  * @cd: pointer to command details structure or NULL
1768e3710a01SPaul M Stillwell Jr  *
1769e3710a01SPaul M Stillwell Jr  * Send the driver version (0x0002) to the firmware
1770e3710a01SPaul M Stillwell Jr  */
17715e24d598STony Nguyen int
ice_aq_send_driver_ver(struct ice_hw * hw,struct ice_driver_ver * dv,struct ice_sq_cd * cd)1772e3710a01SPaul M Stillwell Jr ice_aq_send_driver_ver(struct ice_hw *hw, struct ice_driver_ver *dv,
1773e3710a01SPaul M Stillwell Jr 		       struct ice_sq_cd *cd)
1774e3710a01SPaul M Stillwell Jr {
1775e3710a01SPaul M Stillwell Jr 	struct ice_aqc_driver_ver *cmd;
1776e3710a01SPaul M Stillwell Jr 	struct ice_aq_desc desc;
1777e3710a01SPaul M Stillwell Jr 	u16 len;
1778e3710a01SPaul M Stillwell Jr 
1779e3710a01SPaul M Stillwell Jr 	cmd = &desc.params.driver_ver;
1780e3710a01SPaul M Stillwell Jr 
1781e3710a01SPaul M Stillwell Jr 	if (!dv)
1782d54699e2STony Nguyen 		return -EINVAL;
1783e3710a01SPaul M Stillwell Jr 
1784e3710a01SPaul M Stillwell Jr 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_driver_ver);
1785e3710a01SPaul M Stillwell Jr 
1786e3710a01SPaul M Stillwell Jr 	desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
1787e3710a01SPaul M Stillwell Jr 	cmd->major_ver = dv->major_ver;
1788e3710a01SPaul M Stillwell Jr 	cmd->minor_ver = dv->minor_ver;
1789e3710a01SPaul M Stillwell Jr 	cmd->build_ver = dv->build_ver;
1790e3710a01SPaul M Stillwell Jr 	cmd->subbuild_ver = dv->subbuild_ver;
1791e3710a01SPaul M Stillwell Jr 
1792e3710a01SPaul M Stillwell Jr 	len = 0;
1793e3710a01SPaul M Stillwell Jr 	while (len < sizeof(dv->driver_string) &&
1794e3710a01SPaul M Stillwell Jr 	       isascii(dv->driver_string[len]) && dv->driver_string[len])
1795e3710a01SPaul M Stillwell Jr 		len++;
1796e3710a01SPaul M Stillwell Jr 
1797e3710a01SPaul M Stillwell Jr 	return ice_aq_send_cmd(hw, &desc, dv->driver_string, len, cd);
1798e3710a01SPaul M Stillwell Jr }
1799e3710a01SPaul M Stillwell Jr 
1800e3710a01SPaul M Stillwell Jr /**
18017ec59eeaSAnirudh Venkataramanan  * ice_aq_q_shutdown
1802f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
18037ec59eeaSAnirudh Venkataramanan  * @unloading: is the driver unloading itself
18047ec59eeaSAnirudh Venkataramanan  *
18057ec59eeaSAnirudh Venkataramanan  * Tell the Firmware that we're shutting down the AdminQ and whether
18067ec59eeaSAnirudh Venkataramanan  * or not the driver is unloading as well (0x0003).
18077ec59eeaSAnirudh Venkataramanan  */
ice_aq_q_shutdown(struct ice_hw * hw,bool unloading)18085e24d598STony Nguyen int ice_aq_q_shutdown(struct ice_hw *hw, bool unloading)
18097ec59eeaSAnirudh Venkataramanan {
18107ec59eeaSAnirudh Venkataramanan 	struct ice_aqc_q_shutdown *cmd;
18117ec59eeaSAnirudh Venkataramanan 	struct ice_aq_desc desc;
18127ec59eeaSAnirudh Venkataramanan 
18137ec59eeaSAnirudh Venkataramanan 	cmd = &desc.params.q_shutdown;
18147ec59eeaSAnirudh Venkataramanan 
18157ec59eeaSAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_q_shutdown);
18167ec59eeaSAnirudh Venkataramanan 
18177ec59eeaSAnirudh Venkataramanan 	if (unloading)
18187404e84aSBruce Allan 		cmd->driver_unloading = ICE_AQC_DRIVER_UNLOADING;
18197ec59eeaSAnirudh Venkataramanan 
18207ec59eeaSAnirudh Venkataramanan 	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
18217ec59eeaSAnirudh Venkataramanan }
1822f31e4b6fSAnirudh Venkataramanan 
1823f31e4b6fSAnirudh Venkataramanan /**
1824f31e4b6fSAnirudh Venkataramanan  * ice_aq_req_res
1825f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
1826f9867df6SAnirudh Venkataramanan  * @res: resource ID
1827f31e4b6fSAnirudh Venkataramanan  * @access: access type
1828f31e4b6fSAnirudh Venkataramanan  * @sdp_number: resource number
1829f31e4b6fSAnirudh Venkataramanan  * @timeout: the maximum time in ms that the driver may hold the resource
1830f31e4b6fSAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
1831f31e4b6fSAnirudh Venkataramanan  *
1832ff2b1321SDan Nowlin  * Requests common resource using the admin queue commands (0x0008).
1833ff2b1321SDan Nowlin  * When attempting to acquire the Global Config Lock, the driver can
1834ff2b1321SDan Nowlin  * learn of three states:
1835d54699e2STony Nguyen  *  1) 0 -         acquired lock, and can perform download package
1836d54699e2STony Nguyen  *  2) -EIO -      did not get lock, driver should fail to load
1837d54699e2STony Nguyen  *  3) -EALREADY - did not get lock, but another driver has
1838ff2b1321SDan Nowlin  *                 successfully downloaded the package; the driver does
1839ff2b1321SDan Nowlin  *                 not have to download the package and can continue
1840ff2b1321SDan Nowlin  *                 loading
1841ff2b1321SDan Nowlin  *
1842ff2b1321SDan Nowlin  * Note that if the caller is in an acquire lock, perform action, release lock
1843ff2b1321SDan Nowlin  * phase of operation, it is possible that the FW may detect a timeout and issue
1844ff2b1321SDan Nowlin  * a CORER. In this case, the driver will receive a CORER interrupt and will
1845ff2b1321SDan Nowlin  * have to determine its cause. The calling thread that is handling this flow
1846ff2b1321SDan Nowlin  * will likely get an error propagated back to it indicating the Download
1847ff2b1321SDan Nowlin  * Package, Update Package or the Release Resource AQ commands timed out.
1848f31e4b6fSAnirudh Venkataramanan  */
18495e24d598STony Nguyen static int
ice_aq_req_res(struct ice_hw * hw,enum ice_aq_res_ids res,enum ice_aq_res_access_type access,u8 sdp_number,u32 * timeout,struct ice_sq_cd * cd)1850f31e4b6fSAnirudh Venkataramanan ice_aq_req_res(struct ice_hw *hw, enum ice_aq_res_ids res,
1851f31e4b6fSAnirudh Venkataramanan 	       enum ice_aq_res_access_type access, u8 sdp_number, u32 *timeout,
1852f31e4b6fSAnirudh Venkataramanan 	       struct ice_sq_cd *cd)
1853f31e4b6fSAnirudh Venkataramanan {
1854f31e4b6fSAnirudh Venkataramanan 	struct ice_aqc_req_res *cmd_resp;
1855f31e4b6fSAnirudh Venkataramanan 	struct ice_aq_desc desc;
18565e24d598STony Nguyen 	int status;
1857f31e4b6fSAnirudh Venkataramanan 
1858f31e4b6fSAnirudh Venkataramanan 	cmd_resp = &desc.params.res_owner;
1859f31e4b6fSAnirudh Venkataramanan 
1860f31e4b6fSAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_req_res);
1861f31e4b6fSAnirudh Venkataramanan 
1862f31e4b6fSAnirudh Venkataramanan 	cmd_resp->res_id = cpu_to_le16(res);
1863f31e4b6fSAnirudh Venkataramanan 	cmd_resp->access_type = cpu_to_le16(access);
1864f31e4b6fSAnirudh Venkataramanan 	cmd_resp->res_number = cpu_to_le32(sdp_number);
1865ff2b1321SDan Nowlin 	cmd_resp->timeout = cpu_to_le32(*timeout);
1866ff2b1321SDan Nowlin 	*timeout = 0;
1867f31e4b6fSAnirudh Venkataramanan 
1868f31e4b6fSAnirudh Venkataramanan 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
1869ff2b1321SDan Nowlin 
1870f31e4b6fSAnirudh Venkataramanan 	/* The completion specifies the maximum time in ms that the driver
1871f31e4b6fSAnirudh Venkataramanan 	 * may hold the resource in the Timeout field.
1872ff2b1321SDan Nowlin 	 */
1873ff2b1321SDan Nowlin 
1874ff2b1321SDan Nowlin 	/* Global config lock response utilizes an additional status field.
1875ff2b1321SDan Nowlin 	 *
1876ff2b1321SDan Nowlin 	 * If the Global config lock resource is held by some other driver, the
1877ff2b1321SDan Nowlin 	 * command completes with ICE_AQ_RES_GLBL_IN_PROG in the status field
1878ff2b1321SDan Nowlin 	 * and the timeout field indicates the maximum time the current owner
1879ff2b1321SDan Nowlin 	 * of the resource has to free it.
1880ff2b1321SDan Nowlin 	 */
1881ff2b1321SDan Nowlin 	if (res == ICE_GLOBAL_CFG_LOCK_RES_ID) {
1882ff2b1321SDan Nowlin 		if (le16_to_cpu(cmd_resp->status) == ICE_AQ_RES_GLBL_SUCCESS) {
1883ff2b1321SDan Nowlin 			*timeout = le32_to_cpu(cmd_resp->timeout);
1884ff2b1321SDan Nowlin 			return 0;
1885ff2b1321SDan Nowlin 		} else if (le16_to_cpu(cmd_resp->status) ==
1886ff2b1321SDan Nowlin 			   ICE_AQ_RES_GLBL_IN_PROG) {
1887ff2b1321SDan Nowlin 			*timeout = le32_to_cpu(cmd_resp->timeout);
1888d54699e2STony Nguyen 			return -EIO;
1889ff2b1321SDan Nowlin 		} else if (le16_to_cpu(cmd_resp->status) ==
1890ff2b1321SDan Nowlin 			   ICE_AQ_RES_GLBL_DONE) {
1891d54699e2STony Nguyen 			return -EALREADY;
1892ff2b1321SDan Nowlin 		}
1893ff2b1321SDan Nowlin 
1894ff2b1321SDan Nowlin 		/* invalid FW response, force a timeout immediately */
1895ff2b1321SDan Nowlin 		*timeout = 0;
1896d54699e2STony Nguyen 		return -EIO;
1897ff2b1321SDan Nowlin 	}
1898ff2b1321SDan Nowlin 
1899ff2b1321SDan Nowlin 	/* If the resource is held by some other driver, the command completes
1900ff2b1321SDan Nowlin 	 * with a busy return value and the timeout field indicates the maximum
1901ff2b1321SDan Nowlin 	 * time the current owner of the resource has to free it.
1902f31e4b6fSAnirudh Venkataramanan 	 */
1903f31e4b6fSAnirudh Venkataramanan 	if (!status || hw->adminq.sq_last_status == ICE_AQ_RC_EBUSY)
1904f31e4b6fSAnirudh Venkataramanan 		*timeout = le32_to_cpu(cmd_resp->timeout);
1905f31e4b6fSAnirudh Venkataramanan 
1906f31e4b6fSAnirudh Venkataramanan 	return status;
1907f31e4b6fSAnirudh Venkataramanan }
1908f31e4b6fSAnirudh Venkataramanan 
1909f31e4b6fSAnirudh Venkataramanan /**
1910f31e4b6fSAnirudh Venkataramanan  * ice_aq_release_res
1911f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
1912f9867df6SAnirudh Venkataramanan  * @res: resource ID
1913f31e4b6fSAnirudh Venkataramanan  * @sdp_number: resource number
1914f31e4b6fSAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
1915f31e4b6fSAnirudh Venkataramanan  *
1916f31e4b6fSAnirudh Venkataramanan  * release common resource using the admin queue commands (0x0009)
1917f31e4b6fSAnirudh Venkataramanan  */
19185e24d598STony Nguyen static int
ice_aq_release_res(struct ice_hw * hw,enum ice_aq_res_ids res,u8 sdp_number,struct ice_sq_cd * cd)1919f31e4b6fSAnirudh Venkataramanan ice_aq_release_res(struct ice_hw *hw, enum ice_aq_res_ids res, u8 sdp_number,
1920f31e4b6fSAnirudh Venkataramanan 		   struct ice_sq_cd *cd)
1921f31e4b6fSAnirudh Venkataramanan {
1922f31e4b6fSAnirudh Venkataramanan 	struct ice_aqc_req_res *cmd;
1923f31e4b6fSAnirudh Venkataramanan 	struct ice_aq_desc desc;
1924f31e4b6fSAnirudh Venkataramanan 
1925f31e4b6fSAnirudh Venkataramanan 	cmd = &desc.params.res_owner;
1926f31e4b6fSAnirudh Venkataramanan 
1927f31e4b6fSAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_release_res);
1928f31e4b6fSAnirudh Venkataramanan 
1929f31e4b6fSAnirudh Venkataramanan 	cmd->res_id = cpu_to_le16(res);
1930f31e4b6fSAnirudh Venkataramanan 	cmd->res_number = cpu_to_le32(sdp_number);
1931f31e4b6fSAnirudh Venkataramanan 
1932f31e4b6fSAnirudh Venkataramanan 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
1933f31e4b6fSAnirudh Venkataramanan }
1934f31e4b6fSAnirudh Venkataramanan 
1935f31e4b6fSAnirudh Venkataramanan /**
1936f31e4b6fSAnirudh Venkataramanan  * ice_acquire_res
1937f31e4b6fSAnirudh Venkataramanan  * @hw: pointer to the HW structure
1938f9867df6SAnirudh Venkataramanan  * @res: resource ID
1939f31e4b6fSAnirudh Venkataramanan  * @access: access type (read or write)
1940ff2b1321SDan Nowlin  * @timeout: timeout in milliseconds
1941f31e4b6fSAnirudh Venkataramanan  *
1942f31e4b6fSAnirudh Venkataramanan  * This function will attempt to acquire the ownership of a resource.
1943f31e4b6fSAnirudh Venkataramanan  */
19445e24d598STony Nguyen int
ice_acquire_res(struct ice_hw * hw,enum ice_aq_res_ids res,enum ice_aq_res_access_type access,u32 timeout)1945f31e4b6fSAnirudh Venkataramanan ice_acquire_res(struct ice_hw *hw, enum ice_aq_res_ids res,
1946ff2b1321SDan Nowlin 		enum ice_aq_res_access_type access, u32 timeout)
1947f31e4b6fSAnirudh Venkataramanan {
1948f31e4b6fSAnirudh Venkataramanan #define ICE_RES_POLLING_DELAY_MS	10
1949f31e4b6fSAnirudh Venkataramanan 	u32 delay = ICE_RES_POLLING_DELAY_MS;
1950ff2b1321SDan Nowlin 	u32 time_left = timeout;
19515e24d598STony Nguyen 	int status;
1952f31e4b6fSAnirudh Venkataramanan 
1953f31e4b6fSAnirudh Venkataramanan 	status = ice_aq_req_res(hw, res, access, 0, &time_left, NULL);
1954f31e4b6fSAnirudh Venkataramanan 
1955d54699e2STony Nguyen 	/* A return code of -EALREADY means that another driver has
1956ff2b1321SDan Nowlin 	 * previously acquired the resource and performed any necessary updates;
1957ff2b1321SDan Nowlin 	 * in this case the caller does not obtain the resource and has no
1958ff2b1321SDan Nowlin 	 * further work to do.
1959f31e4b6fSAnirudh Venkataramanan 	 */
1960d54699e2STony Nguyen 	if (status == -EALREADY)
1961f31e4b6fSAnirudh Venkataramanan 		goto ice_acquire_res_exit;
1962f31e4b6fSAnirudh Venkataramanan 
1963f31e4b6fSAnirudh Venkataramanan 	if (status)
19649228d8b2SJacob Keller 		ice_debug(hw, ICE_DBG_RES, "resource %d acquire type %d failed.\n", res, access);
1965f31e4b6fSAnirudh Venkataramanan 
1966f31e4b6fSAnirudh Venkataramanan 	/* If necessary, poll until the current lock owner timeouts */
1967f31e4b6fSAnirudh Venkataramanan 	timeout = time_left;
1968f31e4b6fSAnirudh Venkataramanan 	while (status && timeout && time_left) {
1969f31e4b6fSAnirudh Venkataramanan 		mdelay(delay);
1970f31e4b6fSAnirudh Venkataramanan 		timeout = (timeout > delay) ? timeout - delay : 0;
1971f31e4b6fSAnirudh Venkataramanan 		status = ice_aq_req_res(hw, res, access, 0, &time_left, NULL);
1972f31e4b6fSAnirudh Venkataramanan 
1973d54699e2STony Nguyen 		if (status == -EALREADY)
1974f31e4b6fSAnirudh Venkataramanan 			/* lock free, but no work to do */
1975f31e4b6fSAnirudh Venkataramanan 			break;
1976f31e4b6fSAnirudh Venkataramanan 
1977f31e4b6fSAnirudh Venkataramanan 		if (!status)
1978f31e4b6fSAnirudh Venkataramanan 			/* lock acquired */
1979f31e4b6fSAnirudh Venkataramanan 			break;
1980f31e4b6fSAnirudh Venkataramanan 	}
1981d54699e2STony Nguyen 	if (status && status != -EALREADY)
1982f31e4b6fSAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_RES, "resource acquire timed out.\n");
1983f31e4b6fSAnirudh Venkataramanan 
1984f31e4b6fSAnirudh Venkataramanan ice_acquire_res_exit:
1985d54699e2STony Nguyen 	if (status == -EALREADY) {
1986f31e4b6fSAnirudh Venkataramanan 		if (access == ICE_RES_WRITE)
19879228d8b2SJacob Keller 			ice_debug(hw, ICE_DBG_RES, "resource indicates no work to do.\n");
1988f31e4b6fSAnirudh Venkataramanan 		else
1989d54699e2STony Nguyen 			ice_debug(hw, ICE_DBG_RES, "Warning: -EALREADY not expected\n");
1990f31e4b6fSAnirudh Venkataramanan 	}
1991f31e4b6fSAnirudh Venkataramanan 	return status;
1992f31e4b6fSAnirudh Venkataramanan }
1993f31e4b6fSAnirudh Venkataramanan 
1994f31e4b6fSAnirudh Venkataramanan /**
1995f31e4b6fSAnirudh Venkataramanan  * ice_release_res
1996f31e4b6fSAnirudh Venkataramanan  * @hw: pointer to the HW structure
1997f9867df6SAnirudh Venkataramanan  * @res: resource ID
1998f31e4b6fSAnirudh Venkataramanan  *
1999f31e4b6fSAnirudh Venkataramanan  * This function will release a resource using the proper Admin Command.
2000f31e4b6fSAnirudh Venkataramanan  */
ice_release_res(struct ice_hw * hw,enum ice_aq_res_ids res)2001f31e4b6fSAnirudh Venkataramanan void ice_release_res(struct ice_hw *hw, enum ice_aq_res_ids res)
2002f31e4b6fSAnirudh Venkataramanan {
2003f86d6f9cSMichal Schmidt 	unsigned long timeout;
20045518ac2aSTony Nguyen 	int status;
2005f31e4b6fSAnirudh Venkataramanan 
2006f31e4b6fSAnirudh Venkataramanan 	/* there are some rare cases when trying to release the resource
2007f9867df6SAnirudh Venkataramanan 	 * results in an admin queue timeout, so handle them correctly
2008f31e4b6fSAnirudh Venkataramanan 	 */
2009f86d6f9cSMichal Schmidt 	timeout = jiffies + 10 * ICE_CTL_Q_SQ_CMD_TIMEOUT;
2010f86d6f9cSMichal Schmidt 	do {
2011f31e4b6fSAnirudh Venkataramanan 		status = ice_aq_release_res(hw, res, 0, NULL);
2012f86d6f9cSMichal Schmidt 		if (status != -EIO)
2013f86d6f9cSMichal Schmidt 			break;
2014f86d6f9cSMichal Schmidt 		usleep_range(1000, 2000);
2015f86d6f9cSMichal Schmidt 	} while (time_before(jiffies, timeout));
2016f31e4b6fSAnirudh Venkataramanan }
2017f31e4b6fSAnirudh Venkataramanan 
2018f31e4b6fSAnirudh Venkataramanan /**
201931ad4e4eSTony Nguyen  * ice_aq_alloc_free_res - command to allocate/free resources
202031ad4e4eSTony Nguyen  * @hw: pointer to the HW struct
202131ad4e4eSTony Nguyen  * @buf: Indirect buffer to hold data parameters and response
202231ad4e4eSTony Nguyen  * @buf_size: size of buffer for indirect commands
202331ad4e4eSTony Nguyen  * @opc: pass in the command opcode
202431ad4e4eSTony Nguyen  *
202531ad4e4eSTony Nguyen  * Helper function to allocate/free resources using the admin queue commands
202631ad4e4eSTony Nguyen  */
ice_aq_alloc_free_res(struct ice_hw * hw,struct ice_aqc_alloc_free_res_elem * buf,u16 buf_size,enum ice_adminq_opc opc)202752da2fb2SPrzemek Kitszel int ice_aq_alloc_free_res(struct ice_hw *hw,
202831ad4e4eSTony Nguyen 			  struct ice_aqc_alloc_free_res_elem *buf, u16 buf_size,
202952da2fb2SPrzemek Kitszel 			  enum ice_adminq_opc opc)
203031ad4e4eSTony Nguyen {
203131ad4e4eSTony Nguyen 	struct ice_aqc_alloc_free_res_cmd *cmd;
203231ad4e4eSTony Nguyen 	struct ice_aq_desc desc;
203331ad4e4eSTony Nguyen 
203431ad4e4eSTony Nguyen 	cmd = &desc.params.sw_res_ctrl;
203531ad4e4eSTony Nguyen 
203652da2fb2SPrzemek Kitszel 	if (!buf || buf_size < flex_array_size(buf, elem, 1))
2037d54699e2STony Nguyen 		return -EINVAL;
203831ad4e4eSTony Nguyen 
203931ad4e4eSTony Nguyen 	ice_fill_dflt_direct_cmd_desc(&desc, opc);
204031ad4e4eSTony Nguyen 
204131ad4e4eSTony Nguyen 	desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
204231ad4e4eSTony Nguyen 
204352da2fb2SPrzemek Kitszel 	cmd->num_entries = cpu_to_le16(1);
204431ad4e4eSTony Nguyen 
204552da2fb2SPrzemek Kitszel 	return ice_aq_send_cmd(hw, &desc, buf, buf_size, NULL);
204631ad4e4eSTony Nguyen }
204731ad4e4eSTony Nguyen 
204831ad4e4eSTony Nguyen /**
204931ad4e4eSTony Nguyen  * ice_alloc_hw_res - allocate resource
205031ad4e4eSTony Nguyen  * @hw: pointer to the HW struct
205131ad4e4eSTony Nguyen  * @type: type of resource
205231ad4e4eSTony Nguyen  * @num: number of resources to allocate
205331ad4e4eSTony Nguyen  * @btm: allocate from bottom
205431ad4e4eSTony Nguyen  * @res: pointer to array that will receive the resources
205531ad4e4eSTony Nguyen  */
20565e24d598STony Nguyen int
ice_alloc_hw_res(struct ice_hw * hw,u16 type,u16 num,bool btm,u16 * res)205731ad4e4eSTony Nguyen ice_alloc_hw_res(struct ice_hw *hw, u16 type, u16 num, bool btm, u16 *res)
205831ad4e4eSTony Nguyen {
205931ad4e4eSTony Nguyen 	struct ice_aqc_alloc_free_res_elem *buf;
206031ad4e4eSTony Nguyen 	u16 buf_len;
20615518ac2aSTony Nguyen 	int status;
206231ad4e4eSTony Nguyen 
206366486d89SBruce Allan 	buf_len = struct_size(buf, elem, num);
206431ad4e4eSTony Nguyen 	buf = kzalloc(buf_len, GFP_KERNEL);
206531ad4e4eSTony Nguyen 	if (!buf)
2066d54699e2STony Nguyen 		return -ENOMEM;
206731ad4e4eSTony Nguyen 
206831ad4e4eSTony Nguyen 	/* Prepare buffer to allocate resource. */
206931ad4e4eSTony Nguyen 	buf->num_elems = cpu_to_le16(num);
207031ad4e4eSTony Nguyen 	buf->res_type = cpu_to_le16(type | ICE_AQC_RES_TYPE_FLAG_DEDICATED |
207131ad4e4eSTony Nguyen 				    ICE_AQC_RES_TYPE_FLAG_IGNORE_INDEX);
207231ad4e4eSTony Nguyen 	if (btm)
207331ad4e4eSTony Nguyen 		buf->res_type |= cpu_to_le16(ICE_AQC_RES_TYPE_FLAG_SCAN_BOTTOM);
207431ad4e4eSTony Nguyen 
207552da2fb2SPrzemek Kitszel 	status = ice_aq_alloc_free_res(hw, buf, buf_len, ice_aqc_opc_alloc_res);
207631ad4e4eSTony Nguyen 	if (status)
207731ad4e4eSTony Nguyen 		goto ice_alloc_res_exit;
207831ad4e4eSTony Nguyen 
207966486d89SBruce Allan 	memcpy(res, buf->elem, sizeof(*buf->elem) * num);
208031ad4e4eSTony Nguyen 
208131ad4e4eSTony Nguyen ice_alloc_res_exit:
208231ad4e4eSTony Nguyen 	kfree(buf);
208331ad4e4eSTony Nguyen 	return status;
208431ad4e4eSTony Nguyen }
208531ad4e4eSTony Nguyen 
208631ad4e4eSTony Nguyen /**
2087451f2c44STony Nguyen  * ice_free_hw_res - free allocated HW resource
2088451f2c44STony Nguyen  * @hw: pointer to the HW struct
2089451f2c44STony Nguyen  * @type: type of resource to free
2090451f2c44STony Nguyen  * @num: number of resources
2091451f2c44STony Nguyen  * @res: pointer to array that contains the resources to free
2092451f2c44STony Nguyen  */
ice_free_hw_res(struct ice_hw * hw,u16 type,u16 num,u16 * res)20935e24d598STony Nguyen int ice_free_hw_res(struct ice_hw *hw, u16 type, u16 num, u16 *res)
2094451f2c44STony Nguyen {
2095451f2c44STony Nguyen 	struct ice_aqc_alloc_free_res_elem *buf;
2096451f2c44STony Nguyen 	u16 buf_len;
20975518ac2aSTony Nguyen 	int status;
2098451f2c44STony Nguyen 
209966486d89SBruce Allan 	buf_len = struct_size(buf, elem, num);
2100451f2c44STony Nguyen 	buf = kzalloc(buf_len, GFP_KERNEL);
2101451f2c44STony Nguyen 	if (!buf)
2102d54699e2STony Nguyen 		return -ENOMEM;
2103451f2c44STony Nguyen 
2104451f2c44STony Nguyen 	/* Prepare buffer to free resource. */
2105451f2c44STony Nguyen 	buf->num_elems = cpu_to_le16(num);
2106451f2c44STony Nguyen 	buf->res_type = cpu_to_le16(type);
210766486d89SBruce Allan 	memcpy(buf->elem, res, sizeof(*buf->elem) * num);
2108451f2c44STony Nguyen 
210952da2fb2SPrzemek Kitszel 	status = ice_aq_alloc_free_res(hw, buf, buf_len, ice_aqc_opc_free_res);
2110451f2c44STony Nguyen 	if (status)
2111451f2c44STony Nguyen 		ice_debug(hw, ICE_DBG_SW, "CQ CMD Buffer:\n");
2112451f2c44STony Nguyen 
2113451f2c44STony Nguyen 	kfree(buf);
2114451f2c44STony Nguyen 	return status;
2115451f2c44STony Nguyen }
2116451f2c44STony Nguyen 
2117451f2c44STony Nguyen /**
21187a1f7111SBrett Creeley  * ice_get_num_per_func - determine number of resources per PF
2119f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW structure
21207a1f7111SBrett Creeley  * @max: value to be evenly split between each PF
2121995c90f2SAnirudh Venkataramanan  *
2122995c90f2SAnirudh Venkataramanan  * Determine the number of valid functions by going through the bitmap returned
21237a1f7111SBrett Creeley  * from parsing capabilities and use this to calculate the number of resources
21247a1f7111SBrett Creeley  * per PF based on the max value passed in.
2125995c90f2SAnirudh Venkataramanan  */
ice_get_num_per_func(struct ice_hw * hw,u32 max)21267a1f7111SBrett Creeley static u32 ice_get_num_per_func(struct ice_hw *hw, u32 max)
2127995c90f2SAnirudh Venkataramanan {
2128995c90f2SAnirudh Venkataramanan 	u8 funcs;
2129995c90f2SAnirudh Venkataramanan 
2130995c90f2SAnirudh Venkataramanan #define ICE_CAPS_VALID_FUNCS_M	0xFF
2131995c90f2SAnirudh Venkataramanan 	funcs = hweight8(hw->dev_caps.common_cap.valid_functions &
2132995c90f2SAnirudh Venkataramanan 			 ICE_CAPS_VALID_FUNCS_M);
2133995c90f2SAnirudh Venkataramanan 
2134995c90f2SAnirudh Venkataramanan 	if (!funcs)
2135995c90f2SAnirudh Venkataramanan 		return 0;
2136995c90f2SAnirudh Venkataramanan 
21377a1f7111SBrett Creeley 	return max / funcs;
2138995c90f2SAnirudh Venkataramanan }
2139995c90f2SAnirudh Venkataramanan 
2140995c90f2SAnirudh Venkataramanan /**
2141595b13e2SJacob Keller  * ice_parse_common_caps - parse common device/function capabilities
2142f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
2143595b13e2SJacob Keller  * @caps: pointer to common capabilities structure
2144595b13e2SJacob Keller  * @elem: the capability element to parse
2145595b13e2SJacob Keller  * @prefix: message prefix for tracing capabilities
21469c20346bSAnirudh Venkataramanan  *
2147595b13e2SJacob Keller  * Given a capability element, extract relevant details into the common
2148595b13e2SJacob Keller  * capability structure.
2149595b13e2SJacob Keller  *
2150595b13e2SJacob Keller  * Returns: true if the capability matches one of the common capability ids,
2151595b13e2SJacob Keller  * false otherwise.
21529c20346bSAnirudh Venkataramanan  */
2153595b13e2SJacob Keller static bool
ice_parse_common_caps(struct ice_hw * hw,struct ice_hw_common_caps * caps,struct ice_aqc_list_caps_elem * elem,const char * prefix)2154595b13e2SJacob Keller ice_parse_common_caps(struct ice_hw *hw, struct ice_hw_common_caps *caps,
2155595b13e2SJacob Keller 		      struct ice_aqc_list_caps_elem *elem, const char *prefix)
21569c20346bSAnirudh Venkataramanan {
2157595b13e2SJacob Keller 	u32 logical_id = le32_to_cpu(elem->logical_id);
2158595b13e2SJacob Keller 	u32 phys_id = le32_to_cpu(elem->phys_id);
2159595b13e2SJacob Keller 	u32 number = le32_to_cpu(elem->number);
2160595b13e2SJacob Keller 	u16 cap = le16_to_cpu(elem->cap);
2161595b13e2SJacob Keller 	bool found = true;
21629c20346bSAnirudh Venkataramanan 
21639c20346bSAnirudh Venkataramanan 	switch (cap) {
2164995c90f2SAnirudh Venkataramanan 	case ICE_AQC_CAPS_VALID_FUNCTIONS:
2165995c90f2SAnirudh Venkataramanan 		caps->valid_functions = number;
21669228d8b2SJacob Keller 		ice_debug(hw, ICE_DBG_INIT, "%s: valid_functions (bitmap) = %d\n", prefix,
2167995c90f2SAnirudh Venkataramanan 			  caps->valid_functions);
2168995c90f2SAnirudh Venkataramanan 		break;
216975d2b253SAnirudh Venkataramanan 	case ICE_AQC_CAPS_SRIOV:
217075d2b253SAnirudh Venkataramanan 		caps->sr_iov_1_1 = (number == 1);
21719228d8b2SJacob Keller 		ice_debug(hw, ICE_DBG_INIT, "%s: sr_iov_1_1 = %d\n", prefix,
2172a84db525SAnirudh Venkataramanan 			  caps->sr_iov_1_1);
217375d2b253SAnirudh Venkataramanan 		break;
2174a257f188SUsha Ketineni 	case ICE_AQC_CAPS_DCB:
2175a257f188SUsha Ketineni 		caps->dcb = (number == 1);
2176a257f188SUsha Ketineni 		caps->active_tc_bitmap = logical_id;
2177a257f188SUsha Ketineni 		caps->maxtc = phys_id;
21789228d8b2SJacob Keller 		ice_debug(hw, ICE_DBG_INIT, "%s: dcb = %d\n", prefix, caps->dcb);
21799228d8b2SJacob Keller 		ice_debug(hw, ICE_DBG_INIT, "%s: active_tc_bitmap = %d\n", prefix,
2180a257f188SUsha Ketineni 			  caps->active_tc_bitmap);
21819228d8b2SJacob Keller 		ice_debug(hw, ICE_DBG_INIT, "%s: maxtc = %d\n", prefix, caps->maxtc);
2182a257f188SUsha Ketineni 		break;
21839c20346bSAnirudh Venkataramanan 	case ICE_AQC_CAPS_RSS:
21849c20346bSAnirudh Venkataramanan 		caps->rss_table_size = number;
21859c20346bSAnirudh Venkataramanan 		caps->rss_table_entry_width = logical_id;
21869228d8b2SJacob Keller 		ice_debug(hw, ICE_DBG_INIT, "%s: rss_table_size = %d\n", prefix,
21879c20346bSAnirudh Venkataramanan 			  caps->rss_table_size);
21889228d8b2SJacob Keller 		ice_debug(hw, ICE_DBG_INIT, "%s: rss_table_entry_width = %d\n", prefix,
21899c20346bSAnirudh Venkataramanan 			  caps->rss_table_entry_width);
21909c20346bSAnirudh Venkataramanan 		break;
21919c20346bSAnirudh Venkataramanan 	case ICE_AQC_CAPS_RXQS:
21929c20346bSAnirudh Venkataramanan 		caps->num_rxq = number;
21939c20346bSAnirudh Venkataramanan 		caps->rxq_first_id = phys_id;
21949228d8b2SJacob Keller 		ice_debug(hw, ICE_DBG_INIT, "%s: num_rxq = %d\n", prefix,
2195a84db525SAnirudh Venkataramanan 			  caps->num_rxq);
21969228d8b2SJacob Keller 		ice_debug(hw, ICE_DBG_INIT, "%s: rxq_first_id = %d\n", prefix,
21979c20346bSAnirudh Venkataramanan 			  caps->rxq_first_id);
21989c20346bSAnirudh Venkataramanan 		break;
21999c20346bSAnirudh Venkataramanan 	case ICE_AQC_CAPS_TXQS:
22009c20346bSAnirudh Venkataramanan 		caps->num_txq = number;
22019c20346bSAnirudh Venkataramanan 		caps->txq_first_id = phys_id;
22029228d8b2SJacob Keller 		ice_debug(hw, ICE_DBG_INIT, "%s: num_txq = %d\n", prefix,
2203a84db525SAnirudh Venkataramanan 			  caps->num_txq);
22049228d8b2SJacob Keller 		ice_debug(hw, ICE_DBG_INIT, "%s: txq_first_id = %d\n", prefix,
22059c20346bSAnirudh Venkataramanan 			  caps->txq_first_id);
22069c20346bSAnirudh Venkataramanan 		break;
22079c20346bSAnirudh Venkataramanan 	case ICE_AQC_CAPS_MSIX:
22089c20346bSAnirudh Venkataramanan 		caps->num_msix_vectors = number;
22099c20346bSAnirudh Venkataramanan 		caps->msix_vector_first_id = phys_id;
22109228d8b2SJacob Keller 		ice_debug(hw, ICE_DBG_INIT, "%s: num_msix_vectors = %d\n", prefix,
22119c20346bSAnirudh Venkataramanan 			  caps->num_msix_vectors);
22129228d8b2SJacob Keller 		ice_debug(hw, ICE_DBG_INIT, "%s: msix_vector_first_id = %d\n", prefix,
22139c20346bSAnirudh Venkataramanan 			  caps->msix_vector_first_id);
22149c20346bSAnirudh Venkataramanan 		break;
22152ab560a7SJacob Keller 	case ICE_AQC_CAPS_PENDING_NVM_VER:
22162ab560a7SJacob Keller 		caps->nvm_update_pending_nvm = true;
22172ab560a7SJacob Keller 		ice_debug(hw, ICE_DBG_INIT, "%s: update_pending_nvm\n", prefix);
22182ab560a7SJacob Keller 		break;
22192ab560a7SJacob Keller 	case ICE_AQC_CAPS_PENDING_OROM_VER:
22202ab560a7SJacob Keller 		caps->nvm_update_pending_orom = true;
22212ab560a7SJacob Keller 		ice_debug(hw, ICE_DBG_INIT, "%s: update_pending_orom\n", prefix);
22222ab560a7SJacob Keller 		break;
22232ab560a7SJacob Keller 	case ICE_AQC_CAPS_PENDING_NET_VER:
22242ab560a7SJacob Keller 		caps->nvm_update_pending_netlist = true;
22252ab560a7SJacob Keller 		ice_debug(hw, ICE_DBG_INIT, "%s: update_pending_netlist\n", prefix);
22262ab560a7SJacob Keller 		break;
2227de9b277eSJacek Naczyk 	case ICE_AQC_CAPS_NVM_MGMT:
2228de9b277eSJacek Naczyk 		caps->nvm_unified_update =
2229de9b277eSJacek Naczyk 			(number & ICE_NVM_MGMT_UNIFIED_UPD_SUPPORT) ?
2230de9b277eSJacek Naczyk 			true : false;
2231de9b277eSJacek Naczyk 		ice_debug(hw, ICE_DBG_INIT, "%s: nvm_unified_update = %d\n", prefix,
2232de9b277eSJacek Naczyk 			  caps->nvm_unified_update);
2233de9b277eSJacek Naczyk 		break;
2234d25a0fc4SDave Ertman 	case ICE_AQC_CAPS_RDMA:
2235d25a0fc4SDave Ertman 		caps->rdma = (number == 1);
2236d25a0fc4SDave Ertman 		ice_debug(hw, ICE_DBG_INIT, "%s: rdma = %d\n", prefix, caps->rdma);
2237d25a0fc4SDave Ertman 		break;
2238595b13e2SJacob Keller 	case ICE_AQC_CAPS_MAX_MTU:
2239595b13e2SJacob Keller 		caps->max_mtu = number;
2240595b13e2SJacob Keller 		ice_debug(hw, ICE_DBG_INIT, "%s: max_mtu = %d\n",
2241595b13e2SJacob Keller 			  prefix, caps->max_mtu);
2242595b13e2SJacob Keller 		break;
2243399e27dbSJacob Keller 	case ICE_AQC_CAPS_PCIE_RESET_AVOIDANCE:
2244399e27dbSJacob Keller 		caps->pcie_reset_avoidance = (number > 0);
2245399e27dbSJacob Keller 		ice_debug(hw, ICE_DBG_INIT,
2246399e27dbSJacob Keller 			  "%s: pcie_reset_avoidance = %d\n", prefix,
2247399e27dbSJacob Keller 			  caps->pcie_reset_avoidance);
2248399e27dbSJacob Keller 		break;
2249399e27dbSJacob Keller 	case ICE_AQC_CAPS_POST_UPDATE_RESET_RESTRICT:
2250399e27dbSJacob Keller 		caps->reset_restrict_support = (number == 1);
2251399e27dbSJacob Keller 		ice_debug(hw, ICE_DBG_INIT,
2252399e27dbSJacob Keller 			  "%s: reset_restrict_support = %d\n", prefix,
2253399e27dbSJacob Keller 			  caps->reset_restrict_support);
2254399e27dbSJacob Keller 		break;
2255bb52f42aSDave Ertman 	case ICE_AQC_CAPS_FW_LAG_SUPPORT:
2256bb52f42aSDave Ertman 		caps->roce_lag = !!(number & ICE_AQC_BIT_ROCEV2_LAG);
2257bb52f42aSDave Ertman 		ice_debug(hw, ICE_DBG_INIT, "%s: roce_lag = %u\n",
2258bb52f42aSDave Ertman 			  prefix, caps->roce_lag);
2259bb52f42aSDave Ertman 		caps->sriov_lag = !!(number & ICE_AQC_BIT_SRIOV_LAG);
2260bb52f42aSDave Ertman 		ice_debug(hw, ICE_DBG_INIT, "%s: sriov_lag = %u\n",
2261bb52f42aSDave Ertman 			  prefix, caps->sriov_lag);
2262bb52f42aSDave Ertman 		break;
2263595b13e2SJacob Keller 	default:
2264595b13e2SJacob Keller 		/* Not one of the recognized common capabilities */
2265595b13e2SJacob Keller 		found = false;
2266148beb61SHenry Tieman 	}
2267595b13e2SJacob Keller 
2268595b13e2SJacob Keller 	return found;
2269595b13e2SJacob Keller }
2270595b13e2SJacob Keller 
2271595b13e2SJacob Keller /**
2272595b13e2SJacob Keller  * ice_recalc_port_limited_caps - Recalculate port limited capabilities
2273595b13e2SJacob Keller  * @hw: pointer to the HW structure
2274595b13e2SJacob Keller  * @caps: pointer to capabilities structure to fix
2275595b13e2SJacob Keller  *
2276595b13e2SJacob Keller  * Re-calculate the capabilities that are dependent on the number of physical
2277595b13e2SJacob Keller  * ports; i.e. some features are not supported or function differently on
2278595b13e2SJacob Keller  * devices with more than 4 ports.
2279595b13e2SJacob Keller  */
2280595b13e2SJacob Keller static void
ice_recalc_port_limited_caps(struct ice_hw * hw,struct ice_hw_common_caps * caps)2281595b13e2SJacob Keller ice_recalc_port_limited_caps(struct ice_hw *hw, struct ice_hw_common_caps *caps)
2282595b13e2SJacob Keller {
2283595b13e2SJacob Keller 	/* This assumes device capabilities are always scanned before function
2284595b13e2SJacob Keller 	 * capabilities during the initialization flow.
2285595b13e2SJacob Keller 	 */
2286595b13e2SJacob Keller 	if (hw->dev_caps.num_funcs > 4) {
2287595b13e2SJacob Keller 		/* Max 4 TCs per port */
2288595b13e2SJacob Keller 		caps->maxtc = 4;
22899228d8b2SJacob Keller 		ice_debug(hw, ICE_DBG_INIT, "reducing maxtc to %d (based on #ports)\n",
2290595b13e2SJacob Keller 			  caps->maxtc);
2291d25a0fc4SDave Ertman 		if (caps->rdma) {
2292d25a0fc4SDave Ertman 			ice_debug(hw, ICE_DBG_INIT, "forcing RDMA off\n");
2293d25a0fc4SDave Ertman 			caps->rdma = 0;
2294d25a0fc4SDave Ertman 		}
2295d25a0fc4SDave Ertman 
2296d25a0fc4SDave Ertman 		/* print message only when processing device capabilities
2297d25a0fc4SDave Ertman 		 * during initialization.
2298d25a0fc4SDave Ertman 		 */
2299d25a0fc4SDave Ertman 		if (caps == &hw->dev_caps.common_cap)
2300d25a0fc4SDave Ertman 			dev_info(ice_hw_to_dev(hw), "RDMA functionality is not available with the current device configuration.\n");
2301595b13e2SJacob Keller 	}
2302595b13e2SJacob Keller }
2303595b13e2SJacob Keller 
2304595b13e2SJacob Keller /**
2305595b13e2SJacob Keller  * ice_parse_vf_func_caps - Parse ICE_AQC_CAPS_VF function caps
2306595b13e2SJacob Keller  * @hw: pointer to the HW struct
2307595b13e2SJacob Keller  * @func_p: pointer to function capabilities structure
2308595b13e2SJacob Keller  * @cap: pointer to the capability element to parse
2309595b13e2SJacob Keller  *
2310595b13e2SJacob Keller  * Extract function capabilities for ICE_AQC_CAPS_VF.
2311595b13e2SJacob Keller  */
2312595b13e2SJacob Keller static void
ice_parse_vf_func_caps(struct ice_hw * hw,struct ice_hw_func_caps * func_p,struct ice_aqc_list_caps_elem * cap)2313595b13e2SJacob Keller ice_parse_vf_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_p,
2314595b13e2SJacob Keller 		       struct ice_aqc_list_caps_elem *cap)
2315595b13e2SJacob Keller {
2316595b13e2SJacob Keller 	u32 logical_id = le32_to_cpu(cap->logical_id);
2317595b13e2SJacob Keller 	u32 number = le32_to_cpu(cap->number);
2318595b13e2SJacob Keller 
2319595b13e2SJacob Keller 	func_p->num_allocd_vfs = number;
2320595b13e2SJacob Keller 	func_p->vf_base_id = logical_id;
2321595b13e2SJacob Keller 	ice_debug(hw, ICE_DBG_INIT, "func caps: num_allocd_vfs = %d\n",
2322595b13e2SJacob Keller 		  func_p->num_allocd_vfs);
2323595b13e2SJacob Keller 	ice_debug(hw, ICE_DBG_INIT, "func caps: vf_base_id = %d\n",
2324595b13e2SJacob Keller 		  func_p->vf_base_id);
2325595b13e2SJacob Keller }
2326595b13e2SJacob Keller 
2327595b13e2SJacob Keller /**
2328595b13e2SJacob Keller  * ice_parse_vsi_func_caps - Parse ICE_AQC_CAPS_VSI function caps
2329595b13e2SJacob Keller  * @hw: pointer to the HW struct
2330595b13e2SJacob Keller  * @func_p: pointer to function capabilities structure
2331595b13e2SJacob Keller  * @cap: pointer to the capability element to parse
2332595b13e2SJacob Keller  *
2333595b13e2SJacob Keller  * Extract function capabilities for ICE_AQC_CAPS_VSI.
2334595b13e2SJacob Keller  */
2335595b13e2SJacob Keller static void
ice_parse_vsi_func_caps(struct ice_hw * hw,struct ice_hw_func_caps * func_p,struct ice_aqc_list_caps_elem * cap)2336595b13e2SJacob Keller ice_parse_vsi_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_p,
2337595b13e2SJacob Keller 			struct ice_aqc_list_caps_elem *cap)
2338595b13e2SJacob Keller {
2339595b13e2SJacob Keller 	func_p->guar_num_vsi = ice_get_num_per_func(hw, ICE_MAX_VSI);
2340595b13e2SJacob Keller 	ice_debug(hw, ICE_DBG_INIT, "func caps: guar_num_vsi (fw) = %d\n",
2341595b13e2SJacob Keller 		  le32_to_cpu(cap->number));
2342595b13e2SJacob Keller 	ice_debug(hw, ICE_DBG_INIT, "func caps: guar_num_vsi = %d\n",
2343595b13e2SJacob Keller 		  func_p->guar_num_vsi);
2344595b13e2SJacob Keller }
2345595b13e2SJacob Keller 
2346595b13e2SJacob Keller /**
23479733cc94SJacob Keller  * ice_parse_1588_func_caps - Parse ICE_AQC_CAPS_1588 function caps
23489733cc94SJacob Keller  * @hw: pointer to the HW struct
23499733cc94SJacob Keller  * @func_p: pointer to function capabilities structure
23509733cc94SJacob Keller  * @cap: pointer to the capability element to parse
23519733cc94SJacob Keller  *
23529733cc94SJacob Keller  * Extract function capabilities for ICE_AQC_CAPS_1588.
23539733cc94SJacob Keller  */
23549733cc94SJacob Keller static void
ice_parse_1588_func_caps(struct ice_hw * hw,struct ice_hw_func_caps * func_p,struct ice_aqc_list_caps_elem * cap)23559733cc94SJacob Keller ice_parse_1588_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_p,
23569733cc94SJacob Keller 			 struct ice_aqc_list_caps_elem *cap)
23579733cc94SJacob Keller {
23589733cc94SJacob Keller 	struct ice_ts_func_info *info = &func_p->ts_func_info;
23599733cc94SJacob Keller 	u32 number = le32_to_cpu(cap->number);
23609733cc94SJacob Keller 
23619733cc94SJacob Keller 	info->ena = ((number & ICE_TS_FUNC_ENA_M) != 0);
23629733cc94SJacob Keller 	func_p->common_cap.ieee_1588 = info->ena;
23639733cc94SJacob Keller 
23649733cc94SJacob Keller 	info->src_tmr_owned = ((number & ICE_TS_SRC_TMR_OWND_M) != 0);
23659733cc94SJacob Keller 	info->tmr_ena = ((number & ICE_TS_TMR_ENA_M) != 0);
23669733cc94SJacob Keller 	info->tmr_index_owned = ((number & ICE_TS_TMR_IDX_OWND_M) != 0);
23679733cc94SJacob Keller 	info->tmr_index_assoc = ((number & ICE_TS_TMR_IDX_ASSOC_M) != 0);
23689733cc94SJacob Keller 
23699733cc94SJacob Keller 	info->clk_freq = (number & ICE_TS_CLK_FREQ_M) >> ICE_TS_CLK_FREQ_S;
23709733cc94SJacob Keller 	info->clk_src = ((number & ICE_TS_CLK_SRC_M) != 0);
23719733cc94SJacob Keller 
2372405efa49SJacob Keller 	if (info->clk_freq < NUM_ICE_TIME_REF_FREQ) {
2373405efa49SJacob Keller 		info->time_ref = (enum ice_time_ref_freq)info->clk_freq;
2374405efa49SJacob Keller 	} else {
2375405efa49SJacob Keller 		/* Unknown clock frequency, so assume a (probably incorrect)
2376405efa49SJacob Keller 		 * default to avoid out-of-bounds look ups of frequency
2377405efa49SJacob Keller 		 * related information.
2378405efa49SJacob Keller 		 */
2379405efa49SJacob Keller 		ice_debug(hw, ICE_DBG_INIT, "1588 func caps: unknown clock frequency %u\n",
2380405efa49SJacob Keller 			  info->clk_freq);
2381405efa49SJacob Keller 		info->time_ref = ICE_TIME_REF_FREQ_25_000;
2382405efa49SJacob Keller 	}
2383405efa49SJacob Keller 
23849733cc94SJacob Keller 	ice_debug(hw, ICE_DBG_INIT, "func caps: ieee_1588 = %u\n",
23859733cc94SJacob Keller 		  func_p->common_cap.ieee_1588);
23869733cc94SJacob Keller 	ice_debug(hw, ICE_DBG_INIT, "func caps: src_tmr_owned = %u\n",
23879733cc94SJacob Keller 		  info->src_tmr_owned);
23889733cc94SJacob Keller 	ice_debug(hw, ICE_DBG_INIT, "func caps: tmr_ena = %u\n",
23899733cc94SJacob Keller 		  info->tmr_ena);
23909733cc94SJacob Keller 	ice_debug(hw, ICE_DBG_INIT, "func caps: tmr_index_owned = %u\n",
23919733cc94SJacob Keller 		  info->tmr_index_owned);
23929733cc94SJacob Keller 	ice_debug(hw, ICE_DBG_INIT, "func caps: tmr_index_assoc = %u\n",
23939733cc94SJacob Keller 		  info->tmr_index_assoc);
23949733cc94SJacob Keller 	ice_debug(hw, ICE_DBG_INIT, "func caps: clk_freq = %u\n",
23959733cc94SJacob Keller 		  info->clk_freq);
23969733cc94SJacob Keller 	ice_debug(hw, ICE_DBG_INIT, "func caps: clk_src = %u\n",
23979733cc94SJacob Keller 		  info->clk_src);
23989733cc94SJacob Keller }
23999733cc94SJacob Keller 
24009733cc94SJacob Keller /**
2401595b13e2SJacob Keller  * ice_parse_fdir_func_caps - Parse ICE_AQC_CAPS_FD function caps
2402595b13e2SJacob Keller  * @hw: pointer to the HW struct
2403595b13e2SJacob Keller  * @func_p: pointer to function capabilities structure
2404595b13e2SJacob Keller  *
2405595b13e2SJacob Keller  * Extract function capabilities for ICE_AQC_CAPS_FD.
2406595b13e2SJacob Keller  */
2407595b13e2SJacob Keller static void
ice_parse_fdir_func_caps(struct ice_hw * hw,struct ice_hw_func_caps * func_p)2408595b13e2SJacob Keller ice_parse_fdir_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_p)
2409595b13e2SJacob Keller {
2410*88f7ac6cSPaul Greenwalt 	u32 reg_val, gsize, bsize;
2411148beb61SHenry Tieman 
2412148beb61SHenry Tieman 	reg_val = rd32(hw, GLQF_FD_SIZE);
2413*88f7ac6cSPaul Greenwalt 	switch (hw->mac_type) {
2414*88f7ac6cSPaul Greenwalt 	case ICE_MAC_E830:
2415*88f7ac6cSPaul Greenwalt 		gsize = FIELD_GET(E830_GLQF_FD_SIZE_FD_GSIZE_M, reg_val);
2416*88f7ac6cSPaul Greenwalt 		bsize = FIELD_GET(E830_GLQF_FD_SIZE_FD_BSIZE_M, reg_val);
2417*88f7ac6cSPaul Greenwalt 		break;
2418*88f7ac6cSPaul Greenwalt 	case ICE_MAC_E810:
2419*88f7ac6cSPaul Greenwalt 	default:
2420*88f7ac6cSPaul Greenwalt 		gsize = FIELD_GET(E800_GLQF_FD_SIZE_FD_GSIZE_M, reg_val);
2421*88f7ac6cSPaul Greenwalt 		bsize = FIELD_GET(E800_GLQF_FD_SIZE_FD_BSIZE_M, reg_val);
2422*88f7ac6cSPaul Greenwalt 	}
2423*88f7ac6cSPaul Greenwalt 	func_p->fd_fltr_guar = ice_get_num_per_func(hw, gsize);
2424*88f7ac6cSPaul Greenwalt 	func_p->fd_fltr_best_effort = bsize;
2425595b13e2SJacob Keller 
24269228d8b2SJacob Keller 	ice_debug(hw, ICE_DBG_INIT, "func caps: fd_fltr_guar = %d\n",
2427595b13e2SJacob Keller 		  func_p->fd_fltr_guar);
24289228d8b2SJacob Keller 	ice_debug(hw, ICE_DBG_INIT, "func caps: fd_fltr_best_effort = %d\n",
2429595b13e2SJacob Keller 		  func_p->fd_fltr_best_effort);
2430148beb61SHenry Tieman }
2431595b13e2SJacob Keller 
2432595b13e2SJacob Keller /**
2433595b13e2SJacob Keller  * ice_parse_func_caps - Parse function capabilities
2434595b13e2SJacob Keller  * @hw: pointer to the HW struct
2435595b13e2SJacob Keller  * @func_p: pointer to function capabilities structure
2436595b13e2SJacob Keller  * @buf: buffer containing the function capability records
2437595b13e2SJacob Keller  * @cap_count: the number of capabilities
2438595b13e2SJacob Keller  *
2439595b13e2SJacob Keller  * Helper function to parse function (0x000A) capabilities list. For
2440595b13e2SJacob Keller  * capabilities shared between device and function, this relies on
2441595b13e2SJacob Keller  * ice_parse_common_caps.
2442595b13e2SJacob Keller  *
2443595b13e2SJacob Keller  * Loop through the list of provided capabilities and extract the relevant
2444595b13e2SJacob Keller  * data into the function capabilities structured.
2445595b13e2SJacob Keller  */
2446595b13e2SJacob Keller static void
ice_parse_func_caps(struct ice_hw * hw,struct ice_hw_func_caps * func_p,void * buf,u32 cap_count)2447595b13e2SJacob Keller ice_parse_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_p,
2448595b13e2SJacob Keller 		    void *buf, u32 cap_count)
2449595b13e2SJacob Keller {
2450595b13e2SJacob Keller 	struct ice_aqc_list_caps_elem *cap_resp;
2451595b13e2SJacob Keller 	u32 i;
2452595b13e2SJacob Keller 
24537a63dae0SBruce Allan 	cap_resp = buf;
2454595b13e2SJacob Keller 
2455595b13e2SJacob Keller 	memset(func_p, 0, sizeof(*func_p));
2456595b13e2SJacob Keller 
2457595b13e2SJacob Keller 	for (i = 0; i < cap_count; i++) {
2458595b13e2SJacob Keller 		u16 cap = le16_to_cpu(cap_resp[i].cap);
2459595b13e2SJacob Keller 		bool found;
2460595b13e2SJacob Keller 
2461595b13e2SJacob Keller 		found = ice_parse_common_caps(hw, &func_p->common_cap,
2462595b13e2SJacob Keller 					      &cap_resp[i], "func caps");
2463595b13e2SJacob Keller 
2464595b13e2SJacob Keller 		switch (cap) {
2465595b13e2SJacob Keller 		case ICE_AQC_CAPS_VF:
2466595b13e2SJacob Keller 			ice_parse_vf_func_caps(hw, func_p, &cap_resp[i]);
2467148beb61SHenry Tieman 			break;
2468595b13e2SJacob Keller 		case ICE_AQC_CAPS_VSI:
2469595b13e2SJacob Keller 			ice_parse_vsi_func_caps(hw, func_p, &cap_resp[i]);
2470595b13e2SJacob Keller 			break;
24719733cc94SJacob Keller 		case ICE_AQC_CAPS_1588:
24729733cc94SJacob Keller 			ice_parse_1588_func_caps(hw, func_p, &cap_resp[i]);
24739733cc94SJacob Keller 			break;
2474595b13e2SJacob Keller 		case ICE_AQC_CAPS_FD:
2475595b13e2SJacob Keller 			ice_parse_fdir_func_caps(hw, func_p);
24769c20346bSAnirudh Venkataramanan 			break;
24779c20346bSAnirudh Venkataramanan 		default:
2478595b13e2SJacob Keller 			/* Don't list common capabilities as unknown */
2479595b13e2SJacob Keller 			if (!found)
24809228d8b2SJacob Keller 				ice_debug(hw, ICE_DBG_INIT, "func caps: unknown capability[%d]: 0x%x\n",
2481a84db525SAnirudh Venkataramanan 					  i, cap);
24829c20346bSAnirudh Venkataramanan 			break;
24839c20346bSAnirudh Venkataramanan 		}
24849c20346bSAnirudh Venkataramanan 	}
24859164f761SBruce Allan 
2486595b13e2SJacob Keller 	ice_recalc_port_limited_caps(hw, &func_p->common_cap);
24879164f761SBruce Allan }
2488595b13e2SJacob Keller 
2489595b13e2SJacob Keller /**
2490595b13e2SJacob Keller  * ice_parse_valid_functions_cap - Parse ICE_AQC_CAPS_VALID_FUNCTIONS caps
2491595b13e2SJacob Keller  * @hw: pointer to the HW struct
2492595b13e2SJacob Keller  * @dev_p: pointer to device capabilities structure
2493595b13e2SJacob Keller  * @cap: capability element to parse
2494595b13e2SJacob Keller  *
2495595b13e2SJacob Keller  * Parse ICE_AQC_CAPS_VALID_FUNCTIONS for device capabilities.
2496595b13e2SJacob Keller  */
2497595b13e2SJacob Keller static void
ice_parse_valid_functions_cap(struct ice_hw * hw,struct ice_hw_dev_caps * dev_p,struct ice_aqc_list_caps_elem * cap)2498595b13e2SJacob Keller ice_parse_valid_functions_cap(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
2499595b13e2SJacob Keller 			      struct ice_aqc_list_caps_elem *cap)
2500595b13e2SJacob Keller {
2501595b13e2SJacob Keller 	u32 number = le32_to_cpu(cap->number);
2502595b13e2SJacob Keller 
2503595b13e2SJacob Keller 	dev_p->num_funcs = hweight32(number);
2504595b13e2SJacob Keller 	ice_debug(hw, ICE_DBG_INIT, "dev caps: num_funcs = %d\n",
2505595b13e2SJacob Keller 		  dev_p->num_funcs);
2506595b13e2SJacob Keller }
2507595b13e2SJacob Keller 
2508595b13e2SJacob Keller /**
2509595b13e2SJacob Keller  * ice_parse_vf_dev_caps - Parse ICE_AQC_CAPS_VF device caps
2510595b13e2SJacob Keller  * @hw: pointer to the HW struct
2511595b13e2SJacob Keller  * @dev_p: pointer to device capabilities structure
2512595b13e2SJacob Keller  * @cap: capability element to parse
2513595b13e2SJacob Keller  *
2514595b13e2SJacob Keller  * Parse ICE_AQC_CAPS_VF for device capabilities.
2515595b13e2SJacob Keller  */
2516595b13e2SJacob Keller static void
ice_parse_vf_dev_caps(struct ice_hw * hw,struct ice_hw_dev_caps * dev_p,struct ice_aqc_list_caps_elem * cap)2517595b13e2SJacob Keller ice_parse_vf_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
2518595b13e2SJacob Keller 		      struct ice_aqc_list_caps_elem *cap)
2519595b13e2SJacob Keller {
2520595b13e2SJacob Keller 	u32 number = le32_to_cpu(cap->number);
2521595b13e2SJacob Keller 
2522595b13e2SJacob Keller 	dev_p->num_vfs_exposed = number;
2523595b13e2SJacob Keller 	ice_debug(hw, ICE_DBG_INIT, "dev_caps: num_vfs_exposed = %d\n",
2524595b13e2SJacob Keller 		  dev_p->num_vfs_exposed);
2525595b13e2SJacob Keller }
2526595b13e2SJacob Keller 
2527595b13e2SJacob Keller /**
2528595b13e2SJacob Keller  * ice_parse_vsi_dev_caps - Parse ICE_AQC_CAPS_VSI device caps
2529595b13e2SJacob Keller  * @hw: pointer to the HW struct
2530595b13e2SJacob Keller  * @dev_p: pointer to device capabilities structure
2531595b13e2SJacob Keller  * @cap: capability element to parse
2532595b13e2SJacob Keller  *
2533595b13e2SJacob Keller  * Parse ICE_AQC_CAPS_VSI for device capabilities.
2534595b13e2SJacob Keller  */
2535595b13e2SJacob Keller static void
ice_parse_vsi_dev_caps(struct ice_hw * hw,struct ice_hw_dev_caps * dev_p,struct ice_aqc_list_caps_elem * cap)2536595b13e2SJacob Keller ice_parse_vsi_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
2537595b13e2SJacob Keller 		       struct ice_aqc_list_caps_elem *cap)
2538595b13e2SJacob Keller {
2539595b13e2SJacob Keller 	u32 number = le32_to_cpu(cap->number);
2540595b13e2SJacob Keller 
2541595b13e2SJacob Keller 	dev_p->num_vsi_allocd_to_host = number;
2542595b13e2SJacob Keller 	ice_debug(hw, ICE_DBG_INIT, "dev caps: num_vsi_allocd_to_host = %d\n",
2543595b13e2SJacob Keller 		  dev_p->num_vsi_allocd_to_host);
2544595b13e2SJacob Keller }
2545595b13e2SJacob Keller 
2546595b13e2SJacob Keller /**
25479733cc94SJacob Keller  * ice_parse_1588_dev_caps - Parse ICE_AQC_CAPS_1588 device caps
25489733cc94SJacob Keller  * @hw: pointer to the HW struct
25499733cc94SJacob Keller  * @dev_p: pointer to device capabilities structure
25509733cc94SJacob Keller  * @cap: capability element to parse
25519733cc94SJacob Keller  *
25529733cc94SJacob Keller  * Parse ICE_AQC_CAPS_1588 for device capabilities.
25539733cc94SJacob Keller  */
25549733cc94SJacob Keller static void
ice_parse_1588_dev_caps(struct ice_hw * hw,struct ice_hw_dev_caps * dev_p,struct ice_aqc_list_caps_elem * cap)25559733cc94SJacob Keller ice_parse_1588_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
25569733cc94SJacob Keller 			struct ice_aqc_list_caps_elem *cap)
25579733cc94SJacob Keller {
25589733cc94SJacob Keller 	struct ice_ts_dev_info *info = &dev_p->ts_dev_info;
25599733cc94SJacob Keller 	u32 logical_id = le32_to_cpu(cap->logical_id);
25609733cc94SJacob Keller 	u32 phys_id = le32_to_cpu(cap->phys_id);
25619733cc94SJacob Keller 	u32 number = le32_to_cpu(cap->number);
25629733cc94SJacob Keller 
25639733cc94SJacob Keller 	info->ena = ((number & ICE_TS_DEV_ENA_M) != 0);
25649733cc94SJacob Keller 	dev_p->common_cap.ieee_1588 = info->ena;
25659733cc94SJacob Keller 
25669733cc94SJacob Keller 	info->tmr0_owner = number & ICE_TS_TMR0_OWNR_M;
25679733cc94SJacob Keller 	info->tmr0_owned = ((number & ICE_TS_TMR0_OWND_M) != 0);
25689733cc94SJacob Keller 	info->tmr0_ena = ((number & ICE_TS_TMR0_ENA_M) != 0);
25699733cc94SJacob Keller 
25709733cc94SJacob Keller 	info->tmr1_owner = (number & ICE_TS_TMR1_OWNR_M) >> ICE_TS_TMR1_OWNR_S;
25719733cc94SJacob Keller 	info->tmr1_owned = ((number & ICE_TS_TMR1_OWND_M) != 0);
25729733cc94SJacob Keller 	info->tmr1_ena = ((number & ICE_TS_TMR1_ENA_M) != 0);
25739733cc94SJacob Keller 
25741229b339SKarol Kolacinski 	info->ts_ll_read = ((number & ICE_TS_LL_TX_TS_READ_M) != 0);
25751229b339SKarol Kolacinski 
25769733cc94SJacob Keller 	info->ena_ports = logical_id;
25779733cc94SJacob Keller 	info->tmr_own_map = phys_id;
25789733cc94SJacob Keller 
25799733cc94SJacob Keller 	ice_debug(hw, ICE_DBG_INIT, "dev caps: ieee_1588 = %u\n",
25809733cc94SJacob Keller 		  dev_p->common_cap.ieee_1588);
25819733cc94SJacob Keller 	ice_debug(hw, ICE_DBG_INIT, "dev caps: tmr0_owner = %u\n",
25829733cc94SJacob Keller 		  info->tmr0_owner);
25839733cc94SJacob Keller 	ice_debug(hw, ICE_DBG_INIT, "dev caps: tmr0_owned = %u\n",
25849733cc94SJacob Keller 		  info->tmr0_owned);
25859733cc94SJacob Keller 	ice_debug(hw, ICE_DBG_INIT, "dev caps: tmr0_ena = %u\n",
25869733cc94SJacob Keller 		  info->tmr0_ena);
25879733cc94SJacob Keller 	ice_debug(hw, ICE_DBG_INIT, "dev caps: tmr1_owner = %u\n",
25889733cc94SJacob Keller 		  info->tmr1_owner);
25899733cc94SJacob Keller 	ice_debug(hw, ICE_DBG_INIT, "dev caps: tmr1_owned = %u\n",
25909733cc94SJacob Keller 		  info->tmr1_owned);
25919733cc94SJacob Keller 	ice_debug(hw, ICE_DBG_INIT, "dev caps: tmr1_ena = %u\n",
25929733cc94SJacob Keller 		  info->tmr1_ena);
25931229b339SKarol Kolacinski 	ice_debug(hw, ICE_DBG_INIT, "dev caps: ts_ll_read = %u\n",
25941229b339SKarol Kolacinski 		  info->ts_ll_read);
25959733cc94SJacob Keller 	ice_debug(hw, ICE_DBG_INIT, "dev caps: ieee_1588 ena_ports = %u\n",
25969733cc94SJacob Keller 		  info->ena_ports);
25979733cc94SJacob Keller 	ice_debug(hw, ICE_DBG_INIT, "dev caps: tmr_own_map = %u\n",
25989733cc94SJacob Keller 		  info->tmr_own_map);
25999733cc94SJacob Keller }
26009733cc94SJacob Keller 
26019733cc94SJacob Keller /**
2602595b13e2SJacob Keller  * ice_parse_fdir_dev_caps - Parse ICE_AQC_CAPS_FD device caps
2603595b13e2SJacob Keller  * @hw: pointer to the HW struct
2604595b13e2SJacob Keller  * @dev_p: pointer to device capabilities structure
2605595b13e2SJacob Keller  * @cap: capability element to parse
2606595b13e2SJacob Keller  *
2607595b13e2SJacob Keller  * Parse ICE_AQC_CAPS_FD for device capabilities.
2608595b13e2SJacob Keller  */
2609595b13e2SJacob Keller static void
ice_parse_fdir_dev_caps(struct ice_hw * hw,struct ice_hw_dev_caps * dev_p,struct ice_aqc_list_caps_elem * cap)2610595b13e2SJacob Keller ice_parse_fdir_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
2611595b13e2SJacob Keller 			struct ice_aqc_list_caps_elem *cap)
2612595b13e2SJacob Keller {
2613595b13e2SJacob Keller 	u32 number = le32_to_cpu(cap->number);
2614595b13e2SJacob Keller 
2615595b13e2SJacob Keller 	dev_p->num_flow_director_fltr = number;
2616595b13e2SJacob Keller 	ice_debug(hw, ICE_DBG_INIT, "dev caps: num_flow_director_fltr = %d\n",
2617595b13e2SJacob Keller 		  dev_p->num_flow_director_fltr);
2618595b13e2SJacob Keller }
2619595b13e2SJacob Keller 
2620595b13e2SJacob Keller /**
2621595b13e2SJacob Keller  * ice_parse_dev_caps - Parse device capabilities
2622595b13e2SJacob Keller  * @hw: pointer to the HW struct
2623595b13e2SJacob Keller  * @dev_p: pointer to device capabilities structure
2624595b13e2SJacob Keller  * @buf: buffer containing the device capability records
2625595b13e2SJacob Keller  * @cap_count: the number of capabilities
2626595b13e2SJacob Keller  *
2627595b13e2SJacob Keller  * Helper device to parse device (0x000B) capabilities list. For
26287dbc63f0STony Nguyen  * capabilities shared between device and function, this relies on
2629595b13e2SJacob Keller  * ice_parse_common_caps.
2630595b13e2SJacob Keller  *
2631595b13e2SJacob Keller  * Loop through the list of provided capabilities and extract the relevant
2632595b13e2SJacob Keller  * data into the device capabilities structured.
2633595b13e2SJacob Keller  */
2634595b13e2SJacob Keller static void
ice_parse_dev_caps(struct ice_hw * hw,struct ice_hw_dev_caps * dev_p,void * buf,u32 cap_count)2635595b13e2SJacob Keller ice_parse_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
2636595b13e2SJacob Keller 		   void *buf, u32 cap_count)
2637595b13e2SJacob Keller {
2638595b13e2SJacob Keller 	struct ice_aqc_list_caps_elem *cap_resp;
2639595b13e2SJacob Keller 	u32 i;
2640595b13e2SJacob Keller 
26417a63dae0SBruce Allan 	cap_resp = buf;
2642595b13e2SJacob Keller 
2643595b13e2SJacob Keller 	memset(dev_p, 0, sizeof(*dev_p));
2644595b13e2SJacob Keller 
2645595b13e2SJacob Keller 	for (i = 0; i < cap_count; i++) {
2646595b13e2SJacob Keller 		u16 cap = le16_to_cpu(cap_resp[i].cap);
2647595b13e2SJacob Keller 		bool found;
2648595b13e2SJacob Keller 
2649595b13e2SJacob Keller 		found = ice_parse_common_caps(hw, &dev_p->common_cap,
2650595b13e2SJacob Keller 					      &cap_resp[i], "dev caps");
2651595b13e2SJacob Keller 
2652595b13e2SJacob Keller 		switch (cap) {
2653595b13e2SJacob Keller 		case ICE_AQC_CAPS_VALID_FUNCTIONS:
2654595b13e2SJacob Keller 			ice_parse_valid_functions_cap(hw, dev_p, &cap_resp[i]);
2655595b13e2SJacob Keller 			break;
2656595b13e2SJacob Keller 		case ICE_AQC_CAPS_VF:
2657595b13e2SJacob Keller 			ice_parse_vf_dev_caps(hw, dev_p, &cap_resp[i]);
2658595b13e2SJacob Keller 			break;
2659595b13e2SJacob Keller 		case ICE_AQC_CAPS_VSI:
2660595b13e2SJacob Keller 			ice_parse_vsi_dev_caps(hw, dev_p, &cap_resp[i]);
2661595b13e2SJacob Keller 			break;
26629733cc94SJacob Keller 		case ICE_AQC_CAPS_1588:
26639733cc94SJacob Keller 			ice_parse_1588_dev_caps(hw, dev_p, &cap_resp[i]);
26649733cc94SJacob Keller 			break;
2665595b13e2SJacob Keller 		case  ICE_AQC_CAPS_FD:
2666595b13e2SJacob Keller 			ice_parse_fdir_dev_caps(hw, dev_p, &cap_resp[i]);
2667595b13e2SJacob Keller 			break;
2668595b13e2SJacob Keller 		default:
2669595b13e2SJacob Keller 			/* Don't list common capabilities as unknown */
2670595b13e2SJacob Keller 			if (!found)
26719228d8b2SJacob Keller 				ice_debug(hw, ICE_DBG_INIT, "dev caps: unknown capability[%d]: 0x%x\n",
2672595b13e2SJacob Keller 					  i, cap);
2673595b13e2SJacob Keller 			break;
2674595b13e2SJacob Keller 		}
2675595b13e2SJacob Keller 	}
2676595b13e2SJacob Keller 
2677595b13e2SJacob Keller 	ice_recalc_port_limited_caps(hw, &dev_p->common_cap);
2678595b13e2SJacob Keller }
2679595b13e2SJacob Keller 
2680595b13e2SJacob Keller /**
2681272ad794SKarol Kolacinski  * ice_aq_get_netlist_node
2682272ad794SKarol Kolacinski  * @hw: pointer to the hw struct
2683272ad794SKarol Kolacinski  * @cmd: get_link_topo AQ structure
2684272ad794SKarol Kolacinski  * @node_part_number: output node part number if node found
2685272ad794SKarol Kolacinski  * @node_handle: output node handle parameter if node found
2686272ad794SKarol Kolacinski  */
2687272ad794SKarol Kolacinski static int
ice_aq_get_netlist_node(struct ice_hw * hw,struct ice_aqc_get_link_topo * cmd,u8 * node_part_number,u16 * node_handle)2688272ad794SKarol Kolacinski ice_aq_get_netlist_node(struct ice_hw *hw, struct ice_aqc_get_link_topo *cmd,
2689272ad794SKarol Kolacinski 			u8 *node_part_number, u16 *node_handle)
2690272ad794SKarol Kolacinski {
2691272ad794SKarol Kolacinski 	struct ice_aq_desc desc;
2692272ad794SKarol Kolacinski 
2693272ad794SKarol Kolacinski 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_link_topo);
2694272ad794SKarol Kolacinski 	desc.params.get_link_topo = *cmd;
2695272ad794SKarol Kolacinski 
2696272ad794SKarol Kolacinski 	if (ice_aq_send_cmd(hw, &desc, NULL, 0, NULL))
2697272ad794SKarol Kolacinski 		return -EIO;
2698272ad794SKarol Kolacinski 
2699272ad794SKarol Kolacinski 	if (node_handle)
2700272ad794SKarol Kolacinski 		*node_handle = le16_to_cpu(desc.params.get_link_topo.addr.handle);
2701272ad794SKarol Kolacinski 	if (node_part_number)
2702272ad794SKarol Kolacinski 		*node_part_number = desc.params.get_link_topo.node_part_num;
2703272ad794SKarol Kolacinski 
2704272ad794SKarol Kolacinski 	return 0;
2705272ad794SKarol Kolacinski }
2706272ad794SKarol Kolacinski 
2707272ad794SKarol Kolacinski /**
2708272ad794SKarol Kolacinski  * ice_is_pf_c827 - check if pf contains c827 phy
2709272ad794SKarol Kolacinski  * @hw: pointer to the hw struct
2710272ad794SKarol Kolacinski  */
ice_is_pf_c827(struct ice_hw * hw)2711272ad794SKarol Kolacinski bool ice_is_pf_c827(struct ice_hw *hw)
2712272ad794SKarol Kolacinski {
2713272ad794SKarol Kolacinski 	struct ice_aqc_get_link_topo cmd = {};
2714272ad794SKarol Kolacinski 	u8 node_part_number;
2715272ad794SKarol Kolacinski 	u16 node_handle;
2716272ad794SKarol Kolacinski 	int status;
2717272ad794SKarol Kolacinski 
2718272ad794SKarol Kolacinski 	if (hw->mac_type != ICE_MAC_E810)
2719272ad794SKarol Kolacinski 		return false;
2720272ad794SKarol Kolacinski 
2721272ad794SKarol Kolacinski 	if (hw->device_id != ICE_DEV_ID_E810C_QSFP)
2722272ad794SKarol Kolacinski 		return true;
2723272ad794SKarol Kolacinski 
2724272ad794SKarol Kolacinski 	cmd.addr.topo_params.node_type_ctx =
2725272ad794SKarol Kolacinski 		FIELD_PREP(ICE_AQC_LINK_TOPO_NODE_TYPE_M, ICE_AQC_LINK_TOPO_NODE_TYPE_PHY) |
2726272ad794SKarol Kolacinski 		FIELD_PREP(ICE_AQC_LINK_TOPO_NODE_CTX_M, ICE_AQC_LINK_TOPO_NODE_CTX_PORT);
2727272ad794SKarol Kolacinski 	cmd.addr.topo_params.index = 0;
2728272ad794SKarol Kolacinski 
2729272ad794SKarol Kolacinski 	status = ice_aq_get_netlist_node(hw, &cmd, &node_part_number,
2730272ad794SKarol Kolacinski 					 &node_handle);
2731272ad794SKarol Kolacinski 
2732272ad794SKarol Kolacinski 	if (status || node_part_number != ICE_AQC_GET_LINK_TOPO_NODE_NR_C827)
2733272ad794SKarol Kolacinski 		return false;
2734272ad794SKarol Kolacinski 
2735272ad794SKarol Kolacinski 	if (node_handle == E810C_QSFP_C827_0_HANDLE || node_handle == E810C_QSFP_C827_1_HANDLE)
2736272ad794SKarol Kolacinski 		return true;
2737272ad794SKarol Kolacinski 
2738272ad794SKarol Kolacinski 	return false;
2739272ad794SKarol Kolacinski }
2740272ad794SKarol Kolacinski 
2741272ad794SKarol Kolacinski /**
27428d7aab35SJacob Keller  * ice_aq_list_caps - query function/device capabilities
2743f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
27448d7aab35SJacob Keller  * @buf: a buffer to hold the capabilities
27458d7aab35SJacob Keller  * @buf_size: size of the buffer
27468d7aab35SJacob Keller  * @cap_count: if not NULL, set to the number of capabilities reported
27478d7aab35SJacob Keller  * @opc: capabilities type to discover, device or function
27489c20346bSAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
27499c20346bSAnirudh Venkataramanan  *
27508d7aab35SJacob Keller  * Get the function (0x000A) or device (0x000B) capabilities description from
27518d7aab35SJacob Keller  * firmware and store it in the buffer.
27528d7aab35SJacob Keller  *
27538d7aab35SJacob Keller  * If the cap_count pointer is not NULL, then it is set to the number of
27548d7aab35SJacob Keller  * capabilities firmware will report. Note that if the buffer size is too
27558d7aab35SJacob Keller  * small, it is possible the command will return ICE_AQ_ERR_ENOMEM. The
27568d7aab35SJacob Keller  * cap_count will still be updated in this case. It is recommended that the
27578d7aab35SJacob Keller  * buffer size be set to ICE_AQ_MAX_BUF_LEN (the largest possible buffer that
27588d7aab35SJacob Keller  * firmware could return) to avoid this.
27599c20346bSAnirudh Venkataramanan  */
27605e24d598STony Nguyen int
ice_aq_list_caps(struct ice_hw * hw,void * buf,u16 buf_size,u32 * cap_count,enum ice_adminq_opc opc,struct ice_sq_cd * cd)27618d7aab35SJacob Keller ice_aq_list_caps(struct ice_hw *hw, void *buf, u16 buf_size, u32 *cap_count,
27629c20346bSAnirudh Venkataramanan 		 enum ice_adminq_opc opc, struct ice_sq_cd *cd)
27639c20346bSAnirudh Venkataramanan {
27649c20346bSAnirudh Venkataramanan 	struct ice_aqc_list_caps *cmd;
27659c20346bSAnirudh Venkataramanan 	struct ice_aq_desc desc;
27665e24d598STony Nguyen 	int status;
27679c20346bSAnirudh Venkataramanan 
27689c20346bSAnirudh Venkataramanan 	cmd = &desc.params.get_cap;
27699c20346bSAnirudh Venkataramanan 
27709c20346bSAnirudh Venkataramanan 	if (opc != ice_aqc_opc_list_func_caps &&
27719c20346bSAnirudh Venkataramanan 	    opc != ice_aqc_opc_list_dev_caps)
2772d54699e2STony Nguyen 		return -EINVAL;
27739c20346bSAnirudh Venkataramanan 
27749c20346bSAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, opc);
27759c20346bSAnirudh Venkataramanan 	status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
27768d7aab35SJacob Keller 
27778d7aab35SJacob Keller 	if (cap_count)
277899189e8bSAnirudh Venkataramanan 		*cap_count = le32_to_cpu(cmd->count);
27798d7aab35SJacob Keller 
27808d7aab35SJacob Keller 	return status;
27818d7aab35SJacob Keller }
27828d7aab35SJacob Keller 
27838d7aab35SJacob Keller /**
278481aed647SJacob Keller  * ice_discover_dev_caps - Read and extract device capabilities
27857d86cf38SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
278681aed647SJacob Keller  * @dev_caps: pointer to device capabilities structure
278781aed647SJacob Keller  *
278881aed647SJacob Keller  * Read the device capabilities and extract them into the dev_caps structure
278981aed647SJacob Keller  * for later use.
27907d86cf38SAnirudh Venkataramanan  */
27915e24d598STony Nguyen int
ice_discover_dev_caps(struct ice_hw * hw,struct ice_hw_dev_caps * dev_caps)279281aed647SJacob Keller ice_discover_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_caps)
27937d86cf38SAnirudh Venkataramanan {
279481aed647SJacob Keller 	u32 cap_count = 0;
27957d86cf38SAnirudh Venkataramanan 	void *cbuf;
27965518ac2aSTony Nguyen 	int status;
27977d86cf38SAnirudh Venkataramanan 
27981082b360SJacob Keller 	cbuf = kzalloc(ICE_AQ_MAX_BUF_LEN, GFP_KERNEL);
27997d86cf38SAnirudh Venkataramanan 	if (!cbuf)
2800d54699e2STony Nguyen 		return -ENOMEM;
28017d86cf38SAnirudh Venkataramanan 
28021082b360SJacob Keller 	/* Although the driver doesn't know the number of capabilities the
28031082b360SJacob Keller 	 * device will return, we can simply send a 4KB buffer, the maximum
28041082b360SJacob Keller 	 * possible size that firmware can return.
28051082b360SJacob Keller 	 */
28061082b360SJacob Keller 	cap_count = ICE_AQ_MAX_BUF_LEN / sizeof(struct ice_aqc_list_caps_elem);
28071082b360SJacob Keller 
280881aed647SJacob Keller 	status = ice_aq_list_caps(hw, cbuf, ICE_AQ_MAX_BUF_LEN, &cap_count,
280981aed647SJacob Keller 				  ice_aqc_opc_list_dev_caps, NULL);
281081aed647SJacob Keller 	if (!status)
281181aed647SJacob Keller 		ice_parse_dev_caps(hw, dev_caps, cbuf, cap_count);
281281aed647SJacob Keller 	kfree(cbuf);
281381aed647SJacob Keller 
281481aed647SJacob Keller 	return status;
281581aed647SJacob Keller }
281681aed647SJacob Keller 
281781aed647SJacob Keller /**
281881aed647SJacob Keller  * ice_discover_func_caps - Read and extract function capabilities
281981aed647SJacob Keller  * @hw: pointer to the hardware structure
282081aed647SJacob Keller  * @func_caps: pointer to function capabilities structure
282181aed647SJacob Keller  *
282281aed647SJacob Keller  * Read the function capabilities and extract them into the func_caps structure
282381aed647SJacob Keller  * for later use.
282481aed647SJacob Keller  */
28255e24d598STony Nguyen static int
ice_discover_func_caps(struct ice_hw * hw,struct ice_hw_func_caps * func_caps)282681aed647SJacob Keller ice_discover_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_caps)
282781aed647SJacob Keller {
282881aed647SJacob Keller 	u32 cap_count = 0;
282981aed647SJacob Keller 	void *cbuf;
28305518ac2aSTony Nguyen 	int status;
283181aed647SJacob Keller 
283281aed647SJacob Keller 	cbuf = kzalloc(ICE_AQ_MAX_BUF_LEN, GFP_KERNEL);
283381aed647SJacob Keller 	if (!cbuf)
2834d54699e2STony Nguyen 		return -ENOMEM;
283581aed647SJacob Keller 
283681aed647SJacob Keller 	/* Although the driver doesn't know the number of capabilities the
283781aed647SJacob Keller 	 * device will return, we can simply send a 4KB buffer, the maximum
283881aed647SJacob Keller 	 * possible size that firmware can return.
283981aed647SJacob Keller 	 */
284081aed647SJacob Keller 	cap_count = ICE_AQ_MAX_BUF_LEN / sizeof(struct ice_aqc_list_caps_elem);
284181aed647SJacob Keller 
284281aed647SJacob Keller 	status = ice_aq_list_caps(hw, cbuf, ICE_AQ_MAX_BUF_LEN, &cap_count,
284381aed647SJacob Keller 				  ice_aqc_opc_list_func_caps, NULL);
284481aed647SJacob Keller 	if (!status)
284581aed647SJacob Keller 		ice_parse_func_caps(hw, func_caps, cbuf, cap_count);
28461082b360SJacob Keller 	kfree(cbuf);
28479c20346bSAnirudh Venkataramanan 
28489c20346bSAnirudh Venkataramanan 	return status;
28499c20346bSAnirudh Venkataramanan }
28509c20346bSAnirudh Venkataramanan 
28519c20346bSAnirudh Venkataramanan /**
2852462acf6aSTony Nguyen  * ice_set_safe_mode_caps - Override dev/func capabilities when in safe mode
2853462acf6aSTony Nguyen  * @hw: pointer to the hardware structure
2854462acf6aSTony Nguyen  */
ice_set_safe_mode_caps(struct ice_hw * hw)2855462acf6aSTony Nguyen void ice_set_safe_mode_caps(struct ice_hw *hw)
2856462acf6aSTony Nguyen {
2857462acf6aSTony Nguyen 	struct ice_hw_func_caps *func_caps = &hw->func_caps;
2858462acf6aSTony Nguyen 	struct ice_hw_dev_caps *dev_caps = &hw->dev_caps;
2859be49b1adSJacob Keller 	struct ice_hw_common_caps cached_caps;
2860eae1bbb2SBruce Allan 	u32 num_funcs;
2861462acf6aSTony Nguyen 
2862462acf6aSTony Nguyen 	/* cache some func_caps values that should be restored after memset */
2863be49b1adSJacob Keller 	cached_caps = func_caps->common_cap;
2864462acf6aSTony Nguyen 
2865462acf6aSTony Nguyen 	/* unset func capabilities */
2866462acf6aSTony Nguyen 	memset(func_caps, 0, sizeof(*func_caps));
2867462acf6aSTony Nguyen 
2868be49b1adSJacob Keller #define ICE_RESTORE_FUNC_CAP(name) \
2869be49b1adSJacob Keller 	func_caps->common_cap.name = cached_caps.name
2870be49b1adSJacob Keller 
2871462acf6aSTony Nguyen 	/* restore cached values */
2872be49b1adSJacob Keller 	ICE_RESTORE_FUNC_CAP(valid_functions);
2873be49b1adSJacob Keller 	ICE_RESTORE_FUNC_CAP(txq_first_id);
2874be49b1adSJacob Keller 	ICE_RESTORE_FUNC_CAP(rxq_first_id);
2875be49b1adSJacob Keller 	ICE_RESTORE_FUNC_CAP(msix_vector_first_id);
2876be49b1adSJacob Keller 	ICE_RESTORE_FUNC_CAP(max_mtu);
2877be49b1adSJacob Keller 	ICE_RESTORE_FUNC_CAP(nvm_unified_update);
2878be49b1adSJacob Keller 	ICE_RESTORE_FUNC_CAP(nvm_update_pending_nvm);
2879be49b1adSJacob Keller 	ICE_RESTORE_FUNC_CAP(nvm_update_pending_orom);
2880be49b1adSJacob Keller 	ICE_RESTORE_FUNC_CAP(nvm_update_pending_netlist);
2881462acf6aSTony Nguyen 
2882462acf6aSTony Nguyen 	/* one Tx and one Rx queue in safe mode */
2883462acf6aSTony Nguyen 	func_caps->common_cap.num_rxq = 1;
2884462acf6aSTony Nguyen 	func_caps->common_cap.num_txq = 1;
2885462acf6aSTony Nguyen 
2886462acf6aSTony Nguyen 	/* two MSIX vectors, one for traffic and one for misc causes */
2887462acf6aSTony Nguyen 	func_caps->common_cap.num_msix_vectors = 2;
2888462acf6aSTony Nguyen 	func_caps->guar_num_vsi = 1;
2889462acf6aSTony Nguyen 
2890462acf6aSTony Nguyen 	/* cache some dev_caps values that should be restored after memset */
2891be49b1adSJacob Keller 	cached_caps = dev_caps->common_cap;
2892eae1bbb2SBruce Allan 	num_funcs = dev_caps->num_funcs;
2893462acf6aSTony Nguyen 
2894462acf6aSTony Nguyen 	/* unset dev capabilities */
2895462acf6aSTony Nguyen 	memset(dev_caps, 0, sizeof(*dev_caps));
2896462acf6aSTony Nguyen 
2897be49b1adSJacob Keller #define ICE_RESTORE_DEV_CAP(name) \
2898be49b1adSJacob Keller 	dev_caps->common_cap.name = cached_caps.name
2899be49b1adSJacob Keller 
2900462acf6aSTony Nguyen 	/* restore cached values */
2901be49b1adSJacob Keller 	ICE_RESTORE_DEV_CAP(valid_functions);
2902be49b1adSJacob Keller 	ICE_RESTORE_DEV_CAP(txq_first_id);
2903be49b1adSJacob Keller 	ICE_RESTORE_DEV_CAP(rxq_first_id);
2904be49b1adSJacob Keller 	ICE_RESTORE_DEV_CAP(msix_vector_first_id);
2905be49b1adSJacob Keller 	ICE_RESTORE_DEV_CAP(max_mtu);
2906be49b1adSJacob Keller 	ICE_RESTORE_DEV_CAP(nvm_unified_update);
2907be49b1adSJacob Keller 	ICE_RESTORE_DEV_CAP(nvm_update_pending_nvm);
2908be49b1adSJacob Keller 	ICE_RESTORE_DEV_CAP(nvm_update_pending_orom);
2909be49b1adSJacob Keller 	ICE_RESTORE_DEV_CAP(nvm_update_pending_netlist);
2910eae1bbb2SBruce Allan 	dev_caps->num_funcs = num_funcs;
2911462acf6aSTony Nguyen 
2912462acf6aSTony Nguyen 	/* one Tx and one Rx queue per function in safe mode */
2913eae1bbb2SBruce Allan 	dev_caps->common_cap.num_rxq = num_funcs;
2914eae1bbb2SBruce Allan 	dev_caps->common_cap.num_txq = num_funcs;
2915462acf6aSTony Nguyen 
2916462acf6aSTony Nguyen 	/* two MSIX vectors per function */
2917eae1bbb2SBruce Allan 	dev_caps->common_cap.num_msix_vectors = 2 * num_funcs;
2918462acf6aSTony Nguyen }
2919462acf6aSTony Nguyen 
2920462acf6aSTony Nguyen /**
29219c20346bSAnirudh Venkataramanan  * ice_get_caps - get info about the HW
29229c20346bSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
29239c20346bSAnirudh Venkataramanan  */
ice_get_caps(struct ice_hw * hw)29245e24d598STony Nguyen int ice_get_caps(struct ice_hw *hw)
29259c20346bSAnirudh Venkataramanan {
29265e24d598STony Nguyen 	int status;
29279c20346bSAnirudh Venkataramanan 
292881aed647SJacob Keller 	status = ice_discover_dev_caps(hw, &hw->dev_caps);
292981aed647SJacob Keller 	if (status)
29309c20346bSAnirudh Venkataramanan 		return status;
293181aed647SJacob Keller 
293281aed647SJacob Keller 	return ice_discover_func_caps(hw, &hw->func_caps);
29339c20346bSAnirudh Venkataramanan }
29349c20346bSAnirudh Venkataramanan 
29359c20346bSAnirudh Venkataramanan /**
2936e94d4478SAnirudh Venkataramanan  * ice_aq_manage_mac_write - manage MAC address write command
2937f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
2938e94d4478SAnirudh Venkataramanan  * @mac_addr: MAC address to be written as LAA/LAA+WoL/Port address
2939e94d4478SAnirudh Venkataramanan  * @flags: flags to control write behavior
2940e94d4478SAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
2941e94d4478SAnirudh Venkataramanan  *
2942e94d4478SAnirudh Venkataramanan  * This function is used to write MAC address to the NVM (0x0108).
2943e94d4478SAnirudh Venkataramanan  */
29445e24d598STony Nguyen int
ice_aq_manage_mac_write(struct ice_hw * hw,const u8 * mac_addr,u8 flags,struct ice_sq_cd * cd)2945d671e3e0SJacob Keller ice_aq_manage_mac_write(struct ice_hw *hw, const u8 *mac_addr, u8 flags,
2946e94d4478SAnirudh Venkataramanan 			struct ice_sq_cd *cd)
2947e94d4478SAnirudh Venkataramanan {
2948e94d4478SAnirudh Venkataramanan 	struct ice_aqc_manage_mac_write *cmd;
2949e94d4478SAnirudh Venkataramanan 	struct ice_aq_desc desc;
2950e94d4478SAnirudh Venkataramanan 
2951e94d4478SAnirudh Venkataramanan 	cmd = &desc.params.mac_write;
2952e94d4478SAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_manage_mac_write);
2953e94d4478SAnirudh Venkataramanan 
2954e94d4478SAnirudh Venkataramanan 	cmd->flags = flags;
29555df42c82SJesse Brandeburg 	ether_addr_copy(cmd->mac_addr, mac_addr);
2956e94d4478SAnirudh Venkataramanan 
2957e94d4478SAnirudh Venkataramanan 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
2958e94d4478SAnirudh Venkataramanan }
2959e94d4478SAnirudh Venkataramanan 
2960e94d4478SAnirudh Venkataramanan /**
2961f31e4b6fSAnirudh Venkataramanan  * ice_aq_clear_pxe_mode
2962f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
2963f31e4b6fSAnirudh Venkataramanan  *
2964f31e4b6fSAnirudh Venkataramanan  * Tell the firmware that the driver is taking over from PXE (0x0110).
2965f31e4b6fSAnirudh Venkataramanan  */
ice_aq_clear_pxe_mode(struct ice_hw * hw)29665e24d598STony Nguyen static int ice_aq_clear_pxe_mode(struct ice_hw *hw)
2967f31e4b6fSAnirudh Venkataramanan {
2968f31e4b6fSAnirudh Venkataramanan 	struct ice_aq_desc desc;
2969f31e4b6fSAnirudh Venkataramanan 
2970f31e4b6fSAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_clear_pxe_mode);
2971f31e4b6fSAnirudh Venkataramanan 	desc.params.clear_pxe.rx_cnt = ICE_AQC_CLEAR_PXE_RX_CNT;
2972f31e4b6fSAnirudh Venkataramanan 
2973f31e4b6fSAnirudh Venkataramanan 	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
2974f31e4b6fSAnirudh Venkataramanan }
2975f31e4b6fSAnirudh Venkataramanan 
2976f31e4b6fSAnirudh Venkataramanan /**
2977f31e4b6fSAnirudh Venkataramanan  * ice_clear_pxe_mode - clear pxe operations mode
2978f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
2979f31e4b6fSAnirudh Venkataramanan  *
2980f31e4b6fSAnirudh Venkataramanan  * Make sure all PXE mode settings are cleared, including things
2981f31e4b6fSAnirudh Venkataramanan  * like descriptor fetch/write-back mode.
2982f31e4b6fSAnirudh Venkataramanan  */
ice_clear_pxe_mode(struct ice_hw * hw)2983f31e4b6fSAnirudh Venkataramanan void ice_clear_pxe_mode(struct ice_hw *hw)
2984f31e4b6fSAnirudh Venkataramanan {
2985f31e4b6fSAnirudh Venkataramanan 	if (ice_check_sq_alive(hw, &hw->adminq))
2986f31e4b6fSAnirudh Venkataramanan 		ice_aq_clear_pxe_mode(hw);
2987f31e4b6fSAnirudh Venkataramanan }
2988cdedef59SAnirudh Venkataramanan 
2989cdedef59SAnirudh Venkataramanan /**
2990a1ffafb0SBrett Creeley  * ice_aq_set_port_params - set physical port parameters.
2991a1ffafb0SBrett Creeley  * @pi: pointer to the port info struct
2992a1ffafb0SBrett Creeley  * @double_vlan: if set double VLAN is enabled
2993a1ffafb0SBrett Creeley  * @cd: pointer to command details structure or NULL
2994a1ffafb0SBrett Creeley  *
2995a1ffafb0SBrett Creeley  * Set Physical port parameters (0x0203)
2996a1ffafb0SBrett Creeley  */
2997a1ffafb0SBrett Creeley int
ice_aq_set_port_params(struct ice_port_info * pi,bool double_vlan,struct ice_sq_cd * cd)2998a1ffafb0SBrett Creeley ice_aq_set_port_params(struct ice_port_info *pi, bool double_vlan,
2999a1ffafb0SBrett Creeley 		       struct ice_sq_cd *cd)
3000a1ffafb0SBrett Creeley 
3001a1ffafb0SBrett Creeley {
3002a1ffafb0SBrett Creeley 	struct ice_aqc_set_port_params *cmd;
3003a1ffafb0SBrett Creeley 	struct ice_hw *hw = pi->hw;
3004a1ffafb0SBrett Creeley 	struct ice_aq_desc desc;
3005a1ffafb0SBrett Creeley 	u16 cmd_flags = 0;
3006a1ffafb0SBrett Creeley 
3007a1ffafb0SBrett Creeley 	cmd = &desc.params.set_port_params;
3008a1ffafb0SBrett Creeley 
3009a1ffafb0SBrett Creeley 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_port_params);
3010a1ffafb0SBrett Creeley 	if (double_vlan)
3011a1ffafb0SBrett Creeley 		cmd_flags |= ICE_AQC_SET_P_PARAMS_DOUBLE_VLAN_ENA;
3012a1ffafb0SBrett Creeley 	cmd->cmd_flags = cpu_to_le16(cmd_flags);
3013a1ffafb0SBrett Creeley 
3014a1ffafb0SBrett Creeley 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
3015a1ffafb0SBrett Creeley }
3016a1ffafb0SBrett Creeley 
3017a1ffafb0SBrett Creeley /**
301839ed02a4SAnirudh Venkataramanan  * ice_is_100m_speed_supported
301939ed02a4SAnirudh Venkataramanan  * @hw: pointer to the HW struct
302039ed02a4SAnirudh Venkataramanan  *
302139ed02a4SAnirudh Venkataramanan  * returns true if 100M speeds are supported by the device,
302239ed02a4SAnirudh Venkataramanan  * false otherwise.
302339ed02a4SAnirudh Venkataramanan  */
ice_is_100m_speed_supported(struct ice_hw * hw)302439ed02a4SAnirudh Venkataramanan bool ice_is_100m_speed_supported(struct ice_hw *hw)
302539ed02a4SAnirudh Venkataramanan {
302639ed02a4SAnirudh Venkataramanan 	switch (hw->device_id) {
302739ed02a4SAnirudh Venkataramanan 	case ICE_DEV_ID_E822C_SGMII:
302839ed02a4SAnirudh Venkataramanan 	case ICE_DEV_ID_E822L_SGMII:
302939ed02a4SAnirudh Venkataramanan 	case ICE_DEV_ID_E823L_1GBE:
303039ed02a4SAnirudh Venkataramanan 	case ICE_DEV_ID_E823C_SGMII:
303139ed02a4SAnirudh Venkataramanan 		return true;
303239ed02a4SAnirudh Venkataramanan 	default:
303339ed02a4SAnirudh Venkataramanan 		return false;
303439ed02a4SAnirudh Venkataramanan 	}
303539ed02a4SAnirudh Venkataramanan }
303639ed02a4SAnirudh Venkataramanan 
303739ed02a4SAnirudh Venkataramanan /**
303848cb27f2SChinh Cao  * ice_get_link_speed_based_on_phy_type - returns link speed
303948cb27f2SChinh Cao  * @phy_type_low: lower part of phy_type
3040aef74145SAnirudh Venkataramanan  * @phy_type_high: higher part of phy_type
304148cb27f2SChinh Cao  *
3042f9867df6SAnirudh Venkataramanan  * This helper function will convert an entry in PHY type structure
3043aef74145SAnirudh Venkataramanan  * [phy_type_low, phy_type_high] to its corresponding link speed.
3044aef74145SAnirudh Venkataramanan  * Note: In the structure of [phy_type_low, phy_type_high], there should
3045f9867df6SAnirudh Venkataramanan  * be one bit set, as this function will convert one PHY type to its
304648cb27f2SChinh Cao  * speed.
30471d0e28a9SBrett Creeley  * If no bit gets set, ICE_AQ_LINK_SPEED_UNKNOWN will be returned
30481d0e28a9SBrett Creeley  * If more than one bit gets set, ICE_AQ_LINK_SPEED_UNKNOWN will be returned
304948cb27f2SChinh Cao  */
3050aef74145SAnirudh Venkataramanan static u16
ice_get_link_speed_based_on_phy_type(u64 phy_type_low,u64 phy_type_high)3051aef74145SAnirudh Venkataramanan ice_get_link_speed_based_on_phy_type(u64 phy_type_low, u64 phy_type_high)
305248cb27f2SChinh Cao {
3053aef74145SAnirudh Venkataramanan 	u16 speed_phy_type_high = ICE_AQ_LINK_SPEED_UNKNOWN;
305448cb27f2SChinh Cao 	u16 speed_phy_type_low = ICE_AQ_LINK_SPEED_UNKNOWN;
305548cb27f2SChinh Cao 
305648cb27f2SChinh Cao 	switch (phy_type_low) {
305748cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_100BASE_TX:
305848cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_100M_SGMII:
305948cb27f2SChinh Cao 		speed_phy_type_low = ICE_AQ_LINK_SPEED_100MB;
306048cb27f2SChinh Cao 		break;
306148cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_1000BASE_T:
306248cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_1000BASE_SX:
306348cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_1000BASE_LX:
306448cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_1000BASE_KX:
306548cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_1G_SGMII:
306648cb27f2SChinh Cao 		speed_phy_type_low = ICE_AQ_LINK_SPEED_1000MB;
306748cb27f2SChinh Cao 		break;
306848cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_2500BASE_T:
306948cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_2500BASE_X:
307048cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_2500BASE_KX:
307148cb27f2SChinh Cao 		speed_phy_type_low = ICE_AQ_LINK_SPEED_2500MB;
307248cb27f2SChinh Cao 		break;
307348cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_5GBASE_T:
307448cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_5GBASE_KR:
307548cb27f2SChinh Cao 		speed_phy_type_low = ICE_AQ_LINK_SPEED_5GB;
307648cb27f2SChinh Cao 		break;
307748cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_10GBASE_T:
307848cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_10G_SFI_DA:
307948cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_10GBASE_SR:
308048cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_10GBASE_LR:
308148cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_10GBASE_KR_CR1:
308248cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_10G_SFI_AOC_ACC:
308348cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_10G_SFI_C2C:
308448cb27f2SChinh Cao 		speed_phy_type_low = ICE_AQ_LINK_SPEED_10GB;
308548cb27f2SChinh Cao 		break;
308648cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_25GBASE_T:
308748cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_25GBASE_CR:
308848cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_25GBASE_CR_S:
308948cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_25GBASE_CR1:
309048cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_25GBASE_SR:
309148cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_25GBASE_LR:
309248cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_25GBASE_KR:
309348cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_25GBASE_KR_S:
309448cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_25GBASE_KR1:
309548cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_25G_AUI_AOC_ACC:
309648cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_25G_AUI_C2C:
309748cb27f2SChinh Cao 		speed_phy_type_low = ICE_AQ_LINK_SPEED_25GB;
309848cb27f2SChinh Cao 		break;
309948cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_40GBASE_CR4:
310048cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_40GBASE_SR4:
310148cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_40GBASE_LR4:
310248cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_40GBASE_KR4:
310348cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_40G_XLAUI_AOC_ACC:
310448cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_40G_XLAUI:
310548cb27f2SChinh Cao 		speed_phy_type_low = ICE_AQ_LINK_SPEED_40GB;
310648cb27f2SChinh Cao 		break;
3107aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_50GBASE_CR2:
3108aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_50GBASE_SR2:
3109aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_50GBASE_LR2:
3110aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_50GBASE_KR2:
3111aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_50G_LAUI2_AOC_ACC:
3112aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_50G_LAUI2:
3113aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_50G_AUI2_AOC_ACC:
3114aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_50G_AUI2:
3115aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_50GBASE_CP:
3116aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_50GBASE_SR:
3117aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_50GBASE_FR:
3118aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_50GBASE_LR:
3119aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4:
3120aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_50G_AUI1_AOC_ACC:
3121aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_50G_AUI1:
3122aef74145SAnirudh Venkataramanan 		speed_phy_type_low = ICE_AQ_LINK_SPEED_50GB;
3123aef74145SAnirudh Venkataramanan 		break;
3124aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_100GBASE_CR4:
3125aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_100GBASE_SR4:
3126aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_100GBASE_LR4:
3127aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_100GBASE_KR4:
3128aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_100G_CAUI4_AOC_ACC:
3129aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_100G_CAUI4:
3130aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_100G_AUI4_AOC_ACC:
3131aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_100G_AUI4:
3132aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_100GBASE_CR_PAM4:
3133aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4:
3134aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_100GBASE_CP2:
3135aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_100GBASE_SR2:
3136aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_100GBASE_DR:
3137aef74145SAnirudh Venkataramanan 		speed_phy_type_low = ICE_AQ_LINK_SPEED_100GB;
3138aef74145SAnirudh Venkataramanan 		break;
313948cb27f2SChinh Cao 	default:
314048cb27f2SChinh Cao 		speed_phy_type_low = ICE_AQ_LINK_SPEED_UNKNOWN;
314148cb27f2SChinh Cao 		break;
314248cb27f2SChinh Cao 	}
314348cb27f2SChinh Cao 
3144aef74145SAnirudh Venkataramanan 	switch (phy_type_high) {
3145aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_HIGH_100GBASE_KR2_PAM4:
3146aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_HIGH_100G_CAUI2_AOC_ACC:
3147aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_HIGH_100G_CAUI2:
3148aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_HIGH_100G_AUI2_AOC_ACC:
3149aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_HIGH_100G_AUI2:
3150aef74145SAnirudh Venkataramanan 		speed_phy_type_high = ICE_AQ_LINK_SPEED_100GB;
3151aef74145SAnirudh Venkataramanan 		break;
3152aef74145SAnirudh Venkataramanan 	default:
3153aef74145SAnirudh Venkataramanan 		speed_phy_type_high = ICE_AQ_LINK_SPEED_UNKNOWN;
3154aef74145SAnirudh Venkataramanan 		break;
3155aef74145SAnirudh Venkataramanan 	}
3156aef74145SAnirudh Venkataramanan 
3157aef74145SAnirudh Venkataramanan 	if (speed_phy_type_low == ICE_AQ_LINK_SPEED_UNKNOWN &&
3158aef74145SAnirudh Venkataramanan 	    speed_phy_type_high == ICE_AQ_LINK_SPEED_UNKNOWN)
3159aef74145SAnirudh Venkataramanan 		return ICE_AQ_LINK_SPEED_UNKNOWN;
3160aef74145SAnirudh Venkataramanan 	else if (speed_phy_type_low != ICE_AQ_LINK_SPEED_UNKNOWN &&
3161aef74145SAnirudh Venkataramanan 		 speed_phy_type_high != ICE_AQ_LINK_SPEED_UNKNOWN)
3162aef74145SAnirudh Venkataramanan 		return ICE_AQ_LINK_SPEED_UNKNOWN;
3163aef74145SAnirudh Venkataramanan 	else if (speed_phy_type_low != ICE_AQ_LINK_SPEED_UNKNOWN &&
3164aef74145SAnirudh Venkataramanan 		 speed_phy_type_high == ICE_AQ_LINK_SPEED_UNKNOWN)
316548cb27f2SChinh Cao 		return speed_phy_type_low;
3166aef74145SAnirudh Venkataramanan 	else
3167aef74145SAnirudh Venkataramanan 		return speed_phy_type_high;
316848cb27f2SChinh Cao }
316948cb27f2SChinh Cao 
317048cb27f2SChinh Cao /**
317148cb27f2SChinh Cao  * ice_update_phy_type
317248cb27f2SChinh Cao  * @phy_type_low: pointer to the lower part of phy_type
3173aef74145SAnirudh Venkataramanan  * @phy_type_high: pointer to the higher part of phy_type
317448cb27f2SChinh Cao  * @link_speeds_bitmap: targeted link speeds bitmap
317548cb27f2SChinh Cao  *
317648cb27f2SChinh Cao  * Note: For the link_speeds_bitmap structure, you can check it at
317748cb27f2SChinh Cao  * [ice_aqc_get_link_status->link_speed]. Caller can pass in
317848cb27f2SChinh Cao  * link_speeds_bitmap include multiple speeds.
317948cb27f2SChinh Cao  *
3180aef74145SAnirudh Venkataramanan  * Each entry in this [phy_type_low, phy_type_high] structure will
3181aef74145SAnirudh Venkataramanan  * present a certain link speed. This helper function will turn on bits
3182aef74145SAnirudh Venkataramanan  * in [phy_type_low, phy_type_high] structure based on the value of
318348cb27f2SChinh Cao  * link_speeds_bitmap input parameter.
318448cb27f2SChinh Cao  */
3185aef74145SAnirudh Venkataramanan void
ice_update_phy_type(u64 * phy_type_low,u64 * phy_type_high,u16 link_speeds_bitmap)3186aef74145SAnirudh Venkataramanan ice_update_phy_type(u64 *phy_type_low, u64 *phy_type_high,
3187aef74145SAnirudh Venkataramanan 		    u16 link_speeds_bitmap)
318848cb27f2SChinh Cao {
3189aef74145SAnirudh Venkataramanan 	u64 pt_high;
319048cb27f2SChinh Cao 	u64 pt_low;
319148cb27f2SChinh Cao 	int index;
3192207e3721SBruce Allan 	u16 speed;
319348cb27f2SChinh Cao 
319448cb27f2SChinh Cao 	/* We first check with low part of phy_type */
319548cb27f2SChinh Cao 	for (index = 0; index <= ICE_PHY_TYPE_LOW_MAX_INDEX; index++) {
319648cb27f2SChinh Cao 		pt_low = BIT_ULL(index);
3197aef74145SAnirudh Venkataramanan 		speed = ice_get_link_speed_based_on_phy_type(pt_low, 0);
319848cb27f2SChinh Cao 
319948cb27f2SChinh Cao 		if (link_speeds_bitmap & speed)
320048cb27f2SChinh Cao 			*phy_type_low |= BIT_ULL(index);
320148cb27f2SChinh Cao 	}
3202aef74145SAnirudh Venkataramanan 
3203aef74145SAnirudh Venkataramanan 	/* We then check with high part of phy_type */
3204aef74145SAnirudh Venkataramanan 	for (index = 0; index <= ICE_PHY_TYPE_HIGH_MAX_INDEX; index++) {
3205aef74145SAnirudh Venkataramanan 		pt_high = BIT_ULL(index);
3206aef74145SAnirudh Venkataramanan 		speed = ice_get_link_speed_based_on_phy_type(0, pt_high);
3207aef74145SAnirudh Venkataramanan 
3208aef74145SAnirudh Venkataramanan 		if (link_speeds_bitmap & speed)
3209aef74145SAnirudh Venkataramanan 			*phy_type_high |= BIT_ULL(index);
3210aef74145SAnirudh Venkataramanan 	}
321148cb27f2SChinh Cao }
321248cb27f2SChinh Cao 
321348cb27f2SChinh Cao /**
3214fcea6f3dSAnirudh Venkataramanan  * ice_aq_set_phy_cfg
3215f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
32161a3571b5SPaul Greenwalt  * @pi: port info structure of the interested logical port
3217fcea6f3dSAnirudh Venkataramanan  * @cfg: structure with PHY configuration data to be set
3218fcea6f3dSAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
3219fcea6f3dSAnirudh Venkataramanan  *
3220fcea6f3dSAnirudh Venkataramanan  * Set the various PHY configuration parameters supported on the Port.
3221fcea6f3dSAnirudh Venkataramanan  * One or more of the Set PHY config parameters may be ignored in an MFP
3222fcea6f3dSAnirudh Venkataramanan  * mode as the PF may not have the privilege to set some of the PHY Config
3223fcea6f3dSAnirudh Venkataramanan  * parameters. This status will be indicated by the command response (0x0601).
3224fcea6f3dSAnirudh Venkataramanan  */
32255e24d598STony Nguyen int
ice_aq_set_phy_cfg(struct ice_hw * hw,struct ice_port_info * pi,struct ice_aqc_set_phy_cfg_data * cfg,struct ice_sq_cd * cd)32261a3571b5SPaul Greenwalt ice_aq_set_phy_cfg(struct ice_hw *hw, struct ice_port_info *pi,
3227fcea6f3dSAnirudh Venkataramanan 		   struct ice_aqc_set_phy_cfg_data *cfg, struct ice_sq_cd *cd)
3228fcea6f3dSAnirudh Venkataramanan {
3229fcea6f3dSAnirudh Venkataramanan 	struct ice_aq_desc desc;
32305e24d598STony Nguyen 	int status;
3231fcea6f3dSAnirudh Venkataramanan 
3232fcea6f3dSAnirudh Venkataramanan 	if (!cfg)
3233d54699e2STony Nguyen 		return -EINVAL;
3234fcea6f3dSAnirudh Venkataramanan 
3235d8df260aSChinh T Cao 	/* Ensure that only valid bits of cfg->caps can be turned on. */
3236d8df260aSChinh T Cao 	if (cfg->caps & ~ICE_AQ_PHY_ENA_VALID_MASK) {
32379228d8b2SJacob Keller 		ice_debug(hw, ICE_DBG_PHY, "Invalid bit is set in ice_aqc_set_phy_cfg_data->caps : 0x%x\n",
3238d8df260aSChinh T Cao 			  cfg->caps);
3239d8df260aSChinh T Cao 
3240d8df260aSChinh T Cao 		cfg->caps &= ICE_AQ_PHY_ENA_VALID_MASK;
3241d8df260aSChinh T Cao 	}
3242d8df260aSChinh T Cao 
3243fcea6f3dSAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_phy_cfg);
32441a3571b5SPaul Greenwalt 	desc.params.set_phy.lport_num = pi->lport;
324548cb27f2SChinh Cao 	desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
3246fcea6f3dSAnirudh Venkataramanan 
324755df52a0SPaul Greenwalt 	ice_debug(hw, ICE_DBG_LINK, "set phy cfg\n");
3248dc67039bSJesse Brandeburg 	ice_debug(hw, ICE_DBG_LINK, "	phy_type_low = 0x%llx\n",
3249dc67039bSJesse Brandeburg 		  (unsigned long long)le64_to_cpu(cfg->phy_type_low));
3250dc67039bSJesse Brandeburg 	ice_debug(hw, ICE_DBG_LINK, "	phy_type_high = 0x%llx\n",
3251dc67039bSJesse Brandeburg 		  (unsigned long long)le64_to_cpu(cfg->phy_type_high));
3252dc67039bSJesse Brandeburg 	ice_debug(hw, ICE_DBG_LINK, "	caps = 0x%x\n", cfg->caps);
3253bdeff971SLev Faerman 	ice_debug(hw, ICE_DBG_LINK, "	low_power_ctrl_an = 0x%x\n",
3254bdeff971SLev Faerman 		  cfg->low_power_ctrl_an);
3255dc67039bSJesse Brandeburg 	ice_debug(hw, ICE_DBG_LINK, "	eee_cap = 0x%x\n", cfg->eee_cap);
3256dc67039bSJesse Brandeburg 	ice_debug(hw, ICE_DBG_LINK, "	eeer_value = 0x%x\n", cfg->eeer_value);
325755df52a0SPaul Greenwalt 	ice_debug(hw, ICE_DBG_LINK, "	link_fec_opt = 0x%x\n",
325855df52a0SPaul Greenwalt 		  cfg->link_fec_opt);
3259dc67039bSJesse Brandeburg 
3260b5e19a64SChinh T Cao 	status = ice_aq_send_cmd(hw, &desc, cfg, sizeof(*cfg), cd);
3261b5e19a64SChinh T Cao 	if (hw->adminq.sq_last_status == ICE_AQ_RC_EMODE)
3262b5e19a64SChinh T Cao 		status = 0;
3263b5e19a64SChinh T Cao 
32641a3571b5SPaul Greenwalt 	if (!status)
32651a3571b5SPaul Greenwalt 		pi->phy.curr_user_phy_cfg = *cfg;
32661a3571b5SPaul Greenwalt 
3267b5e19a64SChinh T Cao 	return status;
3268fcea6f3dSAnirudh Venkataramanan }
3269fcea6f3dSAnirudh Venkataramanan 
3270fcea6f3dSAnirudh Venkataramanan /**
3271fcea6f3dSAnirudh Venkataramanan  * ice_update_link_info - update status of the HW network link
3272fcea6f3dSAnirudh Venkataramanan  * @pi: port info structure of the interested logical port
3273fcea6f3dSAnirudh Venkataramanan  */
ice_update_link_info(struct ice_port_info * pi)32745e24d598STony Nguyen int ice_update_link_info(struct ice_port_info *pi)
3275fcea6f3dSAnirudh Venkataramanan {
3276092a33d4SBruce Allan 	struct ice_link_status *li;
32775e24d598STony Nguyen 	int status;
3278fcea6f3dSAnirudh Venkataramanan 
3279fcea6f3dSAnirudh Venkataramanan 	if (!pi)
3280d54699e2STony Nguyen 		return -EINVAL;
3281fcea6f3dSAnirudh Venkataramanan 
3282092a33d4SBruce Allan 	li = &pi->phy.link_info;
3283fcea6f3dSAnirudh Venkataramanan 
3284092a33d4SBruce Allan 	status = ice_aq_get_link_info(pi, true, NULL, NULL);
3285092a33d4SBruce Allan 	if (status)
3286092a33d4SBruce Allan 		return status;
3287092a33d4SBruce Allan 
3288092a33d4SBruce Allan 	if (li->link_info & ICE_AQ_MEDIA_AVAILABLE) {
3289092a33d4SBruce Allan 		struct ice_aqc_get_phy_caps_data *pcaps;
3290092a33d4SBruce Allan 		struct ice_hw *hw;
3291092a33d4SBruce Allan 
3292092a33d4SBruce Allan 		hw = pi->hw;
3293092a33d4SBruce Allan 		pcaps = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*pcaps),
3294092a33d4SBruce Allan 				     GFP_KERNEL);
3295fcea6f3dSAnirudh Venkataramanan 		if (!pcaps)
3296d54699e2STony Nguyen 			return -ENOMEM;
3297fcea6f3dSAnirudh Venkataramanan 
3298d6730a87SAnirudh Venkataramanan 		status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_TOPO_CAP_MEDIA,
3299fcea6f3dSAnirudh Venkataramanan 					     pcaps, NULL);
3300fcea6f3dSAnirudh Venkataramanan 
3301fcea6f3dSAnirudh Venkataramanan 		devm_kfree(ice_hw_to_dev(hw), pcaps);
3302092a33d4SBruce Allan 	}
3303092a33d4SBruce Allan 
3304fcea6f3dSAnirudh Venkataramanan 	return status;
3305fcea6f3dSAnirudh Venkataramanan }
3306fcea6f3dSAnirudh Venkataramanan 
3307fcea6f3dSAnirudh Venkataramanan /**
33081a3571b5SPaul Greenwalt  * ice_cache_phy_user_req
33091a3571b5SPaul Greenwalt  * @pi: port information structure
33101a3571b5SPaul Greenwalt  * @cache_data: PHY logging data
33111a3571b5SPaul Greenwalt  * @cache_mode: PHY logging mode
33121a3571b5SPaul Greenwalt  *
33131a3571b5SPaul Greenwalt  * Log the user request on (FC, FEC, SPEED) for later use.
33141a3571b5SPaul Greenwalt  */
33151a3571b5SPaul Greenwalt static void
ice_cache_phy_user_req(struct ice_port_info * pi,struct ice_phy_cache_mode_data cache_data,enum ice_phy_cache_mode cache_mode)33161a3571b5SPaul Greenwalt ice_cache_phy_user_req(struct ice_port_info *pi,
33171a3571b5SPaul Greenwalt 		       struct ice_phy_cache_mode_data cache_data,
33181a3571b5SPaul Greenwalt 		       enum ice_phy_cache_mode cache_mode)
33191a3571b5SPaul Greenwalt {
33201a3571b5SPaul Greenwalt 	if (!pi)
33211a3571b5SPaul Greenwalt 		return;
33221a3571b5SPaul Greenwalt 
33231a3571b5SPaul Greenwalt 	switch (cache_mode) {
33241a3571b5SPaul Greenwalt 	case ICE_FC_MODE:
33251a3571b5SPaul Greenwalt 		pi->phy.curr_user_fc_req = cache_data.data.curr_user_fc_req;
33261a3571b5SPaul Greenwalt 		break;
33271a3571b5SPaul Greenwalt 	case ICE_SPEED_MODE:
33281a3571b5SPaul Greenwalt 		pi->phy.curr_user_speed_req =
33291a3571b5SPaul Greenwalt 			cache_data.data.curr_user_speed_req;
33301a3571b5SPaul Greenwalt 		break;
33311a3571b5SPaul Greenwalt 	case ICE_FEC_MODE:
33321a3571b5SPaul Greenwalt 		pi->phy.curr_user_fec_req = cache_data.data.curr_user_fec_req;
33331a3571b5SPaul Greenwalt 		break;
33341a3571b5SPaul Greenwalt 	default:
33351a3571b5SPaul Greenwalt 		break;
33361a3571b5SPaul Greenwalt 	}
33371a3571b5SPaul Greenwalt }
33381a3571b5SPaul Greenwalt 
33391a3571b5SPaul Greenwalt /**
33401a3571b5SPaul Greenwalt  * ice_caps_to_fc_mode
33411a3571b5SPaul Greenwalt  * @caps: PHY capabilities
33421a3571b5SPaul Greenwalt  *
33431a3571b5SPaul Greenwalt  * Convert PHY FC capabilities to ice FC mode
33441a3571b5SPaul Greenwalt  */
ice_caps_to_fc_mode(u8 caps)33451a3571b5SPaul Greenwalt enum ice_fc_mode ice_caps_to_fc_mode(u8 caps)
33461a3571b5SPaul Greenwalt {
33471a3571b5SPaul Greenwalt 	if (caps & ICE_AQC_PHY_EN_TX_LINK_PAUSE &&
33481a3571b5SPaul Greenwalt 	    caps & ICE_AQC_PHY_EN_RX_LINK_PAUSE)
33491a3571b5SPaul Greenwalt 		return ICE_FC_FULL;
33501a3571b5SPaul Greenwalt 
33511a3571b5SPaul Greenwalt 	if (caps & ICE_AQC_PHY_EN_TX_LINK_PAUSE)
33521a3571b5SPaul Greenwalt 		return ICE_FC_TX_PAUSE;
33531a3571b5SPaul Greenwalt 
33541a3571b5SPaul Greenwalt 	if (caps & ICE_AQC_PHY_EN_RX_LINK_PAUSE)
33551a3571b5SPaul Greenwalt 		return ICE_FC_RX_PAUSE;
33561a3571b5SPaul Greenwalt 
33571a3571b5SPaul Greenwalt 	return ICE_FC_NONE;
33581a3571b5SPaul Greenwalt }
33591a3571b5SPaul Greenwalt 
33601a3571b5SPaul Greenwalt /**
33611a3571b5SPaul Greenwalt  * ice_caps_to_fec_mode
33621a3571b5SPaul Greenwalt  * @caps: PHY capabilities
33631a3571b5SPaul Greenwalt  * @fec_options: Link FEC options
33641a3571b5SPaul Greenwalt  *
33651a3571b5SPaul Greenwalt  * Convert PHY FEC capabilities to ice FEC mode
33661a3571b5SPaul Greenwalt  */
ice_caps_to_fec_mode(u8 caps,u8 fec_options)33671a3571b5SPaul Greenwalt enum ice_fec_mode ice_caps_to_fec_mode(u8 caps, u8 fec_options)
33681a3571b5SPaul Greenwalt {
33691a3571b5SPaul Greenwalt 	if (caps & ICE_AQC_PHY_EN_AUTO_FEC)
33701a3571b5SPaul Greenwalt 		return ICE_FEC_AUTO;
33711a3571b5SPaul Greenwalt 
33721a3571b5SPaul Greenwalt 	if (fec_options & (ICE_AQC_PHY_FEC_10G_KR_40G_KR4_EN |
33731a3571b5SPaul Greenwalt 			   ICE_AQC_PHY_FEC_10G_KR_40G_KR4_REQ |
33741a3571b5SPaul Greenwalt 			   ICE_AQC_PHY_FEC_25G_KR_CLAUSE74_EN |
33751a3571b5SPaul Greenwalt 			   ICE_AQC_PHY_FEC_25G_KR_REQ))
33761a3571b5SPaul Greenwalt 		return ICE_FEC_BASER;
33771a3571b5SPaul Greenwalt 
33781a3571b5SPaul Greenwalt 	if (fec_options & (ICE_AQC_PHY_FEC_25G_RS_528_REQ |
33791a3571b5SPaul Greenwalt 			   ICE_AQC_PHY_FEC_25G_RS_544_REQ |
33801a3571b5SPaul Greenwalt 			   ICE_AQC_PHY_FEC_25G_RS_CLAUSE91_EN))
33811a3571b5SPaul Greenwalt 		return ICE_FEC_RS;
33821a3571b5SPaul Greenwalt 
33831a3571b5SPaul Greenwalt 	return ICE_FEC_NONE;
33841a3571b5SPaul Greenwalt }
33851a3571b5SPaul Greenwalt 
33861a3571b5SPaul Greenwalt /**
33872ffb6085SPaul Greenwalt  * ice_cfg_phy_fc - Configure PHY FC data based on FC mode
33881a3571b5SPaul Greenwalt  * @pi: port information structure
33892ffb6085SPaul Greenwalt  * @cfg: PHY configuration data to set FC mode
33902ffb6085SPaul Greenwalt  * @req_mode: FC mode to configure
3391fcea6f3dSAnirudh Venkataramanan  */
33925e24d598STony Nguyen int
ice_cfg_phy_fc(struct ice_port_info * pi,struct ice_aqc_set_phy_cfg_data * cfg,enum ice_fc_mode req_mode)33931a3571b5SPaul Greenwalt ice_cfg_phy_fc(struct ice_port_info *pi, struct ice_aqc_set_phy_cfg_data *cfg,
33941a3571b5SPaul Greenwalt 	       enum ice_fc_mode req_mode)
3395fcea6f3dSAnirudh Venkataramanan {
33961a3571b5SPaul Greenwalt 	struct ice_phy_cache_mode_data cache_data;
3397fcea6f3dSAnirudh Venkataramanan 	u8 pause_mask = 0x0;
3398fcea6f3dSAnirudh Venkataramanan 
33991a3571b5SPaul Greenwalt 	if (!pi || !cfg)
3400d54699e2STony Nguyen 		return -EINVAL;
3401fcea6f3dSAnirudh Venkataramanan 
34022ffb6085SPaul Greenwalt 	switch (req_mode) {
3403fcea6f3dSAnirudh Venkataramanan 	case ICE_FC_FULL:
3404fcea6f3dSAnirudh Venkataramanan 		pause_mask |= ICE_AQC_PHY_EN_TX_LINK_PAUSE;
3405fcea6f3dSAnirudh Venkataramanan 		pause_mask |= ICE_AQC_PHY_EN_RX_LINK_PAUSE;
3406fcea6f3dSAnirudh Venkataramanan 		break;
3407fcea6f3dSAnirudh Venkataramanan 	case ICE_FC_RX_PAUSE:
3408fcea6f3dSAnirudh Venkataramanan 		pause_mask |= ICE_AQC_PHY_EN_RX_LINK_PAUSE;
3409fcea6f3dSAnirudh Venkataramanan 		break;
3410fcea6f3dSAnirudh Venkataramanan 	case ICE_FC_TX_PAUSE:
3411fcea6f3dSAnirudh Venkataramanan 		pause_mask |= ICE_AQC_PHY_EN_TX_LINK_PAUSE;
3412fcea6f3dSAnirudh Venkataramanan 		break;
3413fcea6f3dSAnirudh Venkataramanan 	default:
3414fcea6f3dSAnirudh Venkataramanan 		break;
3415fcea6f3dSAnirudh Venkataramanan 	}
3416fcea6f3dSAnirudh Venkataramanan 
34172ffb6085SPaul Greenwalt 	/* clear the old pause settings */
34182ffb6085SPaul Greenwalt 	cfg->caps &= ~(ICE_AQC_PHY_EN_TX_LINK_PAUSE |
34192ffb6085SPaul Greenwalt 		ICE_AQC_PHY_EN_RX_LINK_PAUSE);
34202ffb6085SPaul Greenwalt 
34212ffb6085SPaul Greenwalt 	/* set the new capabilities */
34222ffb6085SPaul Greenwalt 	cfg->caps |= pause_mask;
34232ffb6085SPaul Greenwalt 
34241a3571b5SPaul Greenwalt 	/* Cache user FC request */
34251a3571b5SPaul Greenwalt 	cache_data.data.curr_user_fc_req = req_mode;
34261a3571b5SPaul Greenwalt 	ice_cache_phy_user_req(pi, cache_data, ICE_FC_MODE);
34271a3571b5SPaul Greenwalt 
34282ffb6085SPaul Greenwalt 	return 0;
34292ffb6085SPaul Greenwalt }
34302ffb6085SPaul Greenwalt 
34312ffb6085SPaul Greenwalt /**
34322ffb6085SPaul Greenwalt  * ice_set_fc
34332ffb6085SPaul Greenwalt  * @pi: port information structure
34342ffb6085SPaul Greenwalt  * @aq_failures: pointer to status code, specific to ice_set_fc routine
34352ffb6085SPaul Greenwalt  * @ena_auto_link_update: enable automatic link update
34362ffb6085SPaul Greenwalt  *
34372ffb6085SPaul Greenwalt  * Set the requested flow control mode.
34382ffb6085SPaul Greenwalt  */
34395e24d598STony Nguyen int
ice_set_fc(struct ice_port_info * pi,u8 * aq_failures,bool ena_auto_link_update)34402ffb6085SPaul Greenwalt ice_set_fc(struct ice_port_info *pi, u8 *aq_failures, bool ena_auto_link_update)
34412ffb6085SPaul Greenwalt {
34422ffb6085SPaul Greenwalt 	struct ice_aqc_set_phy_cfg_data cfg = { 0 };
34432ffb6085SPaul Greenwalt 	struct ice_aqc_get_phy_caps_data *pcaps;
34442ffb6085SPaul Greenwalt 	struct ice_hw *hw;
34455518ac2aSTony Nguyen 	int status;
34462ffb6085SPaul Greenwalt 
34471a3571b5SPaul Greenwalt 	if (!pi || !aq_failures)
3448d54699e2STony Nguyen 		return -EINVAL;
34492ffb6085SPaul Greenwalt 
34502ffb6085SPaul Greenwalt 	*aq_failures = 0;
34512ffb6085SPaul Greenwalt 	hw = pi->hw;
34522ffb6085SPaul Greenwalt 
3453fcea6f3dSAnirudh Venkataramanan 	pcaps = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*pcaps), GFP_KERNEL);
3454fcea6f3dSAnirudh Venkataramanan 	if (!pcaps)
3455d54699e2STony Nguyen 		return -ENOMEM;
3456fcea6f3dSAnirudh Venkataramanan 
3457f9867df6SAnirudh Venkataramanan 	/* Get the current PHY config */
3458d6730a87SAnirudh Venkataramanan 	status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_ACTIVE_CFG,
3459d6730a87SAnirudh Venkataramanan 				     pcaps, NULL);
3460fcea6f3dSAnirudh Venkataramanan 	if (status) {
3461fcea6f3dSAnirudh Venkataramanan 		*aq_failures = ICE_SET_FC_AQ_FAIL_GET;
3462fcea6f3dSAnirudh Venkataramanan 		goto out;
3463fcea6f3dSAnirudh Venkataramanan 	}
3464fcea6f3dSAnirudh Venkataramanan 
3465ea78ce4dSPaul Greenwalt 	ice_copy_phy_caps_to_cfg(pi, pcaps, &cfg);
3466d8df260aSChinh T Cao 
34672ffb6085SPaul Greenwalt 	/* Configure the set PHY data */
34681a3571b5SPaul Greenwalt 	status = ice_cfg_phy_fc(pi, &cfg, pi->fc.req_mode);
34692ffb6085SPaul Greenwalt 	if (status)
34702ffb6085SPaul Greenwalt 		goto out;
3471d8df260aSChinh T Cao 
3472fcea6f3dSAnirudh Venkataramanan 	/* If the capabilities have changed, then set the new config */
3473fcea6f3dSAnirudh Venkataramanan 	if (cfg.caps != pcaps->caps) {
3474fcea6f3dSAnirudh Venkataramanan 		int retry_count, retry_max = 10;
3475fcea6f3dSAnirudh Venkataramanan 
3476fcea6f3dSAnirudh Venkataramanan 		/* Auto restart link so settings take effect */
347748cb27f2SChinh Cao 		if (ena_auto_link_update)
347848cb27f2SChinh Cao 			cfg.caps |= ICE_AQ_PHY_ENA_AUTO_LINK_UPDT;
3479fcea6f3dSAnirudh Venkataramanan 
34801a3571b5SPaul Greenwalt 		status = ice_aq_set_phy_cfg(hw, pi, &cfg, NULL);
3481fcea6f3dSAnirudh Venkataramanan 		if (status) {
3482fcea6f3dSAnirudh Venkataramanan 			*aq_failures = ICE_SET_FC_AQ_FAIL_SET;
3483fcea6f3dSAnirudh Venkataramanan 			goto out;
3484fcea6f3dSAnirudh Venkataramanan 		}
3485fcea6f3dSAnirudh Venkataramanan 
3486fcea6f3dSAnirudh Venkataramanan 		/* Update the link info
3487fcea6f3dSAnirudh Venkataramanan 		 * It sometimes takes a really long time for link to
3488fcea6f3dSAnirudh Venkataramanan 		 * come back from the atomic reset. Thus, we wait a
3489fcea6f3dSAnirudh Venkataramanan 		 * little bit.
3490fcea6f3dSAnirudh Venkataramanan 		 */
3491fcea6f3dSAnirudh Venkataramanan 		for (retry_count = 0; retry_count < retry_max; retry_count++) {
3492fcea6f3dSAnirudh Venkataramanan 			status = ice_update_link_info(pi);
3493fcea6f3dSAnirudh Venkataramanan 
3494fcea6f3dSAnirudh Venkataramanan 			if (!status)
3495fcea6f3dSAnirudh Venkataramanan 				break;
3496fcea6f3dSAnirudh Venkataramanan 
3497fcea6f3dSAnirudh Venkataramanan 			mdelay(100);
3498fcea6f3dSAnirudh Venkataramanan 		}
3499fcea6f3dSAnirudh Venkataramanan 
3500fcea6f3dSAnirudh Venkataramanan 		if (status)
3501fcea6f3dSAnirudh Venkataramanan 			*aq_failures = ICE_SET_FC_AQ_FAIL_UPDATE;
3502fcea6f3dSAnirudh Venkataramanan 	}
3503fcea6f3dSAnirudh Venkataramanan 
3504fcea6f3dSAnirudh Venkataramanan out:
3505fcea6f3dSAnirudh Venkataramanan 	devm_kfree(ice_hw_to_dev(hw), pcaps);
3506fcea6f3dSAnirudh Venkataramanan 	return status;
3507fcea6f3dSAnirudh Venkataramanan }
3508fcea6f3dSAnirudh Venkataramanan 
3509fcea6f3dSAnirudh Venkataramanan /**
35101a3571b5SPaul Greenwalt  * ice_phy_caps_equals_cfg
35111a3571b5SPaul Greenwalt  * @phy_caps: PHY capabilities
35121a3571b5SPaul Greenwalt  * @phy_cfg: PHY configuration
35131a3571b5SPaul Greenwalt  *
35141a3571b5SPaul Greenwalt  * Helper function to determine if PHY capabilities matches PHY
35151a3571b5SPaul Greenwalt  * configuration
35161a3571b5SPaul Greenwalt  */
35171a3571b5SPaul Greenwalt bool
ice_phy_caps_equals_cfg(struct ice_aqc_get_phy_caps_data * phy_caps,struct ice_aqc_set_phy_cfg_data * phy_cfg)35181a3571b5SPaul Greenwalt ice_phy_caps_equals_cfg(struct ice_aqc_get_phy_caps_data *phy_caps,
35191a3571b5SPaul Greenwalt 			struct ice_aqc_set_phy_cfg_data *phy_cfg)
35201a3571b5SPaul Greenwalt {
35211a3571b5SPaul Greenwalt 	u8 caps_mask, cfg_mask;
35221a3571b5SPaul Greenwalt 
35231a3571b5SPaul Greenwalt 	if (!phy_caps || !phy_cfg)
35241a3571b5SPaul Greenwalt 		return false;
35251a3571b5SPaul Greenwalt 
35261a3571b5SPaul Greenwalt 	/* These bits are not common between capabilities and configuration.
35271a3571b5SPaul Greenwalt 	 * Do not use them to determine equality.
35281a3571b5SPaul Greenwalt 	 */
35291a3571b5SPaul Greenwalt 	caps_mask = ICE_AQC_PHY_CAPS_MASK & ~(ICE_AQC_PHY_AN_MODE |
35301a3571b5SPaul Greenwalt 					      ICE_AQC_GET_PHY_EN_MOD_QUAL);
35311a3571b5SPaul Greenwalt 	cfg_mask = ICE_AQ_PHY_ENA_VALID_MASK & ~ICE_AQ_PHY_ENA_AUTO_LINK_UPDT;
35321a3571b5SPaul Greenwalt 
35331a3571b5SPaul Greenwalt 	if (phy_caps->phy_type_low != phy_cfg->phy_type_low ||
35341a3571b5SPaul Greenwalt 	    phy_caps->phy_type_high != phy_cfg->phy_type_high ||
35351a3571b5SPaul Greenwalt 	    ((phy_caps->caps & caps_mask) != (phy_cfg->caps & cfg_mask)) ||
3536bdeff971SLev Faerman 	    phy_caps->low_power_ctrl_an != phy_cfg->low_power_ctrl_an ||
35371a3571b5SPaul Greenwalt 	    phy_caps->eee_cap != phy_cfg->eee_cap ||
35381a3571b5SPaul Greenwalt 	    phy_caps->eeer_value != phy_cfg->eeer_value ||
35391a3571b5SPaul Greenwalt 	    phy_caps->link_fec_options != phy_cfg->link_fec_opt)
35401a3571b5SPaul Greenwalt 		return false;
35411a3571b5SPaul Greenwalt 
35421a3571b5SPaul Greenwalt 	return true;
35431a3571b5SPaul Greenwalt }
35441a3571b5SPaul Greenwalt 
35451a3571b5SPaul Greenwalt /**
3546f776b3acSPaul Greenwalt  * ice_copy_phy_caps_to_cfg - Copy PHY ability data to configuration data
3547ea78ce4dSPaul Greenwalt  * @pi: port information structure
3548f776b3acSPaul Greenwalt  * @caps: PHY ability structure to copy date from
3549f776b3acSPaul Greenwalt  * @cfg: PHY configuration structure to copy data to
3550f776b3acSPaul Greenwalt  *
3551f776b3acSPaul Greenwalt  * Helper function to copy AQC PHY get ability data to PHY set configuration
3552f776b3acSPaul Greenwalt  * data structure
3553f776b3acSPaul Greenwalt  */
3554f776b3acSPaul Greenwalt void
ice_copy_phy_caps_to_cfg(struct ice_port_info * pi,struct ice_aqc_get_phy_caps_data * caps,struct ice_aqc_set_phy_cfg_data * cfg)3555ea78ce4dSPaul Greenwalt ice_copy_phy_caps_to_cfg(struct ice_port_info *pi,
3556ea78ce4dSPaul Greenwalt 			 struct ice_aqc_get_phy_caps_data *caps,
3557f776b3acSPaul Greenwalt 			 struct ice_aqc_set_phy_cfg_data *cfg)
3558f776b3acSPaul Greenwalt {
3559ea78ce4dSPaul Greenwalt 	if (!pi || !caps || !cfg)
3560f776b3acSPaul Greenwalt 		return;
3561f776b3acSPaul Greenwalt 
35622ffb6085SPaul Greenwalt 	memset(cfg, 0, sizeof(*cfg));
3563f776b3acSPaul Greenwalt 	cfg->phy_type_low = caps->phy_type_low;
3564f776b3acSPaul Greenwalt 	cfg->phy_type_high = caps->phy_type_high;
3565f776b3acSPaul Greenwalt 	cfg->caps = caps->caps;
3566bdeff971SLev Faerman 	cfg->low_power_ctrl_an = caps->low_power_ctrl_an;
3567f776b3acSPaul Greenwalt 	cfg->eee_cap = caps->eee_cap;
3568f776b3acSPaul Greenwalt 	cfg->eeer_value = caps->eeer_value;
3569f776b3acSPaul Greenwalt 	cfg->link_fec_opt = caps->link_fec_options;
3570ea78ce4dSPaul Greenwalt 	cfg->module_compliance_enforcement =
3571ea78ce4dSPaul Greenwalt 		caps->module_compliance_enforcement;
3572f776b3acSPaul Greenwalt }
3573f776b3acSPaul Greenwalt 
3574f776b3acSPaul Greenwalt /**
3575f776b3acSPaul Greenwalt  * ice_cfg_phy_fec - Configure PHY FEC data based on FEC mode
357661cf42e7SPaul Greenwalt  * @pi: port information structure
3577f776b3acSPaul Greenwalt  * @cfg: PHY configuration data to set FEC mode
3578f776b3acSPaul Greenwalt  * @fec: FEC mode to configure
3579f776b3acSPaul Greenwalt  */
35805e24d598STony Nguyen int
ice_cfg_phy_fec(struct ice_port_info * pi,struct ice_aqc_set_phy_cfg_data * cfg,enum ice_fec_mode fec)358161cf42e7SPaul Greenwalt ice_cfg_phy_fec(struct ice_port_info *pi, struct ice_aqc_set_phy_cfg_data *cfg,
358261cf42e7SPaul Greenwalt 		enum ice_fec_mode fec)
3583f776b3acSPaul Greenwalt {
358461cf42e7SPaul Greenwalt 	struct ice_aqc_get_phy_caps_data *pcaps;
35850a02944fSAnirudh Venkataramanan 	struct ice_hw *hw;
35865518ac2aSTony Nguyen 	int status;
358761cf42e7SPaul Greenwalt 
358861cf42e7SPaul Greenwalt 	if (!pi || !cfg)
3589d54699e2STony Nguyen 		return -EINVAL;
359061cf42e7SPaul Greenwalt 
35910a02944fSAnirudh Venkataramanan 	hw = pi->hw;
35920a02944fSAnirudh Venkataramanan 
359361cf42e7SPaul Greenwalt 	pcaps = kzalloc(sizeof(*pcaps), GFP_KERNEL);
359461cf42e7SPaul Greenwalt 	if (!pcaps)
3595d54699e2STony Nguyen 		return -ENOMEM;
359661cf42e7SPaul Greenwalt 
35970a02944fSAnirudh Venkataramanan 	status = ice_aq_get_phy_caps(pi, false,
35980a02944fSAnirudh Venkataramanan 				     (ice_fw_supports_report_dflt_cfg(hw) ?
35990a02944fSAnirudh Venkataramanan 				      ICE_AQC_REPORT_DFLT_CFG :
36000a02944fSAnirudh Venkataramanan 				      ICE_AQC_REPORT_TOPO_CAP_MEDIA), pcaps, NULL);
360161cf42e7SPaul Greenwalt 	if (status)
360261cf42e7SPaul Greenwalt 		goto out;
360361cf42e7SPaul Greenwalt 
360461cf42e7SPaul Greenwalt 	cfg->caps |= pcaps->caps & ICE_AQC_PHY_EN_AUTO_FEC;
360561cf42e7SPaul Greenwalt 	cfg->link_fec_opt = pcaps->link_fec_options;
360661cf42e7SPaul Greenwalt 
3607f776b3acSPaul Greenwalt 	switch (fec) {
3608f776b3acSPaul Greenwalt 	case ICE_FEC_BASER:
36093747f031SChinh T Cao 		/* Clear RS bits, and AND BASE-R ability
3610f776b3acSPaul Greenwalt 		 * bits and OR request bits.
3611f776b3acSPaul Greenwalt 		 */
3612f776b3acSPaul Greenwalt 		cfg->link_fec_opt &= ICE_AQC_PHY_FEC_10G_KR_40G_KR4_EN |
3613f776b3acSPaul Greenwalt 			ICE_AQC_PHY_FEC_25G_KR_CLAUSE74_EN;
3614f776b3acSPaul Greenwalt 		cfg->link_fec_opt |= ICE_AQC_PHY_FEC_10G_KR_40G_KR4_REQ |
3615f776b3acSPaul Greenwalt 			ICE_AQC_PHY_FEC_25G_KR_REQ;
3616f776b3acSPaul Greenwalt 		break;
3617f776b3acSPaul Greenwalt 	case ICE_FEC_RS:
36183747f031SChinh T Cao 		/* Clear BASE-R bits, and AND RS ability
3619f776b3acSPaul Greenwalt 		 * bits and OR request bits.
3620f776b3acSPaul Greenwalt 		 */
3621f776b3acSPaul Greenwalt 		cfg->link_fec_opt &= ICE_AQC_PHY_FEC_25G_RS_CLAUSE91_EN;
3622f776b3acSPaul Greenwalt 		cfg->link_fec_opt |= ICE_AQC_PHY_FEC_25G_RS_528_REQ |
3623f776b3acSPaul Greenwalt 			ICE_AQC_PHY_FEC_25G_RS_544_REQ;
3624f776b3acSPaul Greenwalt 		break;
3625f776b3acSPaul Greenwalt 	case ICE_FEC_NONE:
36263747f031SChinh T Cao 		/* Clear all FEC option bits. */
3627f776b3acSPaul Greenwalt 		cfg->link_fec_opt &= ~ICE_AQC_PHY_FEC_MASK;
3628f776b3acSPaul Greenwalt 		break;
3629f776b3acSPaul Greenwalt 	case ICE_FEC_AUTO:
3630f776b3acSPaul Greenwalt 		/* AND auto FEC bit, and all caps bits. */
3631f776b3acSPaul Greenwalt 		cfg->caps &= ICE_AQC_PHY_CAPS_MASK;
363261cf42e7SPaul Greenwalt 		cfg->link_fec_opt |= pcaps->link_fec_options;
363361cf42e7SPaul Greenwalt 		break;
363461cf42e7SPaul Greenwalt 	default:
3635d54699e2STony Nguyen 		status = -EINVAL;
3636f776b3acSPaul Greenwalt 		break;
3637f776b3acSPaul Greenwalt 	}
363861cf42e7SPaul Greenwalt 
363975751c80SJeb Cramer 	if (fec == ICE_FEC_AUTO && ice_fw_supports_link_override(hw) &&
364075751c80SJeb Cramer 	    !ice_fw_supports_report_dflt_cfg(hw)) {
36415950bdc8STom Rix 		struct ice_link_default_override_tlv tlv = { 0 };
3642ea78ce4dSPaul Greenwalt 
364321338d58SDan Carpenter 		status = ice_get_link_default_override(&tlv, pi);
364421338d58SDan Carpenter 		if (status)
3645ea78ce4dSPaul Greenwalt 			goto out;
3646ea78ce4dSPaul Greenwalt 
3647ea78ce4dSPaul Greenwalt 		if (!(tlv.options & ICE_LINK_OVERRIDE_STRICT_MODE) &&
3648ea78ce4dSPaul Greenwalt 		    (tlv.options & ICE_LINK_OVERRIDE_EN))
3649ea78ce4dSPaul Greenwalt 			cfg->link_fec_opt = tlv.fec_options;
3650ea78ce4dSPaul Greenwalt 	}
3651ea78ce4dSPaul Greenwalt 
365261cf42e7SPaul Greenwalt out:
365361cf42e7SPaul Greenwalt 	kfree(pcaps);
365461cf42e7SPaul Greenwalt 
365561cf42e7SPaul Greenwalt 	return status;
3656f776b3acSPaul Greenwalt }
3657f776b3acSPaul Greenwalt 
3658f776b3acSPaul Greenwalt /**
36590b28b702SAnirudh Venkataramanan  * ice_get_link_status - get status of the HW network link
36600b28b702SAnirudh Venkataramanan  * @pi: port information structure
36610b28b702SAnirudh Venkataramanan  * @link_up: pointer to bool (true/false = linkup/linkdown)
36620b28b702SAnirudh Venkataramanan  *
36630b28b702SAnirudh Venkataramanan  * Variable link_up is true if link is up, false if link is down.
36640b28b702SAnirudh Venkataramanan  * The variable link_up is invalid if status is non zero. As a
36650b28b702SAnirudh Venkataramanan  * result of this call, link status reporting becomes enabled
36660b28b702SAnirudh Venkataramanan  */
ice_get_link_status(struct ice_port_info * pi,bool * link_up)36675e24d598STony Nguyen int ice_get_link_status(struct ice_port_info *pi, bool *link_up)
36680b28b702SAnirudh Venkataramanan {
36690b28b702SAnirudh Venkataramanan 	struct ice_phy_info *phy_info;
36705e24d598STony Nguyen 	int status = 0;
36710b28b702SAnirudh Venkataramanan 
3672c7f2c42bSAnirudh Venkataramanan 	if (!pi || !link_up)
3673d54699e2STony Nguyen 		return -EINVAL;
36740b28b702SAnirudh Venkataramanan 
36750b28b702SAnirudh Venkataramanan 	phy_info = &pi->phy;
36760b28b702SAnirudh Venkataramanan 
36770b28b702SAnirudh Venkataramanan 	if (phy_info->get_link_info) {
36780b28b702SAnirudh Venkataramanan 		status = ice_update_link_info(pi);
36790b28b702SAnirudh Venkataramanan 
36800b28b702SAnirudh Venkataramanan 		if (status)
36819228d8b2SJacob Keller 			ice_debug(pi->hw, ICE_DBG_LINK, "get link status error, status = %d\n",
36820b28b702SAnirudh Venkataramanan 				  status);
36830b28b702SAnirudh Venkataramanan 	}
36840b28b702SAnirudh Venkataramanan 
36850b28b702SAnirudh Venkataramanan 	*link_up = phy_info->link_info.link_info & ICE_AQ_LINK_UP;
36860b28b702SAnirudh Venkataramanan 
36870b28b702SAnirudh Venkataramanan 	return status;
36880b28b702SAnirudh Venkataramanan }
36890b28b702SAnirudh Venkataramanan 
36900b28b702SAnirudh Venkataramanan /**
3691fcea6f3dSAnirudh Venkataramanan  * ice_aq_set_link_restart_an
3692fcea6f3dSAnirudh Venkataramanan  * @pi: pointer to the port information structure
3693fcea6f3dSAnirudh Venkataramanan  * @ena_link: if true: enable link, if false: disable link
3694fcea6f3dSAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
3695fcea6f3dSAnirudh Venkataramanan  *
3696fcea6f3dSAnirudh Venkataramanan  * Sets up the link and restarts the Auto-Negotiation over the link.
3697fcea6f3dSAnirudh Venkataramanan  */
36985e24d598STony Nguyen int
ice_aq_set_link_restart_an(struct ice_port_info * pi,bool ena_link,struct ice_sq_cd * cd)3699fcea6f3dSAnirudh Venkataramanan ice_aq_set_link_restart_an(struct ice_port_info *pi, bool ena_link,
3700fcea6f3dSAnirudh Venkataramanan 			   struct ice_sq_cd *cd)
3701fcea6f3dSAnirudh Venkataramanan {
3702fcea6f3dSAnirudh Venkataramanan 	struct ice_aqc_restart_an *cmd;
3703fcea6f3dSAnirudh Venkataramanan 	struct ice_aq_desc desc;
3704fcea6f3dSAnirudh Venkataramanan 
3705fcea6f3dSAnirudh Venkataramanan 	cmd = &desc.params.restart_an;
3706fcea6f3dSAnirudh Venkataramanan 
3707fcea6f3dSAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_restart_an);
3708fcea6f3dSAnirudh Venkataramanan 
3709fcea6f3dSAnirudh Venkataramanan 	cmd->cmd_flags = ICE_AQC_RESTART_AN_LINK_RESTART;
3710fcea6f3dSAnirudh Venkataramanan 	cmd->lport_num = pi->lport;
3711fcea6f3dSAnirudh Venkataramanan 	if (ena_link)
3712fcea6f3dSAnirudh Venkataramanan 		cmd->cmd_flags |= ICE_AQC_RESTART_AN_LINK_ENABLE;
3713fcea6f3dSAnirudh Venkataramanan 	else
3714fcea6f3dSAnirudh Venkataramanan 		cmd->cmd_flags &= ~ICE_AQC_RESTART_AN_LINK_ENABLE;
3715fcea6f3dSAnirudh Venkataramanan 
3716fcea6f3dSAnirudh Venkataramanan 	return ice_aq_send_cmd(pi->hw, &desc, NULL, 0, cd);
3717fcea6f3dSAnirudh Venkataramanan }
3718fcea6f3dSAnirudh Venkataramanan 
3719fcea6f3dSAnirudh Venkataramanan /**
3720250c3b3eSBrett Creeley  * ice_aq_set_event_mask
3721250c3b3eSBrett Creeley  * @hw: pointer to the HW struct
3722250c3b3eSBrett Creeley  * @port_num: port number of the physical function
3723250c3b3eSBrett Creeley  * @mask: event mask to be set
3724250c3b3eSBrett Creeley  * @cd: pointer to command details structure or NULL
3725250c3b3eSBrett Creeley  *
3726250c3b3eSBrett Creeley  * Set event mask (0x0613)
3727250c3b3eSBrett Creeley  */
37285e24d598STony Nguyen int
ice_aq_set_event_mask(struct ice_hw * hw,u8 port_num,u16 mask,struct ice_sq_cd * cd)3729250c3b3eSBrett Creeley ice_aq_set_event_mask(struct ice_hw *hw, u8 port_num, u16 mask,
3730250c3b3eSBrett Creeley 		      struct ice_sq_cd *cd)
3731250c3b3eSBrett Creeley {
3732250c3b3eSBrett Creeley 	struct ice_aqc_set_event_mask *cmd;
3733250c3b3eSBrett Creeley 	struct ice_aq_desc desc;
3734250c3b3eSBrett Creeley 
3735250c3b3eSBrett Creeley 	cmd = &desc.params.set_event_mask;
3736250c3b3eSBrett Creeley 
3737250c3b3eSBrett Creeley 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_event_mask);
3738250c3b3eSBrett Creeley 
3739250c3b3eSBrett Creeley 	cmd->lport_num = port_num;
3740250c3b3eSBrett Creeley 
3741250c3b3eSBrett Creeley 	cmd->event_mask = cpu_to_le16(mask);
3742250c3b3eSBrett Creeley 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
3743250c3b3eSBrett Creeley }
3744250c3b3eSBrett Creeley 
3745250c3b3eSBrett Creeley /**
37460e674aebSAnirudh Venkataramanan  * ice_aq_set_mac_loopback
37470e674aebSAnirudh Venkataramanan  * @hw: pointer to the HW struct
37480e674aebSAnirudh Venkataramanan  * @ena_lpbk: Enable or Disable loopback
37490e674aebSAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
37500e674aebSAnirudh Venkataramanan  *
37510e674aebSAnirudh Venkataramanan  * Enable/disable loopback on a given port
37520e674aebSAnirudh Venkataramanan  */
37535e24d598STony Nguyen int
ice_aq_set_mac_loopback(struct ice_hw * hw,bool ena_lpbk,struct ice_sq_cd * cd)37540e674aebSAnirudh Venkataramanan ice_aq_set_mac_loopback(struct ice_hw *hw, bool ena_lpbk, struct ice_sq_cd *cd)
37550e674aebSAnirudh Venkataramanan {
37560e674aebSAnirudh Venkataramanan 	struct ice_aqc_set_mac_lb *cmd;
37570e674aebSAnirudh Venkataramanan 	struct ice_aq_desc desc;
37580e674aebSAnirudh Venkataramanan 
37590e674aebSAnirudh Venkataramanan 	cmd = &desc.params.set_mac_lb;
37600e674aebSAnirudh Venkataramanan 
37610e674aebSAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_mac_lb);
37620e674aebSAnirudh Venkataramanan 	if (ena_lpbk)
37630e674aebSAnirudh Venkataramanan 		cmd->lb_mode = ICE_AQ_MAC_LB_EN;
37640e674aebSAnirudh Venkataramanan 
37650e674aebSAnirudh Venkataramanan 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
37660e674aebSAnirudh Venkataramanan }
37670e674aebSAnirudh Venkataramanan 
37680e674aebSAnirudh Venkataramanan /**
37698e151d50SAnirudh Venkataramanan  * ice_aq_set_port_id_led
37708e151d50SAnirudh Venkataramanan  * @pi: pointer to the port information
37718e151d50SAnirudh Venkataramanan  * @is_orig_mode: is this LED set to original mode (by the net-list)
37728e151d50SAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
37738e151d50SAnirudh Venkataramanan  *
37748e151d50SAnirudh Venkataramanan  * Set LED value for the given port (0x06e9)
37758e151d50SAnirudh Venkataramanan  */
37765e24d598STony Nguyen int
ice_aq_set_port_id_led(struct ice_port_info * pi,bool is_orig_mode,struct ice_sq_cd * cd)37778e151d50SAnirudh Venkataramanan ice_aq_set_port_id_led(struct ice_port_info *pi, bool is_orig_mode,
37788e151d50SAnirudh Venkataramanan 		       struct ice_sq_cd *cd)
37798e151d50SAnirudh Venkataramanan {
37808e151d50SAnirudh Venkataramanan 	struct ice_aqc_set_port_id_led *cmd;
37818e151d50SAnirudh Venkataramanan 	struct ice_hw *hw = pi->hw;
37828e151d50SAnirudh Venkataramanan 	struct ice_aq_desc desc;
37838e151d50SAnirudh Venkataramanan 
37848e151d50SAnirudh Venkataramanan 	cmd = &desc.params.set_port_id_led;
37858e151d50SAnirudh Venkataramanan 
37868e151d50SAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_port_id_led);
37878e151d50SAnirudh Venkataramanan 
37888e151d50SAnirudh Venkataramanan 	if (is_orig_mode)
37898e151d50SAnirudh Venkataramanan 		cmd->ident_mode = ICE_AQC_PORT_IDENT_LED_ORIG;
37908e151d50SAnirudh Venkataramanan 	else
37918e151d50SAnirudh Venkataramanan 		cmd->ident_mode = ICE_AQC_PORT_IDENT_LED_BLINK;
37928e151d50SAnirudh Venkataramanan 
37938e151d50SAnirudh Venkataramanan 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
37948e151d50SAnirudh Venkataramanan }
37958e151d50SAnirudh Venkataramanan 
37968e151d50SAnirudh Venkataramanan /**
3797781f15eaSAnatolii Gerasymenko  * ice_aq_get_port_options
3798781f15eaSAnatolii Gerasymenko  * @hw: pointer to the HW struct
3799781f15eaSAnatolii Gerasymenko  * @options: buffer for the resultant port options
3800781f15eaSAnatolii Gerasymenko  * @option_count: input - size of the buffer in port options structures,
3801781f15eaSAnatolii Gerasymenko  *                output - number of returned port options
3802781f15eaSAnatolii Gerasymenko  * @lport: logical port to call the command with (optional)
3803781f15eaSAnatolii Gerasymenko  * @lport_valid: when false, FW uses port owned by the PF instead of lport,
3804781f15eaSAnatolii Gerasymenko  *               when PF owns more than 1 port it must be true
3805781f15eaSAnatolii Gerasymenko  * @active_option_idx: index of active port option in returned buffer
3806781f15eaSAnatolii Gerasymenko  * @active_option_valid: active option in returned buffer is valid
3807781f15eaSAnatolii Gerasymenko  * @pending_option_idx: index of pending port option in returned buffer
3808781f15eaSAnatolii Gerasymenko  * @pending_option_valid: pending option in returned buffer is valid
3809781f15eaSAnatolii Gerasymenko  *
3810781f15eaSAnatolii Gerasymenko  * Calls Get Port Options AQC (0x06ea) and verifies result.
3811781f15eaSAnatolii Gerasymenko  */
3812781f15eaSAnatolii Gerasymenko int
ice_aq_get_port_options(struct ice_hw * hw,struct ice_aqc_get_port_options_elem * options,u8 * option_count,u8 lport,bool lport_valid,u8 * active_option_idx,bool * active_option_valid,u8 * pending_option_idx,bool * pending_option_valid)3813781f15eaSAnatolii Gerasymenko ice_aq_get_port_options(struct ice_hw *hw,
3814781f15eaSAnatolii Gerasymenko 			struct ice_aqc_get_port_options_elem *options,
3815781f15eaSAnatolii Gerasymenko 			u8 *option_count, u8 lport, bool lport_valid,
3816781f15eaSAnatolii Gerasymenko 			u8 *active_option_idx, bool *active_option_valid,
3817781f15eaSAnatolii Gerasymenko 			u8 *pending_option_idx, bool *pending_option_valid)
3818781f15eaSAnatolii Gerasymenko {
3819781f15eaSAnatolii Gerasymenko 	struct ice_aqc_get_port_options *cmd;
3820781f15eaSAnatolii Gerasymenko 	struct ice_aq_desc desc;
3821781f15eaSAnatolii Gerasymenko 	int status;
3822781f15eaSAnatolii Gerasymenko 	u8 i;
3823781f15eaSAnatolii Gerasymenko 
3824781f15eaSAnatolii Gerasymenko 	/* options buffer shall be able to hold max returned options */
3825781f15eaSAnatolii Gerasymenko 	if (*option_count < ICE_AQC_PORT_OPT_COUNT_M)
3826781f15eaSAnatolii Gerasymenko 		return -EINVAL;
3827781f15eaSAnatolii Gerasymenko 
3828781f15eaSAnatolii Gerasymenko 	cmd = &desc.params.get_port_options;
3829781f15eaSAnatolii Gerasymenko 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_port_options);
3830781f15eaSAnatolii Gerasymenko 
3831781f15eaSAnatolii Gerasymenko 	if (lport_valid)
3832781f15eaSAnatolii Gerasymenko 		cmd->lport_num = lport;
3833781f15eaSAnatolii Gerasymenko 	cmd->lport_num_valid = lport_valid;
3834781f15eaSAnatolii Gerasymenko 
3835781f15eaSAnatolii Gerasymenko 	status = ice_aq_send_cmd(hw, &desc, options,
3836781f15eaSAnatolii Gerasymenko 				 *option_count * sizeof(*options), NULL);
3837781f15eaSAnatolii Gerasymenko 	if (status)
3838781f15eaSAnatolii Gerasymenko 		return status;
3839781f15eaSAnatolii Gerasymenko 
3840781f15eaSAnatolii Gerasymenko 	/* verify direct FW response & set output parameters */
3841781f15eaSAnatolii Gerasymenko 	*option_count = FIELD_GET(ICE_AQC_PORT_OPT_COUNT_M,
3842781f15eaSAnatolii Gerasymenko 				  cmd->port_options_count);
3843781f15eaSAnatolii Gerasymenko 	ice_debug(hw, ICE_DBG_PHY, "options: %x\n", *option_count);
3844781f15eaSAnatolii Gerasymenko 	*active_option_valid = FIELD_GET(ICE_AQC_PORT_OPT_VALID,
3845781f15eaSAnatolii Gerasymenko 					 cmd->port_options);
3846781f15eaSAnatolii Gerasymenko 	if (*active_option_valid) {
3847781f15eaSAnatolii Gerasymenko 		*active_option_idx = FIELD_GET(ICE_AQC_PORT_OPT_ACTIVE_M,
3848781f15eaSAnatolii Gerasymenko 					       cmd->port_options);
3849781f15eaSAnatolii Gerasymenko 		if (*active_option_idx > (*option_count - 1))
3850781f15eaSAnatolii Gerasymenko 			return -EIO;
3851781f15eaSAnatolii Gerasymenko 		ice_debug(hw, ICE_DBG_PHY, "active idx: %x\n",
3852781f15eaSAnatolii Gerasymenko 			  *active_option_idx);
3853781f15eaSAnatolii Gerasymenko 	}
3854781f15eaSAnatolii Gerasymenko 
3855781f15eaSAnatolii Gerasymenko 	*pending_option_valid = FIELD_GET(ICE_AQC_PENDING_PORT_OPT_VALID,
3856781f15eaSAnatolii Gerasymenko 					  cmd->pending_port_option_status);
3857781f15eaSAnatolii Gerasymenko 	if (*pending_option_valid) {
3858781f15eaSAnatolii Gerasymenko 		*pending_option_idx = FIELD_GET(ICE_AQC_PENDING_PORT_OPT_IDX_M,
3859781f15eaSAnatolii Gerasymenko 						cmd->pending_port_option_status);
3860781f15eaSAnatolii Gerasymenko 		if (*pending_option_idx > (*option_count - 1))
3861781f15eaSAnatolii Gerasymenko 			return -EIO;
3862781f15eaSAnatolii Gerasymenko 		ice_debug(hw, ICE_DBG_PHY, "pending idx: %x\n",
3863781f15eaSAnatolii Gerasymenko 			  *pending_option_idx);
3864781f15eaSAnatolii Gerasymenko 	}
3865781f15eaSAnatolii Gerasymenko 
3866781f15eaSAnatolii Gerasymenko 	/* mask output options fields */
3867781f15eaSAnatolii Gerasymenko 	for (i = 0; i < *option_count; i++) {
3868781f15eaSAnatolii Gerasymenko 		options[i].pmd = FIELD_GET(ICE_AQC_PORT_OPT_PMD_COUNT_M,
3869781f15eaSAnatolii Gerasymenko 					   options[i].pmd);
3870781f15eaSAnatolii Gerasymenko 		options[i].max_lane_speed = FIELD_GET(ICE_AQC_PORT_OPT_MAX_LANE_M,
3871781f15eaSAnatolii Gerasymenko 						      options[i].max_lane_speed);
3872781f15eaSAnatolii Gerasymenko 		ice_debug(hw, ICE_DBG_PHY, "pmds: %x max speed: %x\n",
3873781f15eaSAnatolii Gerasymenko 			  options[i].pmd, options[i].max_lane_speed);
3874781f15eaSAnatolii Gerasymenko 	}
3875781f15eaSAnatolii Gerasymenko 
3876781f15eaSAnatolii Gerasymenko 	return 0;
3877781f15eaSAnatolii Gerasymenko }
3878781f15eaSAnatolii Gerasymenko 
3879781f15eaSAnatolii Gerasymenko /**
3880781f15eaSAnatolii Gerasymenko  * ice_aq_set_port_option
3881781f15eaSAnatolii Gerasymenko  * @hw: pointer to the HW struct
3882781f15eaSAnatolii Gerasymenko  * @lport: logical port to call the command with
3883781f15eaSAnatolii Gerasymenko  * @lport_valid: when false, FW uses port owned by the PF instead of lport,
3884781f15eaSAnatolii Gerasymenko  *               when PF owns more than 1 port it must be true
3885781f15eaSAnatolii Gerasymenko  * @new_option: new port option to be written
3886781f15eaSAnatolii Gerasymenko  *
3887781f15eaSAnatolii Gerasymenko  * Calls Set Port Options AQC (0x06eb).
3888781f15eaSAnatolii Gerasymenko  */
3889781f15eaSAnatolii Gerasymenko int
ice_aq_set_port_option(struct ice_hw * hw,u8 lport,u8 lport_valid,u8 new_option)3890781f15eaSAnatolii Gerasymenko ice_aq_set_port_option(struct ice_hw *hw, u8 lport, u8 lport_valid,
3891781f15eaSAnatolii Gerasymenko 		       u8 new_option)
3892781f15eaSAnatolii Gerasymenko {
3893781f15eaSAnatolii Gerasymenko 	struct ice_aqc_set_port_option *cmd;
3894781f15eaSAnatolii Gerasymenko 	struct ice_aq_desc desc;
3895781f15eaSAnatolii Gerasymenko 
3896781f15eaSAnatolii Gerasymenko 	if (new_option > ICE_AQC_PORT_OPT_COUNT_M)
3897781f15eaSAnatolii Gerasymenko 		return -EINVAL;
3898781f15eaSAnatolii Gerasymenko 
3899781f15eaSAnatolii Gerasymenko 	cmd = &desc.params.set_port_option;
3900781f15eaSAnatolii Gerasymenko 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_port_option);
3901781f15eaSAnatolii Gerasymenko 
3902781f15eaSAnatolii Gerasymenko 	if (lport_valid)
3903781f15eaSAnatolii Gerasymenko 		cmd->lport_num = lport;
3904781f15eaSAnatolii Gerasymenko 
3905781f15eaSAnatolii Gerasymenko 	cmd->lport_num_valid = lport_valid;
3906781f15eaSAnatolii Gerasymenko 	cmd->selected_port_option = new_option;
3907781f15eaSAnatolii Gerasymenko 
3908781f15eaSAnatolii Gerasymenko 	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
3909781f15eaSAnatolii Gerasymenko }
3910781f15eaSAnatolii Gerasymenko 
3911781f15eaSAnatolii Gerasymenko /**
3912a012dca9SScott W Taylor  * ice_aq_sff_eeprom
3913a012dca9SScott W Taylor  * @hw: pointer to the HW struct
3914a012dca9SScott W Taylor  * @lport: bits [7:0] = logical port, bit [8] = logical port valid
3915a012dca9SScott W Taylor  * @bus_addr: I2C bus address of the eeprom (typically 0xA0, 0=topo default)
3916a012dca9SScott W Taylor  * @mem_addr: I2C offset. lower 8 bits for address, 8 upper bits zero padding.
3917a012dca9SScott W Taylor  * @page: QSFP page
3918a012dca9SScott W Taylor  * @set_page: set or ignore the page
3919a012dca9SScott W Taylor  * @data: pointer to data buffer to be read/written to the I2C device.
3920a012dca9SScott W Taylor  * @length: 1-16 for read, 1 for write.
3921a012dca9SScott W Taylor  * @write: 0 read, 1 for write.
3922a012dca9SScott W Taylor  * @cd: pointer to command details structure or NULL
3923a012dca9SScott W Taylor  *
3924a012dca9SScott W Taylor  * Read/Write SFF EEPROM (0x06EE)
3925a012dca9SScott W Taylor  */
39265e24d598STony Nguyen int
ice_aq_sff_eeprom(struct ice_hw * hw,u16 lport,u8 bus_addr,u16 mem_addr,u8 page,u8 set_page,u8 * data,u8 length,bool write,struct ice_sq_cd * cd)3927a012dca9SScott W Taylor ice_aq_sff_eeprom(struct ice_hw *hw, u16 lport, u8 bus_addr,
3928a012dca9SScott W Taylor 		  u16 mem_addr, u8 page, u8 set_page, u8 *data, u8 length,
3929a012dca9SScott W Taylor 		  bool write, struct ice_sq_cd *cd)
3930a012dca9SScott W Taylor {
3931a012dca9SScott W Taylor 	struct ice_aqc_sff_eeprom *cmd;
3932a012dca9SScott W Taylor 	struct ice_aq_desc desc;
39335e24d598STony Nguyen 	int status;
3934a012dca9SScott W Taylor 
3935a012dca9SScott W Taylor 	if (!data || (mem_addr & 0xff00))
3936d54699e2STony Nguyen 		return -EINVAL;
3937a012dca9SScott W Taylor 
3938a012dca9SScott W Taylor 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_sff_eeprom);
3939a012dca9SScott W Taylor 	cmd = &desc.params.read_write_sff_param;
3940800c1443SBruce Allan 	desc.flags = cpu_to_le16(ICE_AQ_FLAG_RD);
3941a012dca9SScott W Taylor 	cmd->lport_num = (u8)(lport & 0xff);
3942a012dca9SScott W Taylor 	cmd->lport_num_valid = (u8)((lport >> 8) & 0x01);
3943a012dca9SScott W Taylor 	cmd->i2c_bus_addr = cpu_to_le16(((bus_addr >> 1) &
3944a012dca9SScott W Taylor 					 ICE_AQC_SFF_I2CBUS_7BIT_M) |
3945a012dca9SScott W Taylor 					((set_page <<
3946a012dca9SScott W Taylor 					  ICE_AQC_SFF_SET_EEPROM_PAGE_S) &
3947a012dca9SScott W Taylor 					 ICE_AQC_SFF_SET_EEPROM_PAGE_M));
3948a012dca9SScott W Taylor 	cmd->i2c_mem_addr = cpu_to_le16(mem_addr & 0xff);
3949a012dca9SScott W Taylor 	cmd->eeprom_page = cpu_to_le16((u16)page << ICE_AQC_SFF_EEPROM_PAGE_S);
3950a012dca9SScott W Taylor 	if (write)
3951a012dca9SScott W Taylor 		cmd->i2c_bus_addr |= cpu_to_le16(ICE_AQC_SFF_IS_WRITE);
3952a012dca9SScott W Taylor 
3953a012dca9SScott W Taylor 	status = ice_aq_send_cmd(hw, &desc, data, length, cd);
3954a012dca9SScott W Taylor 	return status;
3955a012dca9SScott W Taylor }
3956a012dca9SScott W Taylor 
ice_lut_type_to_size(enum ice_lut_type type)3957b6143c9bSPrzemek Kitszel static enum ice_lut_size ice_lut_type_to_size(enum ice_lut_type type)
3958b6143c9bSPrzemek Kitszel {
3959b6143c9bSPrzemek Kitszel 	switch (type) {
3960b6143c9bSPrzemek Kitszel 	case ICE_LUT_VSI:
3961b6143c9bSPrzemek Kitszel 		return ICE_LUT_VSI_SIZE;
3962b6143c9bSPrzemek Kitszel 	case ICE_LUT_GLOBAL:
3963b6143c9bSPrzemek Kitszel 		return ICE_LUT_GLOBAL_SIZE;
3964b6143c9bSPrzemek Kitszel 	case ICE_LUT_PF:
3965b6143c9bSPrzemek Kitszel 		return ICE_LUT_PF_SIZE;
3966b6143c9bSPrzemek Kitszel 	}
3967b6143c9bSPrzemek Kitszel 	WARN_ONCE(1, "incorrect type passed");
3968b6143c9bSPrzemek Kitszel 	return ICE_LUT_VSI_SIZE;
3969b6143c9bSPrzemek Kitszel }
3970b6143c9bSPrzemek Kitszel 
ice_lut_size_to_flag(enum ice_lut_size size)3971b6143c9bSPrzemek Kitszel static enum ice_aqc_lut_flags ice_lut_size_to_flag(enum ice_lut_size size)
3972b6143c9bSPrzemek Kitszel {
3973b6143c9bSPrzemek Kitszel 	switch (size) {
3974b6143c9bSPrzemek Kitszel 	case ICE_LUT_VSI_SIZE:
3975b6143c9bSPrzemek Kitszel 		return ICE_AQC_LUT_SIZE_SMALL;
3976b6143c9bSPrzemek Kitszel 	case ICE_LUT_GLOBAL_SIZE:
3977b6143c9bSPrzemek Kitszel 		return ICE_AQC_LUT_SIZE_512;
3978b6143c9bSPrzemek Kitszel 	case ICE_LUT_PF_SIZE:
3979b6143c9bSPrzemek Kitszel 		return ICE_AQC_LUT_SIZE_2K;
3980b6143c9bSPrzemek Kitszel 	}
3981b6143c9bSPrzemek Kitszel 	WARN_ONCE(1, "incorrect size passed");
3982b6143c9bSPrzemek Kitszel 	return 0;
3983b6143c9bSPrzemek Kitszel }
3984b6143c9bSPrzemek Kitszel 
3985a012dca9SScott W Taylor /**
3986d76a60baSAnirudh Venkataramanan  * __ice_aq_get_set_rss_lut
3987d76a60baSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
3988e3c53928SBrett Creeley  * @params: RSS LUT parameters
3989d76a60baSAnirudh Venkataramanan  * @set: set true to set the table, false to get the table
3990d76a60baSAnirudh Venkataramanan  *
3991d76a60baSAnirudh Venkataramanan  * Internal function to get (0x0B05) or set (0x0B03) RSS look up table
3992d76a60baSAnirudh Venkataramanan  */
39935e24d598STony Nguyen static int
__ice_aq_get_set_rss_lut(struct ice_hw * hw,struct ice_aq_get_set_rss_lut_params * params,bool set)3994b6143c9bSPrzemek Kitszel __ice_aq_get_set_rss_lut(struct ice_hw *hw,
3995b6143c9bSPrzemek Kitszel 			 struct ice_aq_get_set_rss_lut_params *params, bool set)
3996d76a60baSAnirudh Venkataramanan {
3997b6143c9bSPrzemek Kitszel 	u16 opcode, vsi_id, vsi_handle = params->vsi_handle, glob_lut_idx = 0;
3998b6143c9bSPrzemek Kitszel 	enum ice_lut_type lut_type = params->lut_type;
3999b6143c9bSPrzemek Kitszel 	struct ice_aqc_get_set_rss_lut *desc_params;
4000b6143c9bSPrzemek Kitszel 	enum ice_aqc_lut_flags flags;
4001b6143c9bSPrzemek Kitszel 	enum ice_lut_size lut_size;
4002d76a60baSAnirudh Venkataramanan 	struct ice_aq_desc desc;
4003b6143c9bSPrzemek Kitszel 	u8 *lut = params->lut;
4004e3c53928SBrett Creeley 
4005b6143c9bSPrzemek Kitszel 
4006b6143c9bSPrzemek Kitszel 	if (!lut || !ice_is_vsi_valid(hw, vsi_handle))
4007d54699e2STony Nguyen 		return -EINVAL;
4008e3c53928SBrett Creeley 
4009b6143c9bSPrzemek Kitszel 	lut_size = ice_lut_type_to_size(lut_type);
4010b6143c9bSPrzemek Kitszel 	if (lut_size > params->lut_size)
4011b6143c9bSPrzemek Kitszel 		return -EINVAL;
4012b6143c9bSPrzemek Kitszel 	else if (set && lut_size != params->lut_size)
4013d54699e2STony Nguyen 		return -EINVAL;
4014e3c53928SBrett Creeley 
4015b6143c9bSPrzemek Kitszel 	opcode = set ? ice_aqc_opc_set_rss_lut : ice_aqc_opc_get_rss_lut;
4016b6143c9bSPrzemek Kitszel 	ice_fill_dflt_direct_cmd_desc(&desc, opcode);
4017b6143c9bSPrzemek Kitszel 	if (set)
4018d76a60baSAnirudh Venkataramanan 		desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
4019d76a60baSAnirudh Venkataramanan 
4020b6143c9bSPrzemek Kitszel 	desc_params = &desc.params.get_set_rss_lut;
4021b6143c9bSPrzemek Kitszel 	vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
4022b6143c9bSPrzemek Kitszel 	desc_params->vsi_id = cpu_to_le16(vsi_id | ICE_AQC_RSS_VSI_VALID);
4023d76a60baSAnirudh Venkataramanan 
4024b6143c9bSPrzemek Kitszel 	if (lut_type == ICE_LUT_GLOBAL)
4025b6143c9bSPrzemek Kitszel 		glob_lut_idx = FIELD_PREP(ICE_AQC_LUT_GLOBAL_IDX,
4026b6143c9bSPrzemek Kitszel 					  params->global_lut_id);
4027d76a60baSAnirudh Venkataramanan 
4028b6143c9bSPrzemek Kitszel 	flags = lut_type | glob_lut_idx | ice_lut_size_to_flag(lut_size);
4029b6143c9bSPrzemek Kitszel 	desc_params->flags = cpu_to_le16(flags);
4030d76a60baSAnirudh Venkataramanan 
4031b6143c9bSPrzemek Kitszel 	return ice_aq_send_cmd(hw, &desc, lut, lut_size, NULL);
4032d76a60baSAnirudh Venkataramanan }
4033d76a60baSAnirudh Venkataramanan 
4034d76a60baSAnirudh Venkataramanan /**
4035d76a60baSAnirudh Venkataramanan  * ice_aq_get_rss_lut
4036d76a60baSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
4037e3c53928SBrett Creeley  * @get_params: RSS LUT parameters used to specify which RSS LUT to get
4038d76a60baSAnirudh Venkataramanan  *
4039d76a60baSAnirudh Venkataramanan  * get the RSS lookup table, PF or VSI type
4040d76a60baSAnirudh Venkataramanan  */
40415e24d598STony Nguyen int
ice_aq_get_rss_lut(struct ice_hw * hw,struct ice_aq_get_set_rss_lut_params * get_params)4042e3c53928SBrett Creeley ice_aq_get_rss_lut(struct ice_hw *hw, struct ice_aq_get_set_rss_lut_params *get_params)
4043d76a60baSAnirudh Venkataramanan {
4044e3c53928SBrett Creeley 	return __ice_aq_get_set_rss_lut(hw, get_params, false);
4045d76a60baSAnirudh Venkataramanan }
4046d76a60baSAnirudh Venkataramanan 
4047d76a60baSAnirudh Venkataramanan /**
4048d76a60baSAnirudh Venkataramanan  * ice_aq_set_rss_lut
4049d76a60baSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
4050e3c53928SBrett Creeley  * @set_params: RSS LUT parameters used to specify how to set the RSS LUT
4051d76a60baSAnirudh Venkataramanan  *
4052d76a60baSAnirudh Venkataramanan  * set the RSS lookup table, PF or VSI type
4053d76a60baSAnirudh Venkataramanan  */
40545e24d598STony Nguyen int
ice_aq_set_rss_lut(struct ice_hw * hw,struct ice_aq_get_set_rss_lut_params * set_params)4055e3c53928SBrett Creeley ice_aq_set_rss_lut(struct ice_hw *hw, struct ice_aq_get_set_rss_lut_params *set_params)
4056d76a60baSAnirudh Venkataramanan {
4057e3c53928SBrett Creeley 	return __ice_aq_get_set_rss_lut(hw, set_params, true);
4058d76a60baSAnirudh Venkataramanan }
4059d76a60baSAnirudh Venkataramanan 
4060d76a60baSAnirudh Venkataramanan /**
4061d76a60baSAnirudh Venkataramanan  * __ice_aq_get_set_rss_key
4062f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
4063d76a60baSAnirudh Venkataramanan  * @vsi_id: VSI FW index
4064d76a60baSAnirudh Venkataramanan  * @key: pointer to key info struct
4065d76a60baSAnirudh Venkataramanan  * @set: set true to set the key, false to get the key
4066d76a60baSAnirudh Venkataramanan  *
4067d76a60baSAnirudh Venkataramanan  * get (0x0B04) or set (0x0B02) the RSS key per VSI
4068d76a60baSAnirudh Venkataramanan  */
40695518ac2aSTony Nguyen static int
__ice_aq_get_set_rss_key(struct ice_hw * hw,u16 vsi_id,struct ice_aqc_get_set_rss_keys * key,bool set)40705518ac2aSTony Nguyen __ice_aq_get_set_rss_key(struct ice_hw *hw, u16 vsi_id,
40715518ac2aSTony Nguyen 			 struct ice_aqc_get_set_rss_keys *key, bool set)
4072d76a60baSAnirudh Venkataramanan {
4073b6143c9bSPrzemek Kitszel 	struct ice_aqc_get_set_rss_key *desc_params;
4074d76a60baSAnirudh Venkataramanan 	u16 key_size = sizeof(*key);
4075d76a60baSAnirudh Venkataramanan 	struct ice_aq_desc desc;
4076d76a60baSAnirudh Venkataramanan 
4077d76a60baSAnirudh Venkataramanan 	if (set) {
4078d76a60baSAnirudh Venkataramanan 		ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_rss_key);
4079d76a60baSAnirudh Venkataramanan 		desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
4080d76a60baSAnirudh Venkataramanan 	} else {
4081d76a60baSAnirudh Venkataramanan 		ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_rss_key);
4082d76a60baSAnirudh Venkataramanan 	}
4083d76a60baSAnirudh Venkataramanan 
4084b6143c9bSPrzemek Kitszel 	desc_params = &desc.params.get_set_rss_key;
4085b6143c9bSPrzemek Kitszel 	desc_params->vsi_id = cpu_to_le16(vsi_id | ICE_AQC_RSS_VSI_VALID);
4086d76a60baSAnirudh Venkataramanan 
4087d76a60baSAnirudh Venkataramanan 	return ice_aq_send_cmd(hw, &desc, key, key_size, NULL);
4088d76a60baSAnirudh Venkataramanan }
4089d76a60baSAnirudh Venkataramanan 
4090d76a60baSAnirudh Venkataramanan /**
4091d76a60baSAnirudh Venkataramanan  * ice_aq_get_rss_key
4092f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
40934fb33f31SAnirudh Venkataramanan  * @vsi_handle: software VSI handle
4094d76a60baSAnirudh Venkataramanan  * @key: pointer to key info struct
4095d76a60baSAnirudh Venkataramanan  *
4096d76a60baSAnirudh Venkataramanan  * get the RSS key per VSI
4097d76a60baSAnirudh Venkataramanan  */
40985e24d598STony Nguyen int
ice_aq_get_rss_key(struct ice_hw * hw,u16 vsi_handle,struct ice_aqc_get_set_rss_keys * key)40994fb33f31SAnirudh Venkataramanan ice_aq_get_rss_key(struct ice_hw *hw, u16 vsi_handle,
4100d76a60baSAnirudh Venkataramanan 		   struct ice_aqc_get_set_rss_keys *key)
4101d76a60baSAnirudh Venkataramanan {
41024fb33f31SAnirudh Venkataramanan 	if (!ice_is_vsi_valid(hw, vsi_handle) || !key)
4103d54699e2STony Nguyen 		return -EINVAL;
41044fb33f31SAnirudh Venkataramanan 
41054fb33f31SAnirudh Venkataramanan 	return __ice_aq_get_set_rss_key(hw, ice_get_hw_vsi_num(hw, vsi_handle),
41064fb33f31SAnirudh Venkataramanan 					key, false);
4107d76a60baSAnirudh Venkataramanan }
4108d76a60baSAnirudh Venkataramanan 
4109d76a60baSAnirudh Venkataramanan /**
4110d76a60baSAnirudh Venkataramanan  * ice_aq_set_rss_key
4111f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
41124fb33f31SAnirudh Venkataramanan  * @vsi_handle: software VSI handle
4113d76a60baSAnirudh Venkataramanan  * @keys: pointer to key info struct
4114d76a60baSAnirudh Venkataramanan  *
4115d76a60baSAnirudh Venkataramanan  * set the RSS key per VSI
4116d76a60baSAnirudh Venkataramanan  */
41175e24d598STony Nguyen int
ice_aq_set_rss_key(struct ice_hw * hw,u16 vsi_handle,struct ice_aqc_get_set_rss_keys * keys)41184fb33f31SAnirudh Venkataramanan ice_aq_set_rss_key(struct ice_hw *hw, u16 vsi_handle,
4119d76a60baSAnirudh Venkataramanan 		   struct ice_aqc_get_set_rss_keys *keys)
4120d76a60baSAnirudh Venkataramanan {
41214fb33f31SAnirudh Venkataramanan 	if (!ice_is_vsi_valid(hw, vsi_handle) || !keys)
4122d54699e2STony Nguyen 		return -EINVAL;
41234fb33f31SAnirudh Venkataramanan 
41244fb33f31SAnirudh Venkataramanan 	return __ice_aq_get_set_rss_key(hw, ice_get_hw_vsi_num(hw, vsi_handle),
41254fb33f31SAnirudh Venkataramanan 					keys, true);
4126d76a60baSAnirudh Venkataramanan }
4127d76a60baSAnirudh Venkataramanan 
4128d76a60baSAnirudh Venkataramanan /**
4129cdedef59SAnirudh Venkataramanan  * ice_aq_add_lan_txq
4130cdedef59SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
4131cdedef59SAnirudh Venkataramanan  * @num_qgrps: Number of added queue groups
4132cdedef59SAnirudh Venkataramanan  * @qg_list: list of queue groups to be added
4133cdedef59SAnirudh Venkataramanan  * @buf_size: size of buffer for indirect command
4134cdedef59SAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
4135cdedef59SAnirudh Venkataramanan  *
4136cdedef59SAnirudh Venkataramanan  * Add Tx LAN queue (0x0C30)
4137cdedef59SAnirudh Venkataramanan  *
4138cdedef59SAnirudh Venkataramanan  * NOTE:
4139cdedef59SAnirudh Venkataramanan  * Prior to calling add Tx LAN queue:
4140cdedef59SAnirudh Venkataramanan  * Initialize the following as part of the Tx queue context:
4141cdedef59SAnirudh Venkataramanan  * Completion queue ID if the queue uses Completion queue, Quanta profile,
4142cdedef59SAnirudh Venkataramanan  * Cache profile and Packet shaper profile.
4143cdedef59SAnirudh Venkataramanan  *
4144cdedef59SAnirudh Venkataramanan  * After add Tx LAN queue AQ command is completed:
4145cdedef59SAnirudh Venkataramanan  * Interrupts should be associated with specific queues,
4146cdedef59SAnirudh Venkataramanan  * Association of Tx queue to Doorbell queue is not part of Add LAN Tx queue
4147cdedef59SAnirudh Venkataramanan  * flow.
4148cdedef59SAnirudh Venkataramanan  */
41495e24d598STony Nguyen static int
ice_aq_add_lan_txq(struct ice_hw * hw,u8 num_qgrps,struct ice_aqc_add_tx_qgrp * qg_list,u16 buf_size,struct ice_sq_cd * cd)4150cdedef59SAnirudh Venkataramanan ice_aq_add_lan_txq(struct ice_hw *hw, u8 num_qgrps,
4151cdedef59SAnirudh Venkataramanan 		   struct ice_aqc_add_tx_qgrp *qg_list, u16 buf_size,
4152cdedef59SAnirudh Venkataramanan 		   struct ice_sq_cd *cd)
4153cdedef59SAnirudh Venkataramanan {
4154cdedef59SAnirudh Venkataramanan 	struct ice_aqc_add_tx_qgrp *list;
4155cdedef59SAnirudh Venkataramanan 	struct ice_aqc_add_txqs *cmd;
4156cdedef59SAnirudh Venkataramanan 	struct ice_aq_desc desc;
415766486d89SBruce Allan 	u16 i, sum_size = 0;
4158cdedef59SAnirudh Venkataramanan 
4159cdedef59SAnirudh Venkataramanan 	cmd = &desc.params.add_txqs;
4160cdedef59SAnirudh Venkataramanan 
4161cdedef59SAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_txqs);
4162cdedef59SAnirudh Venkataramanan 
4163cdedef59SAnirudh Venkataramanan 	if (!qg_list)
4164d54699e2STony Nguyen 		return -EINVAL;
4165cdedef59SAnirudh Venkataramanan 
4166cdedef59SAnirudh Venkataramanan 	if (num_qgrps > ICE_LAN_TXQ_MAX_QGRPS)
4167d54699e2STony Nguyen 		return -EINVAL;
4168cdedef59SAnirudh Venkataramanan 
416966486d89SBruce Allan 	for (i = 0, list = qg_list; i < num_qgrps; i++) {
417066486d89SBruce Allan 		sum_size += struct_size(list, txqs, list->num_txqs);
417166486d89SBruce Allan 		list = (struct ice_aqc_add_tx_qgrp *)(list->txqs +
417266486d89SBruce Allan 						      list->num_txqs);
4173cdedef59SAnirudh Venkataramanan 	}
4174cdedef59SAnirudh Venkataramanan 
417566486d89SBruce Allan 	if (buf_size != sum_size)
4176d54699e2STony Nguyen 		return -EINVAL;
4177cdedef59SAnirudh Venkataramanan 
4178cdedef59SAnirudh Venkataramanan 	desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
4179cdedef59SAnirudh Venkataramanan 
4180cdedef59SAnirudh Venkataramanan 	cmd->num_qgrps = num_qgrps;
4181cdedef59SAnirudh Venkataramanan 
4182cdedef59SAnirudh Venkataramanan 	return ice_aq_send_cmd(hw, &desc, qg_list, buf_size, cd);
4183cdedef59SAnirudh Venkataramanan }
4184cdedef59SAnirudh Venkataramanan 
4185cdedef59SAnirudh Venkataramanan /**
4186cdedef59SAnirudh Venkataramanan  * ice_aq_dis_lan_txq
4187cdedef59SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
4188cdedef59SAnirudh Venkataramanan  * @num_qgrps: number of groups in the list
4189cdedef59SAnirudh Venkataramanan  * @qg_list: the list of groups to disable
4190cdedef59SAnirudh Venkataramanan  * @buf_size: the total size of the qg_list buffer in bytes
419194c4441bSAnirudh Venkataramanan  * @rst_src: if called due to reset, specifies the reset source
4192ddf30f7fSAnirudh Venkataramanan  * @vmvf_num: the relative VM or VF number that is undergoing the reset
4193cdedef59SAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
4194cdedef59SAnirudh Venkataramanan  *
4195cdedef59SAnirudh Venkataramanan  * Disable LAN Tx queue (0x0C31)
4196cdedef59SAnirudh Venkataramanan  */
41975e24d598STony Nguyen static int
ice_aq_dis_lan_txq(struct ice_hw * hw,u8 num_qgrps,struct ice_aqc_dis_txq_item * qg_list,u16 buf_size,enum ice_disq_rst_src rst_src,u16 vmvf_num,struct ice_sq_cd * cd)4198cdedef59SAnirudh Venkataramanan ice_aq_dis_lan_txq(struct ice_hw *hw, u8 num_qgrps,
4199cdedef59SAnirudh Venkataramanan 		   struct ice_aqc_dis_txq_item *qg_list, u16 buf_size,
4200ddf30f7fSAnirudh Venkataramanan 		   enum ice_disq_rst_src rst_src, u16 vmvf_num,
4201cdedef59SAnirudh Venkataramanan 		   struct ice_sq_cd *cd)
4202cdedef59SAnirudh Venkataramanan {
420366486d89SBruce Allan 	struct ice_aqc_dis_txq_item *item;
4204cdedef59SAnirudh Venkataramanan 	struct ice_aqc_dis_txqs *cmd;
4205cdedef59SAnirudh Venkataramanan 	struct ice_aq_desc desc;
4206cdedef59SAnirudh Venkataramanan 	u16 i, sz = 0;
42075518ac2aSTony Nguyen 	int status;
4208cdedef59SAnirudh Venkataramanan 
4209cdedef59SAnirudh Venkataramanan 	cmd = &desc.params.dis_txqs;
4210cdedef59SAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_dis_txqs);
4211cdedef59SAnirudh Venkataramanan 
4212ddf30f7fSAnirudh Venkataramanan 	/* qg_list can be NULL only in VM/VF reset flow */
4213ddf30f7fSAnirudh Venkataramanan 	if (!qg_list && !rst_src)
4214d54699e2STony Nguyen 		return -EINVAL;
4215cdedef59SAnirudh Venkataramanan 
4216cdedef59SAnirudh Venkataramanan 	if (num_qgrps > ICE_LAN_TXQ_MAX_QGRPS)
4217d54699e2STony Nguyen 		return -EINVAL;
4218ddf30f7fSAnirudh Venkataramanan 
4219cdedef59SAnirudh Venkataramanan 	cmd->num_entries = num_qgrps;
4220cdedef59SAnirudh Venkataramanan 
4221ddf30f7fSAnirudh Venkataramanan 	cmd->vmvf_and_timeout = cpu_to_le16((5 << ICE_AQC_Q_DIS_TIMEOUT_S) &
4222ddf30f7fSAnirudh Venkataramanan 					    ICE_AQC_Q_DIS_TIMEOUT_M);
4223ddf30f7fSAnirudh Venkataramanan 
4224ddf30f7fSAnirudh Venkataramanan 	switch (rst_src) {
4225ddf30f7fSAnirudh Venkataramanan 	case ICE_VM_RESET:
4226ddf30f7fSAnirudh Venkataramanan 		cmd->cmd_type = ICE_AQC_Q_DIS_CMD_VM_RESET;
4227ddf30f7fSAnirudh Venkataramanan 		cmd->vmvf_and_timeout |=
4228ddf30f7fSAnirudh Venkataramanan 			cpu_to_le16(vmvf_num & ICE_AQC_Q_DIS_VMVF_NUM_M);
4229ddf30f7fSAnirudh Venkataramanan 		break;
4230ddf30f7fSAnirudh Venkataramanan 	case ICE_VF_RESET:
4231ddf30f7fSAnirudh Venkataramanan 		cmd->cmd_type = ICE_AQC_Q_DIS_CMD_VF_RESET;
4232f9867df6SAnirudh Venkataramanan 		/* In this case, FW expects vmvf_num to be absolute VF ID */
4233ddf30f7fSAnirudh Venkataramanan 		cmd->vmvf_and_timeout |=
4234ddf30f7fSAnirudh Venkataramanan 			cpu_to_le16((vmvf_num + hw->func_caps.vf_base_id) &
4235ddf30f7fSAnirudh Venkataramanan 				    ICE_AQC_Q_DIS_VMVF_NUM_M);
4236ddf30f7fSAnirudh Venkataramanan 		break;
4237ddf30f7fSAnirudh Venkataramanan 	case ICE_NO_RESET:
4238ddf30f7fSAnirudh Venkataramanan 	default:
4239ddf30f7fSAnirudh Venkataramanan 		break;
4240ddf30f7fSAnirudh Venkataramanan 	}
4241ddf30f7fSAnirudh Venkataramanan 
42426e9650d5SVictor Raj 	/* flush pipe on time out */
42436e9650d5SVictor Raj 	cmd->cmd_type |= ICE_AQC_Q_DIS_CMD_FLUSH_PIPE;
4244ddf30f7fSAnirudh Venkataramanan 	/* If no queue group info, we are in a reset flow. Issue the AQ */
4245ddf30f7fSAnirudh Venkataramanan 	if (!qg_list)
4246ddf30f7fSAnirudh Venkataramanan 		goto do_aq;
4247ddf30f7fSAnirudh Venkataramanan 
4248ddf30f7fSAnirudh Venkataramanan 	/* set RD bit to indicate that command buffer is provided by the driver
4249ddf30f7fSAnirudh Venkataramanan 	 * and it needs to be read by the firmware
4250ddf30f7fSAnirudh Venkataramanan 	 */
4251ddf30f7fSAnirudh Venkataramanan 	desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
4252ddf30f7fSAnirudh Venkataramanan 
425366486d89SBruce Allan 	for (i = 0, item = qg_list; i < num_qgrps; i++) {
425466486d89SBruce Allan 		u16 item_size = struct_size(item, q_id, item->num_qs);
4255cdedef59SAnirudh Venkataramanan 
4256cdedef59SAnirudh Venkataramanan 		/* If the num of queues is even, add 2 bytes of padding */
425766486d89SBruce Allan 		if ((item->num_qs % 2) == 0)
425866486d89SBruce Allan 			item_size += 2;
425966486d89SBruce Allan 
426066486d89SBruce Allan 		sz += item_size;
426166486d89SBruce Allan 
426266486d89SBruce Allan 		item = (struct ice_aqc_dis_txq_item *)((u8 *)item + item_size);
4263cdedef59SAnirudh Venkataramanan 	}
4264cdedef59SAnirudh Venkataramanan 
4265cdedef59SAnirudh Venkataramanan 	if (buf_size != sz)
4266d54699e2STony Nguyen 		return -EINVAL;
4267cdedef59SAnirudh Venkataramanan 
4268ddf30f7fSAnirudh Venkataramanan do_aq:
42696e9650d5SVictor Raj 	status = ice_aq_send_cmd(hw, &desc, qg_list, buf_size, cd);
42706e9650d5SVictor Raj 	if (status) {
42716e9650d5SVictor Raj 		if (!qg_list)
42726e9650d5SVictor Raj 			ice_debug(hw, ICE_DBG_SCHED, "VM%d disable failed %d\n",
42736e9650d5SVictor Raj 				  vmvf_num, hw->adminq.sq_last_status);
42746e9650d5SVictor Raj 		else
42752f2da36eSAnirudh Venkataramanan 			ice_debug(hw, ICE_DBG_SCHED, "disable queue %d failed %d\n",
42766e9650d5SVictor Raj 				  le16_to_cpu(qg_list[0].q_id[0]),
42776e9650d5SVictor Raj 				  hw->adminq.sq_last_status);
42786e9650d5SVictor Raj 	}
42796e9650d5SVictor Raj 	return status;
4280cdedef59SAnirudh Venkataramanan }
4281cdedef59SAnirudh Venkataramanan 
4282348048e7SDave Ertman /**
428323ccae5cSDave Ertman  * ice_aq_cfg_lan_txq
428423ccae5cSDave Ertman  * @hw: pointer to the hardware structure
428523ccae5cSDave Ertman  * @buf: buffer for command
428623ccae5cSDave Ertman  * @buf_size: size of buffer in bytes
428723ccae5cSDave Ertman  * @num_qs: number of queues being configured
428823ccae5cSDave Ertman  * @oldport: origination lport
428923ccae5cSDave Ertman  * @newport: destination lport
429023ccae5cSDave Ertman  * @cd: pointer to command details structure or NULL
429123ccae5cSDave Ertman  *
429223ccae5cSDave Ertman  * Move/Configure LAN Tx queue (0x0C32)
429323ccae5cSDave Ertman  *
429423ccae5cSDave Ertman  * There is a better AQ command to use for moving nodes, so only coding
429523ccae5cSDave Ertman  * this one for configuring the node.
429623ccae5cSDave Ertman  */
429723ccae5cSDave Ertman int
ice_aq_cfg_lan_txq(struct ice_hw * hw,struct ice_aqc_cfg_txqs_buf * buf,u16 buf_size,u16 num_qs,u8 oldport,u8 newport,struct ice_sq_cd * cd)429823ccae5cSDave Ertman ice_aq_cfg_lan_txq(struct ice_hw *hw, struct ice_aqc_cfg_txqs_buf *buf,
429923ccae5cSDave Ertman 		   u16 buf_size, u16 num_qs, u8 oldport, u8 newport,
430023ccae5cSDave Ertman 		   struct ice_sq_cd *cd)
430123ccae5cSDave Ertman {
430223ccae5cSDave Ertman 	struct ice_aqc_cfg_txqs *cmd;
430323ccae5cSDave Ertman 	struct ice_aq_desc desc;
430423ccae5cSDave Ertman 	int status;
430523ccae5cSDave Ertman 
430623ccae5cSDave Ertman 	cmd = &desc.params.cfg_txqs;
430723ccae5cSDave Ertman 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_cfg_txqs);
430823ccae5cSDave Ertman 	desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
430923ccae5cSDave Ertman 
431023ccae5cSDave Ertman 	if (!buf)
431123ccae5cSDave Ertman 		return -EINVAL;
431223ccae5cSDave Ertman 
431323ccae5cSDave Ertman 	cmd->cmd_type = ICE_AQC_Q_CFG_TC_CHNG;
431423ccae5cSDave Ertman 	cmd->num_qs = num_qs;
431523ccae5cSDave Ertman 	cmd->port_num_chng = (oldport & ICE_AQC_Q_CFG_SRC_PRT_M);
431623ccae5cSDave Ertman 	cmd->port_num_chng |= (newport << ICE_AQC_Q_CFG_DST_PRT_S) &
431723ccae5cSDave Ertman 			      ICE_AQC_Q_CFG_DST_PRT_M;
431823ccae5cSDave Ertman 	cmd->time_out = (5 << ICE_AQC_Q_CFG_TIMEOUT_S) &
431923ccae5cSDave Ertman 			ICE_AQC_Q_CFG_TIMEOUT_M;
432023ccae5cSDave Ertman 	cmd->blocked_cgds = 0;
432123ccae5cSDave Ertman 
432223ccae5cSDave Ertman 	status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
432323ccae5cSDave Ertman 	if (status)
432423ccae5cSDave Ertman 		ice_debug(hw, ICE_DBG_SCHED, "Failed to reconfigure nodes %d\n",
432523ccae5cSDave Ertman 			  hw->adminq.sq_last_status);
432623ccae5cSDave Ertman 	return status;
432723ccae5cSDave Ertman }
432823ccae5cSDave Ertman 
432923ccae5cSDave Ertman /**
4330348048e7SDave Ertman  * ice_aq_add_rdma_qsets
4331348048e7SDave Ertman  * @hw: pointer to the hardware structure
4332348048e7SDave Ertman  * @num_qset_grps: Number of RDMA Qset groups
4333348048e7SDave Ertman  * @qset_list: list of Qset groups to be added
4334348048e7SDave Ertman  * @buf_size: size of buffer for indirect command
4335348048e7SDave Ertman  * @cd: pointer to command details structure or NULL
4336348048e7SDave Ertman  *
4337348048e7SDave Ertman  * Add Tx RDMA Qsets (0x0C33)
4338348048e7SDave Ertman  */
4339348048e7SDave Ertman static int
ice_aq_add_rdma_qsets(struct ice_hw * hw,u8 num_qset_grps,struct ice_aqc_add_rdma_qset_data * qset_list,u16 buf_size,struct ice_sq_cd * cd)4340348048e7SDave Ertman ice_aq_add_rdma_qsets(struct ice_hw *hw, u8 num_qset_grps,
4341348048e7SDave Ertman 		      struct ice_aqc_add_rdma_qset_data *qset_list,
4342348048e7SDave Ertman 		      u16 buf_size, struct ice_sq_cd *cd)
4343348048e7SDave Ertman {
4344348048e7SDave Ertman 	struct ice_aqc_add_rdma_qset_data *list;
4345348048e7SDave Ertman 	struct ice_aqc_add_rdma_qset *cmd;
4346348048e7SDave Ertman 	struct ice_aq_desc desc;
4347348048e7SDave Ertman 	u16 i, sum_size = 0;
4348348048e7SDave Ertman 
4349348048e7SDave Ertman 	cmd = &desc.params.add_rdma_qset;
4350348048e7SDave Ertman 
4351348048e7SDave Ertman 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_rdma_qset);
4352348048e7SDave Ertman 
4353348048e7SDave Ertman 	if (num_qset_grps > ICE_LAN_TXQ_MAX_QGRPS)
4354348048e7SDave Ertman 		return -EINVAL;
4355348048e7SDave Ertman 
4356348048e7SDave Ertman 	for (i = 0, list = qset_list; i < num_qset_grps; i++) {
4357348048e7SDave Ertman 		u16 num_qsets = le16_to_cpu(list->num_qsets);
4358348048e7SDave Ertman 
4359348048e7SDave Ertman 		sum_size += struct_size(list, rdma_qsets, num_qsets);
4360348048e7SDave Ertman 		list = (struct ice_aqc_add_rdma_qset_data *)(list->rdma_qsets +
4361348048e7SDave Ertman 							     num_qsets);
4362348048e7SDave Ertman 	}
4363348048e7SDave Ertman 
4364348048e7SDave Ertman 	if (buf_size != sum_size)
4365348048e7SDave Ertman 		return -EINVAL;
4366348048e7SDave Ertman 
4367348048e7SDave Ertman 	desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
4368348048e7SDave Ertman 
4369348048e7SDave Ertman 	cmd->num_qset_grps = num_qset_grps;
4370348048e7SDave Ertman 
4371d54699e2STony Nguyen 	return ice_aq_send_cmd(hw, &desc, qset_list, buf_size, cd);
4372348048e7SDave Ertman }
4373348048e7SDave Ertman 
4374cdedef59SAnirudh Venkataramanan /* End of FW Admin Queue command wrappers */
4375cdedef59SAnirudh Venkataramanan 
4376cdedef59SAnirudh Venkataramanan /**
4377cdedef59SAnirudh Venkataramanan  * ice_write_byte - write a byte to a packed context structure
4378cdedef59SAnirudh Venkataramanan  * @src_ctx:  the context structure to read from
4379cdedef59SAnirudh Venkataramanan  * @dest_ctx: the context to be written to
4380cdedef59SAnirudh Venkataramanan  * @ce_info:  a description of the struct to be filled
4381cdedef59SAnirudh Venkataramanan  */
4382c8b7abddSBruce Allan static void
ice_write_byte(u8 * src_ctx,u8 * dest_ctx,const struct ice_ctx_ele * ce_info)4383c8b7abddSBruce Allan ice_write_byte(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
4384cdedef59SAnirudh Venkataramanan {
4385cdedef59SAnirudh Venkataramanan 	u8 src_byte, dest_byte, mask;
4386cdedef59SAnirudh Venkataramanan 	u8 *from, *dest;
4387cdedef59SAnirudh Venkataramanan 	u16 shift_width;
4388cdedef59SAnirudh Venkataramanan 
4389cdedef59SAnirudh Venkataramanan 	/* copy from the next struct field */
4390cdedef59SAnirudh Venkataramanan 	from = src_ctx + ce_info->offset;
4391cdedef59SAnirudh Venkataramanan 
4392cdedef59SAnirudh Venkataramanan 	/* prepare the bits and mask */
4393cdedef59SAnirudh Venkataramanan 	shift_width = ce_info->lsb % 8;
4394cdedef59SAnirudh Venkataramanan 	mask = (u8)(BIT(ce_info->width) - 1);
4395cdedef59SAnirudh Venkataramanan 
4396cdedef59SAnirudh Venkataramanan 	src_byte = *from;
4397cdedef59SAnirudh Venkataramanan 	src_byte &= mask;
4398cdedef59SAnirudh Venkataramanan 
4399cdedef59SAnirudh Venkataramanan 	/* shift to correct alignment */
4400cdedef59SAnirudh Venkataramanan 	mask <<= shift_width;
4401cdedef59SAnirudh Venkataramanan 	src_byte <<= shift_width;
4402cdedef59SAnirudh Venkataramanan 
4403cdedef59SAnirudh Venkataramanan 	/* get the current bits from the target bit string */
4404cdedef59SAnirudh Venkataramanan 	dest = dest_ctx + (ce_info->lsb / 8);
4405cdedef59SAnirudh Venkataramanan 
4406cdedef59SAnirudh Venkataramanan 	memcpy(&dest_byte, dest, sizeof(dest_byte));
4407cdedef59SAnirudh Venkataramanan 
4408cdedef59SAnirudh Venkataramanan 	dest_byte &= ~mask;	/* get the bits not changing */
4409cdedef59SAnirudh Venkataramanan 	dest_byte |= src_byte;	/* add in the new bits */
4410cdedef59SAnirudh Venkataramanan 
4411cdedef59SAnirudh Venkataramanan 	/* put it all back */
4412cdedef59SAnirudh Venkataramanan 	memcpy(dest, &dest_byte, sizeof(dest_byte));
4413cdedef59SAnirudh Venkataramanan }
4414cdedef59SAnirudh Venkataramanan 
4415cdedef59SAnirudh Venkataramanan /**
4416cdedef59SAnirudh Venkataramanan  * ice_write_word - write a word to a packed context structure
4417cdedef59SAnirudh Venkataramanan  * @src_ctx:  the context structure to read from
4418cdedef59SAnirudh Venkataramanan  * @dest_ctx: the context to be written to
4419cdedef59SAnirudh Venkataramanan  * @ce_info:  a description of the struct to be filled
4420cdedef59SAnirudh Venkataramanan  */
4421c8b7abddSBruce Allan static void
ice_write_word(u8 * src_ctx,u8 * dest_ctx,const struct ice_ctx_ele * ce_info)4422c8b7abddSBruce Allan ice_write_word(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
4423cdedef59SAnirudh Venkataramanan {
4424cdedef59SAnirudh Venkataramanan 	u16 src_word, mask;
4425cdedef59SAnirudh Venkataramanan 	__le16 dest_word;
4426cdedef59SAnirudh Venkataramanan 	u8 *from, *dest;
4427cdedef59SAnirudh Venkataramanan 	u16 shift_width;
4428cdedef59SAnirudh Venkataramanan 
4429cdedef59SAnirudh Venkataramanan 	/* copy from the next struct field */
4430cdedef59SAnirudh Venkataramanan 	from = src_ctx + ce_info->offset;
4431cdedef59SAnirudh Venkataramanan 
4432cdedef59SAnirudh Venkataramanan 	/* prepare the bits and mask */
4433cdedef59SAnirudh Venkataramanan 	shift_width = ce_info->lsb % 8;
4434cdedef59SAnirudh Venkataramanan 	mask = BIT(ce_info->width) - 1;
4435cdedef59SAnirudh Venkataramanan 
4436cdedef59SAnirudh Venkataramanan 	/* don't swizzle the bits until after the mask because the mask bits
4437cdedef59SAnirudh Venkataramanan 	 * will be in a different bit position on big endian machines
4438cdedef59SAnirudh Venkataramanan 	 */
4439cdedef59SAnirudh Venkataramanan 	src_word = *(u16 *)from;
4440cdedef59SAnirudh Venkataramanan 	src_word &= mask;
4441cdedef59SAnirudh Venkataramanan 
4442cdedef59SAnirudh Venkataramanan 	/* shift to correct alignment */
4443cdedef59SAnirudh Venkataramanan 	mask <<= shift_width;
4444cdedef59SAnirudh Venkataramanan 	src_word <<= shift_width;
4445cdedef59SAnirudh Venkataramanan 
4446cdedef59SAnirudh Venkataramanan 	/* get the current bits from the target bit string */
4447cdedef59SAnirudh Venkataramanan 	dest = dest_ctx + (ce_info->lsb / 8);
4448cdedef59SAnirudh Venkataramanan 
4449cdedef59SAnirudh Venkataramanan 	memcpy(&dest_word, dest, sizeof(dest_word));
4450cdedef59SAnirudh Venkataramanan 
4451cdedef59SAnirudh Venkataramanan 	dest_word &= ~(cpu_to_le16(mask));	/* get the bits not changing */
4452cdedef59SAnirudh Venkataramanan 	dest_word |= cpu_to_le16(src_word);	/* add in the new bits */
4453cdedef59SAnirudh Venkataramanan 
4454cdedef59SAnirudh Venkataramanan 	/* put it all back */
4455cdedef59SAnirudh Venkataramanan 	memcpy(dest, &dest_word, sizeof(dest_word));
4456cdedef59SAnirudh Venkataramanan }
4457cdedef59SAnirudh Venkataramanan 
4458cdedef59SAnirudh Venkataramanan /**
4459cdedef59SAnirudh Venkataramanan  * ice_write_dword - write a dword to a packed context structure
4460cdedef59SAnirudh Venkataramanan  * @src_ctx:  the context structure to read from
4461cdedef59SAnirudh Venkataramanan  * @dest_ctx: the context to be written to
4462cdedef59SAnirudh Venkataramanan  * @ce_info:  a description of the struct to be filled
4463cdedef59SAnirudh Venkataramanan  */
4464c8b7abddSBruce Allan static void
ice_write_dword(u8 * src_ctx,u8 * dest_ctx,const struct ice_ctx_ele * ce_info)4465c8b7abddSBruce Allan ice_write_dword(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
4466cdedef59SAnirudh Venkataramanan {
4467cdedef59SAnirudh Venkataramanan 	u32 src_dword, mask;
4468cdedef59SAnirudh Venkataramanan 	__le32 dest_dword;
4469cdedef59SAnirudh Venkataramanan 	u8 *from, *dest;
4470cdedef59SAnirudh Venkataramanan 	u16 shift_width;
4471cdedef59SAnirudh Venkataramanan 
4472cdedef59SAnirudh Venkataramanan 	/* copy from the next struct field */
4473cdedef59SAnirudh Venkataramanan 	from = src_ctx + ce_info->offset;
4474cdedef59SAnirudh Venkataramanan 
4475cdedef59SAnirudh Venkataramanan 	/* prepare the bits and mask */
4476cdedef59SAnirudh Venkataramanan 	shift_width = ce_info->lsb % 8;
4477cdedef59SAnirudh Venkataramanan 
4478cdedef59SAnirudh Venkataramanan 	/* if the field width is exactly 32 on an x86 machine, then the shift
4479cdedef59SAnirudh Venkataramanan 	 * operation will not work because the SHL instructions count is masked
4480cdedef59SAnirudh Venkataramanan 	 * to 5 bits so the shift will do nothing
4481cdedef59SAnirudh Venkataramanan 	 */
4482cdedef59SAnirudh Venkataramanan 	if (ce_info->width < 32)
4483cdedef59SAnirudh Venkataramanan 		mask = BIT(ce_info->width) - 1;
4484cdedef59SAnirudh Venkataramanan 	else
4485cdedef59SAnirudh Venkataramanan 		mask = (u32)~0;
4486cdedef59SAnirudh Venkataramanan 
4487cdedef59SAnirudh Venkataramanan 	/* don't swizzle the bits until after the mask because the mask bits
4488cdedef59SAnirudh Venkataramanan 	 * will be in a different bit position on big endian machines
4489cdedef59SAnirudh Venkataramanan 	 */
4490cdedef59SAnirudh Venkataramanan 	src_dword = *(u32 *)from;
4491cdedef59SAnirudh Venkataramanan 	src_dword &= mask;
4492cdedef59SAnirudh Venkataramanan 
4493cdedef59SAnirudh Venkataramanan 	/* shift to correct alignment */
4494cdedef59SAnirudh Venkataramanan 	mask <<= shift_width;
4495cdedef59SAnirudh Venkataramanan 	src_dword <<= shift_width;
4496cdedef59SAnirudh Venkataramanan 
4497cdedef59SAnirudh Venkataramanan 	/* get the current bits from the target bit string */
4498cdedef59SAnirudh Venkataramanan 	dest = dest_ctx + (ce_info->lsb / 8);
4499cdedef59SAnirudh Venkataramanan 
4500cdedef59SAnirudh Venkataramanan 	memcpy(&dest_dword, dest, sizeof(dest_dword));
4501cdedef59SAnirudh Venkataramanan 
4502cdedef59SAnirudh Venkataramanan 	dest_dword &= ~(cpu_to_le32(mask));	/* get the bits not changing */
4503cdedef59SAnirudh Venkataramanan 	dest_dword |= cpu_to_le32(src_dword);	/* add in the new bits */
4504cdedef59SAnirudh Venkataramanan 
4505cdedef59SAnirudh Venkataramanan 	/* put it all back */
4506cdedef59SAnirudh Venkataramanan 	memcpy(dest, &dest_dword, sizeof(dest_dword));
4507cdedef59SAnirudh Venkataramanan }
4508cdedef59SAnirudh Venkataramanan 
4509cdedef59SAnirudh Venkataramanan /**
4510cdedef59SAnirudh Venkataramanan  * ice_write_qword - write a qword to a packed context structure
4511cdedef59SAnirudh Venkataramanan  * @src_ctx:  the context structure to read from
4512cdedef59SAnirudh Venkataramanan  * @dest_ctx: the context to be written to
4513cdedef59SAnirudh Venkataramanan  * @ce_info:  a description of the struct to be filled
4514cdedef59SAnirudh Venkataramanan  */
4515c8b7abddSBruce Allan static void
ice_write_qword(u8 * src_ctx,u8 * dest_ctx,const struct ice_ctx_ele * ce_info)4516c8b7abddSBruce Allan ice_write_qword(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
4517cdedef59SAnirudh Venkataramanan {
4518cdedef59SAnirudh Venkataramanan 	u64 src_qword, mask;
4519cdedef59SAnirudh Venkataramanan 	__le64 dest_qword;
4520cdedef59SAnirudh Venkataramanan 	u8 *from, *dest;
4521cdedef59SAnirudh Venkataramanan 	u16 shift_width;
4522cdedef59SAnirudh Venkataramanan 
4523cdedef59SAnirudh Venkataramanan 	/* copy from the next struct field */
4524cdedef59SAnirudh Venkataramanan 	from = src_ctx + ce_info->offset;
4525cdedef59SAnirudh Venkataramanan 
4526cdedef59SAnirudh Venkataramanan 	/* prepare the bits and mask */
4527cdedef59SAnirudh Venkataramanan 	shift_width = ce_info->lsb % 8;
4528cdedef59SAnirudh Venkataramanan 
4529cdedef59SAnirudh Venkataramanan 	/* if the field width is exactly 64 on an x86 machine, then the shift
4530cdedef59SAnirudh Venkataramanan 	 * operation will not work because the SHL instructions count is masked
4531cdedef59SAnirudh Venkataramanan 	 * to 6 bits so the shift will do nothing
4532cdedef59SAnirudh Venkataramanan 	 */
4533cdedef59SAnirudh Venkataramanan 	if (ce_info->width < 64)
4534cdedef59SAnirudh Venkataramanan 		mask = BIT_ULL(ce_info->width) - 1;
4535cdedef59SAnirudh Venkataramanan 	else
4536cdedef59SAnirudh Venkataramanan 		mask = (u64)~0;
4537cdedef59SAnirudh Venkataramanan 
4538cdedef59SAnirudh Venkataramanan 	/* don't swizzle the bits until after the mask because the mask bits
4539cdedef59SAnirudh Venkataramanan 	 * will be in a different bit position on big endian machines
4540cdedef59SAnirudh Venkataramanan 	 */
4541cdedef59SAnirudh Venkataramanan 	src_qword = *(u64 *)from;
4542cdedef59SAnirudh Venkataramanan 	src_qword &= mask;
4543cdedef59SAnirudh Venkataramanan 
4544cdedef59SAnirudh Venkataramanan 	/* shift to correct alignment */
4545cdedef59SAnirudh Venkataramanan 	mask <<= shift_width;
4546cdedef59SAnirudh Venkataramanan 	src_qword <<= shift_width;
4547cdedef59SAnirudh Venkataramanan 
4548cdedef59SAnirudh Venkataramanan 	/* get the current bits from the target bit string */
4549cdedef59SAnirudh Venkataramanan 	dest = dest_ctx + (ce_info->lsb / 8);
4550cdedef59SAnirudh Venkataramanan 
4551cdedef59SAnirudh Venkataramanan 	memcpy(&dest_qword, dest, sizeof(dest_qword));
4552cdedef59SAnirudh Venkataramanan 
4553cdedef59SAnirudh Venkataramanan 	dest_qword &= ~(cpu_to_le64(mask));	/* get the bits not changing */
4554cdedef59SAnirudh Venkataramanan 	dest_qword |= cpu_to_le64(src_qword);	/* add in the new bits */
4555cdedef59SAnirudh Venkataramanan 
4556cdedef59SAnirudh Venkataramanan 	/* put it all back */
4557cdedef59SAnirudh Venkataramanan 	memcpy(dest, &dest_qword, sizeof(dest_qword));
4558cdedef59SAnirudh Venkataramanan }
4559cdedef59SAnirudh Venkataramanan 
4560cdedef59SAnirudh Venkataramanan /**
4561cdedef59SAnirudh Venkataramanan  * ice_set_ctx - set context bits in packed structure
45627e34786aSBruce Allan  * @hw: pointer to the hardware structure
4563cdedef59SAnirudh Venkataramanan  * @src_ctx:  pointer to a generic non-packed context structure
4564cdedef59SAnirudh Venkataramanan  * @dest_ctx: pointer to memory for the packed structure
4565cdedef59SAnirudh Venkataramanan  * @ce_info:  a description of the structure to be transformed
4566cdedef59SAnirudh Venkataramanan  */
45675e24d598STony Nguyen int
ice_set_ctx(struct ice_hw * hw,u8 * src_ctx,u8 * dest_ctx,const struct ice_ctx_ele * ce_info)45687e34786aSBruce Allan ice_set_ctx(struct ice_hw *hw, u8 *src_ctx, u8 *dest_ctx,
45697e34786aSBruce Allan 	    const struct ice_ctx_ele *ce_info)
4570cdedef59SAnirudh Venkataramanan {
4571cdedef59SAnirudh Venkataramanan 	int f;
4572cdedef59SAnirudh Venkataramanan 
4573cdedef59SAnirudh Venkataramanan 	for (f = 0; ce_info[f].width; f++) {
4574cdedef59SAnirudh Venkataramanan 		/* We have to deal with each element of the FW response
4575cdedef59SAnirudh Venkataramanan 		 * using the correct size so that we are correct regardless
4576cdedef59SAnirudh Venkataramanan 		 * of the endianness of the machine.
4577cdedef59SAnirudh Venkataramanan 		 */
45787e34786aSBruce Allan 		if (ce_info[f].width > (ce_info[f].size_of * BITS_PER_BYTE)) {
45799228d8b2SJacob Keller 			ice_debug(hw, ICE_DBG_QCTX, "Field %d width of %d bits larger than size of %d byte(s) ... skipping write\n",
45807e34786aSBruce Allan 				  f, ce_info[f].width, ce_info[f].size_of);
45817e34786aSBruce Allan 			continue;
45827e34786aSBruce Allan 		}
4583cdedef59SAnirudh Venkataramanan 		switch (ce_info[f].size_of) {
4584cdedef59SAnirudh Venkataramanan 		case sizeof(u8):
4585cdedef59SAnirudh Venkataramanan 			ice_write_byte(src_ctx, dest_ctx, &ce_info[f]);
4586cdedef59SAnirudh Venkataramanan 			break;
4587cdedef59SAnirudh Venkataramanan 		case sizeof(u16):
4588cdedef59SAnirudh Venkataramanan 			ice_write_word(src_ctx, dest_ctx, &ce_info[f]);
4589cdedef59SAnirudh Venkataramanan 			break;
4590cdedef59SAnirudh Venkataramanan 		case sizeof(u32):
4591cdedef59SAnirudh Venkataramanan 			ice_write_dword(src_ctx, dest_ctx, &ce_info[f]);
4592cdedef59SAnirudh Venkataramanan 			break;
4593cdedef59SAnirudh Venkataramanan 		case sizeof(u64):
4594cdedef59SAnirudh Venkataramanan 			ice_write_qword(src_ctx, dest_ctx, &ce_info[f]);
4595cdedef59SAnirudh Venkataramanan 			break;
4596cdedef59SAnirudh Venkataramanan 		default:
4597d54699e2STony Nguyen 			return -EINVAL;
4598cdedef59SAnirudh Venkataramanan 		}
4599cdedef59SAnirudh Venkataramanan 	}
4600cdedef59SAnirudh Venkataramanan 
4601cdedef59SAnirudh Venkataramanan 	return 0;
4602cdedef59SAnirudh Venkataramanan }
4603cdedef59SAnirudh Venkataramanan 
4604cdedef59SAnirudh Venkataramanan /**
4605bb87ee0eSAnirudh Venkataramanan  * ice_get_lan_q_ctx - get the LAN queue context for the given VSI and TC
4606bb87ee0eSAnirudh Venkataramanan  * @hw: pointer to the HW struct
4607bb87ee0eSAnirudh Venkataramanan  * @vsi_handle: software VSI handle
4608bb87ee0eSAnirudh Venkataramanan  * @tc: TC number
4609bb87ee0eSAnirudh Venkataramanan  * @q_handle: software queue handle
4610bb87ee0eSAnirudh Venkataramanan  */
46111ddef455SUsha Ketineni struct ice_q_ctx *
ice_get_lan_q_ctx(struct ice_hw * hw,u16 vsi_handle,u8 tc,u16 q_handle)4612bb87ee0eSAnirudh Venkataramanan ice_get_lan_q_ctx(struct ice_hw *hw, u16 vsi_handle, u8 tc, u16 q_handle)
4613bb87ee0eSAnirudh Venkataramanan {
4614bb87ee0eSAnirudh Venkataramanan 	struct ice_vsi_ctx *vsi;
4615bb87ee0eSAnirudh Venkataramanan 	struct ice_q_ctx *q_ctx;
4616bb87ee0eSAnirudh Venkataramanan 
4617bb87ee0eSAnirudh Venkataramanan 	vsi = ice_get_vsi_ctx(hw, vsi_handle);
4618bb87ee0eSAnirudh Venkataramanan 	if (!vsi)
4619bb87ee0eSAnirudh Venkataramanan 		return NULL;
4620bb87ee0eSAnirudh Venkataramanan 	if (q_handle >= vsi->num_lan_q_entries[tc])
4621bb87ee0eSAnirudh Venkataramanan 		return NULL;
4622bb87ee0eSAnirudh Venkataramanan 	if (!vsi->lan_q_ctx[tc])
4623bb87ee0eSAnirudh Venkataramanan 		return NULL;
4624bb87ee0eSAnirudh Venkataramanan 	q_ctx = vsi->lan_q_ctx[tc];
4625bb87ee0eSAnirudh Venkataramanan 	return &q_ctx[q_handle];
4626bb87ee0eSAnirudh Venkataramanan }
4627bb87ee0eSAnirudh Venkataramanan 
4628bb87ee0eSAnirudh Venkataramanan /**
4629cdedef59SAnirudh Venkataramanan  * ice_ena_vsi_txq
4630cdedef59SAnirudh Venkataramanan  * @pi: port information structure
46314fb33f31SAnirudh Venkataramanan  * @vsi_handle: software VSI handle
4632f9867df6SAnirudh Venkataramanan  * @tc: TC number
4633bb87ee0eSAnirudh Venkataramanan  * @q_handle: software queue handle
4634cdedef59SAnirudh Venkataramanan  * @num_qgrps: Number of added queue groups
4635cdedef59SAnirudh Venkataramanan  * @buf: list of queue groups to be added
4636cdedef59SAnirudh Venkataramanan  * @buf_size: size of buffer for indirect command
4637cdedef59SAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
4638cdedef59SAnirudh Venkataramanan  *
4639f9867df6SAnirudh Venkataramanan  * This function adds one LAN queue
4640cdedef59SAnirudh Venkataramanan  */
46415e24d598STony Nguyen int
ice_ena_vsi_txq(struct ice_port_info * pi,u16 vsi_handle,u8 tc,u16 q_handle,u8 num_qgrps,struct ice_aqc_add_tx_qgrp * buf,u16 buf_size,struct ice_sq_cd * cd)4642bb87ee0eSAnirudh Venkataramanan ice_ena_vsi_txq(struct ice_port_info *pi, u16 vsi_handle, u8 tc, u16 q_handle,
4643bb87ee0eSAnirudh Venkataramanan 		u8 num_qgrps, struct ice_aqc_add_tx_qgrp *buf, u16 buf_size,
4644cdedef59SAnirudh Venkataramanan 		struct ice_sq_cd *cd)
4645cdedef59SAnirudh Venkataramanan {
4646cdedef59SAnirudh Venkataramanan 	struct ice_aqc_txsched_elem_data node = { 0 };
4647cdedef59SAnirudh Venkataramanan 	struct ice_sched_node *parent;
4648bb87ee0eSAnirudh Venkataramanan 	struct ice_q_ctx *q_ctx;
4649cdedef59SAnirudh Venkataramanan 	struct ice_hw *hw;
46505518ac2aSTony Nguyen 	int status;
4651cdedef59SAnirudh Venkataramanan 
4652cdedef59SAnirudh Venkataramanan 	if (!pi || pi->port_state != ICE_SCHED_PORT_STATE_READY)
4653d54699e2STony Nguyen 		return -EIO;
4654cdedef59SAnirudh Venkataramanan 
4655cdedef59SAnirudh Venkataramanan 	if (num_qgrps > 1 || buf->num_txqs > 1)
4656d54699e2STony Nguyen 		return -ENOSPC;
4657cdedef59SAnirudh Venkataramanan 
4658cdedef59SAnirudh Venkataramanan 	hw = pi->hw;
4659cdedef59SAnirudh Venkataramanan 
46604fb33f31SAnirudh Venkataramanan 	if (!ice_is_vsi_valid(hw, vsi_handle))
4661d54699e2STony Nguyen 		return -EINVAL;
46624fb33f31SAnirudh Venkataramanan 
4663cdedef59SAnirudh Venkataramanan 	mutex_lock(&pi->sched_lock);
4664cdedef59SAnirudh Venkataramanan 
4665bb87ee0eSAnirudh Venkataramanan 	q_ctx = ice_get_lan_q_ctx(hw, vsi_handle, tc, q_handle);
4666bb87ee0eSAnirudh Venkataramanan 	if (!q_ctx) {
4667bb87ee0eSAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_SCHED, "Enaq: invalid queue handle %d\n",
4668bb87ee0eSAnirudh Venkataramanan 			  q_handle);
4669d54699e2STony Nguyen 		status = -EINVAL;
4670bb87ee0eSAnirudh Venkataramanan 		goto ena_txq_exit;
4671bb87ee0eSAnirudh Venkataramanan 	}
4672bb87ee0eSAnirudh Venkataramanan 
4673cdedef59SAnirudh Venkataramanan 	/* find a parent node */
46744fb33f31SAnirudh Venkataramanan 	parent = ice_sched_get_free_qparent(pi, vsi_handle, tc,
4675cdedef59SAnirudh Venkataramanan 					    ICE_SCHED_NODE_OWNER_LAN);
4676cdedef59SAnirudh Venkataramanan 	if (!parent) {
4677d54699e2STony Nguyen 		status = -EINVAL;
4678cdedef59SAnirudh Venkataramanan 		goto ena_txq_exit;
4679cdedef59SAnirudh Venkataramanan 	}
46804fb33f31SAnirudh Venkataramanan 
4681cdedef59SAnirudh Venkataramanan 	buf->parent_teid = parent->info.node_teid;
4682cdedef59SAnirudh Venkataramanan 	node.parent_teid = parent->info.node_teid;
4683cdedef59SAnirudh Venkataramanan 	/* Mark that the values in the "generic" section as valid. The default
4684cdedef59SAnirudh Venkataramanan 	 * value in the "generic" section is zero. This means that :
4685cdedef59SAnirudh Venkataramanan 	 * - Scheduling mode is Bytes Per Second (BPS), indicated by Bit 0.
4686cdedef59SAnirudh Venkataramanan 	 * - 0 priority among siblings, indicated by Bit 1-3.
4687cdedef59SAnirudh Venkataramanan 	 * - WFQ, indicated by Bit 4.
4688cdedef59SAnirudh Venkataramanan 	 * - 0 Adjustment value is used in PSM credit update flow, indicated by
4689cdedef59SAnirudh Venkataramanan 	 * Bit 5-6.
4690cdedef59SAnirudh Venkataramanan 	 * - Bit 7 is reserved.
4691cdedef59SAnirudh Venkataramanan 	 * Without setting the generic section as valid in valid_sections, the
4692f9867df6SAnirudh Venkataramanan 	 * Admin queue command will fail with error code ICE_AQ_RC_EINVAL.
4693cdedef59SAnirudh Venkataramanan 	 */
4694984824a2STarun Singh 	buf->txqs[0].info.valid_sections =
4695984824a2STarun Singh 		ICE_AQC_ELEM_VALID_GENERIC | ICE_AQC_ELEM_VALID_CIR |
4696984824a2STarun Singh 		ICE_AQC_ELEM_VALID_EIR;
4697984824a2STarun Singh 	buf->txqs[0].info.generic = 0;
4698984824a2STarun Singh 	buf->txqs[0].info.cir_bw.bw_profile_idx =
4699984824a2STarun Singh 		cpu_to_le16(ICE_SCHED_DFLT_RL_PROF_ID);
4700984824a2STarun Singh 	buf->txqs[0].info.cir_bw.bw_alloc =
4701984824a2STarun Singh 		cpu_to_le16(ICE_SCHED_DFLT_BW_WT);
4702984824a2STarun Singh 	buf->txqs[0].info.eir_bw.bw_profile_idx =
4703984824a2STarun Singh 		cpu_to_le16(ICE_SCHED_DFLT_RL_PROF_ID);
4704984824a2STarun Singh 	buf->txqs[0].info.eir_bw.bw_alloc =
4705984824a2STarun Singh 		cpu_to_le16(ICE_SCHED_DFLT_BW_WT);
4706cdedef59SAnirudh Venkataramanan 
4707f9867df6SAnirudh Venkataramanan 	/* add the LAN queue */
4708cdedef59SAnirudh Venkataramanan 	status = ice_aq_add_lan_txq(hw, num_qgrps, buf, buf_size, cd);
47096e9650d5SVictor Raj 	if (status) {
4710bb87ee0eSAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_SCHED, "enable queue %d failed %d\n",
47116e9650d5SVictor Raj 			  le16_to_cpu(buf->txqs[0].txq_id),
47126e9650d5SVictor Raj 			  hw->adminq.sq_last_status);
4713cdedef59SAnirudh Venkataramanan 		goto ena_txq_exit;
47146e9650d5SVictor Raj 	}
4715cdedef59SAnirudh Venkataramanan 
4716cdedef59SAnirudh Venkataramanan 	node.node_teid = buf->txqs[0].q_teid;
4717cdedef59SAnirudh Venkataramanan 	node.data.elem_type = ICE_AQC_ELEM_TYPE_LEAF;
4718bb87ee0eSAnirudh Venkataramanan 	q_ctx->q_handle = q_handle;
47191ddef455SUsha Ketineni 	q_ctx->q_teid = le32_to_cpu(node.node_teid);
4720cdedef59SAnirudh Venkataramanan 
47211ddef455SUsha Ketineni 	/* add a leaf node into scheduler tree queue layer */
4722bdf96d96SMichal Wilczynski 	status = ice_sched_add_node(pi, hw->num_tx_sched_layers - 1, &node, NULL);
47231ddef455SUsha Ketineni 	if (!status)
47241ddef455SUsha Ketineni 		status = ice_sched_replay_q_bw(pi, q_ctx);
4725cdedef59SAnirudh Venkataramanan 
4726cdedef59SAnirudh Venkataramanan ena_txq_exit:
4727cdedef59SAnirudh Venkataramanan 	mutex_unlock(&pi->sched_lock);
4728cdedef59SAnirudh Venkataramanan 	return status;
4729cdedef59SAnirudh Venkataramanan }
4730cdedef59SAnirudh Venkataramanan 
4731cdedef59SAnirudh Venkataramanan /**
4732cdedef59SAnirudh Venkataramanan  * ice_dis_vsi_txq
4733cdedef59SAnirudh Venkataramanan  * @pi: port information structure
4734bb87ee0eSAnirudh Venkataramanan  * @vsi_handle: software VSI handle
4735bb87ee0eSAnirudh Venkataramanan  * @tc: TC number
4736cdedef59SAnirudh Venkataramanan  * @num_queues: number of queues
4737bb87ee0eSAnirudh Venkataramanan  * @q_handles: pointer to software queue handle array
4738cdedef59SAnirudh Venkataramanan  * @q_ids: pointer to the q_id array
4739cdedef59SAnirudh Venkataramanan  * @q_teids: pointer to queue node teids
474094c4441bSAnirudh Venkataramanan  * @rst_src: if called due to reset, specifies the reset source
4741ddf30f7fSAnirudh Venkataramanan  * @vmvf_num: the relative VM or VF number that is undergoing the reset
4742cdedef59SAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
4743cdedef59SAnirudh Venkataramanan  *
4744cdedef59SAnirudh Venkataramanan  * This function removes queues and their corresponding nodes in SW DB
4745cdedef59SAnirudh Venkataramanan  */
47465e24d598STony Nguyen int
ice_dis_vsi_txq(struct ice_port_info * pi,u16 vsi_handle,u8 tc,u8 num_queues,u16 * q_handles,u16 * q_ids,u32 * q_teids,enum ice_disq_rst_src rst_src,u16 vmvf_num,struct ice_sq_cd * cd)4747bb87ee0eSAnirudh Venkataramanan ice_dis_vsi_txq(struct ice_port_info *pi, u16 vsi_handle, u8 tc, u8 num_queues,
4748bb87ee0eSAnirudh Venkataramanan 		u16 *q_handles, u16 *q_ids, u32 *q_teids,
4749bb87ee0eSAnirudh Venkataramanan 		enum ice_disq_rst_src rst_src, u16 vmvf_num,
4750ddf30f7fSAnirudh Venkataramanan 		struct ice_sq_cd *cd)
4751cdedef59SAnirudh Venkataramanan {
475266486d89SBruce Allan 	struct ice_aqc_dis_txq_item *qg_list;
4753bb87ee0eSAnirudh Venkataramanan 	struct ice_q_ctx *q_ctx;
47545518ac2aSTony Nguyen 	int status = -ENOENT;
475566486d89SBruce Allan 	struct ice_hw *hw;
475666486d89SBruce Allan 	u16 i, buf_size;
4757cdedef59SAnirudh Venkataramanan 
4758cdedef59SAnirudh Venkataramanan 	if (!pi || pi->port_state != ICE_SCHED_PORT_STATE_READY)
4759d54699e2STony Nguyen 		return -EIO;
4760cdedef59SAnirudh Venkataramanan 
476166486d89SBruce Allan 	hw = pi->hw;
476266486d89SBruce Allan 
476385796d6eSAkeem G Abodunrin 	if (!num_queues) {
476485796d6eSAkeem G Abodunrin 		/* if queue is disabled already yet the disable queue command
476585796d6eSAkeem G Abodunrin 		 * has to be sent to complete the VF reset, then call
476685796d6eSAkeem G Abodunrin 		 * ice_aq_dis_lan_txq without any queue information
476785796d6eSAkeem G Abodunrin 		 */
476885796d6eSAkeem G Abodunrin 		if (rst_src)
476966486d89SBruce Allan 			return ice_aq_dis_lan_txq(hw, 0, NULL, 0, rst_src,
477085796d6eSAkeem G Abodunrin 						  vmvf_num, NULL);
4771d54699e2STony Nguyen 		return -EIO;
477285796d6eSAkeem G Abodunrin 	}
4773ddf30f7fSAnirudh Venkataramanan 
477466486d89SBruce Allan 	buf_size = struct_size(qg_list, q_id, 1);
477566486d89SBruce Allan 	qg_list = kzalloc(buf_size, GFP_KERNEL);
477666486d89SBruce Allan 	if (!qg_list)
4777d54699e2STony Nguyen 		return -ENOMEM;
477866486d89SBruce Allan 
4779cdedef59SAnirudh Venkataramanan 	mutex_lock(&pi->sched_lock);
4780cdedef59SAnirudh Venkataramanan 
4781cdedef59SAnirudh Venkataramanan 	for (i = 0; i < num_queues; i++) {
4782cdedef59SAnirudh Venkataramanan 		struct ice_sched_node *node;
4783cdedef59SAnirudh Venkataramanan 
4784cdedef59SAnirudh Venkataramanan 		node = ice_sched_find_node_by_teid(pi->root, q_teids[i]);
4785cdedef59SAnirudh Venkataramanan 		if (!node)
4786cdedef59SAnirudh Venkataramanan 			continue;
478766486d89SBruce Allan 		q_ctx = ice_get_lan_q_ctx(hw, vsi_handle, tc, q_handles[i]);
4788bb87ee0eSAnirudh Venkataramanan 		if (!q_ctx) {
478966486d89SBruce Allan 			ice_debug(hw, ICE_DBG_SCHED, "invalid queue handle%d\n",
4790bb87ee0eSAnirudh Venkataramanan 				  q_handles[i]);
4791bb87ee0eSAnirudh Venkataramanan 			continue;
4792bb87ee0eSAnirudh Venkataramanan 		}
4793bb87ee0eSAnirudh Venkataramanan 		if (q_ctx->q_handle != q_handles[i]) {
479466486d89SBruce Allan 			ice_debug(hw, ICE_DBG_SCHED, "Err:handles %d %d\n",
4795bb87ee0eSAnirudh Venkataramanan 				  q_ctx->q_handle, q_handles[i]);
4796bb87ee0eSAnirudh Venkataramanan 			continue;
4797bb87ee0eSAnirudh Venkataramanan 		}
479866486d89SBruce Allan 		qg_list->parent_teid = node->info.parent_teid;
479966486d89SBruce Allan 		qg_list->num_qs = 1;
480066486d89SBruce Allan 		qg_list->q_id[0] = cpu_to_le16(q_ids[i]);
480166486d89SBruce Allan 		status = ice_aq_dis_lan_txq(hw, 1, qg_list, buf_size, rst_src,
480266486d89SBruce Allan 					    vmvf_num, cd);
4803cdedef59SAnirudh Venkataramanan 
4804cdedef59SAnirudh Venkataramanan 		if (status)
4805cdedef59SAnirudh Venkataramanan 			break;
4806cdedef59SAnirudh Venkataramanan 		ice_free_sched_node(pi, node);
4807bb87ee0eSAnirudh Venkataramanan 		q_ctx->q_handle = ICE_INVAL_Q_HANDLE;
4808f3fbda33SJacob Keller 		q_ctx->q_teid = ICE_INVAL_TEID;
4809cdedef59SAnirudh Venkataramanan 	}
4810cdedef59SAnirudh Venkataramanan 	mutex_unlock(&pi->sched_lock);
481166486d89SBruce Allan 	kfree(qg_list);
4812cdedef59SAnirudh Venkataramanan 	return status;
4813cdedef59SAnirudh Venkataramanan }
48145513b920SAnirudh Venkataramanan 
48155513b920SAnirudh Venkataramanan /**
481694c4441bSAnirudh Venkataramanan  * ice_cfg_vsi_qs - configure the new/existing VSI queues
48175513b920SAnirudh Venkataramanan  * @pi: port information structure
48184fb33f31SAnirudh Venkataramanan  * @vsi_handle: software VSI handle
48195513b920SAnirudh Venkataramanan  * @tc_bitmap: TC bitmap
48205513b920SAnirudh Venkataramanan  * @maxqs: max queues array per TC
4821f9867df6SAnirudh Venkataramanan  * @owner: LAN or RDMA
48225513b920SAnirudh Venkataramanan  *
48235513b920SAnirudh Venkataramanan  * This function adds/updates the VSI queues per TC.
48245513b920SAnirudh Venkataramanan  */
48255e24d598STony Nguyen static int
ice_cfg_vsi_qs(struct ice_port_info * pi,u16 vsi_handle,u8 tc_bitmap,u16 * maxqs,u8 owner)48264fb33f31SAnirudh Venkataramanan ice_cfg_vsi_qs(struct ice_port_info *pi, u16 vsi_handle, u8 tc_bitmap,
48275513b920SAnirudh Venkataramanan 	       u16 *maxqs, u8 owner)
48285513b920SAnirudh Venkataramanan {
48295e24d598STony Nguyen 	int status = 0;
48305513b920SAnirudh Venkataramanan 	u8 i;
48315513b920SAnirudh Venkataramanan 
48325513b920SAnirudh Venkataramanan 	if (!pi || pi->port_state != ICE_SCHED_PORT_STATE_READY)
4833d54699e2STony Nguyen 		return -EIO;
48345513b920SAnirudh Venkataramanan 
48354fb33f31SAnirudh Venkataramanan 	if (!ice_is_vsi_valid(pi->hw, vsi_handle))
4836d54699e2STony Nguyen 		return -EINVAL;
48374fb33f31SAnirudh Venkataramanan 
48385513b920SAnirudh Venkataramanan 	mutex_lock(&pi->sched_lock);
48395513b920SAnirudh Venkataramanan 
48402bdc97beSBruce Allan 	ice_for_each_traffic_class(i) {
48415513b920SAnirudh Venkataramanan 		/* configuration is possible only if TC node is present */
48425513b920SAnirudh Venkataramanan 		if (!ice_sched_get_tc_node(pi, i))
48435513b920SAnirudh Venkataramanan 			continue;
48445513b920SAnirudh Venkataramanan 
48454fb33f31SAnirudh Venkataramanan 		status = ice_sched_cfg_vsi(pi, vsi_handle, i, maxqs[i], owner,
48465513b920SAnirudh Venkataramanan 					   ice_is_tc_ena(tc_bitmap, i));
48475513b920SAnirudh Venkataramanan 		if (status)
48485513b920SAnirudh Venkataramanan 			break;
48495513b920SAnirudh Venkataramanan 	}
48505513b920SAnirudh Venkataramanan 
48515513b920SAnirudh Venkataramanan 	mutex_unlock(&pi->sched_lock);
48525513b920SAnirudh Venkataramanan 	return status;
48535513b920SAnirudh Venkataramanan }
48545513b920SAnirudh Venkataramanan 
48555513b920SAnirudh Venkataramanan /**
4856f9867df6SAnirudh Venkataramanan  * ice_cfg_vsi_lan - configure VSI LAN queues
48575513b920SAnirudh Venkataramanan  * @pi: port information structure
48584fb33f31SAnirudh Venkataramanan  * @vsi_handle: software VSI handle
48595513b920SAnirudh Venkataramanan  * @tc_bitmap: TC bitmap
4860f9867df6SAnirudh Venkataramanan  * @max_lanqs: max LAN queues array per TC
48615513b920SAnirudh Venkataramanan  *
4862f9867df6SAnirudh Venkataramanan  * This function adds/updates the VSI LAN queues per TC.
48635513b920SAnirudh Venkataramanan  */
48645e24d598STony Nguyen int
ice_cfg_vsi_lan(struct ice_port_info * pi,u16 vsi_handle,u8 tc_bitmap,u16 * max_lanqs)48654fb33f31SAnirudh Venkataramanan ice_cfg_vsi_lan(struct ice_port_info *pi, u16 vsi_handle, u8 tc_bitmap,
48665513b920SAnirudh Venkataramanan 		u16 *max_lanqs)
48675513b920SAnirudh Venkataramanan {
48684fb33f31SAnirudh Venkataramanan 	return ice_cfg_vsi_qs(pi, vsi_handle, tc_bitmap, max_lanqs,
48695513b920SAnirudh Venkataramanan 			      ICE_SCHED_NODE_OWNER_LAN);
48705513b920SAnirudh Venkataramanan }
487145d3d428SAnirudh Venkataramanan 
487245d3d428SAnirudh Venkataramanan /**
4873348048e7SDave Ertman  * ice_cfg_vsi_rdma - configure the VSI RDMA queues
4874348048e7SDave Ertman  * @pi: port information structure
4875348048e7SDave Ertman  * @vsi_handle: software VSI handle
4876348048e7SDave Ertman  * @tc_bitmap: TC bitmap
4877348048e7SDave Ertman  * @max_rdmaqs: max RDMA queues array per TC
4878348048e7SDave Ertman  *
4879348048e7SDave Ertman  * This function adds/updates the VSI RDMA queues per TC.
4880348048e7SDave Ertman  */
4881348048e7SDave Ertman int
ice_cfg_vsi_rdma(struct ice_port_info * pi,u16 vsi_handle,u16 tc_bitmap,u16 * max_rdmaqs)4882348048e7SDave Ertman ice_cfg_vsi_rdma(struct ice_port_info *pi, u16 vsi_handle, u16 tc_bitmap,
4883348048e7SDave Ertman 		 u16 *max_rdmaqs)
4884348048e7SDave Ertman {
4885d54699e2STony Nguyen 	return ice_cfg_vsi_qs(pi, vsi_handle, tc_bitmap, max_rdmaqs,
4886d54699e2STony Nguyen 			      ICE_SCHED_NODE_OWNER_RDMA);
4887348048e7SDave Ertman }
4888348048e7SDave Ertman 
4889348048e7SDave Ertman /**
4890348048e7SDave Ertman  * ice_ena_vsi_rdma_qset
4891348048e7SDave Ertman  * @pi: port information structure
4892348048e7SDave Ertman  * @vsi_handle: software VSI handle
4893348048e7SDave Ertman  * @tc: TC number
4894348048e7SDave Ertman  * @rdma_qset: pointer to RDMA Qset
4895348048e7SDave Ertman  * @num_qsets: number of RDMA Qsets
4896348048e7SDave Ertman  * @qset_teid: pointer to Qset node TEIDs
4897348048e7SDave Ertman  *
4898348048e7SDave Ertman  * This function adds RDMA Qset
4899348048e7SDave Ertman  */
4900348048e7SDave Ertman int
ice_ena_vsi_rdma_qset(struct ice_port_info * pi,u16 vsi_handle,u8 tc,u16 * rdma_qset,u16 num_qsets,u32 * qset_teid)4901348048e7SDave Ertman ice_ena_vsi_rdma_qset(struct ice_port_info *pi, u16 vsi_handle, u8 tc,
4902348048e7SDave Ertman 		      u16 *rdma_qset, u16 num_qsets, u32 *qset_teid)
4903348048e7SDave Ertman {
4904348048e7SDave Ertman 	struct ice_aqc_txsched_elem_data node = { 0 };
4905348048e7SDave Ertman 	struct ice_aqc_add_rdma_qset_data *buf;
4906348048e7SDave Ertman 	struct ice_sched_node *parent;
4907348048e7SDave Ertman 	struct ice_hw *hw;
4908348048e7SDave Ertman 	u16 i, buf_size;
4909348048e7SDave Ertman 	int ret;
4910348048e7SDave Ertman 
4911348048e7SDave Ertman 	if (!pi || pi->port_state != ICE_SCHED_PORT_STATE_READY)
4912348048e7SDave Ertman 		return -EIO;
4913348048e7SDave Ertman 	hw = pi->hw;
4914348048e7SDave Ertman 
4915348048e7SDave Ertman 	if (!ice_is_vsi_valid(hw, vsi_handle))
4916348048e7SDave Ertman 		return -EINVAL;
4917348048e7SDave Ertman 
4918348048e7SDave Ertman 	buf_size = struct_size(buf, rdma_qsets, num_qsets);
4919348048e7SDave Ertman 	buf = kzalloc(buf_size, GFP_KERNEL);
4920348048e7SDave Ertman 	if (!buf)
4921348048e7SDave Ertman 		return -ENOMEM;
4922348048e7SDave Ertman 	mutex_lock(&pi->sched_lock);
4923348048e7SDave Ertman 
4924348048e7SDave Ertman 	parent = ice_sched_get_free_qparent(pi, vsi_handle, tc,
4925348048e7SDave Ertman 					    ICE_SCHED_NODE_OWNER_RDMA);
4926348048e7SDave Ertman 	if (!parent) {
4927348048e7SDave Ertman 		ret = -EINVAL;
4928348048e7SDave Ertman 		goto rdma_error_exit;
4929348048e7SDave Ertman 	}
4930348048e7SDave Ertman 	buf->parent_teid = parent->info.node_teid;
4931348048e7SDave Ertman 	node.parent_teid = parent->info.node_teid;
4932348048e7SDave Ertman 
4933348048e7SDave Ertman 	buf->num_qsets = cpu_to_le16(num_qsets);
4934348048e7SDave Ertman 	for (i = 0; i < num_qsets; i++) {
4935348048e7SDave Ertman 		buf->rdma_qsets[i].tx_qset_id = cpu_to_le16(rdma_qset[i]);
4936348048e7SDave Ertman 		buf->rdma_qsets[i].info.valid_sections =
4937348048e7SDave Ertman 			ICE_AQC_ELEM_VALID_GENERIC | ICE_AQC_ELEM_VALID_CIR |
4938348048e7SDave Ertman 			ICE_AQC_ELEM_VALID_EIR;
4939348048e7SDave Ertman 		buf->rdma_qsets[i].info.generic = 0;
4940348048e7SDave Ertman 		buf->rdma_qsets[i].info.cir_bw.bw_profile_idx =
4941348048e7SDave Ertman 			cpu_to_le16(ICE_SCHED_DFLT_RL_PROF_ID);
4942348048e7SDave Ertman 		buf->rdma_qsets[i].info.cir_bw.bw_alloc =
4943348048e7SDave Ertman 			cpu_to_le16(ICE_SCHED_DFLT_BW_WT);
4944348048e7SDave Ertman 		buf->rdma_qsets[i].info.eir_bw.bw_profile_idx =
4945348048e7SDave Ertman 			cpu_to_le16(ICE_SCHED_DFLT_RL_PROF_ID);
4946348048e7SDave Ertman 		buf->rdma_qsets[i].info.eir_bw.bw_alloc =
4947348048e7SDave Ertman 			cpu_to_le16(ICE_SCHED_DFLT_BW_WT);
4948348048e7SDave Ertman 	}
4949348048e7SDave Ertman 	ret = ice_aq_add_rdma_qsets(hw, 1, buf, buf_size, NULL);
4950348048e7SDave Ertman 	if (ret) {
4951348048e7SDave Ertman 		ice_debug(hw, ICE_DBG_RDMA, "add RDMA qset failed\n");
4952348048e7SDave Ertman 		goto rdma_error_exit;
4953348048e7SDave Ertman 	}
4954348048e7SDave Ertman 	node.data.elem_type = ICE_AQC_ELEM_TYPE_LEAF;
4955348048e7SDave Ertman 	for (i = 0; i < num_qsets; i++) {
4956348048e7SDave Ertman 		node.node_teid = buf->rdma_qsets[i].qset_teid;
49572ccc1c1cSTony Nguyen 		ret = ice_sched_add_node(pi, hw->num_tx_sched_layers - 1,
4958bdf96d96SMichal Wilczynski 					 &node, NULL);
49592ccc1c1cSTony Nguyen 		if (ret)
4960348048e7SDave Ertman 			break;
4961348048e7SDave Ertman 		qset_teid[i] = le32_to_cpu(node.node_teid);
4962348048e7SDave Ertman 	}
4963348048e7SDave Ertman rdma_error_exit:
4964348048e7SDave Ertman 	mutex_unlock(&pi->sched_lock);
4965348048e7SDave Ertman 	kfree(buf);
4966348048e7SDave Ertman 	return ret;
4967348048e7SDave Ertman }
4968348048e7SDave Ertman 
4969348048e7SDave Ertman /**
4970348048e7SDave Ertman  * ice_dis_vsi_rdma_qset - free RDMA resources
4971348048e7SDave Ertman  * @pi: port_info struct
4972348048e7SDave Ertman  * @count: number of RDMA Qsets to free
4973348048e7SDave Ertman  * @qset_teid: TEID of Qset node
4974348048e7SDave Ertman  * @q_id: list of queue IDs being disabled
4975348048e7SDave Ertman  */
4976348048e7SDave Ertman int
ice_dis_vsi_rdma_qset(struct ice_port_info * pi,u16 count,u32 * qset_teid,u16 * q_id)4977348048e7SDave Ertman ice_dis_vsi_rdma_qset(struct ice_port_info *pi, u16 count, u32 *qset_teid,
4978348048e7SDave Ertman 		      u16 *q_id)
4979348048e7SDave Ertman {
4980348048e7SDave Ertman 	struct ice_aqc_dis_txq_item *qg_list;
4981348048e7SDave Ertman 	struct ice_hw *hw;
49825518ac2aSTony Nguyen 	int status = 0;
4983348048e7SDave Ertman 	u16 qg_size;
4984348048e7SDave Ertman 	int i;
4985348048e7SDave Ertman 
4986348048e7SDave Ertman 	if (!pi || pi->port_state != ICE_SCHED_PORT_STATE_READY)
4987348048e7SDave Ertman 		return -EIO;
4988348048e7SDave Ertman 
4989348048e7SDave Ertman 	hw = pi->hw;
4990348048e7SDave Ertman 
4991348048e7SDave Ertman 	qg_size = struct_size(qg_list, q_id, 1);
4992348048e7SDave Ertman 	qg_list = kzalloc(qg_size, GFP_KERNEL);
4993348048e7SDave Ertman 	if (!qg_list)
4994348048e7SDave Ertman 		return -ENOMEM;
4995348048e7SDave Ertman 
4996348048e7SDave Ertman 	mutex_lock(&pi->sched_lock);
4997348048e7SDave Ertman 
4998348048e7SDave Ertman 	for (i = 0; i < count; i++) {
4999348048e7SDave Ertman 		struct ice_sched_node *node;
5000348048e7SDave Ertman 
5001348048e7SDave Ertman 		node = ice_sched_find_node_by_teid(pi->root, qset_teid[i]);
5002348048e7SDave Ertman 		if (!node)
5003348048e7SDave Ertman 			continue;
5004348048e7SDave Ertman 
5005348048e7SDave Ertman 		qg_list->parent_teid = node->info.parent_teid;
5006348048e7SDave Ertman 		qg_list->num_qs = 1;
5007348048e7SDave Ertman 		qg_list->q_id[0] =
5008348048e7SDave Ertman 			cpu_to_le16(q_id[i] |
5009348048e7SDave Ertman 				    ICE_AQC_Q_DIS_BUF_ELEM_TYPE_RDMA_QSET);
5010348048e7SDave Ertman 
5011348048e7SDave Ertman 		status = ice_aq_dis_lan_txq(hw, 1, qg_list, qg_size,
5012348048e7SDave Ertman 					    ICE_NO_RESET, 0, NULL);
5013348048e7SDave Ertman 		if (status)
5014348048e7SDave Ertman 			break;
5015348048e7SDave Ertman 
5016348048e7SDave Ertman 		ice_free_sched_node(pi, node);
5017348048e7SDave Ertman 	}
5018348048e7SDave Ertman 
5019348048e7SDave Ertman 	mutex_unlock(&pi->sched_lock);
5020348048e7SDave Ertman 	kfree(qg_list);
5021d54699e2STony Nguyen 	return status;
5022348048e7SDave Ertman }
5023348048e7SDave Ertman 
5024348048e7SDave Ertman /**
5025334cb062SAnirudh Venkataramanan  * ice_replay_pre_init - replay pre initialization
5026f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
5027334cb062SAnirudh Venkataramanan  *
5028334cb062SAnirudh Venkataramanan  * Initializes required config data for VSI, FD, ACL, and RSS before replay.
5029334cb062SAnirudh Venkataramanan  */
ice_replay_pre_init(struct ice_hw * hw)50305e24d598STony Nguyen static int ice_replay_pre_init(struct ice_hw *hw)
5031334cb062SAnirudh Venkataramanan {
5032334cb062SAnirudh Venkataramanan 	struct ice_switch_info *sw = hw->switch_info;
5033334cb062SAnirudh Venkataramanan 	u8 i;
5034334cb062SAnirudh Venkataramanan 
5035334cb062SAnirudh Venkataramanan 	/* Delete old entries from replay filter list head if there is any */
5036334cb062SAnirudh Venkataramanan 	ice_rm_all_sw_replay_rule_info(hw);
5037334cb062SAnirudh Venkataramanan 	/* In start of replay, move entries into replay_rules list, it
5038334cb062SAnirudh Venkataramanan 	 * will allow adding rules entries back to filt_rules list,
5039334cb062SAnirudh Venkataramanan 	 * which is operational list.
5040334cb062SAnirudh Venkataramanan 	 */
5041c36a2b97SVictor Raj 	for (i = 0; i < ICE_MAX_NUM_RECIPES; i++)
5042334cb062SAnirudh Venkataramanan 		list_replace_init(&sw->recp_list[i].filt_rules,
5043334cb062SAnirudh Venkataramanan 				  &sw->recp_list[i].filt_replay_rules);
5044b126bd6bSKiran Patil 	ice_sched_replay_agg_vsi_preinit(hw);
5045334cb062SAnirudh Venkataramanan 
5046334cb062SAnirudh Venkataramanan 	return 0;
5047334cb062SAnirudh Venkataramanan }
5048334cb062SAnirudh Venkataramanan 
5049334cb062SAnirudh Venkataramanan /**
5050334cb062SAnirudh Venkataramanan  * ice_replay_vsi - replay VSI configuration
5051f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
5052334cb062SAnirudh Venkataramanan  * @vsi_handle: driver VSI handle
5053334cb062SAnirudh Venkataramanan  *
5054334cb062SAnirudh Venkataramanan  * Restore all VSI configuration after reset. It is required to call this
5055334cb062SAnirudh Venkataramanan  * function with main VSI first.
5056334cb062SAnirudh Venkataramanan  */
ice_replay_vsi(struct ice_hw * hw,u16 vsi_handle)50575e24d598STony Nguyen int ice_replay_vsi(struct ice_hw *hw, u16 vsi_handle)
5058334cb062SAnirudh Venkataramanan {
50595e24d598STony Nguyen 	int status;
5060334cb062SAnirudh Venkataramanan 
5061334cb062SAnirudh Venkataramanan 	if (!ice_is_vsi_valid(hw, vsi_handle))
5062d54699e2STony Nguyen 		return -EINVAL;
5063334cb062SAnirudh Venkataramanan 
5064334cb062SAnirudh Venkataramanan 	/* Replay pre-initialization if there is any */
5065334cb062SAnirudh Venkataramanan 	if (vsi_handle == ICE_MAIN_VSI_HANDLE) {
5066334cb062SAnirudh Venkataramanan 		status = ice_replay_pre_init(hw);
5067334cb062SAnirudh Venkataramanan 		if (status)
5068334cb062SAnirudh Venkataramanan 			return status;
5069334cb062SAnirudh Venkataramanan 	}
5070c90ed40cSTony Nguyen 	/* Replay per VSI all RSS configurations */
5071c90ed40cSTony Nguyen 	status = ice_replay_rss_cfg(hw, vsi_handle);
5072c90ed40cSTony Nguyen 	if (status)
5073c90ed40cSTony Nguyen 		return status;
5074334cb062SAnirudh Venkataramanan 	/* Replay per VSI all filters */
5075334cb062SAnirudh Venkataramanan 	status = ice_replay_vsi_all_fltr(hw, vsi_handle);
5076b126bd6bSKiran Patil 	if (!status)
5077b126bd6bSKiran Patil 		status = ice_replay_vsi_agg(hw, vsi_handle);
5078334cb062SAnirudh Venkataramanan 	return status;
5079334cb062SAnirudh Venkataramanan }
5080334cb062SAnirudh Venkataramanan 
5081334cb062SAnirudh Venkataramanan /**
5082334cb062SAnirudh Venkataramanan  * ice_replay_post - post replay configuration cleanup
5083f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
5084334cb062SAnirudh Venkataramanan  *
5085334cb062SAnirudh Venkataramanan  * Post replay cleanup.
5086334cb062SAnirudh Venkataramanan  */
ice_replay_post(struct ice_hw * hw)5087334cb062SAnirudh Venkataramanan void ice_replay_post(struct ice_hw *hw)
5088334cb062SAnirudh Venkataramanan {
5089334cb062SAnirudh Venkataramanan 	/* Delete old entries from replay filter list head */
5090334cb062SAnirudh Venkataramanan 	ice_rm_all_sw_replay_rule_info(hw);
5091b126bd6bSKiran Patil 	ice_sched_replay_agg(hw);
5092334cb062SAnirudh Venkataramanan }
5093334cb062SAnirudh Venkataramanan 
5094334cb062SAnirudh Venkataramanan /**
509545d3d428SAnirudh Venkataramanan  * ice_stat_update40 - read 40 bit stat from the chip and update stat values
509645d3d428SAnirudh Venkataramanan  * @hw: ptr to the hardware info
509736517fd3SJacob Keller  * @reg: offset of 64 bit HW register to read from
509845d3d428SAnirudh Venkataramanan  * @prev_stat_loaded: bool to specify if previous stats are loaded
509945d3d428SAnirudh Venkataramanan  * @prev_stat: ptr to previous loaded stat value
510045d3d428SAnirudh Venkataramanan  * @cur_stat: ptr to current stat value
510145d3d428SAnirudh Venkataramanan  */
5102c8b7abddSBruce Allan void
ice_stat_update40(struct ice_hw * hw,u32 reg,bool prev_stat_loaded,u64 * prev_stat,u64 * cur_stat)510336517fd3SJacob Keller ice_stat_update40(struct ice_hw *hw, u32 reg, bool prev_stat_loaded,
510436517fd3SJacob Keller 		  u64 *prev_stat, u64 *cur_stat)
510545d3d428SAnirudh Venkataramanan {
510636517fd3SJacob Keller 	u64 new_data = rd64(hw, reg) & (BIT_ULL(40) - 1);
510745d3d428SAnirudh Venkataramanan 
510845d3d428SAnirudh Venkataramanan 	/* device stats are not reset at PFR, they likely will not be zeroed
510936517fd3SJacob Keller 	 * when the driver starts. Thus, save the value from the first read
511036517fd3SJacob Keller 	 * without adding to the statistic value so that we report stats which
511136517fd3SJacob Keller 	 * count up from zero.
511245d3d428SAnirudh Venkataramanan 	 */
511336517fd3SJacob Keller 	if (!prev_stat_loaded) {
511445d3d428SAnirudh Venkataramanan 		*prev_stat = new_data;
511536517fd3SJacob Keller 		return;
511636517fd3SJacob Keller 	}
511736517fd3SJacob Keller 
511836517fd3SJacob Keller 	/* Calculate the difference between the new and old values, and then
511936517fd3SJacob Keller 	 * add it to the software stat value.
512036517fd3SJacob Keller 	 */
512145d3d428SAnirudh Venkataramanan 	if (new_data >= *prev_stat)
512236517fd3SJacob Keller 		*cur_stat += new_data - *prev_stat;
512345d3d428SAnirudh Venkataramanan 	else
512445d3d428SAnirudh Venkataramanan 		/* to manage the potential roll-over */
512536517fd3SJacob Keller 		*cur_stat += (new_data + BIT_ULL(40)) - *prev_stat;
512636517fd3SJacob Keller 
512736517fd3SJacob Keller 	/* Update the previously stored value to prepare for next read */
512836517fd3SJacob Keller 	*prev_stat = new_data;
512945d3d428SAnirudh Venkataramanan }
513045d3d428SAnirudh Venkataramanan 
513145d3d428SAnirudh Venkataramanan /**
513245d3d428SAnirudh Venkataramanan  * ice_stat_update32 - read 32 bit stat from the chip and update stat values
513345d3d428SAnirudh Venkataramanan  * @hw: ptr to the hardware info
513436517fd3SJacob Keller  * @reg: offset of HW register to read from
513545d3d428SAnirudh Venkataramanan  * @prev_stat_loaded: bool to specify if previous stats are loaded
513645d3d428SAnirudh Venkataramanan  * @prev_stat: ptr to previous loaded stat value
513745d3d428SAnirudh Venkataramanan  * @cur_stat: ptr to current stat value
513845d3d428SAnirudh Venkataramanan  */
5139c8b7abddSBruce Allan void
ice_stat_update32(struct ice_hw * hw,u32 reg,bool prev_stat_loaded,u64 * prev_stat,u64 * cur_stat)5140c8b7abddSBruce Allan ice_stat_update32(struct ice_hw *hw, u32 reg, bool prev_stat_loaded,
514145d3d428SAnirudh Venkataramanan 		  u64 *prev_stat, u64 *cur_stat)
514245d3d428SAnirudh Venkataramanan {
514345d3d428SAnirudh Venkataramanan 	u32 new_data;
514445d3d428SAnirudh Venkataramanan 
514545d3d428SAnirudh Venkataramanan 	new_data = rd32(hw, reg);
514645d3d428SAnirudh Venkataramanan 
514745d3d428SAnirudh Venkataramanan 	/* device stats are not reset at PFR, they likely will not be zeroed
514836517fd3SJacob Keller 	 * when the driver starts. Thus, save the value from the first read
514936517fd3SJacob Keller 	 * without adding to the statistic value so that we report stats which
515036517fd3SJacob Keller 	 * count up from zero.
515145d3d428SAnirudh Venkataramanan 	 */
515236517fd3SJacob Keller 	if (!prev_stat_loaded) {
515345d3d428SAnirudh Venkataramanan 		*prev_stat = new_data;
515436517fd3SJacob Keller 		return;
515536517fd3SJacob Keller 	}
515636517fd3SJacob Keller 
515736517fd3SJacob Keller 	/* Calculate the difference between the new and old values, and then
515836517fd3SJacob Keller 	 * add it to the software stat value.
515936517fd3SJacob Keller 	 */
516045d3d428SAnirudh Venkataramanan 	if (new_data >= *prev_stat)
516136517fd3SJacob Keller 		*cur_stat += new_data - *prev_stat;
516245d3d428SAnirudh Venkataramanan 	else
516345d3d428SAnirudh Venkataramanan 		/* to manage the potential roll-over */
516436517fd3SJacob Keller 		*cur_stat += (new_data + BIT_ULL(32)) - *prev_stat;
516536517fd3SJacob Keller 
516636517fd3SJacob Keller 	/* Update the previously stored value to prepare for next read */
516736517fd3SJacob Keller 	*prev_stat = new_data;
516845d3d428SAnirudh Venkataramanan }
51697b9ffc76SAnirudh Venkataramanan 
51707b9ffc76SAnirudh Venkataramanan /**
51717b9ffc76SAnirudh Venkataramanan  * ice_sched_query_elem - query element information from HW
51727b9ffc76SAnirudh Venkataramanan  * @hw: pointer to the HW struct
51737b9ffc76SAnirudh Venkataramanan  * @node_teid: node TEID to be queried
51747b9ffc76SAnirudh Venkataramanan  * @buf: buffer to element information
51757b9ffc76SAnirudh Venkataramanan  *
51767b9ffc76SAnirudh Venkataramanan  * This function queries HW element information
51777b9ffc76SAnirudh Venkataramanan  */
51785e24d598STony Nguyen int
ice_sched_query_elem(struct ice_hw * hw,u32 node_teid,struct ice_aqc_txsched_elem_data * buf)51797b9ffc76SAnirudh Venkataramanan ice_sched_query_elem(struct ice_hw *hw, u32 node_teid,
5180b3c38904SBruce Allan 		     struct ice_aqc_txsched_elem_data *buf)
51817b9ffc76SAnirudh Venkataramanan {
51827b9ffc76SAnirudh Venkataramanan 	u16 buf_size, num_elem_ret = 0;
51835e24d598STony Nguyen 	int status;
51847b9ffc76SAnirudh Venkataramanan 
51857b9ffc76SAnirudh Venkataramanan 	buf_size = sizeof(*buf);
51867b9ffc76SAnirudh Venkataramanan 	memset(buf, 0, buf_size);
5187b3c38904SBruce Allan 	buf->node_teid = cpu_to_le32(node_teid);
51887b9ffc76SAnirudh Venkataramanan 	status = ice_aq_query_sched_elems(hw, 1, buf, buf_size, &num_elem_ret,
51897b9ffc76SAnirudh Venkataramanan 					  NULL);
51907b9ffc76SAnirudh Venkataramanan 	if (status || num_elem_ret != 1)
51917b9ffc76SAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_SCHED, "query element failed\n");
51927b9ffc76SAnirudh Venkataramanan 	return status;
51937b9ffc76SAnirudh Venkataramanan }
5194ea78ce4dSPaul Greenwalt 
5195ea78ce4dSPaul Greenwalt /**
519643113ff7SKarol Kolacinski  * ice_aq_read_i2c
519743113ff7SKarol Kolacinski  * @hw: pointer to the hw struct
519843113ff7SKarol Kolacinski  * @topo_addr: topology address for a device to communicate with
519943113ff7SKarol Kolacinski  * @bus_addr: 7-bit I2C bus address
520043113ff7SKarol Kolacinski  * @addr: I2C memory address (I2C offset) with up to 16 bits
520143113ff7SKarol Kolacinski  * @params: I2C parameters: bit [7] - Repeated start,
520243113ff7SKarol Kolacinski  *			    bits [6:5] data offset size,
520343113ff7SKarol Kolacinski  *			    bit [4] - I2C address type,
520443113ff7SKarol Kolacinski  *			    bits [3:0] - data size to read (0-16 bytes)
520543113ff7SKarol Kolacinski  * @data: pointer to data (0 to 16 bytes) to be read from the I2C device
520643113ff7SKarol Kolacinski  * @cd: pointer to command details structure or NULL
520743113ff7SKarol Kolacinski  *
520843113ff7SKarol Kolacinski  * Read I2C (0x06E2)
520943113ff7SKarol Kolacinski  */
521043113ff7SKarol Kolacinski int
ice_aq_read_i2c(struct ice_hw * hw,struct ice_aqc_link_topo_addr topo_addr,u16 bus_addr,__le16 addr,u8 params,u8 * data,struct ice_sq_cd * cd)521143113ff7SKarol Kolacinski ice_aq_read_i2c(struct ice_hw *hw, struct ice_aqc_link_topo_addr topo_addr,
521243113ff7SKarol Kolacinski 		u16 bus_addr, __le16 addr, u8 params, u8 *data,
521343113ff7SKarol Kolacinski 		struct ice_sq_cd *cd)
521443113ff7SKarol Kolacinski {
521543113ff7SKarol Kolacinski 	struct ice_aq_desc desc = { 0 };
521643113ff7SKarol Kolacinski 	struct ice_aqc_i2c *cmd;
521743113ff7SKarol Kolacinski 	u8 data_size;
521843113ff7SKarol Kolacinski 	int status;
521943113ff7SKarol Kolacinski 
522043113ff7SKarol Kolacinski 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_read_i2c);
5221fcf9b695SKarol Kolacinski 	cmd = &desc.params.read_write_i2c;
522243113ff7SKarol Kolacinski 
522343113ff7SKarol Kolacinski 	if (!data)
522443113ff7SKarol Kolacinski 		return -EINVAL;
522543113ff7SKarol Kolacinski 
522643113ff7SKarol Kolacinski 	data_size = FIELD_GET(ICE_AQC_I2C_DATA_SIZE_M, params);
522743113ff7SKarol Kolacinski 
522843113ff7SKarol Kolacinski 	cmd->i2c_bus_addr = cpu_to_le16(bus_addr);
522943113ff7SKarol Kolacinski 	cmd->topo_addr = topo_addr;
523043113ff7SKarol Kolacinski 	cmd->i2c_params = params;
523143113ff7SKarol Kolacinski 	cmd->i2c_addr = addr;
523243113ff7SKarol Kolacinski 
523343113ff7SKarol Kolacinski 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
523443113ff7SKarol Kolacinski 	if (!status) {
523543113ff7SKarol Kolacinski 		struct ice_aqc_read_i2c_resp *resp;
523643113ff7SKarol Kolacinski 		u8 i;
523743113ff7SKarol Kolacinski 
523843113ff7SKarol Kolacinski 		resp = &desc.params.read_i2c_resp;
523943113ff7SKarol Kolacinski 		for (i = 0; i < data_size; i++) {
524043113ff7SKarol Kolacinski 			*data = resp->i2c_data[i];
524143113ff7SKarol Kolacinski 			data++;
524243113ff7SKarol Kolacinski 		}
524343113ff7SKarol Kolacinski 	}
524443113ff7SKarol Kolacinski 
524543113ff7SKarol Kolacinski 	return status;
524643113ff7SKarol Kolacinski }
524743113ff7SKarol Kolacinski 
524843113ff7SKarol Kolacinski /**
5249fcf9b695SKarol Kolacinski  * ice_aq_write_i2c
5250fcf9b695SKarol Kolacinski  * @hw: pointer to the hw struct
5251fcf9b695SKarol Kolacinski  * @topo_addr: topology address for a device to communicate with
5252fcf9b695SKarol Kolacinski  * @bus_addr: 7-bit I2C bus address
5253fcf9b695SKarol Kolacinski  * @addr: I2C memory address (I2C offset) with up to 16 bits
5254fcf9b695SKarol Kolacinski  * @params: I2C parameters: bit [4] - I2C address type, bits [3:0] - data size to write (0-7 bytes)
5255fcf9b695SKarol Kolacinski  * @data: pointer to data (0 to 4 bytes) to be written to the I2C device
5256fcf9b695SKarol Kolacinski  * @cd: pointer to command details structure or NULL
5257fcf9b695SKarol Kolacinski  *
5258fcf9b695SKarol Kolacinski  * Write I2C (0x06E3)
5259fcf9b695SKarol Kolacinski  *
5260fcf9b695SKarol Kolacinski  * * Return:
5261fcf9b695SKarol Kolacinski  * * 0             - Successful write to the i2c device
5262fcf9b695SKarol Kolacinski  * * -EINVAL       - Data size greater than 4 bytes
5263fcf9b695SKarol Kolacinski  * * -EIO          - FW error
5264fcf9b695SKarol Kolacinski  */
5265fcf9b695SKarol Kolacinski int
ice_aq_write_i2c(struct ice_hw * hw,struct ice_aqc_link_topo_addr topo_addr,u16 bus_addr,__le16 addr,u8 params,const u8 * data,struct ice_sq_cd * cd)5266fcf9b695SKarol Kolacinski ice_aq_write_i2c(struct ice_hw *hw, struct ice_aqc_link_topo_addr topo_addr,
5267bf15bb38SMichal Schmidt 		 u16 bus_addr, __le16 addr, u8 params, const u8 *data,
5268fcf9b695SKarol Kolacinski 		 struct ice_sq_cd *cd)
5269fcf9b695SKarol Kolacinski {
5270fcf9b695SKarol Kolacinski 	struct ice_aq_desc desc = { 0 };
5271fcf9b695SKarol Kolacinski 	struct ice_aqc_i2c *cmd;
5272fcf9b695SKarol Kolacinski 	u8 data_size;
5273fcf9b695SKarol Kolacinski 
5274fcf9b695SKarol Kolacinski 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_write_i2c);
5275fcf9b695SKarol Kolacinski 	cmd = &desc.params.read_write_i2c;
5276fcf9b695SKarol Kolacinski 
5277fcf9b695SKarol Kolacinski 	data_size = FIELD_GET(ICE_AQC_I2C_DATA_SIZE_M, params);
5278fcf9b695SKarol Kolacinski 
5279fcf9b695SKarol Kolacinski 	/* data_size limited to 4 */
5280fcf9b695SKarol Kolacinski 	if (data_size > 4)
5281fcf9b695SKarol Kolacinski 		return -EINVAL;
5282fcf9b695SKarol Kolacinski 
5283fcf9b695SKarol Kolacinski 	cmd->i2c_bus_addr = cpu_to_le16(bus_addr);
5284fcf9b695SKarol Kolacinski 	cmd->topo_addr = topo_addr;
5285fcf9b695SKarol Kolacinski 	cmd->i2c_params = params;
5286fcf9b695SKarol Kolacinski 	cmd->i2c_addr = addr;
5287fcf9b695SKarol Kolacinski 
5288fcf9b695SKarol Kolacinski 	memcpy(cmd->i2c_data, data, data_size);
5289fcf9b695SKarol Kolacinski 
5290fcf9b695SKarol Kolacinski 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
5291fcf9b695SKarol Kolacinski }
5292fcf9b695SKarol Kolacinski 
5293fcf9b695SKarol Kolacinski /**
52947f9ab54dSJacob Keller  * ice_aq_set_driver_param - Set driver parameter to share via firmware
52957f9ab54dSJacob Keller  * @hw: pointer to the HW struct
52967f9ab54dSJacob Keller  * @idx: parameter index to set
52977f9ab54dSJacob Keller  * @value: the value to set the parameter to
52987f9ab54dSJacob Keller  * @cd: pointer to command details structure or NULL
52997f9ab54dSJacob Keller  *
53007f9ab54dSJacob Keller  * Set the value of one of the software defined parameters. All PFs connected
53017f9ab54dSJacob Keller  * to this device can read the value using ice_aq_get_driver_param.
53027f9ab54dSJacob Keller  *
53037f9ab54dSJacob Keller  * Note that firmware provides no synchronization or locking, and will not
53047f9ab54dSJacob Keller  * save the parameter value during a device reset. It is expected that
53057f9ab54dSJacob Keller  * a single PF will write the parameter value, while all other PFs will only
53067f9ab54dSJacob Keller  * read it.
53077f9ab54dSJacob Keller  */
53087f9ab54dSJacob Keller int
ice_aq_set_driver_param(struct ice_hw * hw,enum ice_aqc_driver_params idx,u32 value,struct ice_sq_cd * cd)53097f9ab54dSJacob Keller ice_aq_set_driver_param(struct ice_hw *hw, enum ice_aqc_driver_params idx,
53107f9ab54dSJacob Keller 			u32 value, struct ice_sq_cd *cd)
53117f9ab54dSJacob Keller {
53127f9ab54dSJacob Keller 	struct ice_aqc_driver_shared_params *cmd;
53137f9ab54dSJacob Keller 	struct ice_aq_desc desc;
53147f9ab54dSJacob Keller 
53157f9ab54dSJacob Keller 	if (idx >= ICE_AQC_DRIVER_PARAM_MAX)
53167f9ab54dSJacob Keller 		return -EIO;
53177f9ab54dSJacob Keller 
53187f9ab54dSJacob Keller 	cmd = &desc.params.drv_shared_params;
53197f9ab54dSJacob Keller 
53207f9ab54dSJacob Keller 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_driver_shared_params);
53217f9ab54dSJacob Keller 
53227f9ab54dSJacob Keller 	cmd->set_or_get_op = ICE_AQC_DRIVER_PARAM_SET;
53237f9ab54dSJacob Keller 	cmd->param_indx = idx;
53247f9ab54dSJacob Keller 	cmd->param_val = cpu_to_le32(value);
53257f9ab54dSJacob Keller 
5326d54699e2STony Nguyen 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
53277f9ab54dSJacob Keller }
53287f9ab54dSJacob Keller 
53297f9ab54dSJacob Keller /**
53307f9ab54dSJacob Keller  * ice_aq_get_driver_param - Get driver parameter shared via firmware
53317f9ab54dSJacob Keller  * @hw: pointer to the HW struct
53327f9ab54dSJacob Keller  * @idx: parameter index to set
53337f9ab54dSJacob Keller  * @value: storage to return the shared parameter
53347f9ab54dSJacob Keller  * @cd: pointer to command details structure or NULL
53357f9ab54dSJacob Keller  *
53367f9ab54dSJacob Keller  * Get the value of one of the software defined parameters.
53377f9ab54dSJacob Keller  *
53387f9ab54dSJacob Keller  * Note that firmware provides no synchronization or locking. It is expected
53397f9ab54dSJacob Keller  * that only a single PF will write a given parameter.
53407f9ab54dSJacob Keller  */
53417f9ab54dSJacob Keller int
ice_aq_get_driver_param(struct ice_hw * hw,enum ice_aqc_driver_params idx,u32 * value,struct ice_sq_cd * cd)53427f9ab54dSJacob Keller ice_aq_get_driver_param(struct ice_hw *hw, enum ice_aqc_driver_params idx,
53437f9ab54dSJacob Keller 			u32 *value, struct ice_sq_cd *cd)
53447f9ab54dSJacob Keller {
53457f9ab54dSJacob Keller 	struct ice_aqc_driver_shared_params *cmd;
53467f9ab54dSJacob Keller 	struct ice_aq_desc desc;
53475e24d598STony Nguyen 	int status;
53487f9ab54dSJacob Keller 
53497f9ab54dSJacob Keller 	if (idx >= ICE_AQC_DRIVER_PARAM_MAX)
53507f9ab54dSJacob Keller 		return -EIO;
53517f9ab54dSJacob Keller 
53527f9ab54dSJacob Keller 	cmd = &desc.params.drv_shared_params;
53537f9ab54dSJacob Keller 
53547f9ab54dSJacob Keller 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_driver_shared_params);
53557f9ab54dSJacob Keller 
53567f9ab54dSJacob Keller 	cmd->set_or_get_op = ICE_AQC_DRIVER_PARAM_GET;
53577f9ab54dSJacob Keller 	cmd->param_indx = idx;
53587f9ab54dSJacob Keller 
53597f9ab54dSJacob Keller 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
53607f9ab54dSJacob Keller 	if (status)
5361d54699e2STony Nguyen 		return status;
53627f9ab54dSJacob Keller 
53637f9ab54dSJacob Keller 	*value = le32_to_cpu(cmd->param_val);
53647f9ab54dSJacob Keller 
53657f9ab54dSJacob Keller 	return 0;
53667f9ab54dSJacob Keller }
53677f9ab54dSJacob Keller 
53687f9ab54dSJacob Keller /**
53693bb6324bSMaciej Machnikowski  * ice_aq_set_gpio
53703bb6324bSMaciej Machnikowski  * @hw: pointer to the hw struct
53713bb6324bSMaciej Machnikowski  * @gpio_ctrl_handle: GPIO controller node handle
53723bb6324bSMaciej Machnikowski  * @pin_idx: IO Number of the GPIO that needs to be set
53733bb6324bSMaciej Machnikowski  * @value: SW provide IO value to set in the LSB
53743bb6324bSMaciej Machnikowski  * @cd: pointer to command details structure or NULL
53753bb6324bSMaciej Machnikowski  *
53763bb6324bSMaciej Machnikowski  * Sends 0x06EC AQ command to set the GPIO pin state that's part of the topology
53773bb6324bSMaciej Machnikowski  */
53783bb6324bSMaciej Machnikowski int
ice_aq_set_gpio(struct ice_hw * hw,u16 gpio_ctrl_handle,u8 pin_idx,bool value,struct ice_sq_cd * cd)53793bb6324bSMaciej Machnikowski ice_aq_set_gpio(struct ice_hw *hw, u16 gpio_ctrl_handle, u8 pin_idx, bool value,
53803bb6324bSMaciej Machnikowski 		struct ice_sq_cd *cd)
53813bb6324bSMaciej Machnikowski {
53823bb6324bSMaciej Machnikowski 	struct ice_aqc_gpio *cmd;
53833bb6324bSMaciej Machnikowski 	struct ice_aq_desc desc;
53843bb6324bSMaciej Machnikowski 
53853bb6324bSMaciej Machnikowski 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_gpio);
53863bb6324bSMaciej Machnikowski 	cmd = &desc.params.read_write_gpio;
53873bb6324bSMaciej Machnikowski 	cmd->gpio_ctrl_handle = cpu_to_le16(gpio_ctrl_handle);
53883bb6324bSMaciej Machnikowski 	cmd->gpio_num = pin_idx;
53893bb6324bSMaciej Machnikowski 	cmd->gpio_val = value ? 1 : 0;
53903bb6324bSMaciej Machnikowski 
5391d54699e2STony Nguyen 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
53923bb6324bSMaciej Machnikowski }
53933bb6324bSMaciej Machnikowski 
53943bb6324bSMaciej Machnikowski /**
53953bb6324bSMaciej Machnikowski  * ice_aq_get_gpio
53963bb6324bSMaciej Machnikowski  * @hw: pointer to the hw struct
53973bb6324bSMaciej Machnikowski  * @gpio_ctrl_handle: GPIO controller node handle
53983bb6324bSMaciej Machnikowski  * @pin_idx: IO Number of the GPIO that needs to be set
53993bb6324bSMaciej Machnikowski  * @value: IO value read
54003bb6324bSMaciej Machnikowski  * @cd: pointer to command details structure or NULL
54013bb6324bSMaciej Machnikowski  *
54023bb6324bSMaciej Machnikowski  * Sends 0x06ED AQ command to get the value of a GPIO signal which is part of
54033bb6324bSMaciej Machnikowski  * the topology
54043bb6324bSMaciej Machnikowski  */
54053bb6324bSMaciej Machnikowski int
ice_aq_get_gpio(struct ice_hw * hw,u16 gpio_ctrl_handle,u8 pin_idx,bool * value,struct ice_sq_cd * cd)54063bb6324bSMaciej Machnikowski ice_aq_get_gpio(struct ice_hw *hw, u16 gpio_ctrl_handle, u8 pin_idx,
54073bb6324bSMaciej Machnikowski 		bool *value, struct ice_sq_cd *cd)
54083bb6324bSMaciej Machnikowski {
54093bb6324bSMaciej Machnikowski 	struct ice_aqc_gpio *cmd;
54103bb6324bSMaciej Machnikowski 	struct ice_aq_desc desc;
54115e24d598STony Nguyen 	int status;
54123bb6324bSMaciej Machnikowski 
54133bb6324bSMaciej Machnikowski 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_gpio);
54143bb6324bSMaciej Machnikowski 	cmd = &desc.params.read_write_gpio;
54153bb6324bSMaciej Machnikowski 	cmd->gpio_ctrl_handle = cpu_to_le16(gpio_ctrl_handle);
54163bb6324bSMaciej Machnikowski 	cmd->gpio_num = pin_idx;
54173bb6324bSMaciej Machnikowski 
54183bb6324bSMaciej Machnikowski 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
54193bb6324bSMaciej Machnikowski 	if (status)
5420d54699e2STony Nguyen 		return status;
54213bb6324bSMaciej Machnikowski 
54223bb6324bSMaciej Machnikowski 	*value = !!cmd->gpio_val;
54233bb6324bSMaciej Machnikowski 	return 0;
54243bb6324bSMaciej Machnikowski }
54253bb6324bSMaciej Machnikowski 
54263bb6324bSMaciej Machnikowski /**
54271bd50f2dSPaul Greenwalt  * ice_is_fw_api_min_ver
54281bd50f2dSPaul Greenwalt  * @hw: pointer to the hardware structure
54291bd50f2dSPaul Greenwalt  * @maj: major version
54301bd50f2dSPaul Greenwalt  * @min: minor version
54311bd50f2dSPaul Greenwalt  * @patch: patch version
54321bd50f2dSPaul Greenwalt  *
54331bd50f2dSPaul Greenwalt  * Checks if the firmware API is minimum version
54341bd50f2dSPaul Greenwalt  */
ice_is_fw_api_min_ver(struct ice_hw * hw,u8 maj,u8 min,u8 patch)54351bd50f2dSPaul Greenwalt static bool ice_is_fw_api_min_ver(struct ice_hw *hw, u8 maj, u8 min, u8 patch)
54361bd50f2dSPaul Greenwalt {
54371bd50f2dSPaul Greenwalt 	if (hw->api_maj_ver == maj) {
54381bd50f2dSPaul Greenwalt 		if (hw->api_min_ver > min)
54391bd50f2dSPaul Greenwalt 			return true;
54401bd50f2dSPaul Greenwalt 		if (hw->api_min_ver == min && hw->api_patch >= patch)
54411bd50f2dSPaul Greenwalt 			return true;
54421bd50f2dSPaul Greenwalt 	} else if (hw->api_maj_ver > maj) {
54431bd50f2dSPaul Greenwalt 		return true;
54441bd50f2dSPaul Greenwalt 	}
54451bd50f2dSPaul Greenwalt 
54461bd50f2dSPaul Greenwalt 	return false;
54471bd50f2dSPaul Greenwalt }
54481bd50f2dSPaul Greenwalt 
54491bd50f2dSPaul Greenwalt /**
5450ea78ce4dSPaul Greenwalt  * ice_fw_supports_link_override
5451ea78ce4dSPaul Greenwalt  * @hw: pointer to the hardware structure
5452ea78ce4dSPaul Greenwalt  *
5453ea78ce4dSPaul Greenwalt  * Checks if the firmware supports link override
5454ea78ce4dSPaul Greenwalt  */
ice_fw_supports_link_override(struct ice_hw * hw)5455ea78ce4dSPaul Greenwalt bool ice_fw_supports_link_override(struct ice_hw *hw)
5456ea78ce4dSPaul Greenwalt {
54571bd50f2dSPaul Greenwalt 	return ice_is_fw_api_min_ver(hw, ICE_FW_API_LINK_OVERRIDE_MAJ,
54581bd50f2dSPaul Greenwalt 				     ICE_FW_API_LINK_OVERRIDE_MIN,
54591bd50f2dSPaul Greenwalt 				     ICE_FW_API_LINK_OVERRIDE_PATCH);
5460ea78ce4dSPaul Greenwalt }
5461ea78ce4dSPaul Greenwalt 
5462ea78ce4dSPaul Greenwalt /**
5463ea78ce4dSPaul Greenwalt  * ice_get_link_default_override
5464ea78ce4dSPaul Greenwalt  * @ldo: pointer to the link default override struct
5465ea78ce4dSPaul Greenwalt  * @pi: pointer to the port info struct
5466ea78ce4dSPaul Greenwalt  *
5467ea78ce4dSPaul Greenwalt  * Gets the link default override for a port
5468ea78ce4dSPaul Greenwalt  */
54695e24d598STony Nguyen int
ice_get_link_default_override(struct ice_link_default_override_tlv * ldo,struct ice_port_info * pi)5470ea78ce4dSPaul Greenwalt ice_get_link_default_override(struct ice_link_default_override_tlv *ldo,
5471ea78ce4dSPaul Greenwalt 			      struct ice_port_info *pi)
5472ea78ce4dSPaul Greenwalt {
5473ea78ce4dSPaul Greenwalt 	u16 i, tlv, tlv_len, tlv_start, buf, offset;
5474ea78ce4dSPaul Greenwalt 	struct ice_hw *hw = pi->hw;
54755e24d598STony Nguyen 	int status;
5476ea78ce4dSPaul Greenwalt 
5477ea78ce4dSPaul Greenwalt 	status = ice_get_pfa_module_tlv(hw, &tlv, &tlv_len,
5478ea78ce4dSPaul Greenwalt 					ICE_SR_LINK_DEFAULT_OVERRIDE_PTR);
5479ea78ce4dSPaul Greenwalt 	if (status) {
54809228d8b2SJacob Keller 		ice_debug(hw, ICE_DBG_INIT, "Failed to read link override TLV.\n");
5481ea78ce4dSPaul Greenwalt 		return status;
5482ea78ce4dSPaul Greenwalt 	}
5483ea78ce4dSPaul Greenwalt 
5484ea78ce4dSPaul Greenwalt 	/* Each port has its own config; calculate for our port */
5485ea78ce4dSPaul Greenwalt 	tlv_start = tlv + pi->lport * ICE_SR_PFA_LINK_OVERRIDE_WORDS +
5486ea78ce4dSPaul Greenwalt 		ICE_SR_PFA_LINK_OVERRIDE_OFFSET;
5487ea78ce4dSPaul Greenwalt 
5488ea78ce4dSPaul Greenwalt 	/* link options first */
5489ea78ce4dSPaul Greenwalt 	status = ice_read_sr_word(hw, tlv_start, &buf);
5490ea78ce4dSPaul Greenwalt 	if (status) {
54919228d8b2SJacob Keller 		ice_debug(hw, ICE_DBG_INIT, "Failed to read override link options.\n");
5492ea78ce4dSPaul Greenwalt 		return status;
5493ea78ce4dSPaul Greenwalt 	}
5494ea78ce4dSPaul Greenwalt 	ldo->options = buf & ICE_LINK_OVERRIDE_OPT_M;
5495ea78ce4dSPaul Greenwalt 	ldo->phy_config = (buf & ICE_LINK_OVERRIDE_PHY_CFG_M) >>
5496ea78ce4dSPaul Greenwalt 		ICE_LINK_OVERRIDE_PHY_CFG_S;
5497ea78ce4dSPaul Greenwalt 
5498ea78ce4dSPaul Greenwalt 	/* link PHY config */
5499ea78ce4dSPaul Greenwalt 	offset = tlv_start + ICE_SR_PFA_LINK_OVERRIDE_FEC_OFFSET;
5500ea78ce4dSPaul Greenwalt 	status = ice_read_sr_word(hw, offset, &buf);
5501ea78ce4dSPaul Greenwalt 	if (status) {
55029228d8b2SJacob Keller 		ice_debug(hw, ICE_DBG_INIT, "Failed to read override phy config.\n");
5503ea78ce4dSPaul Greenwalt 		return status;
5504ea78ce4dSPaul Greenwalt 	}
5505ea78ce4dSPaul Greenwalt 	ldo->fec_options = buf & ICE_LINK_OVERRIDE_FEC_OPT_M;
5506ea78ce4dSPaul Greenwalt 
5507ea78ce4dSPaul Greenwalt 	/* PHY types low */
5508ea78ce4dSPaul Greenwalt 	offset = tlv_start + ICE_SR_PFA_LINK_OVERRIDE_PHY_OFFSET;
5509ea78ce4dSPaul Greenwalt 	for (i = 0; i < ICE_SR_PFA_LINK_OVERRIDE_PHY_WORDS; i++) {
5510ea78ce4dSPaul Greenwalt 		status = ice_read_sr_word(hw, (offset + i), &buf);
5511ea78ce4dSPaul Greenwalt 		if (status) {
55129228d8b2SJacob Keller 			ice_debug(hw, ICE_DBG_INIT, "Failed to read override link options.\n");
5513ea78ce4dSPaul Greenwalt 			return status;
5514ea78ce4dSPaul Greenwalt 		}
5515ea78ce4dSPaul Greenwalt 		/* shift 16 bits at a time to fill 64 bits */
5516ea78ce4dSPaul Greenwalt 		ldo->phy_type_low |= ((u64)buf << (i * 16));
5517ea78ce4dSPaul Greenwalt 	}
5518ea78ce4dSPaul Greenwalt 
5519ea78ce4dSPaul Greenwalt 	/* PHY types high */
5520ea78ce4dSPaul Greenwalt 	offset = tlv_start + ICE_SR_PFA_LINK_OVERRIDE_PHY_OFFSET +
5521ea78ce4dSPaul Greenwalt 		ICE_SR_PFA_LINK_OVERRIDE_PHY_WORDS;
5522ea78ce4dSPaul Greenwalt 	for (i = 0; i < ICE_SR_PFA_LINK_OVERRIDE_PHY_WORDS; i++) {
5523ea78ce4dSPaul Greenwalt 		status = ice_read_sr_word(hw, (offset + i), &buf);
5524ea78ce4dSPaul Greenwalt 		if (status) {
55259228d8b2SJacob Keller 			ice_debug(hw, ICE_DBG_INIT, "Failed to read override link options.\n");
5526ea78ce4dSPaul Greenwalt 			return status;
5527ea78ce4dSPaul Greenwalt 		}
5528ea78ce4dSPaul Greenwalt 		/* shift 16 bits at a time to fill 64 bits */
5529ea78ce4dSPaul Greenwalt 		ldo->phy_type_high |= ((u64)buf << (i * 16));
5530ea78ce4dSPaul Greenwalt 	}
5531ea78ce4dSPaul Greenwalt 
5532ea78ce4dSPaul Greenwalt 	return status;
5533ea78ce4dSPaul Greenwalt }
55345ee30564SPaul Greenwalt 
55355ee30564SPaul Greenwalt /**
55365ee30564SPaul Greenwalt  * ice_is_phy_caps_an_enabled - check if PHY capabilities autoneg is enabled
55375ee30564SPaul Greenwalt  * @caps: get PHY capability data
55385ee30564SPaul Greenwalt  */
ice_is_phy_caps_an_enabled(struct ice_aqc_get_phy_caps_data * caps)55395ee30564SPaul Greenwalt bool ice_is_phy_caps_an_enabled(struct ice_aqc_get_phy_caps_data *caps)
55405ee30564SPaul Greenwalt {
55415ee30564SPaul Greenwalt 	if (caps->caps & ICE_AQC_PHY_AN_MODE ||
5542bdeff971SLev Faerman 	    caps->low_power_ctrl_an & (ICE_AQC_PHY_AN_EN_CLAUSE28 |
55435ee30564SPaul Greenwalt 				       ICE_AQC_PHY_AN_EN_CLAUSE73 |
55445ee30564SPaul Greenwalt 				       ICE_AQC_PHY_AN_EN_CLAUSE37))
55455ee30564SPaul Greenwalt 		return true;
55465ee30564SPaul Greenwalt 
55475ee30564SPaul Greenwalt 	return false;
55485ee30564SPaul Greenwalt }
55497d9c9b79SDave Ertman 
55507d9c9b79SDave Ertman /**
55517d9c9b79SDave Ertman  * ice_aq_set_lldp_mib - Set the LLDP MIB
55527d9c9b79SDave Ertman  * @hw: pointer to the HW struct
55537d9c9b79SDave Ertman  * @mib_type: Local, Remote or both Local and Remote MIBs
55547d9c9b79SDave Ertman  * @buf: pointer to the caller-supplied buffer to store the MIB block
55557d9c9b79SDave Ertman  * @buf_size: size of the buffer (in bytes)
55567d9c9b79SDave Ertman  * @cd: pointer to command details structure or NULL
55577d9c9b79SDave Ertman  *
55587d9c9b79SDave Ertman  * Set the LLDP MIB. (0x0A08)
55597d9c9b79SDave Ertman  */
55605e24d598STony Nguyen int
ice_aq_set_lldp_mib(struct ice_hw * hw,u8 mib_type,void * buf,u16 buf_size,struct ice_sq_cd * cd)55617d9c9b79SDave Ertman ice_aq_set_lldp_mib(struct ice_hw *hw, u8 mib_type, void *buf, u16 buf_size,
55627d9c9b79SDave Ertman 		    struct ice_sq_cd *cd)
55637d9c9b79SDave Ertman {
55647d9c9b79SDave Ertman 	struct ice_aqc_lldp_set_local_mib *cmd;
55657d9c9b79SDave Ertman 	struct ice_aq_desc desc;
55667d9c9b79SDave Ertman 
55677d9c9b79SDave Ertman 	cmd = &desc.params.lldp_set_mib;
55687d9c9b79SDave Ertman 
55697d9c9b79SDave Ertman 	if (buf_size == 0 || !buf)
5570d54699e2STony Nguyen 		return -EINVAL;
55717d9c9b79SDave Ertman 
55727d9c9b79SDave Ertman 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_lldp_set_local_mib);
55737d9c9b79SDave Ertman 
55747d9c9b79SDave Ertman 	desc.flags |= cpu_to_le16((u16)ICE_AQ_FLAG_RD);
55757d9c9b79SDave Ertman 	desc.datalen = cpu_to_le16(buf_size);
55767d9c9b79SDave Ertman 
55777d9c9b79SDave Ertman 	cmd->type = mib_type;
55787d9c9b79SDave Ertman 	cmd->length = cpu_to_le16(buf_size);
55797d9c9b79SDave Ertman 
55807d9c9b79SDave Ertman 	return ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
55817d9c9b79SDave Ertman }
558234295a36SDave Ertman 
558334295a36SDave Ertman /**
5584ef860480STony Nguyen  * ice_fw_supports_lldp_fltr_ctrl - check NVM version supports lldp_fltr_ctrl
558534295a36SDave Ertman  * @hw: pointer to HW struct
558634295a36SDave Ertman  */
ice_fw_supports_lldp_fltr_ctrl(struct ice_hw * hw)558734295a36SDave Ertman bool ice_fw_supports_lldp_fltr_ctrl(struct ice_hw *hw)
558834295a36SDave Ertman {
558934295a36SDave Ertman 	if (hw->mac_type != ICE_MAC_E810)
559034295a36SDave Ertman 		return false;
559134295a36SDave Ertman 
55921bd50f2dSPaul Greenwalt 	return ice_is_fw_api_min_ver(hw, ICE_FW_API_LLDP_FLTR_MAJ,
55931bd50f2dSPaul Greenwalt 				     ICE_FW_API_LLDP_FLTR_MIN,
55941bd50f2dSPaul Greenwalt 				     ICE_FW_API_LLDP_FLTR_PATCH);
559534295a36SDave Ertman }
559634295a36SDave Ertman 
559734295a36SDave Ertman /**
559834295a36SDave Ertman  * ice_lldp_fltr_add_remove - add or remove a LLDP Rx switch filter
559934295a36SDave Ertman  * @hw: pointer to HW struct
560034295a36SDave Ertman  * @vsi_num: absolute HW index for VSI
560134295a36SDave Ertman  * @add: boolean for if adding or removing a filter
560234295a36SDave Ertman  */
56035e24d598STony Nguyen int
ice_lldp_fltr_add_remove(struct ice_hw * hw,u16 vsi_num,bool add)560434295a36SDave Ertman ice_lldp_fltr_add_remove(struct ice_hw *hw, u16 vsi_num, bool add)
560534295a36SDave Ertman {
560634295a36SDave Ertman 	struct ice_aqc_lldp_filter_ctrl *cmd;
560734295a36SDave Ertman 	struct ice_aq_desc desc;
560834295a36SDave Ertman 
560934295a36SDave Ertman 	cmd = &desc.params.lldp_filter_ctrl;
561034295a36SDave Ertman 
561134295a36SDave Ertman 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_lldp_filter_ctrl);
561234295a36SDave Ertman 
561334295a36SDave Ertman 	if (add)
561434295a36SDave Ertman 		cmd->cmd_flags = ICE_AQC_LLDP_FILTER_ACTION_ADD;
561534295a36SDave Ertman 	else
561634295a36SDave Ertman 		cmd->cmd_flags = ICE_AQC_LLDP_FILTER_ACTION_DELETE;
561734295a36SDave Ertman 
561834295a36SDave Ertman 	cmd->vsi_num = cpu_to_le16(vsi_num);
561934295a36SDave Ertman 
562034295a36SDave Ertman 	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
562134295a36SDave Ertman }
56220a02944fSAnirudh Venkataramanan 
56230a02944fSAnirudh Venkataramanan /**
5624a4f68f37STsotne Chakhvadze  * ice_lldp_execute_pending_mib - execute LLDP pending MIB request
5625a4f68f37STsotne Chakhvadze  * @hw: pointer to HW struct
5626a4f68f37STsotne Chakhvadze  */
ice_lldp_execute_pending_mib(struct ice_hw * hw)5627a4f68f37STsotne Chakhvadze int ice_lldp_execute_pending_mib(struct ice_hw *hw)
5628a4f68f37STsotne Chakhvadze {
5629a4f68f37STsotne Chakhvadze 	struct ice_aq_desc desc;
5630a4f68f37STsotne Chakhvadze 
5631a4f68f37STsotne Chakhvadze 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_lldp_execute_pending_mib);
5632a4f68f37STsotne Chakhvadze 
5633a4f68f37STsotne Chakhvadze 	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
5634a4f68f37STsotne Chakhvadze }
5635a4f68f37STsotne Chakhvadze 
5636a4f68f37STsotne Chakhvadze /**
56370a02944fSAnirudh Venkataramanan  * ice_fw_supports_report_dflt_cfg
56380a02944fSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
56390a02944fSAnirudh Venkataramanan  *
56400a02944fSAnirudh Venkataramanan  * Checks if the firmware supports report default configuration
56410a02944fSAnirudh Venkataramanan  */
ice_fw_supports_report_dflt_cfg(struct ice_hw * hw)56420a02944fSAnirudh Venkataramanan bool ice_fw_supports_report_dflt_cfg(struct ice_hw *hw)
56430a02944fSAnirudh Venkataramanan {
56441bd50f2dSPaul Greenwalt 	return ice_is_fw_api_min_ver(hw, ICE_FW_API_REPORT_DFLT_CFG_MAJ,
56451bd50f2dSPaul Greenwalt 				     ICE_FW_API_REPORT_DFLT_CFG_MIN,
56461bd50f2dSPaul Greenwalt 				     ICE_FW_API_REPORT_DFLT_CFG_PATCH);
56470a02944fSAnirudh Venkataramanan }
56481d0e28a9SBrett Creeley 
56491d0e28a9SBrett Creeley /* each of the indexes into the following array match the speed of a return
56501d0e28a9SBrett Creeley  * value from the list of AQ returned speeds like the range:
56511d0e28a9SBrett Creeley  * ICE_AQ_LINK_SPEED_10MB .. ICE_AQ_LINK_SPEED_100GB excluding
56521d0e28a9SBrett Creeley  * ICE_AQ_LINK_SPEED_UNKNOWN which is BIT(15) and maps to BIT(14) in this
56531d0e28a9SBrett Creeley  * array. The array is defined as 15 elements long because the link_speed
56541d0e28a9SBrett Creeley  * returned by the firmware is a 16 bit * value, but is indexed
56551d0e28a9SBrett Creeley  * by [fls(speed) - 1]
56561d0e28a9SBrett Creeley  */
5657b2dbde3aSMichal Swiatkowski static const u32 ice_aq_to_link_speed[] = {
56581d0e28a9SBrett Creeley 	SPEED_10,	/* BIT(0) */
56591d0e28a9SBrett Creeley 	SPEED_100,
56601d0e28a9SBrett Creeley 	SPEED_1000,
56611d0e28a9SBrett Creeley 	SPEED_2500,
56621d0e28a9SBrett Creeley 	SPEED_5000,
56631d0e28a9SBrett Creeley 	SPEED_10000,
56641d0e28a9SBrett Creeley 	SPEED_20000,
56651d0e28a9SBrett Creeley 	SPEED_25000,
56661d0e28a9SBrett Creeley 	SPEED_40000,
56671d0e28a9SBrett Creeley 	SPEED_50000,
56681d0e28a9SBrett Creeley 	SPEED_100000,	/* BIT(10) */
56691d0e28a9SBrett Creeley };
56701d0e28a9SBrett Creeley 
56711d0e28a9SBrett Creeley /**
56721d0e28a9SBrett Creeley  * ice_get_link_speed - get integer speed from table
56731d0e28a9SBrett Creeley  * @index: array index from fls(aq speed) - 1
56741d0e28a9SBrett Creeley  *
56751d0e28a9SBrett Creeley  * Returns: u32 value containing integer speed
56761d0e28a9SBrett Creeley  */
ice_get_link_speed(u16 index)56771d0e28a9SBrett Creeley u32 ice_get_link_speed(u16 index)
56781d0e28a9SBrett Creeley {
5679b2dbde3aSMichal Swiatkowski 	if (index >= ARRAY_SIZE(ice_aq_to_link_speed))
5680b2dbde3aSMichal Swiatkowski 		return 0;
5681b2dbde3aSMichal Swiatkowski 
56821d0e28a9SBrett Creeley 	return ice_aq_to_link_speed[index];
56831d0e28a9SBrett Creeley }
5684