]> git.proxmox.com Git - ceph.git/blob - ceph/src/seastar/dpdk/drivers/net/i40e/base/i40e_dcb.c
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / seastar / dpdk / drivers / net / i40e / base / i40e_dcb.c
1 /*******************************************************************************
2
3 Copyright (c) 2013 - 2015, Intel Corporation
4 All rights reserved.
5
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
8
9 1. Redistributions of source code must retain the above copyright notice,
10 this list of conditions and the following disclaimer.
11
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15
16 3. Neither the name of the Intel Corporation nor the names of its
17 contributors may be used to endorse or promote products derived from
18 this software without specific prior written permission.
19
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 POSSIBILITY OF SUCH DAMAGE.
31
32 ***************************************************************************/
33
34 #include "i40e_adminq.h"
35 #include "i40e_prototype.h"
36 #include "i40e_dcb.h"
37
38 /**
39 * i40e_get_dcbx_status
40 * @hw: pointer to the hw struct
41 * @status: Embedded DCBX Engine Status
42 *
43 * Get the DCBX status from the Firmware
44 **/
45 enum i40e_status_code i40e_get_dcbx_status(struct i40e_hw *hw, u16 *status)
46 {
47 u32 reg;
48
49 if (!status)
50 return I40E_ERR_PARAM;
51
52 reg = rd32(hw, I40E_PRTDCB_GENS);
53 *status = (u16)((reg & I40E_PRTDCB_GENS_DCBX_STATUS_MASK) >>
54 I40E_PRTDCB_GENS_DCBX_STATUS_SHIFT);
55
56 return I40E_SUCCESS;
57 }
58
59 /**
60 * i40e_parse_ieee_etscfg_tlv
61 * @tlv: IEEE 802.1Qaz ETS CFG TLV
62 * @dcbcfg: Local store to update ETS CFG data
63 *
64 * Parses IEEE 802.1Qaz ETS CFG TLV
65 **/
66 static void i40e_parse_ieee_etscfg_tlv(struct i40e_lldp_org_tlv *tlv,
67 struct i40e_dcbx_config *dcbcfg)
68 {
69 struct i40e_dcb_ets_config *etscfg;
70 u8 *buf = tlv->tlvinfo;
71 u16 offset = 0;
72 u8 priority;
73 int i;
74
75 /* First Octet post subtype
76 * --------------------------
77 * |will-|CBS | Re- | Max |
78 * |ing | |served| TCs |
79 * --------------------------
80 * |1bit | 1bit|3 bits|3bits|
81 */
82 etscfg = &dcbcfg->etscfg;
83 etscfg->willing = (u8)((buf[offset] & I40E_IEEE_ETS_WILLING_MASK) >>
84 I40E_IEEE_ETS_WILLING_SHIFT);
85 etscfg->cbs = (u8)((buf[offset] & I40E_IEEE_ETS_CBS_MASK) >>
86 I40E_IEEE_ETS_CBS_SHIFT);
87 etscfg->maxtcs = (u8)((buf[offset] & I40E_IEEE_ETS_MAXTC_MASK) >>
88 I40E_IEEE_ETS_MAXTC_SHIFT);
89
90 /* Move offset to Priority Assignment Table */
91 offset++;
92
93 /* Priority Assignment Table (4 octets)
94 * Octets:| 1 | 2 | 3 | 4 |
95 * -----------------------------------------
96 * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
97 * -----------------------------------------
98 * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0|
99 * -----------------------------------------
100 */
101 for (i = 0; i < 4; i++) {
102 priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_1_MASK) >>
103 I40E_IEEE_ETS_PRIO_1_SHIFT);
104 etscfg->prioritytable[i * 2] = priority;
105 priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_0_MASK) >>
106 I40E_IEEE_ETS_PRIO_0_SHIFT);
107 etscfg->prioritytable[i * 2 + 1] = priority;
108 offset++;
109 }
110
111 /* TC Bandwidth Table (8 octets)
112 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
113 * ---------------------------------
114 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
115 * ---------------------------------
116 */
117 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
118 etscfg->tcbwtable[i] = buf[offset++];
119
120 /* TSA Assignment Table (8 octets)
121 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
122 * ---------------------------------
123 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
124 * ---------------------------------
125 */
126 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
127 etscfg->tsatable[i] = buf[offset++];
128 }
129
130 /**
131 * i40e_parse_ieee_etsrec_tlv
132 * @tlv: IEEE 802.1Qaz ETS REC TLV
133 * @dcbcfg: Local store to update ETS REC data
134 *
135 * Parses IEEE 802.1Qaz ETS REC TLV
136 **/
137 static void i40e_parse_ieee_etsrec_tlv(struct i40e_lldp_org_tlv *tlv,
138 struct i40e_dcbx_config *dcbcfg)
139 {
140 u8 *buf = tlv->tlvinfo;
141 u16 offset = 0;
142 u8 priority;
143 int i;
144
145 /* Move offset to priority table */
146 offset++;
147
148 /* Priority Assignment Table (4 octets)
149 * Octets:| 1 | 2 | 3 | 4 |
150 * -----------------------------------------
151 * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
152 * -----------------------------------------
153 * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0|
154 * -----------------------------------------
155 */
156 for (i = 0; i < 4; i++) {
157 priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_1_MASK) >>
158 I40E_IEEE_ETS_PRIO_1_SHIFT);
159 dcbcfg->etsrec.prioritytable[i*2] = priority;
160 priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_0_MASK) >>
161 I40E_IEEE_ETS_PRIO_0_SHIFT);
162 dcbcfg->etsrec.prioritytable[i*2 + 1] = priority;
163 offset++;
164 }
165
166 /* TC Bandwidth Table (8 octets)
167 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
168 * ---------------------------------
169 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
170 * ---------------------------------
171 */
172 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
173 dcbcfg->etsrec.tcbwtable[i] = buf[offset++];
174
175 /* TSA Assignment Table (8 octets)
176 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
177 * ---------------------------------
178 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
179 * ---------------------------------
180 */
181 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
182 dcbcfg->etsrec.tsatable[i] = buf[offset++];
183 }
184
185 /**
186 * i40e_parse_ieee_pfccfg_tlv
187 * @tlv: IEEE 802.1Qaz PFC CFG TLV
188 * @dcbcfg: Local store to update PFC CFG data
189 *
190 * Parses IEEE 802.1Qaz PFC CFG TLV
191 **/
192 static void i40e_parse_ieee_pfccfg_tlv(struct i40e_lldp_org_tlv *tlv,
193 struct i40e_dcbx_config *dcbcfg)
194 {
195 u8 *buf = tlv->tlvinfo;
196
197 /* ----------------------------------------
198 * |will-|MBC | Re- | PFC | PFC Enable |
199 * |ing | |served| cap | |
200 * -----------------------------------------
201 * |1bit | 1bit|2 bits|4bits| 1 octet |
202 */
203 dcbcfg->pfc.willing = (u8)((buf[0] & I40E_IEEE_PFC_WILLING_MASK) >>
204 I40E_IEEE_PFC_WILLING_SHIFT);
205 dcbcfg->pfc.mbc = (u8)((buf[0] & I40E_IEEE_PFC_MBC_MASK) >>
206 I40E_IEEE_PFC_MBC_SHIFT);
207 dcbcfg->pfc.pfccap = (u8)((buf[0] & I40E_IEEE_PFC_CAP_MASK) >>
208 I40E_IEEE_PFC_CAP_SHIFT);
209 dcbcfg->pfc.pfcenable = buf[1];
210 }
211
212 /**
213 * i40e_parse_ieee_app_tlv
214 * @tlv: IEEE 802.1Qaz APP TLV
215 * @dcbcfg: Local store to update APP PRIO data
216 *
217 * Parses IEEE 802.1Qaz APP PRIO TLV
218 **/
219 static void i40e_parse_ieee_app_tlv(struct i40e_lldp_org_tlv *tlv,
220 struct i40e_dcbx_config *dcbcfg)
221 {
222 u16 typelength;
223 u16 offset = 0;
224 u16 length;
225 int i = 0;
226 u8 *buf;
227
228 typelength = I40E_NTOHS(tlv->typelength);
229 length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
230 I40E_LLDP_TLV_LEN_SHIFT);
231 buf = tlv->tlvinfo;
232
233 /* The App priority table starts 5 octets after TLV header */
234 length -= (sizeof(tlv->ouisubtype) + 1);
235
236 /* Move offset to App Priority Table */
237 offset++;
238
239 /* Application Priority Table (3 octets)
240 * Octets:| 1 | 2 | 3 |
241 * -----------------------------------------
242 * |Priority|Rsrvd| Sel | Protocol ID |
243 * -----------------------------------------
244 * Bits:|23 21|20 19|18 16|15 0|
245 * -----------------------------------------
246 */
247 while (offset < length) {
248 dcbcfg->app[i].priority = (u8)((buf[offset] &
249 I40E_IEEE_APP_PRIO_MASK) >>
250 I40E_IEEE_APP_PRIO_SHIFT);
251 dcbcfg->app[i].selector = (u8)((buf[offset] &
252 I40E_IEEE_APP_SEL_MASK) >>
253 I40E_IEEE_APP_SEL_SHIFT);
254 dcbcfg->app[i].protocolid = (buf[offset + 1] << 0x8) |
255 buf[offset + 2];
256 /* Move to next app */
257 offset += 3;
258 i++;
259 if (i >= I40E_DCBX_MAX_APPS)
260 break;
261 }
262
263 dcbcfg->numapps = i;
264 }
265
266 /**
267 * i40e_parse_ieee_etsrec_tlv
268 * @tlv: IEEE 802.1Qaz TLV
269 * @dcbcfg: Local store to update ETS REC data
270 *
271 * Get the TLV subtype and send it to parsing function
272 * based on the subtype value
273 **/
274 static void i40e_parse_ieee_tlv(struct i40e_lldp_org_tlv *tlv,
275 struct i40e_dcbx_config *dcbcfg)
276 {
277 u32 ouisubtype;
278 u8 subtype;
279
280 ouisubtype = I40E_NTOHL(tlv->ouisubtype);
281 subtype = (u8)((ouisubtype & I40E_LLDP_TLV_SUBTYPE_MASK) >>
282 I40E_LLDP_TLV_SUBTYPE_SHIFT);
283 switch (subtype) {
284 case I40E_IEEE_SUBTYPE_ETS_CFG:
285 i40e_parse_ieee_etscfg_tlv(tlv, dcbcfg);
286 break;
287 case I40E_IEEE_SUBTYPE_ETS_REC:
288 i40e_parse_ieee_etsrec_tlv(tlv, dcbcfg);
289 break;
290 case I40E_IEEE_SUBTYPE_PFC_CFG:
291 i40e_parse_ieee_pfccfg_tlv(tlv, dcbcfg);
292 break;
293 case I40E_IEEE_SUBTYPE_APP_PRI:
294 i40e_parse_ieee_app_tlv(tlv, dcbcfg);
295 break;
296 default:
297 break;
298 }
299 }
300
301 /**
302 * i40e_parse_cee_pgcfg_tlv
303 * @tlv: CEE DCBX PG CFG TLV
304 * @dcbcfg: Local store to update ETS CFG data
305 *
306 * Parses CEE DCBX PG CFG TLV
307 **/
308 static void i40e_parse_cee_pgcfg_tlv(struct i40e_cee_feat_tlv *tlv,
309 struct i40e_dcbx_config *dcbcfg)
310 {
311 struct i40e_dcb_ets_config *etscfg;
312 u8 *buf = tlv->tlvinfo;
313 u16 offset = 0;
314 u8 priority;
315 int i;
316
317 etscfg = &dcbcfg->etscfg;
318
319 if (tlv->en_will_err & I40E_CEE_FEAT_TLV_WILLING_MASK)
320 etscfg->willing = 1;
321
322 etscfg->cbs = 0;
323 /* Priority Group Table (4 octets)
324 * Octets:| 1 | 2 | 3 | 4 |
325 * -----------------------------------------
326 * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
327 * -----------------------------------------
328 * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0|
329 * -----------------------------------------
330 */
331 for (i = 0; i < 4; i++) {
332 priority = (u8)((buf[offset] & I40E_CEE_PGID_PRIO_1_MASK) >>
333 I40E_CEE_PGID_PRIO_1_SHIFT);
334 etscfg->prioritytable[i * 2] = priority;
335 priority = (u8)((buf[offset] & I40E_CEE_PGID_PRIO_0_MASK) >>
336 I40E_CEE_PGID_PRIO_0_SHIFT);
337 etscfg->prioritytable[i * 2 + 1] = priority;
338 offset++;
339 }
340
341 /* PG Percentage Table (8 octets)
342 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
343 * ---------------------------------
344 * |pg0|pg1|pg2|pg3|pg4|pg5|pg6|pg7|
345 * ---------------------------------
346 */
347 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
348 etscfg->tcbwtable[i] = buf[offset++];
349
350 /* Number of TCs supported (1 octet) */
351 etscfg->maxtcs = buf[offset];
352 }
353
354 /**
355 * i40e_parse_cee_pfccfg_tlv
356 * @tlv: CEE DCBX PFC CFG TLV
357 * @dcbcfg: Local store to update PFC CFG data
358 *
359 * Parses CEE DCBX PFC CFG TLV
360 **/
361 static void i40e_parse_cee_pfccfg_tlv(struct i40e_cee_feat_tlv *tlv,
362 struct i40e_dcbx_config *dcbcfg)
363 {
364 u8 *buf = tlv->tlvinfo;
365
366 if (tlv->en_will_err & I40E_CEE_FEAT_TLV_WILLING_MASK)
367 dcbcfg->pfc.willing = 1;
368
369 /* ------------------------
370 * | PFC Enable | PFC TCs |
371 * ------------------------
372 * | 1 octet | 1 octet |
373 */
374 dcbcfg->pfc.pfcenable = buf[0];
375 dcbcfg->pfc.pfccap = buf[1];
376 }
377
378 /**
379 * i40e_parse_cee_app_tlv
380 * @tlv: CEE DCBX APP TLV
381 * @dcbcfg: Local store to update APP PRIO data
382 *
383 * Parses CEE DCBX APP PRIO TLV
384 **/
385 static void i40e_parse_cee_app_tlv(struct i40e_cee_feat_tlv *tlv,
386 struct i40e_dcbx_config *dcbcfg)
387 {
388 u16 length, typelength, offset = 0;
389 struct i40e_cee_app_prio *app;
390 u8 i;
391
392 typelength = I40E_NTOHS(tlv->hdr.typelen);
393 length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
394 I40E_LLDP_TLV_LEN_SHIFT);
395
396 dcbcfg->numapps = length / sizeof(*app);
397 if (!dcbcfg->numapps)
398 return;
399 if (dcbcfg->numapps > I40E_DCBX_MAX_APPS)
400 dcbcfg->numapps = I40E_DCBX_MAX_APPS;
401
402 for (i = 0; i < dcbcfg->numapps; i++) {
403 u8 up, selector;
404
405 app = (struct i40e_cee_app_prio *)(tlv->tlvinfo + offset);
406 for (up = 0; up < I40E_MAX_USER_PRIORITY; up++) {
407 if (app->prio_map & BIT(up))
408 break;
409 }
410 dcbcfg->app[i].priority = up;
411
412 /* Get Selector from lower 2 bits, and convert to IEEE */
413 selector = (app->upper_oui_sel & I40E_CEE_APP_SELECTOR_MASK);
414 switch (selector) {
415 case I40E_CEE_APP_SEL_ETHTYPE:
416 dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE;
417 break;
418 case I40E_CEE_APP_SEL_TCPIP:
419 dcbcfg->app[i].selector = I40E_APP_SEL_TCPIP;
420 break;
421 default:
422 /* Keep selector as it is for unknown types */
423 dcbcfg->app[i].selector = selector;
424 }
425
426 dcbcfg->app[i].protocolid = I40E_NTOHS(app->protocol);
427 /* Move to next app */
428 offset += sizeof(*app);
429 }
430 }
431
432 /**
433 * i40e_parse_cee_tlv
434 * @tlv: CEE DCBX TLV
435 * @dcbcfg: Local store to update DCBX config data
436 *
437 * Get the TLV subtype and send it to parsing function
438 * based on the subtype value
439 **/
440 static void i40e_parse_cee_tlv(struct i40e_lldp_org_tlv *tlv,
441 struct i40e_dcbx_config *dcbcfg)
442 {
443 u16 len, tlvlen, sublen, typelength;
444 struct i40e_cee_feat_tlv *sub_tlv;
445 u8 subtype, feat_tlv_count = 0;
446 u32 ouisubtype;
447
448 ouisubtype = I40E_NTOHL(tlv->ouisubtype);
449 subtype = (u8)((ouisubtype & I40E_LLDP_TLV_SUBTYPE_MASK) >>
450 I40E_LLDP_TLV_SUBTYPE_SHIFT);
451 /* Return if not CEE DCBX */
452 if (subtype != I40E_CEE_DCBX_TYPE)
453 return;
454
455 typelength = I40E_NTOHS(tlv->typelength);
456 tlvlen = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
457 I40E_LLDP_TLV_LEN_SHIFT);
458 len = sizeof(tlv->typelength) + sizeof(ouisubtype) +
459 sizeof(struct i40e_cee_ctrl_tlv);
460 /* Return if no CEE DCBX Feature TLVs */
461 if (tlvlen <= len)
462 return;
463
464 sub_tlv = (struct i40e_cee_feat_tlv *)((char *)tlv + len);
465 while (feat_tlv_count < I40E_CEE_MAX_FEAT_TYPE) {
466 typelength = I40E_NTOHS(sub_tlv->hdr.typelen);
467 sublen = (u16)((typelength &
468 I40E_LLDP_TLV_LEN_MASK) >>
469 I40E_LLDP_TLV_LEN_SHIFT);
470 subtype = (u8)((typelength & I40E_LLDP_TLV_TYPE_MASK) >>
471 I40E_LLDP_TLV_TYPE_SHIFT);
472 switch (subtype) {
473 case I40E_CEE_SUBTYPE_PG_CFG:
474 i40e_parse_cee_pgcfg_tlv(sub_tlv, dcbcfg);
475 break;
476 case I40E_CEE_SUBTYPE_PFC_CFG:
477 i40e_parse_cee_pfccfg_tlv(sub_tlv, dcbcfg);
478 break;
479 case I40E_CEE_SUBTYPE_APP_PRI:
480 i40e_parse_cee_app_tlv(sub_tlv, dcbcfg);
481 break;
482 default:
483 return; /* Invalid Sub-type return */
484 }
485 feat_tlv_count++;
486 /* Move to next sub TLV */
487 sub_tlv = (struct i40e_cee_feat_tlv *)((char *)sub_tlv +
488 sizeof(sub_tlv->hdr.typelen) +
489 sublen);
490 }
491 }
492
493 /**
494 * i40e_parse_org_tlv
495 * @tlv: Organization specific TLV
496 * @dcbcfg: Local store to update ETS REC data
497 *
498 * Currently only IEEE 802.1Qaz TLV is supported, all others
499 * will be returned
500 **/
501 static void i40e_parse_org_tlv(struct i40e_lldp_org_tlv *tlv,
502 struct i40e_dcbx_config *dcbcfg)
503 {
504 u32 ouisubtype;
505 u32 oui;
506
507 ouisubtype = I40E_NTOHL(tlv->ouisubtype);
508 oui = (u32)((ouisubtype & I40E_LLDP_TLV_OUI_MASK) >>
509 I40E_LLDP_TLV_OUI_SHIFT);
510 switch (oui) {
511 case I40E_IEEE_8021QAZ_OUI:
512 i40e_parse_ieee_tlv(tlv, dcbcfg);
513 break;
514 case I40E_CEE_DCBX_OUI:
515 i40e_parse_cee_tlv(tlv, dcbcfg);
516 break;
517 default:
518 break;
519 }
520 }
521
522 /**
523 * i40e_lldp_to_dcb_config
524 * @lldpmib: LLDPDU to be parsed
525 * @dcbcfg: store for LLDPDU data
526 *
527 * Parse DCB configuration from the LLDPDU
528 **/
529 enum i40e_status_code i40e_lldp_to_dcb_config(u8 *lldpmib,
530 struct i40e_dcbx_config *dcbcfg)
531 {
532 enum i40e_status_code ret = I40E_SUCCESS;
533 struct i40e_lldp_org_tlv *tlv;
534 u16 type;
535 u16 length;
536 u16 typelength;
537 u16 offset = 0;
538
539 if (!lldpmib || !dcbcfg)
540 return I40E_ERR_PARAM;
541
542 /* set to the start of LLDPDU */
543 lldpmib += I40E_LLDP_MIB_HLEN;
544 tlv = (struct i40e_lldp_org_tlv *)lldpmib;
545 while (1) {
546 typelength = I40E_NTOHS(tlv->typelength);
547 type = (u16)((typelength & I40E_LLDP_TLV_TYPE_MASK) >>
548 I40E_LLDP_TLV_TYPE_SHIFT);
549 length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
550 I40E_LLDP_TLV_LEN_SHIFT);
551 offset += sizeof(typelength) + length;
552
553 /* END TLV or beyond LLDPDU size */
554 if ((type == I40E_TLV_TYPE_END) || (offset > I40E_LLDPDU_SIZE))
555 break;
556
557 switch (type) {
558 case I40E_TLV_TYPE_ORG:
559 i40e_parse_org_tlv(tlv, dcbcfg);
560 break;
561 default:
562 break;
563 }
564
565 /* Move to next TLV */
566 tlv = (struct i40e_lldp_org_tlv *)((char *)tlv +
567 sizeof(tlv->typelength) +
568 length);
569 }
570
571 return ret;
572 }
573
574 /**
575 * i40e_aq_get_dcb_config
576 * @hw: pointer to the hw struct
577 * @mib_type: mib type for the query
578 * @bridgetype: bridge type for the query (remote)
579 * @dcbcfg: store for LLDPDU data
580 *
581 * Query DCB configuration from the Firmware
582 **/
583 enum i40e_status_code i40e_aq_get_dcb_config(struct i40e_hw *hw, u8 mib_type,
584 u8 bridgetype,
585 struct i40e_dcbx_config *dcbcfg)
586 {
587 enum i40e_status_code ret = I40E_SUCCESS;
588 struct i40e_virt_mem mem;
589 u8 *lldpmib;
590
591 /* Allocate the LLDPDU */
592 ret = i40e_allocate_virt_mem(hw, &mem, I40E_LLDPDU_SIZE);
593 if (ret)
594 return ret;
595
596 lldpmib = (u8 *)mem.va;
597 ret = i40e_aq_get_lldp_mib(hw, bridgetype, mib_type,
598 (void *)lldpmib, I40E_LLDPDU_SIZE,
599 NULL, NULL, NULL);
600 if (ret)
601 goto free_mem;
602
603 /* Parse LLDP MIB to get dcb configuration */
604 ret = i40e_lldp_to_dcb_config(lldpmib, dcbcfg);
605
606 free_mem:
607 i40e_free_virt_mem(hw, &mem);
608 return ret;
609 }
610
611 /**
612 * i40e_cee_to_dcb_v1_config
613 * @cee_cfg: pointer to CEE v1 response configuration struct
614 * @dcbcfg: DCB configuration struct
615 *
616 * Convert CEE v1 configuration from firmware to DCB configuration
617 **/
618 static void i40e_cee_to_dcb_v1_config(
619 struct i40e_aqc_get_cee_dcb_cfg_v1_resp *cee_cfg,
620 struct i40e_dcbx_config *dcbcfg)
621 {
622 u16 status, tlv_status = LE16_TO_CPU(cee_cfg->tlv_status);
623 u16 app_prio = LE16_TO_CPU(cee_cfg->oper_app_prio);
624 u8 i, tc, err;
625
626 /* CEE PG data to ETS config */
627 dcbcfg->etscfg.maxtcs = cee_cfg->oper_num_tc;
628
629 /* Note that the FW creates the oper_prio_tc nibbles reversed
630 * from those in the CEE Priority Group sub-TLV.
631 */
632 for (i = 0; i < 4; i++) {
633 tc = (u8)((cee_cfg->oper_prio_tc[i] &
634 I40E_CEE_PGID_PRIO_0_MASK) >>
635 I40E_CEE_PGID_PRIO_0_SHIFT);
636 dcbcfg->etscfg.prioritytable[i*2] = tc;
637 tc = (u8)((cee_cfg->oper_prio_tc[i] &
638 I40E_CEE_PGID_PRIO_1_MASK) >>
639 I40E_CEE_PGID_PRIO_1_SHIFT);
640 dcbcfg->etscfg.prioritytable[i*2 + 1] = tc;
641 }
642
643 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
644 dcbcfg->etscfg.tcbwtable[i] = cee_cfg->oper_tc_bw[i];
645
646 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
647 if (dcbcfg->etscfg.prioritytable[i] == I40E_CEE_PGID_STRICT) {
648 /* Map it to next empty TC */
649 dcbcfg->etscfg.prioritytable[i] =
650 cee_cfg->oper_num_tc - 1;
651 dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_STRICT;
652 } else {
653 dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS;
654 }
655 }
656
657 /* CEE PFC data to ETS config */
658 dcbcfg->pfc.pfcenable = cee_cfg->oper_pfc_en;
659 dcbcfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;
660
661 status = (tlv_status & I40E_AQC_CEE_APP_STATUS_MASK) >>
662 I40E_AQC_CEE_APP_STATUS_SHIFT;
663 err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
664 /* Add APPs if Error is False */
665 if (!err) {
666 /* CEE operating configuration supports FCoE/iSCSI/FIP only */
667 dcbcfg->numapps = I40E_CEE_OPER_MAX_APPS;
668
669 /* FCoE APP */
670 dcbcfg->app[0].priority =
671 (app_prio & I40E_AQC_CEE_APP_FCOE_MASK) >>
672 I40E_AQC_CEE_APP_FCOE_SHIFT;
673 dcbcfg->app[0].selector = I40E_APP_SEL_ETHTYPE;
674 dcbcfg->app[0].protocolid = I40E_APP_PROTOID_FCOE;
675
676 /* iSCSI APP */
677 dcbcfg->app[1].priority =
678 (app_prio & I40E_AQC_CEE_APP_ISCSI_MASK) >>
679 I40E_AQC_CEE_APP_ISCSI_SHIFT;
680 dcbcfg->app[1].selector = I40E_APP_SEL_TCPIP;
681 dcbcfg->app[1].protocolid = I40E_APP_PROTOID_ISCSI;
682
683 /* FIP APP */
684 dcbcfg->app[2].priority =
685 (app_prio & I40E_AQC_CEE_APP_FIP_MASK) >>
686 I40E_AQC_CEE_APP_FIP_SHIFT;
687 dcbcfg->app[2].selector = I40E_APP_SEL_ETHTYPE;
688 dcbcfg->app[2].protocolid = I40E_APP_PROTOID_FIP;
689 }
690 }
691
692 /**
693 * i40e_cee_to_dcb_config
694 * @cee_cfg: pointer to CEE configuration struct
695 * @dcbcfg: DCB configuration struct
696 *
697 * Convert CEE configuration from firmware to DCB configuration
698 **/
699 static void i40e_cee_to_dcb_config(
700 struct i40e_aqc_get_cee_dcb_cfg_resp *cee_cfg,
701 struct i40e_dcbx_config *dcbcfg)
702 {
703 u32 status, tlv_status = LE32_TO_CPU(cee_cfg->tlv_status);
704 u16 app_prio = LE16_TO_CPU(cee_cfg->oper_app_prio);
705 u8 i, tc, err, sync, oper;
706
707 /* CEE PG data to ETS config */
708 dcbcfg->etscfg.maxtcs = cee_cfg->oper_num_tc;
709
710 /* Note that the FW creates the oper_prio_tc nibbles reversed
711 * from those in the CEE Priority Group sub-TLV.
712 */
713 for (i = 0; i < 4; i++) {
714 tc = (u8)((cee_cfg->oper_prio_tc[i] &
715 I40E_CEE_PGID_PRIO_0_MASK) >>
716 I40E_CEE_PGID_PRIO_0_SHIFT);
717 dcbcfg->etscfg.prioritytable[i*2] = tc;
718 tc = (u8)((cee_cfg->oper_prio_tc[i] &
719 I40E_CEE_PGID_PRIO_1_MASK) >>
720 I40E_CEE_PGID_PRIO_1_SHIFT);
721 dcbcfg->etscfg.prioritytable[i*2 + 1] = tc;
722 }
723
724 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
725 dcbcfg->etscfg.tcbwtable[i] = cee_cfg->oper_tc_bw[i];
726
727 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
728 if (dcbcfg->etscfg.prioritytable[i] == I40E_CEE_PGID_STRICT) {
729 /* Map it to next empty TC */
730 dcbcfg->etscfg.prioritytable[i] =
731 cee_cfg->oper_num_tc - 1;
732 dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_STRICT;
733 } else {
734 dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS;
735 }
736 }
737
738 /* CEE PFC data to ETS config */
739 dcbcfg->pfc.pfcenable = cee_cfg->oper_pfc_en;
740 dcbcfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;
741
742 i = 0;
743 status = (tlv_status & I40E_AQC_CEE_FCOE_STATUS_MASK) >>
744 I40E_AQC_CEE_FCOE_STATUS_SHIFT;
745 err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
746 sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0;
747 oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0;
748 /* Add FCoE APP if Error is False and Oper/Sync is True */
749 if (!err && sync && oper) {
750 /* FCoE APP */
751 dcbcfg->app[i].priority =
752 (app_prio & I40E_AQC_CEE_APP_FCOE_MASK) >>
753 I40E_AQC_CEE_APP_FCOE_SHIFT;
754 dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE;
755 dcbcfg->app[i].protocolid = I40E_APP_PROTOID_FCOE;
756 i++;
757 }
758
759 status = (tlv_status & I40E_AQC_CEE_ISCSI_STATUS_MASK) >>
760 I40E_AQC_CEE_ISCSI_STATUS_SHIFT;
761 err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
762 sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0;
763 oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0;
764 /* Add iSCSI APP if Error is False and Oper/Sync is True */
765 if (!err && sync && oper) {
766 /* iSCSI APP */
767 dcbcfg->app[i].priority =
768 (app_prio & I40E_AQC_CEE_APP_ISCSI_MASK) >>
769 I40E_AQC_CEE_APP_ISCSI_SHIFT;
770 dcbcfg->app[i].selector = I40E_APP_SEL_TCPIP;
771 dcbcfg->app[i].protocolid = I40E_APP_PROTOID_ISCSI;
772 i++;
773 }
774
775 status = (tlv_status & I40E_AQC_CEE_FIP_STATUS_MASK) >>
776 I40E_AQC_CEE_FIP_STATUS_SHIFT;
777 err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
778 sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0;
779 oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0;
780 /* Add FIP APP if Error is False and Oper/Sync is True */
781 if (!err && sync && oper) {
782 /* FIP APP */
783 dcbcfg->app[i].priority =
784 (app_prio & I40E_AQC_CEE_APP_FIP_MASK) >>
785 I40E_AQC_CEE_APP_FIP_SHIFT;
786 dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE;
787 dcbcfg->app[i].protocolid = I40E_APP_PROTOID_FIP;
788 i++;
789 }
790 dcbcfg->numapps = i;
791 }
792
793 /**
794 * i40e_get_ieee_dcb_config
795 * @hw: pointer to the hw struct
796 *
797 * Get IEEE mode DCB configuration from the Firmware
798 **/
799 STATIC enum i40e_status_code i40e_get_ieee_dcb_config(struct i40e_hw *hw)
800 {
801 enum i40e_status_code ret = I40E_SUCCESS;
802
803 /* IEEE mode */
804 hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_IEEE;
805 /* Get Local DCB Config */
806 ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_LOCAL, 0,
807 &hw->local_dcbx_config);
808 if (ret)
809 goto out;
810
811 /* Get Remote DCB Config */
812 ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_REMOTE,
813 I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE,
814 &hw->remote_dcbx_config);
815 /* Don't treat ENOENT as an error for Remote MIBs */
816 if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT)
817 ret = I40E_SUCCESS;
818
819 out:
820 return ret;
821 }
822
823 /**
824 * i40e_get_dcb_config
825 * @hw: pointer to the hw struct
826 *
827 * Get DCB configuration from the Firmware
828 **/
829 enum i40e_status_code i40e_get_dcb_config(struct i40e_hw *hw)
830 {
831 enum i40e_status_code ret = I40E_SUCCESS;
832 struct i40e_aqc_get_cee_dcb_cfg_resp cee_cfg;
833 struct i40e_aqc_get_cee_dcb_cfg_v1_resp cee_v1_cfg;
834
835 /* If Firmware version < v4.33 on X710/XL710, IEEE only */
836 if ((hw->mac.type == I40E_MAC_XL710) &&
837 (((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver < 33)) ||
838 (hw->aq.fw_maj_ver < 4)))
839 return i40e_get_ieee_dcb_config(hw);
840
841 /* If Firmware version == v4.33 on X710/XL710, use old CEE struct */
842 if ((hw->mac.type == I40E_MAC_XL710) &&
843 ((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver == 33))) {
844 ret = i40e_aq_get_cee_dcb_config(hw, &cee_v1_cfg,
845 sizeof(cee_v1_cfg), NULL);
846 if (ret == I40E_SUCCESS) {
847 /* CEE mode */
848 hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_CEE;
849 hw->local_dcbx_config.tlv_status =
850 LE16_TO_CPU(cee_v1_cfg.tlv_status);
851 i40e_cee_to_dcb_v1_config(&cee_v1_cfg,
852 &hw->local_dcbx_config);
853 }
854 } else {
855 ret = i40e_aq_get_cee_dcb_config(hw, &cee_cfg,
856 sizeof(cee_cfg), NULL);
857 if (ret == I40E_SUCCESS) {
858 /* CEE mode */
859 hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_CEE;
860 hw->local_dcbx_config.tlv_status =
861 LE32_TO_CPU(cee_cfg.tlv_status);
862 i40e_cee_to_dcb_config(&cee_cfg,
863 &hw->local_dcbx_config);
864 }
865 }
866
867 /* CEE mode not enabled try querying IEEE data */
868 if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT)
869 return i40e_get_ieee_dcb_config(hw);
870
871 if (ret != I40E_SUCCESS)
872 goto out;
873
874 /* Get CEE DCB Desired Config */
875 ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_LOCAL, 0,
876 &hw->desired_dcbx_config);
877 if (ret)
878 goto out;
879
880 /* Get Remote DCB Config */
881 ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_REMOTE,
882 I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE,
883 &hw->remote_dcbx_config);
884 /* Don't treat ENOENT as an error for Remote MIBs */
885 if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT)
886 ret = I40E_SUCCESS;
887
888 out:
889 return ret;
890 }
891
892 /**
893 * i40e_init_dcb
894 * @hw: pointer to the hw struct
895 *
896 * Update DCB configuration from the Firmware
897 **/
898 enum i40e_status_code i40e_init_dcb(struct i40e_hw *hw)
899 {
900 enum i40e_status_code ret = I40E_SUCCESS;
901 struct i40e_lldp_variables lldp_cfg;
902 u8 adminstatus = 0;
903
904 if (!hw->func_caps.dcb)
905 return ret;
906
907 /* Read LLDP NVM area */
908 ret = i40e_read_lldp_cfg(hw, &lldp_cfg);
909 if (ret)
910 return ret;
911
912 /* Get the LLDP AdminStatus for the current port */
913 adminstatus = lldp_cfg.adminstatus >> (hw->port * 4);
914 adminstatus &= 0xF;
915
916 /* LLDP agent disabled */
917 if (!adminstatus) {
918 hw->dcbx_status = I40E_DCBX_STATUS_DISABLED;
919 return ret;
920 }
921
922 /* Get DCBX status */
923 ret = i40e_get_dcbx_status(hw, &hw->dcbx_status);
924 if (ret)
925 return ret;
926
927 /* Check the DCBX Status */
928 switch (hw->dcbx_status) {
929 case I40E_DCBX_STATUS_DONE:
930 case I40E_DCBX_STATUS_IN_PROGRESS:
931 /* Get current DCBX configuration */
932 ret = i40e_get_dcb_config(hw);
933 if (ret)
934 return ret;
935 break;
936 case I40E_DCBX_STATUS_DISABLED:
937 return ret;
938 case I40E_DCBX_STATUS_NOT_STARTED:
939 case I40E_DCBX_STATUS_MULTIPLE_PEERS:
940 default:
941 break;
942 }
943
944 /* Configure the LLDP MIB change event */
945 ret = i40e_aq_cfg_lldp_mib_change_event(hw, true, NULL);
946 if (ret)
947 return ret;
948
949 return ret;
950 }
951
952 /**
953 * i40e_add_ieee_ets_tlv - Prepare ETS TLV in IEEE format
954 * @tlv: Fill the ETS config data in IEEE format
955 * @dcbcfg: Local store which holds the DCB Config
956 *
957 * Prepare IEEE 802.1Qaz ETS CFG TLV
958 **/
959 static void i40e_add_ieee_ets_tlv(struct i40e_lldp_org_tlv *tlv,
960 struct i40e_dcbx_config *dcbcfg)
961 {
962 u8 priority0, priority1, maxtcwilling = 0;
963 struct i40e_dcb_ets_config *etscfg;
964 u16 offset = 0, typelength, i;
965 u8 *buf = tlv->tlvinfo;
966 u32 ouisubtype;
967
968 typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) |
969 I40E_IEEE_ETS_TLV_LENGTH);
970 tlv->typelength = I40E_HTONS(typelength);
971
972 ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) |
973 I40E_IEEE_SUBTYPE_ETS_CFG);
974 tlv->ouisubtype = I40E_HTONL(ouisubtype);
975
976 /* First Octet post subtype
977 * --------------------------
978 * |will-|CBS | Re- | Max |
979 * |ing | |served| TCs |
980 * --------------------------
981 * |1bit | 1bit|3 bits|3bits|
982 */
983 etscfg = &dcbcfg->etscfg;
984 if (etscfg->willing)
985 maxtcwilling = BIT(I40E_IEEE_ETS_WILLING_SHIFT);
986 maxtcwilling |= etscfg->maxtcs & I40E_IEEE_ETS_MAXTC_MASK;
987 buf[offset] = maxtcwilling;
988
989 /* Move offset to Priority Assignment Table */
990 offset++;
991
992 /* Priority Assignment Table (4 octets)
993 * Octets:| 1 | 2 | 3 | 4 |
994 * -----------------------------------------
995 * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
996 * -----------------------------------------
997 * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0|
998 * -----------------------------------------
999 */
1000 for (i = 0; i < 4; i++) {
1001 priority0 = etscfg->prioritytable[i * 2] & 0xF;
1002 priority1 = etscfg->prioritytable[i * 2 + 1] & 0xF;
1003 buf[offset] = (priority0 << I40E_IEEE_ETS_PRIO_1_SHIFT) |
1004 priority1;
1005 offset++;
1006 }
1007
1008 /* TC Bandwidth Table (8 octets)
1009 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
1010 * ---------------------------------
1011 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
1012 * ---------------------------------
1013 */
1014 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
1015 buf[offset++] = etscfg->tcbwtable[i];
1016
1017 /* TSA Assignment Table (8 octets)
1018 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
1019 * ---------------------------------
1020 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
1021 * ---------------------------------
1022 */
1023 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
1024 buf[offset++] = etscfg->tsatable[i];
1025 }
1026
1027 /**
1028 * i40e_add_ieee_etsrec_tlv - Prepare ETS Recommended TLV in IEEE format
1029 * @tlv: Fill ETS Recommended TLV in IEEE format
1030 * @dcbcfg: Local store which holds the DCB Config
1031 *
1032 * Prepare IEEE 802.1Qaz ETS REC TLV
1033 **/
1034 static void i40e_add_ieee_etsrec_tlv(struct i40e_lldp_org_tlv *tlv,
1035 struct i40e_dcbx_config *dcbcfg)
1036 {
1037 struct i40e_dcb_ets_config *etsrec;
1038 u16 offset = 0, typelength, i;
1039 u8 priority0, priority1;
1040 u8 *buf = tlv->tlvinfo;
1041 u32 ouisubtype;
1042
1043 typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) |
1044 I40E_IEEE_ETS_TLV_LENGTH);
1045 tlv->typelength = I40E_HTONS(typelength);
1046
1047 ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) |
1048 I40E_IEEE_SUBTYPE_ETS_REC);
1049 tlv->ouisubtype = I40E_HTONL(ouisubtype);
1050
1051 etsrec = &dcbcfg->etsrec;
1052 /* First Octet is reserved */
1053 /* Move offset to Priority Assignment Table */
1054 offset++;
1055
1056 /* Priority Assignment Table (4 octets)
1057 * Octets:| 1 | 2 | 3 | 4 |
1058 * -----------------------------------------
1059 * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
1060 * -----------------------------------------
1061 * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0|
1062 * -----------------------------------------
1063 */
1064 for (i = 0; i < 4; i++) {
1065 priority0 = etsrec->prioritytable[i * 2] & 0xF;
1066 priority1 = etsrec->prioritytable[i * 2 + 1] & 0xF;
1067 buf[offset] = (priority0 << I40E_IEEE_ETS_PRIO_1_SHIFT) |
1068 priority1;
1069 offset++;
1070 }
1071
1072 /* TC Bandwidth Table (8 octets)
1073 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
1074 * ---------------------------------
1075 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
1076 * ---------------------------------
1077 */
1078 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
1079 buf[offset++] = etsrec->tcbwtable[i];
1080
1081 /* TSA Assignment Table (8 octets)
1082 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
1083 * ---------------------------------
1084 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
1085 * ---------------------------------
1086 */
1087 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
1088 buf[offset++] = etsrec->tsatable[i];
1089 }
1090
1091 /**
1092 * i40e_add_ieee_pfc_tlv - Prepare PFC TLV in IEEE format
1093 * @tlv: Fill PFC TLV in IEEE format
1094 * @dcbcfg: Local store to get PFC CFG data
1095 *
1096 * Prepare IEEE 802.1Qaz PFC CFG TLV
1097 **/
1098 static void i40e_add_ieee_pfc_tlv(struct i40e_lldp_org_tlv *tlv,
1099 struct i40e_dcbx_config *dcbcfg)
1100 {
1101 u8 *buf = tlv->tlvinfo;
1102 u32 ouisubtype;
1103 u16 typelength;
1104
1105 typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) |
1106 I40E_IEEE_PFC_TLV_LENGTH);
1107 tlv->typelength = I40E_HTONS(typelength);
1108
1109 ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) |
1110 I40E_IEEE_SUBTYPE_PFC_CFG);
1111 tlv->ouisubtype = I40E_HTONL(ouisubtype);
1112
1113 /* ----------------------------------------
1114 * |will-|MBC | Re- | PFC | PFC Enable |
1115 * |ing | |served| cap | |
1116 * -----------------------------------------
1117 * |1bit | 1bit|2 bits|4bits| 1 octet |
1118 */
1119 if (dcbcfg->pfc.willing)
1120 buf[0] = BIT(I40E_IEEE_PFC_WILLING_SHIFT);
1121
1122 if (dcbcfg->pfc.mbc)
1123 buf[0] |= BIT(I40E_IEEE_PFC_MBC_SHIFT);
1124
1125 buf[0] |= dcbcfg->pfc.pfccap & 0xF;
1126 buf[1] = dcbcfg->pfc.pfcenable;
1127 }
1128
1129 /**
1130 * i40e_add_ieee_app_pri_tlv - Prepare APP TLV in IEEE format
1131 * @tlv: Fill APP TLV in IEEE format
1132 * @dcbcfg: Local store to get APP CFG data
1133 *
1134 * Prepare IEEE 802.1Qaz APP CFG TLV
1135 **/
1136 static void i40e_add_ieee_app_pri_tlv(struct i40e_lldp_org_tlv *tlv,
1137 struct i40e_dcbx_config *dcbcfg)
1138 {
1139 u16 typelength, length, offset = 0;
1140 u8 priority, selector, i = 0;
1141 u8 *buf = tlv->tlvinfo;
1142 u32 ouisubtype;
1143
1144 /* No APP TLVs then just return */
1145 if (dcbcfg->numapps == 0)
1146 return;
1147 ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) |
1148 I40E_IEEE_SUBTYPE_APP_PRI);
1149 tlv->ouisubtype = I40E_HTONL(ouisubtype);
1150
1151 /* Move offset to App Priority Table */
1152 offset++;
1153 /* Application Priority Table (3 octets)
1154 * Octets:| 1 | 2 | 3 |
1155 * -----------------------------------------
1156 * |Priority|Rsrvd| Sel | Protocol ID |
1157 * -----------------------------------------
1158 * Bits:|23 21|20 19|18 16|15 0|
1159 * -----------------------------------------
1160 */
1161 while (i < dcbcfg->numapps) {
1162 priority = dcbcfg->app[i].priority & 0x7;
1163 selector = dcbcfg->app[i].selector & 0x7;
1164 buf[offset] = (priority << I40E_IEEE_APP_PRIO_SHIFT) | selector;
1165 buf[offset + 1] = (dcbcfg->app[i].protocolid >> 0x8) & 0xFF;
1166 buf[offset + 2] = dcbcfg->app[i].protocolid & 0xFF;
1167 /* Move to next app */
1168 offset += 3;
1169 i++;
1170 if (i >= I40E_DCBX_MAX_APPS)
1171 break;
1172 }
1173 /* length includes size of ouisubtype + 1 reserved + 3*numapps */
1174 length = sizeof(tlv->ouisubtype) + 1 + (i*3);
1175 typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) |
1176 (length & 0x1FF));
1177 tlv->typelength = I40E_HTONS(typelength);
1178 }
1179
1180 /**
1181 * i40e_add_dcb_tlv - Add all IEEE TLVs
1182 * @tlv: pointer to org tlv
1183 *
1184 * add tlv information
1185 **/
1186 static void i40e_add_dcb_tlv(struct i40e_lldp_org_tlv *tlv,
1187 struct i40e_dcbx_config *dcbcfg,
1188 u16 tlvid)
1189 {
1190 switch (tlvid) {
1191 case I40E_IEEE_TLV_ID_ETS_CFG:
1192 i40e_add_ieee_ets_tlv(tlv, dcbcfg);
1193 break;
1194 case I40E_IEEE_TLV_ID_ETS_REC:
1195 i40e_add_ieee_etsrec_tlv(tlv, dcbcfg);
1196 break;
1197 case I40E_IEEE_TLV_ID_PFC_CFG:
1198 i40e_add_ieee_pfc_tlv(tlv, dcbcfg);
1199 break;
1200 case I40E_IEEE_TLV_ID_APP_PRI:
1201 i40e_add_ieee_app_pri_tlv(tlv, dcbcfg);
1202 break;
1203 default:
1204 break;
1205 }
1206 }
1207
1208 /**
1209 * i40e_set_dcb_config - Set the local LLDP MIB to FW
1210 * @hw: pointer to the hw struct
1211 *
1212 * Set DCB configuration to the Firmware
1213 **/
1214 enum i40e_status_code i40e_set_dcb_config(struct i40e_hw *hw)
1215 {
1216 enum i40e_status_code ret = I40E_SUCCESS;
1217 struct i40e_dcbx_config *dcbcfg;
1218 struct i40e_virt_mem mem;
1219 u8 mib_type, *lldpmib;
1220 u16 miblen;
1221
1222 /* update the hw local config */
1223 dcbcfg = &hw->local_dcbx_config;
1224 /* Allocate the LLDPDU */
1225 ret = i40e_allocate_virt_mem(hw, &mem, I40E_LLDPDU_SIZE);
1226 if (ret)
1227 return ret;
1228
1229 mib_type = SET_LOCAL_MIB_AC_TYPE_LOCAL_MIB;
1230 if (dcbcfg->app_mode == I40E_DCBX_APPS_NON_WILLING) {
1231 mib_type |= SET_LOCAL_MIB_AC_TYPE_NON_WILLING_APPS <<
1232 SET_LOCAL_MIB_AC_TYPE_NON_WILLING_APPS_SHIFT;
1233 }
1234 lldpmib = (u8 *)mem.va;
1235 ret = i40e_dcb_config_to_lldp(lldpmib, &miblen, dcbcfg);
1236 ret = i40e_aq_set_lldp_mib(hw, mib_type, (void *)lldpmib, miblen, NULL);
1237
1238 i40e_free_virt_mem(hw, &mem);
1239 return ret;
1240 }
1241
1242 /**
1243 * i40e_dcb_config_to_lldp - Convert Dcbconfig to MIB format
1244 * @hw: pointer to the hw struct
1245 * @dcbcfg: store for LLDPDU data
1246 *
1247 * send DCB configuration to FW
1248 **/
1249 enum i40e_status_code i40e_dcb_config_to_lldp(u8 *lldpmib, u16 *miblen,
1250 struct i40e_dcbx_config *dcbcfg)
1251 {
1252 u16 length, offset = 0, tlvid = I40E_TLV_ID_START;
1253 enum i40e_status_code ret = I40E_SUCCESS;
1254 struct i40e_lldp_org_tlv *tlv;
1255 u16 typelength;
1256
1257 tlv = (struct i40e_lldp_org_tlv *)lldpmib;
1258 while (1) {
1259 i40e_add_dcb_tlv(tlv, dcbcfg, tlvid++);
1260 typelength = I40E_NTOHS(tlv->typelength);
1261 length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
1262 I40E_LLDP_TLV_LEN_SHIFT);
1263 if (length)
1264 offset += length + 2;
1265 /* END TLV or beyond LLDPDU size */
1266 if ((tlvid >= I40E_TLV_ID_END_OF_LLDPPDU) ||
1267 (offset > I40E_LLDPDU_SIZE))
1268 break;
1269 /* Move to next TLV */
1270 if (length)
1271 tlv = (struct i40e_lldp_org_tlv *)((char *)tlv +
1272 sizeof(tlv->typelength) + length);
1273 }
1274 *miblen = offset;
1275 return ret;
1276 }
1277
1278
1279 /**
1280 * i40e_read_lldp_cfg - read LLDP Configuration data from NVM
1281 * @hw: pointer to the HW structure
1282 * @lldp_cfg: pointer to hold lldp configuration variables
1283 *
1284 * Reads the LLDP configuration data from NVM
1285 **/
1286 enum i40e_status_code i40e_read_lldp_cfg(struct i40e_hw *hw,
1287 struct i40e_lldp_variables *lldp_cfg)
1288 {
1289 enum i40e_status_code ret = I40E_SUCCESS;
1290 u32 offset = (2 * I40E_NVM_LLDP_CFG_PTR);
1291
1292 if (!lldp_cfg)
1293 return I40E_ERR_PARAM;
1294
1295 ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
1296 if (ret != I40E_SUCCESS)
1297 goto err_lldp_cfg;
1298
1299 ret = i40e_aq_read_nvm(hw, I40E_SR_EMP_MODULE_PTR, offset,
1300 sizeof(struct i40e_lldp_variables),
1301 (u8 *)lldp_cfg,
1302 true, NULL);
1303 i40e_release_nvm(hw);
1304
1305 err_lldp_cfg:
1306 return ret;
1307 }