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