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