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