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