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