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