1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2019, Intel Corporation. */
3
4 #include "ice_common.h"
5 #include "ice_lib.h"
6 #include "ice_sched.h"
7 #include "ice_dcb.h"
8
9 /**
10 * ice_aq_get_lldp_mib
11 * @hw: pointer to the HW struct
12 * @bridge_type: type of bridge requested
13 * @mib_type: Local, Remote or both Local and Remote MIBs
14 * @buf: pointer to the caller-supplied buffer to store the MIB block
15 * @buf_size: size of the buffer (in bytes)
16 * @local_len: length of the returned Local LLDP MIB
17 * @remote_len: length of the returned Remote LLDP MIB
18 * @cd: pointer to command details structure or NULL
19 *
20 * Requests the complete LLDP MIB (entire packet). (0x0A00)
21 */
22 static enum ice_status
ice_aq_get_lldp_mib(struct ice_hw * hw,u8 bridge_type,u8 mib_type,void * buf,u16 buf_size,u16 * local_len,u16 * remote_len,struct ice_sq_cd * cd)23 ice_aq_get_lldp_mib(struct ice_hw *hw, u8 bridge_type, u8 mib_type, void *buf,
24 u16 buf_size, u16 *local_len, u16 *remote_len,
25 struct ice_sq_cd *cd)
26 {
27 struct ice_aqc_lldp_get_mib *cmd;
28 struct ice_aq_desc desc;
29 enum ice_status status;
30
31 cmd = &desc.params.lldp_get_mib;
32
33 if (buf_size == 0 || !buf)
34 return ICE_ERR_PARAM;
35
36 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_lldp_get_mib);
37
38 cmd->type = mib_type & ICE_AQ_LLDP_MIB_TYPE_M;
39 cmd->type |= (bridge_type << ICE_AQ_LLDP_BRID_TYPE_S) &
40 ICE_AQ_LLDP_BRID_TYPE_M;
41
42 desc.datalen = cpu_to_le16(buf_size);
43
44 status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
45 if (!status) {
46 if (local_len)
47 *local_len = le16_to_cpu(cmd->local_len);
48 if (remote_len)
49 *remote_len = le16_to_cpu(cmd->remote_len);
50 }
51
52 return status;
53 }
54
55 /**
56 * ice_aq_cfg_lldp_mib_change
57 * @hw: pointer to the HW struct
58 * @ena_update: Enable or Disable event posting
59 * @cd: pointer to command details structure or NULL
60 *
61 * Enable or Disable posting of an event on ARQ when LLDP MIB
62 * associated with the interface changes (0x0A01)
63 */
64 static enum ice_status
ice_aq_cfg_lldp_mib_change(struct ice_hw * hw,bool ena_update,struct ice_sq_cd * cd)65 ice_aq_cfg_lldp_mib_change(struct ice_hw *hw, bool ena_update,
66 struct ice_sq_cd *cd)
67 {
68 struct ice_aqc_lldp_set_mib_change *cmd;
69 struct ice_aq_desc desc;
70
71 cmd = &desc.params.lldp_set_event;
72
73 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_lldp_set_mib_change);
74
75 if (!ena_update)
76 cmd->command |= ICE_AQ_LLDP_MIB_UPDATE_DIS;
77
78 return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
79 }
80
81 /**
82 * ice_aq_stop_lldp
83 * @hw: pointer to the HW struct
84 * @shutdown_lldp_agent: True if LLDP Agent needs to be Shutdown
85 * False if LLDP Agent needs to be Stopped
86 * @persist: True if Stop/Shutdown of LLDP Agent needs to be persistent across
87 * reboots
88 * @cd: pointer to command details structure or NULL
89 *
90 * Stop or Shutdown the embedded LLDP Agent (0x0A05)
91 */
92 enum ice_status
ice_aq_stop_lldp(struct ice_hw * hw,bool shutdown_lldp_agent,bool persist,struct ice_sq_cd * cd)93 ice_aq_stop_lldp(struct ice_hw *hw, bool shutdown_lldp_agent, bool persist,
94 struct ice_sq_cd *cd)
95 {
96 struct ice_aqc_lldp_stop *cmd;
97 struct ice_aq_desc desc;
98
99 cmd = &desc.params.lldp_stop;
100
101 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_lldp_stop);
102
103 if (shutdown_lldp_agent)
104 cmd->command |= ICE_AQ_LLDP_AGENT_SHUTDOWN;
105
106 if (persist)
107 cmd->command |= ICE_AQ_LLDP_AGENT_PERSIST_DIS;
108
109 return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
110 }
111
112 /**
113 * ice_aq_start_lldp
114 * @hw: pointer to the HW struct
115 * @persist: True if Start of LLDP Agent needs to be persistent across reboots
116 * @cd: pointer to command details structure or NULL
117 *
118 * Start the embedded LLDP Agent on all ports. (0x0A06)
119 */
120 enum ice_status
ice_aq_start_lldp(struct ice_hw * hw,bool persist,struct ice_sq_cd * cd)121 ice_aq_start_lldp(struct ice_hw *hw, bool persist, struct ice_sq_cd *cd)
122 {
123 struct ice_aqc_lldp_start *cmd;
124 struct ice_aq_desc desc;
125
126 cmd = &desc.params.lldp_start;
127
128 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_lldp_start);
129
130 cmd->command = ICE_AQ_LLDP_AGENT_START;
131
132 if (persist)
133 cmd->command |= ICE_AQ_LLDP_AGENT_PERSIST_ENA;
134
135 return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
136 }
137
138 /**
139 * ice_get_dcbx_status
140 * @hw: pointer to the HW struct
141 *
142 * Get the DCBX status from the Firmware
143 */
ice_get_dcbx_status(struct ice_hw * hw)144 static u8 ice_get_dcbx_status(struct ice_hw *hw)
145 {
146 u32 reg;
147
148 reg = rd32(hw, PRTDCB_GENS);
149 return (u8)((reg & PRTDCB_GENS_DCBX_STATUS_M) >>
150 PRTDCB_GENS_DCBX_STATUS_S);
151 }
152
153 /**
154 * ice_parse_ieee_ets_common_tlv
155 * @buf: Data buffer to be parsed for ETS CFG/REC data
156 * @ets_cfg: Container to store parsed data
157 *
158 * Parses the common data of IEEE 802.1Qaz ETS CFG/REC TLV
159 */
160 static void
ice_parse_ieee_ets_common_tlv(u8 * buf,struct ice_dcb_ets_cfg * ets_cfg)161 ice_parse_ieee_ets_common_tlv(u8 *buf, struct ice_dcb_ets_cfg *ets_cfg)
162 {
163 u8 offset = 0;
164 int i;
165
166 /* Priority Assignment Table (4 octets)
167 * Octets:| 1 | 2 | 3 | 4 |
168 * -----------------------------------------
169 * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
170 * -----------------------------------------
171 * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0|
172 * -----------------------------------------
173 */
174 for (i = 0; i < 4; i++) {
175 ets_cfg->prio_table[i * 2] =
176 ((buf[offset] & ICE_IEEE_ETS_PRIO_1_M) >>
177 ICE_IEEE_ETS_PRIO_1_S);
178 ets_cfg->prio_table[i * 2 + 1] =
179 ((buf[offset] & ICE_IEEE_ETS_PRIO_0_M) >>
180 ICE_IEEE_ETS_PRIO_0_S);
181 offset++;
182 }
183
184 /* TC Bandwidth Table (8 octets)
185 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
186 * ---------------------------------
187 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
188 * ---------------------------------
189 *
190 * TSA Assignment Table (8 octets)
191 * Octets:| 9 | 10| 11| 12| 13| 14| 15| 16|
192 * ---------------------------------
193 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
194 * ---------------------------------
195 */
196 ice_for_each_traffic_class(i) {
197 ets_cfg->tcbwtable[i] = buf[offset];
198 ets_cfg->tsatable[i] = buf[ICE_MAX_TRAFFIC_CLASS + offset++];
199 }
200 }
201
202 /**
203 * ice_parse_ieee_etscfg_tlv
204 * @tlv: IEEE 802.1Qaz ETS CFG TLV
205 * @dcbcfg: Local store to update ETS CFG data
206 *
207 * Parses IEEE 802.1Qaz ETS CFG TLV
208 */
209 static void
ice_parse_ieee_etscfg_tlv(struct ice_lldp_org_tlv * tlv,struct ice_dcbx_cfg * dcbcfg)210 ice_parse_ieee_etscfg_tlv(struct ice_lldp_org_tlv *tlv,
211 struct ice_dcbx_cfg *dcbcfg)
212 {
213 struct ice_dcb_ets_cfg *etscfg;
214 u8 *buf = tlv->tlvinfo;
215
216 /* First Octet post subtype
217 * --------------------------
218 * |will-|CBS | Re- | Max |
219 * |ing | |served| TCs |
220 * --------------------------
221 * |1bit | 1bit|3 bits|3bits|
222 */
223 etscfg = &dcbcfg->etscfg;
224 etscfg->willing = ((buf[0] & ICE_IEEE_ETS_WILLING_M) >>
225 ICE_IEEE_ETS_WILLING_S);
226 etscfg->cbs = ((buf[0] & ICE_IEEE_ETS_CBS_M) >> ICE_IEEE_ETS_CBS_S);
227 etscfg->maxtcs = ((buf[0] & ICE_IEEE_ETS_MAXTC_M) >>
228 ICE_IEEE_ETS_MAXTC_S);
229
230 /* Begin parsing at Priority Assignment Table (offset 1 in buf) */
231 ice_parse_ieee_ets_common_tlv(&buf[1], etscfg);
232 }
233
234 /**
235 * ice_parse_ieee_etsrec_tlv
236 * @tlv: IEEE 802.1Qaz ETS REC TLV
237 * @dcbcfg: Local store to update ETS REC data
238 *
239 * Parses IEEE 802.1Qaz ETS REC TLV
240 */
241 static void
ice_parse_ieee_etsrec_tlv(struct ice_lldp_org_tlv * tlv,struct ice_dcbx_cfg * dcbcfg)242 ice_parse_ieee_etsrec_tlv(struct ice_lldp_org_tlv *tlv,
243 struct ice_dcbx_cfg *dcbcfg)
244 {
245 u8 *buf = tlv->tlvinfo;
246
247 /* Begin parsing at Priority Assignment Table (offset 1 in buf) */
248 ice_parse_ieee_ets_common_tlv(&buf[1], &dcbcfg->etsrec);
249 }
250
251 /**
252 * ice_parse_ieee_pfccfg_tlv
253 * @tlv: IEEE 802.1Qaz PFC CFG TLV
254 * @dcbcfg: Local store to update PFC CFG data
255 *
256 * Parses IEEE 802.1Qaz PFC CFG TLV
257 */
258 static void
ice_parse_ieee_pfccfg_tlv(struct ice_lldp_org_tlv * tlv,struct ice_dcbx_cfg * dcbcfg)259 ice_parse_ieee_pfccfg_tlv(struct ice_lldp_org_tlv *tlv,
260 struct ice_dcbx_cfg *dcbcfg)
261 {
262 u8 *buf = tlv->tlvinfo;
263
264 /* ----------------------------------------
265 * |will-|MBC | Re- | PFC | PFC Enable |
266 * |ing | |served| cap | |
267 * -----------------------------------------
268 * |1bit | 1bit|2 bits|4bits| 1 octet |
269 */
270 dcbcfg->pfc.willing = ((buf[0] & ICE_IEEE_PFC_WILLING_M) >>
271 ICE_IEEE_PFC_WILLING_S);
272 dcbcfg->pfc.mbc = ((buf[0] & ICE_IEEE_PFC_MBC_M) >> ICE_IEEE_PFC_MBC_S);
273 dcbcfg->pfc.pfccap = ((buf[0] & ICE_IEEE_PFC_CAP_M) >>
274 ICE_IEEE_PFC_CAP_S);
275 dcbcfg->pfc.pfcena = buf[1];
276 }
277
278 /**
279 * ice_parse_ieee_app_tlv
280 * @tlv: IEEE 802.1Qaz APP TLV
281 * @dcbcfg: Local store to update APP PRIO data
282 *
283 * Parses IEEE 802.1Qaz APP PRIO TLV
284 */
285 static void
ice_parse_ieee_app_tlv(struct ice_lldp_org_tlv * tlv,struct ice_dcbx_cfg * dcbcfg)286 ice_parse_ieee_app_tlv(struct ice_lldp_org_tlv *tlv,
287 struct ice_dcbx_cfg *dcbcfg)
288 {
289 u16 offset = 0;
290 u16 typelen;
291 int i = 0;
292 u16 len;
293 u8 *buf;
294
295 typelen = ntohs(tlv->typelen);
296 len = ((typelen & ICE_LLDP_TLV_LEN_M) >> ICE_LLDP_TLV_LEN_S);
297 buf = tlv->tlvinfo;
298
299 /* Removing sizeof(ouisubtype) and reserved byte from len.
300 * Remaining len div 3 is number of APP TLVs.
301 */
302 len -= (sizeof(tlv->ouisubtype) + 1);
303
304 /* Move offset to App Priority Table */
305 offset++;
306
307 /* Application Priority Table (3 octets)
308 * Octets:| 1 | 2 | 3 |
309 * -----------------------------------------
310 * |Priority|Rsrvd| Sel | Protocol ID |
311 * -----------------------------------------
312 * Bits:|23 21|20 19|18 16|15 0|
313 * -----------------------------------------
314 */
315 while (offset < len) {
316 dcbcfg->app[i].priority = ((buf[offset] &
317 ICE_IEEE_APP_PRIO_M) >>
318 ICE_IEEE_APP_PRIO_S);
319 dcbcfg->app[i].selector = ((buf[offset] &
320 ICE_IEEE_APP_SEL_M) >>
321 ICE_IEEE_APP_SEL_S);
322 dcbcfg->app[i].prot_id = (buf[offset + 1] << 0x8) |
323 buf[offset + 2];
324 /* Move to next app */
325 offset += 3;
326 i++;
327 if (i >= ICE_DCBX_MAX_APPS)
328 break;
329 }
330
331 dcbcfg->numapps = i;
332 }
333
334 /**
335 * ice_parse_ieee_tlv
336 * @tlv: IEEE 802.1Qaz TLV
337 * @dcbcfg: Local store to update ETS REC data
338 *
339 * Get the TLV subtype and send it to parsing function
340 * based on the subtype value
341 */
342 static void
ice_parse_ieee_tlv(struct ice_lldp_org_tlv * tlv,struct ice_dcbx_cfg * dcbcfg)343 ice_parse_ieee_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg)
344 {
345 u32 ouisubtype;
346 u8 subtype;
347
348 ouisubtype = ntohl(tlv->ouisubtype);
349 subtype = (u8)((ouisubtype & ICE_LLDP_TLV_SUBTYPE_M) >>
350 ICE_LLDP_TLV_SUBTYPE_S);
351 switch (subtype) {
352 case ICE_IEEE_SUBTYPE_ETS_CFG:
353 ice_parse_ieee_etscfg_tlv(tlv, dcbcfg);
354 break;
355 case ICE_IEEE_SUBTYPE_ETS_REC:
356 ice_parse_ieee_etsrec_tlv(tlv, dcbcfg);
357 break;
358 case ICE_IEEE_SUBTYPE_PFC_CFG:
359 ice_parse_ieee_pfccfg_tlv(tlv, dcbcfg);
360 break;
361 case ICE_IEEE_SUBTYPE_APP_PRI:
362 ice_parse_ieee_app_tlv(tlv, dcbcfg);
363 break;
364 default:
365 break;
366 }
367 }
368
369 /**
370 * ice_parse_cee_pgcfg_tlv
371 * @tlv: CEE DCBX PG CFG TLV
372 * @dcbcfg: Local store to update ETS CFG data
373 *
374 * Parses CEE DCBX PG CFG TLV
375 */
376 static void
ice_parse_cee_pgcfg_tlv(struct ice_cee_feat_tlv * tlv,struct ice_dcbx_cfg * dcbcfg)377 ice_parse_cee_pgcfg_tlv(struct ice_cee_feat_tlv *tlv,
378 struct ice_dcbx_cfg *dcbcfg)
379 {
380 struct ice_dcb_ets_cfg *etscfg;
381 u8 *buf = tlv->tlvinfo;
382 u16 offset = 0;
383 int i;
384
385 etscfg = &dcbcfg->etscfg;
386
387 if (tlv->en_will_err & ICE_CEE_FEAT_TLV_WILLING_M)
388 etscfg->willing = 1;
389
390 etscfg->cbs = 0;
391 /* Priority Group Table (4 octets)
392 * Octets:| 1 | 2 | 3 | 4 |
393 * -----------------------------------------
394 * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
395 * -----------------------------------------
396 * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0|
397 * -----------------------------------------
398 */
399 for (i = 0; i < 4; i++) {
400 etscfg->prio_table[i * 2] =
401 ((buf[offset] & ICE_CEE_PGID_PRIO_1_M) >>
402 ICE_CEE_PGID_PRIO_1_S);
403 etscfg->prio_table[i * 2 + 1] =
404 ((buf[offset] & ICE_CEE_PGID_PRIO_0_M) >>
405 ICE_CEE_PGID_PRIO_0_S);
406 offset++;
407 }
408
409 /* PG Percentage Table (8 octets)
410 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
411 * ---------------------------------
412 * |pg0|pg1|pg2|pg3|pg4|pg5|pg6|pg7|
413 * ---------------------------------
414 */
415 ice_for_each_traffic_class(i) {
416 etscfg->tcbwtable[i] = buf[offset++];
417
418 if (etscfg->prio_table[i] == ICE_CEE_PGID_STRICT)
419 dcbcfg->etscfg.tsatable[i] = ICE_IEEE_TSA_STRICT;
420 else
421 dcbcfg->etscfg.tsatable[i] = ICE_IEEE_TSA_ETS;
422 }
423
424 /* Number of TCs supported (1 octet) */
425 etscfg->maxtcs = buf[offset];
426 }
427
428 /**
429 * ice_parse_cee_pfccfg_tlv
430 * @tlv: CEE DCBX PFC CFG TLV
431 * @dcbcfg: Local store to update PFC CFG data
432 *
433 * Parses CEE DCBX PFC CFG TLV
434 */
435 static void
ice_parse_cee_pfccfg_tlv(struct ice_cee_feat_tlv * tlv,struct ice_dcbx_cfg * dcbcfg)436 ice_parse_cee_pfccfg_tlv(struct ice_cee_feat_tlv *tlv,
437 struct ice_dcbx_cfg *dcbcfg)
438 {
439 u8 *buf = tlv->tlvinfo;
440
441 if (tlv->en_will_err & ICE_CEE_FEAT_TLV_WILLING_M)
442 dcbcfg->pfc.willing = 1;
443
444 /* ------------------------
445 * | PFC Enable | PFC TCs |
446 * ------------------------
447 * | 1 octet | 1 octet |
448 */
449 dcbcfg->pfc.pfcena = buf[0];
450 dcbcfg->pfc.pfccap = buf[1];
451 }
452
453 /**
454 * ice_parse_cee_app_tlv
455 * @tlv: CEE DCBX APP TLV
456 * @dcbcfg: Local store to update APP PRIO data
457 *
458 * Parses CEE DCBX APP PRIO TLV
459 */
460 static void
ice_parse_cee_app_tlv(struct ice_cee_feat_tlv * tlv,struct ice_dcbx_cfg * dcbcfg)461 ice_parse_cee_app_tlv(struct ice_cee_feat_tlv *tlv, struct ice_dcbx_cfg *dcbcfg)
462 {
463 u16 len, typelen, offset = 0;
464 struct ice_cee_app_prio *app;
465 u8 i;
466
467 typelen = ntohs(tlv->hdr.typelen);
468 len = ((typelen & ICE_LLDP_TLV_LEN_M) >> ICE_LLDP_TLV_LEN_S);
469
470 dcbcfg->numapps = len / sizeof(*app);
471 if (!dcbcfg->numapps)
472 return;
473 if (dcbcfg->numapps > ICE_DCBX_MAX_APPS)
474 dcbcfg->numapps = ICE_DCBX_MAX_APPS;
475
476 for (i = 0; i < dcbcfg->numapps; i++) {
477 u8 up, selector;
478
479 app = (struct ice_cee_app_prio *)(tlv->tlvinfo + offset);
480 for (up = 0; up < ICE_MAX_USER_PRIORITY; up++)
481 if (app->prio_map & BIT(up))
482 break;
483
484 dcbcfg->app[i].priority = up;
485
486 /* Get Selector from lower 2 bits, and convert to IEEE */
487 selector = (app->upper_oui_sel & ICE_CEE_APP_SELECTOR_M);
488 switch (selector) {
489 case ICE_CEE_APP_SEL_ETHTYPE:
490 dcbcfg->app[i].selector = ICE_APP_SEL_ETHTYPE;
491 break;
492 case ICE_CEE_APP_SEL_TCPIP:
493 dcbcfg->app[i].selector = ICE_APP_SEL_TCPIP;
494 break;
495 default:
496 /* Keep selector as it is for unknown types */
497 dcbcfg->app[i].selector = selector;
498 }
499
500 dcbcfg->app[i].prot_id = ntohs(app->protocol);
501 /* Move to next app */
502 offset += sizeof(*app);
503 }
504 }
505
506 /**
507 * ice_parse_cee_tlv
508 * @tlv: CEE DCBX TLV
509 * @dcbcfg: Local store to update DCBX config data
510 *
511 * Get the TLV subtype and send it to parsing function
512 * based on the subtype value
513 */
514 static void
ice_parse_cee_tlv(struct ice_lldp_org_tlv * tlv,struct ice_dcbx_cfg * dcbcfg)515 ice_parse_cee_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg)
516 {
517 struct ice_cee_feat_tlv *sub_tlv;
518 u8 subtype, feat_tlv_count = 0;
519 u16 len, tlvlen, typelen;
520 u32 ouisubtype;
521
522 ouisubtype = ntohl(tlv->ouisubtype);
523 subtype = (u8)((ouisubtype & ICE_LLDP_TLV_SUBTYPE_M) >>
524 ICE_LLDP_TLV_SUBTYPE_S);
525 /* Return if not CEE DCBX */
526 if (subtype != ICE_CEE_DCBX_TYPE)
527 return;
528
529 typelen = ntohs(tlv->typelen);
530 tlvlen = ((typelen & ICE_LLDP_TLV_LEN_M) >> ICE_LLDP_TLV_LEN_S);
531 len = sizeof(tlv->typelen) + sizeof(ouisubtype) +
532 sizeof(struct ice_cee_ctrl_tlv);
533 /* Return if no CEE DCBX Feature TLVs */
534 if (tlvlen <= len)
535 return;
536
537 sub_tlv = (struct ice_cee_feat_tlv *)((char *)tlv + len);
538 while (feat_tlv_count < ICE_CEE_MAX_FEAT_TYPE) {
539 u16 sublen;
540
541 typelen = ntohs(sub_tlv->hdr.typelen);
542 sublen = ((typelen & ICE_LLDP_TLV_LEN_M) >> ICE_LLDP_TLV_LEN_S);
543 subtype = (u8)((typelen & ICE_LLDP_TLV_TYPE_M) >>
544 ICE_LLDP_TLV_TYPE_S);
545 switch (subtype) {
546 case ICE_CEE_SUBTYPE_PG_CFG:
547 ice_parse_cee_pgcfg_tlv(sub_tlv, dcbcfg);
548 break;
549 case ICE_CEE_SUBTYPE_PFC_CFG:
550 ice_parse_cee_pfccfg_tlv(sub_tlv, dcbcfg);
551 break;
552 case ICE_CEE_SUBTYPE_APP_PRI:
553 ice_parse_cee_app_tlv(sub_tlv, dcbcfg);
554 break;
555 default:
556 return; /* Invalid Sub-type return */
557 }
558 feat_tlv_count++;
559 /* Move to next sub TLV */
560 sub_tlv = (struct ice_cee_feat_tlv *)
561 ((char *)sub_tlv + sizeof(sub_tlv->hdr.typelen) +
562 sublen);
563 }
564 }
565
566 /**
567 * ice_parse_org_tlv
568 * @tlv: Organization specific TLV
569 * @dcbcfg: Local store to update ETS REC data
570 *
571 * Currently only IEEE 802.1Qaz TLV is supported, all others
572 * will be returned
573 */
574 static void
ice_parse_org_tlv(struct ice_lldp_org_tlv * tlv,struct ice_dcbx_cfg * dcbcfg)575 ice_parse_org_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg)
576 {
577 u32 ouisubtype;
578 u32 oui;
579
580 ouisubtype = ntohl(tlv->ouisubtype);
581 oui = ((ouisubtype & ICE_LLDP_TLV_OUI_M) >> ICE_LLDP_TLV_OUI_S);
582 switch (oui) {
583 case ICE_IEEE_8021QAZ_OUI:
584 ice_parse_ieee_tlv(tlv, dcbcfg);
585 break;
586 case ICE_CEE_DCBX_OUI:
587 ice_parse_cee_tlv(tlv, dcbcfg);
588 break;
589 default:
590 break;
591 }
592 }
593
594 /**
595 * ice_lldp_to_dcb_cfg
596 * @lldpmib: LLDPDU to be parsed
597 * @dcbcfg: store for LLDPDU data
598 *
599 * Parse DCB configuration from the LLDPDU
600 */
601 static enum ice_status
ice_lldp_to_dcb_cfg(u8 * lldpmib,struct ice_dcbx_cfg * dcbcfg)602 ice_lldp_to_dcb_cfg(u8 *lldpmib, struct ice_dcbx_cfg *dcbcfg)
603 {
604 struct ice_lldp_org_tlv *tlv;
605 enum ice_status ret = 0;
606 u16 offset = 0;
607 u16 typelen;
608 u16 type;
609 u16 len;
610
611 if (!lldpmib || !dcbcfg)
612 return ICE_ERR_PARAM;
613
614 /* set to the start of LLDPDU */
615 lldpmib += ETH_HLEN;
616 tlv = (struct ice_lldp_org_tlv *)lldpmib;
617 while (1) {
618 typelen = ntohs(tlv->typelen);
619 type = ((typelen & ICE_LLDP_TLV_TYPE_M) >> ICE_LLDP_TLV_TYPE_S);
620 len = ((typelen & ICE_LLDP_TLV_LEN_M) >> ICE_LLDP_TLV_LEN_S);
621 offset += sizeof(typelen) + len;
622
623 /* END TLV or beyond LLDPDU size */
624 if (type == ICE_TLV_TYPE_END || offset > ICE_LLDPDU_SIZE)
625 break;
626
627 switch (type) {
628 case ICE_TLV_TYPE_ORG:
629 ice_parse_org_tlv(tlv, dcbcfg);
630 break;
631 default:
632 break;
633 }
634
635 /* Move to next TLV */
636 tlv = (struct ice_lldp_org_tlv *)
637 ((char *)tlv + sizeof(tlv->typelen) + len);
638 }
639
640 return ret;
641 }
642
643 /**
644 * ice_aq_get_dcb_cfg
645 * @hw: pointer to the HW struct
646 * @mib_type: MIB type for the query
647 * @bridgetype: bridge type for the query (remote)
648 * @dcbcfg: store for LLDPDU data
649 *
650 * Query DCB configuration from the firmware
651 */
652 enum ice_status
ice_aq_get_dcb_cfg(struct ice_hw * hw,u8 mib_type,u8 bridgetype,struct ice_dcbx_cfg * dcbcfg)653 ice_aq_get_dcb_cfg(struct ice_hw *hw, u8 mib_type, u8 bridgetype,
654 struct ice_dcbx_cfg *dcbcfg)
655 {
656 enum ice_status ret;
657 u8 *lldpmib;
658
659 /* Allocate the LLDPDU */
660 lldpmib = devm_kzalloc(ice_hw_to_dev(hw), ICE_LLDPDU_SIZE, GFP_KERNEL);
661 if (!lldpmib)
662 return ICE_ERR_NO_MEMORY;
663
664 ret = ice_aq_get_lldp_mib(hw, bridgetype, mib_type, (void *)lldpmib,
665 ICE_LLDPDU_SIZE, NULL, NULL, NULL);
666
667 if (!ret)
668 /* Parse LLDP MIB to get DCB configuration */
669 ret = ice_lldp_to_dcb_cfg(lldpmib, dcbcfg);
670
671 devm_kfree(ice_hw_to_dev(hw), lldpmib);
672
673 return ret;
674 }
675
676 /**
677 * ice_aq_start_stop_dcbx - Start/Stop DCBX service in FW
678 * @hw: pointer to the HW struct
679 * @start_dcbx_agent: True if DCBX Agent needs to be started
680 * False if DCBX Agent needs to be stopped
681 * @dcbx_agent_status: FW indicates back the DCBX agent status
682 * True if DCBX Agent is active
683 * False if DCBX Agent is stopped
684 * @cd: pointer to command details structure or NULL
685 *
686 * Start/Stop the embedded dcbx Agent. In case that this wrapper function
687 * returns ICE_SUCCESS, caller will need to check if FW returns back the same
688 * value as stated in dcbx_agent_status, and react accordingly. (0x0A09)
689 */
690 enum ice_status
ice_aq_start_stop_dcbx(struct ice_hw * hw,bool start_dcbx_agent,bool * dcbx_agent_status,struct ice_sq_cd * cd)691 ice_aq_start_stop_dcbx(struct ice_hw *hw, bool start_dcbx_agent,
692 bool *dcbx_agent_status, struct ice_sq_cd *cd)
693 {
694 struct ice_aqc_lldp_stop_start_specific_agent *cmd;
695 enum ice_status status;
696 struct ice_aq_desc desc;
697 u16 opcode;
698
699 cmd = &desc.params.lldp_agent_ctrl;
700
701 opcode = ice_aqc_opc_lldp_stop_start_specific_agent;
702
703 ice_fill_dflt_direct_cmd_desc(&desc, opcode);
704
705 if (start_dcbx_agent)
706 cmd->command = ICE_AQC_START_STOP_AGENT_START_DCBX;
707
708 status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
709
710 *dcbx_agent_status = false;
711
712 if (!status &&
713 cmd->command == ICE_AQC_START_STOP_AGENT_START_DCBX)
714 *dcbx_agent_status = true;
715
716 return status;
717 }
718
719 /**
720 * ice_aq_get_cee_dcb_cfg
721 * @hw: pointer to the HW struct
722 * @buff: response buffer that stores CEE operational configuration
723 * @cd: pointer to command details structure or NULL
724 *
725 * Get CEE DCBX mode operational configuration from firmware (0x0A07)
726 */
727 static enum ice_status
ice_aq_get_cee_dcb_cfg(struct ice_hw * hw,struct ice_aqc_get_cee_dcb_cfg_resp * buff,struct ice_sq_cd * cd)728 ice_aq_get_cee_dcb_cfg(struct ice_hw *hw,
729 struct ice_aqc_get_cee_dcb_cfg_resp *buff,
730 struct ice_sq_cd *cd)
731 {
732 struct ice_aq_desc desc;
733
734 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_cee_dcb_cfg);
735
736 return ice_aq_send_cmd(hw, &desc, (void *)buff, sizeof(*buff), cd);
737 }
738
739 /**
740 * ice_aq_set_pfc_mode - Set PFC mode
741 * @hw: pointer to the HW struct
742 * @pfc_mode: value of PFC mode to set
743 * @cd: pointer to command details structure or NULL
744 *
745 * This AQ call configures the PFC mode to DSCP-based PFC mode or
746 * VLAN-based PFC (0x0303)
747 */
ice_aq_set_pfc_mode(struct ice_hw * hw,u8 pfc_mode,struct ice_sq_cd * cd)748 int ice_aq_set_pfc_mode(struct ice_hw *hw, u8 pfc_mode, struct ice_sq_cd *cd)
749 {
750 struct ice_aqc_set_query_pfc_mode *cmd;
751 struct ice_aq_desc desc;
752 enum ice_status status;
753
754 if (pfc_mode > ICE_AQC_PFC_DSCP_BASED_PFC)
755 return -EINVAL;
756
757 cmd = &desc.params.set_query_pfc_mode;
758
759 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_pfc_mode);
760
761 cmd->pfc_mode = pfc_mode;
762
763 status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
764 if (status)
765 return ice_status_to_errno(status);
766
767 /* FW will write the PFC mode set back into cmd->pfc_mode, but if DCB is
768 * disabled, FW will write back 0 to cmd->pfc_mode. After the AQ has
769 * been executed, check if cmd->pfc_mode is what was requested. If not,
770 * return an error.
771 */
772 if (cmd->pfc_mode != pfc_mode)
773 return -EOPNOTSUPP;
774
775 return 0;
776 }
777
778 /**
779 * ice_cee_to_dcb_cfg
780 * @cee_cfg: pointer to CEE configuration struct
781 * @pi: port information structure
782 *
783 * Convert CEE configuration from firmware to DCB configuration
784 */
785 static void
ice_cee_to_dcb_cfg(struct ice_aqc_get_cee_dcb_cfg_resp * cee_cfg,struct ice_port_info * pi)786 ice_cee_to_dcb_cfg(struct ice_aqc_get_cee_dcb_cfg_resp *cee_cfg,
787 struct ice_port_info *pi)
788 {
789 u32 status, tlv_status = le32_to_cpu(cee_cfg->tlv_status);
790 u32 ice_aqc_cee_status_mask, ice_aqc_cee_status_shift, j;
791 u8 i, err, sync, oper, app_index, ice_app_sel_type;
792 u16 app_prio = le16_to_cpu(cee_cfg->oper_app_prio);
793 u16 ice_aqc_cee_app_mask, ice_aqc_cee_app_shift;
794 struct ice_dcbx_cfg *cmp_dcbcfg, *dcbcfg;
795 u16 ice_app_prot_id_type;
796
797 dcbcfg = &pi->qos_cfg.local_dcbx_cfg;
798 dcbcfg->dcbx_mode = ICE_DCBX_MODE_CEE;
799 dcbcfg->tlv_status = tlv_status;
800
801 /* CEE PG data */
802 dcbcfg->etscfg.maxtcs = cee_cfg->oper_num_tc;
803
804 /* Note that the FW creates the oper_prio_tc nibbles reversed
805 * from those in the CEE Priority Group sub-TLV.
806 */
807 for (i = 0; i < ICE_MAX_TRAFFIC_CLASS / 2; i++) {
808 dcbcfg->etscfg.prio_table[i * 2] =
809 ((cee_cfg->oper_prio_tc[i] & ICE_CEE_PGID_PRIO_0_M) >>
810 ICE_CEE_PGID_PRIO_0_S);
811 dcbcfg->etscfg.prio_table[i * 2 + 1] =
812 ((cee_cfg->oper_prio_tc[i] & ICE_CEE_PGID_PRIO_1_M) >>
813 ICE_CEE_PGID_PRIO_1_S);
814 }
815
816 ice_for_each_traffic_class(i) {
817 dcbcfg->etscfg.tcbwtable[i] = cee_cfg->oper_tc_bw[i];
818
819 if (dcbcfg->etscfg.prio_table[i] == ICE_CEE_PGID_STRICT) {
820 /* Map it to next empty TC */
821 dcbcfg->etscfg.prio_table[i] = cee_cfg->oper_num_tc - 1;
822 dcbcfg->etscfg.tsatable[i] = ICE_IEEE_TSA_STRICT;
823 } else {
824 dcbcfg->etscfg.tsatable[i] = ICE_IEEE_TSA_ETS;
825 }
826 }
827
828 /* CEE PFC data */
829 dcbcfg->pfc.pfcena = cee_cfg->oper_pfc_en;
830 dcbcfg->pfc.pfccap = ICE_MAX_TRAFFIC_CLASS;
831
832 /* CEE APP TLV data */
833 if (dcbcfg->app_mode == ICE_DCBX_APPS_NON_WILLING)
834 cmp_dcbcfg = &pi->qos_cfg.desired_dcbx_cfg;
835 else
836 cmp_dcbcfg = &pi->qos_cfg.remote_dcbx_cfg;
837
838 app_index = 0;
839 for (i = 0; i < 3; i++) {
840 if (i == 0) {
841 /* FCoE APP */
842 ice_aqc_cee_status_mask = ICE_AQC_CEE_FCOE_STATUS_M;
843 ice_aqc_cee_status_shift = ICE_AQC_CEE_FCOE_STATUS_S;
844 ice_aqc_cee_app_mask = ICE_AQC_CEE_APP_FCOE_M;
845 ice_aqc_cee_app_shift = ICE_AQC_CEE_APP_FCOE_S;
846 ice_app_sel_type = ICE_APP_SEL_ETHTYPE;
847 ice_app_prot_id_type = ETH_P_FCOE;
848 } else if (i == 1) {
849 /* iSCSI APP */
850 ice_aqc_cee_status_mask = ICE_AQC_CEE_ISCSI_STATUS_M;
851 ice_aqc_cee_status_shift = ICE_AQC_CEE_ISCSI_STATUS_S;
852 ice_aqc_cee_app_mask = ICE_AQC_CEE_APP_ISCSI_M;
853 ice_aqc_cee_app_shift = ICE_AQC_CEE_APP_ISCSI_S;
854 ice_app_sel_type = ICE_APP_SEL_TCPIP;
855 ice_app_prot_id_type = ISCSI_LISTEN_PORT;
856
857 for (j = 0; j < cmp_dcbcfg->numapps; j++) {
858 u16 prot_id = cmp_dcbcfg->app[j].prot_id;
859 u8 sel = cmp_dcbcfg->app[j].selector;
860
861 if (sel == ICE_APP_SEL_TCPIP &&
862 (prot_id == ISCSI_LISTEN_PORT ||
863 prot_id == ICE_APP_PROT_ID_ISCSI_860)) {
864 ice_app_prot_id_type = prot_id;
865 break;
866 }
867 }
868 } else {
869 /* FIP APP */
870 ice_aqc_cee_status_mask = ICE_AQC_CEE_FIP_STATUS_M;
871 ice_aqc_cee_status_shift = ICE_AQC_CEE_FIP_STATUS_S;
872 ice_aqc_cee_app_mask = ICE_AQC_CEE_APP_FIP_M;
873 ice_aqc_cee_app_shift = ICE_AQC_CEE_APP_FIP_S;
874 ice_app_sel_type = ICE_APP_SEL_ETHTYPE;
875 ice_app_prot_id_type = ETH_P_FIP;
876 }
877
878 status = (tlv_status & ice_aqc_cee_status_mask) >>
879 ice_aqc_cee_status_shift;
880 err = (status & ICE_TLV_STATUS_ERR) ? 1 : 0;
881 sync = (status & ICE_TLV_STATUS_SYNC) ? 1 : 0;
882 oper = (status & ICE_TLV_STATUS_OPER) ? 1 : 0;
883 /* Add FCoE/iSCSI/FIP APP if Error is False and
884 * Oper/Sync is True
885 */
886 if (!err && sync && oper) {
887 dcbcfg->app[app_index].priority =
888 (app_prio & ice_aqc_cee_app_mask) >>
889 ice_aqc_cee_app_shift;
890 dcbcfg->app[app_index].selector = ice_app_sel_type;
891 dcbcfg->app[app_index].prot_id = ice_app_prot_id_type;
892 app_index++;
893 }
894 }
895
896 dcbcfg->numapps = app_index;
897 }
898
899 /**
900 * ice_get_ieee_or_cee_dcb_cfg
901 * @pi: port information structure
902 * @dcbx_mode: mode of DCBX (IEEE or CEE)
903 *
904 * Get IEEE or CEE mode DCB configuration from the Firmware
905 */
906 static enum ice_status
ice_get_ieee_or_cee_dcb_cfg(struct ice_port_info * pi,u8 dcbx_mode)907 ice_get_ieee_or_cee_dcb_cfg(struct ice_port_info *pi, u8 dcbx_mode)
908 {
909 struct ice_dcbx_cfg *dcbx_cfg = NULL;
910 enum ice_status ret;
911
912 if (!pi)
913 return ICE_ERR_PARAM;
914
915 if (dcbx_mode == ICE_DCBX_MODE_IEEE)
916 dcbx_cfg = &pi->qos_cfg.local_dcbx_cfg;
917 else if (dcbx_mode == ICE_DCBX_MODE_CEE)
918 dcbx_cfg = &pi->qos_cfg.desired_dcbx_cfg;
919
920 /* Get Local DCB Config in case of ICE_DCBX_MODE_IEEE
921 * or get CEE DCB Desired Config in case of ICE_DCBX_MODE_CEE
922 */
923 ret = ice_aq_get_dcb_cfg(pi->hw, ICE_AQ_LLDP_MIB_LOCAL,
924 ICE_AQ_LLDP_BRID_TYPE_NEAREST_BRID, dcbx_cfg);
925 if (ret)
926 goto out;
927
928 /* Get Remote DCB Config */
929 dcbx_cfg = &pi->qos_cfg.remote_dcbx_cfg;
930 ret = ice_aq_get_dcb_cfg(pi->hw, ICE_AQ_LLDP_MIB_REMOTE,
931 ICE_AQ_LLDP_BRID_TYPE_NEAREST_BRID, dcbx_cfg);
932 /* Don't treat ENOENT as an error for Remote MIBs */
933 if (pi->hw->adminq.sq_last_status == ICE_AQ_RC_ENOENT)
934 ret = 0;
935
936 out:
937 return ret;
938 }
939
940 /**
941 * ice_get_dcb_cfg
942 * @pi: port information structure
943 *
944 * Get DCB configuration from the Firmware
945 */
ice_get_dcb_cfg(struct ice_port_info * pi)946 enum ice_status ice_get_dcb_cfg(struct ice_port_info *pi)
947 {
948 struct ice_aqc_get_cee_dcb_cfg_resp cee_cfg;
949 struct ice_dcbx_cfg *dcbx_cfg;
950 enum ice_status ret;
951
952 if (!pi)
953 return ICE_ERR_PARAM;
954
955 ret = ice_aq_get_cee_dcb_cfg(pi->hw, &cee_cfg, NULL);
956 if (!ret) {
957 /* CEE mode */
958 ret = ice_get_ieee_or_cee_dcb_cfg(pi, ICE_DCBX_MODE_CEE);
959 ice_cee_to_dcb_cfg(&cee_cfg, pi);
960 } else if (pi->hw->adminq.sq_last_status == ICE_AQ_RC_ENOENT) {
961 /* CEE mode not enabled try querying IEEE data */
962 dcbx_cfg = &pi->qos_cfg.local_dcbx_cfg;
963 dcbx_cfg->dcbx_mode = ICE_DCBX_MODE_IEEE;
964 ret = ice_get_ieee_or_cee_dcb_cfg(pi, ICE_DCBX_MODE_IEEE);
965 }
966
967 return ret;
968 }
969
970 /**
971 * ice_init_dcb
972 * @hw: pointer to the HW struct
973 * @enable_mib_change: enable MIB change event
974 *
975 * Update DCB configuration from the Firmware
976 */
ice_init_dcb(struct ice_hw * hw,bool enable_mib_change)977 enum ice_status ice_init_dcb(struct ice_hw *hw, bool enable_mib_change)
978 {
979 struct ice_qos_cfg *qos_cfg = &hw->port_info->qos_cfg;
980 enum ice_status ret = 0;
981
982 if (!hw->func_caps.common_cap.dcb)
983 return ICE_ERR_NOT_SUPPORTED;
984
985 qos_cfg->is_sw_lldp = true;
986
987 /* Get DCBX status */
988 qos_cfg->dcbx_status = ice_get_dcbx_status(hw);
989
990 if (qos_cfg->dcbx_status == ICE_DCBX_STATUS_DONE ||
991 qos_cfg->dcbx_status == ICE_DCBX_STATUS_IN_PROGRESS ||
992 qos_cfg->dcbx_status == ICE_DCBX_STATUS_NOT_STARTED) {
993 /* Get current DCBX configuration */
994 ret = ice_get_dcb_cfg(hw->port_info);
995 if (ret)
996 return ret;
997 qos_cfg->is_sw_lldp = false;
998 } else if (qos_cfg->dcbx_status == ICE_DCBX_STATUS_DIS) {
999 return ICE_ERR_NOT_READY;
1000 }
1001
1002 /* Configure the LLDP MIB change event */
1003 if (enable_mib_change) {
1004 ret = ice_aq_cfg_lldp_mib_change(hw, true, NULL);
1005 if (ret)
1006 qos_cfg->is_sw_lldp = true;
1007 }
1008
1009 return ret;
1010 }
1011
1012 /**
1013 * ice_cfg_lldp_mib_change
1014 * @hw: pointer to the HW struct
1015 * @ena_mib: enable/disable MIB change event
1016 *
1017 * Configure (disable/enable) MIB
1018 */
ice_cfg_lldp_mib_change(struct ice_hw * hw,bool ena_mib)1019 enum ice_status ice_cfg_lldp_mib_change(struct ice_hw *hw, bool ena_mib)
1020 {
1021 struct ice_qos_cfg *qos_cfg = &hw->port_info->qos_cfg;
1022 enum ice_status ret;
1023
1024 if (!hw->func_caps.common_cap.dcb)
1025 return ICE_ERR_NOT_SUPPORTED;
1026
1027 /* Get DCBX status */
1028 qos_cfg->dcbx_status = ice_get_dcbx_status(hw);
1029
1030 if (qos_cfg->dcbx_status == ICE_DCBX_STATUS_DIS)
1031 return ICE_ERR_NOT_READY;
1032
1033 ret = ice_aq_cfg_lldp_mib_change(hw, ena_mib, NULL);
1034 if (!ret)
1035 qos_cfg->is_sw_lldp = !ena_mib;
1036
1037 return ret;
1038 }
1039
1040 /**
1041 * ice_add_ieee_ets_common_tlv
1042 * @buf: Data buffer to be populated with ice_dcb_ets_cfg data
1043 * @ets_cfg: Container for ice_dcb_ets_cfg data
1044 *
1045 * Populate the TLV buffer with ice_dcb_ets_cfg data
1046 */
1047 static void
ice_add_ieee_ets_common_tlv(u8 * buf,struct ice_dcb_ets_cfg * ets_cfg)1048 ice_add_ieee_ets_common_tlv(u8 *buf, struct ice_dcb_ets_cfg *ets_cfg)
1049 {
1050 u8 priority0, priority1;
1051 u8 offset = 0;
1052 int i;
1053
1054 /* Priority Assignment Table (4 octets)
1055 * Octets:| 1 | 2 | 3 | 4 |
1056 * -----------------------------------------
1057 * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
1058 * -----------------------------------------
1059 * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0|
1060 * -----------------------------------------
1061 */
1062 for (i = 0; i < ICE_MAX_TRAFFIC_CLASS / 2; i++) {
1063 priority0 = ets_cfg->prio_table[i * 2] & 0xF;
1064 priority1 = ets_cfg->prio_table[i * 2 + 1] & 0xF;
1065 buf[offset] = (priority0 << ICE_IEEE_ETS_PRIO_1_S) | priority1;
1066 offset++;
1067 }
1068
1069 /* TC Bandwidth Table (8 octets)
1070 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
1071 * ---------------------------------
1072 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
1073 * ---------------------------------
1074 *
1075 * TSA Assignment Table (8 octets)
1076 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
1077 * ---------------------------------
1078 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
1079 * ---------------------------------
1080 */
1081 ice_for_each_traffic_class(i) {
1082 buf[offset] = ets_cfg->tcbwtable[i];
1083 buf[ICE_MAX_TRAFFIC_CLASS + offset] = ets_cfg->tsatable[i];
1084 offset++;
1085 }
1086 }
1087
1088 /**
1089 * ice_add_ieee_ets_tlv - Prepare ETS TLV in IEEE format
1090 * @tlv: Fill the ETS config data in IEEE format
1091 * @dcbcfg: Local store which holds the DCB Config
1092 *
1093 * Prepare IEEE 802.1Qaz ETS CFG TLV
1094 */
1095 static void
ice_add_ieee_ets_tlv(struct ice_lldp_org_tlv * tlv,struct ice_dcbx_cfg * dcbcfg)1096 ice_add_ieee_ets_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg)
1097 {
1098 struct ice_dcb_ets_cfg *etscfg;
1099 u8 *buf = tlv->tlvinfo;
1100 u8 maxtcwilling = 0;
1101 u32 ouisubtype;
1102 u16 typelen;
1103
1104 typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) |
1105 ICE_IEEE_ETS_TLV_LEN);
1106 tlv->typelen = htons(typelen);
1107
1108 ouisubtype = ((ICE_IEEE_8021QAZ_OUI << ICE_LLDP_TLV_OUI_S) |
1109 ICE_IEEE_SUBTYPE_ETS_CFG);
1110 tlv->ouisubtype = htonl(ouisubtype);
1111
1112 /* First Octet post subtype
1113 * --------------------------
1114 * |will-|CBS | Re- | Max |
1115 * |ing | |served| TCs |
1116 * --------------------------
1117 * |1bit | 1bit|3 bits|3bits|
1118 */
1119 etscfg = &dcbcfg->etscfg;
1120 if (etscfg->willing)
1121 maxtcwilling = BIT(ICE_IEEE_ETS_WILLING_S);
1122 maxtcwilling |= etscfg->maxtcs & ICE_IEEE_ETS_MAXTC_M;
1123 buf[0] = maxtcwilling;
1124
1125 /* Begin adding at Priority Assignment Table (offset 1 in buf) */
1126 ice_add_ieee_ets_common_tlv(&buf[1], etscfg);
1127 }
1128
1129 /**
1130 * ice_add_ieee_etsrec_tlv - Prepare ETS Recommended TLV in IEEE format
1131 * @tlv: Fill ETS Recommended TLV in IEEE format
1132 * @dcbcfg: Local store which holds the DCB Config
1133 *
1134 * Prepare IEEE 802.1Qaz ETS REC TLV
1135 */
1136 static void
ice_add_ieee_etsrec_tlv(struct ice_lldp_org_tlv * tlv,struct ice_dcbx_cfg * dcbcfg)1137 ice_add_ieee_etsrec_tlv(struct ice_lldp_org_tlv *tlv,
1138 struct ice_dcbx_cfg *dcbcfg)
1139 {
1140 struct ice_dcb_ets_cfg *etsrec;
1141 u8 *buf = tlv->tlvinfo;
1142 u32 ouisubtype;
1143 u16 typelen;
1144
1145 typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) |
1146 ICE_IEEE_ETS_TLV_LEN);
1147 tlv->typelen = htons(typelen);
1148
1149 ouisubtype = ((ICE_IEEE_8021QAZ_OUI << ICE_LLDP_TLV_OUI_S) |
1150 ICE_IEEE_SUBTYPE_ETS_REC);
1151 tlv->ouisubtype = htonl(ouisubtype);
1152
1153 etsrec = &dcbcfg->etsrec;
1154
1155 /* First Octet is reserved */
1156 /* Begin adding at Priority Assignment Table (offset 1 in buf) */
1157 ice_add_ieee_ets_common_tlv(&buf[1], etsrec);
1158 }
1159
1160 /**
1161 * ice_add_ieee_pfc_tlv - Prepare PFC TLV in IEEE format
1162 * @tlv: Fill PFC TLV in IEEE format
1163 * @dcbcfg: Local store which holds the PFC CFG data
1164 *
1165 * Prepare IEEE 802.1Qaz PFC CFG TLV
1166 */
1167 static void
ice_add_ieee_pfc_tlv(struct ice_lldp_org_tlv * tlv,struct ice_dcbx_cfg * dcbcfg)1168 ice_add_ieee_pfc_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg)
1169 {
1170 u8 *buf = tlv->tlvinfo;
1171 u32 ouisubtype;
1172 u16 typelen;
1173
1174 typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) |
1175 ICE_IEEE_PFC_TLV_LEN);
1176 tlv->typelen = htons(typelen);
1177
1178 ouisubtype = ((ICE_IEEE_8021QAZ_OUI << ICE_LLDP_TLV_OUI_S) |
1179 ICE_IEEE_SUBTYPE_PFC_CFG);
1180 tlv->ouisubtype = htonl(ouisubtype);
1181
1182 /* ----------------------------------------
1183 * |will-|MBC | Re- | PFC | PFC Enable |
1184 * |ing | |served| cap | |
1185 * -----------------------------------------
1186 * |1bit | 1bit|2 bits|4bits| 1 octet |
1187 */
1188 if (dcbcfg->pfc.willing)
1189 buf[0] = BIT(ICE_IEEE_PFC_WILLING_S);
1190
1191 if (dcbcfg->pfc.mbc)
1192 buf[0] |= BIT(ICE_IEEE_PFC_MBC_S);
1193
1194 buf[0] |= dcbcfg->pfc.pfccap & 0xF;
1195 buf[1] = dcbcfg->pfc.pfcena;
1196 }
1197
1198 /**
1199 * ice_add_ieee_app_pri_tlv - Prepare APP TLV in IEEE format
1200 * @tlv: Fill APP TLV in IEEE format
1201 * @dcbcfg: Local store which holds the APP CFG data
1202 *
1203 * Prepare IEEE 802.1Qaz APP CFG TLV
1204 */
1205 static void
ice_add_ieee_app_pri_tlv(struct ice_lldp_org_tlv * tlv,struct ice_dcbx_cfg * dcbcfg)1206 ice_add_ieee_app_pri_tlv(struct ice_lldp_org_tlv *tlv,
1207 struct ice_dcbx_cfg *dcbcfg)
1208 {
1209 u16 typelen, len, offset = 0;
1210 u8 priority, selector, i = 0;
1211 u8 *buf = tlv->tlvinfo;
1212 u32 ouisubtype;
1213
1214 /* No APP TLVs then just return */
1215 if (dcbcfg->numapps == 0)
1216 return;
1217 ouisubtype = ((ICE_IEEE_8021QAZ_OUI << ICE_LLDP_TLV_OUI_S) |
1218 ICE_IEEE_SUBTYPE_APP_PRI);
1219 tlv->ouisubtype = htonl(ouisubtype);
1220
1221 /* Move offset to App Priority Table */
1222 offset++;
1223 /* Application Priority Table (3 octets)
1224 * Octets:| 1 | 2 | 3 |
1225 * -----------------------------------------
1226 * |Priority|Rsrvd| Sel | Protocol ID |
1227 * -----------------------------------------
1228 * Bits:|23 21|20 19|18 16|15 0|
1229 * -----------------------------------------
1230 */
1231 while (i < dcbcfg->numapps) {
1232 priority = dcbcfg->app[i].priority & 0x7;
1233 selector = dcbcfg->app[i].selector & 0x7;
1234 buf[offset] = (priority << ICE_IEEE_APP_PRIO_S) | selector;
1235 buf[offset + 1] = (dcbcfg->app[i].prot_id >> 0x8) & 0xFF;
1236 buf[offset + 2] = dcbcfg->app[i].prot_id & 0xFF;
1237 /* Move to next app */
1238 offset += 3;
1239 i++;
1240 if (i >= ICE_DCBX_MAX_APPS)
1241 break;
1242 }
1243 /* len includes size of ouisubtype + 1 reserved + 3*numapps */
1244 len = sizeof(tlv->ouisubtype) + 1 + (i * 3);
1245 typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) | (len & 0x1FF));
1246 tlv->typelen = htons(typelen);
1247 }
1248
1249 /**
1250 * ice_add_dscp_up_tlv - Prepare DSCP to UP TLV
1251 * @tlv: location to build the TLV data
1252 * @dcbcfg: location of data to convert to TLV
1253 */
1254 static void
ice_add_dscp_up_tlv(struct ice_lldp_org_tlv * tlv,struct ice_dcbx_cfg * dcbcfg)1255 ice_add_dscp_up_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg)
1256 {
1257 u8 *buf = tlv->tlvinfo;
1258 u32 ouisubtype;
1259 u16 typelen;
1260 int i;
1261
1262 typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) |
1263 ICE_DSCP_UP_TLV_LEN);
1264 tlv->typelen = htons(typelen);
1265
1266 ouisubtype = (u32)((ICE_DSCP_OUI << ICE_LLDP_TLV_OUI_S) |
1267 ICE_DSCP_SUBTYPE_DSCP2UP);
1268 tlv->ouisubtype = htonl(ouisubtype);
1269
1270 /* bytes 0 - 63 - IPv4 DSCP2UP LUT */
1271 for (i = 0; i < ICE_DSCP_NUM_VAL; i++) {
1272 /* IPv4 mapping */
1273 buf[i] = dcbcfg->dscp_map[i];
1274 /* IPv6 mapping */
1275 buf[i + ICE_DSCP_IPV6_OFFSET] = dcbcfg->dscp_map[i];
1276 }
1277
1278 /* byte 64 - IPv4 untagged traffic */
1279 buf[i] = 0;
1280
1281 /* byte 144 - IPv6 untagged traffic */
1282 buf[i + ICE_DSCP_IPV6_OFFSET] = 0;
1283 }
1284
1285 #define ICE_BYTES_PER_TC 8
1286 /**
1287 * ice_add_dscp_enf_tlv - Prepare DSCP Enforcement TLV
1288 * @tlv: location to build the TLV data
1289 */
1290 static void
ice_add_dscp_enf_tlv(struct ice_lldp_org_tlv * tlv)1291 ice_add_dscp_enf_tlv(struct ice_lldp_org_tlv *tlv)
1292 {
1293 u8 *buf = tlv->tlvinfo;
1294 u32 ouisubtype;
1295 u16 typelen;
1296
1297 typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) |
1298 ICE_DSCP_ENF_TLV_LEN);
1299 tlv->typelen = htons(typelen);
1300
1301 ouisubtype = (u32)((ICE_DSCP_OUI << ICE_LLDP_TLV_OUI_S) |
1302 ICE_DSCP_SUBTYPE_ENFORCE);
1303 tlv->ouisubtype = htonl(ouisubtype);
1304
1305 /* Allow all DSCP values to be valid for all TC's (IPv4 and IPv6) */
1306 memset(buf, 0, 2 * (ICE_MAX_TRAFFIC_CLASS * ICE_BYTES_PER_TC));
1307 }
1308
1309 /**
1310 * ice_add_dscp_tc_bw_tlv - Prepare DSCP BW for TC TLV
1311 * @tlv: location to build the TLV data
1312 * @dcbcfg: location of the data to convert to TLV
1313 */
1314 static void
ice_add_dscp_tc_bw_tlv(struct ice_lldp_org_tlv * tlv,struct ice_dcbx_cfg * dcbcfg)1315 ice_add_dscp_tc_bw_tlv(struct ice_lldp_org_tlv *tlv,
1316 struct ice_dcbx_cfg *dcbcfg)
1317 {
1318 struct ice_dcb_ets_cfg *etscfg;
1319 u8 *buf = tlv->tlvinfo;
1320 u32 ouisubtype;
1321 u8 offset = 0;
1322 u16 typelen;
1323 int i;
1324
1325 typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) |
1326 ICE_DSCP_TC_BW_TLV_LEN);
1327 tlv->typelen = htons(typelen);
1328
1329 ouisubtype = (u32)((ICE_DSCP_OUI << ICE_LLDP_TLV_OUI_S) |
1330 ICE_DSCP_SUBTYPE_TCBW);
1331 tlv->ouisubtype = htonl(ouisubtype);
1332
1333 /* First Octect after subtype
1334 * ----------------------------
1335 * | RSV | CBS | RSV | Max TCs |
1336 * | 1b | 1b | 3b | 3b |
1337 * ----------------------------
1338 */
1339 etscfg = &dcbcfg->etscfg;
1340 buf[0] = etscfg->maxtcs & ICE_IEEE_ETS_MAXTC_M;
1341
1342 /* bytes 1 - 4 reserved */
1343 offset = 5;
1344
1345 /* TC BW table
1346 * bytes 0 - 7 for TC 0 - 7
1347 *
1348 * TSA Assignment table
1349 * bytes 8 - 15 for TC 0 - 7
1350 */
1351 for (i = 0; i < ICE_MAX_TRAFFIC_CLASS; i++) {
1352 buf[offset] = etscfg->tcbwtable[i];
1353 buf[offset + ICE_MAX_TRAFFIC_CLASS] = etscfg->tsatable[i];
1354 offset++;
1355 }
1356 }
1357
1358 /**
1359 * ice_add_dscp_pfc_tlv - Prepare DSCP PFC TLV
1360 * @tlv: Fill PFC TLV in IEEE format
1361 * @dcbcfg: Local store which holds the PFC CFG data
1362 */
1363 static void
ice_add_dscp_pfc_tlv(struct ice_lldp_org_tlv * tlv,struct ice_dcbx_cfg * dcbcfg)1364 ice_add_dscp_pfc_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg)
1365 {
1366 u8 *buf = tlv->tlvinfo;
1367 u32 ouisubtype;
1368 u16 typelen;
1369
1370 typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) |
1371 ICE_DSCP_PFC_TLV_LEN);
1372 tlv->typelen = htons(typelen);
1373
1374 ouisubtype = (u32)((ICE_DSCP_OUI << ICE_LLDP_TLV_OUI_S) |
1375 ICE_DSCP_SUBTYPE_PFC);
1376 tlv->ouisubtype = htonl(ouisubtype);
1377
1378 buf[0] = dcbcfg->pfc.pfccap & 0xF;
1379 buf[1] = dcbcfg->pfc.pfcena & 0xF;
1380 }
1381
1382 /**
1383 * ice_add_dcb_tlv - Add all IEEE or DSCP TLVs
1384 * @tlv: Fill TLV data in IEEE format
1385 * @dcbcfg: Local store which holds the DCB Config
1386 * @tlvid: Type of IEEE TLV
1387 *
1388 * Add tlv information
1389 */
1390 static void
ice_add_dcb_tlv(struct ice_lldp_org_tlv * tlv,struct ice_dcbx_cfg * dcbcfg,u16 tlvid)1391 ice_add_dcb_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg,
1392 u16 tlvid)
1393 {
1394 if (dcbcfg->pfc_mode == ICE_QOS_MODE_VLAN) {
1395 switch (tlvid) {
1396 case ICE_IEEE_TLV_ID_ETS_CFG:
1397 ice_add_ieee_ets_tlv(tlv, dcbcfg);
1398 break;
1399 case ICE_IEEE_TLV_ID_ETS_REC:
1400 ice_add_ieee_etsrec_tlv(tlv, dcbcfg);
1401 break;
1402 case ICE_IEEE_TLV_ID_PFC_CFG:
1403 ice_add_ieee_pfc_tlv(tlv, dcbcfg);
1404 break;
1405 case ICE_IEEE_TLV_ID_APP_PRI:
1406 ice_add_ieee_app_pri_tlv(tlv, dcbcfg);
1407 break;
1408 default:
1409 break;
1410 }
1411 } else {
1412 /* pfc_mode == ICE_QOS_MODE_DSCP */
1413 switch (tlvid) {
1414 case ICE_TLV_ID_DSCP_UP:
1415 ice_add_dscp_up_tlv(tlv, dcbcfg);
1416 break;
1417 case ICE_TLV_ID_DSCP_ENF:
1418 ice_add_dscp_enf_tlv(tlv);
1419 break;
1420 case ICE_TLV_ID_DSCP_TC_BW:
1421 ice_add_dscp_tc_bw_tlv(tlv, dcbcfg);
1422 break;
1423 case ICE_TLV_ID_DSCP_TO_PFC:
1424 ice_add_dscp_pfc_tlv(tlv, dcbcfg);
1425 break;
1426 default:
1427 break;
1428 }
1429 }
1430 }
1431
1432 /**
1433 * ice_dcb_cfg_to_lldp - Convert DCB configuration to MIB format
1434 * @lldpmib: pointer to the HW struct
1435 * @miblen: length of LLDP MIB
1436 * @dcbcfg: Local store which holds the DCB Config
1437 *
1438 * Convert the DCB configuration to MIB format
1439 */
1440 static void
ice_dcb_cfg_to_lldp(u8 * lldpmib,u16 * miblen,struct ice_dcbx_cfg * dcbcfg)1441 ice_dcb_cfg_to_lldp(u8 *lldpmib, u16 *miblen, struct ice_dcbx_cfg *dcbcfg)
1442 {
1443 u16 len, offset = 0, tlvid = ICE_TLV_ID_START;
1444 struct ice_lldp_org_tlv *tlv;
1445 u16 typelen;
1446
1447 tlv = (struct ice_lldp_org_tlv *)lldpmib;
1448 while (1) {
1449 ice_add_dcb_tlv(tlv, dcbcfg, tlvid++);
1450 typelen = ntohs(tlv->typelen);
1451 len = (typelen & ICE_LLDP_TLV_LEN_M) >> ICE_LLDP_TLV_LEN_S;
1452 if (len)
1453 offset += len + 2;
1454 /* END TLV or beyond LLDPDU size */
1455 if (tlvid >= ICE_TLV_ID_END_OF_LLDPPDU ||
1456 offset > ICE_LLDPDU_SIZE)
1457 break;
1458 /* Move to next TLV */
1459 if (len)
1460 tlv = (struct ice_lldp_org_tlv *)
1461 ((char *)tlv + sizeof(tlv->typelen) + len);
1462 }
1463 *miblen = offset;
1464 }
1465
1466 /**
1467 * ice_set_dcb_cfg - Set the local LLDP MIB to FW
1468 * @pi: port information structure
1469 *
1470 * Set DCB configuration to the Firmware
1471 */
ice_set_dcb_cfg(struct ice_port_info * pi)1472 enum ice_status ice_set_dcb_cfg(struct ice_port_info *pi)
1473 {
1474 u8 mib_type, *lldpmib = NULL;
1475 struct ice_dcbx_cfg *dcbcfg;
1476 enum ice_status ret;
1477 struct ice_hw *hw;
1478 u16 miblen;
1479
1480 if (!pi)
1481 return ICE_ERR_PARAM;
1482
1483 hw = pi->hw;
1484
1485 /* update the HW local config */
1486 dcbcfg = &pi->qos_cfg.local_dcbx_cfg;
1487 /* Allocate the LLDPDU */
1488 lldpmib = devm_kzalloc(ice_hw_to_dev(hw), ICE_LLDPDU_SIZE, GFP_KERNEL);
1489 if (!lldpmib)
1490 return ICE_ERR_NO_MEMORY;
1491
1492 mib_type = SET_LOCAL_MIB_TYPE_LOCAL_MIB;
1493 if (dcbcfg->app_mode == ICE_DCBX_APPS_NON_WILLING)
1494 mib_type |= SET_LOCAL_MIB_TYPE_CEE_NON_WILLING;
1495
1496 ice_dcb_cfg_to_lldp(lldpmib, &miblen, dcbcfg);
1497 ret = ice_aq_set_lldp_mib(hw, mib_type, (void *)lldpmib, miblen,
1498 NULL);
1499
1500 devm_kfree(ice_hw_to_dev(hw), lldpmib);
1501
1502 return ret;
1503 }
1504
1505 /**
1506 * ice_aq_query_port_ets - query port ETS configuration
1507 * @pi: port information structure
1508 * @buf: pointer to buffer
1509 * @buf_size: buffer size in bytes
1510 * @cd: pointer to command details structure or NULL
1511 *
1512 * query current port ETS configuration
1513 */
1514 static enum ice_status
ice_aq_query_port_ets(struct ice_port_info * pi,struct ice_aqc_port_ets_elem * buf,u16 buf_size,struct ice_sq_cd * cd)1515 ice_aq_query_port_ets(struct ice_port_info *pi,
1516 struct ice_aqc_port_ets_elem *buf, u16 buf_size,
1517 struct ice_sq_cd *cd)
1518 {
1519 struct ice_aqc_query_port_ets *cmd;
1520 struct ice_aq_desc desc;
1521 enum ice_status status;
1522
1523 if (!pi)
1524 return ICE_ERR_PARAM;
1525 cmd = &desc.params.port_ets;
1526 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_query_port_ets);
1527 cmd->port_teid = pi->root->info.node_teid;
1528
1529 status = ice_aq_send_cmd(pi->hw, &desc, buf, buf_size, cd);
1530 return status;
1531 }
1532
1533 /**
1534 * ice_update_port_tc_tree_cfg - update TC tree configuration
1535 * @pi: port information structure
1536 * @buf: pointer to buffer
1537 *
1538 * update the SW DB with the new TC changes
1539 */
1540 static enum ice_status
ice_update_port_tc_tree_cfg(struct ice_port_info * pi,struct ice_aqc_port_ets_elem * buf)1541 ice_update_port_tc_tree_cfg(struct ice_port_info *pi,
1542 struct ice_aqc_port_ets_elem *buf)
1543 {
1544 struct ice_sched_node *node, *tc_node;
1545 struct ice_aqc_txsched_elem_data elem;
1546 enum ice_status status = 0;
1547 u32 teid1, teid2;
1548 u8 i, j;
1549
1550 if (!pi)
1551 return ICE_ERR_PARAM;
1552 /* suspend the missing TC nodes */
1553 for (i = 0; i < pi->root->num_children; i++) {
1554 teid1 = le32_to_cpu(pi->root->children[i]->info.node_teid);
1555 ice_for_each_traffic_class(j) {
1556 teid2 = le32_to_cpu(buf->tc_node_teid[j]);
1557 if (teid1 == teid2)
1558 break;
1559 }
1560 if (j < ICE_MAX_TRAFFIC_CLASS)
1561 continue;
1562 /* TC is missing */
1563 pi->root->children[i]->in_use = false;
1564 }
1565 /* add the new TC nodes */
1566 ice_for_each_traffic_class(j) {
1567 teid2 = le32_to_cpu(buf->tc_node_teid[j]);
1568 if (teid2 == ICE_INVAL_TEID)
1569 continue;
1570 /* Is it already present in the tree ? */
1571 for (i = 0; i < pi->root->num_children; i++) {
1572 tc_node = pi->root->children[i];
1573 if (!tc_node)
1574 continue;
1575 teid1 = le32_to_cpu(tc_node->info.node_teid);
1576 if (teid1 == teid2) {
1577 tc_node->tc_num = j;
1578 tc_node->in_use = true;
1579 break;
1580 }
1581 }
1582 if (i < pi->root->num_children)
1583 continue;
1584 /* new TC */
1585 status = ice_sched_query_elem(pi->hw, teid2, &elem);
1586 if (!status)
1587 status = ice_sched_add_node(pi, 1, &elem);
1588 if (status)
1589 break;
1590 /* update the TC number */
1591 node = ice_sched_find_node_by_teid(pi->root, teid2);
1592 if (node)
1593 node->tc_num = j;
1594 }
1595 return status;
1596 }
1597
1598 /**
1599 * ice_query_port_ets - query port ETS configuration
1600 * @pi: port information structure
1601 * @buf: pointer to buffer
1602 * @buf_size: buffer size in bytes
1603 * @cd: pointer to command details structure or NULL
1604 *
1605 * query current port ETS configuration and update the
1606 * SW DB with the TC changes
1607 */
1608 enum ice_status
ice_query_port_ets(struct ice_port_info * pi,struct ice_aqc_port_ets_elem * buf,u16 buf_size,struct ice_sq_cd * cd)1609 ice_query_port_ets(struct ice_port_info *pi,
1610 struct ice_aqc_port_ets_elem *buf, u16 buf_size,
1611 struct ice_sq_cd *cd)
1612 {
1613 enum ice_status status;
1614
1615 mutex_lock(&pi->sched_lock);
1616 status = ice_aq_query_port_ets(pi, buf, buf_size, cd);
1617 if (!status)
1618 status = ice_update_port_tc_tree_cfg(pi, buf);
1619 mutex_unlock(&pi->sched_lock);
1620 return status;
1621 }
1622