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