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"
77ec59eeaSAnirudh Venkataramanan 
8f31e4b6fSAnirudh Venkataramanan #define ICE_PF_RESET_WAIT_COUNT	200
9f31e4b6fSAnirudh Venkataramanan 
10f31e4b6fSAnirudh Venkataramanan /**
11f31e4b6fSAnirudh Venkataramanan  * ice_set_mac_type - Sets MAC type
12f31e4b6fSAnirudh Venkataramanan  * @hw: pointer to the HW structure
13f31e4b6fSAnirudh Venkataramanan  *
14f31e4b6fSAnirudh Venkataramanan  * This function sets the MAC type of the adapter based on the
15f31e4b6fSAnirudh Venkataramanan  * vendor ID and device ID stored in the hw structure.
16f31e4b6fSAnirudh Venkataramanan  */
17f31e4b6fSAnirudh Venkataramanan static enum ice_status ice_set_mac_type(struct ice_hw *hw)
18f31e4b6fSAnirudh Venkataramanan {
19f31e4b6fSAnirudh Venkataramanan 	if (hw->vendor_id != PCI_VENDOR_ID_INTEL)
20f31e4b6fSAnirudh Venkataramanan 		return ICE_ERR_DEVICE_NOT_SUPPORTED;
21f31e4b6fSAnirudh Venkataramanan 
22f31e4b6fSAnirudh Venkataramanan 	hw->mac_type = ICE_MAC_GENERIC;
23f31e4b6fSAnirudh Venkataramanan 	return 0;
24f31e4b6fSAnirudh Venkataramanan }
25f31e4b6fSAnirudh Venkataramanan 
26f31e4b6fSAnirudh Venkataramanan /**
27f31e4b6fSAnirudh Venkataramanan  * ice_clear_pf_cfg - Clear PF configuration
28f31e4b6fSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
29f31e4b6fSAnirudh Venkataramanan  */
30f31e4b6fSAnirudh Venkataramanan enum ice_status ice_clear_pf_cfg(struct ice_hw *hw)
31f31e4b6fSAnirudh Venkataramanan {
32f31e4b6fSAnirudh Venkataramanan 	struct ice_aq_desc desc;
33f31e4b6fSAnirudh Venkataramanan 
34f31e4b6fSAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_clear_pf_cfg);
35f31e4b6fSAnirudh Venkataramanan 
36f31e4b6fSAnirudh Venkataramanan 	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
37f31e4b6fSAnirudh Venkataramanan }
38f31e4b6fSAnirudh Venkataramanan 
39f31e4b6fSAnirudh Venkataramanan /**
40dc49c772SAnirudh Venkataramanan  * ice_aq_manage_mac_read - manage MAC address read command
41dc49c772SAnirudh Venkataramanan  * @hw: pointer to the hw struct
42dc49c772SAnirudh Venkataramanan  * @buf: a virtual buffer to hold the manage MAC read response
43dc49c772SAnirudh Venkataramanan  * @buf_size: Size of the virtual buffer
44dc49c772SAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
45dc49c772SAnirudh Venkataramanan  *
46dc49c772SAnirudh Venkataramanan  * This function is used to return per PF station MAC address (0x0107).
47dc49c772SAnirudh Venkataramanan  * NOTE: Upon successful completion of this command, MAC address information
48dc49c772SAnirudh Venkataramanan  * is returned in user specified buffer. Please interpret user specified
49dc49c772SAnirudh Venkataramanan  * buffer as "manage_mac_read" response.
50dc49c772SAnirudh Venkataramanan  * Response such as various MAC addresses are stored in HW struct (port.mac)
51dc49c772SAnirudh Venkataramanan  * ice_aq_discover_caps is expected to be called before this function is called.
52dc49c772SAnirudh Venkataramanan  */
53dc49c772SAnirudh Venkataramanan static enum ice_status
54dc49c772SAnirudh Venkataramanan ice_aq_manage_mac_read(struct ice_hw *hw, void *buf, u16 buf_size,
55dc49c772SAnirudh Venkataramanan 		       struct ice_sq_cd *cd)
56dc49c772SAnirudh Venkataramanan {
57dc49c772SAnirudh Venkataramanan 	struct ice_aqc_manage_mac_read_resp *resp;
58dc49c772SAnirudh Venkataramanan 	struct ice_aqc_manage_mac_read *cmd;
59dc49c772SAnirudh Venkataramanan 	struct ice_aq_desc desc;
60dc49c772SAnirudh Venkataramanan 	enum ice_status status;
61dc49c772SAnirudh Venkataramanan 	u16 flags;
62dc49c772SAnirudh Venkataramanan 
63dc49c772SAnirudh Venkataramanan 	cmd = &desc.params.mac_read;
64dc49c772SAnirudh Venkataramanan 
65dc49c772SAnirudh Venkataramanan 	if (buf_size < sizeof(*resp))
66dc49c772SAnirudh Venkataramanan 		return ICE_ERR_BUF_TOO_SHORT;
67dc49c772SAnirudh Venkataramanan 
68dc49c772SAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_manage_mac_read);
69dc49c772SAnirudh Venkataramanan 
70dc49c772SAnirudh Venkataramanan 	status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
71dc49c772SAnirudh Venkataramanan 	if (status)
72dc49c772SAnirudh Venkataramanan 		return status;
73dc49c772SAnirudh Venkataramanan 
74dc49c772SAnirudh Venkataramanan 	resp = (struct ice_aqc_manage_mac_read_resp *)buf;
75dc49c772SAnirudh Venkataramanan 	flags = le16_to_cpu(cmd->flags) & ICE_AQC_MAN_MAC_READ_M;
76dc49c772SAnirudh Venkataramanan 
77dc49c772SAnirudh Venkataramanan 	if (!(flags & ICE_AQC_MAN_MAC_LAN_ADDR_VALID)) {
78dc49c772SAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_LAN, "got invalid MAC address\n");
79dc49c772SAnirudh Venkataramanan 		return ICE_ERR_CFG;
80dc49c772SAnirudh Venkataramanan 	}
81dc49c772SAnirudh Venkataramanan 
82dc49c772SAnirudh Venkataramanan 	ether_addr_copy(hw->port_info->mac.lan_addr, resp->mac_addr);
83dc49c772SAnirudh Venkataramanan 	ether_addr_copy(hw->port_info->mac.perm_addr, resp->mac_addr);
84dc49c772SAnirudh Venkataramanan 	return 0;
85dc49c772SAnirudh Venkataramanan }
86dc49c772SAnirudh Venkataramanan 
87dc49c772SAnirudh Venkataramanan /**
88dc49c772SAnirudh Venkataramanan  * ice_aq_get_phy_caps - returns PHY capabilities
89dc49c772SAnirudh Venkataramanan  * @pi: port information structure
90dc49c772SAnirudh Venkataramanan  * @qual_mods: report qualified modules
91dc49c772SAnirudh Venkataramanan  * @report_mode: report mode capabilities
92dc49c772SAnirudh Venkataramanan  * @pcaps: structure for PHY capabilities to be filled
93dc49c772SAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
94dc49c772SAnirudh Venkataramanan  *
95dc49c772SAnirudh Venkataramanan  * Returns the various PHY capabilities supported on the Port (0x0600)
96dc49c772SAnirudh Venkataramanan  */
97dc49c772SAnirudh Venkataramanan static enum ice_status
98dc49c772SAnirudh Venkataramanan ice_aq_get_phy_caps(struct ice_port_info *pi, bool qual_mods, u8 report_mode,
99dc49c772SAnirudh Venkataramanan 		    struct ice_aqc_get_phy_caps_data *pcaps,
100dc49c772SAnirudh Venkataramanan 		    struct ice_sq_cd *cd)
101dc49c772SAnirudh Venkataramanan {
102dc49c772SAnirudh Venkataramanan 	struct ice_aqc_get_phy_caps *cmd;
103dc49c772SAnirudh Venkataramanan 	u16 pcaps_size = sizeof(*pcaps);
104dc49c772SAnirudh Venkataramanan 	struct ice_aq_desc desc;
105dc49c772SAnirudh Venkataramanan 	enum ice_status status;
106dc49c772SAnirudh Venkataramanan 
107dc49c772SAnirudh Venkataramanan 	cmd = &desc.params.get_phy;
108dc49c772SAnirudh Venkataramanan 
109dc49c772SAnirudh Venkataramanan 	if (!pcaps || (report_mode & ~ICE_AQC_REPORT_MODE_M) || !pi)
110dc49c772SAnirudh Venkataramanan 		return ICE_ERR_PARAM;
111dc49c772SAnirudh Venkataramanan 
112dc49c772SAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_phy_caps);
113dc49c772SAnirudh Venkataramanan 
114dc49c772SAnirudh Venkataramanan 	if (qual_mods)
115dc49c772SAnirudh Venkataramanan 		cmd->param0 |= cpu_to_le16(ICE_AQC_GET_PHY_RQM);
116dc49c772SAnirudh Venkataramanan 
117dc49c772SAnirudh Venkataramanan 	cmd->param0 |= cpu_to_le16(report_mode);
118dc49c772SAnirudh Venkataramanan 	status = ice_aq_send_cmd(pi->hw, &desc, pcaps, pcaps_size, cd);
119dc49c772SAnirudh Venkataramanan 
120dc49c772SAnirudh Venkataramanan 	if (!status && report_mode == ICE_AQC_REPORT_TOPO_CAP)
121dc49c772SAnirudh Venkataramanan 		pi->phy.phy_type_low = le64_to_cpu(pcaps->phy_type_low);
122dc49c772SAnirudh Venkataramanan 
123dc49c772SAnirudh Venkataramanan 	return status;
124dc49c772SAnirudh Venkataramanan }
125dc49c772SAnirudh Venkataramanan 
126dc49c772SAnirudh Venkataramanan /**
127dc49c772SAnirudh Venkataramanan  * ice_get_media_type - Gets media type
128dc49c772SAnirudh Venkataramanan  * @pi: port information structure
129dc49c772SAnirudh Venkataramanan  */
130dc49c772SAnirudh Venkataramanan static enum ice_media_type ice_get_media_type(struct ice_port_info *pi)
131dc49c772SAnirudh Venkataramanan {
132dc49c772SAnirudh Venkataramanan 	struct ice_link_status *hw_link_info;
133dc49c772SAnirudh Venkataramanan 
134dc49c772SAnirudh Venkataramanan 	if (!pi)
135dc49c772SAnirudh Venkataramanan 		return ICE_MEDIA_UNKNOWN;
136dc49c772SAnirudh Venkataramanan 
137dc49c772SAnirudh Venkataramanan 	hw_link_info = &pi->phy.link_info;
138dc49c772SAnirudh Venkataramanan 
139dc49c772SAnirudh Venkataramanan 	if (hw_link_info->phy_type_low) {
140dc49c772SAnirudh Venkataramanan 		switch (hw_link_info->phy_type_low) {
141dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_1000BASE_SX:
142dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_1000BASE_LX:
143dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_10GBASE_SR:
144dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_10GBASE_LR:
145dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_10G_SFI_C2C:
146dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_25GBASE_SR:
147dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_25GBASE_LR:
148dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_25G_AUI_C2C:
149dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_40GBASE_SR4:
150dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_40GBASE_LR4:
151dc49c772SAnirudh Venkataramanan 			return ICE_MEDIA_FIBER;
152dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_100BASE_TX:
153dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_1000BASE_T:
154dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_2500BASE_T:
155dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_5GBASE_T:
156dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_10GBASE_T:
157dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_25GBASE_T:
158dc49c772SAnirudh Venkataramanan 			return ICE_MEDIA_BASET;
159dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_10G_SFI_DA:
160dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_25GBASE_CR:
161dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_25GBASE_CR_S:
162dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_25GBASE_CR1:
163dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_40GBASE_CR4:
164dc49c772SAnirudh Venkataramanan 			return ICE_MEDIA_DA;
165dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_1000BASE_KX:
166dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_2500BASE_KX:
167dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_2500BASE_X:
168dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_5GBASE_KR:
169dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_10GBASE_KR_CR1:
170dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_25GBASE_KR:
171dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_25GBASE_KR1:
172dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_25GBASE_KR_S:
173dc49c772SAnirudh Venkataramanan 		case ICE_PHY_TYPE_LOW_40GBASE_KR4:
174dc49c772SAnirudh Venkataramanan 			return ICE_MEDIA_BACKPLANE;
175dc49c772SAnirudh Venkataramanan 		}
176dc49c772SAnirudh Venkataramanan 	}
177dc49c772SAnirudh Venkataramanan 
178dc49c772SAnirudh Venkataramanan 	return ICE_MEDIA_UNKNOWN;
179dc49c772SAnirudh Venkataramanan }
180dc49c772SAnirudh Venkataramanan 
181dc49c772SAnirudh Venkataramanan /**
182dc49c772SAnirudh Venkataramanan  * ice_aq_get_link_info
183dc49c772SAnirudh Venkataramanan  * @pi: port information structure
184dc49c772SAnirudh Venkataramanan  * @ena_lse: enable/disable LinkStatusEvent reporting
185dc49c772SAnirudh Venkataramanan  * @link: pointer to link status structure - optional
186dc49c772SAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
187dc49c772SAnirudh Venkataramanan  *
188dc49c772SAnirudh Venkataramanan  * Get Link Status (0x607). Returns the link status of the adapter.
189dc49c772SAnirudh Venkataramanan  */
190dc49c772SAnirudh Venkataramanan enum ice_status
191dc49c772SAnirudh Venkataramanan ice_aq_get_link_info(struct ice_port_info *pi, bool ena_lse,
192dc49c772SAnirudh Venkataramanan 		     struct ice_link_status *link, struct ice_sq_cd *cd)
193dc49c772SAnirudh Venkataramanan {
194dc49c772SAnirudh Venkataramanan 	struct ice_link_status *hw_link_info_old, *hw_link_info;
195dc49c772SAnirudh Venkataramanan 	struct ice_aqc_get_link_status_data link_data = { 0 };
196dc49c772SAnirudh Venkataramanan 	struct ice_aqc_get_link_status *resp;
197dc49c772SAnirudh Venkataramanan 	enum ice_media_type *hw_media_type;
198dc49c772SAnirudh Venkataramanan 	struct ice_fc_info *hw_fc_info;
199dc49c772SAnirudh Venkataramanan 	bool tx_pause, rx_pause;
200dc49c772SAnirudh Venkataramanan 	struct ice_aq_desc desc;
201dc49c772SAnirudh Venkataramanan 	enum ice_status status;
202dc49c772SAnirudh Venkataramanan 	u16 cmd_flags;
203dc49c772SAnirudh Venkataramanan 
204dc49c772SAnirudh Venkataramanan 	if (!pi)
205dc49c772SAnirudh Venkataramanan 		return ICE_ERR_PARAM;
206dc49c772SAnirudh Venkataramanan 	hw_link_info_old = &pi->phy.link_info_old;
207dc49c772SAnirudh Venkataramanan 	hw_media_type = &pi->phy.media_type;
208dc49c772SAnirudh Venkataramanan 	hw_link_info = &pi->phy.link_info;
209dc49c772SAnirudh Venkataramanan 	hw_fc_info = &pi->fc;
210dc49c772SAnirudh Venkataramanan 
211dc49c772SAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_link_status);
212dc49c772SAnirudh Venkataramanan 	cmd_flags = (ena_lse) ? ICE_AQ_LSE_ENA : ICE_AQ_LSE_DIS;
213dc49c772SAnirudh Venkataramanan 	resp = &desc.params.get_link_status;
214dc49c772SAnirudh Venkataramanan 	resp->cmd_flags = cpu_to_le16(cmd_flags);
215dc49c772SAnirudh Venkataramanan 	resp->lport_num = pi->lport;
216dc49c772SAnirudh Venkataramanan 
217dc49c772SAnirudh Venkataramanan 	status = ice_aq_send_cmd(pi->hw, &desc, &link_data, sizeof(link_data),
218dc49c772SAnirudh Venkataramanan 				 cd);
219dc49c772SAnirudh Venkataramanan 
220dc49c772SAnirudh Venkataramanan 	if (status)
221dc49c772SAnirudh Venkataramanan 		return status;
222dc49c772SAnirudh Venkataramanan 
223dc49c772SAnirudh Venkataramanan 	/* save off old link status information */
224dc49c772SAnirudh Venkataramanan 	*hw_link_info_old = *hw_link_info;
225dc49c772SAnirudh Venkataramanan 
226dc49c772SAnirudh Venkataramanan 	/* update current link status information */
227dc49c772SAnirudh Venkataramanan 	hw_link_info->link_speed = le16_to_cpu(link_data.link_speed);
228dc49c772SAnirudh Venkataramanan 	hw_link_info->phy_type_low = le64_to_cpu(link_data.phy_type_low);
229dc49c772SAnirudh Venkataramanan 	*hw_media_type = ice_get_media_type(pi);
230dc49c772SAnirudh Venkataramanan 	hw_link_info->link_info = link_data.link_info;
231dc49c772SAnirudh Venkataramanan 	hw_link_info->an_info = link_data.an_info;
232dc49c772SAnirudh Venkataramanan 	hw_link_info->ext_info = link_data.ext_info;
233dc49c772SAnirudh Venkataramanan 	hw_link_info->max_frame_size = le16_to_cpu(link_data.max_frame_size);
234dc49c772SAnirudh Venkataramanan 	hw_link_info->pacing = link_data.cfg & ICE_AQ_CFG_PACING_M;
235dc49c772SAnirudh Venkataramanan 
236dc49c772SAnirudh Venkataramanan 	/* update fc info */
237dc49c772SAnirudh Venkataramanan 	tx_pause = !!(link_data.an_info & ICE_AQ_LINK_PAUSE_TX);
238dc49c772SAnirudh Venkataramanan 	rx_pause = !!(link_data.an_info & ICE_AQ_LINK_PAUSE_RX);
239dc49c772SAnirudh Venkataramanan 	if (tx_pause && rx_pause)
240dc49c772SAnirudh Venkataramanan 		hw_fc_info->current_mode = ICE_FC_FULL;
241dc49c772SAnirudh Venkataramanan 	else if (tx_pause)
242dc49c772SAnirudh Venkataramanan 		hw_fc_info->current_mode = ICE_FC_TX_PAUSE;
243dc49c772SAnirudh Venkataramanan 	else if (rx_pause)
244dc49c772SAnirudh Venkataramanan 		hw_fc_info->current_mode = ICE_FC_RX_PAUSE;
245dc49c772SAnirudh Venkataramanan 	else
246dc49c772SAnirudh Venkataramanan 		hw_fc_info->current_mode = ICE_FC_NONE;
247dc49c772SAnirudh Venkataramanan 
248dc49c772SAnirudh Venkataramanan 	hw_link_info->lse_ena =
249dc49c772SAnirudh Venkataramanan 		!!(resp->cmd_flags & cpu_to_le16(ICE_AQ_LSE_IS_ENABLED));
250dc49c772SAnirudh Venkataramanan 
251dc49c772SAnirudh Venkataramanan 	/* save link status information */
252dc49c772SAnirudh Venkataramanan 	if (link)
253dc49c772SAnirudh Venkataramanan 		*link = *hw_link_info;
254dc49c772SAnirudh Venkataramanan 
255dc49c772SAnirudh Venkataramanan 	/* flag cleared so calling functions don't call AQ again */
256dc49c772SAnirudh Venkataramanan 	pi->phy.get_link_info = false;
257dc49c772SAnirudh Venkataramanan 
258dc49c772SAnirudh Venkataramanan 	return status;
259dc49c772SAnirudh Venkataramanan }
260dc49c772SAnirudh Venkataramanan 
261dc49c772SAnirudh Venkataramanan /**
262f31e4b6fSAnirudh Venkataramanan  * ice_init_hw - main hardware initialization routine
263f31e4b6fSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
264f31e4b6fSAnirudh Venkataramanan  */
265f31e4b6fSAnirudh Venkataramanan enum ice_status ice_init_hw(struct ice_hw *hw)
266f31e4b6fSAnirudh Venkataramanan {
267dc49c772SAnirudh Venkataramanan 	struct ice_aqc_get_phy_caps_data *pcaps;
268f31e4b6fSAnirudh Venkataramanan 	enum ice_status status;
269dc49c772SAnirudh Venkataramanan 	u16 mac_buf_len;
270dc49c772SAnirudh Venkataramanan 	void *mac_buf;
271f31e4b6fSAnirudh Venkataramanan 
272f31e4b6fSAnirudh Venkataramanan 	/* Set MAC type based on DeviceID */
273f31e4b6fSAnirudh Venkataramanan 	status = ice_set_mac_type(hw);
274f31e4b6fSAnirudh Venkataramanan 	if (status)
275f31e4b6fSAnirudh Venkataramanan 		return status;
276f31e4b6fSAnirudh Venkataramanan 
277f31e4b6fSAnirudh Venkataramanan 	hw->pf_id = (u8)(rd32(hw, PF_FUNC_RID) &
278f31e4b6fSAnirudh Venkataramanan 			 PF_FUNC_RID_FUNC_NUM_M) >>
279f31e4b6fSAnirudh Venkataramanan 		PF_FUNC_RID_FUNC_NUM_S;
280f31e4b6fSAnirudh Venkataramanan 
281f31e4b6fSAnirudh Venkataramanan 	status = ice_reset(hw, ICE_RESET_PFR);
282f31e4b6fSAnirudh Venkataramanan 	if (status)
283f31e4b6fSAnirudh Venkataramanan 		return status;
284f31e4b6fSAnirudh Venkataramanan 
285940b61afSAnirudh Venkataramanan 	/* set these values to minimum allowed */
286940b61afSAnirudh Venkataramanan 	hw->itr_gran_200 = ICE_ITR_GRAN_MIN_200;
287940b61afSAnirudh Venkataramanan 	hw->itr_gran_100 = ICE_ITR_GRAN_MIN_100;
288940b61afSAnirudh Venkataramanan 	hw->itr_gran_50 = ICE_ITR_GRAN_MIN_50;
289940b61afSAnirudh Venkataramanan 	hw->itr_gran_25 = ICE_ITR_GRAN_MIN_25;
290940b61afSAnirudh Venkataramanan 
291f31e4b6fSAnirudh Venkataramanan 	status = ice_init_all_ctrlq(hw);
292f31e4b6fSAnirudh Venkataramanan 	if (status)
293f31e4b6fSAnirudh Venkataramanan 		goto err_unroll_cqinit;
294f31e4b6fSAnirudh Venkataramanan 
295f31e4b6fSAnirudh Venkataramanan 	status = ice_clear_pf_cfg(hw);
296f31e4b6fSAnirudh Venkataramanan 	if (status)
297f31e4b6fSAnirudh Venkataramanan 		goto err_unroll_cqinit;
298f31e4b6fSAnirudh Venkataramanan 
299f31e4b6fSAnirudh Venkataramanan 	ice_clear_pxe_mode(hw);
300f31e4b6fSAnirudh Venkataramanan 
301f31e4b6fSAnirudh Venkataramanan 	status = ice_init_nvm(hw);
302f31e4b6fSAnirudh Venkataramanan 	if (status)
303f31e4b6fSAnirudh Venkataramanan 		goto err_unroll_cqinit;
304f31e4b6fSAnirudh Venkataramanan 
3059c20346bSAnirudh Venkataramanan 	status = ice_get_caps(hw);
3069c20346bSAnirudh Venkataramanan 	if (status)
3079c20346bSAnirudh Venkataramanan 		goto err_unroll_cqinit;
3089c20346bSAnirudh Venkataramanan 
3099c20346bSAnirudh Venkataramanan 	hw->port_info = devm_kzalloc(ice_hw_to_dev(hw),
3109c20346bSAnirudh Venkataramanan 				     sizeof(*hw->port_info), GFP_KERNEL);
3119c20346bSAnirudh Venkataramanan 	if (!hw->port_info) {
3129c20346bSAnirudh Venkataramanan 		status = ICE_ERR_NO_MEMORY;
3139c20346bSAnirudh Venkataramanan 		goto err_unroll_cqinit;
3149c20346bSAnirudh Venkataramanan 	}
3159c20346bSAnirudh Venkataramanan 
3169c20346bSAnirudh Venkataramanan 	/* set the back pointer to hw */
3179c20346bSAnirudh Venkataramanan 	hw->port_info->hw = hw;
3189c20346bSAnirudh Venkataramanan 
3199c20346bSAnirudh Venkataramanan 	/* Initialize port_info struct with switch configuration data */
3209c20346bSAnirudh Venkataramanan 	status = ice_get_initial_sw_cfg(hw);
3219c20346bSAnirudh Venkataramanan 	if (status)
3229c20346bSAnirudh Venkataramanan 		goto err_unroll_alloc;
3239c20346bSAnirudh Venkataramanan 
3249c20346bSAnirudh Venkataramanan 	/* Query the allocated resources for tx scheduler */
3259c20346bSAnirudh Venkataramanan 	status = ice_sched_query_res_alloc(hw);
3269c20346bSAnirudh Venkataramanan 	if (status) {
3279c20346bSAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_SCHED,
3289c20346bSAnirudh Venkataramanan 			  "Failed to get scheduler allocated resources\n");
3299c20346bSAnirudh Venkataramanan 		goto err_unroll_alloc;
3309c20346bSAnirudh Venkataramanan 	}
3319c20346bSAnirudh Venkataramanan 
332dc49c772SAnirudh Venkataramanan 	/* Initialize port_info struct with scheduler data */
333dc49c772SAnirudh Venkataramanan 	status = ice_sched_init_port(hw->port_info);
334dc49c772SAnirudh Venkataramanan 	if (status)
335dc49c772SAnirudh Venkataramanan 		goto err_unroll_sched;
336dc49c772SAnirudh Venkataramanan 
337dc49c772SAnirudh Venkataramanan 	pcaps = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*pcaps), GFP_KERNEL);
338dc49c772SAnirudh Venkataramanan 	if (!pcaps) {
339dc49c772SAnirudh Venkataramanan 		status = ICE_ERR_NO_MEMORY;
340dc49c772SAnirudh Venkataramanan 		goto err_unroll_sched;
341dc49c772SAnirudh Venkataramanan 	}
342dc49c772SAnirudh Venkataramanan 
343dc49c772SAnirudh Venkataramanan 	/* Initialize port_info struct with PHY capabilities */
344dc49c772SAnirudh Venkataramanan 	status = ice_aq_get_phy_caps(hw->port_info, false,
345dc49c772SAnirudh Venkataramanan 				     ICE_AQC_REPORT_TOPO_CAP, pcaps, NULL);
346dc49c772SAnirudh Venkataramanan 	devm_kfree(ice_hw_to_dev(hw), pcaps);
347dc49c772SAnirudh Venkataramanan 	if (status)
348dc49c772SAnirudh Venkataramanan 		goto err_unroll_sched;
349dc49c772SAnirudh Venkataramanan 
350dc49c772SAnirudh Venkataramanan 	/* Initialize port_info struct with link information */
351dc49c772SAnirudh Venkataramanan 	status = ice_aq_get_link_info(hw->port_info, false, NULL, NULL);
352dc49c772SAnirudh Venkataramanan 	if (status)
353dc49c772SAnirudh Venkataramanan 		goto err_unroll_sched;
354dc49c772SAnirudh Venkataramanan 
355dc49c772SAnirudh Venkataramanan 	/* Get port MAC information */
356dc49c772SAnirudh Venkataramanan 	mac_buf_len = sizeof(struct ice_aqc_manage_mac_read_resp);
357dc49c772SAnirudh Venkataramanan 	mac_buf = devm_kzalloc(ice_hw_to_dev(hw), mac_buf_len, GFP_KERNEL);
358dc49c772SAnirudh Venkataramanan 
359dc49c772SAnirudh Venkataramanan 	if (!mac_buf)
360dc49c772SAnirudh Venkataramanan 		goto err_unroll_sched;
361dc49c772SAnirudh Venkataramanan 
362dc49c772SAnirudh Venkataramanan 	status = ice_aq_manage_mac_read(hw, mac_buf, mac_buf_len, NULL);
363dc49c772SAnirudh Venkataramanan 	devm_kfree(ice_hw_to_dev(hw), mac_buf);
364dc49c772SAnirudh Venkataramanan 
365dc49c772SAnirudh Venkataramanan 	if (status)
366dc49c772SAnirudh Venkataramanan 		goto err_unroll_sched;
367dc49c772SAnirudh Venkataramanan 
368f31e4b6fSAnirudh Venkataramanan 	return 0;
369f31e4b6fSAnirudh Venkataramanan 
370dc49c772SAnirudh Venkataramanan err_unroll_sched:
371dc49c772SAnirudh Venkataramanan 	ice_sched_cleanup_all(hw);
3729c20346bSAnirudh Venkataramanan err_unroll_alloc:
3739c20346bSAnirudh Venkataramanan 	devm_kfree(ice_hw_to_dev(hw), hw->port_info);
374f31e4b6fSAnirudh Venkataramanan err_unroll_cqinit:
375f31e4b6fSAnirudh Venkataramanan 	ice_shutdown_all_ctrlq(hw);
376f31e4b6fSAnirudh Venkataramanan 	return status;
377f31e4b6fSAnirudh Venkataramanan }
378f31e4b6fSAnirudh Venkataramanan 
379f31e4b6fSAnirudh Venkataramanan /**
380f31e4b6fSAnirudh Venkataramanan  * ice_deinit_hw - unroll initialization operations done by ice_init_hw
381f31e4b6fSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
382f31e4b6fSAnirudh Venkataramanan  */
383f31e4b6fSAnirudh Venkataramanan void ice_deinit_hw(struct ice_hw *hw)
384f31e4b6fSAnirudh Venkataramanan {
3859c20346bSAnirudh Venkataramanan 	ice_sched_cleanup_all(hw);
386f31e4b6fSAnirudh Venkataramanan 	ice_shutdown_all_ctrlq(hw);
387dc49c772SAnirudh Venkataramanan 
3889c20346bSAnirudh Venkataramanan 	if (hw->port_info) {
3899c20346bSAnirudh Venkataramanan 		devm_kfree(ice_hw_to_dev(hw), hw->port_info);
3909c20346bSAnirudh Venkataramanan 		hw->port_info = NULL;
3919c20346bSAnirudh Venkataramanan 	}
392f31e4b6fSAnirudh Venkataramanan }
393f31e4b6fSAnirudh Venkataramanan 
394f31e4b6fSAnirudh Venkataramanan /**
395f31e4b6fSAnirudh Venkataramanan  * ice_check_reset - Check to see if a global reset is complete
396f31e4b6fSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
397f31e4b6fSAnirudh Venkataramanan  */
398f31e4b6fSAnirudh Venkataramanan enum ice_status ice_check_reset(struct ice_hw *hw)
399f31e4b6fSAnirudh Venkataramanan {
400f31e4b6fSAnirudh Venkataramanan 	u32 cnt, reg = 0, grst_delay;
401f31e4b6fSAnirudh Venkataramanan 
402f31e4b6fSAnirudh Venkataramanan 	/* Poll for Device Active state in case a recent CORER, GLOBR,
403f31e4b6fSAnirudh Venkataramanan 	 * or EMPR has occurred. The grst delay value is in 100ms units.
404f31e4b6fSAnirudh Venkataramanan 	 * Add 1sec for outstanding AQ commands that can take a long time.
405f31e4b6fSAnirudh Venkataramanan 	 */
406f31e4b6fSAnirudh Venkataramanan 	grst_delay = ((rd32(hw, GLGEN_RSTCTL) & GLGEN_RSTCTL_GRSTDEL_M) >>
407f31e4b6fSAnirudh Venkataramanan 		      GLGEN_RSTCTL_GRSTDEL_S) + 10;
408f31e4b6fSAnirudh Venkataramanan 
409f31e4b6fSAnirudh Venkataramanan 	for (cnt = 0; cnt < grst_delay; cnt++) {
410f31e4b6fSAnirudh Venkataramanan 		mdelay(100);
411f31e4b6fSAnirudh Venkataramanan 		reg = rd32(hw, GLGEN_RSTAT);
412f31e4b6fSAnirudh Venkataramanan 		if (!(reg & GLGEN_RSTAT_DEVSTATE_M))
413f31e4b6fSAnirudh Venkataramanan 			break;
414f31e4b6fSAnirudh Venkataramanan 	}
415f31e4b6fSAnirudh Venkataramanan 
416f31e4b6fSAnirudh Venkataramanan 	if (cnt == grst_delay) {
417f31e4b6fSAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_INIT,
418f31e4b6fSAnirudh Venkataramanan 			  "Global reset polling failed to complete.\n");
419f31e4b6fSAnirudh Venkataramanan 		return ICE_ERR_RESET_FAILED;
420f31e4b6fSAnirudh Venkataramanan 	}
421f31e4b6fSAnirudh Venkataramanan 
422f31e4b6fSAnirudh Venkataramanan #define ICE_RESET_DONE_MASK	(GLNVM_ULD_CORER_DONE_M | \
423f31e4b6fSAnirudh Venkataramanan 				 GLNVM_ULD_GLOBR_DONE_M)
424f31e4b6fSAnirudh Venkataramanan 
425f31e4b6fSAnirudh Venkataramanan 	/* Device is Active; check Global Reset processes are done */
426f31e4b6fSAnirudh Venkataramanan 	for (cnt = 0; cnt < ICE_PF_RESET_WAIT_COUNT; cnt++) {
427f31e4b6fSAnirudh Venkataramanan 		reg = rd32(hw, GLNVM_ULD) & ICE_RESET_DONE_MASK;
428f31e4b6fSAnirudh Venkataramanan 		if (reg == ICE_RESET_DONE_MASK) {
429f31e4b6fSAnirudh Venkataramanan 			ice_debug(hw, ICE_DBG_INIT,
430f31e4b6fSAnirudh Venkataramanan 				  "Global reset processes done. %d\n", cnt);
431f31e4b6fSAnirudh Venkataramanan 			break;
432f31e4b6fSAnirudh Venkataramanan 		}
433f31e4b6fSAnirudh Venkataramanan 		mdelay(10);
434f31e4b6fSAnirudh Venkataramanan 	}
435f31e4b6fSAnirudh Venkataramanan 
436f31e4b6fSAnirudh Venkataramanan 	if (cnt == ICE_PF_RESET_WAIT_COUNT) {
437f31e4b6fSAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_INIT,
438f31e4b6fSAnirudh Venkataramanan 			  "Wait for Reset Done timed out. GLNVM_ULD = 0x%x\n",
439f31e4b6fSAnirudh Venkataramanan 			  reg);
440f31e4b6fSAnirudh Venkataramanan 		return ICE_ERR_RESET_FAILED;
441f31e4b6fSAnirudh Venkataramanan 	}
442f31e4b6fSAnirudh Venkataramanan 
443f31e4b6fSAnirudh Venkataramanan 	return 0;
444f31e4b6fSAnirudh Venkataramanan }
445f31e4b6fSAnirudh Venkataramanan 
446f31e4b6fSAnirudh Venkataramanan /**
447f31e4b6fSAnirudh Venkataramanan  * ice_pf_reset - Reset the PF
448f31e4b6fSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
449f31e4b6fSAnirudh Venkataramanan  *
450f31e4b6fSAnirudh Venkataramanan  * If a global reset has been triggered, this function checks
451f31e4b6fSAnirudh Venkataramanan  * for its completion and then issues the PF reset
452f31e4b6fSAnirudh Venkataramanan  */
453f31e4b6fSAnirudh Venkataramanan static enum ice_status ice_pf_reset(struct ice_hw *hw)
454f31e4b6fSAnirudh Venkataramanan {
455f31e4b6fSAnirudh Venkataramanan 	u32 cnt, reg;
456f31e4b6fSAnirudh Venkataramanan 
457f31e4b6fSAnirudh Venkataramanan 	/* If at function entry a global reset was already in progress, i.e.
458f31e4b6fSAnirudh Venkataramanan 	 * state is not 'device active' or any of the reset done bits are not
459f31e4b6fSAnirudh Venkataramanan 	 * set in GLNVM_ULD, there is no need for a PF Reset; poll until the
460f31e4b6fSAnirudh Venkataramanan 	 * global reset is done.
461f31e4b6fSAnirudh Venkataramanan 	 */
462f31e4b6fSAnirudh Venkataramanan 	if ((rd32(hw, GLGEN_RSTAT) & GLGEN_RSTAT_DEVSTATE_M) ||
463f31e4b6fSAnirudh Venkataramanan 	    (rd32(hw, GLNVM_ULD) & ICE_RESET_DONE_MASK) ^ ICE_RESET_DONE_MASK) {
464f31e4b6fSAnirudh Venkataramanan 		/* poll on global reset currently in progress until done */
465f31e4b6fSAnirudh Venkataramanan 		if (ice_check_reset(hw))
466f31e4b6fSAnirudh Venkataramanan 			return ICE_ERR_RESET_FAILED;
467f31e4b6fSAnirudh Venkataramanan 
468f31e4b6fSAnirudh Venkataramanan 		return 0;
469f31e4b6fSAnirudh Venkataramanan 	}
470f31e4b6fSAnirudh Venkataramanan 
471f31e4b6fSAnirudh Venkataramanan 	/* Reset the PF */
472f31e4b6fSAnirudh Venkataramanan 	reg = rd32(hw, PFGEN_CTRL);
473f31e4b6fSAnirudh Venkataramanan 
474f31e4b6fSAnirudh Venkataramanan 	wr32(hw, PFGEN_CTRL, (reg | PFGEN_CTRL_PFSWR_M));
475f31e4b6fSAnirudh Venkataramanan 
476f31e4b6fSAnirudh Venkataramanan 	for (cnt = 0; cnt < ICE_PF_RESET_WAIT_COUNT; cnt++) {
477f31e4b6fSAnirudh Venkataramanan 		reg = rd32(hw, PFGEN_CTRL);
478f31e4b6fSAnirudh Venkataramanan 		if (!(reg & PFGEN_CTRL_PFSWR_M))
479f31e4b6fSAnirudh Venkataramanan 			break;
480f31e4b6fSAnirudh Venkataramanan 
481f31e4b6fSAnirudh Venkataramanan 		mdelay(1);
482f31e4b6fSAnirudh Venkataramanan 	}
483f31e4b6fSAnirudh Venkataramanan 
484f31e4b6fSAnirudh Venkataramanan 	if (cnt == ICE_PF_RESET_WAIT_COUNT) {
485f31e4b6fSAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_INIT,
486f31e4b6fSAnirudh Venkataramanan 			  "PF reset polling failed to complete.\n");
487f31e4b6fSAnirudh Venkataramanan 		return ICE_ERR_RESET_FAILED;
488f31e4b6fSAnirudh Venkataramanan 	}
489f31e4b6fSAnirudh Venkataramanan 
490f31e4b6fSAnirudh Venkataramanan 	return 0;
491f31e4b6fSAnirudh Venkataramanan }
492f31e4b6fSAnirudh Venkataramanan 
493f31e4b6fSAnirudh Venkataramanan /**
494f31e4b6fSAnirudh Venkataramanan  * ice_reset - Perform different types of reset
495f31e4b6fSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
496f31e4b6fSAnirudh Venkataramanan  * @req: reset request
497f31e4b6fSAnirudh Venkataramanan  *
498f31e4b6fSAnirudh Venkataramanan  * This function triggers a reset as specified by the req parameter.
499f31e4b6fSAnirudh Venkataramanan  *
500f31e4b6fSAnirudh Venkataramanan  * Note:
501f31e4b6fSAnirudh Venkataramanan  * If anything other than a PF reset is triggered, PXE mode is restored.
502f31e4b6fSAnirudh Venkataramanan  * This has to be cleared using ice_clear_pxe_mode again, once the AQ
503f31e4b6fSAnirudh Venkataramanan  * interface has been restored in the rebuild flow.
504f31e4b6fSAnirudh Venkataramanan  */
505f31e4b6fSAnirudh Venkataramanan enum ice_status ice_reset(struct ice_hw *hw, enum ice_reset_req req)
506f31e4b6fSAnirudh Venkataramanan {
507f31e4b6fSAnirudh Venkataramanan 	u32 val = 0;
508f31e4b6fSAnirudh Venkataramanan 
509f31e4b6fSAnirudh Venkataramanan 	switch (req) {
510f31e4b6fSAnirudh Venkataramanan 	case ICE_RESET_PFR:
511f31e4b6fSAnirudh Venkataramanan 		return ice_pf_reset(hw);
512f31e4b6fSAnirudh Venkataramanan 	case ICE_RESET_CORER:
513f31e4b6fSAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_INIT, "CoreR requested\n");
514f31e4b6fSAnirudh Venkataramanan 		val = GLGEN_RTRIG_CORER_M;
515f31e4b6fSAnirudh Venkataramanan 		break;
516f31e4b6fSAnirudh Venkataramanan 	case ICE_RESET_GLOBR:
517f31e4b6fSAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_INIT, "GlobalR requested\n");
518f31e4b6fSAnirudh Venkataramanan 		val = GLGEN_RTRIG_GLOBR_M;
519f31e4b6fSAnirudh Venkataramanan 		break;
520f31e4b6fSAnirudh Venkataramanan 	}
521f31e4b6fSAnirudh Venkataramanan 
522f31e4b6fSAnirudh Venkataramanan 	val |= rd32(hw, GLGEN_RTRIG);
523f31e4b6fSAnirudh Venkataramanan 	wr32(hw, GLGEN_RTRIG, val);
524f31e4b6fSAnirudh Venkataramanan 	ice_flush(hw);
525f31e4b6fSAnirudh Venkataramanan 
526f31e4b6fSAnirudh Venkataramanan 	/* wait for the FW to be ready */
527f31e4b6fSAnirudh Venkataramanan 	return ice_check_reset(hw);
528f31e4b6fSAnirudh Venkataramanan }
529f31e4b6fSAnirudh Venkataramanan 
5307ec59eeaSAnirudh Venkataramanan /**
5317ec59eeaSAnirudh Venkataramanan  * ice_debug_cq
5327ec59eeaSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
5337ec59eeaSAnirudh Venkataramanan  * @mask: debug mask
5347ec59eeaSAnirudh Venkataramanan  * @desc: pointer to control queue descriptor
5357ec59eeaSAnirudh Venkataramanan  * @buf: pointer to command buffer
5367ec59eeaSAnirudh Venkataramanan  * @buf_len: max length of buf
5377ec59eeaSAnirudh Venkataramanan  *
5387ec59eeaSAnirudh Venkataramanan  * Dumps debug log about control command with descriptor contents.
5397ec59eeaSAnirudh Venkataramanan  */
5407ec59eeaSAnirudh Venkataramanan void ice_debug_cq(struct ice_hw *hw, u32 __maybe_unused mask, void *desc,
5417ec59eeaSAnirudh Venkataramanan 		  void *buf, u16 buf_len)
5427ec59eeaSAnirudh Venkataramanan {
5437ec59eeaSAnirudh Venkataramanan 	struct ice_aq_desc *cq_desc = (struct ice_aq_desc *)desc;
5447ec59eeaSAnirudh Venkataramanan 	u16 len;
5457ec59eeaSAnirudh Venkataramanan 
5467ec59eeaSAnirudh Venkataramanan #ifndef CONFIG_DYNAMIC_DEBUG
5477ec59eeaSAnirudh Venkataramanan 	if (!(mask & hw->debug_mask))
5487ec59eeaSAnirudh Venkataramanan 		return;
5497ec59eeaSAnirudh Venkataramanan #endif
5507ec59eeaSAnirudh Venkataramanan 
5517ec59eeaSAnirudh Venkataramanan 	if (!desc)
5527ec59eeaSAnirudh Venkataramanan 		return;
5537ec59eeaSAnirudh Venkataramanan 
5547ec59eeaSAnirudh Venkataramanan 	len = le16_to_cpu(cq_desc->datalen);
5557ec59eeaSAnirudh Venkataramanan 
5567ec59eeaSAnirudh Venkataramanan 	ice_debug(hw, mask,
5577ec59eeaSAnirudh Venkataramanan 		  "CQ CMD: opcode 0x%04X, flags 0x%04X, datalen 0x%04X, retval 0x%04X\n",
5587ec59eeaSAnirudh Venkataramanan 		  le16_to_cpu(cq_desc->opcode),
5597ec59eeaSAnirudh Venkataramanan 		  le16_to_cpu(cq_desc->flags),
5607ec59eeaSAnirudh Venkataramanan 		  le16_to_cpu(cq_desc->datalen), le16_to_cpu(cq_desc->retval));
5617ec59eeaSAnirudh Venkataramanan 	ice_debug(hw, mask, "\tcookie (h,l) 0x%08X 0x%08X\n",
5627ec59eeaSAnirudh Venkataramanan 		  le32_to_cpu(cq_desc->cookie_high),
5637ec59eeaSAnirudh Venkataramanan 		  le32_to_cpu(cq_desc->cookie_low));
5647ec59eeaSAnirudh Venkataramanan 	ice_debug(hw, mask, "\tparam (0,1)  0x%08X 0x%08X\n",
5657ec59eeaSAnirudh Venkataramanan 		  le32_to_cpu(cq_desc->params.generic.param0),
5667ec59eeaSAnirudh Venkataramanan 		  le32_to_cpu(cq_desc->params.generic.param1));
5677ec59eeaSAnirudh Venkataramanan 	ice_debug(hw, mask, "\taddr (h,l)   0x%08X 0x%08X\n",
5687ec59eeaSAnirudh Venkataramanan 		  le32_to_cpu(cq_desc->params.generic.addr_high),
5697ec59eeaSAnirudh Venkataramanan 		  le32_to_cpu(cq_desc->params.generic.addr_low));
5707ec59eeaSAnirudh Venkataramanan 	if (buf && cq_desc->datalen != 0) {
5717ec59eeaSAnirudh Venkataramanan 		ice_debug(hw, mask, "Buffer:\n");
5727ec59eeaSAnirudh Venkataramanan 		if (buf_len < len)
5737ec59eeaSAnirudh Venkataramanan 			len = buf_len;
5747ec59eeaSAnirudh Venkataramanan 
5757ec59eeaSAnirudh Venkataramanan 		ice_debug_array(hw, mask, 16, 1, (u8 *)buf, len);
5767ec59eeaSAnirudh Venkataramanan 	}
5777ec59eeaSAnirudh Venkataramanan }
5787ec59eeaSAnirudh Venkataramanan 
5797ec59eeaSAnirudh Venkataramanan /* FW Admin Queue command wrappers */
5807ec59eeaSAnirudh Venkataramanan 
5817ec59eeaSAnirudh Venkataramanan /**
5827ec59eeaSAnirudh Venkataramanan  * ice_aq_send_cmd - send FW Admin Queue command to FW Admin Queue
5837ec59eeaSAnirudh Venkataramanan  * @hw: pointer to the hw struct
5847ec59eeaSAnirudh Venkataramanan  * @desc: descriptor describing the command
5857ec59eeaSAnirudh Venkataramanan  * @buf: buffer to use for indirect commands (NULL for direct commands)
5867ec59eeaSAnirudh Venkataramanan  * @buf_size: size of buffer for indirect commands (0 for direct commands)
5877ec59eeaSAnirudh Venkataramanan  * @cd: pointer to command details structure
5887ec59eeaSAnirudh Venkataramanan  *
5897ec59eeaSAnirudh Venkataramanan  * Helper function to send FW Admin Queue commands to the FW Admin Queue.
5907ec59eeaSAnirudh Venkataramanan  */
5917ec59eeaSAnirudh Venkataramanan enum ice_status
5927ec59eeaSAnirudh Venkataramanan ice_aq_send_cmd(struct ice_hw *hw, struct ice_aq_desc *desc, void *buf,
5937ec59eeaSAnirudh Venkataramanan 		u16 buf_size, struct ice_sq_cd *cd)
5947ec59eeaSAnirudh Venkataramanan {
5957ec59eeaSAnirudh Venkataramanan 	return ice_sq_send_cmd(hw, &hw->adminq, desc, buf, buf_size, cd);
5967ec59eeaSAnirudh Venkataramanan }
5977ec59eeaSAnirudh Venkataramanan 
5987ec59eeaSAnirudh Venkataramanan /**
5997ec59eeaSAnirudh Venkataramanan  * ice_aq_get_fw_ver
6007ec59eeaSAnirudh Venkataramanan  * @hw: pointer to the hw struct
6017ec59eeaSAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
6027ec59eeaSAnirudh Venkataramanan  *
6037ec59eeaSAnirudh Venkataramanan  * Get the firmware version (0x0001) from the admin queue commands
6047ec59eeaSAnirudh Venkataramanan  */
6057ec59eeaSAnirudh Venkataramanan enum ice_status ice_aq_get_fw_ver(struct ice_hw *hw, struct ice_sq_cd *cd)
6067ec59eeaSAnirudh Venkataramanan {
6077ec59eeaSAnirudh Venkataramanan 	struct ice_aqc_get_ver *resp;
6087ec59eeaSAnirudh Venkataramanan 	struct ice_aq_desc desc;
6097ec59eeaSAnirudh Venkataramanan 	enum ice_status status;
6107ec59eeaSAnirudh Venkataramanan 
6117ec59eeaSAnirudh Venkataramanan 	resp = &desc.params.get_ver;
6127ec59eeaSAnirudh Venkataramanan 
6137ec59eeaSAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_ver);
6147ec59eeaSAnirudh Venkataramanan 
6157ec59eeaSAnirudh Venkataramanan 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
6167ec59eeaSAnirudh Venkataramanan 
6177ec59eeaSAnirudh Venkataramanan 	if (!status) {
6187ec59eeaSAnirudh Venkataramanan 		hw->fw_branch = resp->fw_branch;
6197ec59eeaSAnirudh Venkataramanan 		hw->fw_maj_ver = resp->fw_major;
6207ec59eeaSAnirudh Venkataramanan 		hw->fw_min_ver = resp->fw_minor;
6217ec59eeaSAnirudh Venkataramanan 		hw->fw_patch = resp->fw_patch;
6227ec59eeaSAnirudh Venkataramanan 		hw->fw_build = le32_to_cpu(resp->fw_build);
6237ec59eeaSAnirudh Venkataramanan 		hw->api_branch = resp->api_branch;
6247ec59eeaSAnirudh Venkataramanan 		hw->api_maj_ver = resp->api_major;
6257ec59eeaSAnirudh Venkataramanan 		hw->api_min_ver = resp->api_minor;
6267ec59eeaSAnirudh Venkataramanan 		hw->api_patch = resp->api_patch;
6277ec59eeaSAnirudh Venkataramanan 	}
6287ec59eeaSAnirudh Venkataramanan 
6297ec59eeaSAnirudh Venkataramanan 	return status;
6307ec59eeaSAnirudh Venkataramanan }
6317ec59eeaSAnirudh Venkataramanan 
6327ec59eeaSAnirudh Venkataramanan /**
6337ec59eeaSAnirudh Venkataramanan  * ice_aq_q_shutdown
6347ec59eeaSAnirudh Venkataramanan  * @hw: pointer to the hw struct
6357ec59eeaSAnirudh Venkataramanan  * @unloading: is the driver unloading itself
6367ec59eeaSAnirudh Venkataramanan  *
6377ec59eeaSAnirudh Venkataramanan  * Tell the Firmware that we're shutting down the AdminQ and whether
6387ec59eeaSAnirudh Venkataramanan  * or not the driver is unloading as well (0x0003).
6397ec59eeaSAnirudh Venkataramanan  */
6407ec59eeaSAnirudh Venkataramanan enum ice_status ice_aq_q_shutdown(struct ice_hw *hw, bool unloading)
6417ec59eeaSAnirudh Venkataramanan {
6427ec59eeaSAnirudh Venkataramanan 	struct ice_aqc_q_shutdown *cmd;
6437ec59eeaSAnirudh Venkataramanan 	struct ice_aq_desc desc;
6447ec59eeaSAnirudh Venkataramanan 
6457ec59eeaSAnirudh Venkataramanan 	cmd = &desc.params.q_shutdown;
6467ec59eeaSAnirudh Venkataramanan 
6477ec59eeaSAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_q_shutdown);
6487ec59eeaSAnirudh Venkataramanan 
6497ec59eeaSAnirudh Venkataramanan 	if (unloading)
6507ec59eeaSAnirudh Venkataramanan 		cmd->driver_unloading = cpu_to_le32(ICE_AQC_DRIVER_UNLOADING);
6517ec59eeaSAnirudh Venkataramanan 
6527ec59eeaSAnirudh Venkataramanan 	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
6537ec59eeaSAnirudh Venkataramanan }
654f31e4b6fSAnirudh Venkataramanan 
655f31e4b6fSAnirudh Venkataramanan /**
656f31e4b6fSAnirudh Venkataramanan  * ice_aq_req_res
657f31e4b6fSAnirudh Venkataramanan  * @hw: pointer to the hw struct
658f31e4b6fSAnirudh Venkataramanan  * @res: resource id
659f31e4b6fSAnirudh Venkataramanan  * @access: access type
660f31e4b6fSAnirudh Venkataramanan  * @sdp_number: resource number
661f31e4b6fSAnirudh Venkataramanan  * @timeout: the maximum time in ms that the driver may hold the resource
662f31e4b6fSAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
663f31e4b6fSAnirudh Venkataramanan  *
664f31e4b6fSAnirudh Venkataramanan  * requests common resource using the admin queue commands (0x0008)
665f31e4b6fSAnirudh Venkataramanan  */
666f31e4b6fSAnirudh Venkataramanan static enum ice_status
667f31e4b6fSAnirudh Venkataramanan ice_aq_req_res(struct ice_hw *hw, enum ice_aq_res_ids res,
668f31e4b6fSAnirudh Venkataramanan 	       enum ice_aq_res_access_type access, u8 sdp_number, u32 *timeout,
669f31e4b6fSAnirudh Venkataramanan 	       struct ice_sq_cd *cd)
670f31e4b6fSAnirudh Venkataramanan {
671f31e4b6fSAnirudh Venkataramanan 	struct ice_aqc_req_res *cmd_resp;
672f31e4b6fSAnirudh Venkataramanan 	struct ice_aq_desc desc;
673f31e4b6fSAnirudh Venkataramanan 	enum ice_status status;
674f31e4b6fSAnirudh Venkataramanan 
675f31e4b6fSAnirudh Venkataramanan 	cmd_resp = &desc.params.res_owner;
676f31e4b6fSAnirudh Venkataramanan 
677f31e4b6fSAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_req_res);
678f31e4b6fSAnirudh Venkataramanan 
679f31e4b6fSAnirudh Venkataramanan 	cmd_resp->res_id = cpu_to_le16(res);
680f31e4b6fSAnirudh Venkataramanan 	cmd_resp->access_type = cpu_to_le16(access);
681f31e4b6fSAnirudh Venkataramanan 	cmd_resp->res_number = cpu_to_le32(sdp_number);
682f31e4b6fSAnirudh Venkataramanan 
683f31e4b6fSAnirudh Venkataramanan 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
684f31e4b6fSAnirudh Venkataramanan 	/* The completion specifies the maximum time in ms that the driver
685f31e4b6fSAnirudh Venkataramanan 	 * may hold the resource in the Timeout field.
686f31e4b6fSAnirudh Venkataramanan 	 * If the resource is held by someone else, the command completes with
687f31e4b6fSAnirudh Venkataramanan 	 * busy return value and the timeout field indicates the maximum time
688f31e4b6fSAnirudh Venkataramanan 	 * the current owner of the resource has to free it.
689f31e4b6fSAnirudh Venkataramanan 	 */
690f31e4b6fSAnirudh Venkataramanan 	if (!status || hw->adminq.sq_last_status == ICE_AQ_RC_EBUSY)
691f31e4b6fSAnirudh Venkataramanan 		*timeout = le32_to_cpu(cmd_resp->timeout);
692f31e4b6fSAnirudh Venkataramanan 
693f31e4b6fSAnirudh Venkataramanan 	return status;
694f31e4b6fSAnirudh Venkataramanan }
695f31e4b6fSAnirudh Venkataramanan 
696f31e4b6fSAnirudh Venkataramanan /**
697f31e4b6fSAnirudh Venkataramanan  * ice_aq_release_res
698f31e4b6fSAnirudh Venkataramanan  * @hw: pointer to the hw struct
699f31e4b6fSAnirudh Venkataramanan  * @res: resource id
700f31e4b6fSAnirudh Venkataramanan  * @sdp_number: resource number
701f31e4b6fSAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
702f31e4b6fSAnirudh Venkataramanan  *
703f31e4b6fSAnirudh Venkataramanan  * release common resource using the admin queue commands (0x0009)
704f31e4b6fSAnirudh Venkataramanan  */
705f31e4b6fSAnirudh Venkataramanan static enum ice_status
706f31e4b6fSAnirudh Venkataramanan ice_aq_release_res(struct ice_hw *hw, enum ice_aq_res_ids res, u8 sdp_number,
707f31e4b6fSAnirudh Venkataramanan 		   struct ice_sq_cd *cd)
708f31e4b6fSAnirudh Venkataramanan {
709f31e4b6fSAnirudh Venkataramanan 	struct ice_aqc_req_res *cmd;
710f31e4b6fSAnirudh Venkataramanan 	struct ice_aq_desc desc;
711f31e4b6fSAnirudh Venkataramanan 
712f31e4b6fSAnirudh Venkataramanan 	cmd = &desc.params.res_owner;
713f31e4b6fSAnirudh Venkataramanan 
714f31e4b6fSAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_release_res);
715f31e4b6fSAnirudh Venkataramanan 
716f31e4b6fSAnirudh Venkataramanan 	cmd->res_id = cpu_to_le16(res);
717f31e4b6fSAnirudh Venkataramanan 	cmd->res_number = cpu_to_le32(sdp_number);
718f31e4b6fSAnirudh Venkataramanan 
719f31e4b6fSAnirudh Venkataramanan 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
720f31e4b6fSAnirudh Venkataramanan }
721f31e4b6fSAnirudh Venkataramanan 
722f31e4b6fSAnirudh Venkataramanan /**
723f31e4b6fSAnirudh Venkataramanan  * ice_acquire_res
724f31e4b6fSAnirudh Venkataramanan  * @hw: pointer to the HW structure
725f31e4b6fSAnirudh Venkataramanan  * @res: resource id
726f31e4b6fSAnirudh Venkataramanan  * @access: access type (read or write)
727f31e4b6fSAnirudh Venkataramanan  *
728f31e4b6fSAnirudh Venkataramanan  * This function will attempt to acquire the ownership of a resource.
729f31e4b6fSAnirudh Venkataramanan  */
730f31e4b6fSAnirudh Venkataramanan enum ice_status
731f31e4b6fSAnirudh Venkataramanan ice_acquire_res(struct ice_hw *hw, enum ice_aq_res_ids res,
732f31e4b6fSAnirudh Venkataramanan 		enum ice_aq_res_access_type access)
733f31e4b6fSAnirudh Venkataramanan {
734f31e4b6fSAnirudh Venkataramanan #define ICE_RES_POLLING_DELAY_MS	10
735f31e4b6fSAnirudh Venkataramanan 	u32 delay = ICE_RES_POLLING_DELAY_MS;
736f31e4b6fSAnirudh Venkataramanan 	enum ice_status status;
737f31e4b6fSAnirudh Venkataramanan 	u32 time_left = 0;
738f31e4b6fSAnirudh Venkataramanan 	u32 timeout;
739f31e4b6fSAnirudh Venkataramanan 
740f31e4b6fSAnirudh Venkataramanan 	status = ice_aq_req_res(hw, res, access, 0, &time_left, NULL);
741f31e4b6fSAnirudh Venkataramanan 
742f31e4b6fSAnirudh Venkataramanan 	/* An admin queue return code of ICE_AQ_RC_EEXIST means that another
743f31e4b6fSAnirudh Venkataramanan 	 * driver has previously acquired the resource and performed any
744f31e4b6fSAnirudh Venkataramanan 	 * necessary updates; in this case the caller does not obtain the
745f31e4b6fSAnirudh Venkataramanan 	 * resource and has no further work to do.
746f31e4b6fSAnirudh Venkataramanan 	 */
747f31e4b6fSAnirudh Venkataramanan 	if (hw->adminq.sq_last_status == ICE_AQ_RC_EEXIST) {
748f31e4b6fSAnirudh Venkataramanan 		status = ICE_ERR_AQ_NO_WORK;
749f31e4b6fSAnirudh Venkataramanan 		goto ice_acquire_res_exit;
750f31e4b6fSAnirudh Venkataramanan 	}
751f31e4b6fSAnirudh Venkataramanan 
752f31e4b6fSAnirudh Venkataramanan 	if (status)
753f31e4b6fSAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_RES,
754f31e4b6fSAnirudh Venkataramanan 			  "resource %d acquire type %d failed.\n", res, access);
755f31e4b6fSAnirudh Venkataramanan 
756f31e4b6fSAnirudh Venkataramanan 	/* If necessary, poll until the current lock owner timeouts */
757f31e4b6fSAnirudh Venkataramanan 	timeout = time_left;
758f31e4b6fSAnirudh Venkataramanan 	while (status && timeout && time_left) {
759f31e4b6fSAnirudh Venkataramanan 		mdelay(delay);
760f31e4b6fSAnirudh Venkataramanan 		timeout = (timeout > delay) ? timeout - delay : 0;
761f31e4b6fSAnirudh Venkataramanan 		status = ice_aq_req_res(hw, res, access, 0, &time_left, NULL);
762f31e4b6fSAnirudh Venkataramanan 
763f31e4b6fSAnirudh Venkataramanan 		if (hw->adminq.sq_last_status == ICE_AQ_RC_EEXIST) {
764f31e4b6fSAnirudh Venkataramanan 			/* lock free, but no work to do */
765f31e4b6fSAnirudh Venkataramanan 			status = ICE_ERR_AQ_NO_WORK;
766f31e4b6fSAnirudh Venkataramanan 			break;
767f31e4b6fSAnirudh Venkataramanan 		}
768f31e4b6fSAnirudh Venkataramanan 
769f31e4b6fSAnirudh Venkataramanan 		if (!status)
770f31e4b6fSAnirudh Venkataramanan 			/* lock acquired */
771f31e4b6fSAnirudh Venkataramanan 			break;
772f31e4b6fSAnirudh Venkataramanan 	}
773f31e4b6fSAnirudh Venkataramanan 	if (status && status != ICE_ERR_AQ_NO_WORK)
774f31e4b6fSAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_RES, "resource acquire timed out.\n");
775f31e4b6fSAnirudh Venkataramanan 
776f31e4b6fSAnirudh Venkataramanan ice_acquire_res_exit:
777f31e4b6fSAnirudh Venkataramanan 	if (status == ICE_ERR_AQ_NO_WORK) {
778f31e4b6fSAnirudh Venkataramanan 		if (access == ICE_RES_WRITE)
779f31e4b6fSAnirudh Venkataramanan 			ice_debug(hw, ICE_DBG_RES,
780f31e4b6fSAnirudh Venkataramanan 				  "resource indicates no work to do.\n");
781f31e4b6fSAnirudh Venkataramanan 		else
782f31e4b6fSAnirudh Venkataramanan 			ice_debug(hw, ICE_DBG_RES,
783f31e4b6fSAnirudh Venkataramanan 				  "Warning: ICE_ERR_AQ_NO_WORK not expected\n");
784f31e4b6fSAnirudh Venkataramanan 	}
785f31e4b6fSAnirudh Venkataramanan 	return status;
786f31e4b6fSAnirudh Venkataramanan }
787f31e4b6fSAnirudh Venkataramanan 
788f31e4b6fSAnirudh Venkataramanan /**
789f31e4b6fSAnirudh Venkataramanan  * ice_release_res
790f31e4b6fSAnirudh Venkataramanan  * @hw: pointer to the HW structure
791f31e4b6fSAnirudh Venkataramanan  * @res: resource id
792f31e4b6fSAnirudh Venkataramanan  *
793f31e4b6fSAnirudh Venkataramanan  * This function will release a resource using the proper Admin Command.
794f31e4b6fSAnirudh Venkataramanan  */
795f31e4b6fSAnirudh Venkataramanan void ice_release_res(struct ice_hw *hw, enum ice_aq_res_ids res)
796f31e4b6fSAnirudh Venkataramanan {
797f31e4b6fSAnirudh Venkataramanan 	enum ice_status status;
798f31e4b6fSAnirudh Venkataramanan 	u32 total_delay = 0;
799f31e4b6fSAnirudh Venkataramanan 
800f31e4b6fSAnirudh Venkataramanan 	status = ice_aq_release_res(hw, res, 0, NULL);
801f31e4b6fSAnirudh Venkataramanan 
802f31e4b6fSAnirudh Venkataramanan 	/* there are some rare cases when trying to release the resource
803f31e4b6fSAnirudh Venkataramanan 	 * results in an admin Q timeout, so handle them correctly
804f31e4b6fSAnirudh Venkataramanan 	 */
805f31e4b6fSAnirudh Venkataramanan 	while ((status == ICE_ERR_AQ_TIMEOUT) &&
806f31e4b6fSAnirudh Venkataramanan 	       (total_delay < hw->adminq.sq_cmd_timeout)) {
807f31e4b6fSAnirudh Venkataramanan 		mdelay(1);
808f31e4b6fSAnirudh Venkataramanan 		status = ice_aq_release_res(hw, res, 0, NULL);
809f31e4b6fSAnirudh Venkataramanan 		total_delay++;
810f31e4b6fSAnirudh Venkataramanan 	}
811f31e4b6fSAnirudh Venkataramanan }
812f31e4b6fSAnirudh Venkataramanan 
813f31e4b6fSAnirudh Venkataramanan /**
8149c20346bSAnirudh Venkataramanan  * ice_parse_caps - parse function/device capabilities
8159c20346bSAnirudh Venkataramanan  * @hw: pointer to the hw struct
8169c20346bSAnirudh Venkataramanan  * @buf: pointer to a buffer containing function/device capability records
8179c20346bSAnirudh Venkataramanan  * @cap_count: number of capability records in the list
8189c20346bSAnirudh Venkataramanan  * @opc: type of capabilities list to parse
8199c20346bSAnirudh Venkataramanan  *
8209c20346bSAnirudh Venkataramanan  * Helper function to parse function(0x000a)/device(0x000b) capabilities list.
8219c20346bSAnirudh Venkataramanan  */
8229c20346bSAnirudh Venkataramanan static void
8239c20346bSAnirudh Venkataramanan ice_parse_caps(struct ice_hw *hw, void *buf, u32 cap_count,
8249c20346bSAnirudh Venkataramanan 	       enum ice_adminq_opc opc)
8259c20346bSAnirudh Venkataramanan {
8269c20346bSAnirudh Venkataramanan 	struct ice_aqc_list_caps_elem *cap_resp;
8279c20346bSAnirudh Venkataramanan 	struct ice_hw_func_caps *func_p = NULL;
8289c20346bSAnirudh Venkataramanan 	struct ice_hw_dev_caps *dev_p = NULL;
8299c20346bSAnirudh Venkataramanan 	struct ice_hw_common_caps *caps;
8309c20346bSAnirudh Venkataramanan 	u32 i;
8319c20346bSAnirudh Venkataramanan 
8329c20346bSAnirudh Venkataramanan 	if (!buf)
8339c20346bSAnirudh Venkataramanan 		return;
8349c20346bSAnirudh Venkataramanan 
8359c20346bSAnirudh Venkataramanan 	cap_resp = (struct ice_aqc_list_caps_elem *)buf;
8369c20346bSAnirudh Venkataramanan 
8379c20346bSAnirudh Venkataramanan 	if (opc == ice_aqc_opc_list_dev_caps) {
8389c20346bSAnirudh Venkataramanan 		dev_p = &hw->dev_caps;
8399c20346bSAnirudh Venkataramanan 		caps = &dev_p->common_cap;
8409c20346bSAnirudh Venkataramanan 	} else if (opc == ice_aqc_opc_list_func_caps) {
8419c20346bSAnirudh Venkataramanan 		func_p = &hw->func_caps;
8429c20346bSAnirudh Venkataramanan 		caps = &func_p->common_cap;
8439c20346bSAnirudh Venkataramanan 	} else {
8449c20346bSAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_INIT, "wrong opcode\n");
8459c20346bSAnirudh Venkataramanan 		return;
8469c20346bSAnirudh Venkataramanan 	}
8479c20346bSAnirudh Venkataramanan 
8489c20346bSAnirudh Venkataramanan 	for (i = 0; caps && i < cap_count; i++, cap_resp++) {
8499c20346bSAnirudh Venkataramanan 		u32 logical_id = le32_to_cpu(cap_resp->logical_id);
8509c20346bSAnirudh Venkataramanan 		u32 phys_id = le32_to_cpu(cap_resp->phys_id);
8519c20346bSAnirudh Venkataramanan 		u32 number = le32_to_cpu(cap_resp->number);
8529c20346bSAnirudh Venkataramanan 		u16 cap = le16_to_cpu(cap_resp->cap);
8539c20346bSAnirudh Venkataramanan 
8549c20346bSAnirudh Venkataramanan 		switch (cap) {
8559c20346bSAnirudh Venkataramanan 		case ICE_AQC_CAPS_VSI:
8569c20346bSAnirudh Venkataramanan 			if (dev_p) {
8579c20346bSAnirudh Venkataramanan 				dev_p->num_vsi_allocd_to_host = number;
8589c20346bSAnirudh Venkataramanan 				ice_debug(hw, ICE_DBG_INIT,
8599c20346bSAnirudh Venkataramanan 					  "HW caps: Dev.VSI cnt = %d\n",
8609c20346bSAnirudh Venkataramanan 					  dev_p->num_vsi_allocd_to_host);
8619c20346bSAnirudh Venkataramanan 			} else if (func_p) {
8629c20346bSAnirudh Venkataramanan 				func_p->guaranteed_num_vsi = number;
8639c20346bSAnirudh Venkataramanan 				ice_debug(hw, ICE_DBG_INIT,
8649c20346bSAnirudh Venkataramanan 					  "HW caps: Func.VSI cnt = %d\n",
8659c20346bSAnirudh Venkataramanan 					  func_p->guaranteed_num_vsi);
8669c20346bSAnirudh Venkataramanan 			}
8679c20346bSAnirudh Venkataramanan 			break;
8689c20346bSAnirudh Venkataramanan 		case ICE_AQC_CAPS_RSS:
8699c20346bSAnirudh Venkataramanan 			caps->rss_table_size = number;
8709c20346bSAnirudh Venkataramanan 			caps->rss_table_entry_width = logical_id;
8719c20346bSAnirudh Venkataramanan 			ice_debug(hw, ICE_DBG_INIT,
8729c20346bSAnirudh Venkataramanan 				  "HW caps: RSS table size = %d\n",
8739c20346bSAnirudh Venkataramanan 				  caps->rss_table_size);
8749c20346bSAnirudh Venkataramanan 			ice_debug(hw, ICE_DBG_INIT,
8759c20346bSAnirudh Venkataramanan 				  "HW caps: RSS table width = %d\n",
8769c20346bSAnirudh Venkataramanan 				  caps->rss_table_entry_width);
8779c20346bSAnirudh Venkataramanan 			break;
8789c20346bSAnirudh Venkataramanan 		case ICE_AQC_CAPS_RXQS:
8799c20346bSAnirudh Venkataramanan 			caps->num_rxq = number;
8809c20346bSAnirudh Venkataramanan 			caps->rxq_first_id = phys_id;
8819c20346bSAnirudh Venkataramanan 			ice_debug(hw, ICE_DBG_INIT,
8829c20346bSAnirudh Venkataramanan 				  "HW caps: Num Rx Qs = %d\n", caps->num_rxq);
8839c20346bSAnirudh Venkataramanan 			ice_debug(hw, ICE_DBG_INIT,
8849c20346bSAnirudh Venkataramanan 				  "HW caps: Rx first queue ID = %d\n",
8859c20346bSAnirudh Venkataramanan 				  caps->rxq_first_id);
8869c20346bSAnirudh Venkataramanan 			break;
8879c20346bSAnirudh Venkataramanan 		case ICE_AQC_CAPS_TXQS:
8889c20346bSAnirudh Venkataramanan 			caps->num_txq = number;
8899c20346bSAnirudh Venkataramanan 			caps->txq_first_id = phys_id;
8909c20346bSAnirudh Venkataramanan 			ice_debug(hw, ICE_DBG_INIT,
8919c20346bSAnirudh Venkataramanan 				  "HW caps: Num Tx Qs = %d\n", caps->num_txq);
8929c20346bSAnirudh Venkataramanan 			ice_debug(hw, ICE_DBG_INIT,
8939c20346bSAnirudh Venkataramanan 				  "HW caps: Tx first queue ID = %d\n",
8949c20346bSAnirudh Venkataramanan 				  caps->txq_first_id);
8959c20346bSAnirudh Venkataramanan 			break;
8969c20346bSAnirudh Venkataramanan 		case ICE_AQC_CAPS_MSIX:
8979c20346bSAnirudh Venkataramanan 			caps->num_msix_vectors = number;
8989c20346bSAnirudh Venkataramanan 			caps->msix_vector_first_id = phys_id;
8999c20346bSAnirudh Venkataramanan 			ice_debug(hw, ICE_DBG_INIT,
9009c20346bSAnirudh Venkataramanan 				  "HW caps: MSIX vector count = %d\n",
9019c20346bSAnirudh Venkataramanan 				  caps->num_msix_vectors);
9029c20346bSAnirudh Venkataramanan 			ice_debug(hw, ICE_DBG_INIT,
9039c20346bSAnirudh Venkataramanan 				  "HW caps: MSIX first vector index = %d\n",
9049c20346bSAnirudh Venkataramanan 				  caps->msix_vector_first_id);
9059c20346bSAnirudh Venkataramanan 			break;
9069c20346bSAnirudh Venkataramanan 		case ICE_AQC_CAPS_MAX_MTU:
9079c20346bSAnirudh Venkataramanan 			caps->max_mtu = number;
9089c20346bSAnirudh Venkataramanan 			if (dev_p)
9099c20346bSAnirudh Venkataramanan 				ice_debug(hw, ICE_DBG_INIT,
9109c20346bSAnirudh Venkataramanan 					  "HW caps: Dev.MaxMTU = %d\n",
9119c20346bSAnirudh Venkataramanan 					  caps->max_mtu);
9129c20346bSAnirudh Venkataramanan 			else if (func_p)
9139c20346bSAnirudh Venkataramanan 				ice_debug(hw, ICE_DBG_INIT,
9149c20346bSAnirudh Venkataramanan 					  "HW caps: func.MaxMTU = %d\n",
9159c20346bSAnirudh Venkataramanan 					  caps->max_mtu);
9169c20346bSAnirudh Venkataramanan 			break;
9179c20346bSAnirudh Venkataramanan 		default:
9189c20346bSAnirudh Venkataramanan 			ice_debug(hw, ICE_DBG_INIT,
9199c20346bSAnirudh Venkataramanan 				  "HW caps: Unknown capability[%d]: 0x%x\n", i,
9209c20346bSAnirudh Venkataramanan 				  cap);
9219c20346bSAnirudh Venkataramanan 			break;
9229c20346bSAnirudh Venkataramanan 		}
9239c20346bSAnirudh Venkataramanan 	}
9249c20346bSAnirudh Venkataramanan }
9259c20346bSAnirudh Venkataramanan 
9269c20346bSAnirudh Venkataramanan /**
9279c20346bSAnirudh Venkataramanan  * ice_aq_discover_caps - query function/device capabilities
9289c20346bSAnirudh Venkataramanan  * @hw: pointer to the hw struct
9299c20346bSAnirudh Venkataramanan  * @buf: a virtual buffer to hold the capabilities
9309c20346bSAnirudh Venkataramanan  * @buf_size: Size of the virtual buffer
9319c20346bSAnirudh Venkataramanan  * @data_size: Size of the returned data, or buf size needed if AQ err==ENOMEM
9329c20346bSAnirudh Venkataramanan  * @opc: capabilities type to discover - pass in the command opcode
9339c20346bSAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
9349c20346bSAnirudh Venkataramanan  *
9359c20346bSAnirudh Venkataramanan  * Get the function(0x000a)/device(0x000b) capabilities description from
9369c20346bSAnirudh Venkataramanan  * the firmware.
9379c20346bSAnirudh Venkataramanan  */
9389c20346bSAnirudh Venkataramanan static enum ice_status
9399c20346bSAnirudh Venkataramanan ice_aq_discover_caps(struct ice_hw *hw, void *buf, u16 buf_size, u16 *data_size,
9409c20346bSAnirudh Venkataramanan 		     enum ice_adminq_opc opc, struct ice_sq_cd *cd)
9419c20346bSAnirudh Venkataramanan {
9429c20346bSAnirudh Venkataramanan 	struct ice_aqc_list_caps *cmd;
9439c20346bSAnirudh Venkataramanan 	struct ice_aq_desc desc;
9449c20346bSAnirudh Venkataramanan 	enum ice_status status;
9459c20346bSAnirudh Venkataramanan 
9469c20346bSAnirudh Venkataramanan 	cmd = &desc.params.get_cap;
9479c20346bSAnirudh Venkataramanan 
9489c20346bSAnirudh Venkataramanan 	if (opc != ice_aqc_opc_list_func_caps &&
9499c20346bSAnirudh Venkataramanan 	    opc != ice_aqc_opc_list_dev_caps)
9509c20346bSAnirudh Venkataramanan 		return ICE_ERR_PARAM;
9519c20346bSAnirudh Venkataramanan 
9529c20346bSAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, opc);
9539c20346bSAnirudh Venkataramanan 
9549c20346bSAnirudh Venkataramanan 	status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
9559c20346bSAnirudh Venkataramanan 	if (!status)
9569c20346bSAnirudh Venkataramanan 		ice_parse_caps(hw, buf, le32_to_cpu(cmd->count), opc);
9579c20346bSAnirudh Venkataramanan 	*data_size = le16_to_cpu(desc.datalen);
9589c20346bSAnirudh Venkataramanan 
9599c20346bSAnirudh Venkataramanan 	return status;
9609c20346bSAnirudh Venkataramanan }
9619c20346bSAnirudh Venkataramanan 
9629c20346bSAnirudh Venkataramanan /**
9639c20346bSAnirudh Venkataramanan  * ice_get_caps - get info about the HW
9649c20346bSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
9659c20346bSAnirudh Venkataramanan  */
9669c20346bSAnirudh Venkataramanan enum ice_status ice_get_caps(struct ice_hw *hw)
9679c20346bSAnirudh Venkataramanan {
9689c20346bSAnirudh Venkataramanan 	enum ice_status status;
9699c20346bSAnirudh Venkataramanan 	u16 data_size = 0;
9709c20346bSAnirudh Venkataramanan 	u16 cbuf_len;
9719c20346bSAnirudh Venkataramanan 	u8 retries;
9729c20346bSAnirudh Venkataramanan 
9739c20346bSAnirudh Venkataramanan 	/* The driver doesn't know how many capabilities the device will return
9749c20346bSAnirudh Venkataramanan 	 * so the buffer size required isn't known ahead of time. The driver
9759c20346bSAnirudh Venkataramanan 	 * starts with cbuf_len and if this turns out to be insufficient, the
9769c20346bSAnirudh Venkataramanan 	 * device returns ICE_AQ_RC_ENOMEM and also the buffer size it needs.
9779c20346bSAnirudh Venkataramanan 	 * The driver then allocates the buffer of this size and retries the
9789c20346bSAnirudh Venkataramanan 	 * operation. So it follows that the retry count is 2.
9799c20346bSAnirudh Venkataramanan 	 */
9809c20346bSAnirudh Venkataramanan #define ICE_GET_CAP_BUF_COUNT	40
9819c20346bSAnirudh Venkataramanan #define ICE_GET_CAP_RETRY_COUNT	2
9829c20346bSAnirudh Venkataramanan 
9839c20346bSAnirudh Venkataramanan 	cbuf_len = ICE_GET_CAP_BUF_COUNT *
9849c20346bSAnirudh Venkataramanan 		sizeof(struct ice_aqc_list_caps_elem);
9859c20346bSAnirudh Venkataramanan 
9869c20346bSAnirudh Venkataramanan 	retries = ICE_GET_CAP_RETRY_COUNT;
9879c20346bSAnirudh Venkataramanan 
9889c20346bSAnirudh Venkataramanan 	do {
9899c20346bSAnirudh Venkataramanan 		void *cbuf;
9909c20346bSAnirudh Venkataramanan 
9919c20346bSAnirudh Venkataramanan 		cbuf = devm_kzalloc(ice_hw_to_dev(hw), cbuf_len, GFP_KERNEL);
9929c20346bSAnirudh Venkataramanan 		if (!cbuf)
9939c20346bSAnirudh Venkataramanan 			return ICE_ERR_NO_MEMORY;
9949c20346bSAnirudh Venkataramanan 
9959c20346bSAnirudh Venkataramanan 		status = ice_aq_discover_caps(hw, cbuf, cbuf_len, &data_size,
9969c20346bSAnirudh Venkataramanan 					      ice_aqc_opc_list_func_caps, NULL);
9979c20346bSAnirudh Venkataramanan 		devm_kfree(ice_hw_to_dev(hw), cbuf);
9989c20346bSAnirudh Venkataramanan 
9999c20346bSAnirudh Venkataramanan 		if (!status || hw->adminq.sq_last_status != ICE_AQ_RC_ENOMEM)
10009c20346bSAnirudh Venkataramanan 			break;
10019c20346bSAnirudh Venkataramanan 
10029c20346bSAnirudh Venkataramanan 		/* If ENOMEM is returned, try again with bigger buffer */
10039c20346bSAnirudh Venkataramanan 		cbuf_len = data_size;
10049c20346bSAnirudh Venkataramanan 	} while (--retries);
10059c20346bSAnirudh Venkataramanan 
10069c20346bSAnirudh Venkataramanan 	return status;
10079c20346bSAnirudh Venkataramanan }
10089c20346bSAnirudh Venkataramanan 
10099c20346bSAnirudh Venkataramanan /**
1010f31e4b6fSAnirudh Venkataramanan  * ice_aq_clear_pxe_mode
1011f31e4b6fSAnirudh Venkataramanan  * @hw: pointer to the hw struct
1012f31e4b6fSAnirudh Venkataramanan  *
1013f31e4b6fSAnirudh Venkataramanan  * Tell the firmware that the driver is taking over from PXE (0x0110).
1014f31e4b6fSAnirudh Venkataramanan  */
1015f31e4b6fSAnirudh Venkataramanan static enum ice_status ice_aq_clear_pxe_mode(struct ice_hw *hw)
1016f31e4b6fSAnirudh Venkataramanan {
1017f31e4b6fSAnirudh Venkataramanan 	struct ice_aq_desc desc;
1018f31e4b6fSAnirudh Venkataramanan 
1019f31e4b6fSAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_clear_pxe_mode);
1020f31e4b6fSAnirudh Venkataramanan 	desc.params.clear_pxe.rx_cnt = ICE_AQC_CLEAR_PXE_RX_CNT;
1021f31e4b6fSAnirudh Venkataramanan 
1022f31e4b6fSAnirudh Venkataramanan 	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
1023f31e4b6fSAnirudh Venkataramanan }
1024f31e4b6fSAnirudh Venkataramanan 
1025f31e4b6fSAnirudh Venkataramanan /**
1026f31e4b6fSAnirudh Venkataramanan  * ice_clear_pxe_mode - clear pxe operations mode
1027f31e4b6fSAnirudh Venkataramanan  * @hw: pointer to the hw struct
1028f31e4b6fSAnirudh Venkataramanan  *
1029f31e4b6fSAnirudh Venkataramanan  * Make sure all PXE mode settings are cleared, including things
1030f31e4b6fSAnirudh Venkataramanan  * like descriptor fetch/write-back mode.
1031f31e4b6fSAnirudh Venkataramanan  */
1032f31e4b6fSAnirudh Venkataramanan void ice_clear_pxe_mode(struct ice_hw *hw)
1033f31e4b6fSAnirudh Venkataramanan {
1034f31e4b6fSAnirudh Venkataramanan 	if (ice_check_sq_alive(hw, &hw->adminq))
1035f31e4b6fSAnirudh Venkataramanan 		ice_aq_clear_pxe_mode(hw);
1036f31e4b6fSAnirudh Venkataramanan }
1037