17ec59eeaSAnirudh Venkataramanan // SPDX-License-Identifier: GPL-2.0
27ec59eeaSAnirudh Venkataramanan /* Copyright (c) 2018, 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"
87ec59eeaSAnirudh Venkataramanan 
971245072SJacob Keller #define ICE_PF_RESET_WAIT_COUNT	300
10f31e4b6fSAnirudh Venkataramanan 
11f31e4b6fSAnirudh Venkataramanan /**
12f31e4b6fSAnirudh Venkataramanan  * ice_set_mac_type - Sets MAC type
13f31e4b6fSAnirudh Venkataramanan  * @hw: pointer to the HW structure
14f31e4b6fSAnirudh Venkataramanan  *
15f31e4b6fSAnirudh Venkataramanan  * This function sets the MAC type of the adapter based on the
16f9867df6SAnirudh Venkataramanan  * vendor ID and device ID stored in the HW structure.
17f31e4b6fSAnirudh Venkataramanan  */
18f31e4b6fSAnirudh Venkataramanan static enum ice_status ice_set_mac_type(struct ice_hw *hw)
19f31e4b6fSAnirudh Venkataramanan {
20f31e4b6fSAnirudh Venkataramanan 	if (hw->vendor_id != PCI_VENDOR_ID_INTEL)
21f31e4b6fSAnirudh Venkataramanan 		return ICE_ERR_DEVICE_NOT_SUPPORTED;
22f31e4b6fSAnirudh Venkataramanan 
23f31e4b6fSAnirudh Venkataramanan 	hw->mac_type = ICE_MAC_GENERIC;
24f31e4b6fSAnirudh Venkataramanan 	return 0;
25f31e4b6fSAnirudh Venkataramanan }
26f31e4b6fSAnirudh Venkataramanan 
27f31e4b6fSAnirudh Venkataramanan /**
28f31e4b6fSAnirudh Venkataramanan  * ice_clear_pf_cfg - Clear PF configuration
29f31e4b6fSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
303968540bSAnirudh Venkataramanan  *
313968540bSAnirudh Venkataramanan  * Clears any existing PF configuration (VSIs, VSI lists, switch rules, port
323968540bSAnirudh Venkataramanan  * configuration, flow director filters, etc.).
33f31e4b6fSAnirudh Venkataramanan  */
34f31e4b6fSAnirudh Venkataramanan enum ice_status ice_clear_pf_cfg(struct ice_hw *hw)
35f31e4b6fSAnirudh Venkataramanan {
36f31e4b6fSAnirudh Venkataramanan 	struct ice_aq_desc desc;
37f31e4b6fSAnirudh Venkataramanan 
38f31e4b6fSAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_clear_pf_cfg);
39f31e4b6fSAnirudh Venkataramanan 
40f31e4b6fSAnirudh Venkataramanan 	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
41f31e4b6fSAnirudh Venkataramanan }
42f31e4b6fSAnirudh Venkataramanan 
43f31e4b6fSAnirudh Venkataramanan /**
44dc49c772SAnirudh Venkataramanan  * ice_aq_manage_mac_read - manage MAC address read command
45f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
46dc49c772SAnirudh Venkataramanan  * @buf: a virtual buffer to hold the manage MAC read response
47dc49c772SAnirudh Venkataramanan  * @buf_size: Size of the virtual buffer
48dc49c772SAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
49dc49c772SAnirudh Venkataramanan  *
50dc49c772SAnirudh Venkataramanan  * This function is used to return per PF station MAC address (0x0107).
51dc49c772SAnirudh Venkataramanan  * NOTE: Upon successful completion of this command, MAC address information
52dc49c772SAnirudh Venkataramanan  * is returned in user specified buffer. Please interpret user specified
53dc49c772SAnirudh Venkataramanan  * buffer as "manage_mac_read" response.
54dc49c772SAnirudh Venkataramanan  * Response such as various MAC addresses are stored in HW struct (port.mac)
5581aed647SJacob Keller  * ice_discover_dev_caps is expected to be called before this function is
5681aed647SJacob Keller  * called.
57dc49c772SAnirudh Venkataramanan  */
58dc49c772SAnirudh Venkataramanan static enum ice_status
59dc49c772SAnirudh Venkataramanan ice_aq_manage_mac_read(struct ice_hw *hw, void *buf, u16 buf_size,
60dc49c772SAnirudh Venkataramanan 		       struct ice_sq_cd *cd)
61dc49c772SAnirudh Venkataramanan {
62dc49c772SAnirudh Venkataramanan 	struct ice_aqc_manage_mac_read_resp *resp;
63dc49c772SAnirudh Venkataramanan 	struct ice_aqc_manage_mac_read *cmd;
64dc49c772SAnirudh Venkataramanan 	struct ice_aq_desc desc;
65dc49c772SAnirudh Venkataramanan 	enum ice_status status;
66dc49c772SAnirudh Venkataramanan 	u16 flags;
67d6fef10cSMd Fahad Iqbal Polash 	u8 i;
68dc49c772SAnirudh Venkataramanan 
69dc49c772SAnirudh Venkataramanan 	cmd = &desc.params.mac_read;
70dc49c772SAnirudh Venkataramanan 
71dc49c772SAnirudh Venkataramanan 	if (buf_size < sizeof(*resp))
72dc49c772SAnirudh Venkataramanan 		return ICE_ERR_BUF_TOO_SHORT;
73dc49c772SAnirudh Venkataramanan 
74dc49c772SAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_manage_mac_read);
75dc49c772SAnirudh Venkataramanan 
76dc49c772SAnirudh Venkataramanan 	status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
77dc49c772SAnirudh Venkataramanan 	if (status)
78dc49c772SAnirudh Venkataramanan 		return status;
79dc49c772SAnirudh Venkataramanan 
80dc49c772SAnirudh Venkataramanan 	resp = (struct ice_aqc_manage_mac_read_resp *)buf;
81dc49c772SAnirudh Venkataramanan 	flags = le16_to_cpu(cmd->flags) & ICE_AQC_MAN_MAC_READ_M;
82dc49c772SAnirudh Venkataramanan 
83dc49c772SAnirudh Venkataramanan 	if (!(flags & ICE_AQC_MAN_MAC_LAN_ADDR_VALID)) {
84dc49c772SAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_LAN, "got invalid MAC address\n");
85dc49c772SAnirudh Venkataramanan 		return ICE_ERR_CFG;
86dc49c772SAnirudh Venkataramanan 	}
87dc49c772SAnirudh Venkataramanan 
88d6fef10cSMd Fahad Iqbal Polash 	/* A single port can report up to two (LAN and WoL) addresses */
89d6fef10cSMd Fahad Iqbal Polash 	for (i = 0; i < cmd->num_addr; i++)
90d6fef10cSMd Fahad Iqbal Polash 		if (resp[i].addr_type == ICE_AQC_MAN_MAC_ADDR_TYPE_LAN) {
91d6fef10cSMd Fahad Iqbal Polash 			ether_addr_copy(hw->port_info->mac.lan_addr,
92d6fef10cSMd Fahad Iqbal Polash 					resp[i].mac_addr);
93d6fef10cSMd Fahad Iqbal Polash 			ether_addr_copy(hw->port_info->mac.perm_addr,
94d6fef10cSMd Fahad Iqbal Polash 					resp[i].mac_addr);
95d6fef10cSMd Fahad Iqbal Polash 			break;
96d6fef10cSMd Fahad Iqbal Polash 		}
97d6fef10cSMd Fahad Iqbal Polash 
98dc49c772SAnirudh Venkataramanan 	return 0;
99dc49c772SAnirudh Venkataramanan }
100dc49c772SAnirudh Venkataramanan 
101dc49c772SAnirudh Venkataramanan /**
102dc49c772SAnirudh Venkataramanan  * ice_aq_get_phy_caps - returns PHY capabilities
103dc49c772SAnirudh Venkataramanan  * @pi: port information structure
104dc49c772SAnirudh Venkataramanan  * @qual_mods: report qualified modules
105dc49c772SAnirudh Venkataramanan  * @report_mode: report mode capabilities
106dc49c772SAnirudh Venkataramanan  * @pcaps: structure for PHY capabilities to be filled
107dc49c772SAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
108dc49c772SAnirudh Venkataramanan  *
109dc49c772SAnirudh Venkataramanan  * Returns the various PHY capabilities supported on the Port (0x0600)
110dc49c772SAnirudh Venkataramanan  */
11148cb27f2SChinh Cao enum ice_status
112dc49c772SAnirudh Venkataramanan ice_aq_get_phy_caps(struct ice_port_info *pi, bool qual_mods, u8 report_mode,
113dc49c772SAnirudh Venkataramanan 		    struct ice_aqc_get_phy_caps_data *pcaps,
114dc49c772SAnirudh Venkataramanan 		    struct ice_sq_cd *cd)
115dc49c772SAnirudh Venkataramanan {
116dc49c772SAnirudh Venkataramanan 	struct ice_aqc_get_phy_caps *cmd;
117dc49c772SAnirudh Venkataramanan 	u16 pcaps_size = sizeof(*pcaps);
118dc49c772SAnirudh Venkataramanan 	struct ice_aq_desc desc;
119dc49c772SAnirudh Venkataramanan 	enum ice_status status;
120dc49c772SAnirudh Venkataramanan 
121dc49c772SAnirudh Venkataramanan 	cmd = &desc.params.get_phy;
122dc49c772SAnirudh Venkataramanan 
123dc49c772SAnirudh Venkataramanan 	if (!pcaps || (report_mode & ~ICE_AQC_REPORT_MODE_M) || !pi)
124dc49c772SAnirudh Venkataramanan 		return ICE_ERR_PARAM;
125dc49c772SAnirudh Venkataramanan 
126dc49c772SAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_phy_caps);
127dc49c772SAnirudh Venkataramanan 
128dc49c772SAnirudh Venkataramanan 	if (qual_mods)
129dc49c772SAnirudh Venkataramanan 		cmd->param0 |= cpu_to_le16(ICE_AQC_GET_PHY_RQM);
130dc49c772SAnirudh Venkataramanan 
131dc49c772SAnirudh Venkataramanan 	cmd->param0 |= cpu_to_le16(report_mode);
132dc49c772SAnirudh Venkataramanan 	status = ice_aq_send_cmd(pi->hw, &desc, pcaps, pcaps_size, cd);
133dc49c772SAnirudh Venkataramanan 
134aef74145SAnirudh Venkataramanan 	if (!status && report_mode == ICE_AQC_REPORT_TOPO_CAP) {
135dc49c772SAnirudh Venkataramanan 		pi->phy.phy_type_low = le64_to_cpu(pcaps->phy_type_low);
136aef74145SAnirudh Venkataramanan 		pi->phy.phy_type_high = le64_to_cpu(pcaps->phy_type_high);
137aef74145SAnirudh Venkataramanan 	}
138dc49c772SAnirudh Venkataramanan 
139dc49c772SAnirudh Venkataramanan 	return status;
140dc49c772SAnirudh Venkataramanan }
141dc49c772SAnirudh Venkataramanan 
142dc49c772SAnirudh Venkataramanan /**
143dc49c772SAnirudh Venkataramanan  * ice_get_media_type - Gets media type
144dc49c772SAnirudh Venkataramanan  * @pi: port information structure
145dc49c772SAnirudh Venkataramanan  */
146dc49c772SAnirudh Venkataramanan static enum ice_media_type ice_get_media_type(struct ice_port_info *pi)
147dc49c772SAnirudh Venkataramanan {
148dc49c772SAnirudh Venkataramanan 	struct ice_link_status *hw_link_info;
149dc49c772SAnirudh Venkataramanan 
150dc49c772SAnirudh Venkataramanan 	if (!pi)
151dc49c772SAnirudh Venkataramanan 		return ICE_MEDIA_UNKNOWN;
152dc49c772SAnirudh Venkataramanan 
153dc49c772SAnirudh Venkataramanan 	hw_link_info = &pi->phy.link_info;
154aef74145SAnirudh Venkataramanan 	if (hw_link_info->phy_type_low && hw_link_info->phy_type_high)
155aef74145SAnirudh Venkataramanan 		/* If more than one media type is selected, report unknown */
156aef74145SAnirudh Venkataramanan 		return ICE_MEDIA_UNKNOWN;
157dc49c772SAnirudh Venkataramanan 
158dc49c772SAnirudh Venkataramanan 	if (hw_link_info->phy_type_low) {
159dc49c772SAnirudh Venkataramanan 		switch (hw_link_info->phy_type_low) {
160dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_1000BASE_SX:
161dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_1000BASE_LX:
162dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_10GBASE_SR:
163dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_10GBASE_LR:
164dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_10G_SFI_C2C:
165dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_25GBASE_SR:
166dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_25GBASE_LR:
167dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_25G_AUI_C2C:
168dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_40GBASE_SR4:
169dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_40GBASE_LR4:
170aef74145SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_50GBASE_SR2:
171aef74145SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_50GBASE_LR2:
172aef74145SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_50GBASE_SR:
173aef74145SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_50GBASE_FR:
174aef74145SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_50GBASE_LR:
175aef74145SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_100GBASE_SR4:
176aef74145SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_100GBASE_LR4:
177aef74145SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_100GBASE_SR2:
178aef74145SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_100GBASE_DR:
179dc49c772SAnirudh Venkataramanan 			return ICE_MEDIA_FIBER;
180dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_100BASE_TX:
181dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_1000BASE_T:
182dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_2500BASE_T:
183dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_5GBASE_T:
184dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_10GBASE_T:
185dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_25GBASE_T:
186dc49c772SAnirudh Venkataramanan 			return ICE_MEDIA_BASET;
187dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_10G_SFI_DA:
188dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_25GBASE_CR:
189dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_25GBASE_CR_S:
190dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_25GBASE_CR1:
191dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_40GBASE_CR4:
192aef74145SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_50GBASE_CR2:
193aef74145SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_50GBASE_CP:
194aef74145SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_100GBASE_CR4:
195aef74145SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_100GBASE_CR_PAM4:
196aef74145SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_100GBASE_CP2:
197dc49c772SAnirudh Venkataramanan 			return ICE_MEDIA_DA;
198dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_1000BASE_KX:
199dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_2500BASE_KX:
200dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_2500BASE_X:
201dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_5GBASE_KR:
202dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_10GBASE_KR_CR1:
203dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_25GBASE_KR:
204dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_25GBASE_KR1:
205dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_25GBASE_KR_S:
206dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_40GBASE_KR4:
207aef74145SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4:
208aef74145SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_50GBASE_KR2:
209aef74145SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_100GBASE_KR4:
210aef74145SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4:
211aef74145SAnirudh Venkataramanan 			return ICE_MEDIA_BACKPLANE;
212aef74145SAnirudh Venkataramanan 		}
213aef74145SAnirudh Venkataramanan 	} else {
214aef74145SAnirudh Venkataramanan 		switch (hw_link_info->phy_type_high) {
215aef74145SAnirudh Venkataramanan 		case ICE_PHY_TYPE_HIGH_100GBASE_KR2_PAM4:
216dc49c772SAnirudh Venkataramanan 			return ICE_MEDIA_BACKPLANE;
217dc49c772SAnirudh Venkataramanan 		}
218dc49c772SAnirudh Venkataramanan 	}
219dc49c772SAnirudh Venkataramanan 	return ICE_MEDIA_UNKNOWN;
220dc49c772SAnirudh Venkataramanan }
221dc49c772SAnirudh Venkataramanan 
222dc49c772SAnirudh Venkataramanan /**
223dc49c772SAnirudh Venkataramanan  * ice_aq_get_link_info
224dc49c772SAnirudh Venkataramanan  * @pi: port information structure
225dc49c772SAnirudh Venkataramanan  * @ena_lse: enable/disable LinkStatusEvent reporting
226dc49c772SAnirudh Venkataramanan  * @link: pointer to link status structure - optional
227dc49c772SAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
228dc49c772SAnirudh Venkataramanan  *
229dc49c772SAnirudh Venkataramanan  * Get Link Status (0x607). Returns the link status of the adapter.
230dc49c772SAnirudh Venkataramanan  */
231250c3b3eSBrett Creeley enum ice_status
232dc49c772SAnirudh Venkataramanan ice_aq_get_link_info(struct ice_port_info *pi, bool ena_lse,
233dc49c772SAnirudh Venkataramanan 		     struct ice_link_status *link, struct ice_sq_cd *cd)
234dc49c772SAnirudh Venkataramanan {
235dc49c772SAnirudh Venkataramanan 	struct ice_aqc_get_link_status_data link_data = { 0 };
236dc49c772SAnirudh Venkataramanan 	struct ice_aqc_get_link_status *resp;
237dc67039bSJesse Brandeburg 	struct ice_link_status *li_old, *li;
238dc49c772SAnirudh Venkataramanan 	enum ice_media_type *hw_media_type;
239dc49c772SAnirudh Venkataramanan 	struct ice_fc_info *hw_fc_info;
240dc49c772SAnirudh Venkataramanan 	bool tx_pause, rx_pause;
241dc49c772SAnirudh Venkataramanan 	struct ice_aq_desc desc;
242dc49c772SAnirudh Venkataramanan 	enum ice_status status;
243dc67039bSJesse Brandeburg 	struct ice_hw *hw;
244dc49c772SAnirudh Venkataramanan 	u16 cmd_flags;
245dc49c772SAnirudh Venkataramanan 
246dc49c772SAnirudh Venkataramanan 	if (!pi)
247dc49c772SAnirudh Venkataramanan 		return ICE_ERR_PARAM;
248dc67039bSJesse Brandeburg 	hw = pi->hw;
249dc67039bSJesse Brandeburg 	li_old = &pi->phy.link_info_old;
250dc49c772SAnirudh Venkataramanan 	hw_media_type = &pi->phy.media_type;
251dc67039bSJesse Brandeburg 	li = &pi->phy.link_info;
252dc49c772SAnirudh Venkataramanan 	hw_fc_info = &pi->fc;
253dc49c772SAnirudh Venkataramanan 
254dc49c772SAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_link_status);
255dc49c772SAnirudh Venkataramanan 	cmd_flags = (ena_lse) ? ICE_AQ_LSE_ENA : ICE_AQ_LSE_DIS;
256dc49c772SAnirudh Venkataramanan 	resp = &desc.params.get_link_status;
257dc49c772SAnirudh Venkataramanan 	resp->cmd_flags = cpu_to_le16(cmd_flags);
258dc49c772SAnirudh Venkataramanan 	resp->lport_num = pi->lport;
259dc49c772SAnirudh Venkataramanan 
260dc67039bSJesse Brandeburg 	status = ice_aq_send_cmd(hw, &desc, &link_data, sizeof(link_data), cd);
261dc49c772SAnirudh Venkataramanan 
262dc49c772SAnirudh Venkataramanan 	if (status)
263dc49c772SAnirudh Venkataramanan 		return status;
264dc49c772SAnirudh Venkataramanan 
265dc49c772SAnirudh Venkataramanan 	/* save off old link status information */
266dc67039bSJesse Brandeburg 	*li_old = *li;
267dc49c772SAnirudh Venkataramanan 
268dc49c772SAnirudh Venkataramanan 	/* update current link status information */
269dc67039bSJesse Brandeburg 	li->link_speed = le16_to_cpu(link_data.link_speed);
270dc67039bSJesse Brandeburg 	li->phy_type_low = le64_to_cpu(link_data.phy_type_low);
271dc67039bSJesse Brandeburg 	li->phy_type_high = le64_to_cpu(link_data.phy_type_high);
272dc49c772SAnirudh Venkataramanan 	*hw_media_type = ice_get_media_type(pi);
273dc67039bSJesse Brandeburg 	li->link_info = link_data.link_info;
274dc67039bSJesse Brandeburg 	li->an_info = link_data.an_info;
275dc67039bSJesse Brandeburg 	li->ext_info = link_data.ext_info;
276dc67039bSJesse Brandeburg 	li->max_frame_size = le16_to_cpu(link_data.max_frame_size);
277dc67039bSJesse Brandeburg 	li->fec_info = link_data.cfg & ICE_AQ_FEC_MASK;
278dc67039bSJesse Brandeburg 	li->topo_media_conflict = link_data.topo_media_conflict;
279dc67039bSJesse Brandeburg 	li->pacing = link_data.cfg & (ICE_AQ_CFG_PACING_M |
280dc67039bSJesse Brandeburg 				      ICE_AQ_CFG_PACING_TYPE_M);
281dc49c772SAnirudh Venkataramanan 
282dc49c772SAnirudh Venkataramanan 	/* update fc info */
283dc49c772SAnirudh Venkataramanan 	tx_pause = !!(link_data.an_info & ICE_AQ_LINK_PAUSE_TX);
284dc49c772SAnirudh Venkataramanan 	rx_pause = !!(link_data.an_info & ICE_AQ_LINK_PAUSE_RX);
285dc49c772SAnirudh Venkataramanan 	if (tx_pause && rx_pause)
286dc49c772SAnirudh Venkataramanan 		hw_fc_info->current_mode = ICE_FC_FULL;
287dc49c772SAnirudh Venkataramanan 	else if (tx_pause)
288dc49c772SAnirudh Venkataramanan 		hw_fc_info->current_mode = ICE_FC_TX_PAUSE;
289dc49c772SAnirudh Venkataramanan 	else if (rx_pause)
290dc49c772SAnirudh Venkataramanan 		hw_fc_info->current_mode = ICE_FC_RX_PAUSE;
291dc49c772SAnirudh Venkataramanan 	else
292dc49c772SAnirudh Venkataramanan 		hw_fc_info->current_mode = ICE_FC_NONE;
293dc49c772SAnirudh Venkataramanan 
294dc67039bSJesse Brandeburg 	li->lse_ena = !!(resp->cmd_flags & cpu_to_le16(ICE_AQ_LSE_IS_ENABLED));
295dc67039bSJesse Brandeburg 
296dc67039bSJesse Brandeburg 	ice_debug(hw, ICE_DBG_LINK, "link_speed = 0x%x\n", li->link_speed);
297dc67039bSJesse Brandeburg 	ice_debug(hw, ICE_DBG_LINK, "phy_type_low = 0x%llx\n",
298dc67039bSJesse Brandeburg 		  (unsigned long long)li->phy_type_low);
299dc67039bSJesse Brandeburg 	ice_debug(hw, ICE_DBG_LINK, "phy_type_high = 0x%llx\n",
300dc67039bSJesse Brandeburg 		  (unsigned long long)li->phy_type_high);
301dc67039bSJesse Brandeburg 	ice_debug(hw, ICE_DBG_LINK, "media_type = 0x%x\n", *hw_media_type);
302dc67039bSJesse Brandeburg 	ice_debug(hw, ICE_DBG_LINK, "link_info = 0x%x\n", li->link_info);
303dc67039bSJesse Brandeburg 	ice_debug(hw, ICE_DBG_LINK, "an_info = 0x%x\n", li->an_info);
304dc67039bSJesse Brandeburg 	ice_debug(hw, ICE_DBG_LINK, "ext_info = 0x%x\n", li->ext_info);
305dc67039bSJesse Brandeburg 	ice_debug(hw, ICE_DBG_LINK, "lse_ena = 0x%x\n", li->lse_ena);
306dc67039bSJesse Brandeburg 	ice_debug(hw, ICE_DBG_LINK, "max_frame = 0x%x\n", li->max_frame_size);
307dc67039bSJesse Brandeburg 	ice_debug(hw, ICE_DBG_LINK, "pacing = 0x%x\n", li->pacing);
308dc49c772SAnirudh Venkataramanan 
309dc49c772SAnirudh Venkataramanan 	/* save link status information */
310dc49c772SAnirudh Venkataramanan 	if (link)
311dc67039bSJesse Brandeburg 		*link = *li;
312dc49c772SAnirudh Venkataramanan 
313dc49c772SAnirudh Venkataramanan 	/* flag cleared so calling functions don't call AQ again */
314dc49c772SAnirudh Venkataramanan 	pi->phy.get_link_info = false;
315dc49c772SAnirudh Venkataramanan 
3161b5c19c7SBruce Allan 	return 0;
317dc49c772SAnirudh Venkataramanan }
318dc49c772SAnirudh Venkataramanan 
319dc49c772SAnirudh Venkataramanan /**
32042449105SAnirudh Venkataramanan  * ice_fill_tx_timer_and_fc_thresh
32142449105SAnirudh Venkataramanan  * @hw: pointer to the HW struct
32242449105SAnirudh Venkataramanan  * @cmd: pointer to MAC cfg structure
32342449105SAnirudh Venkataramanan  *
32442449105SAnirudh Venkataramanan  * Add Tx timer and FC refresh threshold info to Set MAC Config AQ command
32542449105SAnirudh Venkataramanan  * descriptor
32642449105SAnirudh Venkataramanan  */
32742449105SAnirudh Venkataramanan static void
32842449105SAnirudh Venkataramanan ice_fill_tx_timer_and_fc_thresh(struct ice_hw *hw,
32942449105SAnirudh Venkataramanan 				struct ice_aqc_set_mac_cfg *cmd)
33042449105SAnirudh Venkataramanan {
33142449105SAnirudh Venkataramanan 	u16 fc_thres_val, tx_timer_val;
33242449105SAnirudh Venkataramanan 	u32 val;
33342449105SAnirudh Venkataramanan 
33442449105SAnirudh Venkataramanan 	/* We read back the transmit timer and FC threshold value of
33542449105SAnirudh Venkataramanan 	 * LFC. Thus, we will use index =
33642449105SAnirudh Venkataramanan 	 * PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_MAX_INDEX.
33742449105SAnirudh Venkataramanan 	 *
33842449105SAnirudh Venkataramanan 	 * Also, because we are operating on transmit timer and FC
33942449105SAnirudh Venkataramanan 	 * threshold of LFC, we don't turn on any bit in tx_tmr_priority
34042449105SAnirudh Venkataramanan 	 */
34142449105SAnirudh Venkataramanan #define IDX_OF_LFC PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_MAX_INDEX
34242449105SAnirudh Venkataramanan 
34342449105SAnirudh Venkataramanan 	/* Retrieve the transmit timer */
34442449105SAnirudh Venkataramanan 	val = rd32(hw, PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA(IDX_OF_LFC));
34542449105SAnirudh Venkataramanan 	tx_timer_val = val &
34642449105SAnirudh Venkataramanan 		PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_HSEC_CTL_TX_PAUSE_QUANTA_M;
34742449105SAnirudh Venkataramanan 	cmd->tx_tmr_value = cpu_to_le16(tx_timer_val);
34842449105SAnirudh Venkataramanan 
34942449105SAnirudh Venkataramanan 	/* Retrieve the FC threshold */
35042449105SAnirudh Venkataramanan 	val = rd32(hw, PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER(IDX_OF_LFC));
35142449105SAnirudh Venkataramanan 	fc_thres_val = val & PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_M;
35242449105SAnirudh Venkataramanan 
35342449105SAnirudh Venkataramanan 	cmd->fc_refresh_threshold = cpu_to_le16(fc_thres_val);
35442449105SAnirudh Venkataramanan }
35542449105SAnirudh Venkataramanan 
35642449105SAnirudh Venkataramanan /**
35742449105SAnirudh Venkataramanan  * ice_aq_set_mac_cfg
35842449105SAnirudh Venkataramanan  * @hw: pointer to the HW struct
35942449105SAnirudh Venkataramanan  * @max_frame_size: Maximum Frame Size to be supported
36042449105SAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
36142449105SAnirudh Venkataramanan  *
36242449105SAnirudh Venkataramanan  * Set MAC configuration (0x0603)
36342449105SAnirudh Venkataramanan  */
36442449105SAnirudh Venkataramanan enum ice_status
36542449105SAnirudh Venkataramanan ice_aq_set_mac_cfg(struct ice_hw *hw, u16 max_frame_size, struct ice_sq_cd *cd)
36642449105SAnirudh Venkataramanan {
36742449105SAnirudh Venkataramanan 	struct ice_aqc_set_mac_cfg *cmd;
36842449105SAnirudh Venkataramanan 	struct ice_aq_desc desc;
36942449105SAnirudh Venkataramanan 
37042449105SAnirudh Venkataramanan 	cmd = &desc.params.set_mac_cfg;
37142449105SAnirudh Venkataramanan 
37242449105SAnirudh Venkataramanan 	if (max_frame_size == 0)
37342449105SAnirudh Venkataramanan 		return ICE_ERR_PARAM;
37442449105SAnirudh Venkataramanan 
37542449105SAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_mac_cfg);
37642449105SAnirudh Venkataramanan 
37742449105SAnirudh Venkataramanan 	cmd->max_frame_size = cpu_to_le16(max_frame_size);
37842449105SAnirudh Venkataramanan 
37942449105SAnirudh Venkataramanan 	ice_fill_tx_timer_and_fc_thresh(hw, cmd);
38042449105SAnirudh Venkataramanan 
38142449105SAnirudh Venkataramanan 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
38242449105SAnirudh Venkataramanan }
38342449105SAnirudh Venkataramanan 
38442449105SAnirudh Venkataramanan /**
3859daf8208SAnirudh Venkataramanan  * ice_init_fltr_mgmt_struct - initializes filter management list and locks
386f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
3879daf8208SAnirudh Venkataramanan  */
3889daf8208SAnirudh Venkataramanan static enum ice_status ice_init_fltr_mgmt_struct(struct ice_hw *hw)
3899daf8208SAnirudh Venkataramanan {
3909daf8208SAnirudh Venkataramanan 	struct ice_switch_info *sw;
3911aaef2bcSSurabhi Boob 	enum ice_status status;
3929daf8208SAnirudh Venkataramanan 
3939daf8208SAnirudh Venkataramanan 	hw->switch_info = devm_kzalloc(ice_hw_to_dev(hw),
3949daf8208SAnirudh Venkataramanan 				       sizeof(*hw->switch_info), GFP_KERNEL);
3959daf8208SAnirudh Venkataramanan 	sw = hw->switch_info;
3969daf8208SAnirudh Venkataramanan 
3979daf8208SAnirudh Venkataramanan 	if (!sw)
3989daf8208SAnirudh Venkataramanan 		return ICE_ERR_NO_MEMORY;
3999daf8208SAnirudh Venkataramanan 
4009daf8208SAnirudh Venkataramanan 	INIT_LIST_HEAD(&sw->vsi_list_map_head);
4019daf8208SAnirudh Venkataramanan 
4021aaef2bcSSurabhi Boob 	status = ice_init_def_sw_recp(hw);
4031aaef2bcSSurabhi Boob 	if (status) {
4041aaef2bcSSurabhi Boob 		devm_kfree(ice_hw_to_dev(hw), hw->switch_info);
4051aaef2bcSSurabhi Boob 		return status;
4061aaef2bcSSurabhi Boob 	}
4071aaef2bcSSurabhi Boob 	return 0;
4089daf8208SAnirudh Venkataramanan }
4099daf8208SAnirudh Venkataramanan 
4109daf8208SAnirudh Venkataramanan /**
4119daf8208SAnirudh Venkataramanan  * ice_cleanup_fltr_mgmt_struct - cleanup filter management list and locks
412f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
4139daf8208SAnirudh Venkataramanan  */
4149daf8208SAnirudh Venkataramanan static void ice_cleanup_fltr_mgmt_struct(struct ice_hw *hw)
4159daf8208SAnirudh Venkataramanan {
4169daf8208SAnirudh Venkataramanan 	struct ice_switch_info *sw = hw->switch_info;
4179daf8208SAnirudh Venkataramanan 	struct ice_vsi_list_map_info *v_pos_map;
4189daf8208SAnirudh Venkataramanan 	struct ice_vsi_list_map_info *v_tmp_map;
41980d144c9SAnirudh Venkataramanan 	struct ice_sw_recipe *recps;
42080d144c9SAnirudh Venkataramanan 	u8 i;
4219daf8208SAnirudh Venkataramanan 
4229daf8208SAnirudh Venkataramanan 	list_for_each_entry_safe(v_pos_map, v_tmp_map, &sw->vsi_list_map_head,
4239daf8208SAnirudh Venkataramanan 				 list_entry) {
4249daf8208SAnirudh Venkataramanan 		list_del(&v_pos_map->list_entry);
4259daf8208SAnirudh Venkataramanan 		devm_kfree(ice_hw_to_dev(hw), v_pos_map);
4269daf8208SAnirudh Venkataramanan 	}
42780d144c9SAnirudh Venkataramanan 	recps = hw->switch_info->recp_list;
42880d144c9SAnirudh Venkataramanan 	for (i = 0; i < ICE_SW_LKUP_LAST; i++) {
42980d144c9SAnirudh Venkataramanan 		struct ice_fltr_mgmt_list_entry *lst_itr, *tmp_entry;
4309daf8208SAnirudh Venkataramanan 
43180d144c9SAnirudh Venkataramanan 		recps[i].root_rid = i;
43280d144c9SAnirudh Venkataramanan 		mutex_destroy(&recps[i].filt_rule_lock);
43380d144c9SAnirudh Venkataramanan 		list_for_each_entry_safe(lst_itr, tmp_entry,
43480d144c9SAnirudh Venkataramanan 					 &recps[i].filt_rules, list_entry) {
43580d144c9SAnirudh Venkataramanan 			list_del(&lst_itr->list_entry);
43680d144c9SAnirudh Venkataramanan 			devm_kfree(ice_hw_to_dev(hw), lst_itr);
43780d144c9SAnirudh Venkataramanan 		}
43880d144c9SAnirudh Venkataramanan 	}
439334cb062SAnirudh Venkataramanan 	ice_rm_all_sw_replay_rule_info(hw);
44080d144c9SAnirudh Venkataramanan 	devm_kfree(ice_hw_to_dev(hw), sw->recp_list);
4419daf8208SAnirudh Venkataramanan 	devm_kfree(ice_hw_to_dev(hw), sw);
4429daf8208SAnirudh Venkataramanan }
4439daf8208SAnirudh Venkataramanan 
4448b97ceb1SHieu Tran /**
44511fe1b3aSDan Nowlin  * ice_get_fw_log_cfg - get FW logging configuration
44611fe1b3aSDan Nowlin  * @hw: pointer to the HW struct
44711fe1b3aSDan Nowlin  */
44811fe1b3aSDan Nowlin static enum ice_status ice_get_fw_log_cfg(struct ice_hw *hw)
44911fe1b3aSDan Nowlin {
45011fe1b3aSDan Nowlin 	struct ice_aq_desc desc;
45111fe1b3aSDan Nowlin 	enum ice_status status;
452b3c38904SBruce Allan 	__le16 *config;
45311fe1b3aSDan Nowlin 	u16 size;
45411fe1b3aSDan Nowlin 
455b3c38904SBruce Allan 	size = sizeof(*config) * ICE_AQC_FW_LOG_ID_MAX;
45611fe1b3aSDan Nowlin 	config = devm_kzalloc(ice_hw_to_dev(hw), size, GFP_KERNEL);
45711fe1b3aSDan Nowlin 	if (!config)
45811fe1b3aSDan Nowlin 		return ICE_ERR_NO_MEMORY;
45911fe1b3aSDan Nowlin 
46011fe1b3aSDan Nowlin 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_fw_logging_info);
46111fe1b3aSDan Nowlin 
46211fe1b3aSDan Nowlin 	desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
46311fe1b3aSDan Nowlin 
46411fe1b3aSDan Nowlin 	status = ice_aq_send_cmd(hw, &desc, config, size, NULL);
46511fe1b3aSDan Nowlin 	if (!status) {
46611fe1b3aSDan Nowlin 		u16 i;
46711fe1b3aSDan Nowlin 
4682f2da36eSAnirudh Venkataramanan 		/* Save FW logging information into the HW structure */
46911fe1b3aSDan Nowlin 		for (i = 0; i < ICE_AQC_FW_LOG_ID_MAX; i++) {
47011fe1b3aSDan Nowlin 			u16 v, m, flgs;
47111fe1b3aSDan Nowlin 
472b3c38904SBruce Allan 			v = le16_to_cpu(config[i]);
47311fe1b3aSDan Nowlin 			m = (v & ICE_AQC_FW_LOG_ID_M) >> ICE_AQC_FW_LOG_ID_S;
47411fe1b3aSDan Nowlin 			flgs = (v & ICE_AQC_FW_LOG_EN_M) >> ICE_AQC_FW_LOG_EN_S;
47511fe1b3aSDan Nowlin 
47611fe1b3aSDan Nowlin 			if (m < ICE_AQC_FW_LOG_ID_MAX)
47711fe1b3aSDan Nowlin 				hw->fw_log.evnts[m].cur = flgs;
47811fe1b3aSDan Nowlin 		}
47911fe1b3aSDan Nowlin 	}
48011fe1b3aSDan Nowlin 
48111fe1b3aSDan Nowlin 	devm_kfree(ice_hw_to_dev(hw), config);
48211fe1b3aSDan Nowlin 
48311fe1b3aSDan Nowlin 	return status;
48411fe1b3aSDan Nowlin }
48511fe1b3aSDan Nowlin 
48611fe1b3aSDan Nowlin /**
4878b97ceb1SHieu Tran  * ice_cfg_fw_log - configure FW logging
488f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
4898b97ceb1SHieu Tran  * @enable: enable certain FW logging events if true, disable all if false
4908b97ceb1SHieu Tran  *
4918b97ceb1SHieu Tran  * This function enables/disables the FW logging via Rx CQ events and a UART
4928b97ceb1SHieu Tran  * port based on predetermined configurations. FW logging via the Rx CQ can be
4938b97ceb1SHieu Tran  * enabled/disabled for individual PF's. However, FW logging via the UART can
4948b97ceb1SHieu Tran  * only be enabled/disabled for all PFs on the same device.
4958b97ceb1SHieu Tran  *
4968b97ceb1SHieu Tran  * To enable overall FW logging, the "cq_en" and "uart_en" enable bits in
4978b97ceb1SHieu Tran  * hw->fw_log need to be set accordingly, e.g. based on user-provided input,
4988b97ceb1SHieu Tran  * before initializing the device.
4998b97ceb1SHieu Tran  *
5008b97ceb1SHieu Tran  * When re/configuring FW logging, callers need to update the "cfg" elements of
5018b97ceb1SHieu Tran  * the hw->fw_log.evnts array with the desired logging event configurations for
5028b97ceb1SHieu Tran  * modules of interest. When disabling FW logging completely, the callers can
5038b97ceb1SHieu Tran  * just pass false in the "enable" parameter. On completion, the function will
5048b97ceb1SHieu Tran  * update the "cur" element of the hw->fw_log.evnts array with the resulting
5058b97ceb1SHieu Tran  * logging event configurations of the modules that are being re/configured. FW
5068b97ceb1SHieu Tran  * logging modules that are not part of a reconfiguration operation retain their
5078b97ceb1SHieu Tran  * previous states.
5088b97ceb1SHieu Tran  *
5098b97ceb1SHieu Tran  * Before resetting the device, it is recommended that the driver disables FW
5108b97ceb1SHieu Tran  * logging before shutting down the control queue. When disabling FW logging
5118b97ceb1SHieu Tran  * ("enable" = false), the latest configurations of FW logging events stored in
5128b97ceb1SHieu Tran  * hw->fw_log.evnts[] are not overridden to allow them to be reconfigured after
5138b97ceb1SHieu Tran  * a device reset.
5148b97ceb1SHieu Tran  *
5158b97ceb1SHieu Tran  * When enabling FW logging to emit log messages via the Rx CQ during the
5168b97ceb1SHieu Tran  * device's initialization phase, a mechanism alternative to interrupt handlers
5178b97ceb1SHieu Tran  * needs to be used to extract FW log messages from the Rx CQ periodically and
5188b97ceb1SHieu Tran  * to prevent the Rx CQ from being full and stalling other types of control
5198b97ceb1SHieu Tran  * messages from FW to SW. Interrupts are typically disabled during the device's
5208b97ceb1SHieu Tran  * initialization phase.
5218b97ceb1SHieu Tran  */
5228b97ceb1SHieu Tran static enum ice_status ice_cfg_fw_log(struct ice_hw *hw, bool enable)
5238b97ceb1SHieu Tran {
5248b97ceb1SHieu Tran 	struct ice_aqc_fw_logging *cmd;
5258b97ceb1SHieu Tran 	enum ice_status status = 0;
5268b97ceb1SHieu Tran 	u16 i, chgs = 0, len = 0;
5278b97ceb1SHieu Tran 	struct ice_aq_desc desc;
528b3c38904SBruce Allan 	__le16 *data = NULL;
5298b97ceb1SHieu Tran 	u8 actv_evnts = 0;
5308b97ceb1SHieu Tran 	void *buf = NULL;
5318b97ceb1SHieu Tran 
5328b97ceb1SHieu Tran 	if (!hw->fw_log.cq_en && !hw->fw_log.uart_en)
5338b97ceb1SHieu Tran 		return 0;
5348b97ceb1SHieu Tran 
5358b97ceb1SHieu Tran 	/* Disable FW logging only when the control queue is still responsive */
5368b97ceb1SHieu Tran 	if (!enable &&
5378b97ceb1SHieu Tran 	    (!hw->fw_log.actv_evnts || !ice_check_sq_alive(hw, &hw->adminq)))
5388b97ceb1SHieu Tran 		return 0;
5398b97ceb1SHieu Tran 
54011fe1b3aSDan Nowlin 	/* Get current FW log settings */
54111fe1b3aSDan Nowlin 	status = ice_get_fw_log_cfg(hw);
54211fe1b3aSDan Nowlin 	if (status)
54311fe1b3aSDan Nowlin 		return status;
54411fe1b3aSDan Nowlin 
5458b97ceb1SHieu Tran 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_fw_logging);
5468b97ceb1SHieu Tran 	cmd = &desc.params.fw_logging;
5478b97ceb1SHieu Tran 
5488b97ceb1SHieu Tran 	/* Indicate which controls are valid */
5498b97ceb1SHieu Tran 	if (hw->fw_log.cq_en)
5508b97ceb1SHieu Tran 		cmd->log_ctrl_valid |= ICE_AQC_FW_LOG_AQ_VALID;
5518b97ceb1SHieu Tran 
5528b97ceb1SHieu Tran 	if (hw->fw_log.uart_en)
5538b97ceb1SHieu Tran 		cmd->log_ctrl_valid |= ICE_AQC_FW_LOG_UART_VALID;
5548b97ceb1SHieu Tran 
5558b97ceb1SHieu Tran 	if (enable) {
5568b97ceb1SHieu Tran 		/* Fill in an array of entries with FW logging modules and
5578b97ceb1SHieu Tran 		 * logging events being reconfigured.
5588b97ceb1SHieu Tran 		 */
5598b97ceb1SHieu Tran 		for (i = 0; i < ICE_AQC_FW_LOG_ID_MAX; i++) {
5608b97ceb1SHieu Tran 			u16 val;
5618b97ceb1SHieu Tran 
5628b97ceb1SHieu Tran 			/* Keep track of enabled event types */
5638b97ceb1SHieu Tran 			actv_evnts |= hw->fw_log.evnts[i].cfg;
5648b97ceb1SHieu Tran 
5658b97ceb1SHieu Tran 			if (hw->fw_log.evnts[i].cfg == hw->fw_log.evnts[i].cur)
5668b97ceb1SHieu Tran 				continue;
5678b97ceb1SHieu Tran 
5688b97ceb1SHieu Tran 			if (!data) {
569b3c38904SBruce Allan 				data = devm_kcalloc(ice_hw_to_dev(hw),
570b3c38904SBruce Allan 						    sizeof(*data),
571b3c38904SBruce Allan 						    ICE_AQC_FW_LOG_ID_MAX,
5728b97ceb1SHieu Tran 						    GFP_KERNEL);
5738b97ceb1SHieu Tran 				if (!data)
5748b97ceb1SHieu Tran 					return ICE_ERR_NO_MEMORY;
5758b97ceb1SHieu Tran 			}
5768b97ceb1SHieu Tran 
5778b97ceb1SHieu Tran 			val = i << ICE_AQC_FW_LOG_ID_S;
5788b97ceb1SHieu Tran 			val |= hw->fw_log.evnts[i].cfg << ICE_AQC_FW_LOG_EN_S;
579b3c38904SBruce Allan 			data[chgs++] = cpu_to_le16(val);
5808b97ceb1SHieu Tran 		}
5818b97ceb1SHieu Tran 
5828b97ceb1SHieu Tran 		/* Only enable FW logging if at least one module is specified.
5838b97ceb1SHieu Tran 		 * If FW logging is currently enabled but all modules are not
5848b97ceb1SHieu Tran 		 * enabled to emit log messages, disable FW logging altogether.
5858b97ceb1SHieu Tran 		 */
5868b97ceb1SHieu Tran 		if (actv_evnts) {
5878b97ceb1SHieu Tran 			/* Leave if there is effectively no change */
5888b97ceb1SHieu Tran 			if (!chgs)
5898b97ceb1SHieu Tran 				goto out;
5908b97ceb1SHieu Tran 
5918b97ceb1SHieu Tran 			if (hw->fw_log.cq_en)
5928b97ceb1SHieu Tran 				cmd->log_ctrl |= ICE_AQC_FW_LOG_AQ_EN;
5938b97ceb1SHieu Tran 
5948b97ceb1SHieu Tran 			if (hw->fw_log.uart_en)
5958b97ceb1SHieu Tran 				cmd->log_ctrl |= ICE_AQC_FW_LOG_UART_EN;
5968b97ceb1SHieu Tran 
5978b97ceb1SHieu Tran 			buf = data;
598b3c38904SBruce Allan 			len = sizeof(*data) * chgs;
5998b97ceb1SHieu Tran 			desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
6008b97ceb1SHieu Tran 		}
6018b97ceb1SHieu Tran 	}
6028b97ceb1SHieu Tran 
6038b97ceb1SHieu Tran 	status = ice_aq_send_cmd(hw, &desc, buf, len, NULL);
6048b97ceb1SHieu Tran 	if (!status) {
6058b97ceb1SHieu Tran 		/* Update the current configuration to reflect events enabled.
6068b97ceb1SHieu Tran 		 * hw->fw_log.cq_en and hw->fw_log.uart_en indicate if the FW
6078b97ceb1SHieu Tran 		 * logging mode is enabled for the device. They do not reflect
6088b97ceb1SHieu Tran 		 * actual modules being enabled to emit log messages. So, their
6098b97ceb1SHieu Tran 		 * values remain unchanged even when all modules are disabled.
6108b97ceb1SHieu Tran 		 */
6118b97ceb1SHieu Tran 		u16 cnt = enable ? chgs : (u16)ICE_AQC_FW_LOG_ID_MAX;
6128b97ceb1SHieu Tran 
6138b97ceb1SHieu Tran 		hw->fw_log.actv_evnts = actv_evnts;
6148b97ceb1SHieu Tran 		for (i = 0; i < cnt; i++) {
6158b97ceb1SHieu Tran 			u16 v, m;
6168b97ceb1SHieu Tran 
6178b97ceb1SHieu Tran 			if (!enable) {
6188b97ceb1SHieu Tran 				/* When disabling all FW logging events as part
6198b97ceb1SHieu Tran 				 * of device's de-initialization, the original
6208b97ceb1SHieu Tran 				 * configurations are retained, and can be used
6218b97ceb1SHieu Tran 				 * to reconfigure FW logging later if the device
6228b97ceb1SHieu Tran 				 * is re-initialized.
6238b97ceb1SHieu Tran 				 */
6248b97ceb1SHieu Tran 				hw->fw_log.evnts[i].cur = 0;
6258b97ceb1SHieu Tran 				continue;
6268b97ceb1SHieu Tran 			}
6278b97ceb1SHieu Tran 
628b3c38904SBruce Allan 			v = le16_to_cpu(data[i]);
6298b97ceb1SHieu Tran 			m = (v & ICE_AQC_FW_LOG_ID_M) >> ICE_AQC_FW_LOG_ID_S;
6308b97ceb1SHieu Tran 			hw->fw_log.evnts[m].cur = hw->fw_log.evnts[m].cfg;
6318b97ceb1SHieu Tran 		}
6328b97ceb1SHieu Tran 	}
6338b97ceb1SHieu Tran 
6348b97ceb1SHieu Tran out:
6358b97ceb1SHieu Tran 	if (data)
6368b97ceb1SHieu Tran 		devm_kfree(ice_hw_to_dev(hw), data);
6378b97ceb1SHieu Tran 
6388b97ceb1SHieu Tran 	return status;
6398b97ceb1SHieu Tran }
6408b97ceb1SHieu Tran 
6418b97ceb1SHieu Tran /**
6428b97ceb1SHieu Tran  * ice_output_fw_log
643f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
6448b97ceb1SHieu Tran  * @desc: pointer to the AQ message descriptor
6458b97ceb1SHieu Tran  * @buf: pointer to the buffer accompanying the AQ message
6468b97ceb1SHieu Tran  *
6478b97ceb1SHieu Tran  * Formats a FW Log message and outputs it via the standard driver logs.
6488b97ceb1SHieu Tran  */
6498b97ceb1SHieu Tran void ice_output_fw_log(struct ice_hw *hw, struct ice_aq_desc *desc, void *buf)
6508b97ceb1SHieu Tran {
6514f70daa0SJacob Keller 	ice_debug(hw, ICE_DBG_FW_LOG, "[ FW Log Msg Start ]\n");
6524f70daa0SJacob Keller 	ice_debug_array(hw, ICE_DBG_FW_LOG, 16, 1, (u8 *)buf,
6538b97ceb1SHieu Tran 			le16_to_cpu(desc->datalen));
6544f70daa0SJacob Keller 	ice_debug(hw, ICE_DBG_FW_LOG, "[ FW Log Msg End ]\n");
6558b97ceb1SHieu Tran }
6568b97ceb1SHieu Tran 
6579daf8208SAnirudh Venkataramanan /**
6584ee656bbSTony Nguyen  * ice_get_itr_intrl_gran
659f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
6609e4ab4c2SBrett Creeley  *
6614ee656bbSTony Nguyen  * Determines the ITR/INTRL granularities based on the maximum aggregate
6629e4ab4c2SBrett Creeley  * bandwidth according to the device's configuration during power-on.
6639e4ab4c2SBrett Creeley  */
664fe7219faSBruce Allan static void ice_get_itr_intrl_gran(struct ice_hw *hw)
6659e4ab4c2SBrett Creeley {
6669e4ab4c2SBrett Creeley 	u8 max_agg_bw = (rd32(hw, GL_PWR_MODE_CTL) &
6679e4ab4c2SBrett Creeley 			 GL_PWR_MODE_CTL_CAR_MAX_BW_M) >>
6689e4ab4c2SBrett Creeley 			GL_PWR_MODE_CTL_CAR_MAX_BW_S;
6699e4ab4c2SBrett Creeley 
6709e4ab4c2SBrett Creeley 	switch (max_agg_bw) {
6719e4ab4c2SBrett Creeley 	case ICE_MAX_AGG_BW_200G:
6729e4ab4c2SBrett Creeley 	case ICE_MAX_AGG_BW_100G:
6739e4ab4c2SBrett Creeley 	case ICE_MAX_AGG_BW_50G:
6749e4ab4c2SBrett Creeley 		hw->itr_gran = ICE_ITR_GRAN_ABOVE_25;
6759e4ab4c2SBrett Creeley 		hw->intrl_gran = ICE_INTRL_GRAN_ABOVE_25;
6769e4ab4c2SBrett Creeley 		break;
6779e4ab4c2SBrett Creeley 	case ICE_MAX_AGG_BW_25G:
6789e4ab4c2SBrett Creeley 		hw->itr_gran = ICE_ITR_GRAN_MAX_25;
6799e4ab4c2SBrett Creeley 		hw->intrl_gran = ICE_INTRL_GRAN_MAX_25;
6809e4ab4c2SBrett Creeley 		break;
6819e4ab4c2SBrett Creeley 	}
6829e4ab4c2SBrett Creeley }
6839e4ab4c2SBrett Creeley 
6849e4ab4c2SBrett Creeley /**
685f31e4b6fSAnirudh Venkataramanan  * ice_init_hw - main hardware initialization routine
686f31e4b6fSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
687f31e4b6fSAnirudh Venkataramanan  */
688f31e4b6fSAnirudh Venkataramanan enum ice_status ice_init_hw(struct ice_hw *hw)
689f31e4b6fSAnirudh Venkataramanan {
690dc49c772SAnirudh Venkataramanan 	struct ice_aqc_get_phy_caps_data *pcaps;
691f31e4b6fSAnirudh Venkataramanan 	enum ice_status status;
692dc49c772SAnirudh Venkataramanan 	u16 mac_buf_len;
693dc49c772SAnirudh Venkataramanan 	void *mac_buf;
694f31e4b6fSAnirudh Venkataramanan 
695f31e4b6fSAnirudh Venkataramanan 	/* Set MAC type based on DeviceID */
696f31e4b6fSAnirudh Venkataramanan 	status = ice_set_mac_type(hw);
697f31e4b6fSAnirudh Venkataramanan 	if (status)
698f31e4b6fSAnirudh Venkataramanan 		return status;
699f31e4b6fSAnirudh Venkataramanan 
700f31e4b6fSAnirudh Venkataramanan 	hw->pf_id = (u8)(rd32(hw, PF_FUNC_RID) &
701f31e4b6fSAnirudh Venkataramanan 			 PF_FUNC_RID_FUNC_NUM_M) >>
702f31e4b6fSAnirudh Venkataramanan 		PF_FUNC_RID_FUNC_NUM_S;
703f31e4b6fSAnirudh Venkataramanan 
704f31e4b6fSAnirudh Venkataramanan 	status = ice_reset(hw, ICE_RESET_PFR);
705f31e4b6fSAnirudh Venkataramanan 	if (status)
706f31e4b6fSAnirudh Venkataramanan 		return status;
707f31e4b6fSAnirudh Venkataramanan 
708fe7219faSBruce Allan 	ice_get_itr_intrl_gran(hw);
709940b61afSAnirudh Venkataramanan 
7105c91ecfdSJacob Keller 	status = ice_create_all_ctrlq(hw);
711f31e4b6fSAnirudh Venkataramanan 	if (status)
712f31e4b6fSAnirudh Venkataramanan 		goto err_unroll_cqinit;
713f31e4b6fSAnirudh Venkataramanan 
7148b97ceb1SHieu Tran 	/* Enable FW logging. Not fatal if this fails. */
7158b97ceb1SHieu Tran 	status = ice_cfg_fw_log(hw, true);
7168b97ceb1SHieu Tran 	if (status)
7178b97ceb1SHieu Tran 		ice_debug(hw, ICE_DBG_INIT, "Failed to enable FW logging.\n");
7188b97ceb1SHieu Tran 
719f31e4b6fSAnirudh Venkataramanan 	status = ice_clear_pf_cfg(hw);
720f31e4b6fSAnirudh Venkataramanan 	if (status)
721f31e4b6fSAnirudh Venkataramanan 		goto err_unroll_cqinit;
722f31e4b6fSAnirudh Venkataramanan 
723148beb61SHenry Tieman 	/* Set bit to enable Flow Director filters */
724148beb61SHenry Tieman 	wr32(hw, PFQF_FD_ENA, PFQF_FD_ENA_FD_ENA_M);
725148beb61SHenry Tieman 	INIT_LIST_HEAD(&hw->fdir_list_head);
726148beb61SHenry Tieman 
727f31e4b6fSAnirudh Venkataramanan 	ice_clear_pxe_mode(hw);
728f31e4b6fSAnirudh Venkataramanan 
729f31e4b6fSAnirudh Venkataramanan 	status = ice_init_nvm(hw);
730f31e4b6fSAnirudh Venkataramanan 	if (status)
731f31e4b6fSAnirudh Venkataramanan 		goto err_unroll_cqinit;
732f31e4b6fSAnirudh Venkataramanan 
7339c20346bSAnirudh Venkataramanan 	status = ice_get_caps(hw);
7349c20346bSAnirudh Venkataramanan 	if (status)
7359c20346bSAnirudh Venkataramanan 		goto err_unroll_cqinit;
7369c20346bSAnirudh Venkataramanan 
7379c20346bSAnirudh Venkataramanan 	hw->port_info = devm_kzalloc(ice_hw_to_dev(hw),
7389c20346bSAnirudh Venkataramanan 				     sizeof(*hw->port_info), GFP_KERNEL);
7399c20346bSAnirudh Venkataramanan 	if (!hw->port_info) {
7409c20346bSAnirudh Venkataramanan 		status = ICE_ERR_NO_MEMORY;
7419c20346bSAnirudh Venkataramanan 		goto err_unroll_cqinit;
7429c20346bSAnirudh Venkataramanan 	}
7439c20346bSAnirudh Venkataramanan 
744f9867df6SAnirudh Venkataramanan 	/* set the back pointer to HW */
7459c20346bSAnirudh Venkataramanan 	hw->port_info->hw = hw;
7469c20346bSAnirudh Venkataramanan 
7479c20346bSAnirudh Venkataramanan 	/* Initialize port_info struct with switch configuration data */
7489c20346bSAnirudh Venkataramanan 	status = ice_get_initial_sw_cfg(hw);
7499c20346bSAnirudh Venkataramanan 	if (status)
7509c20346bSAnirudh Venkataramanan 		goto err_unroll_alloc;
7519c20346bSAnirudh Venkataramanan 
7529daf8208SAnirudh Venkataramanan 	hw->evb_veb = true;
7539daf8208SAnirudh Venkataramanan 
754d337f2afSAnirudh Venkataramanan 	/* Query the allocated resources for Tx scheduler */
7559c20346bSAnirudh Venkataramanan 	status = ice_sched_query_res_alloc(hw);
7569c20346bSAnirudh Venkataramanan 	if (status) {
7579c20346bSAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_SCHED,
7589c20346bSAnirudh Venkataramanan 			  "Failed to get scheduler allocated resources\n");
7599c20346bSAnirudh Venkataramanan 		goto err_unroll_alloc;
7609c20346bSAnirudh Venkataramanan 	}
7619c20346bSAnirudh Venkataramanan 
762dc49c772SAnirudh Venkataramanan 	/* Initialize port_info struct with scheduler data */
763dc49c772SAnirudh Venkataramanan 	status = ice_sched_init_port(hw->port_info);
764dc49c772SAnirudh Venkataramanan 	if (status)
765dc49c772SAnirudh Venkataramanan 		goto err_unroll_sched;
766dc49c772SAnirudh Venkataramanan 
767dc49c772SAnirudh Venkataramanan 	pcaps = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*pcaps), GFP_KERNEL);
768dc49c772SAnirudh Venkataramanan 	if (!pcaps) {
769dc49c772SAnirudh Venkataramanan 		status = ICE_ERR_NO_MEMORY;
770dc49c772SAnirudh Venkataramanan 		goto err_unroll_sched;
771dc49c772SAnirudh Venkataramanan 	}
772dc49c772SAnirudh Venkataramanan 
773dc49c772SAnirudh Venkataramanan 	/* Initialize port_info struct with PHY capabilities */
774dc49c772SAnirudh Venkataramanan 	status = ice_aq_get_phy_caps(hw->port_info, false,
775dc49c772SAnirudh Venkataramanan 				     ICE_AQC_REPORT_TOPO_CAP, pcaps, NULL);
776dc49c772SAnirudh Venkataramanan 	devm_kfree(ice_hw_to_dev(hw), pcaps);
777dc49c772SAnirudh Venkataramanan 	if (status)
778dc49c772SAnirudh Venkataramanan 		goto err_unroll_sched;
779dc49c772SAnirudh Venkataramanan 
780dc49c772SAnirudh Venkataramanan 	/* Initialize port_info struct with link information */
781dc49c772SAnirudh Venkataramanan 	status = ice_aq_get_link_info(hw->port_info, false, NULL, NULL);
782dc49c772SAnirudh Venkataramanan 	if (status)
783dc49c772SAnirudh Venkataramanan 		goto err_unroll_sched;
784dc49c772SAnirudh Venkataramanan 
785b36c598cSAnirudh Venkataramanan 	/* need a valid SW entry point to build a Tx tree */
786b36c598cSAnirudh Venkataramanan 	if (!hw->sw_entry_point_layer) {
787b36c598cSAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_SCHED, "invalid sw entry point\n");
788b36c598cSAnirudh Venkataramanan 		status = ICE_ERR_CFG;
789b36c598cSAnirudh Venkataramanan 		goto err_unroll_sched;
790b36c598cSAnirudh Venkataramanan 	}
7919be1d6f8SAnirudh Venkataramanan 	INIT_LIST_HEAD(&hw->agg_list);
7921ddef455SUsha Ketineni 	/* Initialize max burst size */
7931ddef455SUsha Ketineni 	if (!hw->max_burst_size)
7941ddef455SUsha Ketineni 		ice_cfg_rl_burst_size(hw, ICE_SCHED_DFLT_BURST_SIZE);
795b36c598cSAnirudh Venkataramanan 
7969daf8208SAnirudh Venkataramanan 	status = ice_init_fltr_mgmt_struct(hw);
7979daf8208SAnirudh Venkataramanan 	if (status)
7989daf8208SAnirudh Venkataramanan 		goto err_unroll_sched;
7999daf8208SAnirudh Venkataramanan 
800d6fef10cSMd Fahad Iqbal Polash 	/* Get MAC information */
801d6fef10cSMd Fahad Iqbal Polash 	/* A single port can report up to two (LAN and WoL) addresses */
802d6fef10cSMd Fahad Iqbal Polash 	mac_buf = devm_kcalloc(ice_hw_to_dev(hw), 2,
803d6fef10cSMd Fahad Iqbal Polash 			       sizeof(struct ice_aqc_manage_mac_read_resp),
804d6fef10cSMd Fahad Iqbal Polash 			       GFP_KERNEL);
805d6fef10cSMd Fahad Iqbal Polash 	mac_buf_len = 2 * sizeof(struct ice_aqc_manage_mac_read_resp);
806dc49c772SAnirudh Venkataramanan 
80763bb4e1eSWei Yongjun 	if (!mac_buf) {
80863bb4e1eSWei Yongjun 		status = ICE_ERR_NO_MEMORY;
8099daf8208SAnirudh Venkataramanan 		goto err_unroll_fltr_mgmt_struct;
81063bb4e1eSWei Yongjun 	}
811dc49c772SAnirudh Venkataramanan 
812dc49c772SAnirudh Venkataramanan 	status = ice_aq_manage_mac_read(hw, mac_buf, mac_buf_len, NULL);
813dc49c772SAnirudh Venkataramanan 	devm_kfree(ice_hw_to_dev(hw), mac_buf);
814dc49c772SAnirudh Venkataramanan 
815dc49c772SAnirudh Venkataramanan 	if (status)
8169daf8208SAnirudh Venkataramanan 		goto err_unroll_fltr_mgmt_struct;
81742449105SAnirudh Venkataramanan 	/* enable jumbo frame support at MAC level */
81842449105SAnirudh Venkataramanan 	status = ice_aq_set_mac_cfg(hw, ICE_AQ_SET_MAC_FRAME_SIZE_MAX, NULL);
81942449105SAnirudh Venkataramanan 	if (status)
82042449105SAnirudh Venkataramanan 		goto err_unroll_fltr_mgmt_struct;
821148beb61SHenry Tieman 	/* Obtain counter base index which would be used by flow director */
822148beb61SHenry Tieman 	status = ice_alloc_fd_res_cntr(hw, &hw->fd_ctr_base);
823148beb61SHenry Tieman 	if (status)
824148beb61SHenry Tieman 		goto err_unroll_fltr_mgmt_struct;
82532d63fa1STony Nguyen 	status = ice_init_hw_tbls(hw);
82632d63fa1STony Nguyen 	if (status)
82732d63fa1STony Nguyen 		goto err_unroll_fltr_mgmt_struct;
828a4e82a81STony Nguyen 	mutex_init(&hw->tnl_lock);
829f31e4b6fSAnirudh Venkataramanan 	return 0;
830f31e4b6fSAnirudh Venkataramanan 
8319daf8208SAnirudh Venkataramanan err_unroll_fltr_mgmt_struct:
8329daf8208SAnirudh Venkataramanan 	ice_cleanup_fltr_mgmt_struct(hw);
833dc49c772SAnirudh Venkataramanan err_unroll_sched:
834dc49c772SAnirudh Venkataramanan 	ice_sched_cleanup_all(hw);
8359c20346bSAnirudh Venkataramanan err_unroll_alloc:
8369c20346bSAnirudh Venkataramanan 	devm_kfree(ice_hw_to_dev(hw), hw->port_info);
837f31e4b6fSAnirudh Venkataramanan err_unroll_cqinit:
8385c91ecfdSJacob Keller 	ice_destroy_all_ctrlq(hw);
839f31e4b6fSAnirudh Venkataramanan 	return status;
840f31e4b6fSAnirudh Venkataramanan }
841f31e4b6fSAnirudh Venkataramanan 
842f31e4b6fSAnirudh Venkataramanan /**
843f31e4b6fSAnirudh Venkataramanan  * ice_deinit_hw - unroll initialization operations done by ice_init_hw
844f31e4b6fSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
845ed14245aSAnirudh Venkataramanan  *
846ed14245aSAnirudh Venkataramanan  * This should be called only during nominal operation, not as a result of
847ed14245aSAnirudh Venkataramanan  * ice_init_hw() failing since ice_init_hw() will take care of unrolling
848ed14245aSAnirudh Venkataramanan  * applicable initializations if it fails for any reason.
849f31e4b6fSAnirudh Venkataramanan  */
850f31e4b6fSAnirudh Venkataramanan void ice_deinit_hw(struct ice_hw *hw)
851f31e4b6fSAnirudh Venkataramanan {
852148beb61SHenry Tieman 	ice_free_fd_res_cntr(hw, hw->fd_ctr_base);
8538b97ceb1SHieu Tran 	ice_cleanup_fltr_mgmt_struct(hw);
8548b97ceb1SHieu Tran 
8559c20346bSAnirudh Venkataramanan 	ice_sched_cleanup_all(hw);
8569be1d6f8SAnirudh Venkataramanan 	ice_sched_clear_agg(hw);
857c7648810STony Nguyen 	ice_free_seg(hw);
85832d63fa1STony Nguyen 	ice_free_hw_tbls(hw);
859a4e82a81STony Nguyen 	mutex_destroy(&hw->tnl_lock);
860dc49c772SAnirudh Venkataramanan 
8619c20346bSAnirudh Venkataramanan 	if (hw->port_info) {
8629c20346bSAnirudh Venkataramanan 		devm_kfree(ice_hw_to_dev(hw), hw->port_info);
8639c20346bSAnirudh Venkataramanan 		hw->port_info = NULL;
8649c20346bSAnirudh Venkataramanan 	}
8659daf8208SAnirudh Venkataramanan 
8668b97ceb1SHieu Tran 	/* Attempt to disable FW logging before shutting down control queues */
8678b97ceb1SHieu Tran 	ice_cfg_fw_log(hw, false);
8685c91ecfdSJacob Keller 	ice_destroy_all_ctrlq(hw);
86933e055fcSVictor Raj 
87033e055fcSVictor Raj 	/* Clear VSI contexts if not already cleared */
87133e055fcSVictor Raj 	ice_clear_all_vsi_ctx(hw);
872f31e4b6fSAnirudh Venkataramanan }
873f31e4b6fSAnirudh Venkataramanan 
874f31e4b6fSAnirudh Venkataramanan /**
875f31e4b6fSAnirudh Venkataramanan  * ice_check_reset - Check to see if a global reset is complete
876f31e4b6fSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
877f31e4b6fSAnirudh Venkataramanan  */
878f31e4b6fSAnirudh Venkataramanan enum ice_status ice_check_reset(struct ice_hw *hw)
879f31e4b6fSAnirudh Venkataramanan {
880cf8fc2a0SBruce Allan 	u32 cnt, reg = 0, grst_delay, uld_mask;
881f31e4b6fSAnirudh Venkataramanan 
882f31e4b6fSAnirudh Venkataramanan 	/* Poll for Device Active state in case a recent CORER, GLOBR,
883f31e4b6fSAnirudh Venkataramanan 	 * or EMPR has occurred. The grst delay value is in 100ms units.
884f31e4b6fSAnirudh Venkataramanan 	 * Add 1sec for outstanding AQ commands that can take a long time.
885f31e4b6fSAnirudh Venkataramanan 	 */
886f31e4b6fSAnirudh Venkataramanan 	grst_delay = ((rd32(hw, GLGEN_RSTCTL) & GLGEN_RSTCTL_GRSTDEL_M) >>
887f31e4b6fSAnirudh Venkataramanan 		      GLGEN_RSTCTL_GRSTDEL_S) + 10;
888f31e4b6fSAnirudh Venkataramanan 
889f31e4b6fSAnirudh Venkataramanan 	for (cnt = 0; cnt < grst_delay; cnt++) {
890f31e4b6fSAnirudh Venkataramanan 		mdelay(100);
891f31e4b6fSAnirudh Venkataramanan 		reg = rd32(hw, GLGEN_RSTAT);
892f31e4b6fSAnirudh Venkataramanan 		if (!(reg & GLGEN_RSTAT_DEVSTATE_M))
893f31e4b6fSAnirudh Venkataramanan 			break;
894f31e4b6fSAnirudh Venkataramanan 	}
895f31e4b6fSAnirudh Venkataramanan 
896f31e4b6fSAnirudh Venkataramanan 	if (cnt == grst_delay) {
897f31e4b6fSAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_INIT,
898f31e4b6fSAnirudh Venkataramanan 			  "Global reset polling failed to complete.\n");
899f31e4b6fSAnirudh Venkataramanan 		return ICE_ERR_RESET_FAILED;
900f31e4b6fSAnirudh Venkataramanan 	}
901f31e4b6fSAnirudh Venkataramanan 
902cf8fc2a0SBruce Allan #define ICE_RESET_DONE_MASK	(GLNVM_ULD_PCIER_DONE_M |\
903cf8fc2a0SBruce Allan 				 GLNVM_ULD_PCIER_DONE_1_M |\
904cf8fc2a0SBruce Allan 				 GLNVM_ULD_CORER_DONE_M |\
905cf8fc2a0SBruce Allan 				 GLNVM_ULD_GLOBR_DONE_M |\
906cf8fc2a0SBruce Allan 				 GLNVM_ULD_POR_DONE_M |\
907cf8fc2a0SBruce Allan 				 GLNVM_ULD_POR_DONE_1_M |\
908cf8fc2a0SBruce Allan 				 GLNVM_ULD_PCIER_DONE_2_M)
909cf8fc2a0SBruce Allan 
910cf8fc2a0SBruce Allan 	uld_mask = ICE_RESET_DONE_MASK;
911f31e4b6fSAnirudh Venkataramanan 
912f31e4b6fSAnirudh Venkataramanan 	/* Device is Active; check Global Reset processes are done */
913f31e4b6fSAnirudh Venkataramanan 	for (cnt = 0; cnt < ICE_PF_RESET_WAIT_COUNT; cnt++) {
914cf8fc2a0SBruce Allan 		reg = rd32(hw, GLNVM_ULD) & uld_mask;
915cf8fc2a0SBruce Allan 		if (reg == uld_mask) {
916f31e4b6fSAnirudh Venkataramanan 			ice_debug(hw, ICE_DBG_INIT,
917f31e4b6fSAnirudh Venkataramanan 				  "Global reset processes done. %d\n", cnt);
918f31e4b6fSAnirudh Venkataramanan 			break;
919f31e4b6fSAnirudh Venkataramanan 		}
920f31e4b6fSAnirudh Venkataramanan 		mdelay(10);
921f31e4b6fSAnirudh Venkataramanan 	}
922f31e4b6fSAnirudh Venkataramanan 
923f31e4b6fSAnirudh Venkataramanan 	if (cnt == ICE_PF_RESET_WAIT_COUNT) {
924f31e4b6fSAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_INIT,
925f31e4b6fSAnirudh Venkataramanan 			  "Wait for Reset Done timed out. GLNVM_ULD = 0x%x\n",
926f31e4b6fSAnirudh Venkataramanan 			  reg);
927f31e4b6fSAnirudh Venkataramanan 		return ICE_ERR_RESET_FAILED;
928f31e4b6fSAnirudh Venkataramanan 	}
929f31e4b6fSAnirudh Venkataramanan 
930f31e4b6fSAnirudh Venkataramanan 	return 0;
931f31e4b6fSAnirudh Venkataramanan }
932f31e4b6fSAnirudh Venkataramanan 
933f31e4b6fSAnirudh Venkataramanan /**
934f31e4b6fSAnirudh Venkataramanan  * ice_pf_reset - Reset the PF
935f31e4b6fSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
936f31e4b6fSAnirudh Venkataramanan  *
937f31e4b6fSAnirudh Venkataramanan  * If a global reset has been triggered, this function checks
938f31e4b6fSAnirudh Venkataramanan  * for its completion and then issues the PF reset
939f31e4b6fSAnirudh Venkataramanan  */
940f31e4b6fSAnirudh Venkataramanan static enum ice_status ice_pf_reset(struct ice_hw *hw)
941f31e4b6fSAnirudh Venkataramanan {
942f31e4b6fSAnirudh Venkataramanan 	u32 cnt, reg;
943f31e4b6fSAnirudh Venkataramanan 
944f31e4b6fSAnirudh Venkataramanan 	/* If at function entry a global reset was already in progress, i.e.
945f31e4b6fSAnirudh Venkataramanan 	 * state is not 'device active' or any of the reset done bits are not
946f31e4b6fSAnirudh Venkataramanan 	 * set in GLNVM_ULD, there is no need for a PF Reset; poll until the
947f31e4b6fSAnirudh Venkataramanan 	 * global reset is done.
948f31e4b6fSAnirudh Venkataramanan 	 */
949f31e4b6fSAnirudh Venkataramanan 	if ((rd32(hw, GLGEN_RSTAT) & GLGEN_RSTAT_DEVSTATE_M) ||
950f31e4b6fSAnirudh Venkataramanan 	    (rd32(hw, GLNVM_ULD) & ICE_RESET_DONE_MASK) ^ ICE_RESET_DONE_MASK) {
951f31e4b6fSAnirudh Venkataramanan 		/* poll on global reset currently in progress until done */
952f31e4b6fSAnirudh Venkataramanan 		if (ice_check_reset(hw))
953f31e4b6fSAnirudh Venkataramanan 			return ICE_ERR_RESET_FAILED;
954f31e4b6fSAnirudh Venkataramanan 
955f31e4b6fSAnirudh Venkataramanan 		return 0;
956f31e4b6fSAnirudh Venkataramanan 	}
957f31e4b6fSAnirudh Venkataramanan 
958f31e4b6fSAnirudh Venkataramanan 	/* Reset the PF */
959f31e4b6fSAnirudh Venkataramanan 	reg = rd32(hw, PFGEN_CTRL);
960f31e4b6fSAnirudh Venkataramanan 
961f31e4b6fSAnirudh Venkataramanan 	wr32(hw, PFGEN_CTRL, (reg | PFGEN_CTRL_PFSWR_M));
962f31e4b6fSAnirudh Venkataramanan 
963c9a12d6dSDan Nowlin 	/* Wait for the PFR to complete. The wait time is the global config lock
964c9a12d6dSDan Nowlin 	 * timeout plus the PFR timeout which will account for a possible reset
965c9a12d6dSDan Nowlin 	 * that is occurring during a download package operation.
966c9a12d6dSDan Nowlin 	 */
967c9a12d6dSDan Nowlin 	for (cnt = 0; cnt < ICE_GLOBAL_CFG_LOCK_TIMEOUT +
968c9a12d6dSDan Nowlin 	     ICE_PF_RESET_WAIT_COUNT; cnt++) {
969f31e4b6fSAnirudh Venkataramanan 		reg = rd32(hw, PFGEN_CTRL);
970f31e4b6fSAnirudh Venkataramanan 		if (!(reg & PFGEN_CTRL_PFSWR_M))
971f31e4b6fSAnirudh Venkataramanan 			break;
972f31e4b6fSAnirudh Venkataramanan 
973f31e4b6fSAnirudh Venkataramanan 		mdelay(1);
974f31e4b6fSAnirudh Venkataramanan 	}
975f31e4b6fSAnirudh Venkataramanan 
976f31e4b6fSAnirudh Venkataramanan 	if (cnt == ICE_PF_RESET_WAIT_COUNT) {
977f31e4b6fSAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_INIT,
978f31e4b6fSAnirudh Venkataramanan 			  "PF reset polling failed to complete.\n");
979f31e4b6fSAnirudh Venkataramanan 		return ICE_ERR_RESET_FAILED;
980f31e4b6fSAnirudh Venkataramanan 	}
981f31e4b6fSAnirudh Venkataramanan 
982f31e4b6fSAnirudh Venkataramanan 	return 0;
983f31e4b6fSAnirudh Venkataramanan }
984f31e4b6fSAnirudh Venkataramanan 
985f31e4b6fSAnirudh Venkataramanan /**
986f31e4b6fSAnirudh Venkataramanan  * ice_reset - Perform different types of reset
987f31e4b6fSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
988f31e4b6fSAnirudh Venkataramanan  * @req: reset request
989f31e4b6fSAnirudh Venkataramanan  *
990f31e4b6fSAnirudh Venkataramanan  * This function triggers a reset as specified by the req parameter.
991f31e4b6fSAnirudh Venkataramanan  *
992f31e4b6fSAnirudh Venkataramanan  * Note:
993f31e4b6fSAnirudh Venkataramanan  * If anything other than a PF reset is triggered, PXE mode is restored.
994f31e4b6fSAnirudh Venkataramanan  * This has to be cleared using ice_clear_pxe_mode again, once the AQ
995f31e4b6fSAnirudh Venkataramanan  * interface has been restored in the rebuild flow.
996f31e4b6fSAnirudh Venkataramanan  */
997f31e4b6fSAnirudh Venkataramanan enum ice_status ice_reset(struct ice_hw *hw, enum ice_reset_req req)
998f31e4b6fSAnirudh Venkataramanan {
999f31e4b6fSAnirudh Venkataramanan 	u32 val = 0;
1000f31e4b6fSAnirudh Venkataramanan 
1001f31e4b6fSAnirudh Venkataramanan 	switch (req) {
1002f31e4b6fSAnirudh Venkataramanan 	case ICE_RESET_PFR:
1003f31e4b6fSAnirudh Venkataramanan 		return ice_pf_reset(hw);
1004f31e4b6fSAnirudh Venkataramanan 	case ICE_RESET_CORER:
1005f31e4b6fSAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_INIT, "CoreR requested\n");
1006f31e4b6fSAnirudh Venkataramanan 		val = GLGEN_RTRIG_CORER_M;
1007f31e4b6fSAnirudh Venkataramanan 		break;
1008f31e4b6fSAnirudh Venkataramanan 	case ICE_RESET_GLOBR:
1009f31e4b6fSAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_INIT, "GlobalR requested\n");
1010f31e4b6fSAnirudh Venkataramanan 		val = GLGEN_RTRIG_GLOBR_M;
1011f31e4b6fSAnirudh Venkataramanan 		break;
10120f9d5027SAnirudh Venkataramanan 	default:
10130f9d5027SAnirudh Venkataramanan 		return ICE_ERR_PARAM;
1014f31e4b6fSAnirudh Venkataramanan 	}
1015f31e4b6fSAnirudh Venkataramanan 
1016f31e4b6fSAnirudh Venkataramanan 	val |= rd32(hw, GLGEN_RTRIG);
1017f31e4b6fSAnirudh Venkataramanan 	wr32(hw, GLGEN_RTRIG, val);
1018f31e4b6fSAnirudh Venkataramanan 	ice_flush(hw);
1019f31e4b6fSAnirudh Venkataramanan 
1020f31e4b6fSAnirudh Venkataramanan 	/* wait for the FW to be ready */
1021f31e4b6fSAnirudh Venkataramanan 	return ice_check_reset(hw);
1022f31e4b6fSAnirudh Venkataramanan }
1023f31e4b6fSAnirudh Venkataramanan 
10247ec59eeaSAnirudh Venkataramanan /**
1025cdedef59SAnirudh Venkataramanan  * ice_copy_rxq_ctx_to_hw
1026cdedef59SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
1027cdedef59SAnirudh Venkataramanan  * @ice_rxq_ctx: pointer to the rxq context
1028d337f2afSAnirudh Venkataramanan  * @rxq_index: the index of the Rx queue
1029cdedef59SAnirudh Venkataramanan  *
1030f9867df6SAnirudh Venkataramanan  * Copies rxq context from dense structure to HW register space
1031cdedef59SAnirudh Venkataramanan  */
1032cdedef59SAnirudh Venkataramanan static enum ice_status
1033cdedef59SAnirudh Venkataramanan ice_copy_rxq_ctx_to_hw(struct ice_hw *hw, u8 *ice_rxq_ctx, u32 rxq_index)
1034cdedef59SAnirudh Venkataramanan {
1035cdedef59SAnirudh Venkataramanan 	u8 i;
1036cdedef59SAnirudh Venkataramanan 
1037cdedef59SAnirudh Venkataramanan 	if (!ice_rxq_ctx)
1038cdedef59SAnirudh Venkataramanan 		return ICE_ERR_BAD_PTR;
1039cdedef59SAnirudh Venkataramanan 
1040cdedef59SAnirudh Venkataramanan 	if (rxq_index > QRX_CTRL_MAX_INDEX)
1041cdedef59SAnirudh Venkataramanan 		return ICE_ERR_PARAM;
1042cdedef59SAnirudh Venkataramanan 
1043f9867df6SAnirudh Venkataramanan 	/* Copy each dword separately to HW */
1044cdedef59SAnirudh Venkataramanan 	for (i = 0; i < ICE_RXQ_CTX_SIZE_DWORDS; i++) {
1045cdedef59SAnirudh Venkataramanan 		wr32(hw, QRX_CONTEXT(i, rxq_index),
1046cdedef59SAnirudh Venkataramanan 		     *((u32 *)(ice_rxq_ctx + (i * sizeof(u32)))));
1047cdedef59SAnirudh Venkataramanan 
1048cdedef59SAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_QCTX, "qrxdata[%d]: %08X\n", i,
1049cdedef59SAnirudh Venkataramanan 			  *((u32 *)(ice_rxq_ctx + (i * sizeof(u32)))));
1050cdedef59SAnirudh Venkataramanan 	}
1051cdedef59SAnirudh Venkataramanan 
1052cdedef59SAnirudh Venkataramanan 	return 0;
1053cdedef59SAnirudh Venkataramanan }
1054cdedef59SAnirudh Venkataramanan 
1055cdedef59SAnirudh Venkataramanan /* LAN Rx Queue Context */
1056cdedef59SAnirudh Venkataramanan static const struct ice_ctx_ele ice_rlan_ctx_info[] = {
1057cdedef59SAnirudh Venkataramanan 	/* Field		Width	LSB */
1058cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_rlan_ctx, head,		13,	0),
1059cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_rlan_ctx, cpuid,		8,	13),
1060cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_rlan_ctx, base,		57,	32),
1061cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_rlan_ctx, qlen,		13,	89),
1062cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_rlan_ctx, dbuf,		7,	102),
1063cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_rlan_ctx, hbuf,		5,	109),
1064cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_rlan_ctx, dtype,		2,	114),
1065cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_rlan_ctx, dsize,		1,	116),
1066cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_rlan_ctx, crcstrip,		1,	117),
1067cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_rlan_ctx, l2tsel,		1,	119),
1068cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_rlan_ctx, hsplit_0,		4,	120),
1069cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_rlan_ctx, hsplit_1,		2,	124),
1070cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_rlan_ctx, showiv,		1,	127),
1071cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_rlan_ctx, rxmax,		14,	174),
1072cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_rlan_ctx, tphrdesc_ena,	1,	193),
1073cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_rlan_ctx, tphwdesc_ena,	1,	194),
1074cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_rlan_ctx, tphdata_ena,	1,	195),
1075cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_rlan_ctx, tphhead_ena,	1,	196),
1076cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_rlan_ctx, lrxqthresh,		3,	198),
1077c31a5c25SBrett Creeley 	ICE_CTX_STORE(ice_rlan_ctx, prefena,		1,	201),
1078cdedef59SAnirudh Venkataramanan 	{ 0 }
1079cdedef59SAnirudh Venkataramanan };
1080cdedef59SAnirudh Venkataramanan 
1081cdedef59SAnirudh Venkataramanan /**
1082cdedef59SAnirudh Venkataramanan  * ice_write_rxq_ctx
1083cdedef59SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
1084cdedef59SAnirudh Venkataramanan  * @rlan_ctx: pointer to the rxq context
1085d337f2afSAnirudh Venkataramanan  * @rxq_index: the index of the Rx queue
1086cdedef59SAnirudh Venkataramanan  *
1087cdedef59SAnirudh Venkataramanan  * Converts rxq context from sparse to dense structure and then writes
1088c31a5c25SBrett Creeley  * it to HW register space and enables the hardware to prefetch descriptors
1089c31a5c25SBrett Creeley  * instead of only fetching them on demand
1090cdedef59SAnirudh Venkataramanan  */
1091cdedef59SAnirudh Venkataramanan enum ice_status
1092cdedef59SAnirudh Venkataramanan ice_write_rxq_ctx(struct ice_hw *hw, struct ice_rlan_ctx *rlan_ctx,
1093cdedef59SAnirudh Venkataramanan 		  u32 rxq_index)
1094cdedef59SAnirudh Venkataramanan {
1095cdedef59SAnirudh Venkataramanan 	u8 ctx_buf[ICE_RXQ_CTX_SZ] = { 0 };
1096cdedef59SAnirudh Venkataramanan 
1097c31a5c25SBrett Creeley 	if (!rlan_ctx)
1098c31a5c25SBrett Creeley 		return ICE_ERR_BAD_PTR;
1099c31a5c25SBrett Creeley 
1100c31a5c25SBrett Creeley 	rlan_ctx->prefena = 1;
1101c31a5c25SBrett Creeley 
11027e34786aSBruce Allan 	ice_set_ctx(hw, (u8 *)rlan_ctx, ctx_buf, ice_rlan_ctx_info);
1103cdedef59SAnirudh Venkataramanan 	return ice_copy_rxq_ctx_to_hw(hw, ctx_buf, rxq_index);
1104cdedef59SAnirudh Venkataramanan }
1105cdedef59SAnirudh Venkataramanan 
1106cdedef59SAnirudh Venkataramanan /* LAN Tx Queue Context */
1107cdedef59SAnirudh Venkataramanan const struct ice_ctx_ele ice_tlan_ctx_info[] = {
1108cdedef59SAnirudh Venkataramanan 				    /* Field			Width	LSB */
1109cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, base,			57,	0),
1110cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, port_num,			3,	57),
1111cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, cgd_num,			5,	60),
1112cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, pf_num,			3,	65),
1113cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, vmvf_num,			10,	68),
1114cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, vmvf_type,			2,	78),
1115cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, src_vsi,			10,	80),
1116cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, tsyn_ena,			1,	90),
1117201beeb7SAshish Shah 	ICE_CTX_STORE(ice_tlan_ctx, internal_usage_flag,	1,	91),
1118cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, alt_vlan,			1,	92),
1119cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, cpuid,			8,	93),
1120cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, wb_mode,			1,	101),
1121cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, tphrd_desc,			1,	102),
1122cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, tphrd,			1,	103),
1123cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, tphwr_desc,			1,	104),
1124cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, cmpq_id,			9,	105),
1125cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, qnum_in_func,		14,	114),
1126cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, itr_notification_mode,	1,	128),
1127cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, adjust_prof_id,		6,	129),
1128cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, qlen,			13,	135),
1129cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, quanta_prof_idx,		4,	148),
1130cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, tso_ena,			1,	152),
1131cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, tso_qnum,			11,	153),
1132cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, legacy_int,			1,	164),
1133cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, drop_ena,			1,	165),
1134cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, cache_prof_idx,		2,	166),
1135cdedef59SAnirudh Venkataramanan 	ICE_CTX_STORE(ice_tlan_ctx, pkt_shaper_prof_idx,	3,	168),
1136201beeb7SAshish Shah 	ICE_CTX_STORE(ice_tlan_ctx, int_q_state,		122,	171),
1137cdedef59SAnirudh Venkataramanan 	{ 0 }
1138cdedef59SAnirudh Venkataramanan };
1139cdedef59SAnirudh Venkataramanan 
11407ec59eeaSAnirudh Venkataramanan /* FW Admin Queue command wrappers */
11417ec59eeaSAnirudh Venkataramanan 
1142c7648810STony Nguyen /* Software lock/mutex that is meant to be held while the Global Config Lock
1143c7648810STony Nguyen  * in firmware is acquired by the software to prevent most (but not all) types
1144c7648810STony Nguyen  * of AQ commands from being sent to FW
1145c7648810STony Nguyen  */
1146c7648810STony Nguyen DEFINE_MUTEX(ice_global_cfg_lock_sw);
1147c7648810STony Nguyen 
11487ec59eeaSAnirudh Venkataramanan /**
11497ec59eeaSAnirudh Venkataramanan  * ice_aq_send_cmd - send FW Admin Queue command to FW Admin Queue
1150f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
11517ec59eeaSAnirudh Venkataramanan  * @desc: descriptor describing the command
11527ec59eeaSAnirudh Venkataramanan  * @buf: buffer to use for indirect commands (NULL for direct commands)
11537ec59eeaSAnirudh Venkataramanan  * @buf_size: size of buffer for indirect commands (0 for direct commands)
11547ec59eeaSAnirudh Venkataramanan  * @cd: pointer to command details structure
11557ec59eeaSAnirudh Venkataramanan  *
11567ec59eeaSAnirudh Venkataramanan  * Helper function to send FW Admin Queue commands to the FW Admin Queue.
11577ec59eeaSAnirudh Venkataramanan  */
11587ec59eeaSAnirudh Venkataramanan enum ice_status
11597ec59eeaSAnirudh Venkataramanan ice_aq_send_cmd(struct ice_hw *hw, struct ice_aq_desc *desc, void *buf,
11607ec59eeaSAnirudh Venkataramanan 		u16 buf_size, struct ice_sq_cd *cd)
11617ec59eeaSAnirudh Venkataramanan {
1162c7648810STony Nguyen 	struct ice_aqc_req_res *cmd = &desc->params.res_owner;
1163c7648810STony Nguyen 	bool lock_acquired = false;
1164c7648810STony Nguyen 	enum ice_status status;
1165c7648810STony Nguyen 
1166c7648810STony Nguyen 	/* When a package download is in process (i.e. when the firmware's
1167c7648810STony Nguyen 	 * Global Configuration Lock resource is held), only the Download
1168c7648810STony Nguyen 	 * Package, Get Version, Get Package Info List and Release Resource
1169c7648810STony Nguyen 	 * (with resource ID set to Global Config Lock) AdminQ commands are
1170c7648810STony Nguyen 	 * allowed; all others must block until the package download completes
1171c7648810STony Nguyen 	 * and the Global Config Lock is released.  See also
1172c7648810STony Nguyen 	 * ice_acquire_global_cfg_lock().
1173c7648810STony Nguyen 	 */
1174c7648810STony Nguyen 	switch (le16_to_cpu(desc->opcode)) {
1175c7648810STony Nguyen 	case ice_aqc_opc_download_pkg:
1176c7648810STony Nguyen 	case ice_aqc_opc_get_pkg_info_list:
1177c7648810STony Nguyen 	case ice_aqc_opc_get_ver:
1178c7648810STony Nguyen 		break;
1179c7648810STony Nguyen 	case ice_aqc_opc_release_res:
1180c7648810STony Nguyen 		if (le16_to_cpu(cmd->res_id) == ICE_AQC_RES_ID_GLBL_LOCK)
1181c7648810STony Nguyen 			break;
11824e83fc93SBruce Allan 		fallthrough;
1183c7648810STony Nguyen 	default:
1184c7648810STony Nguyen 		mutex_lock(&ice_global_cfg_lock_sw);
1185c7648810STony Nguyen 		lock_acquired = true;
1186c7648810STony Nguyen 		break;
1187c7648810STony Nguyen 	}
1188c7648810STony Nguyen 
1189c7648810STony Nguyen 	status = ice_sq_send_cmd(hw, &hw->adminq, desc, buf, buf_size, cd);
1190c7648810STony Nguyen 	if (lock_acquired)
1191c7648810STony Nguyen 		mutex_unlock(&ice_global_cfg_lock_sw);
1192c7648810STony Nguyen 
1193c7648810STony Nguyen 	return status;
11947ec59eeaSAnirudh Venkataramanan }
11957ec59eeaSAnirudh Venkataramanan 
11967ec59eeaSAnirudh Venkataramanan /**
11977ec59eeaSAnirudh Venkataramanan  * ice_aq_get_fw_ver
1198f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
11997ec59eeaSAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
12007ec59eeaSAnirudh Venkataramanan  *
12017ec59eeaSAnirudh Venkataramanan  * Get the firmware version (0x0001) from the admin queue commands
12027ec59eeaSAnirudh Venkataramanan  */
12037ec59eeaSAnirudh Venkataramanan enum ice_status ice_aq_get_fw_ver(struct ice_hw *hw, struct ice_sq_cd *cd)
12047ec59eeaSAnirudh Venkataramanan {
12057ec59eeaSAnirudh Venkataramanan 	struct ice_aqc_get_ver *resp;
12067ec59eeaSAnirudh Venkataramanan 	struct ice_aq_desc desc;
12077ec59eeaSAnirudh Venkataramanan 	enum ice_status status;
12087ec59eeaSAnirudh Venkataramanan 
12097ec59eeaSAnirudh Venkataramanan 	resp = &desc.params.get_ver;
12107ec59eeaSAnirudh Venkataramanan 
12117ec59eeaSAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_ver);
12127ec59eeaSAnirudh Venkataramanan 
12137ec59eeaSAnirudh Venkataramanan 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
12147ec59eeaSAnirudh Venkataramanan 
12157ec59eeaSAnirudh Venkataramanan 	if (!status) {
12167ec59eeaSAnirudh Venkataramanan 		hw->fw_branch = resp->fw_branch;
12177ec59eeaSAnirudh Venkataramanan 		hw->fw_maj_ver = resp->fw_major;
12187ec59eeaSAnirudh Venkataramanan 		hw->fw_min_ver = resp->fw_minor;
12197ec59eeaSAnirudh Venkataramanan 		hw->fw_patch = resp->fw_patch;
12207ec59eeaSAnirudh Venkataramanan 		hw->fw_build = le32_to_cpu(resp->fw_build);
12217ec59eeaSAnirudh Venkataramanan 		hw->api_branch = resp->api_branch;
12227ec59eeaSAnirudh Venkataramanan 		hw->api_maj_ver = resp->api_major;
12237ec59eeaSAnirudh Venkataramanan 		hw->api_min_ver = resp->api_minor;
12247ec59eeaSAnirudh Venkataramanan 		hw->api_patch = resp->api_patch;
12257ec59eeaSAnirudh Venkataramanan 	}
12267ec59eeaSAnirudh Venkataramanan 
12277ec59eeaSAnirudh Venkataramanan 	return status;
12287ec59eeaSAnirudh Venkataramanan }
12297ec59eeaSAnirudh Venkataramanan 
12307ec59eeaSAnirudh Venkataramanan /**
1231e3710a01SPaul M Stillwell Jr  * ice_aq_send_driver_ver
1232e3710a01SPaul M Stillwell Jr  * @hw: pointer to the HW struct
1233e3710a01SPaul M Stillwell Jr  * @dv: driver's major, minor version
1234e3710a01SPaul M Stillwell Jr  * @cd: pointer to command details structure or NULL
1235e3710a01SPaul M Stillwell Jr  *
1236e3710a01SPaul M Stillwell Jr  * Send the driver version (0x0002) to the firmware
1237e3710a01SPaul M Stillwell Jr  */
1238e3710a01SPaul M Stillwell Jr enum ice_status
1239e3710a01SPaul M Stillwell Jr ice_aq_send_driver_ver(struct ice_hw *hw, struct ice_driver_ver *dv,
1240e3710a01SPaul M Stillwell Jr 		       struct ice_sq_cd *cd)
1241e3710a01SPaul M Stillwell Jr {
1242e3710a01SPaul M Stillwell Jr 	struct ice_aqc_driver_ver *cmd;
1243e3710a01SPaul M Stillwell Jr 	struct ice_aq_desc desc;
1244e3710a01SPaul M Stillwell Jr 	u16 len;
1245e3710a01SPaul M Stillwell Jr 
1246e3710a01SPaul M Stillwell Jr 	cmd = &desc.params.driver_ver;
1247e3710a01SPaul M Stillwell Jr 
1248e3710a01SPaul M Stillwell Jr 	if (!dv)
1249e3710a01SPaul M Stillwell Jr 		return ICE_ERR_PARAM;
1250e3710a01SPaul M Stillwell Jr 
1251e3710a01SPaul M Stillwell Jr 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_driver_ver);
1252e3710a01SPaul M Stillwell Jr 
1253e3710a01SPaul M Stillwell Jr 	desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
1254e3710a01SPaul M Stillwell Jr 	cmd->major_ver = dv->major_ver;
1255e3710a01SPaul M Stillwell Jr 	cmd->minor_ver = dv->minor_ver;
1256e3710a01SPaul M Stillwell Jr 	cmd->build_ver = dv->build_ver;
1257e3710a01SPaul M Stillwell Jr 	cmd->subbuild_ver = dv->subbuild_ver;
1258e3710a01SPaul M Stillwell Jr 
1259e3710a01SPaul M Stillwell Jr 	len = 0;
1260e3710a01SPaul M Stillwell Jr 	while (len < sizeof(dv->driver_string) &&
1261e3710a01SPaul M Stillwell Jr 	       isascii(dv->driver_string[len]) && dv->driver_string[len])
1262e3710a01SPaul M Stillwell Jr 		len++;
1263e3710a01SPaul M Stillwell Jr 
1264e3710a01SPaul M Stillwell Jr 	return ice_aq_send_cmd(hw, &desc, dv->driver_string, len, cd);
1265e3710a01SPaul M Stillwell Jr }
1266e3710a01SPaul M Stillwell Jr 
1267e3710a01SPaul M Stillwell Jr /**
12687ec59eeaSAnirudh Venkataramanan  * ice_aq_q_shutdown
1269f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
12707ec59eeaSAnirudh Venkataramanan  * @unloading: is the driver unloading itself
12717ec59eeaSAnirudh Venkataramanan  *
12727ec59eeaSAnirudh Venkataramanan  * Tell the Firmware that we're shutting down the AdminQ and whether
12737ec59eeaSAnirudh Venkataramanan  * or not the driver is unloading as well (0x0003).
12747ec59eeaSAnirudh Venkataramanan  */
12757ec59eeaSAnirudh Venkataramanan enum ice_status ice_aq_q_shutdown(struct ice_hw *hw, bool unloading)
12767ec59eeaSAnirudh Venkataramanan {
12777ec59eeaSAnirudh Venkataramanan 	struct ice_aqc_q_shutdown *cmd;
12787ec59eeaSAnirudh Venkataramanan 	struct ice_aq_desc desc;
12797ec59eeaSAnirudh Venkataramanan 
12807ec59eeaSAnirudh Venkataramanan 	cmd = &desc.params.q_shutdown;
12817ec59eeaSAnirudh Venkataramanan 
12827ec59eeaSAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_q_shutdown);
12837ec59eeaSAnirudh Venkataramanan 
12847ec59eeaSAnirudh Venkataramanan 	if (unloading)
12857404e84aSBruce Allan 		cmd->driver_unloading = ICE_AQC_DRIVER_UNLOADING;
12867ec59eeaSAnirudh Venkataramanan 
12877ec59eeaSAnirudh Venkataramanan 	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
12887ec59eeaSAnirudh Venkataramanan }
1289f31e4b6fSAnirudh Venkataramanan 
1290f31e4b6fSAnirudh Venkataramanan /**
1291f31e4b6fSAnirudh Venkataramanan  * ice_aq_req_res
1292f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
1293f9867df6SAnirudh Venkataramanan  * @res: resource ID
1294f31e4b6fSAnirudh Venkataramanan  * @access: access type
1295f31e4b6fSAnirudh Venkataramanan  * @sdp_number: resource number
1296f31e4b6fSAnirudh Venkataramanan  * @timeout: the maximum time in ms that the driver may hold the resource
1297f31e4b6fSAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
1298f31e4b6fSAnirudh Venkataramanan  *
1299ff2b1321SDan Nowlin  * Requests common resource using the admin queue commands (0x0008).
1300ff2b1321SDan Nowlin  * When attempting to acquire the Global Config Lock, the driver can
1301ff2b1321SDan Nowlin  * learn of three states:
1302ff2b1321SDan Nowlin  *  1) ICE_SUCCESS -        acquired lock, and can perform download package
1303ff2b1321SDan Nowlin  *  2) ICE_ERR_AQ_ERROR -   did not get lock, driver should fail to load
1304ff2b1321SDan Nowlin  *  3) ICE_ERR_AQ_NO_WORK - did not get lock, but another driver has
1305ff2b1321SDan Nowlin  *                          successfully downloaded the package; the driver does
1306ff2b1321SDan Nowlin  *                          not have to download the package and can continue
1307ff2b1321SDan Nowlin  *                          loading
1308ff2b1321SDan Nowlin  *
1309ff2b1321SDan Nowlin  * Note that if the caller is in an acquire lock, perform action, release lock
1310ff2b1321SDan Nowlin  * phase of operation, it is possible that the FW may detect a timeout and issue
1311ff2b1321SDan Nowlin  * a CORER. In this case, the driver will receive a CORER interrupt and will
1312ff2b1321SDan Nowlin  * have to determine its cause. The calling thread that is handling this flow
1313ff2b1321SDan Nowlin  * will likely get an error propagated back to it indicating the Download
1314ff2b1321SDan Nowlin  * Package, Update Package or the Release Resource AQ commands timed out.
1315f31e4b6fSAnirudh Venkataramanan  */
1316f31e4b6fSAnirudh Venkataramanan static enum ice_status
1317f31e4b6fSAnirudh Venkataramanan ice_aq_req_res(struct ice_hw *hw, enum ice_aq_res_ids res,
1318f31e4b6fSAnirudh Venkataramanan 	       enum ice_aq_res_access_type access, u8 sdp_number, u32 *timeout,
1319f31e4b6fSAnirudh Venkataramanan 	       struct ice_sq_cd *cd)
1320f31e4b6fSAnirudh Venkataramanan {
1321f31e4b6fSAnirudh Venkataramanan 	struct ice_aqc_req_res *cmd_resp;
1322f31e4b6fSAnirudh Venkataramanan 	struct ice_aq_desc desc;
1323f31e4b6fSAnirudh Venkataramanan 	enum ice_status status;
1324f31e4b6fSAnirudh Venkataramanan 
1325f31e4b6fSAnirudh Venkataramanan 	cmd_resp = &desc.params.res_owner;
1326f31e4b6fSAnirudh Venkataramanan 
1327f31e4b6fSAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_req_res);
1328f31e4b6fSAnirudh Venkataramanan 
1329f31e4b6fSAnirudh Venkataramanan 	cmd_resp->res_id = cpu_to_le16(res);
1330f31e4b6fSAnirudh Venkataramanan 	cmd_resp->access_type = cpu_to_le16(access);
1331f31e4b6fSAnirudh Venkataramanan 	cmd_resp->res_number = cpu_to_le32(sdp_number);
1332ff2b1321SDan Nowlin 	cmd_resp->timeout = cpu_to_le32(*timeout);
1333ff2b1321SDan Nowlin 	*timeout = 0;
1334f31e4b6fSAnirudh Venkataramanan 
1335f31e4b6fSAnirudh Venkataramanan 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
1336ff2b1321SDan Nowlin 
1337f31e4b6fSAnirudh Venkataramanan 	/* The completion specifies the maximum time in ms that the driver
1338f31e4b6fSAnirudh Venkataramanan 	 * may hold the resource in the Timeout field.
1339ff2b1321SDan Nowlin 	 */
1340ff2b1321SDan Nowlin 
1341ff2b1321SDan Nowlin 	/* Global config lock response utilizes an additional status field.
1342ff2b1321SDan Nowlin 	 *
1343ff2b1321SDan Nowlin 	 * If the Global config lock resource is held by some other driver, the
1344ff2b1321SDan Nowlin 	 * command completes with ICE_AQ_RES_GLBL_IN_PROG in the status field
1345ff2b1321SDan Nowlin 	 * and the timeout field indicates the maximum time the current owner
1346ff2b1321SDan Nowlin 	 * of the resource has to free it.
1347ff2b1321SDan Nowlin 	 */
1348ff2b1321SDan Nowlin 	if (res == ICE_GLOBAL_CFG_LOCK_RES_ID) {
1349ff2b1321SDan Nowlin 		if (le16_to_cpu(cmd_resp->status) == ICE_AQ_RES_GLBL_SUCCESS) {
1350ff2b1321SDan Nowlin 			*timeout = le32_to_cpu(cmd_resp->timeout);
1351ff2b1321SDan Nowlin 			return 0;
1352ff2b1321SDan Nowlin 		} else if (le16_to_cpu(cmd_resp->status) ==
1353ff2b1321SDan Nowlin 			   ICE_AQ_RES_GLBL_IN_PROG) {
1354ff2b1321SDan Nowlin 			*timeout = le32_to_cpu(cmd_resp->timeout);
1355ff2b1321SDan Nowlin 			return ICE_ERR_AQ_ERROR;
1356ff2b1321SDan Nowlin 		} else if (le16_to_cpu(cmd_resp->status) ==
1357ff2b1321SDan Nowlin 			   ICE_AQ_RES_GLBL_DONE) {
1358ff2b1321SDan Nowlin 			return ICE_ERR_AQ_NO_WORK;
1359ff2b1321SDan Nowlin 		}
1360ff2b1321SDan Nowlin 
1361ff2b1321SDan Nowlin 		/* invalid FW response, force a timeout immediately */
1362ff2b1321SDan Nowlin 		*timeout = 0;
1363ff2b1321SDan Nowlin 		return ICE_ERR_AQ_ERROR;
1364ff2b1321SDan Nowlin 	}
1365ff2b1321SDan Nowlin 
1366ff2b1321SDan Nowlin 	/* If the resource is held by some other driver, the command completes
1367ff2b1321SDan Nowlin 	 * with a busy return value and the timeout field indicates the maximum
1368ff2b1321SDan Nowlin 	 * time the current owner of the resource has to free it.
1369f31e4b6fSAnirudh Venkataramanan 	 */
1370f31e4b6fSAnirudh Venkataramanan 	if (!status || hw->adminq.sq_last_status == ICE_AQ_RC_EBUSY)
1371f31e4b6fSAnirudh Venkataramanan 		*timeout = le32_to_cpu(cmd_resp->timeout);
1372f31e4b6fSAnirudh Venkataramanan 
1373f31e4b6fSAnirudh Venkataramanan 	return status;
1374f31e4b6fSAnirudh Venkataramanan }
1375f31e4b6fSAnirudh Venkataramanan 
1376f31e4b6fSAnirudh Venkataramanan /**
1377f31e4b6fSAnirudh Venkataramanan  * ice_aq_release_res
1378f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
1379f9867df6SAnirudh Venkataramanan  * @res: resource ID
1380f31e4b6fSAnirudh Venkataramanan  * @sdp_number: resource number
1381f31e4b6fSAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
1382f31e4b6fSAnirudh Venkataramanan  *
1383f31e4b6fSAnirudh Venkataramanan  * release common resource using the admin queue commands (0x0009)
1384f31e4b6fSAnirudh Venkataramanan  */
1385f31e4b6fSAnirudh Venkataramanan static enum ice_status
1386f31e4b6fSAnirudh Venkataramanan ice_aq_release_res(struct ice_hw *hw, enum ice_aq_res_ids res, u8 sdp_number,
1387f31e4b6fSAnirudh Venkataramanan 		   struct ice_sq_cd *cd)
1388f31e4b6fSAnirudh Venkataramanan {
1389f31e4b6fSAnirudh Venkataramanan 	struct ice_aqc_req_res *cmd;
1390f31e4b6fSAnirudh Venkataramanan 	struct ice_aq_desc desc;
1391f31e4b6fSAnirudh Venkataramanan 
1392f31e4b6fSAnirudh Venkataramanan 	cmd = &desc.params.res_owner;
1393f31e4b6fSAnirudh Venkataramanan 
1394f31e4b6fSAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_release_res);
1395f31e4b6fSAnirudh Venkataramanan 
1396f31e4b6fSAnirudh Venkataramanan 	cmd->res_id = cpu_to_le16(res);
1397f31e4b6fSAnirudh Venkataramanan 	cmd->res_number = cpu_to_le32(sdp_number);
1398f31e4b6fSAnirudh Venkataramanan 
1399f31e4b6fSAnirudh Venkataramanan 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
1400f31e4b6fSAnirudh Venkataramanan }
1401f31e4b6fSAnirudh Venkataramanan 
1402f31e4b6fSAnirudh Venkataramanan /**
1403f31e4b6fSAnirudh Venkataramanan  * ice_acquire_res
1404f31e4b6fSAnirudh Venkataramanan  * @hw: pointer to the HW structure
1405f9867df6SAnirudh Venkataramanan  * @res: resource ID
1406f31e4b6fSAnirudh Venkataramanan  * @access: access type (read or write)
1407ff2b1321SDan Nowlin  * @timeout: timeout in milliseconds
1408f31e4b6fSAnirudh Venkataramanan  *
1409f31e4b6fSAnirudh Venkataramanan  * This function will attempt to acquire the ownership of a resource.
1410f31e4b6fSAnirudh Venkataramanan  */
1411f31e4b6fSAnirudh Venkataramanan enum ice_status
1412f31e4b6fSAnirudh Venkataramanan ice_acquire_res(struct ice_hw *hw, enum ice_aq_res_ids res,
1413ff2b1321SDan Nowlin 		enum ice_aq_res_access_type access, u32 timeout)
1414f31e4b6fSAnirudh Venkataramanan {
1415f31e4b6fSAnirudh Venkataramanan #define ICE_RES_POLLING_DELAY_MS	10
1416f31e4b6fSAnirudh Venkataramanan 	u32 delay = ICE_RES_POLLING_DELAY_MS;
1417ff2b1321SDan Nowlin 	u32 time_left = timeout;
1418f31e4b6fSAnirudh Venkataramanan 	enum ice_status status;
1419f31e4b6fSAnirudh Venkataramanan 
1420f31e4b6fSAnirudh Venkataramanan 	status = ice_aq_req_res(hw, res, access, 0, &time_left, NULL);
1421f31e4b6fSAnirudh Venkataramanan 
1422ff2b1321SDan Nowlin 	/* A return code of ICE_ERR_AQ_NO_WORK means that another driver has
1423ff2b1321SDan Nowlin 	 * previously acquired the resource and performed any necessary updates;
1424ff2b1321SDan Nowlin 	 * in this case the caller does not obtain the resource and has no
1425ff2b1321SDan Nowlin 	 * further work to do.
1426f31e4b6fSAnirudh Venkataramanan 	 */
1427ff2b1321SDan Nowlin 	if (status == ICE_ERR_AQ_NO_WORK)
1428f31e4b6fSAnirudh Venkataramanan 		goto ice_acquire_res_exit;
1429f31e4b6fSAnirudh Venkataramanan 
1430f31e4b6fSAnirudh Venkataramanan 	if (status)
1431f31e4b6fSAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_RES,
1432f31e4b6fSAnirudh Venkataramanan 			  "resource %d acquire type %d failed.\n", res, access);
1433f31e4b6fSAnirudh Venkataramanan 
1434f31e4b6fSAnirudh Venkataramanan 	/* If necessary, poll until the current lock owner timeouts */
1435f31e4b6fSAnirudh Venkataramanan 	timeout = time_left;
1436f31e4b6fSAnirudh Venkataramanan 	while (status && timeout && time_left) {
1437f31e4b6fSAnirudh Venkataramanan 		mdelay(delay);
1438f31e4b6fSAnirudh Venkataramanan 		timeout = (timeout > delay) ? timeout - delay : 0;
1439f31e4b6fSAnirudh Venkataramanan 		status = ice_aq_req_res(hw, res, access, 0, &time_left, NULL);
1440f31e4b6fSAnirudh Venkataramanan 
1441ff2b1321SDan Nowlin 		if (status == ICE_ERR_AQ_NO_WORK)
1442f31e4b6fSAnirudh Venkataramanan 			/* lock free, but no work to do */
1443f31e4b6fSAnirudh Venkataramanan 			break;
1444f31e4b6fSAnirudh Venkataramanan 
1445f31e4b6fSAnirudh Venkataramanan 		if (!status)
1446f31e4b6fSAnirudh Venkataramanan 			/* lock acquired */
1447f31e4b6fSAnirudh Venkataramanan 			break;
1448f31e4b6fSAnirudh Venkataramanan 	}
1449f31e4b6fSAnirudh Venkataramanan 	if (status && status != ICE_ERR_AQ_NO_WORK)
1450f31e4b6fSAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_RES, "resource acquire timed out.\n");
1451f31e4b6fSAnirudh Venkataramanan 
1452f31e4b6fSAnirudh Venkataramanan ice_acquire_res_exit:
1453f31e4b6fSAnirudh Venkataramanan 	if (status == ICE_ERR_AQ_NO_WORK) {
1454f31e4b6fSAnirudh Venkataramanan 		if (access == ICE_RES_WRITE)
1455f31e4b6fSAnirudh Venkataramanan 			ice_debug(hw, ICE_DBG_RES,
1456f31e4b6fSAnirudh Venkataramanan 				  "resource indicates no work to do.\n");
1457f31e4b6fSAnirudh Venkataramanan 		else
1458f31e4b6fSAnirudh Venkataramanan 			ice_debug(hw, ICE_DBG_RES,
1459f31e4b6fSAnirudh Venkataramanan 				  "Warning: ICE_ERR_AQ_NO_WORK not expected\n");
1460f31e4b6fSAnirudh Venkataramanan 	}
1461f31e4b6fSAnirudh Venkataramanan 	return status;
1462f31e4b6fSAnirudh Venkataramanan }
1463f31e4b6fSAnirudh Venkataramanan 
1464f31e4b6fSAnirudh Venkataramanan /**
1465f31e4b6fSAnirudh Venkataramanan  * ice_release_res
1466f31e4b6fSAnirudh Venkataramanan  * @hw: pointer to the HW structure
1467f9867df6SAnirudh Venkataramanan  * @res: resource ID
1468f31e4b6fSAnirudh Venkataramanan  *
1469f31e4b6fSAnirudh Venkataramanan  * This function will release a resource using the proper Admin Command.
1470f31e4b6fSAnirudh Venkataramanan  */
1471f31e4b6fSAnirudh Venkataramanan void ice_release_res(struct ice_hw *hw, enum ice_aq_res_ids res)
1472f31e4b6fSAnirudh Venkataramanan {
1473f31e4b6fSAnirudh Venkataramanan 	enum ice_status status;
1474f31e4b6fSAnirudh Venkataramanan 	u32 total_delay = 0;
1475f31e4b6fSAnirudh Venkataramanan 
1476f31e4b6fSAnirudh Venkataramanan 	status = ice_aq_release_res(hw, res, 0, NULL);
1477f31e4b6fSAnirudh Venkataramanan 
1478f31e4b6fSAnirudh Venkataramanan 	/* there are some rare cases when trying to release the resource
1479f9867df6SAnirudh Venkataramanan 	 * results in an admin queue timeout, so handle them correctly
1480f31e4b6fSAnirudh Venkataramanan 	 */
1481f31e4b6fSAnirudh Venkataramanan 	while ((status == ICE_ERR_AQ_TIMEOUT) &&
1482f31e4b6fSAnirudh Venkataramanan 	       (total_delay < hw->adminq.sq_cmd_timeout)) {
1483f31e4b6fSAnirudh Venkataramanan 		mdelay(1);
1484f31e4b6fSAnirudh Venkataramanan 		status = ice_aq_release_res(hw, res, 0, NULL);
1485f31e4b6fSAnirudh Venkataramanan 		total_delay++;
1486f31e4b6fSAnirudh Venkataramanan 	}
1487f31e4b6fSAnirudh Venkataramanan }
1488f31e4b6fSAnirudh Venkataramanan 
1489f31e4b6fSAnirudh Venkataramanan /**
149031ad4e4eSTony Nguyen  * ice_aq_alloc_free_res - command to allocate/free resources
149131ad4e4eSTony Nguyen  * @hw: pointer to the HW struct
149231ad4e4eSTony Nguyen  * @num_entries: number of resource entries in buffer
149331ad4e4eSTony Nguyen  * @buf: Indirect buffer to hold data parameters and response
149431ad4e4eSTony Nguyen  * @buf_size: size of buffer for indirect commands
149531ad4e4eSTony Nguyen  * @opc: pass in the command opcode
149631ad4e4eSTony Nguyen  * @cd: pointer to command details structure or NULL
149731ad4e4eSTony Nguyen  *
149831ad4e4eSTony Nguyen  * Helper function to allocate/free resources using the admin queue commands
149931ad4e4eSTony Nguyen  */
150031ad4e4eSTony Nguyen enum ice_status
150131ad4e4eSTony Nguyen ice_aq_alloc_free_res(struct ice_hw *hw, u16 num_entries,
150231ad4e4eSTony Nguyen 		      struct ice_aqc_alloc_free_res_elem *buf, u16 buf_size,
150331ad4e4eSTony Nguyen 		      enum ice_adminq_opc opc, struct ice_sq_cd *cd)
150431ad4e4eSTony Nguyen {
150531ad4e4eSTony Nguyen 	struct ice_aqc_alloc_free_res_cmd *cmd;
150631ad4e4eSTony Nguyen 	struct ice_aq_desc desc;
150731ad4e4eSTony Nguyen 
150831ad4e4eSTony Nguyen 	cmd = &desc.params.sw_res_ctrl;
150931ad4e4eSTony Nguyen 
151031ad4e4eSTony Nguyen 	if (!buf)
151131ad4e4eSTony Nguyen 		return ICE_ERR_PARAM;
151231ad4e4eSTony Nguyen 
151331ad4e4eSTony Nguyen 	if (buf_size < (num_entries * sizeof(buf->elem[0])))
151431ad4e4eSTony Nguyen 		return ICE_ERR_PARAM;
151531ad4e4eSTony Nguyen 
151631ad4e4eSTony Nguyen 	ice_fill_dflt_direct_cmd_desc(&desc, opc);
151731ad4e4eSTony Nguyen 
151831ad4e4eSTony Nguyen 	desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
151931ad4e4eSTony Nguyen 
152031ad4e4eSTony Nguyen 	cmd->num_entries = cpu_to_le16(num_entries);
152131ad4e4eSTony Nguyen 
152231ad4e4eSTony Nguyen 	return ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
152331ad4e4eSTony Nguyen }
152431ad4e4eSTony Nguyen 
152531ad4e4eSTony Nguyen /**
152631ad4e4eSTony Nguyen  * ice_alloc_hw_res - allocate resource
152731ad4e4eSTony Nguyen  * @hw: pointer to the HW struct
152831ad4e4eSTony Nguyen  * @type: type of resource
152931ad4e4eSTony Nguyen  * @num: number of resources to allocate
153031ad4e4eSTony Nguyen  * @btm: allocate from bottom
153131ad4e4eSTony Nguyen  * @res: pointer to array that will receive the resources
153231ad4e4eSTony Nguyen  */
153331ad4e4eSTony Nguyen enum ice_status
153431ad4e4eSTony Nguyen ice_alloc_hw_res(struct ice_hw *hw, u16 type, u16 num, bool btm, u16 *res)
153531ad4e4eSTony Nguyen {
153631ad4e4eSTony Nguyen 	struct ice_aqc_alloc_free_res_elem *buf;
153731ad4e4eSTony Nguyen 	enum ice_status status;
153831ad4e4eSTony Nguyen 	u16 buf_len;
153931ad4e4eSTony Nguyen 
154066486d89SBruce Allan 	buf_len = struct_size(buf, elem, num);
154131ad4e4eSTony Nguyen 	buf = kzalloc(buf_len, GFP_KERNEL);
154231ad4e4eSTony Nguyen 	if (!buf)
154331ad4e4eSTony Nguyen 		return ICE_ERR_NO_MEMORY;
154431ad4e4eSTony Nguyen 
154531ad4e4eSTony Nguyen 	/* Prepare buffer to allocate resource. */
154631ad4e4eSTony Nguyen 	buf->num_elems = cpu_to_le16(num);
154731ad4e4eSTony Nguyen 	buf->res_type = cpu_to_le16(type | ICE_AQC_RES_TYPE_FLAG_DEDICATED |
154831ad4e4eSTony Nguyen 				    ICE_AQC_RES_TYPE_FLAG_IGNORE_INDEX);
154931ad4e4eSTony Nguyen 	if (btm)
155031ad4e4eSTony Nguyen 		buf->res_type |= cpu_to_le16(ICE_AQC_RES_TYPE_FLAG_SCAN_BOTTOM);
155131ad4e4eSTony Nguyen 
155231ad4e4eSTony Nguyen 	status = ice_aq_alloc_free_res(hw, 1, buf, buf_len,
155331ad4e4eSTony Nguyen 				       ice_aqc_opc_alloc_res, NULL);
155431ad4e4eSTony Nguyen 	if (status)
155531ad4e4eSTony Nguyen 		goto ice_alloc_res_exit;
155631ad4e4eSTony Nguyen 
155766486d89SBruce Allan 	memcpy(res, buf->elem, sizeof(*buf->elem) * num);
155831ad4e4eSTony Nguyen 
155931ad4e4eSTony Nguyen ice_alloc_res_exit:
156031ad4e4eSTony Nguyen 	kfree(buf);
156131ad4e4eSTony Nguyen 	return status;
156231ad4e4eSTony Nguyen }
156331ad4e4eSTony Nguyen 
156431ad4e4eSTony Nguyen /**
1565451f2c44STony Nguyen  * ice_free_hw_res - free allocated HW resource
1566451f2c44STony Nguyen  * @hw: pointer to the HW struct
1567451f2c44STony Nguyen  * @type: type of resource to free
1568451f2c44STony Nguyen  * @num: number of resources
1569451f2c44STony Nguyen  * @res: pointer to array that contains the resources to free
1570451f2c44STony Nguyen  */
1571451f2c44STony Nguyen enum ice_status
1572451f2c44STony Nguyen ice_free_hw_res(struct ice_hw *hw, u16 type, u16 num, u16 *res)
1573451f2c44STony Nguyen {
1574451f2c44STony Nguyen 	struct ice_aqc_alloc_free_res_elem *buf;
1575451f2c44STony Nguyen 	enum ice_status status;
1576451f2c44STony Nguyen 	u16 buf_len;
1577451f2c44STony Nguyen 
157866486d89SBruce Allan 	buf_len = struct_size(buf, elem, num);
1579451f2c44STony Nguyen 	buf = kzalloc(buf_len, GFP_KERNEL);
1580451f2c44STony Nguyen 	if (!buf)
1581451f2c44STony Nguyen 		return ICE_ERR_NO_MEMORY;
1582451f2c44STony Nguyen 
1583451f2c44STony Nguyen 	/* Prepare buffer to free resource. */
1584451f2c44STony Nguyen 	buf->num_elems = cpu_to_le16(num);
1585451f2c44STony Nguyen 	buf->res_type = cpu_to_le16(type);
158666486d89SBruce Allan 	memcpy(buf->elem, res, sizeof(*buf->elem) * num);
1587451f2c44STony Nguyen 
1588451f2c44STony Nguyen 	status = ice_aq_alloc_free_res(hw, num, buf, buf_len,
1589451f2c44STony Nguyen 				       ice_aqc_opc_free_res, NULL);
1590451f2c44STony Nguyen 	if (status)
1591451f2c44STony Nguyen 		ice_debug(hw, ICE_DBG_SW, "CQ CMD Buffer:\n");
1592451f2c44STony Nguyen 
1593451f2c44STony Nguyen 	kfree(buf);
1594451f2c44STony Nguyen 	return status;
1595451f2c44STony Nguyen }
1596451f2c44STony Nguyen 
1597451f2c44STony Nguyen /**
15987a1f7111SBrett Creeley  * ice_get_num_per_func - determine number of resources per PF
1599f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW structure
16007a1f7111SBrett Creeley  * @max: value to be evenly split between each PF
1601995c90f2SAnirudh Venkataramanan  *
1602995c90f2SAnirudh Venkataramanan  * Determine the number of valid functions by going through the bitmap returned
16037a1f7111SBrett Creeley  * from parsing capabilities and use this to calculate the number of resources
16047a1f7111SBrett Creeley  * per PF based on the max value passed in.
1605995c90f2SAnirudh Venkataramanan  */
16067a1f7111SBrett Creeley static u32 ice_get_num_per_func(struct ice_hw *hw, u32 max)
1607995c90f2SAnirudh Venkataramanan {
1608995c90f2SAnirudh Venkataramanan 	u8 funcs;
1609995c90f2SAnirudh Venkataramanan 
1610995c90f2SAnirudh Venkataramanan #define ICE_CAPS_VALID_FUNCS_M	0xFF
1611995c90f2SAnirudh Venkataramanan 	funcs = hweight8(hw->dev_caps.common_cap.valid_functions &
1612995c90f2SAnirudh Venkataramanan 			 ICE_CAPS_VALID_FUNCS_M);
1613995c90f2SAnirudh Venkataramanan 
1614995c90f2SAnirudh Venkataramanan 	if (!funcs)
1615995c90f2SAnirudh Venkataramanan 		return 0;
1616995c90f2SAnirudh Venkataramanan 
16177a1f7111SBrett Creeley 	return max / funcs;
1618995c90f2SAnirudh Venkataramanan }
1619995c90f2SAnirudh Venkataramanan 
1620995c90f2SAnirudh Venkataramanan /**
1621595b13e2SJacob Keller  * ice_parse_common_caps - parse common device/function capabilities
1622f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
1623595b13e2SJacob Keller  * @caps: pointer to common capabilities structure
1624595b13e2SJacob Keller  * @elem: the capability element to parse
1625595b13e2SJacob Keller  * @prefix: message prefix for tracing capabilities
16269c20346bSAnirudh Venkataramanan  *
1627595b13e2SJacob Keller  * Given a capability element, extract relevant details into the common
1628595b13e2SJacob Keller  * capability structure.
1629595b13e2SJacob Keller  *
1630595b13e2SJacob Keller  * Returns: true if the capability matches one of the common capability ids,
1631595b13e2SJacob Keller  * false otherwise.
16329c20346bSAnirudh Venkataramanan  */
1633595b13e2SJacob Keller static bool
1634595b13e2SJacob Keller ice_parse_common_caps(struct ice_hw *hw, struct ice_hw_common_caps *caps,
1635595b13e2SJacob Keller 		      struct ice_aqc_list_caps_elem *elem, const char *prefix)
16369c20346bSAnirudh Venkataramanan {
1637595b13e2SJacob Keller 	u32 logical_id = le32_to_cpu(elem->logical_id);
1638595b13e2SJacob Keller 	u32 phys_id = le32_to_cpu(elem->phys_id);
1639595b13e2SJacob Keller 	u32 number = le32_to_cpu(elem->number);
1640595b13e2SJacob Keller 	u16 cap = le16_to_cpu(elem->cap);
1641595b13e2SJacob Keller 	bool found = true;
16429c20346bSAnirudh Venkataramanan 
16439c20346bSAnirudh Venkataramanan 	switch (cap) {
1644995c90f2SAnirudh Venkataramanan 	case ICE_AQC_CAPS_VALID_FUNCTIONS:
1645995c90f2SAnirudh Venkataramanan 		caps->valid_functions = number;
1646995c90f2SAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_INIT,
16475c875c1aSAnirudh Venkataramanan 			  "%s: valid_functions (bitmap) = %d\n", prefix,
1648995c90f2SAnirudh Venkataramanan 			  caps->valid_functions);
1649995c90f2SAnirudh Venkataramanan 		break;
165075d2b253SAnirudh Venkataramanan 	case ICE_AQC_CAPS_SRIOV:
165175d2b253SAnirudh Venkataramanan 		caps->sr_iov_1_1 = (number == 1);
165275d2b253SAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_INIT,
16535c875c1aSAnirudh Venkataramanan 			  "%s: sr_iov_1_1 = %d\n", prefix,
1654a84db525SAnirudh Venkataramanan 			  caps->sr_iov_1_1);
165575d2b253SAnirudh Venkataramanan 		break;
1656a257f188SUsha Ketineni 	case ICE_AQC_CAPS_DCB:
1657a257f188SUsha Ketineni 		caps->dcb = (number == 1);
1658a257f188SUsha Ketineni 		caps->active_tc_bitmap = logical_id;
1659a257f188SUsha Ketineni 		caps->maxtc = phys_id;
1660a257f188SUsha Ketineni 		ice_debug(hw, ICE_DBG_INIT,
16615c875c1aSAnirudh Venkataramanan 			  "%s: dcb = %d\n", prefix, caps->dcb);
1662a257f188SUsha Ketineni 		ice_debug(hw, ICE_DBG_INIT,
16635c875c1aSAnirudh Venkataramanan 			  "%s: active_tc_bitmap = %d\n", prefix,
1664a257f188SUsha Ketineni 			  caps->active_tc_bitmap);
1665a257f188SUsha Ketineni 		ice_debug(hw, ICE_DBG_INIT,
16665c875c1aSAnirudh Venkataramanan 			  "%s: maxtc = %d\n", prefix, caps->maxtc);
1667a257f188SUsha Ketineni 		break;
16689c20346bSAnirudh Venkataramanan 	case ICE_AQC_CAPS_RSS:
16699c20346bSAnirudh Venkataramanan 		caps->rss_table_size = number;
16709c20346bSAnirudh Venkataramanan 		caps->rss_table_entry_width = logical_id;
16719c20346bSAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_INIT,
16725c875c1aSAnirudh Venkataramanan 			  "%s: rss_table_size = %d\n", prefix,
16739c20346bSAnirudh Venkataramanan 			  caps->rss_table_size);
16749c20346bSAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_INIT,
16755c875c1aSAnirudh Venkataramanan 			  "%s: rss_table_entry_width = %d\n", prefix,
16769c20346bSAnirudh Venkataramanan 			  caps->rss_table_entry_width);
16779c20346bSAnirudh Venkataramanan 		break;
16789c20346bSAnirudh Venkataramanan 	case ICE_AQC_CAPS_RXQS:
16799c20346bSAnirudh Venkataramanan 		caps->num_rxq = number;
16809c20346bSAnirudh Venkataramanan 		caps->rxq_first_id = phys_id;
16819c20346bSAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_INIT,
16825c875c1aSAnirudh Venkataramanan 			  "%s: num_rxq = %d\n", prefix,
1683a84db525SAnirudh Venkataramanan 			  caps->num_rxq);
16849c20346bSAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_INIT,
16855c875c1aSAnirudh Venkataramanan 			  "%s: rxq_first_id = %d\n", prefix,
16869c20346bSAnirudh Venkataramanan 			  caps->rxq_first_id);
16879c20346bSAnirudh Venkataramanan 		break;
16889c20346bSAnirudh Venkataramanan 	case ICE_AQC_CAPS_TXQS:
16899c20346bSAnirudh Venkataramanan 		caps->num_txq = number;
16909c20346bSAnirudh Venkataramanan 		caps->txq_first_id = phys_id;
16919c20346bSAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_INIT,
16925c875c1aSAnirudh Venkataramanan 			  "%s: num_txq = %d\n", prefix,
1693a84db525SAnirudh Venkataramanan 			  caps->num_txq);
16949c20346bSAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_INIT,
16955c875c1aSAnirudh Venkataramanan 			  "%s: txq_first_id = %d\n", prefix,
16969c20346bSAnirudh Venkataramanan 			  caps->txq_first_id);
16979c20346bSAnirudh Venkataramanan 		break;
16989c20346bSAnirudh Venkataramanan 	case ICE_AQC_CAPS_MSIX:
16999c20346bSAnirudh Venkataramanan 		caps->num_msix_vectors = number;
17009c20346bSAnirudh Venkataramanan 		caps->msix_vector_first_id = phys_id;
17019c20346bSAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_INIT,
17025c875c1aSAnirudh Venkataramanan 			  "%s: num_msix_vectors = %d\n", prefix,
17039c20346bSAnirudh Venkataramanan 			  caps->num_msix_vectors);
17049c20346bSAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_INIT,
17055c875c1aSAnirudh Venkataramanan 			  "%s: msix_vector_first_id = %d\n", prefix,
17069c20346bSAnirudh Venkataramanan 			  caps->msix_vector_first_id);
17079c20346bSAnirudh Venkataramanan 		break;
1708595b13e2SJacob Keller 	case ICE_AQC_CAPS_MAX_MTU:
1709595b13e2SJacob Keller 		caps->max_mtu = number;
1710595b13e2SJacob Keller 		ice_debug(hw, ICE_DBG_INIT, "%s: max_mtu = %d\n",
1711595b13e2SJacob Keller 			  prefix, caps->max_mtu);
1712595b13e2SJacob Keller 		break;
1713595b13e2SJacob Keller 	default:
1714595b13e2SJacob Keller 		/* Not one of the recognized common capabilities */
1715595b13e2SJacob Keller 		found = false;
1716148beb61SHenry Tieman 	}
1717595b13e2SJacob Keller 
1718595b13e2SJacob Keller 	return found;
1719595b13e2SJacob Keller }
1720595b13e2SJacob Keller 
1721595b13e2SJacob Keller /**
1722595b13e2SJacob Keller  * ice_recalc_port_limited_caps - Recalculate port limited capabilities
1723595b13e2SJacob Keller  * @hw: pointer to the HW structure
1724595b13e2SJacob Keller  * @caps: pointer to capabilities structure to fix
1725595b13e2SJacob Keller  *
1726595b13e2SJacob Keller  * Re-calculate the capabilities that are dependent on the number of physical
1727595b13e2SJacob Keller  * ports; i.e. some features are not supported or function differently on
1728595b13e2SJacob Keller  * devices with more than 4 ports.
1729595b13e2SJacob Keller  */
1730595b13e2SJacob Keller static void
1731595b13e2SJacob Keller ice_recalc_port_limited_caps(struct ice_hw *hw, struct ice_hw_common_caps *caps)
1732595b13e2SJacob Keller {
1733595b13e2SJacob Keller 	/* This assumes device capabilities are always scanned before function
1734595b13e2SJacob Keller 	 * capabilities during the initialization flow.
1735595b13e2SJacob Keller 	 */
1736595b13e2SJacob Keller 	if (hw->dev_caps.num_funcs > 4) {
1737595b13e2SJacob Keller 		/* Max 4 TCs per port */
1738595b13e2SJacob Keller 		caps->maxtc = 4;
1739595b13e2SJacob Keller 		ice_debug(hw, ICE_DBG_INIT,
1740595b13e2SJacob Keller 			  "reducing maxtc to %d (based on #ports)\n",
1741595b13e2SJacob Keller 			  caps->maxtc);
1742595b13e2SJacob Keller 	}
1743595b13e2SJacob Keller }
1744595b13e2SJacob Keller 
1745595b13e2SJacob Keller /**
1746595b13e2SJacob Keller  * ice_parse_vf_func_caps - Parse ICE_AQC_CAPS_VF function caps
1747595b13e2SJacob Keller  * @hw: pointer to the HW struct
1748595b13e2SJacob Keller  * @func_p: pointer to function capabilities structure
1749595b13e2SJacob Keller  * @cap: pointer to the capability element to parse
1750595b13e2SJacob Keller  *
1751595b13e2SJacob Keller  * Extract function capabilities for ICE_AQC_CAPS_VF.
1752595b13e2SJacob Keller  */
1753595b13e2SJacob Keller static void
1754595b13e2SJacob Keller ice_parse_vf_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_p,
1755595b13e2SJacob Keller 		       struct ice_aqc_list_caps_elem *cap)
1756595b13e2SJacob Keller {
1757595b13e2SJacob Keller 	u32 logical_id = le32_to_cpu(cap->logical_id);
1758595b13e2SJacob Keller 	u32 number = le32_to_cpu(cap->number);
1759595b13e2SJacob Keller 
1760595b13e2SJacob Keller 	func_p->num_allocd_vfs = number;
1761595b13e2SJacob Keller 	func_p->vf_base_id = logical_id;
1762595b13e2SJacob Keller 	ice_debug(hw, ICE_DBG_INIT, "func caps: num_allocd_vfs = %d\n",
1763595b13e2SJacob Keller 		  func_p->num_allocd_vfs);
1764595b13e2SJacob Keller 	ice_debug(hw, ICE_DBG_INIT, "func caps: vf_base_id = %d\n",
1765595b13e2SJacob Keller 		  func_p->vf_base_id);
1766595b13e2SJacob Keller }
1767595b13e2SJacob Keller 
1768595b13e2SJacob Keller /**
1769595b13e2SJacob Keller  * ice_parse_vsi_func_caps - Parse ICE_AQC_CAPS_VSI function caps
1770595b13e2SJacob Keller  * @hw: pointer to the HW struct
1771595b13e2SJacob Keller  * @func_p: pointer to function capabilities structure
1772595b13e2SJacob Keller  * @cap: pointer to the capability element to parse
1773595b13e2SJacob Keller  *
1774595b13e2SJacob Keller  * Extract function capabilities for ICE_AQC_CAPS_VSI.
1775595b13e2SJacob Keller  */
1776595b13e2SJacob Keller static void
1777595b13e2SJacob Keller ice_parse_vsi_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_p,
1778595b13e2SJacob Keller 			struct ice_aqc_list_caps_elem *cap)
1779595b13e2SJacob Keller {
1780595b13e2SJacob Keller 	func_p->guar_num_vsi = ice_get_num_per_func(hw, ICE_MAX_VSI);
1781595b13e2SJacob Keller 	ice_debug(hw, ICE_DBG_INIT, "func caps: guar_num_vsi (fw) = %d\n",
1782595b13e2SJacob Keller 		  le32_to_cpu(cap->number));
1783595b13e2SJacob Keller 	ice_debug(hw, ICE_DBG_INIT, "func caps: guar_num_vsi = %d\n",
1784595b13e2SJacob Keller 		  func_p->guar_num_vsi);
1785595b13e2SJacob Keller }
1786595b13e2SJacob Keller 
1787595b13e2SJacob Keller /**
1788595b13e2SJacob Keller  * ice_parse_fdir_func_caps - Parse ICE_AQC_CAPS_FD function caps
1789595b13e2SJacob Keller  * @hw: pointer to the HW struct
1790595b13e2SJacob Keller  * @func_p: pointer to function capabilities structure
1791595b13e2SJacob Keller  *
1792595b13e2SJacob Keller  * Extract function capabilities for ICE_AQC_CAPS_FD.
1793595b13e2SJacob Keller  */
1794595b13e2SJacob Keller static void
1795595b13e2SJacob Keller ice_parse_fdir_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_p)
1796595b13e2SJacob Keller {
1797148beb61SHenry Tieman 	u32 reg_val, val;
1798148beb61SHenry Tieman 
1799148beb61SHenry Tieman 	reg_val = rd32(hw, GLQF_FD_SIZE);
1800148beb61SHenry Tieman 	val = (reg_val & GLQF_FD_SIZE_FD_GSIZE_M) >>
1801148beb61SHenry Tieman 		GLQF_FD_SIZE_FD_GSIZE_S;
1802148beb61SHenry Tieman 	func_p->fd_fltr_guar =
1803148beb61SHenry Tieman 		ice_get_num_per_func(hw, val);
1804148beb61SHenry Tieman 	val = (reg_val & GLQF_FD_SIZE_FD_BSIZE_M) >>
1805148beb61SHenry Tieman 		GLQF_FD_SIZE_FD_BSIZE_S;
1806148beb61SHenry Tieman 	func_p->fd_fltr_best_effort = val;
1807595b13e2SJacob Keller 
1808148beb61SHenry Tieman 	ice_debug(hw, ICE_DBG_INIT,
1809595b13e2SJacob Keller 		  "func caps: fd_fltr_guar = %d\n",
1810595b13e2SJacob Keller 		  func_p->fd_fltr_guar);
1811148beb61SHenry Tieman 	ice_debug(hw, ICE_DBG_INIT,
1812595b13e2SJacob Keller 		  "func caps: fd_fltr_best_effort = %d\n",
1813595b13e2SJacob Keller 		  func_p->fd_fltr_best_effort);
1814148beb61SHenry Tieman }
1815595b13e2SJacob Keller 
1816595b13e2SJacob Keller /**
1817595b13e2SJacob Keller  * ice_parse_func_caps - Parse function capabilities
1818595b13e2SJacob Keller  * @hw: pointer to the HW struct
1819595b13e2SJacob Keller  * @func_p: pointer to function capabilities structure
1820595b13e2SJacob Keller  * @buf: buffer containing the function capability records
1821595b13e2SJacob Keller  * @cap_count: the number of capabilities
1822595b13e2SJacob Keller  *
1823595b13e2SJacob Keller  * Helper function to parse function (0x000A) capabilities list. For
1824595b13e2SJacob Keller  * capabilities shared between device and function, this relies on
1825595b13e2SJacob Keller  * ice_parse_common_caps.
1826595b13e2SJacob Keller  *
1827595b13e2SJacob Keller  * Loop through the list of provided capabilities and extract the relevant
1828595b13e2SJacob Keller  * data into the function capabilities structured.
1829595b13e2SJacob Keller  */
1830595b13e2SJacob Keller static void
1831595b13e2SJacob Keller ice_parse_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_p,
1832595b13e2SJacob Keller 		    void *buf, u32 cap_count)
1833595b13e2SJacob Keller {
1834595b13e2SJacob Keller 	struct ice_aqc_list_caps_elem *cap_resp;
1835595b13e2SJacob Keller 	u32 i;
1836595b13e2SJacob Keller 
1837595b13e2SJacob Keller 	cap_resp = (struct ice_aqc_list_caps_elem *)buf;
1838595b13e2SJacob Keller 
1839595b13e2SJacob Keller 	memset(func_p, 0, sizeof(*func_p));
1840595b13e2SJacob Keller 
1841595b13e2SJacob Keller 	for (i = 0; i < cap_count; i++) {
1842595b13e2SJacob Keller 		u16 cap = le16_to_cpu(cap_resp[i].cap);
1843595b13e2SJacob Keller 		bool found;
1844595b13e2SJacob Keller 
1845595b13e2SJacob Keller 		found = ice_parse_common_caps(hw, &func_p->common_cap,
1846595b13e2SJacob Keller 					      &cap_resp[i], "func caps");
1847595b13e2SJacob Keller 
1848595b13e2SJacob Keller 		switch (cap) {
1849595b13e2SJacob Keller 		case ICE_AQC_CAPS_VF:
1850595b13e2SJacob Keller 			ice_parse_vf_func_caps(hw, func_p, &cap_resp[i]);
1851148beb61SHenry Tieman 			break;
1852595b13e2SJacob Keller 		case ICE_AQC_CAPS_VSI:
1853595b13e2SJacob Keller 			ice_parse_vsi_func_caps(hw, func_p, &cap_resp[i]);
1854595b13e2SJacob Keller 			break;
1855595b13e2SJacob Keller 		case ICE_AQC_CAPS_FD:
1856595b13e2SJacob Keller 			ice_parse_fdir_func_caps(hw, func_p);
18579c20346bSAnirudh Venkataramanan 			break;
18589c20346bSAnirudh Venkataramanan 		default:
1859595b13e2SJacob Keller 			/* Don't list common capabilities as unknown */
1860595b13e2SJacob Keller 			if (!found)
18619c20346bSAnirudh Venkataramanan 				ice_debug(hw, ICE_DBG_INIT,
1862595b13e2SJacob Keller 					  "func caps: unknown capability[%d]: 0x%x\n",
1863a84db525SAnirudh Venkataramanan 					  i, cap);
18649c20346bSAnirudh Venkataramanan 			break;
18659c20346bSAnirudh Venkataramanan 		}
18669c20346bSAnirudh Venkataramanan 	}
18679164f761SBruce Allan 
1868595b13e2SJacob Keller 	ice_recalc_port_limited_caps(hw, &func_p->common_cap);
18699164f761SBruce Allan }
1870595b13e2SJacob Keller 
1871595b13e2SJacob Keller /**
1872595b13e2SJacob Keller  * ice_parse_valid_functions_cap - Parse ICE_AQC_CAPS_VALID_FUNCTIONS caps
1873595b13e2SJacob Keller  * @hw: pointer to the HW struct
1874595b13e2SJacob Keller  * @dev_p: pointer to device capabilities structure
1875595b13e2SJacob Keller  * @cap: capability element to parse
1876595b13e2SJacob Keller  *
1877595b13e2SJacob Keller  * Parse ICE_AQC_CAPS_VALID_FUNCTIONS for device capabilities.
1878595b13e2SJacob Keller  */
1879595b13e2SJacob Keller static void
1880595b13e2SJacob Keller ice_parse_valid_functions_cap(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
1881595b13e2SJacob Keller 			      struct ice_aqc_list_caps_elem *cap)
1882595b13e2SJacob Keller {
1883595b13e2SJacob Keller 	u32 number = le32_to_cpu(cap->number);
1884595b13e2SJacob Keller 
1885595b13e2SJacob Keller 	dev_p->num_funcs = hweight32(number);
1886595b13e2SJacob Keller 	ice_debug(hw, ICE_DBG_INIT, "dev caps: num_funcs = %d\n",
1887595b13e2SJacob Keller 		  dev_p->num_funcs);
1888595b13e2SJacob Keller }
1889595b13e2SJacob Keller 
1890595b13e2SJacob Keller /**
1891595b13e2SJacob Keller  * ice_parse_vf_dev_caps - Parse ICE_AQC_CAPS_VF device caps
1892595b13e2SJacob Keller  * @hw: pointer to the HW struct
1893595b13e2SJacob Keller  * @dev_p: pointer to device capabilities structure
1894595b13e2SJacob Keller  * @cap: capability element to parse
1895595b13e2SJacob Keller  *
1896595b13e2SJacob Keller  * Parse ICE_AQC_CAPS_VF for device capabilities.
1897595b13e2SJacob Keller  */
1898595b13e2SJacob Keller static void
1899595b13e2SJacob Keller ice_parse_vf_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
1900595b13e2SJacob Keller 		      struct ice_aqc_list_caps_elem *cap)
1901595b13e2SJacob Keller {
1902595b13e2SJacob Keller 	u32 number = le32_to_cpu(cap->number);
1903595b13e2SJacob Keller 
1904595b13e2SJacob Keller 	dev_p->num_vfs_exposed = number;
1905595b13e2SJacob Keller 	ice_debug(hw, ICE_DBG_INIT, "dev_caps: num_vfs_exposed = %d\n",
1906595b13e2SJacob Keller 		  dev_p->num_vfs_exposed);
1907595b13e2SJacob Keller }
1908595b13e2SJacob Keller 
1909595b13e2SJacob Keller /**
1910595b13e2SJacob Keller  * ice_parse_vsi_dev_caps - Parse ICE_AQC_CAPS_VSI device caps
1911595b13e2SJacob Keller  * @hw: pointer to the HW struct
1912595b13e2SJacob Keller  * @dev_p: pointer to device capabilities structure
1913595b13e2SJacob Keller  * @cap: capability element to parse
1914595b13e2SJacob Keller  *
1915595b13e2SJacob Keller  * Parse ICE_AQC_CAPS_VSI for device capabilities.
1916595b13e2SJacob Keller  */
1917595b13e2SJacob Keller static void
1918595b13e2SJacob Keller ice_parse_vsi_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
1919595b13e2SJacob Keller 		       struct ice_aqc_list_caps_elem *cap)
1920595b13e2SJacob Keller {
1921595b13e2SJacob Keller 	u32 number = le32_to_cpu(cap->number);
1922595b13e2SJacob Keller 
1923595b13e2SJacob Keller 	dev_p->num_vsi_allocd_to_host = number;
1924595b13e2SJacob Keller 	ice_debug(hw, ICE_DBG_INIT, "dev caps: num_vsi_allocd_to_host = %d\n",
1925595b13e2SJacob Keller 		  dev_p->num_vsi_allocd_to_host);
1926595b13e2SJacob Keller }
1927595b13e2SJacob Keller 
1928595b13e2SJacob Keller /**
1929595b13e2SJacob Keller  * ice_parse_fdir_dev_caps - Parse ICE_AQC_CAPS_FD device caps
1930595b13e2SJacob Keller  * @hw: pointer to the HW struct
1931595b13e2SJacob Keller  * @dev_p: pointer to device capabilities structure
1932595b13e2SJacob Keller  * @cap: capability element to parse
1933595b13e2SJacob Keller  *
1934595b13e2SJacob Keller  * Parse ICE_AQC_CAPS_FD for device capabilities.
1935595b13e2SJacob Keller  */
1936595b13e2SJacob Keller static void
1937595b13e2SJacob Keller ice_parse_fdir_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
1938595b13e2SJacob Keller 			struct ice_aqc_list_caps_elem *cap)
1939595b13e2SJacob Keller {
1940595b13e2SJacob Keller 	u32 number = le32_to_cpu(cap->number);
1941595b13e2SJacob Keller 
1942595b13e2SJacob Keller 	dev_p->num_flow_director_fltr = number;
1943595b13e2SJacob Keller 	ice_debug(hw, ICE_DBG_INIT, "dev caps: num_flow_director_fltr = %d\n",
1944595b13e2SJacob Keller 		  dev_p->num_flow_director_fltr);
1945595b13e2SJacob Keller }
1946595b13e2SJacob Keller 
1947595b13e2SJacob Keller /**
1948595b13e2SJacob Keller  * ice_parse_dev_caps - Parse device capabilities
1949595b13e2SJacob Keller  * @hw: pointer to the HW struct
1950595b13e2SJacob Keller  * @dev_p: pointer to device capabilities structure
1951595b13e2SJacob Keller  * @buf: buffer containing the device capability records
1952595b13e2SJacob Keller  * @cap_count: the number of capabilities
1953595b13e2SJacob Keller  *
1954595b13e2SJacob Keller  * Helper device to parse device (0x000B) capabilities list. For
1955595b13e2SJacob Keller  * capabilities shared between device and device, this relies on
1956595b13e2SJacob Keller  * ice_parse_common_caps.
1957595b13e2SJacob Keller  *
1958595b13e2SJacob Keller  * Loop through the list of provided capabilities and extract the relevant
1959595b13e2SJacob Keller  * data into the device capabilities structured.
1960595b13e2SJacob Keller  */
1961595b13e2SJacob Keller static void
1962595b13e2SJacob Keller ice_parse_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
1963595b13e2SJacob Keller 		   void *buf, u32 cap_count)
1964595b13e2SJacob Keller {
1965595b13e2SJacob Keller 	struct ice_aqc_list_caps_elem *cap_resp;
1966595b13e2SJacob Keller 	u32 i;
1967595b13e2SJacob Keller 
1968595b13e2SJacob Keller 	cap_resp = (struct ice_aqc_list_caps_elem *)buf;
1969595b13e2SJacob Keller 
1970595b13e2SJacob Keller 	memset(dev_p, 0, sizeof(*dev_p));
1971595b13e2SJacob Keller 
1972595b13e2SJacob Keller 	for (i = 0; i < cap_count; i++) {
1973595b13e2SJacob Keller 		u16 cap = le16_to_cpu(cap_resp[i].cap);
1974595b13e2SJacob Keller 		bool found;
1975595b13e2SJacob Keller 
1976595b13e2SJacob Keller 		found = ice_parse_common_caps(hw, &dev_p->common_cap,
1977595b13e2SJacob Keller 					      &cap_resp[i], "dev caps");
1978595b13e2SJacob Keller 
1979595b13e2SJacob Keller 		switch (cap) {
1980595b13e2SJacob Keller 		case ICE_AQC_CAPS_VALID_FUNCTIONS:
1981595b13e2SJacob Keller 			ice_parse_valid_functions_cap(hw, dev_p, &cap_resp[i]);
1982595b13e2SJacob Keller 			break;
1983595b13e2SJacob Keller 		case ICE_AQC_CAPS_VF:
1984595b13e2SJacob Keller 			ice_parse_vf_dev_caps(hw, dev_p, &cap_resp[i]);
1985595b13e2SJacob Keller 			break;
1986595b13e2SJacob Keller 		case ICE_AQC_CAPS_VSI:
1987595b13e2SJacob Keller 			ice_parse_vsi_dev_caps(hw, dev_p, &cap_resp[i]);
1988595b13e2SJacob Keller 			break;
1989595b13e2SJacob Keller 		case  ICE_AQC_CAPS_FD:
1990595b13e2SJacob Keller 			ice_parse_fdir_dev_caps(hw, dev_p, &cap_resp[i]);
1991595b13e2SJacob Keller 			break;
1992595b13e2SJacob Keller 		default:
1993595b13e2SJacob Keller 			/* Don't list common capabilities as unknown */
1994595b13e2SJacob Keller 			if (!found)
1995595b13e2SJacob Keller 				ice_debug(hw, ICE_DBG_INIT,
1996595b13e2SJacob Keller 					  "dev caps: unknown capability[%d]: 0x%x\n",
1997595b13e2SJacob Keller 					  i, cap);
1998595b13e2SJacob Keller 			break;
1999595b13e2SJacob Keller 		}
2000595b13e2SJacob Keller 	}
2001595b13e2SJacob Keller 
2002595b13e2SJacob Keller 	ice_recalc_port_limited_caps(hw, &dev_p->common_cap);
2003595b13e2SJacob Keller }
2004595b13e2SJacob Keller 
2005595b13e2SJacob Keller /**
20068d7aab35SJacob Keller  * ice_aq_list_caps - query function/device capabilities
2007f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
20088d7aab35SJacob Keller  * @buf: a buffer to hold the capabilities
20098d7aab35SJacob Keller  * @buf_size: size of the buffer
20108d7aab35SJacob Keller  * @cap_count: if not NULL, set to the number of capabilities reported
20118d7aab35SJacob Keller  * @opc: capabilities type to discover, device or function
20129c20346bSAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
20139c20346bSAnirudh Venkataramanan  *
20148d7aab35SJacob Keller  * Get the function (0x000A) or device (0x000B) capabilities description from
20158d7aab35SJacob Keller  * firmware and store it in the buffer.
20168d7aab35SJacob Keller  *
20178d7aab35SJacob Keller  * If the cap_count pointer is not NULL, then it is set to the number of
20188d7aab35SJacob Keller  * capabilities firmware will report. Note that if the buffer size is too
20198d7aab35SJacob Keller  * small, it is possible the command will return ICE_AQ_ERR_ENOMEM. The
20208d7aab35SJacob Keller  * cap_count will still be updated in this case. It is recommended that the
20218d7aab35SJacob Keller  * buffer size be set to ICE_AQ_MAX_BUF_LEN (the largest possible buffer that
20228d7aab35SJacob Keller  * firmware could return) to avoid this.
20239c20346bSAnirudh Venkataramanan  */
20248d7aab35SJacob Keller enum ice_status
20258d7aab35SJacob Keller ice_aq_list_caps(struct ice_hw *hw, void *buf, u16 buf_size, u32 *cap_count,
20269c20346bSAnirudh Venkataramanan 		 enum ice_adminq_opc opc, struct ice_sq_cd *cd)
20279c20346bSAnirudh Venkataramanan {
20289c20346bSAnirudh Venkataramanan 	struct ice_aqc_list_caps *cmd;
20299c20346bSAnirudh Venkataramanan 	struct ice_aq_desc desc;
20309c20346bSAnirudh Venkataramanan 	enum ice_status status;
20319c20346bSAnirudh Venkataramanan 
20329c20346bSAnirudh Venkataramanan 	cmd = &desc.params.get_cap;
20339c20346bSAnirudh Venkataramanan 
20349c20346bSAnirudh Venkataramanan 	if (opc != ice_aqc_opc_list_func_caps &&
20359c20346bSAnirudh Venkataramanan 	    opc != ice_aqc_opc_list_dev_caps)
20369c20346bSAnirudh Venkataramanan 		return ICE_ERR_PARAM;
20379c20346bSAnirudh Venkataramanan 
20389c20346bSAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, opc);
20399c20346bSAnirudh Venkataramanan 	status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
20408d7aab35SJacob Keller 
20418d7aab35SJacob Keller 	if (cap_count)
204299189e8bSAnirudh Venkataramanan 		*cap_count = le32_to_cpu(cmd->count);
20438d7aab35SJacob Keller 
20448d7aab35SJacob Keller 	return status;
20458d7aab35SJacob Keller }
20468d7aab35SJacob Keller 
20478d7aab35SJacob Keller /**
204881aed647SJacob Keller  * ice_discover_dev_caps - Read and extract device capabilities
20497d86cf38SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
205081aed647SJacob Keller  * @dev_caps: pointer to device capabilities structure
205181aed647SJacob Keller  *
205281aed647SJacob Keller  * Read the device capabilities and extract them into the dev_caps structure
205381aed647SJacob Keller  * for later use.
20547d86cf38SAnirudh Venkataramanan  */
2055c8b7abddSBruce Allan static enum ice_status
205681aed647SJacob Keller ice_discover_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_caps)
20577d86cf38SAnirudh Venkataramanan {
20587d86cf38SAnirudh Venkataramanan 	enum ice_status status;
205981aed647SJacob Keller 	u32 cap_count = 0;
20607d86cf38SAnirudh Venkataramanan 	void *cbuf;
20617d86cf38SAnirudh Venkataramanan 
20621082b360SJacob Keller 	cbuf = kzalloc(ICE_AQ_MAX_BUF_LEN, GFP_KERNEL);
20637d86cf38SAnirudh Venkataramanan 	if (!cbuf)
20647d86cf38SAnirudh Venkataramanan 		return ICE_ERR_NO_MEMORY;
20657d86cf38SAnirudh Venkataramanan 
20661082b360SJacob Keller 	/* Although the driver doesn't know the number of capabilities the
20671082b360SJacob Keller 	 * device will return, we can simply send a 4KB buffer, the maximum
20681082b360SJacob Keller 	 * possible size that firmware can return.
20691082b360SJacob Keller 	 */
20701082b360SJacob Keller 	cap_count = ICE_AQ_MAX_BUF_LEN / sizeof(struct ice_aqc_list_caps_elem);
20711082b360SJacob Keller 
207281aed647SJacob Keller 	status = ice_aq_list_caps(hw, cbuf, ICE_AQ_MAX_BUF_LEN, &cap_count,
207381aed647SJacob Keller 				  ice_aqc_opc_list_dev_caps, NULL);
207481aed647SJacob Keller 	if (!status)
207581aed647SJacob Keller 		ice_parse_dev_caps(hw, dev_caps, cbuf, cap_count);
207681aed647SJacob Keller 	kfree(cbuf);
207781aed647SJacob Keller 
207881aed647SJacob Keller 	return status;
207981aed647SJacob Keller }
208081aed647SJacob Keller 
208181aed647SJacob Keller /**
208281aed647SJacob Keller  * ice_discover_func_caps - Read and extract function capabilities
208381aed647SJacob Keller  * @hw: pointer to the hardware structure
208481aed647SJacob Keller  * @func_caps: pointer to function capabilities structure
208581aed647SJacob Keller  *
208681aed647SJacob Keller  * Read the function capabilities and extract them into the func_caps structure
208781aed647SJacob Keller  * for later use.
208881aed647SJacob Keller  */
208981aed647SJacob Keller static enum ice_status
209081aed647SJacob Keller ice_discover_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_caps)
209181aed647SJacob Keller {
209281aed647SJacob Keller 	enum ice_status status;
209381aed647SJacob Keller 	u32 cap_count = 0;
209481aed647SJacob Keller 	void *cbuf;
209581aed647SJacob Keller 
209681aed647SJacob Keller 	cbuf = kzalloc(ICE_AQ_MAX_BUF_LEN, GFP_KERNEL);
209781aed647SJacob Keller 	if (!cbuf)
209881aed647SJacob Keller 		return ICE_ERR_NO_MEMORY;
209981aed647SJacob Keller 
210081aed647SJacob Keller 	/* Although the driver doesn't know the number of capabilities the
210181aed647SJacob Keller 	 * device will return, we can simply send a 4KB buffer, the maximum
210281aed647SJacob Keller 	 * possible size that firmware can return.
210381aed647SJacob Keller 	 */
210481aed647SJacob Keller 	cap_count = ICE_AQ_MAX_BUF_LEN / sizeof(struct ice_aqc_list_caps_elem);
210581aed647SJacob Keller 
210681aed647SJacob Keller 	status = ice_aq_list_caps(hw, cbuf, ICE_AQ_MAX_BUF_LEN, &cap_count,
210781aed647SJacob Keller 				  ice_aqc_opc_list_func_caps, NULL);
210881aed647SJacob Keller 	if (!status)
210981aed647SJacob Keller 		ice_parse_func_caps(hw, func_caps, cbuf, cap_count);
21101082b360SJacob Keller 	kfree(cbuf);
21119c20346bSAnirudh Venkataramanan 
21129c20346bSAnirudh Venkataramanan 	return status;
21139c20346bSAnirudh Venkataramanan }
21149c20346bSAnirudh Venkataramanan 
21159c20346bSAnirudh Venkataramanan /**
2116462acf6aSTony Nguyen  * ice_set_safe_mode_caps - Override dev/func capabilities when in safe mode
2117462acf6aSTony Nguyen  * @hw: pointer to the hardware structure
2118462acf6aSTony Nguyen  */
2119462acf6aSTony Nguyen void ice_set_safe_mode_caps(struct ice_hw *hw)
2120462acf6aSTony Nguyen {
2121462acf6aSTony Nguyen 	struct ice_hw_func_caps *func_caps = &hw->func_caps;
2122462acf6aSTony Nguyen 	struct ice_hw_dev_caps *dev_caps = &hw->dev_caps;
2123462acf6aSTony Nguyen 	u32 valid_func, rxq_first_id, txq_first_id;
2124462acf6aSTony Nguyen 	u32 msix_vector_first_id, max_mtu;
2125eae1bbb2SBruce Allan 	u32 num_funcs;
2126462acf6aSTony Nguyen 
2127462acf6aSTony Nguyen 	/* cache some func_caps values that should be restored after memset */
2128462acf6aSTony Nguyen 	valid_func = func_caps->common_cap.valid_functions;
2129462acf6aSTony Nguyen 	txq_first_id = func_caps->common_cap.txq_first_id;
2130462acf6aSTony Nguyen 	rxq_first_id = func_caps->common_cap.rxq_first_id;
2131462acf6aSTony Nguyen 	msix_vector_first_id = func_caps->common_cap.msix_vector_first_id;
2132462acf6aSTony Nguyen 	max_mtu = func_caps->common_cap.max_mtu;
2133462acf6aSTony Nguyen 
2134462acf6aSTony Nguyen 	/* unset func capabilities */
2135462acf6aSTony Nguyen 	memset(func_caps, 0, sizeof(*func_caps));
2136462acf6aSTony Nguyen 
2137462acf6aSTony Nguyen 	/* restore cached values */
2138462acf6aSTony Nguyen 	func_caps->common_cap.valid_functions = valid_func;
2139462acf6aSTony Nguyen 	func_caps->common_cap.txq_first_id = txq_first_id;
2140462acf6aSTony Nguyen 	func_caps->common_cap.rxq_first_id = rxq_first_id;
2141462acf6aSTony Nguyen 	func_caps->common_cap.msix_vector_first_id = msix_vector_first_id;
2142462acf6aSTony Nguyen 	func_caps->common_cap.max_mtu = max_mtu;
2143462acf6aSTony Nguyen 
2144462acf6aSTony Nguyen 	/* one Tx and one Rx queue in safe mode */
2145462acf6aSTony Nguyen 	func_caps->common_cap.num_rxq = 1;
2146462acf6aSTony Nguyen 	func_caps->common_cap.num_txq = 1;
2147462acf6aSTony Nguyen 
2148462acf6aSTony Nguyen 	/* two MSIX vectors, one for traffic and one for misc causes */
2149462acf6aSTony Nguyen 	func_caps->common_cap.num_msix_vectors = 2;
2150462acf6aSTony Nguyen 	func_caps->guar_num_vsi = 1;
2151462acf6aSTony Nguyen 
2152462acf6aSTony Nguyen 	/* cache some dev_caps values that should be restored after memset */
2153462acf6aSTony Nguyen 	valid_func = dev_caps->common_cap.valid_functions;
2154462acf6aSTony Nguyen 	txq_first_id = dev_caps->common_cap.txq_first_id;
2155462acf6aSTony Nguyen 	rxq_first_id = dev_caps->common_cap.rxq_first_id;
2156462acf6aSTony Nguyen 	msix_vector_first_id = dev_caps->common_cap.msix_vector_first_id;
2157462acf6aSTony Nguyen 	max_mtu = dev_caps->common_cap.max_mtu;
2158eae1bbb2SBruce Allan 	num_funcs = dev_caps->num_funcs;
2159462acf6aSTony Nguyen 
2160462acf6aSTony Nguyen 	/* unset dev capabilities */
2161462acf6aSTony Nguyen 	memset(dev_caps, 0, sizeof(*dev_caps));
2162462acf6aSTony Nguyen 
2163462acf6aSTony Nguyen 	/* restore cached values */
2164462acf6aSTony Nguyen 	dev_caps->common_cap.valid_functions = valid_func;
2165462acf6aSTony Nguyen 	dev_caps->common_cap.txq_first_id = txq_first_id;
2166462acf6aSTony Nguyen 	dev_caps->common_cap.rxq_first_id = rxq_first_id;
2167462acf6aSTony Nguyen 	dev_caps->common_cap.msix_vector_first_id = msix_vector_first_id;
2168462acf6aSTony Nguyen 	dev_caps->common_cap.max_mtu = max_mtu;
2169eae1bbb2SBruce Allan 	dev_caps->num_funcs = num_funcs;
2170462acf6aSTony Nguyen 
2171462acf6aSTony Nguyen 	/* one Tx and one Rx queue per function in safe mode */
2172eae1bbb2SBruce Allan 	dev_caps->common_cap.num_rxq = num_funcs;
2173eae1bbb2SBruce Allan 	dev_caps->common_cap.num_txq = num_funcs;
2174462acf6aSTony Nguyen 
2175462acf6aSTony Nguyen 	/* two MSIX vectors per function */
2176eae1bbb2SBruce Allan 	dev_caps->common_cap.num_msix_vectors = 2 * num_funcs;
2177462acf6aSTony Nguyen }
2178462acf6aSTony Nguyen 
2179462acf6aSTony Nguyen /**
21809c20346bSAnirudh Venkataramanan  * ice_get_caps - get info about the HW
21819c20346bSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
21829c20346bSAnirudh Venkataramanan  */
21839c20346bSAnirudh Venkataramanan enum ice_status ice_get_caps(struct ice_hw *hw)
21849c20346bSAnirudh Venkataramanan {
21859c20346bSAnirudh Venkataramanan 	enum ice_status status;
21869c20346bSAnirudh Venkataramanan 
218781aed647SJacob Keller 	status = ice_discover_dev_caps(hw, &hw->dev_caps);
218881aed647SJacob Keller 	if (status)
21899c20346bSAnirudh Venkataramanan 		return status;
219081aed647SJacob Keller 
219181aed647SJacob Keller 	return ice_discover_func_caps(hw, &hw->func_caps);
21929c20346bSAnirudh Venkataramanan }
21939c20346bSAnirudh Venkataramanan 
21949c20346bSAnirudh Venkataramanan /**
2195e94d4478SAnirudh Venkataramanan  * ice_aq_manage_mac_write - manage MAC address write command
2196f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
2197e94d4478SAnirudh Venkataramanan  * @mac_addr: MAC address to be written as LAA/LAA+WoL/Port address
2198e94d4478SAnirudh Venkataramanan  * @flags: flags to control write behavior
2199e94d4478SAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
2200e94d4478SAnirudh Venkataramanan  *
2201e94d4478SAnirudh Venkataramanan  * This function is used to write MAC address to the NVM (0x0108).
2202e94d4478SAnirudh Venkataramanan  */
2203e94d4478SAnirudh Venkataramanan enum ice_status
2204d671e3e0SJacob Keller ice_aq_manage_mac_write(struct ice_hw *hw, const u8 *mac_addr, u8 flags,
2205e94d4478SAnirudh Venkataramanan 			struct ice_sq_cd *cd)
2206e94d4478SAnirudh Venkataramanan {
2207e94d4478SAnirudh Venkataramanan 	struct ice_aqc_manage_mac_write *cmd;
2208e94d4478SAnirudh Venkataramanan 	struct ice_aq_desc desc;
2209e94d4478SAnirudh Venkataramanan 
2210e94d4478SAnirudh Venkataramanan 	cmd = &desc.params.mac_write;
2211e94d4478SAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_manage_mac_write);
2212e94d4478SAnirudh Venkataramanan 
2213e94d4478SAnirudh Venkataramanan 	cmd->flags = flags;
22145df42c82SJesse Brandeburg 	ether_addr_copy(cmd->mac_addr, mac_addr);
2215e94d4478SAnirudh Venkataramanan 
2216e94d4478SAnirudh Venkataramanan 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
2217e94d4478SAnirudh Venkataramanan }
2218e94d4478SAnirudh Venkataramanan 
2219e94d4478SAnirudh Venkataramanan /**
2220f31e4b6fSAnirudh Venkataramanan  * ice_aq_clear_pxe_mode
2221f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
2222f31e4b6fSAnirudh Venkataramanan  *
2223f31e4b6fSAnirudh Venkataramanan  * Tell the firmware that the driver is taking over from PXE (0x0110).
2224f31e4b6fSAnirudh Venkataramanan  */
2225f31e4b6fSAnirudh Venkataramanan static enum ice_status ice_aq_clear_pxe_mode(struct ice_hw *hw)
2226f31e4b6fSAnirudh Venkataramanan {
2227f31e4b6fSAnirudh Venkataramanan 	struct ice_aq_desc desc;
2228f31e4b6fSAnirudh Venkataramanan 
2229f31e4b6fSAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_clear_pxe_mode);
2230f31e4b6fSAnirudh Venkataramanan 	desc.params.clear_pxe.rx_cnt = ICE_AQC_CLEAR_PXE_RX_CNT;
2231f31e4b6fSAnirudh Venkataramanan 
2232f31e4b6fSAnirudh Venkataramanan 	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
2233f31e4b6fSAnirudh Venkataramanan }
2234f31e4b6fSAnirudh Venkataramanan 
2235f31e4b6fSAnirudh Venkataramanan /**
2236f31e4b6fSAnirudh Venkataramanan  * ice_clear_pxe_mode - clear pxe operations mode
2237f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
2238f31e4b6fSAnirudh Venkataramanan  *
2239f31e4b6fSAnirudh Venkataramanan  * Make sure all PXE mode settings are cleared, including things
2240f31e4b6fSAnirudh Venkataramanan  * like descriptor fetch/write-back mode.
2241f31e4b6fSAnirudh Venkataramanan  */
2242f31e4b6fSAnirudh Venkataramanan void ice_clear_pxe_mode(struct ice_hw *hw)
2243f31e4b6fSAnirudh Venkataramanan {
2244f31e4b6fSAnirudh Venkataramanan 	if (ice_check_sq_alive(hw, &hw->adminq))
2245f31e4b6fSAnirudh Venkataramanan 		ice_aq_clear_pxe_mode(hw);
2246f31e4b6fSAnirudh Venkataramanan }
2247cdedef59SAnirudh Venkataramanan 
2248cdedef59SAnirudh Venkataramanan /**
224948cb27f2SChinh Cao  * ice_get_link_speed_based_on_phy_type - returns link speed
225048cb27f2SChinh Cao  * @phy_type_low: lower part of phy_type
2251aef74145SAnirudh Venkataramanan  * @phy_type_high: higher part of phy_type
225248cb27f2SChinh Cao  *
2253f9867df6SAnirudh Venkataramanan  * This helper function will convert an entry in PHY type structure
2254aef74145SAnirudh Venkataramanan  * [phy_type_low, phy_type_high] to its corresponding link speed.
2255aef74145SAnirudh Venkataramanan  * Note: In the structure of [phy_type_low, phy_type_high], there should
2256f9867df6SAnirudh Venkataramanan  * be one bit set, as this function will convert one PHY type to its
225748cb27f2SChinh Cao  * speed.
225848cb27f2SChinh Cao  * If no bit gets set, ICE_LINK_SPEED_UNKNOWN will be returned
225948cb27f2SChinh Cao  * If more than one bit gets set, ICE_LINK_SPEED_UNKNOWN will be returned
226048cb27f2SChinh Cao  */
2261aef74145SAnirudh Venkataramanan static u16
2262aef74145SAnirudh Venkataramanan ice_get_link_speed_based_on_phy_type(u64 phy_type_low, u64 phy_type_high)
226348cb27f2SChinh Cao {
2264aef74145SAnirudh Venkataramanan 	u16 speed_phy_type_high = ICE_AQ_LINK_SPEED_UNKNOWN;
226548cb27f2SChinh Cao 	u16 speed_phy_type_low = ICE_AQ_LINK_SPEED_UNKNOWN;
226648cb27f2SChinh Cao 
226748cb27f2SChinh Cao 	switch (phy_type_low) {
226848cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_100BASE_TX:
226948cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_100M_SGMII:
227048cb27f2SChinh Cao 		speed_phy_type_low = ICE_AQ_LINK_SPEED_100MB;
227148cb27f2SChinh Cao 		break;
227248cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_1000BASE_T:
227348cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_1000BASE_SX:
227448cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_1000BASE_LX:
227548cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_1000BASE_KX:
227648cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_1G_SGMII:
227748cb27f2SChinh Cao 		speed_phy_type_low = ICE_AQ_LINK_SPEED_1000MB;
227848cb27f2SChinh Cao 		break;
227948cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_2500BASE_T:
228048cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_2500BASE_X:
228148cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_2500BASE_KX:
228248cb27f2SChinh Cao 		speed_phy_type_low = ICE_AQ_LINK_SPEED_2500MB;
228348cb27f2SChinh Cao 		break;
228448cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_5GBASE_T:
228548cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_5GBASE_KR:
228648cb27f2SChinh Cao 		speed_phy_type_low = ICE_AQ_LINK_SPEED_5GB;
228748cb27f2SChinh Cao 		break;
228848cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_10GBASE_T:
228948cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_10G_SFI_DA:
229048cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_10GBASE_SR:
229148cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_10GBASE_LR:
229248cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_10GBASE_KR_CR1:
229348cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_10G_SFI_AOC_ACC:
229448cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_10G_SFI_C2C:
229548cb27f2SChinh Cao 		speed_phy_type_low = ICE_AQ_LINK_SPEED_10GB;
229648cb27f2SChinh Cao 		break;
229748cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_25GBASE_T:
229848cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_25GBASE_CR:
229948cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_25GBASE_CR_S:
230048cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_25GBASE_CR1:
230148cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_25GBASE_SR:
230248cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_25GBASE_LR:
230348cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_25GBASE_KR:
230448cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_25GBASE_KR_S:
230548cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_25GBASE_KR1:
230648cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_25G_AUI_AOC_ACC:
230748cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_25G_AUI_C2C:
230848cb27f2SChinh Cao 		speed_phy_type_low = ICE_AQ_LINK_SPEED_25GB;
230948cb27f2SChinh Cao 		break;
231048cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_40GBASE_CR4:
231148cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_40GBASE_SR4:
231248cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_40GBASE_LR4:
231348cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_40GBASE_KR4:
231448cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_40G_XLAUI_AOC_ACC:
231548cb27f2SChinh Cao 	case ICE_PHY_TYPE_LOW_40G_XLAUI:
231648cb27f2SChinh Cao 		speed_phy_type_low = ICE_AQ_LINK_SPEED_40GB;
231748cb27f2SChinh Cao 		break;
2318aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_50GBASE_CR2:
2319aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_50GBASE_SR2:
2320aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_50GBASE_LR2:
2321aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_50GBASE_KR2:
2322aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_50G_LAUI2_AOC_ACC:
2323aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_50G_LAUI2:
2324aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_50G_AUI2_AOC_ACC:
2325aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_50G_AUI2:
2326aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_50GBASE_CP:
2327aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_50GBASE_SR:
2328aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_50GBASE_FR:
2329aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_50GBASE_LR:
2330aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4:
2331aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_50G_AUI1_AOC_ACC:
2332aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_50G_AUI1:
2333aef74145SAnirudh Venkataramanan 		speed_phy_type_low = ICE_AQ_LINK_SPEED_50GB;
2334aef74145SAnirudh Venkataramanan 		break;
2335aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_100GBASE_CR4:
2336aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_100GBASE_SR4:
2337aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_100GBASE_LR4:
2338aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_100GBASE_KR4:
2339aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_100G_CAUI4_AOC_ACC:
2340aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_100G_CAUI4:
2341aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_100G_AUI4_AOC_ACC:
2342aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_100G_AUI4:
2343aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_100GBASE_CR_PAM4:
2344aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4:
2345aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_100GBASE_CP2:
2346aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_100GBASE_SR2:
2347aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_LOW_100GBASE_DR:
2348aef74145SAnirudh Venkataramanan 		speed_phy_type_low = ICE_AQ_LINK_SPEED_100GB;
2349aef74145SAnirudh Venkataramanan 		break;
235048cb27f2SChinh Cao 	default:
235148cb27f2SChinh Cao 		speed_phy_type_low = ICE_AQ_LINK_SPEED_UNKNOWN;
235248cb27f2SChinh Cao 		break;
235348cb27f2SChinh Cao 	}
235448cb27f2SChinh Cao 
2355aef74145SAnirudh Venkataramanan 	switch (phy_type_high) {
2356aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_HIGH_100GBASE_KR2_PAM4:
2357aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_HIGH_100G_CAUI2_AOC_ACC:
2358aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_HIGH_100G_CAUI2:
2359aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_HIGH_100G_AUI2_AOC_ACC:
2360aef74145SAnirudh Venkataramanan 	case ICE_PHY_TYPE_HIGH_100G_AUI2:
2361aef74145SAnirudh Venkataramanan 		speed_phy_type_high = ICE_AQ_LINK_SPEED_100GB;
2362aef74145SAnirudh Venkataramanan 		break;
2363aef74145SAnirudh Venkataramanan 	default:
2364aef74145SAnirudh Venkataramanan 		speed_phy_type_high = ICE_AQ_LINK_SPEED_UNKNOWN;
2365aef74145SAnirudh Venkataramanan 		break;
2366aef74145SAnirudh Venkataramanan 	}
2367aef74145SAnirudh Venkataramanan 
2368aef74145SAnirudh Venkataramanan 	if (speed_phy_type_low == ICE_AQ_LINK_SPEED_UNKNOWN &&
2369aef74145SAnirudh Venkataramanan 	    speed_phy_type_high == ICE_AQ_LINK_SPEED_UNKNOWN)
2370aef74145SAnirudh Venkataramanan 		return ICE_AQ_LINK_SPEED_UNKNOWN;
2371aef74145SAnirudh Venkataramanan 	else if (speed_phy_type_low != ICE_AQ_LINK_SPEED_UNKNOWN &&
2372aef74145SAnirudh Venkataramanan 		 speed_phy_type_high != ICE_AQ_LINK_SPEED_UNKNOWN)
2373aef74145SAnirudh Venkataramanan 		return ICE_AQ_LINK_SPEED_UNKNOWN;
2374aef74145SAnirudh Venkataramanan 	else if (speed_phy_type_low != ICE_AQ_LINK_SPEED_UNKNOWN &&
2375aef74145SAnirudh Venkataramanan 		 speed_phy_type_high == ICE_AQ_LINK_SPEED_UNKNOWN)
237648cb27f2SChinh Cao 		return speed_phy_type_low;
2377aef74145SAnirudh Venkataramanan 	else
2378aef74145SAnirudh Venkataramanan 		return speed_phy_type_high;
237948cb27f2SChinh Cao }
238048cb27f2SChinh Cao 
238148cb27f2SChinh Cao /**
238248cb27f2SChinh Cao  * ice_update_phy_type
238348cb27f2SChinh Cao  * @phy_type_low: pointer to the lower part of phy_type
2384aef74145SAnirudh Venkataramanan  * @phy_type_high: pointer to the higher part of phy_type
238548cb27f2SChinh Cao  * @link_speeds_bitmap: targeted link speeds bitmap
238648cb27f2SChinh Cao  *
238748cb27f2SChinh Cao  * Note: For the link_speeds_bitmap structure, you can check it at
238848cb27f2SChinh Cao  * [ice_aqc_get_link_status->link_speed]. Caller can pass in
238948cb27f2SChinh Cao  * link_speeds_bitmap include multiple speeds.
239048cb27f2SChinh Cao  *
2391aef74145SAnirudh Venkataramanan  * Each entry in this [phy_type_low, phy_type_high] structure will
2392aef74145SAnirudh Venkataramanan  * present a certain link speed. This helper function will turn on bits
2393aef74145SAnirudh Venkataramanan  * in [phy_type_low, phy_type_high] structure based on the value of
239448cb27f2SChinh Cao  * link_speeds_bitmap input parameter.
239548cb27f2SChinh Cao  */
2396aef74145SAnirudh Venkataramanan void
2397aef74145SAnirudh Venkataramanan ice_update_phy_type(u64 *phy_type_low, u64 *phy_type_high,
2398aef74145SAnirudh Venkataramanan 		    u16 link_speeds_bitmap)
239948cb27f2SChinh Cao {
2400aef74145SAnirudh Venkataramanan 	u64 pt_high;
240148cb27f2SChinh Cao 	u64 pt_low;
240248cb27f2SChinh Cao 	int index;
2403207e3721SBruce Allan 	u16 speed;
240448cb27f2SChinh Cao 
240548cb27f2SChinh Cao 	/* We first check with low part of phy_type */
240648cb27f2SChinh Cao 	for (index = 0; index <= ICE_PHY_TYPE_LOW_MAX_INDEX; index++) {
240748cb27f2SChinh Cao 		pt_low = BIT_ULL(index);
2408aef74145SAnirudh Venkataramanan 		speed = ice_get_link_speed_based_on_phy_type(pt_low, 0);
240948cb27f2SChinh Cao 
241048cb27f2SChinh Cao 		if (link_speeds_bitmap & speed)
241148cb27f2SChinh Cao 			*phy_type_low |= BIT_ULL(index);
241248cb27f2SChinh Cao 	}
2413aef74145SAnirudh Venkataramanan 
2414aef74145SAnirudh Venkataramanan 	/* We then check with high part of phy_type */
2415aef74145SAnirudh Venkataramanan 	for (index = 0; index <= ICE_PHY_TYPE_HIGH_MAX_INDEX; index++) {
2416aef74145SAnirudh Venkataramanan 		pt_high = BIT_ULL(index);
2417aef74145SAnirudh Venkataramanan 		speed = ice_get_link_speed_based_on_phy_type(0, pt_high);
2418aef74145SAnirudh Venkataramanan 
2419aef74145SAnirudh Venkataramanan 		if (link_speeds_bitmap & speed)
2420aef74145SAnirudh Venkataramanan 			*phy_type_high |= BIT_ULL(index);
2421aef74145SAnirudh Venkataramanan 	}
242248cb27f2SChinh Cao }
242348cb27f2SChinh Cao 
242448cb27f2SChinh Cao /**
2425fcea6f3dSAnirudh Venkataramanan  * ice_aq_set_phy_cfg
2426f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
2427fcea6f3dSAnirudh Venkataramanan  * @lport: logical port number
2428fcea6f3dSAnirudh Venkataramanan  * @cfg: structure with PHY configuration data to be set
2429fcea6f3dSAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
2430fcea6f3dSAnirudh Venkataramanan  *
2431fcea6f3dSAnirudh Venkataramanan  * Set the various PHY configuration parameters supported on the Port.
2432fcea6f3dSAnirudh Venkataramanan  * One or more of the Set PHY config parameters may be ignored in an MFP
2433fcea6f3dSAnirudh Venkataramanan  * mode as the PF may not have the privilege to set some of the PHY Config
2434fcea6f3dSAnirudh Venkataramanan  * parameters. This status will be indicated by the command response (0x0601).
2435fcea6f3dSAnirudh Venkataramanan  */
243648cb27f2SChinh Cao enum ice_status
2437fcea6f3dSAnirudh Venkataramanan ice_aq_set_phy_cfg(struct ice_hw *hw, u8 lport,
2438fcea6f3dSAnirudh Venkataramanan 		   struct ice_aqc_set_phy_cfg_data *cfg, struct ice_sq_cd *cd)
2439fcea6f3dSAnirudh Venkataramanan {
2440fcea6f3dSAnirudh Venkataramanan 	struct ice_aq_desc desc;
2441b5e19a64SChinh T Cao 	enum ice_status status;
2442fcea6f3dSAnirudh Venkataramanan 
2443fcea6f3dSAnirudh Venkataramanan 	if (!cfg)
2444fcea6f3dSAnirudh Venkataramanan 		return ICE_ERR_PARAM;
2445fcea6f3dSAnirudh Venkataramanan 
2446d8df260aSChinh T Cao 	/* Ensure that only valid bits of cfg->caps can be turned on. */
2447d8df260aSChinh T Cao 	if (cfg->caps & ~ICE_AQ_PHY_ENA_VALID_MASK) {
2448d8df260aSChinh T Cao 		ice_debug(hw, ICE_DBG_PHY,
2449d8df260aSChinh T Cao 			  "Invalid bit is set in ice_aqc_set_phy_cfg_data->caps : 0x%x\n",
2450d8df260aSChinh T Cao 			  cfg->caps);
2451d8df260aSChinh T Cao 
2452d8df260aSChinh T Cao 		cfg->caps &= ICE_AQ_PHY_ENA_VALID_MASK;
2453d8df260aSChinh T Cao 	}
2454d8df260aSChinh T Cao 
2455fcea6f3dSAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_phy_cfg);
245648cb27f2SChinh Cao 	desc.params.set_phy.lport_num = lport;
245748cb27f2SChinh Cao 	desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
2458fcea6f3dSAnirudh Venkataramanan 
2459dc67039bSJesse Brandeburg 	ice_debug(hw, ICE_DBG_LINK, "phy_type_low = 0x%llx\n",
2460dc67039bSJesse Brandeburg 		  (unsigned long long)le64_to_cpu(cfg->phy_type_low));
2461dc67039bSJesse Brandeburg 	ice_debug(hw, ICE_DBG_LINK, "phy_type_high = 0x%llx\n",
2462dc67039bSJesse Brandeburg 		  (unsigned long long)le64_to_cpu(cfg->phy_type_high));
2463dc67039bSJesse Brandeburg 	ice_debug(hw, ICE_DBG_LINK, "caps = 0x%x\n", cfg->caps);
2464dc67039bSJesse Brandeburg 	ice_debug(hw, ICE_DBG_LINK, "low_power_ctrl = 0x%x\n",
2465dc67039bSJesse Brandeburg 		  cfg->low_power_ctrl);
2466dc67039bSJesse Brandeburg 	ice_debug(hw, ICE_DBG_LINK, "eee_cap = 0x%x\n", cfg->eee_cap);
2467dc67039bSJesse Brandeburg 	ice_debug(hw, ICE_DBG_LINK, "eeer_value = 0x%x\n", cfg->eeer_value);
2468dc67039bSJesse Brandeburg 	ice_debug(hw, ICE_DBG_LINK, "link_fec_opt = 0x%x\n", cfg->link_fec_opt);
2469dc67039bSJesse Brandeburg 
2470b5e19a64SChinh T Cao 	status = ice_aq_send_cmd(hw, &desc, cfg, sizeof(*cfg), cd);
2471b5e19a64SChinh T Cao 	if (hw->adminq.sq_last_status == ICE_AQ_RC_EMODE)
2472b5e19a64SChinh T Cao 		status = 0;
2473b5e19a64SChinh T Cao 
2474b5e19a64SChinh T Cao 	return status;
2475fcea6f3dSAnirudh Venkataramanan }
2476fcea6f3dSAnirudh Venkataramanan 
2477fcea6f3dSAnirudh Venkataramanan /**
2478fcea6f3dSAnirudh Venkataramanan  * ice_update_link_info - update status of the HW network link
2479fcea6f3dSAnirudh Venkataramanan  * @pi: port info structure of the interested logical port
2480fcea6f3dSAnirudh Venkataramanan  */
24815755143dSDave Ertman enum ice_status ice_update_link_info(struct ice_port_info *pi)
2482fcea6f3dSAnirudh Venkataramanan {
2483092a33d4SBruce Allan 	struct ice_link_status *li;
2484fcea6f3dSAnirudh Venkataramanan 	enum ice_status status;
2485fcea6f3dSAnirudh Venkataramanan 
2486fcea6f3dSAnirudh Venkataramanan 	if (!pi)
2487fcea6f3dSAnirudh Venkataramanan 		return ICE_ERR_PARAM;
2488fcea6f3dSAnirudh Venkataramanan 
2489092a33d4SBruce Allan 	li = &pi->phy.link_info;
2490fcea6f3dSAnirudh Venkataramanan 
2491092a33d4SBruce Allan 	status = ice_aq_get_link_info(pi, true, NULL, NULL);
2492092a33d4SBruce Allan 	if (status)
2493092a33d4SBruce Allan 		return status;
2494092a33d4SBruce Allan 
2495092a33d4SBruce Allan 	if (li->link_info & ICE_AQ_MEDIA_AVAILABLE) {
2496092a33d4SBruce Allan 		struct ice_aqc_get_phy_caps_data *pcaps;
2497092a33d4SBruce Allan 		struct ice_hw *hw;
2498092a33d4SBruce Allan 
2499092a33d4SBruce Allan 		hw = pi->hw;
2500092a33d4SBruce Allan 		pcaps = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*pcaps),
2501092a33d4SBruce Allan 				     GFP_KERNEL);
2502fcea6f3dSAnirudh Venkataramanan 		if (!pcaps)
2503fcea6f3dSAnirudh Venkataramanan 			return ICE_ERR_NO_MEMORY;
2504fcea6f3dSAnirudh Venkataramanan 
2505057911baSChinh T Cao 		status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_TOPO_CAP,
2506fcea6f3dSAnirudh Venkataramanan 					     pcaps, NULL);
2507092a33d4SBruce Allan 		if (!status)
2508092a33d4SBruce Allan 			memcpy(li->module_type, &pcaps->module_type,
2509092a33d4SBruce Allan 			       sizeof(li->module_type));
2510fcea6f3dSAnirudh Venkataramanan 
2511fcea6f3dSAnirudh Venkataramanan 		devm_kfree(ice_hw_to_dev(hw), pcaps);
2512092a33d4SBruce Allan 	}
2513092a33d4SBruce Allan 
2514fcea6f3dSAnirudh Venkataramanan 	return status;
2515fcea6f3dSAnirudh Venkataramanan }
2516fcea6f3dSAnirudh Venkataramanan 
2517fcea6f3dSAnirudh Venkataramanan /**
2518fcea6f3dSAnirudh Venkataramanan  * ice_set_fc
2519fcea6f3dSAnirudh Venkataramanan  * @pi: port information structure
2520fcea6f3dSAnirudh Venkataramanan  * @aq_failures: pointer to status code, specific to ice_set_fc routine
252148cb27f2SChinh Cao  * @ena_auto_link_update: enable automatic link update
2522fcea6f3dSAnirudh Venkataramanan  *
2523fcea6f3dSAnirudh Venkataramanan  * Set the requested flow control mode.
2524fcea6f3dSAnirudh Venkataramanan  */
2525fcea6f3dSAnirudh Venkataramanan enum ice_status
252648cb27f2SChinh Cao ice_set_fc(struct ice_port_info *pi, u8 *aq_failures, bool ena_auto_link_update)
2527fcea6f3dSAnirudh Venkataramanan {
2528fcea6f3dSAnirudh Venkataramanan 	struct ice_aqc_set_phy_cfg_data cfg = { 0 };
2529fcea6f3dSAnirudh Venkataramanan 	struct ice_aqc_get_phy_caps_data *pcaps;
2530fcea6f3dSAnirudh Venkataramanan 	enum ice_status status;
2531fcea6f3dSAnirudh Venkataramanan 	u8 pause_mask = 0x0;
2532fcea6f3dSAnirudh Venkataramanan 	struct ice_hw *hw;
2533fcea6f3dSAnirudh Venkataramanan 
2534fcea6f3dSAnirudh Venkataramanan 	if (!pi)
2535fcea6f3dSAnirudh Venkataramanan 		return ICE_ERR_PARAM;
2536fcea6f3dSAnirudh Venkataramanan 	hw = pi->hw;
2537fcea6f3dSAnirudh Venkataramanan 	*aq_failures = ICE_SET_FC_AQ_FAIL_NONE;
2538fcea6f3dSAnirudh Venkataramanan 
2539fcea6f3dSAnirudh Venkataramanan 	switch (pi->fc.req_mode) {
2540fcea6f3dSAnirudh Venkataramanan 	case ICE_FC_FULL:
2541fcea6f3dSAnirudh Venkataramanan 		pause_mask |= ICE_AQC_PHY_EN_TX_LINK_PAUSE;
2542fcea6f3dSAnirudh Venkataramanan 		pause_mask |= ICE_AQC_PHY_EN_RX_LINK_PAUSE;
2543fcea6f3dSAnirudh Venkataramanan 		break;
2544fcea6f3dSAnirudh Venkataramanan 	case ICE_FC_RX_PAUSE:
2545fcea6f3dSAnirudh Venkataramanan 		pause_mask |= ICE_AQC_PHY_EN_RX_LINK_PAUSE;
2546fcea6f3dSAnirudh Venkataramanan 		break;
2547fcea6f3dSAnirudh Venkataramanan 	case ICE_FC_TX_PAUSE:
2548fcea6f3dSAnirudh Venkataramanan 		pause_mask |= ICE_AQC_PHY_EN_TX_LINK_PAUSE;
2549fcea6f3dSAnirudh Venkataramanan 		break;
2550fcea6f3dSAnirudh Venkataramanan 	default:
2551fcea6f3dSAnirudh Venkataramanan 		break;
2552fcea6f3dSAnirudh Venkataramanan 	}
2553fcea6f3dSAnirudh Venkataramanan 
2554fcea6f3dSAnirudh Venkataramanan 	pcaps = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*pcaps), GFP_KERNEL);
2555fcea6f3dSAnirudh Venkataramanan 	if (!pcaps)
2556fcea6f3dSAnirudh Venkataramanan 		return ICE_ERR_NO_MEMORY;
2557fcea6f3dSAnirudh Venkataramanan 
2558f9867df6SAnirudh Venkataramanan 	/* Get the current PHY config */
2559fcea6f3dSAnirudh Venkataramanan 	status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_SW_CFG, pcaps,
2560fcea6f3dSAnirudh Venkataramanan 				     NULL);
2561fcea6f3dSAnirudh Venkataramanan 	if (status) {
2562fcea6f3dSAnirudh Venkataramanan 		*aq_failures = ICE_SET_FC_AQ_FAIL_GET;
2563fcea6f3dSAnirudh Venkataramanan 		goto out;
2564fcea6f3dSAnirudh Venkataramanan 	}
2565fcea6f3dSAnirudh Venkataramanan 
2566fcea6f3dSAnirudh Venkataramanan 	/* clear the old pause settings */
2567fcea6f3dSAnirudh Venkataramanan 	cfg.caps = pcaps->caps & ~(ICE_AQC_PHY_EN_TX_LINK_PAUSE |
2568fcea6f3dSAnirudh Venkataramanan 				   ICE_AQC_PHY_EN_RX_LINK_PAUSE);
2569d8df260aSChinh T Cao 
2570fcea6f3dSAnirudh Venkataramanan 	/* set the new capabilities */
2571fcea6f3dSAnirudh Venkataramanan 	cfg.caps |= pause_mask;
2572d8df260aSChinh T Cao 
2573fcea6f3dSAnirudh Venkataramanan 	/* If the capabilities have changed, then set the new config */
2574fcea6f3dSAnirudh Venkataramanan 	if (cfg.caps != pcaps->caps) {
2575fcea6f3dSAnirudh Venkataramanan 		int retry_count, retry_max = 10;
2576fcea6f3dSAnirudh Venkataramanan 
2577fcea6f3dSAnirudh Venkataramanan 		/* Auto restart link so settings take effect */
257848cb27f2SChinh Cao 		if (ena_auto_link_update)
257948cb27f2SChinh Cao 			cfg.caps |= ICE_AQ_PHY_ENA_AUTO_LINK_UPDT;
2580fcea6f3dSAnirudh Venkataramanan 		/* Copy over all the old settings */
2581aef74145SAnirudh Venkataramanan 		cfg.phy_type_high = pcaps->phy_type_high;
2582fcea6f3dSAnirudh Venkataramanan 		cfg.phy_type_low = pcaps->phy_type_low;
2583fcea6f3dSAnirudh Venkataramanan 		cfg.low_power_ctrl = pcaps->low_power_ctrl;
2584fcea6f3dSAnirudh Venkataramanan 		cfg.eee_cap = pcaps->eee_cap;
2585fcea6f3dSAnirudh Venkataramanan 		cfg.eeer_value = pcaps->eeer_value;
2586fcea6f3dSAnirudh Venkataramanan 		cfg.link_fec_opt = pcaps->link_fec_options;
2587fcea6f3dSAnirudh Venkataramanan 
2588fcea6f3dSAnirudh Venkataramanan 		status = ice_aq_set_phy_cfg(hw, pi->lport, &cfg, NULL);
2589fcea6f3dSAnirudh Venkataramanan 		if (status) {
2590fcea6f3dSAnirudh Venkataramanan 			*aq_failures = ICE_SET_FC_AQ_FAIL_SET;
2591fcea6f3dSAnirudh Venkataramanan 			goto out;
2592fcea6f3dSAnirudh Venkataramanan 		}
2593fcea6f3dSAnirudh Venkataramanan 
2594fcea6f3dSAnirudh Venkataramanan 		/* Update the link info
2595fcea6f3dSAnirudh Venkataramanan 		 * It sometimes takes a really long time for link to
2596fcea6f3dSAnirudh Venkataramanan 		 * come back from the atomic reset. Thus, we wait a
2597fcea6f3dSAnirudh Venkataramanan 		 * little bit.
2598fcea6f3dSAnirudh Venkataramanan 		 */
2599fcea6f3dSAnirudh Venkataramanan 		for (retry_count = 0; retry_count < retry_max; retry_count++) {
2600fcea6f3dSAnirudh Venkataramanan 			status = ice_update_link_info(pi);
2601fcea6f3dSAnirudh Venkataramanan 
2602fcea6f3dSAnirudh Venkataramanan 			if (!status)
2603fcea6f3dSAnirudh Venkataramanan 				break;
2604fcea6f3dSAnirudh Venkataramanan 
2605fcea6f3dSAnirudh Venkataramanan 			mdelay(100);
2606fcea6f3dSAnirudh Venkataramanan 		}
2607fcea6f3dSAnirudh Venkataramanan 
2608fcea6f3dSAnirudh Venkataramanan 		if (status)
2609fcea6f3dSAnirudh Venkataramanan 			*aq_failures = ICE_SET_FC_AQ_FAIL_UPDATE;
2610fcea6f3dSAnirudh Venkataramanan 	}
2611fcea6f3dSAnirudh Venkataramanan 
2612fcea6f3dSAnirudh Venkataramanan out:
2613fcea6f3dSAnirudh Venkataramanan 	devm_kfree(ice_hw_to_dev(hw), pcaps);
2614fcea6f3dSAnirudh Venkataramanan 	return status;
2615fcea6f3dSAnirudh Venkataramanan }
2616fcea6f3dSAnirudh Venkataramanan 
2617fcea6f3dSAnirudh Venkataramanan /**
2618f776b3acSPaul Greenwalt  * ice_copy_phy_caps_to_cfg - Copy PHY ability data to configuration data
2619f776b3acSPaul Greenwalt  * @caps: PHY ability structure to copy date from
2620f776b3acSPaul Greenwalt  * @cfg: PHY configuration structure to copy data to
2621f776b3acSPaul Greenwalt  *
2622f776b3acSPaul Greenwalt  * Helper function to copy AQC PHY get ability data to PHY set configuration
2623f776b3acSPaul Greenwalt  * data structure
2624f776b3acSPaul Greenwalt  */
2625f776b3acSPaul Greenwalt void
2626f776b3acSPaul Greenwalt ice_copy_phy_caps_to_cfg(struct ice_aqc_get_phy_caps_data *caps,
2627f776b3acSPaul Greenwalt 			 struct ice_aqc_set_phy_cfg_data *cfg)
2628f776b3acSPaul Greenwalt {
2629f776b3acSPaul Greenwalt 	if (!caps || !cfg)
2630f776b3acSPaul Greenwalt 		return;
2631f776b3acSPaul Greenwalt 
2632f776b3acSPaul Greenwalt 	cfg->phy_type_low = caps->phy_type_low;
2633f776b3acSPaul Greenwalt 	cfg->phy_type_high = caps->phy_type_high;
2634f776b3acSPaul Greenwalt 	cfg->caps = caps->caps;
2635f776b3acSPaul Greenwalt 	cfg->low_power_ctrl = caps->low_power_ctrl;
2636f776b3acSPaul Greenwalt 	cfg->eee_cap = caps->eee_cap;
2637f776b3acSPaul Greenwalt 	cfg->eeer_value = caps->eeer_value;
2638f776b3acSPaul Greenwalt 	cfg->link_fec_opt = caps->link_fec_options;
2639f776b3acSPaul Greenwalt }
2640f776b3acSPaul Greenwalt 
2641f776b3acSPaul Greenwalt /**
2642f776b3acSPaul Greenwalt  * ice_cfg_phy_fec - Configure PHY FEC data based on FEC mode
2643f776b3acSPaul Greenwalt  * @cfg: PHY configuration data to set FEC mode
2644f776b3acSPaul Greenwalt  * @fec: FEC mode to configure
2645f776b3acSPaul Greenwalt  *
2646f776b3acSPaul Greenwalt  * Caller should copy ice_aqc_get_phy_caps_data.caps ICE_AQC_PHY_EN_AUTO_FEC
2647f776b3acSPaul Greenwalt  * (bit 7) and ice_aqc_get_phy_caps_data.link_fec_options to cfg.caps
2648f776b3acSPaul Greenwalt  * ICE_AQ_PHY_ENA_AUTO_FEC (bit 7) and cfg.link_fec_options before calling.
2649f776b3acSPaul Greenwalt  */
2650f776b3acSPaul Greenwalt void
2651f776b3acSPaul Greenwalt ice_cfg_phy_fec(struct ice_aqc_set_phy_cfg_data *cfg, enum ice_fec_mode fec)
2652f776b3acSPaul Greenwalt {
2653f776b3acSPaul Greenwalt 	switch (fec) {
2654f776b3acSPaul Greenwalt 	case ICE_FEC_BASER:
26553747f031SChinh T Cao 		/* Clear RS bits, and AND BASE-R ability
2656f776b3acSPaul Greenwalt 		 * bits and OR request bits.
2657f776b3acSPaul Greenwalt 		 */
2658f776b3acSPaul Greenwalt 		cfg->link_fec_opt &= ICE_AQC_PHY_FEC_10G_KR_40G_KR4_EN |
2659f776b3acSPaul Greenwalt 				     ICE_AQC_PHY_FEC_25G_KR_CLAUSE74_EN;
2660f776b3acSPaul Greenwalt 		cfg->link_fec_opt |= ICE_AQC_PHY_FEC_10G_KR_40G_KR4_REQ |
2661f776b3acSPaul Greenwalt 				     ICE_AQC_PHY_FEC_25G_KR_REQ;
2662f776b3acSPaul Greenwalt 		break;
2663f776b3acSPaul Greenwalt 	case ICE_FEC_RS:
26643747f031SChinh T Cao 		/* Clear BASE-R bits, and AND RS ability
2665f776b3acSPaul Greenwalt 		 * bits and OR request bits.
2666f776b3acSPaul Greenwalt 		 */
2667f776b3acSPaul Greenwalt 		cfg->link_fec_opt &= ICE_AQC_PHY_FEC_25G_RS_CLAUSE91_EN;
2668f776b3acSPaul Greenwalt 		cfg->link_fec_opt |= ICE_AQC_PHY_FEC_25G_RS_528_REQ |
2669f776b3acSPaul Greenwalt 				     ICE_AQC_PHY_FEC_25G_RS_544_REQ;
2670f776b3acSPaul Greenwalt 		break;
2671f776b3acSPaul Greenwalt 	case ICE_FEC_NONE:
26723747f031SChinh T Cao 		/* Clear all FEC option bits. */
2673f776b3acSPaul Greenwalt 		cfg->link_fec_opt &= ~ICE_AQC_PHY_FEC_MASK;
2674f776b3acSPaul Greenwalt 		break;
2675f776b3acSPaul Greenwalt 	case ICE_FEC_AUTO:
2676f776b3acSPaul Greenwalt 		/* AND auto FEC bit, and all caps bits. */
2677f776b3acSPaul Greenwalt 		cfg->caps &= ICE_AQC_PHY_CAPS_MASK;
2678f776b3acSPaul Greenwalt 		break;
2679f776b3acSPaul Greenwalt 	}
2680f776b3acSPaul Greenwalt }
2681f776b3acSPaul Greenwalt 
2682f776b3acSPaul Greenwalt /**
26830b28b702SAnirudh Venkataramanan  * ice_get_link_status - get status of the HW network link
26840b28b702SAnirudh Venkataramanan  * @pi: port information structure
26850b28b702SAnirudh Venkataramanan  * @link_up: pointer to bool (true/false = linkup/linkdown)
26860b28b702SAnirudh Venkataramanan  *
26870b28b702SAnirudh Venkataramanan  * Variable link_up is true if link is up, false if link is down.
26880b28b702SAnirudh Venkataramanan  * The variable link_up is invalid if status is non zero. As a
26890b28b702SAnirudh Venkataramanan  * result of this call, link status reporting becomes enabled
26900b28b702SAnirudh Venkataramanan  */
26910b28b702SAnirudh Venkataramanan enum ice_status ice_get_link_status(struct ice_port_info *pi, bool *link_up)
26920b28b702SAnirudh Venkataramanan {
26930b28b702SAnirudh Venkataramanan 	struct ice_phy_info *phy_info;
26940b28b702SAnirudh Venkataramanan 	enum ice_status status = 0;
26950b28b702SAnirudh Venkataramanan 
2696c7f2c42bSAnirudh Venkataramanan 	if (!pi || !link_up)
26970b28b702SAnirudh Venkataramanan 		return ICE_ERR_PARAM;
26980b28b702SAnirudh Venkataramanan 
26990b28b702SAnirudh Venkataramanan 	phy_info = &pi->phy;
27000b28b702SAnirudh Venkataramanan 
27010b28b702SAnirudh Venkataramanan 	if (phy_info->get_link_info) {
27020b28b702SAnirudh Venkataramanan 		status = ice_update_link_info(pi);
27030b28b702SAnirudh Venkataramanan 
27040b28b702SAnirudh Venkataramanan 		if (status)
27050b28b702SAnirudh Venkataramanan 			ice_debug(pi->hw, ICE_DBG_LINK,
27060b28b702SAnirudh Venkataramanan 				  "get link status error, status = %d\n",
27070b28b702SAnirudh Venkataramanan 				  status);
27080b28b702SAnirudh Venkataramanan 	}
27090b28b702SAnirudh Venkataramanan 
27100b28b702SAnirudh Venkataramanan 	*link_up = phy_info->link_info.link_info & ICE_AQ_LINK_UP;
27110b28b702SAnirudh Venkataramanan 
27120b28b702SAnirudh Venkataramanan 	return status;
27130b28b702SAnirudh Venkataramanan }
27140b28b702SAnirudh Venkataramanan 
27150b28b702SAnirudh Venkataramanan /**
2716fcea6f3dSAnirudh Venkataramanan  * ice_aq_set_link_restart_an
2717fcea6f3dSAnirudh Venkataramanan  * @pi: pointer to the port information structure
2718fcea6f3dSAnirudh Venkataramanan  * @ena_link: if true: enable link, if false: disable link
2719fcea6f3dSAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
2720fcea6f3dSAnirudh Venkataramanan  *
2721fcea6f3dSAnirudh Venkataramanan  * Sets up the link and restarts the Auto-Negotiation over the link.
2722fcea6f3dSAnirudh Venkataramanan  */
2723fcea6f3dSAnirudh Venkataramanan enum ice_status
2724fcea6f3dSAnirudh Venkataramanan ice_aq_set_link_restart_an(struct ice_port_info *pi, bool ena_link,
2725fcea6f3dSAnirudh Venkataramanan 			   struct ice_sq_cd *cd)
2726fcea6f3dSAnirudh Venkataramanan {
2727fcea6f3dSAnirudh Venkataramanan 	struct ice_aqc_restart_an *cmd;
2728fcea6f3dSAnirudh Venkataramanan 	struct ice_aq_desc desc;
2729fcea6f3dSAnirudh Venkataramanan 
2730fcea6f3dSAnirudh Venkataramanan 	cmd = &desc.params.restart_an;
2731fcea6f3dSAnirudh Venkataramanan 
2732fcea6f3dSAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_restart_an);
2733fcea6f3dSAnirudh Venkataramanan 
2734fcea6f3dSAnirudh Venkataramanan 	cmd->cmd_flags = ICE_AQC_RESTART_AN_LINK_RESTART;
2735fcea6f3dSAnirudh Venkataramanan 	cmd->lport_num = pi->lport;
2736fcea6f3dSAnirudh Venkataramanan 	if (ena_link)
2737fcea6f3dSAnirudh Venkataramanan 		cmd->cmd_flags |= ICE_AQC_RESTART_AN_LINK_ENABLE;
2738fcea6f3dSAnirudh Venkataramanan 	else
2739fcea6f3dSAnirudh Venkataramanan 		cmd->cmd_flags &= ~ICE_AQC_RESTART_AN_LINK_ENABLE;
2740fcea6f3dSAnirudh Venkataramanan 
2741fcea6f3dSAnirudh Venkataramanan 	return ice_aq_send_cmd(pi->hw, &desc, NULL, 0, cd);
2742fcea6f3dSAnirudh Venkataramanan }
2743fcea6f3dSAnirudh Venkataramanan 
2744fcea6f3dSAnirudh Venkataramanan /**
2745250c3b3eSBrett Creeley  * ice_aq_set_event_mask
2746250c3b3eSBrett Creeley  * @hw: pointer to the HW struct
2747250c3b3eSBrett Creeley  * @port_num: port number of the physical function
2748250c3b3eSBrett Creeley  * @mask: event mask to be set
2749250c3b3eSBrett Creeley  * @cd: pointer to command details structure or NULL
2750250c3b3eSBrett Creeley  *
2751250c3b3eSBrett Creeley  * Set event mask (0x0613)
2752250c3b3eSBrett Creeley  */
2753250c3b3eSBrett Creeley enum ice_status
2754250c3b3eSBrett Creeley ice_aq_set_event_mask(struct ice_hw *hw, u8 port_num, u16 mask,
2755250c3b3eSBrett Creeley 		      struct ice_sq_cd *cd)
2756250c3b3eSBrett Creeley {
2757250c3b3eSBrett Creeley 	struct ice_aqc_set_event_mask *cmd;
2758250c3b3eSBrett Creeley 	struct ice_aq_desc desc;
2759250c3b3eSBrett Creeley 
2760250c3b3eSBrett Creeley 	cmd = &desc.params.set_event_mask;
2761250c3b3eSBrett Creeley 
2762250c3b3eSBrett Creeley 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_event_mask);
2763250c3b3eSBrett Creeley 
2764250c3b3eSBrett Creeley 	cmd->lport_num = port_num;
2765250c3b3eSBrett Creeley 
2766250c3b3eSBrett Creeley 	cmd->event_mask = cpu_to_le16(mask);
2767250c3b3eSBrett Creeley 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
2768250c3b3eSBrett Creeley }
2769250c3b3eSBrett Creeley 
2770250c3b3eSBrett Creeley /**
27710e674aebSAnirudh Venkataramanan  * ice_aq_set_mac_loopback
27720e674aebSAnirudh Venkataramanan  * @hw: pointer to the HW struct
27730e674aebSAnirudh Venkataramanan  * @ena_lpbk: Enable or Disable loopback
27740e674aebSAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
27750e674aebSAnirudh Venkataramanan  *
27760e674aebSAnirudh Venkataramanan  * Enable/disable loopback on a given port
27770e674aebSAnirudh Venkataramanan  */
27780e674aebSAnirudh Venkataramanan enum ice_status
27790e674aebSAnirudh Venkataramanan ice_aq_set_mac_loopback(struct ice_hw *hw, bool ena_lpbk, struct ice_sq_cd *cd)
27800e674aebSAnirudh Venkataramanan {
27810e674aebSAnirudh Venkataramanan 	struct ice_aqc_set_mac_lb *cmd;
27820e674aebSAnirudh Venkataramanan 	struct ice_aq_desc desc;
27830e674aebSAnirudh Venkataramanan 
27840e674aebSAnirudh Venkataramanan 	cmd = &desc.params.set_mac_lb;
27850e674aebSAnirudh Venkataramanan 
27860e674aebSAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_mac_lb);
27870e674aebSAnirudh Venkataramanan 	if (ena_lpbk)
27880e674aebSAnirudh Venkataramanan 		cmd->lb_mode = ICE_AQ_MAC_LB_EN;
27890e674aebSAnirudh Venkataramanan 
27900e674aebSAnirudh Venkataramanan 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
27910e674aebSAnirudh Venkataramanan }
27920e674aebSAnirudh Venkataramanan 
27930e674aebSAnirudh Venkataramanan /**
27948e151d50SAnirudh Venkataramanan  * ice_aq_set_port_id_led
27958e151d50SAnirudh Venkataramanan  * @pi: pointer to the port information
27968e151d50SAnirudh Venkataramanan  * @is_orig_mode: is this LED set to original mode (by the net-list)
27978e151d50SAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
27988e151d50SAnirudh Venkataramanan  *
27998e151d50SAnirudh Venkataramanan  * Set LED value for the given port (0x06e9)
28008e151d50SAnirudh Venkataramanan  */
28018e151d50SAnirudh Venkataramanan enum ice_status
28028e151d50SAnirudh Venkataramanan ice_aq_set_port_id_led(struct ice_port_info *pi, bool is_orig_mode,
28038e151d50SAnirudh Venkataramanan 		       struct ice_sq_cd *cd)
28048e151d50SAnirudh Venkataramanan {
28058e151d50SAnirudh Venkataramanan 	struct ice_aqc_set_port_id_led *cmd;
28068e151d50SAnirudh Venkataramanan 	struct ice_hw *hw = pi->hw;
28078e151d50SAnirudh Venkataramanan 	struct ice_aq_desc desc;
28088e151d50SAnirudh Venkataramanan 
28098e151d50SAnirudh Venkataramanan 	cmd = &desc.params.set_port_id_led;
28108e151d50SAnirudh Venkataramanan 
28118e151d50SAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_port_id_led);
28128e151d50SAnirudh Venkataramanan 
28138e151d50SAnirudh Venkataramanan 	if (is_orig_mode)
28148e151d50SAnirudh Venkataramanan 		cmd->ident_mode = ICE_AQC_PORT_IDENT_LED_ORIG;
28158e151d50SAnirudh Venkataramanan 	else
28168e151d50SAnirudh Venkataramanan 		cmd->ident_mode = ICE_AQC_PORT_IDENT_LED_BLINK;
28178e151d50SAnirudh Venkataramanan 
28188e151d50SAnirudh Venkataramanan 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
28198e151d50SAnirudh Venkataramanan }
28208e151d50SAnirudh Venkataramanan 
28218e151d50SAnirudh Venkataramanan /**
2822a012dca9SScott W Taylor  * ice_aq_sff_eeprom
2823a012dca9SScott W Taylor  * @hw: pointer to the HW struct
2824a012dca9SScott W Taylor  * @lport: bits [7:0] = logical port, bit [8] = logical port valid
2825a012dca9SScott W Taylor  * @bus_addr: I2C bus address of the eeprom (typically 0xA0, 0=topo default)
2826a012dca9SScott W Taylor  * @mem_addr: I2C offset. lower 8 bits for address, 8 upper bits zero padding.
2827a012dca9SScott W Taylor  * @page: QSFP page
2828a012dca9SScott W Taylor  * @set_page: set or ignore the page
2829a012dca9SScott W Taylor  * @data: pointer to data buffer to be read/written to the I2C device.
2830a012dca9SScott W Taylor  * @length: 1-16 for read, 1 for write.
2831a012dca9SScott W Taylor  * @write: 0 read, 1 for write.
2832a012dca9SScott W Taylor  * @cd: pointer to command details structure or NULL
2833a012dca9SScott W Taylor  *
2834a012dca9SScott W Taylor  * Read/Write SFF EEPROM (0x06EE)
2835a012dca9SScott W Taylor  */
2836a012dca9SScott W Taylor enum ice_status
2837a012dca9SScott W Taylor ice_aq_sff_eeprom(struct ice_hw *hw, u16 lport, u8 bus_addr,
2838a012dca9SScott W Taylor 		  u16 mem_addr, u8 page, u8 set_page, u8 *data, u8 length,
2839a012dca9SScott W Taylor 		  bool write, struct ice_sq_cd *cd)
2840a012dca9SScott W Taylor {
2841a012dca9SScott W Taylor 	struct ice_aqc_sff_eeprom *cmd;
2842a012dca9SScott W Taylor 	struct ice_aq_desc desc;
2843a012dca9SScott W Taylor 	enum ice_status status;
2844a012dca9SScott W Taylor 
2845a012dca9SScott W Taylor 	if (!data || (mem_addr & 0xff00))
2846a012dca9SScott W Taylor 		return ICE_ERR_PARAM;
2847a012dca9SScott W Taylor 
2848a012dca9SScott W Taylor 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_sff_eeprom);
2849a012dca9SScott W Taylor 	cmd = &desc.params.read_write_sff_param;
2850a012dca9SScott W Taylor 	desc.flags = cpu_to_le16(ICE_AQ_FLAG_RD | ICE_AQ_FLAG_BUF);
2851a012dca9SScott W Taylor 	cmd->lport_num = (u8)(lport & 0xff);
2852a012dca9SScott W Taylor 	cmd->lport_num_valid = (u8)((lport >> 8) & 0x01);
2853a012dca9SScott W Taylor 	cmd->i2c_bus_addr = cpu_to_le16(((bus_addr >> 1) &
2854a012dca9SScott W Taylor 					 ICE_AQC_SFF_I2CBUS_7BIT_M) |
2855a012dca9SScott W Taylor 					((set_page <<
2856a012dca9SScott W Taylor 					  ICE_AQC_SFF_SET_EEPROM_PAGE_S) &
2857a012dca9SScott W Taylor 					 ICE_AQC_SFF_SET_EEPROM_PAGE_M));
2858a012dca9SScott W Taylor 	cmd->i2c_mem_addr = cpu_to_le16(mem_addr & 0xff);
2859a012dca9SScott W Taylor 	cmd->eeprom_page = cpu_to_le16((u16)page << ICE_AQC_SFF_EEPROM_PAGE_S);
2860a012dca9SScott W Taylor 	if (write)
2861a012dca9SScott W Taylor 		cmd->i2c_bus_addr |= cpu_to_le16(ICE_AQC_SFF_IS_WRITE);
2862a012dca9SScott W Taylor 
2863a012dca9SScott W Taylor 	status = ice_aq_send_cmd(hw, &desc, data, length, cd);
2864a012dca9SScott W Taylor 	return status;
2865a012dca9SScott W Taylor }
2866a012dca9SScott W Taylor 
2867a012dca9SScott W Taylor /**
2868d76a60baSAnirudh Venkataramanan  * __ice_aq_get_set_rss_lut
2869d76a60baSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
2870d76a60baSAnirudh Venkataramanan  * @vsi_id: VSI FW index
2871d76a60baSAnirudh Venkataramanan  * @lut_type: LUT table type
2872d76a60baSAnirudh Venkataramanan  * @lut: pointer to the LUT buffer provided by the caller
2873d76a60baSAnirudh Venkataramanan  * @lut_size: size of the LUT buffer
2874d76a60baSAnirudh Venkataramanan  * @glob_lut_idx: global LUT index
2875d76a60baSAnirudh Venkataramanan  * @set: set true to set the table, false to get the table
2876d76a60baSAnirudh Venkataramanan  *
2877d76a60baSAnirudh Venkataramanan  * Internal function to get (0x0B05) or set (0x0B03) RSS look up table
2878d76a60baSAnirudh Venkataramanan  */
2879d76a60baSAnirudh Venkataramanan static enum ice_status
2880d76a60baSAnirudh Venkataramanan __ice_aq_get_set_rss_lut(struct ice_hw *hw, u16 vsi_id, u8 lut_type, u8 *lut,
2881d76a60baSAnirudh Venkataramanan 			 u16 lut_size, u8 glob_lut_idx, bool set)
2882d76a60baSAnirudh Venkataramanan {
2883d76a60baSAnirudh Venkataramanan 	struct ice_aqc_get_set_rss_lut *cmd_resp;
2884d76a60baSAnirudh Venkataramanan 	struct ice_aq_desc desc;
2885d76a60baSAnirudh Venkataramanan 	enum ice_status status;
2886d76a60baSAnirudh Venkataramanan 	u16 flags = 0;
2887d76a60baSAnirudh Venkataramanan 
2888d76a60baSAnirudh Venkataramanan 	cmd_resp = &desc.params.get_set_rss_lut;
2889d76a60baSAnirudh Venkataramanan 
2890d76a60baSAnirudh Venkataramanan 	if (set) {
2891d76a60baSAnirudh Venkataramanan 		ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_rss_lut);
2892d76a60baSAnirudh Venkataramanan 		desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
2893d76a60baSAnirudh Venkataramanan 	} else {
2894d76a60baSAnirudh Venkataramanan 		ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_rss_lut);
2895d76a60baSAnirudh Venkataramanan 	}
2896d76a60baSAnirudh Venkataramanan 
2897d76a60baSAnirudh Venkataramanan 	cmd_resp->vsi_id = cpu_to_le16(((vsi_id <<
2898d76a60baSAnirudh Venkataramanan 					 ICE_AQC_GSET_RSS_LUT_VSI_ID_S) &
2899d76a60baSAnirudh Venkataramanan 					ICE_AQC_GSET_RSS_LUT_VSI_ID_M) |
2900d76a60baSAnirudh Venkataramanan 				       ICE_AQC_GSET_RSS_LUT_VSI_VALID);
2901d76a60baSAnirudh Venkataramanan 
2902d76a60baSAnirudh Venkataramanan 	switch (lut_type) {
2903d76a60baSAnirudh Venkataramanan 	case ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_VSI:
2904d76a60baSAnirudh Venkataramanan 	case ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_PF:
2905d76a60baSAnirudh Venkataramanan 	case ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_GLOBAL:
2906d76a60baSAnirudh Venkataramanan 		flags |= ((lut_type << ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_S) &
2907d76a60baSAnirudh Venkataramanan 			  ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_M);
2908d76a60baSAnirudh Venkataramanan 		break;
2909d76a60baSAnirudh Venkataramanan 	default:
2910d76a60baSAnirudh Venkataramanan 		status = ICE_ERR_PARAM;
2911d76a60baSAnirudh Venkataramanan 		goto ice_aq_get_set_rss_lut_exit;
2912d76a60baSAnirudh Venkataramanan 	}
2913d76a60baSAnirudh Venkataramanan 
2914d76a60baSAnirudh Venkataramanan 	if (lut_type == ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_GLOBAL) {
2915d76a60baSAnirudh Venkataramanan 		flags |= ((glob_lut_idx << ICE_AQC_GSET_RSS_LUT_GLOBAL_IDX_S) &
2916d76a60baSAnirudh Venkataramanan 			  ICE_AQC_GSET_RSS_LUT_GLOBAL_IDX_M);
2917d76a60baSAnirudh Venkataramanan 
2918d76a60baSAnirudh Venkataramanan 		if (!set)
2919d76a60baSAnirudh Venkataramanan 			goto ice_aq_get_set_rss_lut_send;
2920d76a60baSAnirudh Venkataramanan 	} else if (lut_type == ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_PF) {
2921d76a60baSAnirudh Venkataramanan 		if (!set)
2922d76a60baSAnirudh Venkataramanan 			goto ice_aq_get_set_rss_lut_send;
2923d76a60baSAnirudh Venkataramanan 	} else {
2924d76a60baSAnirudh Venkataramanan 		goto ice_aq_get_set_rss_lut_send;
2925d76a60baSAnirudh Venkataramanan 	}
2926d76a60baSAnirudh Venkataramanan 
2927d76a60baSAnirudh Venkataramanan 	/* LUT size is only valid for Global and PF table types */
29284381147dSAnirudh Venkataramanan 	switch (lut_size) {
29294381147dSAnirudh Venkataramanan 	case ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_128:
29304381147dSAnirudh Venkataramanan 		break;
29314381147dSAnirudh Venkataramanan 	case ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_512:
2932d76a60baSAnirudh Venkataramanan 		flags |= (ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_512_FLAG <<
2933d76a60baSAnirudh Venkataramanan 			  ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_S) &
2934d76a60baSAnirudh Venkataramanan 			 ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_M;
29354381147dSAnirudh Venkataramanan 		break;
29364381147dSAnirudh Venkataramanan 	case ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_2K:
29374381147dSAnirudh Venkataramanan 		if (lut_type == ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_PF) {
2938d76a60baSAnirudh Venkataramanan 			flags |= (ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_2K_FLAG <<
2939d76a60baSAnirudh Venkataramanan 				  ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_S) &
2940d76a60baSAnirudh Venkataramanan 				 ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_M;
29414381147dSAnirudh Venkataramanan 			break;
29424381147dSAnirudh Venkataramanan 		}
29434e83fc93SBruce Allan 		fallthrough;
29444381147dSAnirudh Venkataramanan 	default:
2945d76a60baSAnirudh Venkataramanan 		status = ICE_ERR_PARAM;
2946d76a60baSAnirudh Venkataramanan 		goto ice_aq_get_set_rss_lut_exit;
2947d76a60baSAnirudh Venkataramanan 	}
2948d76a60baSAnirudh Venkataramanan 
2949d76a60baSAnirudh Venkataramanan ice_aq_get_set_rss_lut_send:
2950d76a60baSAnirudh Venkataramanan 	cmd_resp->flags = cpu_to_le16(flags);
2951d76a60baSAnirudh Venkataramanan 	status = ice_aq_send_cmd(hw, &desc, lut, lut_size, NULL);
2952d76a60baSAnirudh Venkataramanan 
2953d76a60baSAnirudh Venkataramanan ice_aq_get_set_rss_lut_exit:
2954d76a60baSAnirudh Venkataramanan 	return status;
2955d76a60baSAnirudh Venkataramanan }
2956d76a60baSAnirudh Venkataramanan 
2957d76a60baSAnirudh Venkataramanan /**
2958d76a60baSAnirudh Venkataramanan  * ice_aq_get_rss_lut
2959d76a60baSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
29604fb33f31SAnirudh Venkataramanan  * @vsi_handle: software VSI handle
2961d76a60baSAnirudh Venkataramanan  * @lut_type: LUT table type
2962d76a60baSAnirudh Venkataramanan  * @lut: pointer to the LUT buffer provided by the caller
2963d76a60baSAnirudh Venkataramanan  * @lut_size: size of the LUT buffer
2964d76a60baSAnirudh Venkataramanan  *
2965d76a60baSAnirudh Venkataramanan  * get the RSS lookup table, PF or VSI type
2966d76a60baSAnirudh Venkataramanan  */
2967d76a60baSAnirudh Venkataramanan enum ice_status
29684fb33f31SAnirudh Venkataramanan ice_aq_get_rss_lut(struct ice_hw *hw, u16 vsi_handle, u8 lut_type,
29694fb33f31SAnirudh Venkataramanan 		   u8 *lut, u16 lut_size)
2970d76a60baSAnirudh Venkataramanan {
29714fb33f31SAnirudh Venkataramanan 	if (!ice_is_vsi_valid(hw, vsi_handle) || !lut)
29724fb33f31SAnirudh Venkataramanan 		return ICE_ERR_PARAM;
29734fb33f31SAnirudh Venkataramanan 
29744fb33f31SAnirudh Venkataramanan 	return __ice_aq_get_set_rss_lut(hw, ice_get_hw_vsi_num(hw, vsi_handle),
29754fb33f31SAnirudh Venkataramanan 					lut_type, lut, lut_size, 0, false);
2976d76a60baSAnirudh Venkataramanan }
2977d76a60baSAnirudh Venkataramanan 
2978d76a60baSAnirudh Venkataramanan /**
2979d76a60baSAnirudh Venkataramanan  * ice_aq_set_rss_lut
2980d76a60baSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
29814fb33f31SAnirudh Venkataramanan  * @vsi_handle: software VSI handle
2982d76a60baSAnirudh Venkataramanan  * @lut_type: LUT table type
2983d76a60baSAnirudh Venkataramanan  * @lut: pointer to the LUT buffer provided by the caller
2984d76a60baSAnirudh Venkataramanan  * @lut_size: size of the LUT buffer
2985d76a60baSAnirudh Venkataramanan  *
2986d76a60baSAnirudh Venkataramanan  * set the RSS lookup table, PF or VSI type
2987d76a60baSAnirudh Venkataramanan  */
2988d76a60baSAnirudh Venkataramanan enum ice_status
29894fb33f31SAnirudh Venkataramanan ice_aq_set_rss_lut(struct ice_hw *hw, u16 vsi_handle, u8 lut_type,
29904fb33f31SAnirudh Venkataramanan 		   u8 *lut, u16 lut_size)
2991d76a60baSAnirudh Venkataramanan {
29924fb33f31SAnirudh Venkataramanan 	if (!ice_is_vsi_valid(hw, vsi_handle) || !lut)
29934fb33f31SAnirudh Venkataramanan 		return ICE_ERR_PARAM;
29944fb33f31SAnirudh Venkataramanan 
29954fb33f31SAnirudh Venkataramanan 	return __ice_aq_get_set_rss_lut(hw, ice_get_hw_vsi_num(hw, vsi_handle),
29964fb33f31SAnirudh Venkataramanan 					lut_type, lut, lut_size, 0, true);
2997d76a60baSAnirudh Venkataramanan }
2998d76a60baSAnirudh Venkataramanan 
2999d76a60baSAnirudh Venkataramanan /**
3000d76a60baSAnirudh Venkataramanan  * __ice_aq_get_set_rss_key
3001f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
3002d76a60baSAnirudh Venkataramanan  * @vsi_id: VSI FW index
3003d76a60baSAnirudh Venkataramanan  * @key: pointer to key info struct
3004d76a60baSAnirudh Venkataramanan  * @set: set true to set the key, false to get the key
3005d76a60baSAnirudh Venkataramanan  *
3006d76a60baSAnirudh Venkataramanan  * get (0x0B04) or set (0x0B02) the RSS key per VSI
3007d76a60baSAnirudh Venkataramanan  */
3008d76a60baSAnirudh Venkataramanan static enum
3009d76a60baSAnirudh Venkataramanan ice_status __ice_aq_get_set_rss_key(struct ice_hw *hw, u16 vsi_id,
3010d76a60baSAnirudh Venkataramanan 				    struct ice_aqc_get_set_rss_keys *key,
3011d76a60baSAnirudh Venkataramanan 				    bool set)
3012d76a60baSAnirudh Venkataramanan {
3013d76a60baSAnirudh Venkataramanan 	struct ice_aqc_get_set_rss_key *cmd_resp;
3014d76a60baSAnirudh Venkataramanan 	u16 key_size = sizeof(*key);
3015d76a60baSAnirudh Venkataramanan 	struct ice_aq_desc desc;
3016d76a60baSAnirudh Venkataramanan 
3017d76a60baSAnirudh Venkataramanan 	cmd_resp = &desc.params.get_set_rss_key;
3018d76a60baSAnirudh Venkataramanan 
3019d76a60baSAnirudh Venkataramanan 	if (set) {
3020d76a60baSAnirudh Venkataramanan 		ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_rss_key);
3021d76a60baSAnirudh Venkataramanan 		desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
3022d76a60baSAnirudh Venkataramanan 	} else {
3023d76a60baSAnirudh Venkataramanan 		ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_rss_key);
3024d76a60baSAnirudh Venkataramanan 	}
3025d76a60baSAnirudh Venkataramanan 
3026d76a60baSAnirudh Venkataramanan 	cmd_resp->vsi_id = cpu_to_le16(((vsi_id <<
3027d76a60baSAnirudh Venkataramanan 					 ICE_AQC_GSET_RSS_KEY_VSI_ID_S) &
3028d76a60baSAnirudh Venkataramanan 					ICE_AQC_GSET_RSS_KEY_VSI_ID_M) |
3029d76a60baSAnirudh Venkataramanan 				       ICE_AQC_GSET_RSS_KEY_VSI_VALID);
3030d76a60baSAnirudh Venkataramanan 
3031d76a60baSAnirudh Venkataramanan 	return ice_aq_send_cmd(hw, &desc, key, key_size, NULL);
3032d76a60baSAnirudh Venkataramanan }
3033d76a60baSAnirudh Venkataramanan 
3034d76a60baSAnirudh Venkataramanan /**
3035d76a60baSAnirudh Venkataramanan  * ice_aq_get_rss_key
3036f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
30374fb33f31SAnirudh Venkataramanan  * @vsi_handle: software VSI handle
3038d76a60baSAnirudh Venkataramanan  * @key: pointer to key info struct
3039d76a60baSAnirudh Venkataramanan  *
3040d76a60baSAnirudh Venkataramanan  * get the RSS key per VSI
3041d76a60baSAnirudh Venkataramanan  */
3042d76a60baSAnirudh Venkataramanan enum ice_status
30434fb33f31SAnirudh Venkataramanan ice_aq_get_rss_key(struct ice_hw *hw, u16 vsi_handle,
3044d76a60baSAnirudh Venkataramanan 		   struct ice_aqc_get_set_rss_keys *key)
3045d76a60baSAnirudh Venkataramanan {
30464fb33f31SAnirudh Venkataramanan 	if (!ice_is_vsi_valid(hw, vsi_handle) || !key)
30474fb33f31SAnirudh Venkataramanan 		return ICE_ERR_PARAM;
30484fb33f31SAnirudh Venkataramanan 
30494fb33f31SAnirudh Venkataramanan 	return __ice_aq_get_set_rss_key(hw, ice_get_hw_vsi_num(hw, vsi_handle),
30504fb33f31SAnirudh Venkataramanan 					key, false);
3051d76a60baSAnirudh Venkataramanan }
3052d76a60baSAnirudh Venkataramanan 
3053d76a60baSAnirudh Venkataramanan /**
3054d76a60baSAnirudh Venkataramanan  * ice_aq_set_rss_key
3055f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
30564fb33f31SAnirudh Venkataramanan  * @vsi_handle: software VSI handle
3057d76a60baSAnirudh Venkataramanan  * @keys: pointer to key info struct
3058d76a60baSAnirudh Venkataramanan  *
3059d76a60baSAnirudh Venkataramanan  * set the RSS key per VSI
3060d76a60baSAnirudh Venkataramanan  */
3061d76a60baSAnirudh Venkataramanan enum ice_status
30624fb33f31SAnirudh Venkataramanan ice_aq_set_rss_key(struct ice_hw *hw, u16 vsi_handle,
3063d76a60baSAnirudh Venkataramanan 		   struct ice_aqc_get_set_rss_keys *keys)
3064d76a60baSAnirudh Venkataramanan {
30654fb33f31SAnirudh Venkataramanan 	if (!ice_is_vsi_valid(hw, vsi_handle) || !keys)
30664fb33f31SAnirudh Venkataramanan 		return ICE_ERR_PARAM;
30674fb33f31SAnirudh Venkataramanan 
30684fb33f31SAnirudh Venkataramanan 	return __ice_aq_get_set_rss_key(hw, ice_get_hw_vsi_num(hw, vsi_handle),
30694fb33f31SAnirudh Venkataramanan 					keys, true);
3070d76a60baSAnirudh Venkataramanan }
3071d76a60baSAnirudh Venkataramanan 
3072d76a60baSAnirudh Venkataramanan /**
3073cdedef59SAnirudh Venkataramanan  * ice_aq_add_lan_txq
3074cdedef59SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
3075cdedef59SAnirudh Venkataramanan  * @num_qgrps: Number of added queue groups
3076cdedef59SAnirudh Venkataramanan  * @qg_list: list of queue groups to be added
3077cdedef59SAnirudh Venkataramanan  * @buf_size: size of buffer for indirect command
3078cdedef59SAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
3079cdedef59SAnirudh Venkataramanan  *
3080cdedef59SAnirudh Venkataramanan  * Add Tx LAN queue (0x0C30)
3081cdedef59SAnirudh Venkataramanan  *
3082cdedef59SAnirudh Venkataramanan  * NOTE:
3083cdedef59SAnirudh Venkataramanan  * Prior to calling add Tx LAN queue:
3084cdedef59SAnirudh Venkataramanan  * Initialize the following as part of the Tx queue context:
3085cdedef59SAnirudh Venkataramanan  * Completion queue ID if the queue uses Completion queue, Quanta profile,
3086cdedef59SAnirudh Venkataramanan  * Cache profile and Packet shaper profile.
3087cdedef59SAnirudh Venkataramanan  *
3088cdedef59SAnirudh Venkataramanan  * After add Tx LAN queue AQ command is completed:
3089cdedef59SAnirudh Venkataramanan  * Interrupts should be associated with specific queues,
3090cdedef59SAnirudh Venkataramanan  * Association of Tx queue to Doorbell queue is not part of Add LAN Tx queue
3091cdedef59SAnirudh Venkataramanan  * flow.
3092cdedef59SAnirudh Venkataramanan  */
3093cdedef59SAnirudh Venkataramanan static enum ice_status
3094cdedef59SAnirudh Venkataramanan ice_aq_add_lan_txq(struct ice_hw *hw, u8 num_qgrps,
3095cdedef59SAnirudh Venkataramanan 		   struct ice_aqc_add_tx_qgrp *qg_list, u16 buf_size,
3096cdedef59SAnirudh Venkataramanan 		   struct ice_sq_cd *cd)
3097cdedef59SAnirudh Venkataramanan {
3098cdedef59SAnirudh Venkataramanan 	struct ice_aqc_add_tx_qgrp *list;
3099cdedef59SAnirudh Venkataramanan 	struct ice_aqc_add_txqs *cmd;
3100cdedef59SAnirudh Venkataramanan 	struct ice_aq_desc desc;
310166486d89SBruce Allan 	u16 i, sum_size = 0;
3102cdedef59SAnirudh Venkataramanan 
3103cdedef59SAnirudh Venkataramanan 	cmd = &desc.params.add_txqs;
3104cdedef59SAnirudh Venkataramanan 
3105cdedef59SAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_txqs);
3106cdedef59SAnirudh Venkataramanan 
3107cdedef59SAnirudh Venkataramanan 	if (!qg_list)
3108cdedef59SAnirudh Venkataramanan 		return ICE_ERR_PARAM;
3109cdedef59SAnirudh Venkataramanan 
3110cdedef59SAnirudh Venkataramanan 	if (num_qgrps > ICE_LAN_TXQ_MAX_QGRPS)
3111cdedef59SAnirudh Venkataramanan 		return ICE_ERR_PARAM;
3112cdedef59SAnirudh Venkataramanan 
311366486d89SBruce Allan 	for (i = 0, list = qg_list; i < num_qgrps; i++) {
311466486d89SBruce Allan 		sum_size += struct_size(list, txqs, list->num_txqs);
311566486d89SBruce Allan 		list = (struct ice_aqc_add_tx_qgrp *)(list->txqs +
311666486d89SBruce Allan 						      list->num_txqs);
3117cdedef59SAnirudh Venkataramanan 	}
3118cdedef59SAnirudh Venkataramanan 
311966486d89SBruce Allan 	if (buf_size != sum_size)
3120cdedef59SAnirudh Venkataramanan 		return ICE_ERR_PARAM;
3121cdedef59SAnirudh Venkataramanan 
3122cdedef59SAnirudh Venkataramanan 	desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
3123cdedef59SAnirudh Venkataramanan 
3124cdedef59SAnirudh Venkataramanan 	cmd->num_qgrps = num_qgrps;
3125cdedef59SAnirudh Venkataramanan 
3126cdedef59SAnirudh Venkataramanan 	return ice_aq_send_cmd(hw, &desc, qg_list, buf_size, cd);
3127cdedef59SAnirudh Venkataramanan }
3128cdedef59SAnirudh Venkataramanan 
3129cdedef59SAnirudh Venkataramanan /**
3130cdedef59SAnirudh Venkataramanan  * ice_aq_dis_lan_txq
3131cdedef59SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
3132cdedef59SAnirudh Venkataramanan  * @num_qgrps: number of groups in the list
3133cdedef59SAnirudh Venkataramanan  * @qg_list: the list of groups to disable
3134cdedef59SAnirudh Venkataramanan  * @buf_size: the total size of the qg_list buffer in bytes
313594c4441bSAnirudh Venkataramanan  * @rst_src: if called due to reset, specifies the reset source
3136ddf30f7fSAnirudh Venkataramanan  * @vmvf_num: the relative VM or VF number that is undergoing the reset
3137cdedef59SAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
3138cdedef59SAnirudh Venkataramanan  *
3139cdedef59SAnirudh Venkataramanan  * Disable LAN Tx queue (0x0C31)
3140cdedef59SAnirudh Venkataramanan  */
3141cdedef59SAnirudh Venkataramanan static enum ice_status
3142cdedef59SAnirudh Venkataramanan ice_aq_dis_lan_txq(struct ice_hw *hw, u8 num_qgrps,
3143cdedef59SAnirudh Venkataramanan 		   struct ice_aqc_dis_txq_item *qg_list, u16 buf_size,
3144ddf30f7fSAnirudh Venkataramanan 		   enum ice_disq_rst_src rst_src, u16 vmvf_num,
3145cdedef59SAnirudh Venkataramanan 		   struct ice_sq_cd *cd)
3146cdedef59SAnirudh Venkataramanan {
314766486d89SBruce Allan 	struct ice_aqc_dis_txq_item *item;
3148cdedef59SAnirudh Venkataramanan 	struct ice_aqc_dis_txqs *cmd;
3149cdedef59SAnirudh Venkataramanan 	struct ice_aq_desc desc;
31506e9650d5SVictor Raj 	enum ice_status status;
3151cdedef59SAnirudh Venkataramanan 	u16 i, sz = 0;
3152cdedef59SAnirudh Venkataramanan 
3153cdedef59SAnirudh Venkataramanan 	cmd = &desc.params.dis_txqs;
3154cdedef59SAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_dis_txqs);
3155cdedef59SAnirudh Venkataramanan 
3156ddf30f7fSAnirudh Venkataramanan 	/* qg_list can be NULL only in VM/VF reset flow */
3157ddf30f7fSAnirudh Venkataramanan 	if (!qg_list && !rst_src)
3158cdedef59SAnirudh Venkataramanan 		return ICE_ERR_PARAM;
3159cdedef59SAnirudh Venkataramanan 
3160cdedef59SAnirudh Venkataramanan 	if (num_qgrps > ICE_LAN_TXQ_MAX_QGRPS)
3161cdedef59SAnirudh Venkataramanan 		return ICE_ERR_PARAM;
3162ddf30f7fSAnirudh Venkataramanan 
3163cdedef59SAnirudh Venkataramanan 	cmd->num_entries = num_qgrps;
3164cdedef59SAnirudh Venkataramanan 
3165ddf30f7fSAnirudh Venkataramanan 	cmd->vmvf_and_timeout = cpu_to_le16((5 << ICE_AQC_Q_DIS_TIMEOUT_S) &
3166ddf30f7fSAnirudh Venkataramanan 					    ICE_AQC_Q_DIS_TIMEOUT_M);
3167ddf30f7fSAnirudh Venkataramanan 
3168ddf30f7fSAnirudh Venkataramanan 	switch (rst_src) {
3169ddf30f7fSAnirudh Venkataramanan 	case ICE_VM_RESET:
3170ddf30f7fSAnirudh Venkataramanan 		cmd->cmd_type = ICE_AQC_Q_DIS_CMD_VM_RESET;
3171ddf30f7fSAnirudh Venkataramanan 		cmd->vmvf_and_timeout |=
3172ddf30f7fSAnirudh Venkataramanan 			cpu_to_le16(vmvf_num & ICE_AQC_Q_DIS_VMVF_NUM_M);
3173ddf30f7fSAnirudh Venkataramanan 		break;
3174ddf30f7fSAnirudh Venkataramanan 	case ICE_VF_RESET:
3175ddf30f7fSAnirudh Venkataramanan 		cmd->cmd_type = ICE_AQC_Q_DIS_CMD_VF_RESET;
3176f9867df6SAnirudh Venkataramanan 		/* In this case, FW expects vmvf_num to be absolute VF ID */
3177ddf30f7fSAnirudh Venkataramanan 		cmd->vmvf_and_timeout |=
3178ddf30f7fSAnirudh Venkataramanan 			cpu_to_le16((vmvf_num + hw->func_caps.vf_base_id) &
3179ddf30f7fSAnirudh Venkataramanan 				    ICE_AQC_Q_DIS_VMVF_NUM_M);
3180ddf30f7fSAnirudh Venkataramanan 		break;
3181ddf30f7fSAnirudh Venkataramanan 	case ICE_NO_RESET:
3182ddf30f7fSAnirudh Venkataramanan 	default:
3183ddf30f7fSAnirudh Venkataramanan 		break;
3184ddf30f7fSAnirudh Venkataramanan 	}
3185ddf30f7fSAnirudh Venkataramanan 
31866e9650d5SVictor Raj 	/* flush pipe on time out */
31876e9650d5SVictor Raj 	cmd->cmd_type |= ICE_AQC_Q_DIS_CMD_FLUSH_PIPE;
3188ddf30f7fSAnirudh Venkataramanan 	/* If no queue group info, we are in a reset flow. Issue the AQ */
3189ddf30f7fSAnirudh Venkataramanan 	if (!qg_list)
3190ddf30f7fSAnirudh Venkataramanan 		goto do_aq;
3191ddf30f7fSAnirudh Venkataramanan 
3192ddf30f7fSAnirudh Venkataramanan 	/* set RD bit to indicate that command buffer is provided by the driver
3193ddf30f7fSAnirudh Venkataramanan 	 * and it needs to be read by the firmware
3194ddf30f7fSAnirudh Venkataramanan 	 */
3195ddf30f7fSAnirudh Venkataramanan 	desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
3196ddf30f7fSAnirudh Venkataramanan 
319766486d89SBruce Allan 	for (i = 0, item = qg_list; i < num_qgrps; i++) {
319866486d89SBruce Allan 		u16 item_size = struct_size(item, q_id, item->num_qs);
3199cdedef59SAnirudh Venkataramanan 
3200cdedef59SAnirudh Venkataramanan 		/* If the num of queues is even, add 2 bytes of padding */
320166486d89SBruce Allan 		if ((item->num_qs % 2) == 0)
320266486d89SBruce Allan 			item_size += 2;
320366486d89SBruce Allan 
320466486d89SBruce Allan 		sz += item_size;
320566486d89SBruce Allan 
320666486d89SBruce Allan 		item = (struct ice_aqc_dis_txq_item *)((u8 *)item + item_size);
3207cdedef59SAnirudh Venkataramanan 	}
3208cdedef59SAnirudh Venkataramanan 
3209cdedef59SAnirudh Venkataramanan 	if (buf_size != sz)
3210cdedef59SAnirudh Venkataramanan 		return ICE_ERR_PARAM;
3211cdedef59SAnirudh Venkataramanan 
3212ddf30f7fSAnirudh Venkataramanan do_aq:
32136e9650d5SVictor Raj 	status = ice_aq_send_cmd(hw, &desc, qg_list, buf_size, cd);
32146e9650d5SVictor Raj 	if (status) {
32156e9650d5SVictor Raj 		if (!qg_list)
32166e9650d5SVictor Raj 			ice_debug(hw, ICE_DBG_SCHED, "VM%d disable failed %d\n",
32176e9650d5SVictor Raj 				  vmvf_num, hw->adminq.sq_last_status);
32186e9650d5SVictor Raj 		else
32192f2da36eSAnirudh Venkataramanan 			ice_debug(hw, ICE_DBG_SCHED, "disable queue %d failed %d\n",
32206e9650d5SVictor Raj 				  le16_to_cpu(qg_list[0].q_id[0]),
32216e9650d5SVictor Raj 				  hw->adminq.sq_last_status);
32226e9650d5SVictor Raj 	}
32236e9650d5SVictor Raj 	return status;
3224cdedef59SAnirudh Venkataramanan }
3225cdedef59SAnirudh Venkataramanan 
3226cdedef59SAnirudh Venkataramanan /* End of FW Admin Queue command wrappers */
3227cdedef59SAnirudh Venkataramanan 
3228cdedef59SAnirudh Venkataramanan /**
3229cdedef59SAnirudh Venkataramanan  * ice_write_byte - write a byte to a packed context structure
3230cdedef59SAnirudh Venkataramanan  * @src_ctx:  the context structure to read from
3231cdedef59SAnirudh Venkataramanan  * @dest_ctx: the context to be written to
3232cdedef59SAnirudh Venkataramanan  * @ce_info:  a description of the struct to be filled
3233cdedef59SAnirudh Venkataramanan  */
3234c8b7abddSBruce Allan static void
3235c8b7abddSBruce Allan ice_write_byte(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
3236cdedef59SAnirudh Venkataramanan {
3237cdedef59SAnirudh Venkataramanan 	u8 src_byte, dest_byte, mask;
3238cdedef59SAnirudh Venkataramanan 	u8 *from, *dest;
3239cdedef59SAnirudh Venkataramanan 	u16 shift_width;
3240cdedef59SAnirudh Venkataramanan 
3241cdedef59SAnirudh Venkataramanan 	/* copy from the next struct field */
3242cdedef59SAnirudh Venkataramanan 	from = src_ctx + ce_info->offset;
3243cdedef59SAnirudh Venkataramanan 
3244cdedef59SAnirudh Venkataramanan 	/* prepare the bits and mask */
3245cdedef59SAnirudh Venkataramanan 	shift_width = ce_info->lsb % 8;
3246cdedef59SAnirudh Venkataramanan 	mask = (u8)(BIT(ce_info->width) - 1);
3247cdedef59SAnirudh Venkataramanan 
3248cdedef59SAnirudh Venkataramanan 	src_byte = *from;
3249cdedef59SAnirudh Venkataramanan 	src_byte &= mask;
3250cdedef59SAnirudh Venkataramanan 
3251cdedef59SAnirudh Venkataramanan 	/* shift to correct alignment */
3252cdedef59SAnirudh Venkataramanan 	mask <<= shift_width;
3253cdedef59SAnirudh Venkataramanan 	src_byte <<= shift_width;
3254cdedef59SAnirudh Venkataramanan 
3255cdedef59SAnirudh Venkataramanan 	/* get the current bits from the target bit string */
3256cdedef59SAnirudh Venkataramanan 	dest = dest_ctx + (ce_info->lsb / 8);
3257cdedef59SAnirudh Venkataramanan 
3258cdedef59SAnirudh Venkataramanan 	memcpy(&dest_byte, dest, sizeof(dest_byte));
3259cdedef59SAnirudh Venkataramanan 
3260cdedef59SAnirudh Venkataramanan 	dest_byte &= ~mask;	/* get the bits not changing */
3261cdedef59SAnirudh Venkataramanan 	dest_byte |= src_byte;	/* add in the new bits */
3262cdedef59SAnirudh Venkataramanan 
3263cdedef59SAnirudh Venkataramanan 	/* put it all back */
3264cdedef59SAnirudh Venkataramanan 	memcpy(dest, &dest_byte, sizeof(dest_byte));
3265cdedef59SAnirudh Venkataramanan }
3266cdedef59SAnirudh Venkataramanan 
3267cdedef59SAnirudh Venkataramanan /**
3268cdedef59SAnirudh Venkataramanan  * ice_write_word - write a word to a packed context structure
3269cdedef59SAnirudh Venkataramanan  * @src_ctx:  the context structure to read from
3270cdedef59SAnirudh Venkataramanan  * @dest_ctx: the context to be written to
3271cdedef59SAnirudh Venkataramanan  * @ce_info:  a description of the struct to be filled
3272cdedef59SAnirudh Venkataramanan  */
3273c8b7abddSBruce Allan static void
3274c8b7abddSBruce Allan ice_write_word(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
3275cdedef59SAnirudh Venkataramanan {
3276cdedef59SAnirudh Venkataramanan 	u16 src_word, mask;
3277cdedef59SAnirudh Venkataramanan 	__le16 dest_word;
3278cdedef59SAnirudh Venkataramanan 	u8 *from, *dest;
3279cdedef59SAnirudh Venkataramanan 	u16 shift_width;
3280cdedef59SAnirudh Venkataramanan 
3281cdedef59SAnirudh Venkataramanan 	/* copy from the next struct field */
3282cdedef59SAnirudh Venkataramanan 	from = src_ctx + ce_info->offset;
3283cdedef59SAnirudh Venkataramanan 
3284cdedef59SAnirudh Venkataramanan 	/* prepare the bits and mask */
3285cdedef59SAnirudh Venkataramanan 	shift_width = ce_info->lsb % 8;
3286cdedef59SAnirudh Venkataramanan 	mask = BIT(ce_info->width) - 1;
3287cdedef59SAnirudh Venkataramanan 
3288cdedef59SAnirudh Venkataramanan 	/* don't swizzle the bits until after the mask because the mask bits
3289cdedef59SAnirudh Venkataramanan 	 * will be in a different bit position on big endian machines
3290cdedef59SAnirudh Venkataramanan 	 */
3291cdedef59SAnirudh Venkataramanan 	src_word = *(u16 *)from;
3292cdedef59SAnirudh Venkataramanan 	src_word &= mask;
3293cdedef59SAnirudh Venkataramanan 
3294cdedef59SAnirudh Venkataramanan 	/* shift to correct alignment */
3295cdedef59SAnirudh Venkataramanan 	mask <<= shift_width;
3296cdedef59SAnirudh Venkataramanan 	src_word <<= shift_width;
3297cdedef59SAnirudh Venkataramanan 
3298cdedef59SAnirudh Venkataramanan 	/* get the current bits from the target bit string */
3299cdedef59SAnirudh Venkataramanan 	dest = dest_ctx + (ce_info->lsb / 8);
3300cdedef59SAnirudh Venkataramanan 
3301cdedef59SAnirudh Venkataramanan 	memcpy(&dest_word, dest, sizeof(dest_word));
3302cdedef59SAnirudh Venkataramanan 
3303cdedef59SAnirudh Venkataramanan 	dest_word &= ~(cpu_to_le16(mask));	/* get the bits not changing */
3304cdedef59SAnirudh Venkataramanan 	dest_word |= cpu_to_le16(src_word);	/* add in the new bits */
3305cdedef59SAnirudh Venkataramanan 
3306cdedef59SAnirudh Venkataramanan 	/* put it all back */
3307cdedef59SAnirudh Venkataramanan 	memcpy(dest, &dest_word, sizeof(dest_word));
3308cdedef59SAnirudh Venkataramanan }
3309cdedef59SAnirudh Venkataramanan 
3310cdedef59SAnirudh Venkataramanan /**
3311cdedef59SAnirudh Venkataramanan  * ice_write_dword - write a dword to a packed context structure
3312cdedef59SAnirudh Venkataramanan  * @src_ctx:  the context structure to read from
3313cdedef59SAnirudh Venkataramanan  * @dest_ctx: the context to be written to
3314cdedef59SAnirudh Venkataramanan  * @ce_info:  a description of the struct to be filled
3315cdedef59SAnirudh Venkataramanan  */
3316c8b7abddSBruce Allan static void
3317c8b7abddSBruce Allan ice_write_dword(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
3318cdedef59SAnirudh Venkataramanan {
3319cdedef59SAnirudh Venkataramanan 	u32 src_dword, mask;
3320cdedef59SAnirudh Venkataramanan 	__le32 dest_dword;
3321cdedef59SAnirudh Venkataramanan 	u8 *from, *dest;
3322cdedef59SAnirudh Venkataramanan 	u16 shift_width;
3323cdedef59SAnirudh Venkataramanan 
3324cdedef59SAnirudh Venkataramanan 	/* copy from the next struct field */
3325cdedef59SAnirudh Venkataramanan 	from = src_ctx + ce_info->offset;
3326cdedef59SAnirudh Venkataramanan 
3327cdedef59SAnirudh Venkataramanan 	/* prepare the bits and mask */
3328cdedef59SAnirudh Venkataramanan 	shift_width = ce_info->lsb % 8;
3329cdedef59SAnirudh Venkataramanan 
3330cdedef59SAnirudh Venkataramanan 	/* if the field width is exactly 32 on an x86 machine, then the shift
3331cdedef59SAnirudh Venkataramanan 	 * operation will not work because the SHL instructions count is masked
3332cdedef59SAnirudh Venkataramanan 	 * to 5 bits so the shift will do nothing
3333cdedef59SAnirudh Venkataramanan 	 */
3334cdedef59SAnirudh Venkataramanan 	if (ce_info->width < 32)
3335cdedef59SAnirudh Venkataramanan 		mask = BIT(ce_info->width) - 1;
3336cdedef59SAnirudh Venkataramanan 	else
3337cdedef59SAnirudh Venkataramanan 		mask = (u32)~0;
3338cdedef59SAnirudh Venkataramanan 
3339cdedef59SAnirudh Venkataramanan 	/* don't swizzle the bits until after the mask because the mask bits
3340cdedef59SAnirudh Venkataramanan 	 * will be in a different bit position on big endian machines
3341cdedef59SAnirudh Venkataramanan 	 */
3342cdedef59SAnirudh Venkataramanan 	src_dword = *(u32 *)from;
3343cdedef59SAnirudh Venkataramanan 	src_dword &= mask;
3344cdedef59SAnirudh Venkataramanan 
3345cdedef59SAnirudh Venkataramanan 	/* shift to correct alignment */
3346cdedef59SAnirudh Venkataramanan 	mask <<= shift_width;
3347cdedef59SAnirudh Venkataramanan 	src_dword <<= shift_width;
3348cdedef59SAnirudh Venkataramanan 
3349cdedef59SAnirudh Venkataramanan 	/* get the current bits from the target bit string */
3350cdedef59SAnirudh Venkataramanan 	dest = dest_ctx + (ce_info->lsb / 8);
3351cdedef59SAnirudh Venkataramanan 
3352cdedef59SAnirudh Venkataramanan 	memcpy(&dest_dword, dest, sizeof(dest_dword));
3353cdedef59SAnirudh Venkataramanan 
3354cdedef59SAnirudh Venkataramanan 	dest_dword &= ~(cpu_to_le32(mask));	/* get the bits not changing */
3355cdedef59SAnirudh Venkataramanan 	dest_dword |= cpu_to_le32(src_dword);	/* add in the new bits */
3356cdedef59SAnirudh Venkataramanan 
3357cdedef59SAnirudh Venkataramanan 	/* put it all back */
3358cdedef59SAnirudh Venkataramanan 	memcpy(dest, &dest_dword, sizeof(dest_dword));
3359cdedef59SAnirudh Venkataramanan }
3360cdedef59SAnirudh Venkataramanan 
3361cdedef59SAnirudh Venkataramanan /**
3362cdedef59SAnirudh Venkataramanan  * ice_write_qword - write a qword to a packed context structure
3363cdedef59SAnirudh Venkataramanan  * @src_ctx:  the context structure to read from
3364cdedef59SAnirudh Venkataramanan  * @dest_ctx: the context to be written to
3365cdedef59SAnirudh Venkataramanan  * @ce_info:  a description of the struct to be filled
3366cdedef59SAnirudh Venkataramanan  */
3367c8b7abddSBruce Allan static void
3368c8b7abddSBruce Allan ice_write_qword(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
3369cdedef59SAnirudh Venkataramanan {
3370cdedef59SAnirudh Venkataramanan 	u64 src_qword, mask;
3371cdedef59SAnirudh Venkataramanan 	__le64 dest_qword;
3372cdedef59SAnirudh Venkataramanan 	u8 *from, *dest;
3373cdedef59SAnirudh Venkataramanan 	u16 shift_width;
3374cdedef59SAnirudh Venkataramanan 
3375cdedef59SAnirudh Venkataramanan 	/* copy from the next struct field */
3376cdedef59SAnirudh Venkataramanan 	from = src_ctx + ce_info->offset;
3377cdedef59SAnirudh Venkataramanan 
3378cdedef59SAnirudh Venkataramanan 	/* prepare the bits and mask */
3379cdedef59SAnirudh Venkataramanan 	shift_width = ce_info->lsb % 8;
3380cdedef59SAnirudh Venkataramanan 
3381cdedef59SAnirudh Venkataramanan 	/* if the field width is exactly 64 on an x86 machine, then the shift
3382cdedef59SAnirudh Venkataramanan 	 * operation will not work because the SHL instructions count is masked
3383cdedef59SAnirudh Venkataramanan 	 * to 6 bits so the shift will do nothing
3384cdedef59SAnirudh Venkataramanan 	 */
3385cdedef59SAnirudh Venkataramanan 	if (ce_info->width < 64)
3386cdedef59SAnirudh Venkataramanan 		mask = BIT_ULL(ce_info->width) - 1;
3387cdedef59SAnirudh Venkataramanan 	else
3388cdedef59SAnirudh Venkataramanan 		mask = (u64)~0;
3389cdedef59SAnirudh Venkataramanan 
3390cdedef59SAnirudh Venkataramanan 	/* don't swizzle the bits until after the mask because the mask bits
3391cdedef59SAnirudh Venkataramanan 	 * will be in a different bit position on big endian machines
3392cdedef59SAnirudh Venkataramanan 	 */
3393cdedef59SAnirudh Venkataramanan 	src_qword = *(u64 *)from;
3394cdedef59SAnirudh Venkataramanan 	src_qword &= mask;
3395cdedef59SAnirudh Venkataramanan 
3396cdedef59SAnirudh Venkataramanan 	/* shift to correct alignment */
3397cdedef59SAnirudh Venkataramanan 	mask <<= shift_width;
3398cdedef59SAnirudh Venkataramanan 	src_qword <<= shift_width;
3399cdedef59SAnirudh Venkataramanan 
3400cdedef59SAnirudh Venkataramanan 	/* get the current bits from the target bit string */
3401cdedef59SAnirudh Venkataramanan 	dest = dest_ctx + (ce_info->lsb / 8);
3402cdedef59SAnirudh Venkataramanan 
3403cdedef59SAnirudh Venkataramanan 	memcpy(&dest_qword, dest, sizeof(dest_qword));
3404cdedef59SAnirudh Venkataramanan 
3405cdedef59SAnirudh Venkataramanan 	dest_qword &= ~(cpu_to_le64(mask));	/* get the bits not changing */
3406cdedef59SAnirudh Venkataramanan 	dest_qword |= cpu_to_le64(src_qword);	/* add in the new bits */
3407cdedef59SAnirudh Venkataramanan 
3408cdedef59SAnirudh Venkataramanan 	/* put it all back */
3409cdedef59SAnirudh Venkataramanan 	memcpy(dest, &dest_qword, sizeof(dest_qword));
3410cdedef59SAnirudh Venkataramanan }
3411cdedef59SAnirudh Venkataramanan 
3412cdedef59SAnirudh Venkataramanan /**
3413cdedef59SAnirudh Venkataramanan  * ice_set_ctx - set context bits in packed structure
34147e34786aSBruce Allan  * @hw: pointer to the hardware structure
3415cdedef59SAnirudh Venkataramanan  * @src_ctx:  pointer to a generic non-packed context structure
3416cdedef59SAnirudh Venkataramanan  * @dest_ctx: pointer to memory for the packed structure
3417cdedef59SAnirudh Venkataramanan  * @ce_info:  a description of the structure to be transformed
3418cdedef59SAnirudh Venkataramanan  */
3419cdedef59SAnirudh Venkataramanan enum ice_status
34207e34786aSBruce Allan ice_set_ctx(struct ice_hw *hw, u8 *src_ctx, u8 *dest_ctx,
34217e34786aSBruce Allan 	    const struct ice_ctx_ele *ce_info)
3422cdedef59SAnirudh Venkataramanan {
3423cdedef59SAnirudh Venkataramanan 	int f;
3424cdedef59SAnirudh Venkataramanan 
3425cdedef59SAnirudh Venkataramanan 	for (f = 0; ce_info[f].width; f++) {
3426cdedef59SAnirudh Venkataramanan 		/* We have to deal with each element of the FW response
3427cdedef59SAnirudh Venkataramanan 		 * using the correct size so that we are correct regardless
3428cdedef59SAnirudh Venkataramanan 		 * of the endianness of the machine.
3429cdedef59SAnirudh Venkataramanan 		 */
34307e34786aSBruce Allan 		if (ce_info[f].width > (ce_info[f].size_of * BITS_PER_BYTE)) {
34317e34786aSBruce Allan 			ice_debug(hw, ICE_DBG_QCTX,
34327e34786aSBruce Allan 				  "Field %d width of %d bits larger than size of %d byte(s) ... skipping write\n",
34337e34786aSBruce Allan 				  f, ce_info[f].width, ce_info[f].size_of);
34347e34786aSBruce Allan 			continue;
34357e34786aSBruce Allan 		}
3436cdedef59SAnirudh Venkataramanan 		switch (ce_info[f].size_of) {
3437cdedef59SAnirudh Venkataramanan 		case sizeof(u8):
3438cdedef59SAnirudh Venkataramanan 			ice_write_byte(src_ctx, dest_ctx, &ce_info[f]);
3439cdedef59SAnirudh Venkataramanan 			break;
3440cdedef59SAnirudh Venkataramanan 		case sizeof(u16):
3441cdedef59SAnirudh Venkataramanan 			ice_write_word(src_ctx, dest_ctx, &ce_info[f]);
3442cdedef59SAnirudh Venkataramanan 			break;
3443cdedef59SAnirudh Venkataramanan 		case sizeof(u32):
3444cdedef59SAnirudh Venkataramanan 			ice_write_dword(src_ctx, dest_ctx, &ce_info[f]);
3445cdedef59SAnirudh Venkataramanan 			break;
3446cdedef59SAnirudh Venkataramanan 		case sizeof(u64):
3447cdedef59SAnirudh Venkataramanan 			ice_write_qword(src_ctx, dest_ctx, &ce_info[f]);
3448cdedef59SAnirudh Venkataramanan 			break;
3449cdedef59SAnirudh Venkataramanan 		default:
3450cdedef59SAnirudh Venkataramanan 			return ICE_ERR_INVAL_SIZE;
3451cdedef59SAnirudh Venkataramanan 		}
3452cdedef59SAnirudh Venkataramanan 	}
3453cdedef59SAnirudh Venkataramanan 
3454cdedef59SAnirudh Venkataramanan 	return 0;
3455cdedef59SAnirudh Venkataramanan }
3456cdedef59SAnirudh Venkataramanan 
3457cdedef59SAnirudh Venkataramanan /**
3458bb87ee0eSAnirudh Venkataramanan  * ice_get_lan_q_ctx - get the LAN queue context for the given VSI and TC
3459bb87ee0eSAnirudh Venkataramanan  * @hw: pointer to the HW struct
3460bb87ee0eSAnirudh Venkataramanan  * @vsi_handle: software VSI handle
3461bb87ee0eSAnirudh Venkataramanan  * @tc: TC number
3462bb87ee0eSAnirudh Venkataramanan  * @q_handle: software queue handle
3463bb87ee0eSAnirudh Venkataramanan  */
34641ddef455SUsha Ketineni struct ice_q_ctx *
3465bb87ee0eSAnirudh Venkataramanan ice_get_lan_q_ctx(struct ice_hw *hw, u16 vsi_handle, u8 tc, u16 q_handle)
3466bb87ee0eSAnirudh Venkataramanan {
3467bb87ee0eSAnirudh Venkataramanan 	struct ice_vsi_ctx *vsi;
3468bb87ee0eSAnirudh Venkataramanan 	struct ice_q_ctx *q_ctx;
3469bb87ee0eSAnirudh Venkataramanan 
3470bb87ee0eSAnirudh Venkataramanan 	vsi = ice_get_vsi_ctx(hw, vsi_handle);
3471bb87ee0eSAnirudh Venkataramanan 	if (!vsi)
3472bb87ee0eSAnirudh Venkataramanan 		return NULL;
3473bb87ee0eSAnirudh Venkataramanan 	if (q_handle >= vsi->num_lan_q_entries[tc])
3474bb87ee0eSAnirudh Venkataramanan 		return NULL;
3475bb87ee0eSAnirudh Venkataramanan 	if (!vsi->lan_q_ctx[tc])
3476bb87ee0eSAnirudh Venkataramanan 		return NULL;
3477bb87ee0eSAnirudh Venkataramanan 	q_ctx = vsi->lan_q_ctx[tc];
3478bb87ee0eSAnirudh Venkataramanan 	return &q_ctx[q_handle];
3479bb87ee0eSAnirudh Venkataramanan }
3480bb87ee0eSAnirudh Venkataramanan 
3481bb87ee0eSAnirudh Venkataramanan /**
3482cdedef59SAnirudh Venkataramanan  * ice_ena_vsi_txq
3483cdedef59SAnirudh Venkataramanan  * @pi: port information structure
34844fb33f31SAnirudh Venkataramanan  * @vsi_handle: software VSI handle
3485f9867df6SAnirudh Venkataramanan  * @tc: TC number
3486bb87ee0eSAnirudh Venkataramanan  * @q_handle: software queue handle
3487cdedef59SAnirudh Venkataramanan  * @num_qgrps: Number of added queue groups
3488cdedef59SAnirudh Venkataramanan  * @buf: list of queue groups to be added
3489cdedef59SAnirudh Venkataramanan  * @buf_size: size of buffer for indirect command
3490cdedef59SAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
3491cdedef59SAnirudh Venkataramanan  *
3492f9867df6SAnirudh Venkataramanan  * This function adds one LAN queue
3493cdedef59SAnirudh Venkataramanan  */
3494cdedef59SAnirudh Venkataramanan enum ice_status
3495bb87ee0eSAnirudh Venkataramanan ice_ena_vsi_txq(struct ice_port_info *pi, u16 vsi_handle, u8 tc, u16 q_handle,
3496bb87ee0eSAnirudh Venkataramanan 		u8 num_qgrps, struct ice_aqc_add_tx_qgrp *buf, u16 buf_size,
3497cdedef59SAnirudh Venkataramanan 		struct ice_sq_cd *cd)
3498cdedef59SAnirudh Venkataramanan {
3499cdedef59SAnirudh Venkataramanan 	struct ice_aqc_txsched_elem_data node = { 0 };
3500cdedef59SAnirudh Venkataramanan 	struct ice_sched_node *parent;
3501bb87ee0eSAnirudh Venkataramanan 	struct ice_q_ctx *q_ctx;
3502cdedef59SAnirudh Venkataramanan 	enum ice_status status;
3503cdedef59SAnirudh Venkataramanan 	struct ice_hw *hw;
3504cdedef59SAnirudh Venkataramanan 
3505cdedef59SAnirudh Venkataramanan 	if (!pi || pi->port_state != ICE_SCHED_PORT_STATE_READY)
3506cdedef59SAnirudh Venkataramanan 		return ICE_ERR_CFG;
3507cdedef59SAnirudh Venkataramanan 
3508cdedef59SAnirudh Venkataramanan 	if (num_qgrps > 1 || buf->num_txqs > 1)
3509cdedef59SAnirudh Venkataramanan 		return ICE_ERR_MAX_LIMIT;
3510cdedef59SAnirudh Venkataramanan 
3511cdedef59SAnirudh Venkataramanan 	hw = pi->hw;
3512cdedef59SAnirudh Venkataramanan 
35134fb33f31SAnirudh Venkataramanan 	if (!ice_is_vsi_valid(hw, vsi_handle))
35144fb33f31SAnirudh Venkataramanan 		return ICE_ERR_PARAM;
35154fb33f31SAnirudh Venkataramanan 
3516cdedef59SAnirudh Venkataramanan 	mutex_lock(&pi->sched_lock);
3517cdedef59SAnirudh Venkataramanan 
3518bb87ee0eSAnirudh Venkataramanan 	q_ctx = ice_get_lan_q_ctx(hw, vsi_handle, tc, q_handle);
3519bb87ee0eSAnirudh Venkataramanan 	if (!q_ctx) {
3520bb87ee0eSAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_SCHED, "Enaq: invalid queue handle %d\n",
3521bb87ee0eSAnirudh Venkataramanan 			  q_handle);
3522bb87ee0eSAnirudh Venkataramanan 		status = ICE_ERR_PARAM;
3523bb87ee0eSAnirudh Venkataramanan 		goto ena_txq_exit;
3524bb87ee0eSAnirudh Venkataramanan 	}
3525bb87ee0eSAnirudh Venkataramanan 
3526cdedef59SAnirudh Venkataramanan 	/* find a parent node */
35274fb33f31SAnirudh Venkataramanan 	parent = ice_sched_get_free_qparent(pi, vsi_handle, tc,
3528cdedef59SAnirudh Venkataramanan 					    ICE_SCHED_NODE_OWNER_LAN);
3529cdedef59SAnirudh Venkataramanan 	if (!parent) {
3530cdedef59SAnirudh Venkataramanan 		status = ICE_ERR_PARAM;
3531cdedef59SAnirudh Venkataramanan 		goto ena_txq_exit;
3532cdedef59SAnirudh Venkataramanan 	}
35334fb33f31SAnirudh Venkataramanan 
3534cdedef59SAnirudh Venkataramanan 	buf->parent_teid = parent->info.node_teid;
3535cdedef59SAnirudh Venkataramanan 	node.parent_teid = parent->info.node_teid;
3536cdedef59SAnirudh Venkataramanan 	/* Mark that the values in the "generic" section as valid. The default
3537cdedef59SAnirudh Venkataramanan 	 * value in the "generic" section is zero. This means that :
3538cdedef59SAnirudh Venkataramanan 	 * - Scheduling mode is Bytes Per Second (BPS), indicated by Bit 0.
3539cdedef59SAnirudh Venkataramanan 	 * - 0 priority among siblings, indicated by Bit 1-3.
3540cdedef59SAnirudh Venkataramanan 	 * - WFQ, indicated by Bit 4.
3541cdedef59SAnirudh Venkataramanan 	 * - 0 Adjustment value is used in PSM credit update flow, indicated by
3542cdedef59SAnirudh Venkataramanan 	 * Bit 5-6.
3543cdedef59SAnirudh Venkataramanan 	 * - Bit 7 is reserved.
3544cdedef59SAnirudh Venkataramanan 	 * Without setting the generic section as valid in valid_sections, the
3545f9867df6SAnirudh Venkataramanan 	 * Admin queue command will fail with error code ICE_AQ_RC_EINVAL.
3546cdedef59SAnirudh Venkataramanan 	 */
3547cdedef59SAnirudh Venkataramanan 	buf->txqs[0].info.valid_sections = ICE_AQC_ELEM_VALID_GENERIC;
3548cdedef59SAnirudh Venkataramanan 
3549f9867df6SAnirudh Venkataramanan 	/* add the LAN queue */
3550cdedef59SAnirudh Venkataramanan 	status = ice_aq_add_lan_txq(hw, num_qgrps, buf, buf_size, cd);
35516e9650d5SVictor Raj 	if (status) {
3552bb87ee0eSAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_SCHED, "enable queue %d failed %d\n",
35536e9650d5SVictor Raj 			  le16_to_cpu(buf->txqs[0].txq_id),
35546e9650d5SVictor Raj 			  hw->adminq.sq_last_status);
3555cdedef59SAnirudh Venkataramanan 		goto ena_txq_exit;
35566e9650d5SVictor Raj 	}
3557cdedef59SAnirudh Venkataramanan 
3558cdedef59SAnirudh Venkataramanan 	node.node_teid = buf->txqs[0].q_teid;
3559cdedef59SAnirudh Venkataramanan 	node.data.elem_type = ICE_AQC_ELEM_TYPE_LEAF;
3560bb87ee0eSAnirudh Venkataramanan 	q_ctx->q_handle = q_handle;
35611ddef455SUsha Ketineni 	q_ctx->q_teid = le32_to_cpu(node.node_teid);
3562cdedef59SAnirudh Venkataramanan 
35631ddef455SUsha Ketineni 	/* add a leaf node into scheduler tree queue layer */
3564cdedef59SAnirudh Venkataramanan 	status = ice_sched_add_node(pi, hw->num_tx_sched_layers - 1, &node);
35651ddef455SUsha Ketineni 	if (!status)
35661ddef455SUsha Ketineni 		status = ice_sched_replay_q_bw(pi, q_ctx);
3567cdedef59SAnirudh Venkataramanan 
3568cdedef59SAnirudh Venkataramanan ena_txq_exit:
3569cdedef59SAnirudh Venkataramanan 	mutex_unlock(&pi->sched_lock);
3570cdedef59SAnirudh Venkataramanan 	return status;
3571cdedef59SAnirudh Venkataramanan }
3572cdedef59SAnirudh Venkataramanan 
3573cdedef59SAnirudh Venkataramanan /**
3574cdedef59SAnirudh Venkataramanan  * ice_dis_vsi_txq
3575cdedef59SAnirudh Venkataramanan  * @pi: port information structure
3576bb87ee0eSAnirudh Venkataramanan  * @vsi_handle: software VSI handle
3577bb87ee0eSAnirudh Venkataramanan  * @tc: TC number
3578cdedef59SAnirudh Venkataramanan  * @num_queues: number of queues
3579bb87ee0eSAnirudh Venkataramanan  * @q_handles: pointer to software queue handle array
3580cdedef59SAnirudh Venkataramanan  * @q_ids: pointer to the q_id array
3581cdedef59SAnirudh Venkataramanan  * @q_teids: pointer to queue node teids
358294c4441bSAnirudh Venkataramanan  * @rst_src: if called due to reset, specifies the reset source
3583ddf30f7fSAnirudh Venkataramanan  * @vmvf_num: the relative VM or VF number that is undergoing the reset
3584cdedef59SAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
3585cdedef59SAnirudh Venkataramanan  *
3586cdedef59SAnirudh Venkataramanan  * This function removes queues and their corresponding nodes in SW DB
3587cdedef59SAnirudh Venkataramanan  */
3588cdedef59SAnirudh Venkataramanan enum ice_status
3589bb87ee0eSAnirudh Venkataramanan ice_dis_vsi_txq(struct ice_port_info *pi, u16 vsi_handle, u8 tc, u8 num_queues,
3590bb87ee0eSAnirudh Venkataramanan 		u16 *q_handles, u16 *q_ids, u32 *q_teids,
3591bb87ee0eSAnirudh Venkataramanan 		enum ice_disq_rst_src rst_src, u16 vmvf_num,
3592ddf30f7fSAnirudh Venkataramanan 		struct ice_sq_cd *cd)
3593cdedef59SAnirudh Venkataramanan {
3594cdedef59SAnirudh Venkataramanan 	enum ice_status status = ICE_ERR_DOES_NOT_EXIST;
359566486d89SBruce Allan 	struct ice_aqc_dis_txq_item *qg_list;
3596bb87ee0eSAnirudh Venkataramanan 	struct ice_q_ctx *q_ctx;
359766486d89SBruce Allan 	struct ice_hw *hw;
359866486d89SBruce Allan 	u16 i, buf_size;
3599cdedef59SAnirudh Venkataramanan 
3600cdedef59SAnirudh Venkataramanan 	if (!pi || pi->port_state != ICE_SCHED_PORT_STATE_READY)
3601cdedef59SAnirudh Venkataramanan 		return ICE_ERR_CFG;
3602cdedef59SAnirudh Venkataramanan 
360366486d89SBruce Allan 	hw = pi->hw;
360466486d89SBruce Allan 
360585796d6eSAkeem G Abodunrin 	if (!num_queues) {
360685796d6eSAkeem G Abodunrin 		/* if queue is disabled already yet the disable queue command
360785796d6eSAkeem G Abodunrin 		 * has to be sent to complete the VF reset, then call
360885796d6eSAkeem G Abodunrin 		 * ice_aq_dis_lan_txq without any queue information
360985796d6eSAkeem G Abodunrin 		 */
361085796d6eSAkeem G Abodunrin 		if (rst_src)
361166486d89SBruce Allan 			return ice_aq_dis_lan_txq(hw, 0, NULL, 0, rst_src,
361285796d6eSAkeem G Abodunrin 						  vmvf_num, NULL);
361385796d6eSAkeem G Abodunrin 		return ICE_ERR_CFG;
361485796d6eSAkeem G Abodunrin 	}
3615ddf30f7fSAnirudh Venkataramanan 
361666486d89SBruce Allan 	buf_size = struct_size(qg_list, q_id, 1);
361766486d89SBruce Allan 	qg_list = kzalloc(buf_size, GFP_KERNEL);
361866486d89SBruce Allan 	if (!qg_list)
361966486d89SBruce Allan 		return ICE_ERR_NO_MEMORY;
362066486d89SBruce Allan 
3621cdedef59SAnirudh Venkataramanan 	mutex_lock(&pi->sched_lock);
3622cdedef59SAnirudh Venkataramanan 
3623cdedef59SAnirudh Venkataramanan 	for (i = 0; i < num_queues; i++) {
3624cdedef59SAnirudh Venkataramanan 		struct ice_sched_node *node;
3625cdedef59SAnirudh Venkataramanan 
3626cdedef59SAnirudh Venkataramanan 		node = ice_sched_find_node_by_teid(pi->root, q_teids[i]);
3627cdedef59SAnirudh Venkataramanan 		if (!node)
3628cdedef59SAnirudh Venkataramanan 			continue;
362966486d89SBruce Allan 		q_ctx = ice_get_lan_q_ctx(hw, vsi_handle, tc, q_handles[i]);
3630bb87ee0eSAnirudh Venkataramanan 		if (!q_ctx) {
363166486d89SBruce Allan 			ice_debug(hw, ICE_DBG_SCHED, "invalid queue handle%d\n",
3632bb87ee0eSAnirudh Venkataramanan 				  q_handles[i]);
3633bb87ee0eSAnirudh Venkataramanan 			continue;
3634bb87ee0eSAnirudh Venkataramanan 		}
3635bb87ee0eSAnirudh Venkataramanan 		if (q_ctx->q_handle != q_handles[i]) {
363666486d89SBruce Allan 			ice_debug(hw, ICE_DBG_SCHED, "Err:handles %d %d\n",
3637bb87ee0eSAnirudh Venkataramanan 				  q_ctx->q_handle, q_handles[i]);
3638bb87ee0eSAnirudh Venkataramanan 			continue;
3639bb87ee0eSAnirudh Venkataramanan 		}
364066486d89SBruce Allan 		qg_list->parent_teid = node->info.parent_teid;
364166486d89SBruce Allan 		qg_list->num_qs = 1;
364266486d89SBruce Allan 		qg_list->q_id[0] = cpu_to_le16(q_ids[i]);
364366486d89SBruce Allan 		status = ice_aq_dis_lan_txq(hw, 1, qg_list, buf_size, rst_src,
364466486d89SBruce Allan 					    vmvf_num, cd);
3645cdedef59SAnirudh Venkataramanan 
3646cdedef59SAnirudh Venkataramanan 		if (status)
3647cdedef59SAnirudh Venkataramanan 			break;
3648cdedef59SAnirudh Venkataramanan 		ice_free_sched_node(pi, node);
3649bb87ee0eSAnirudh Venkataramanan 		q_ctx->q_handle = ICE_INVAL_Q_HANDLE;
3650cdedef59SAnirudh Venkataramanan 	}
3651cdedef59SAnirudh Venkataramanan 	mutex_unlock(&pi->sched_lock);
365266486d89SBruce Allan 	kfree(qg_list);
3653cdedef59SAnirudh Venkataramanan 	return status;
3654cdedef59SAnirudh Venkataramanan }
36555513b920SAnirudh Venkataramanan 
36565513b920SAnirudh Venkataramanan /**
365794c4441bSAnirudh Venkataramanan  * ice_cfg_vsi_qs - configure the new/existing VSI queues
36585513b920SAnirudh Venkataramanan  * @pi: port information structure
36594fb33f31SAnirudh Venkataramanan  * @vsi_handle: software VSI handle
36605513b920SAnirudh Venkataramanan  * @tc_bitmap: TC bitmap
36615513b920SAnirudh Venkataramanan  * @maxqs: max queues array per TC
3662f9867df6SAnirudh Venkataramanan  * @owner: LAN or RDMA
36635513b920SAnirudh Venkataramanan  *
36645513b920SAnirudh Venkataramanan  * This function adds/updates the VSI queues per TC.
36655513b920SAnirudh Venkataramanan  */
36665513b920SAnirudh Venkataramanan static enum ice_status
36674fb33f31SAnirudh Venkataramanan ice_cfg_vsi_qs(struct ice_port_info *pi, u16 vsi_handle, u8 tc_bitmap,
36685513b920SAnirudh Venkataramanan 	       u16 *maxqs, u8 owner)
36695513b920SAnirudh Venkataramanan {
36705513b920SAnirudh Venkataramanan 	enum ice_status status = 0;
36715513b920SAnirudh Venkataramanan 	u8 i;
36725513b920SAnirudh Venkataramanan 
36735513b920SAnirudh Venkataramanan 	if (!pi || pi->port_state != ICE_SCHED_PORT_STATE_READY)
36745513b920SAnirudh Venkataramanan 		return ICE_ERR_CFG;
36755513b920SAnirudh Venkataramanan 
36764fb33f31SAnirudh Venkataramanan 	if (!ice_is_vsi_valid(pi->hw, vsi_handle))
36774fb33f31SAnirudh Venkataramanan 		return ICE_ERR_PARAM;
36784fb33f31SAnirudh Venkataramanan 
36795513b920SAnirudh Venkataramanan 	mutex_lock(&pi->sched_lock);
36805513b920SAnirudh Venkataramanan 
36812bdc97beSBruce Allan 	ice_for_each_traffic_class(i) {
36825513b920SAnirudh Venkataramanan 		/* configuration is possible only if TC node is present */
36835513b920SAnirudh Venkataramanan 		if (!ice_sched_get_tc_node(pi, i))
36845513b920SAnirudh Venkataramanan 			continue;
36855513b920SAnirudh Venkataramanan 
36864fb33f31SAnirudh Venkataramanan 		status = ice_sched_cfg_vsi(pi, vsi_handle, i, maxqs[i], owner,
36875513b920SAnirudh Venkataramanan 					   ice_is_tc_ena(tc_bitmap, i));
36885513b920SAnirudh Venkataramanan 		if (status)
36895513b920SAnirudh Venkataramanan 			break;
36905513b920SAnirudh Venkataramanan 	}
36915513b920SAnirudh Venkataramanan 
36925513b920SAnirudh Venkataramanan 	mutex_unlock(&pi->sched_lock);
36935513b920SAnirudh Venkataramanan 	return status;
36945513b920SAnirudh Venkataramanan }
36955513b920SAnirudh Venkataramanan 
36965513b920SAnirudh Venkataramanan /**
3697f9867df6SAnirudh Venkataramanan  * ice_cfg_vsi_lan - configure VSI LAN queues
36985513b920SAnirudh Venkataramanan  * @pi: port information structure
36994fb33f31SAnirudh Venkataramanan  * @vsi_handle: software VSI handle
37005513b920SAnirudh Venkataramanan  * @tc_bitmap: TC bitmap
3701f9867df6SAnirudh Venkataramanan  * @max_lanqs: max LAN queues array per TC
37025513b920SAnirudh Venkataramanan  *
3703f9867df6SAnirudh Venkataramanan  * This function adds/updates the VSI LAN queues per TC.
37045513b920SAnirudh Venkataramanan  */
37055513b920SAnirudh Venkataramanan enum ice_status
37064fb33f31SAnirudh Venkataramanan ice_cfg_vsi_lan(struct ice_port_info *pi, u16 vsi_handle, u8 tc_bitmap,
37075513b920SAnirudh Venkataramanan 		u16 *max_lanqs)
37085513b920SAnirudh Venkataramanan {
37094fb33f31SAnirudh Venkataramanan 	return ice_cfg_vsi_qs(pi, vsi_handle, tc_bitmap, max_lanqs,
37105513b920SAnirudh Venkataramanan 			      ICE_SCHED_NODE_OWNER_LAN);
37115513b920SAnirudh Venkataramanan }
371245d3d428SAnirudh Venkataramanan 
371345d3d428SAnirudh Venkataramanan /**
3714334cb062SAnirudh Venkataramanan  * ice_replay_pre_init - replay pre initialization
3715f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
3716334cb062SAnirudh Venkataramanan  *
3717334cb062SAnirudh Venkataramanan  * Initializes required config data for VSI, FD, ACL, and RSS before replay.
3718334cb062SAnirudh Venkataramanan  */
3719334cb062SAnirudh Venkataramanan static enum ice_status ice_replay_pre_init(struct ice_hw *hw)
3720334cb062SAnirudh Venkataramanan {
3721334cb062SAnirudh Venkataramanan 	struct ice_switch_info *sw = hw->switch_info;
3722334cb062SAnirudh Venkataramanan 	u8 i;
3723334cb062SAnirudh Venkataramanan 
3724334cb062SAnirudh Venkataramanan 	/* Delete old entries from replay filter list head if there is any */
3725334cb062SAnirudh Venkataramanan 	ice_rm_all_sw_replay_rule_info(hw);
3726334cb062SAnirudh Venkataramanan 	/* In start of replay, move entries into replay_rules list, it
3727334cb062SAnirudh Venkataramanan 	 * will allow adding rules entries back to filt_rules list,
3728334cb062SAnirudh Venkataramanan 	 * which is operational list.
3729334cb062SAnirudh Venkataramanan 	 */
3730334cb062SAnirudh Venkataramanan 	for (i = 0; i < ICE_SW_LKUP_LAST; i++)
3731334cb062SAnirudh Venkataramanan 		list_replace_init(&sw->recp_list[i].filt_rules,
3732334cb062SAnirudh Venkataramanan 				  &sw->recp_list[i].filt_replay_rules);
3733334cb062SAnirudh Venkataramanan 
3734334cb062SAnirudh Venkataramanan 	return 0;
3735334cb062SAnirudh Venkataramanan }
3736334cb062SAnirudh Venkataramanan 
3737334cb062SAnirudh Venkataramanan /**
3738334cb062SAnirudh Venkataramanan  * ice_replay_vsi - replay VSI configuration
3739f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
3740334cb062SAnirudh Venkataramanan  * @vsi_handle: driver VSI handle
3741334cb062SAnirudh Venkataramanan  *
3742334cb062SAnirudh Venkataramanan  * Restore all VSI configuration after reset. It is required to call this
3743334cb062SAnirudh Venkataramanan  * function with main VSI first.
3744334cb062SAnirudh Venkataramanan  */
3745334cb062SAnirudh Venkataramanan enum ice_status ice_replay_vsi(struct ice_hw *hw, u16 vsi_handle)
3746334cb062SAnirudh Venkataramanan {
3747334cb062SAnirudh Venkataramanan 	enum ice_status status;
3748334cb062SAnirudh Venkataramanan 
3749334cb062SAnirudh Venkataramanan 	if (!ice_is_vsi_valid(hw, vsi_handle))
3750334cb062SAnirudh Venkataramanan 		return ICE_ERR_PARAM;
3751334cb062SAnirudh Venkataramanan 
3752334cb062SAnirudh Venkataramanan 	/* Replay pre-initialization if there is any */
3753334cb062SAnirudh Venkataramanan 	if (vsi_handle == ICE_MAIN_VSI_HANDLE) {
3754334cb062SAnirudh Venkataramanan 		status = ice_replay_pre_init(hw);
3755334cb062SAnirudh Venkataramanan 		if (status)
3756334cb062SAnirudh Venkataramanan 			return status;
3757334cb062SAnirudh Venkataramanan 	}
3758c90ed40cSTony Nguyen 	/* Replay per VSI all RSS configurations */
3759c90ed40cSTony Nguyen 	status = ice_replay_rss_cfg(hw, vsi_handle);
3760c90ed40cSTony Nguyen 	if (status)
3761c90ed40cSTony Nguyen 		return status;
3762334cb062SAnirudh Venkataramanan 	/* Replay per VSI all filters */
3763334cb062SAnirudh Venkataramanan 	status = ice_replay_vsi_all_fltr(hw, vsi_handle);
3764334cb062SAnirudh Venkataramanan 	return status;
3765334cb062SAnirudh Venkataramanan }
3766334cb062SAnirudh Venkataramanan 
3767334cb062SAnirudh Venkataramanan /**
3768334cb062SAnirudh Venkataramanan  * ice_replay_post - post replay configuration cleanup
3769f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
3770334cb062SAnirudh Venkataramanan  *
3771334cb062SAnirudh Venkataramanan  * Post replay cleanup.
3772334cb062SAnirudh Venkataramanan  */
3773334cb062SAnirudh Venkataramanan void ice_replay_post(struct ice_hw *hw)
3774334cb062SAnirudh Venkataramanan {
3775334cb062SAnirudh Venkataramanan 	/* Delete old entries from replay filter list head */
3776334cb062SAnirudh Venkataramanan 	ice_rm_all_sw_replay_rule_info(hw);
3777334cb062SAnirudh Venkataramanan }
3778334cb062SAnirudh Venkataramanan 
3779334cb062SAnirudh Venkataramanan /**
378045d3d428SAnirudh Venkataramanan  * ice_stat_update40 - read 40 bit stat from the chip and update stat values
378145d3d428SAnirudh Venkataramanan  * @hw: ptr to the hardware info
378236517fd3SJacob Keller  * @reg: offset of 64 bit HW register to read from
378345d3d428SAnirudh Venkataramanan  * @prev_stat_loaded: bool to specify if previous stats are loaded
378445d3d428SAnirudh Venkataramanan  * @prev_stat: ptr to previous loaded stat value
378545d3d428SAnirudh Venkataramanan  * @cur_stat: ptr to current stat value
378645d3d428SAnirudh Venkataramanan  */
3787c8b7abddSBruce Allan void
378836517fd3SJacob Keller ice_stat_update40(struct ice_hw *hw, u32 reg, bool prev_stat_loaded,
378936517fd3SJacob Keller 		  u64 *prev_stat, u64 *cur_stat)
379045d3d428SAnirudh Venkataramanan {
379136517fd3SJacob Keller 	u64 new_data = rd64(hw, reg) & (BIT_ULL(40) - 1);
379245d3d428SAnirudh Venkataramanan 
379345d3d428SAnirudh Venkataramanan 	/* device stats are not reset at PFR, they likely will not be zeroed
379436517fd3SJacob Keller 	 * when the driver starts. Thus, save the value from the first read
379536517fd3SJacob Keller 	 * without adding to the statistic value so that we report stats which
379636517fd3SJacob Keller 	 * count up from zero.
379745d3d428SAnirudh Venkataramanan 	 */
379836517fd3SJacob Keller 	if (!prev_stat_loaded) {
379945d3d428SAnirudh Venkataramanan 		*prev_stat = new_data;
380036517fd3SJacob Keller 		return;
380136517fd3SJacob Keller 	}
380236517fd3SJacob Keller 
380336517fd3SJacob Keller 	/* Calculate the difference between the new and old values, and then
380436517fd3SJacob Keller 	 * add it to the software stat value.
380536517fd3SJacob Keller 	 */
380645d3d428SAnirudh Venkataramanan 	if (new_data >= *prev_stat)
380736517fd3SJacob Keller 		*cur_stat += new_data - *prev_stat;
380845d3d428SAnirudh Venkataramanan 	else
380945d3d428SAnirudh Venkataramanan 		/* to manage the potential roll-over */
381036517fd3SJacob Keller 		*cur_stat += (new_data + BIT_ULL(40)) - *prev_stat;
381136517fd3SJacob Keller 
381236517fd3SJacob Keller 	/* Update the previously stored value to prepare for next read */
381336517fd3SJacob Keller 	*prev_stat = new_data;
381445d3d428SAnirudh Venkataramanan }
381545d3d428SAnirudh Venkataramanan 
381645d3d428SAnirudh Venkataramanan /**
381745d3d428SAnirudh Venkataramanan  * ice_stat_update32 - read 32 bit stat from the chip and update stat values
381845d3d428SAnirudh Venkataramanan  * @hw: ptr to the hardware info
381936517fd3SJacob Keller  * @reg: offset of HW register to read from
382045d3d428SAnirudh Venkataramanan  * @prev_stat_loaded: bool to specify if previous stats are loaded
382145d3d428SAnirudh Venkataramanan  * @prev_stat: ptr to previous loaded stat value
382245d3d428SAnirudh Venkataramanan  * @cur_stat: ptr to current stat value
382345d3d428SAnirudh Venkataramanan  */
3824c8b7abddSBruce Allan void
3825c8b7abddSBruce Allan ice_stat_update32(struct ice_hw *hw, u32 reg, bool prev_stat_loaded,
382645d3d428SAnirudh Venkataramanan 		  u64 *prev_stat, u64 *cur_stat)
382745d3d428SAnirudh Venkataramanan {
382845d3d428SAnirudh Venkataramanan 	u32 new_data;
382945d3d428SAnirudh Venkataramanan 
383045d3d428SAnirudh Venkataramanan 	new_data = rd32(hw, reg);
383145d3d428SAnirudh Venkataramanan 
383245d3d428SAnirudh Venkataramanan 	/* device stats are not reset at PFR, they likely will not be zeroed
383336517fd3SJacob Keller 	 * when the driver starts. Thus, save the value from the first read
383436517fd3SJacob Keller 	 * without adding to the statistic value so that we report stats which
383536517fd3SJacob Keller 	 * count up from zero.
383645d3d428SAnirudh Venkataramanan 	 */
383736517fd3SJacob Keller 	if (!prev_stat_loaded) {
383845d3d428SAnirudh Venkataramanan 		*prev_stat = new_data;
383936517fd3SJacob Keller 		return;
384036517fd3SJacob Keller 	}
384136517fd3SJacob Keller 
384236517fd3SJacob Keller 	/* Calculate the difference between the new and old values, and then
384336517fd3SJacob Keller 	 * add it to the software stat value.
384436517fd3SJacob Keller 	 */
384545d3d428SAnirudh Venkataramanan 	if (new_data >= *prev_stat)
384636517fd3SJacob Keller 		*cur_stat += new_data - *prev_stat;
384745d3d428SAnirudh Venkataramanan 	else
384845d3d428SAnirudh Venkataramanan 		/* to manage the potential roll-over */
384936517fd3SJacob Keller 		*cur_stat += (new_data + BIT_ULL(32)) - *prev_stat;
385036517fd3SJacob Keller 
385136517fd3SJacob Keller 	/* Update the previously stored value to prepare for next read */
385236517fd3SJacob Keller 	*prev_stat = new_data;
385345d3d428SAnirudh Venkataramanan }
38547b9ffc76SAnirudh Venkataramanan 
38557b9ffc76SAnirudh Venkataramanan /**
38567b9ffc76SAnirudh Venkataramanan  * ice_sched_query_elem - query element information from HW
38577b9ffc76SAnirudh Venkataramanan  * @hw: pointer to the HW struct
38587b9ffc76SAnirudh Venkataramanan  * @node_teid: node TEID to be queried
38597b9ffc76SAnirudh Venkataramanan  * @buf: buffer to element information
38607b9ffc76SAnirudh Venkataramanan  *
38617b9ffc76SAnirudh Venkataramanan  * This function queries HW element information
38627b9ffc76SAnirudh Venkataramanan  */
38637b9ffc76SAnirudh Venkataramanan enum ice_status
38647b9ffc76SAnirudh Venkataramanan ice_sched_query_elem(struct ice_hw *hw, u32 node_teid,
3865b3c38904SBruce Allan 		     struct ice_aqc_txsched_elem_data *buf)
38667b9ffc76SAnirudh Venkataramanan {
38677b9ffc76SAnirudh Venkataramanan 	u16 buf_size, num_elem_ret = 0;
38687b9ffc76SAnirudh Venkataramanan 	enum ice_status status;
38697b9ffc76SAnirudh Venkataramanan 
38707b9ffc76SAnirudh Venkataramanan 	buf_size = sizeof(*buf);
38717b9ffc76SAnirudh Venkataramanan 	memset(buf, 0, buf_size);
3872b3c38904SBruce Allan 	buf->node_teid = cpu_to_le32(node_teid);
38737b9ffc76SAnirudh Venkataramanan 	status = ice_aq_query_sched_elems(hw, 1, buf, buf_size, &num_elem_ret,
38747b9ffc76SAnirudh Venkataramanan 					  NULL);
38757b9ffc76SAnirudh Venkataramanan 	if (status || num_elem_ret != 1)
38767b9ffc76SAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_SCHED, "query element failed\n");
38777b9ffc76SAnirudh Venkataramanan 	return status;
38787b9ffc76SAnirudh Venkataramanan }
3879