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