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