1 /******************************************************************************
3 Copyright (c) 2013-2019, Intel Corporation
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
9 1. Redistributions of source code must retain the above copyright notice,
10 this list of conditions and the following disclaimer.
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.
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.
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.
32 ******************************************************************************/
35 #include "i40e_adminq.h"
36 #include "i40e_prototype.h"
40 * i40e_get_dcbx_status
41 * @hw: pointer to the hw struct
42 * @status: Embedded DCBX Engine Status
44 * Get the DCBX status from the Firmware
46 enum i40e_status_code i40e_get_dcbx_status(struct i40e_hw *hw, u16 *status)
51 return I40E_ERR_PARAM;
53 reg = rd32(hw, I40E_PRTDCB_GENS);
54 *status = (u16)((reg & I40E_PRTDCB_GENS_DCBX_STATUS_MASK) >>
55 I40E_PRTDCB_GENS_DCBX_STATUS_SHIFT);
61 * i40e_parse_ieee_etscfg_tlv
62 * @tlv: IEEE 802.1Qaz ETS CFG TLV
63 * @dcbcfg: Local store to update ETS CFG data
65 * Parses IEEE 802.1Qaz ETS CFG TLV
67 static void i40e_parse_ieee_etscfg_tlv(struct i40e_lldp_org_tlv *tlv,
68 struct i40e_dcbx_config *dcbcfg)
70 struct i40e_dcb_ets_config *etscfg;
71 u8 *buf = tlv->tlvinfo;
76 /* First Octet post subtype
77 * --------------------------
78 * |will-|CBS | Re- | Max |
79 * |ing | |served| TCs |
80 * --------------------------
81 * |1bit | 1bit|3 bits|3bits|
83 etscfg = &dcbcfg->etscfg;
84 etscfg->willing = (u8)((buf[offset] & I40E_IEEE_ETS_WILLING_MASK) >>
85 I40E_IEEE_ETS_WILLING_SHIFT);
86 etscfg->cbs = (u8)((buf[offset] & I40E_IEEE_ETS_CBS_MASK) >>
87 I40E_IEEE_ETS_CBS_SHIFT);
88 etscfg->maxtcs = (u8)((buf[offset] & I40E_IEEE_ETS_MAXTC_MASK) >>
89 I40E_IEEE_ETS_MAXTC_SHIFT);
91 /* Move offset to Priority Assignment Table */
94 /* Priority Assignment Table (4 octets)
95 * Octets:| 1 | 2 | 3 | 4 |
96 * -----------------------------------------
97 * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
98 * -----------------------------------------
99 * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0|
100 * -----------------------------------------
102 for (i = 0; i < 4; i++) {
103 priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_1_MASK) >>
104 I40E_IEEE_ETS_PRIO_1_SHIFT);
105 etscfg->prioritytable[i * 2] = priority;
106 priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_0_MASK) >>
107 I40E_IEEE_ETS_PRIO_0_SHIFT);
108 etscfg->prioritytable[i * 2 + 1] = priority;
112 /* TC Bandwidth Table (8 octets)
113 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
114 * ---------------------------------
115 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
116 * ---------------------------------
118 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
119 etscfg->tcbwtable[i] = buf[offset++];
121 /* TSA Assignment Table (8 octets)
122 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
123 * ---------------------------------
124 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
125 * ---------------------------------
127 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
128 etscfg->tsatable[i] = buf[offset++];
132 * i40e_parse_ieee_etsrec_tlv
133 * @tlv: IEEE 802.1Qaz ETS REC TLV
134 * @dcbcfg: Local store to update ETS REC data
136 * Parses IEEE 802.1Qaz ETS REC TLV
138 static void i40e_parse_ieee_etsrec_tlv(struct i40e_lldp_org_tlv *tlv,
139 struct i40e_dcbx_config *dcbcfg)
141 u8 *buf = tlv->tlvinfo;
146 /* Move offset to priority table */
149 /* Priority Assignment Table (4 octets)
150 * Octets:| 1 | 2 | 3 | 4 |
151 * -----------------------------------------
152 * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
153 * -----------------------------------------
154 * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0|
155 * -----------------------------------------
157 for (i = 0; i < 4; i++) {
158 priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_1_MASK) >>
159 I40E_IEEE_ETS_PRIO_1_SHIFT);
160 dcbcfg->etsrec.prioritytable[i*2] = priority;
161 priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_0_MASK) >>
162 I40E_IEEE_ETS_PRIO_0_SHIFT);
163 dcbcfg->etsrec.prioritytable[i*2 + 1] = priority;
167 /* TC Bandwidth Table (8 octets)
168 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
169 * ---------------------------------
170 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
171 * ---------------------------------
173 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
174 dcbcfg->etsrec.tcbwtable[i] = buf[offset++];
176 /* TSA Assignment Table (8 octets)
177 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
178 * ---------------------------------
179 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
180 * ---------------------------------
182 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
183 dcbcfg->etsrec.tsatable[i] = buf[offset++];
187 * i40e_parse_ieee_pfccfg_tlv
188 * @tlv: IEEE 802.1Qaz PFC CFG TLV
189 * @dcbcfg: Local store to update PFC CFG data
191 * Parses IEEE 802.1Qaz PFC CFG TLV
193 static void i40e_parse_ieee_pfccfg_tlv(struct i40e_lldp_org_tlv *tlv,
194 struct i40e_dcbx_config *dcbcfg)
196 u8 *buf = tlv->tlvinfo;
198 /* ----------------------------------------
199 * |will-|MBC | Re- | PFC | PFC Enable |
200 * |ing | |served| cap | |
201 * -----------------------------------------
202 * |1bit | 1bit|2 bits|4bits| 1 octet |
204 dcbcfg->pfc.willing = (u8)((buf[0] & I40E_IEEE_PFC_WILLING_MASK) >>
205 I40E_IEEE_PFC_WILLING_SHIFT);
206 dcbcfg->pfc.mbc = (u8)((buf[0] & I40E_IEEE_PFC_MBC_MASK) >>
207 I40E_IEEE_PFC_MBC_SHIFT);
208 dcbcfg->pfc.pfccap = (u8)((buf[0] & I40E_IEEE_PFC_CAP_MASK) >>
209 I40E_IEEE_PFC_CAP_SHIFT);
210 dcbcfg->pfc.pfcenable = buf[1];
214 * i40e_parse_ieee_app_tlv
215 * @tlv: IEEE 802.1Qaz APP TLV
216 * @dcbcfg: Local store to update APP PRIO data
218 * Parses IEEE 802.1Qaz APP PRIO TLV
220 static void i40e_parse_ieee_app_tlv(struct i40e_lldp_org_tlv *tlv,
221 struct i40e_dcbx_config *dcbcfg)
229 typelength = I40E_NTOHS(tlv->typelength);
230 length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
231 I40E_LLDP_TLV_LEN_SHIFT);
234 /* The App priority table starts 5 octets after TLV header */
235 length -= (sizeof(tlv->ouisubtype) + 1);
237 /* Move offset to App Priority Table */
240 /* Application Priority Table (3 octets)
241 * Octets:| 1 | 2 | 3 |
242 * -----------------------------------------
243 * |Priority|Rsrvd| Sel | Protocol ID |
244 * -----------------------------------------
245 * Bits:|23 21|20 19|18 16|15 0|
246 * -----------------------------------------
248 while (offset < length) {
249 dcbcfg->app[i].priority = (u8)((buf[offset] &
250 I40E_IEEE_APP_PRIO_MASK) >>
251 I40E_IEEE_APP_PRIO_SHIFT);
252 dcbcfg->app[i].selector = (u8)((buf[offset] &
253 I40E_IEEE_APP_SEL_MASK) >>
254 I40E_IEEE_APP_SEL_SHIFT);
255 dcbcfg->app[i].protocolid = (buf[offset + 1] << 0x8) |
257 /* Move to next app */
260 if (i >= I40E_DCBX_MAX_APPS)
268 * i40e_parse_ieee_etsrec_tlv
269 * @tlv: IEEE 802.1Qaz TLV
270 * @dcbcfg: Local store to update ETS REC data
272 * Get the TLV subtype and send it to parsing function
273 * based on the subtype value
275 static void i40e_parse_ieee_tlv(struct i40e_lldp_org_tlv *tlv,
276 struct i40e_dcbx_config *dcbcfg)
281 ouisubtype = I40E_NTOHL(tlv->ouisubtype);
282 subtype = (u8)((ouisubtype & I40E_LLDP_TLV_SUBTYPE_MASK) >>
283 I40E_LLDP_TLV_SUBTYPE_SHIFT);
285 case I40E_IEEE_SUBTYPE_ETS_CFG:
286 i40e_parse_ieee_etscfg_tlv(tlv, dcbcfg);
288 case I40E_IEEE_SUBTYPE_ETS_REC:
289 i40e_parse_ieee_etsrec_tlv(tlv, dcbcfg);
291 case I40E_IEEE_SUBTYPE_PFC_CFG:
292 i40e_parse_ieee_pfccfg_tlv(tlv, dcbcfg);
294 case I40E_IEEE_SUBTYPE_APP_PRI:
295 i40e_parse_ieee_app_tlv(tlv, dcbcfg);
303 * i40e_parse_cee_pgcfg_tlv
304 * @tlv: CEE DCBX PG CFG TLV
305 * @dcbcfg: Local store to update ETS CFG data
307 * Parses CEE DCBX PG CFG TLV
309 static void i40e_parse_cee_pgcfg_tlv(struct i40e_cee_feat_tlv *tlv,
310 struct i40e_dcbx_config *dcbcfg)
312 struct i40e_dcb_ets_config *etscfg;
313 u8 *buf = tlv->tlvinfo;
318 etscfg = &dcbcfg->etscfg;
320 if (tlv->en_will_err & I40E_CEE_FEAT_TLV_WILLING_MASK)
324 /* Priority Group Table (4 octets)
325 * Octets:| 1 | 2 | 3 | 4 |
326 * -----------------------------------------
327 * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
328 * -----------------------------------------
329 * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0|
330 * -----------------------------------------
332 for (i = 0; i < 4; i++) {
333 priority = (u8)((buf[offset] & I40E_CEE_PGID_PRIO_1_MASK) >>
334 I40E_CEE_PGID_PRIO_1_SHIFT);
335 etscfg->prioritytable[i * 2] = priority;
336 priority = (u8)((buf[offset] & I40E_CEE_PGID_PRIO_0_MASK) >>
337 I40E_CEE_PGID_PRIO_0_SHIFT);
338 etscfg->prioritytable[i * 2 + 1] = priority;
342 /* PG Percentage Table (8 octets)
343 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
344 * ---------------------------------
345 * |pg0|pg1|pg2|pg3|pg4|pg5|pg6|pg7|
346 * ---------------------------------
348 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
349 etscfg->tcbwtable[i] = buf[offset++];
351 /* Number of TCs supported (1 octet) */
352 etscfg->maxtcs = buf[offset];
356 * i40e_parse_cee_pfccfg_tlv
357 * @tlv: CEE DCBX PFC CFG TLV
358 * @dcbcfg: Local store to update PFC CFG data
360 * Parses CEE DCBX PFC CFG TLV
362 static void i40e_parse_cee_pfccfg_tlv(struct i40e_cee_feat_tlv *tlv,
363 struct i40e_dcbx_config *dcbcfg)
365 u8 *buf = tlv->tlvinfo;
367 if (tlv->en_will_err & I40E_CEE_FEAT_TLV_WILLING_MASK)
368 dcbcfg->pfc.willing = 1;
370 /* ------------------------
371 * | PFC Enable | PFC TCs |
372 * ------------------------
373 * | 1 octet | 1 octet |
375 dcbcfg->pfc.pfcenable = buf[0];
376 dcbcfg->pfc.pfccap = buf[1];
380 * i40e_parse_cee_app_tlv
381 * @tlv: CEE DCBX APP TLV
382 * @dcbcfg: Local store to update APP PRIO data
384 * Parses CEE DCBX APP PRIO TLV
386 static void i40e_parse_cee_app_tlv(struct i40e_cee_feat_tlv *tlv,
387 struct i40e_dcbx_config *dcbcfg)
389 u16 length, typelength, offset = 0;
390 struct i40e_cee_app_prio *app;
393 typelength = I40E_NTOHS(tlv->hdr.typelen);
394 length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
395 I40E_LLDP_TLV_LEN_SHIFT);
397 dcbcfg->numapps = length / sizeof(*app);
398 if (!dcbcfg->numapps)
400 if (dcbcfg->numapps > I40E_DCBX_MAX_APPS)
401 dcbcfg->numapps = I40E_DCBX_MAX_APPS;
403 for (i = 0; i < dcbcfg->numapps; i++) {
406 app = (struct i40e_cee_app_prio *)(tlv->tlvinfo + offset);
407 for (up = 0; up < I40E_MAX_USER_PRIORITY; up++) {
408 if (app->prio_map & BIT(up))
411 dcbcfg->app[i].priority = up;
413 /* Get Selector from lower 2 bits, and convert to IEEE */
414 selector = (app->upper_oui_sel & I40E_CEE_APP_SELECTOR_MASK);
416 case I40E_CEE_APP_SEL_ETHTYPE:
417 dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE;
419 case I40E_CEE_APP_SEL_TCPIP:
420 dcbcfg->app[i].selector = I40E_APP_SEL_TCPIP;
423 /* Keep selector as it is for unknown types */
424 dcbcfg->app[i].selector = selector;
427 dcbcfg->app[i].protocolid = I40E_NTOHS(app->protocol);
428 /* Move to next app */
429 offset += sizeof(*app);
436 * @dcbcfg: Local store to update DCBX config data
438 * Get the TLV subtype and send it to parsing function
439 * based on the subtype value
441 static void i40e_parse_cee_tlv(struct i40e_lldp_org_tlv *tlv,
442 struct i40e_dcbx_config *dcbcfg)
444 u16 len, tlvlen, sublen, typelength;
445 struct i40e_cee_feat_tlv *sub_tlv;
446 u8 subtype, feat_tlv_count = 0;
449 ouisubtype = I40E_NTOHL(tlv->ouisubtype);
450 subtype = (u8)((ouisubtype & I40E_LLDP_TLV_SUBTYPE_MASK) >>
451 I40E_LLDP_TLV_SUBTYPE_SHIFT);
452 /* Return if not CEE DCBX */
453 if (subtype != I40E_CEE_DCBX_TYPE)
456 typelength = I40E_NTOHS(tlv->typelength);
457 tlvlen = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
458 I40E_LLDP_TLV_LEN_SHIFT);
459 len = sizeof(tlv->typelength) + sizeof(ouisubtype) +
460 sizeof(struct i40e_cee_ctrl_tlv);
461 /* Return if no CEE DCBX Feature TLVs */
465 sub_tlv = (struct i40e_cee_feat_tlv *)((char *)tlv + len);
466 while (feat_tlv_count < I40E_CEE_MAX_FEAT_TYPE) {
467 typelength = I40E_NTOHS(sub_tlv->hdr.typelen);
468 sublen = (u16)((typelength &
469 I40E_LLDP_TLV_LEN_MASK) >>
470 I40E_LLDP_TLV_LEN_SHIFT);
471 subtype = (u8)((typelength & I40E_LLDP_TLV_TYPE_MASK) >>
472 I40E_LLDP_TLV_TYPE_SHIFT);
474 case I40E_CEE_SUBTYPE_PG_CFG:
475 i40e_parse_cee_pgcfg_tlv(sub_tlv, dcbcfg);
477 case I40E_CEE_SUBTYPE_PFC_CFG:
478 i40e_parse_cee_pfccfg_tlv(sub_tlv, dcbcfg);
480 case I40E_CEE_SUBTYPE_APP_PRI:
481 i40e_parse_cee_app_tlv(sub_tlv, dcbcfg);
484 return; /* Invalid Sub-type return */
487 /* Move to next sub TLV */
488 sub_tlv = (struct i40e_cee_feat_tlv *)((char *)sub_tlv +
489 sizeof(sub_tlv->hdr.typelen) +
496 * @tlv: Organization specific TLV
497 * @dcbcfg: Local store to update ETS REC data
499 * Currently only IEEE 802.1Qaz TLV is supported, all others
502 static void i40e_parse_org_tlv(struct i40e_lldp_org_tlv *tlv,
503 struct i40e_dcbx_config *dcbcfg)
508 ouisubtype = I40E_NTOHL(tlv->ouisubtype);
509 oui = (u32)((ouisubtype & I40E_LLDP_TLV_OUI_MASK) >>
510 I40E_LLDP_TLV_OUI_SHIFT);
512 case I40E_IEEE_8021QAZ_OUI:
513 i40e_parse_ieee_tlv(tlv, dcbcfg);
515 case I40E_CEE_DCBX_OUI:
516 i40e_parse_cee_tlv(tlv, dcbcfg);
524 * i40e_lldp_to_dcb_config
525 * @lldpmib: LLDPDU to be parsed
526 * @dcbcfg: store for LLDPDU data
528 * Parse DCB configuration from the LLDPDU
530 enum i40e_status_code i40e_lldp_to_dcb_config(u8 *lldpmib,
531 struct i40e_dcbx_config *dcbcfg)
533 enum i40e_status_code ret = I40E_SUCCESS;
534 struct i40e_lldp_org_tlv *tlv;
540 if (!lldpmib || !dcbcfg)
541 return I40E_ERR_PARAM;
543 /* set to the start of LLDPDU */
544 lldpmib += I40E_LLDP_MIB_HLEN;
545 tlv = (struct i40e_lldp_org_tlv *)lldpmib;
547 typelength = I40E_NTOHS(tlv->typelength);
548 type = (u16)((typelength & I40E_LLDP_TLV_TYPE_MASK) >>
549 I40E_LLDP_TLV_TYPE_SHIFT);
550 length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
551 I40E_LLDP_TLV_LEN_SHIFT);
552 offset += sizeof(typelength) + length;
554 /* END TLV or beyond LLDPDU size */
555 if ((type == I40E_TLV_TYPE_END) || (offset > I40E_LLDPDU_SIZE))
559 case I40E_TLV_TYPE_ORG:
560 i40e_parse_org_tlv(tlv, dcbcfg);
566 /* Move to next TLV */
567 tlv = (struct i40e_lldp_org_tlv *)((char *)tlv +
568 sizeof(tlv->typelength) +
576 * i40e_aq_get_dcb_config
577 * @hw: pointer to the hw struct
578 * @mib_type: mib type for the query
579 * @bridgetype: bridge type for the query (remote)
580 * @dcbcfg: store for LLDPDU data
582 * Query DCB configuration from the Firmware
584 enum i40e_status_code i40e_aq_get_dcb_config(struct i40e_hw *hw, u8 mib_type,
586 struct i40e_dcbx_config *dcbcfg)
588 enum i40e_status_code ret = I40E_SUCCESS;
589 struct i40e_virt_mem mem;
592 /* Allocate the LLDPDU */
593 ret = i40e_allocate_virt_mem(hw, &mem, I40E_LLDPDU_SIZE);
597 lldpmib = (u8 *)mem.va;
598 ret = i40e_aq_get_lldp_mib(hw, bridgetype, mib_type,
599 (void *)lldpmib, I40E_LLDPDU_SIZE,
604 /* Parse LLDP MIB to get dcb configuration */
605 ret = i40e_lldp_to_dcb_config(lldpmib, dcbcfg);
608 i40e_free_virt_mem(hw, &mem);
613 * i40e_cee_to_dcb_v1_config
614 * @cee_cfg: pointer to CEE v1 response configuration struct
615 * @dcbcfg: DCB configuration struct
617 * Convert CEE v1 configuration from firmware to DCB configuration
619 static void i40e_cee_to_dcb_v1_config(
620 struct i40e_aqc_get_cee_dcb_cfg_v1_resp *cee_cfg,
621 struct i40e_dcbx_config *dcbcfg)
623 u16 status, tlv_status = LE16_TO_CPU(cee_cfg->tlv_status);
624 u16 app_prio = LE16_TO_CPU(cee_cfg->oper_app_prio);
627 /* CEE PG data to ETS config */
628 dcbcfg->etscfg.maxtcs = cee_cfg->oper_num_tc;
630 /* Note that the FW creates the oper_prio_tc nibbles reversed
631 * from those in the CEE Priority Group sub-TLV.
633 for (i = 0; i < 4; i++) {
634 tc = (u8)((cee_cfg->oper_prio_tc[i] &
635 I40E_CEE_PGID_PRIO_0_MASK) >>
636 I40E_CEE_PGID_PRIO_0_SHIFT);
637 dcbcfg->etscfg.prioritytable[i*2] = tc;
638 tc = (u8)((cee_cfg->oper_prio_tc[i] &
639 I40E_CEE_PGID_PRIO_1_MASK) >>
640 I40E_CEE_PGID_PRIO_1_SHIFT);
641 dcbcfg->etscfg.prioritytable[i*2 + 1] = tc;
644 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
645 dcbcfg->etscfg.tcbwtable[i] = cee_cfg->oper_tc_bw[i];
647 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
648 if (dcbcfg->etscfg.prioritytable[i] == I40E_CEE_PGID_STRICT) {
649 /* Map it to next empty TC */
650 dcbcfg->etscfg.prioritytable[i] =
651 cee_cfg->oper_num_tc - 1;
652 dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_STRICT;
654 dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS;
658 /* CEE PFC data to ETS config */
659 dcbcfg->pfc.pfcenable = cee_cfg->oper_pfc_en;
660 dcbcfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;
662 status = (tlv_status & I40E_AQC_CEE_APP_STATUS_MASK) >>
663 I40E_AQC_CEE_APP_STATUS_SHIFT;
664 err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
665 /* Add APPs if Error is False */
667 /* CEE operating configuration supports FCoE/iSCSI/FIP only */
668 dcbcfg->numapps = I40E_CEE_OPER_MAX_APPS;
671 dcbcfg->app[0].priority =
672 (app_prio & I40E_AQC_CEE_APP_FCOE_MASK) >>
673 I40E_AQC_CEE_APP_FCOE_SHIFT;
674 dcbcfg->app[0].selector = I40E_APP_SEL_ETHTYPE;
675 dcbcfg->app[0].protocolid = I40E_APP_PROTOID_FCOE;
678 dcbcfg->app[1].priority =
679 (app_prio & I40E_AQC_CEE_APP_ISCSI_MASK) >>
680 I40E_AQC_CEE_APP_ISCSI_SHIFT;
681 dcbcfg->app[1].selector = I40E_APP_SEL_TCPIP;
682 dcbcfg->app[1].protocolid = I40E_APP_PROTOID_ISCSI;
685 dcbcfg->app[2].priority =
686 (app_prio & I40E_AQC_CEE_APP_FIP_MASK) >>
687 I40E_AQC_CEE_APP_FIP_SHIFT;
688 dcbcfg->app[2].selector = I40E_APP_SEL_ETHTYPE;
689 dcbcfg->app[2].protocolid = I40E_APP_PROTOID_FIP;
694 * i40e_cee_to_dcb_config
695 * @cee_cfg: pointer to CEE configuration struct
696 * @dcbcfg: DCB configuration struct
698 * Convert CEE configuration from firmware to DCB configuration
700 static void i40e_cee_to_dcb_config(
701 struct i40e_aqc_get_cee_dcb_cfg_resp *cee_cfg,
702 struct i40e_dcbx_config *dcbcfg)
704 u32 status, tlv_status = LE32_TO_CPU(cee_cfg->tlv_status);
705 u16 app_prio = LE16_TO_CPU(cee_cfg->oper_app_prio);
706 u8 i, tc, err, sync, oper;
708 /* CEE PG data to ETS config */
709 dcbcfg->etscfg.maxtcs = cee_cfg->oper_num_tc;
711 /* Note that the FW creates the oper_prio_tc nibbles reversed
712 * from those in the CEE Priority Group sub-TLV.
714 for (i = 0; i < 4; i++) {
715 tc = (u8)((cee_cfg->oper_prio_tc[i] &
716 I40E_CEE_PGID_PRIO_0_MASK) >>
717 I40E_CEE_PGID_PRIO_0_SHIFT);
718 dcbcfg->etscfg.prioritytable[i*2] = tc;
719 tc = (u8)((cee_cfg->oper_prio_tc[i] &
720 I40E_CEE_PGID_PRIO_1_MASK) >>
721 I40E_CEE_PGID_PRIO_1_SHIFT);
722 dcbcfg->etscfg.prioritytable[i*2 + 1] = tc;
725 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
726 dcbcfg->etscfg.tcbwtable[i] = cee_cfg->oper_tc_bw[i];
728 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
729 if (dcbcfg->etscfg.prioritytable[i] == I40E_CEE_PGID_STRICT) {
730 /* Map it to next empty TC */
731 dcbcfg->etscfg.prioritytable[i] =
732 cee_cfg->oper_num_tc - 1;
733 dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_STRICT;
735 dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS;
739 /* CEE PFC data to ETS config */
740 dcbcfg->pfc.pfcenable = cee_cfg->oper_pfc_en;
741 dcbcfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;
744 status = (tlv_status & I40E_AQC_CEE_FCOE_STATUS_MASK) >>
745 I40E_AQC_CEE_FCOE_STATUS_SHIFT;
746 err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
747 sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0;
748 oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0;
749 /* Add FCoE APP if Error is False and Oper/Sync is True */
750 if (!err && sync && oper) {
752 dcbcfg->app[i].priority =
753 (app_prio & I40E_AQC_CEE_APP_FCOE_MASK) >>
754 I40E_AQC_CEE_APP_FCOE_SHIFT;
755 dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE;
756 dcbcfg->app[i].protocolid = I40E_APP_PROTOID_FCOE;
760 status = (tlv_status & I40E_AQC_CEE_ISCSI_STATUS_MASK) >>
761 I40E_AQC_CEE_ISCSI_STATUS_SHIFT;
762 err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
763 sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0;
764 oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0;
765 /* Add iSCSI APP if Error is False and Oper/Sync is True */
766 if (!err && sync && oper) {
768 dcbcfg->app[i].priority =
769 (app_prio & I40E_AQC_CEE_APP_ISCSI_MASK) >>
770 I40E_AQC_CEE_APP_ISCSI_SHIFT;
771 dcbcfg->app[i].selector = I40E_APP_SEL_TCPIP;
772 dcbcfg->app[i].protocolid = I40E_APP_PROTOID_ISCSI;
776 status = (tlv_status & I40E_AQC_CEE_FIP_STATUS_MASK) >>
777 I40E_AQC_CEE_FIP_STATUS_SHIFT;
778 err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
779 sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0;
780 oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0;
781 /* Add FIP APP if Error is False and Oper/Sync is True */
782 if (!err && sync && oper) {
784 dcbcfg->app[i].priority =
785 (app_prio & I40E_AQC_CEE_APP_FIP_MASK) >>
786 I40E_AQC_CEE_APP_FIP_SHIFT;
787 dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE;
788 dcbcfg->app[i].protocolid = I40E_APP_PROTOID_FIP;
795 * i40e_get_ieee_dcb_config
796 * @hw: pointer to the hw struct
798 * Get IEEE mode DCB configuration from the Firmware
800 static enum i40e_status_code i40e_get_ieee_dcb_config(struct i40e_hw *hw)
802 enum i40e_status_code ret = I40E_SUCCESS;
805 hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_IEEE;
806 /* Get Local DCB Config */
807 ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_LOCAL, 0,
808 &hw->local_dcbx_config);
812 /* Get Remote DCB Config */
813 ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_REMOTE,
814 I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE,
815 &hw->remote_dcbx_config);
816 /* Don't treat ENOENT as an error for Remote MIBs */
817 if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT)
825 * i40e_get_dcb_config
826 * @hw: pointer to the hw struct
828 * Get DCB configuration from the Firmware
830 enum i40e_status_code i40e_get_dcb_config(struct i40e_hw *hw)
832 enum i40e_status_code ret = I40E_SUCCESS;
833 struct i40e_aqc_get_cee_dcb_cfg_resp cee_cfg;
834 struct i40e_aqc_get_cee_dcb_cfg_v1_resp cee_v1_cfg;
836 /* If Firmware version < v4.33 on X710/XL710, IEEE only */
837 if ((hw->mac.type == I40E_MAC_XL710) &&
838 (((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver < 33)) ||
839 (hw->aq.fw_maj_ver < 4)))
840 return i40e_get_ieee_dcb_config(hw);
842 /* If Firmware version == v4.33 on X710/XL710, use old CEE struct */
843 if ((hw->mac.type == I40E_MAC_XL710) &&
844 ((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver == 33))) {
845 ret = i40e_aq_get_cee_dcb_config(hw, &cee_v1_cfg,
846 sizeof(cee_v1_cfg), NULL);
847 if (ret == I40E_SUCCESS) {
849 hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_CEE;
850 hw->local_dcbx_config.tlv_status =
851 LE16_TO_CPU(cee_v1_cfg.tlv_status);
852 i40e_cee_to_dcb_v1_config(&cee_v1_cfg,
853 &hw->local_dcbx_config);
856 ret = i40e_aq_get_cee_dcb_config(hw, &cee_cfg,
857 sizeof(cee_cfg), NULL);
858 if (ret == I40E_SUCCESS) {
860 hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_CEE;
861 hw->local_dcbx_config.tlv_status =
862 LE32_TO_CPU(cee_cfg.tlv_status);
863 i40e_cee_to_dcb_config(&cee_cfg,
864 &hw->local_dcbx_config);
868 /* CEE mode not enabled try querying IEEE data */
869 if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT)
870 return i40e_get_ieee_dcb_config(hw);
872 if (ret != I40E_SUCCESS)
875 /* Get CEE DCB Desired Config */
876 ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_LOCAL, 0,
877 &hw->desired_dcbx_config);
881 /* Get Remote DCB Config */
882 ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_REMOTE,
883 I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE,
884 &hw->remote_dcbx_config);
885 /* Don't treat ENOENT as an error for Remote MIBs */
886 if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT)
895 * @hw: pointer to the hw struct
896 * @enable_mib_change: enable mib change event
898 * Update DCB configuration from the Firmware
900 enum i40e_status_code i40e_init_dcb(struct i40e_hw *hw, bool enable_mib_change)
902 enum i40e_status_code ret = I40E_SUCCESS;
903 struct i40e_lldp_variables lldp_cfg;
906 if (!hw->func_caps.dcb)
907 return I40E_NOT_SUPPORTED;
909 /* Read LLDP NVM area */
910 ret = i40e_read_lldp_cfg(hw, &lldp_cfg);
912 return I40E_ERR_NOT_READY;
914 /* Get the LLDP AdminStatus for the current port */
915 adminstatus = lldp_cfg.adminstatus >> (hw->port * 4);
918 /* LLDP agent disabled */
920 hw->dcbx_status = I40E_DCBX_STATUS_DISABLED;
921 return I40E_ERR_NOT_READY;
924 /* Get DCBX status */
925 ret = i40e_get_dcbx_status(hw, &hw->dcbx_status);
929 /* Check the DCBX Status */
930 if (hw->dcbx_status == I40E_DCBX_STATUS_DONE ||
931 hw->dcbx_status == I40E_DCBX_STATUS_IN_PROGRESS) {
932 /* Get current DCBX configuration */
933 ret = i40e_get_dcb_config(hw);
936 } else if (hw->dcbx_status == I40E_DCBX_STATUS_DISABLED) {
937 return I40E_ERR_NOT_READY;
940 /* Configure the LLDP MIB change event */
941 if (enable_mib_change)
942 ret = i40e_aq_cfg_lldp_mib_change_event(hw, TRUE, NULL);
948 * i40e_get_fw_lldp_status
949 * @hw: pointer to the hw struct
950 * @lldp_status: pointer to the status enum
952 * Get status of FW Link Layer Discovery Protocol (LLDP) Agent.
953 * Status of agent is reported via @lldp_status parameter.
955 enum i40e_status_code
956 i40e_get_fw_lldp_status(struct i40e_hw *hw,
957 enum i40e_get_fw_lldp_status_resp *lldp_status)
959 enum i40e_status_code ret;
960 struct i40e_virt_mem mem;
964 return I40E_ERR_PARAM;
966 /* Allocate buffer for the LLDPDU */
967 ret = i40e_allocate_virt_mem(hw, &mem, I40E_LLDPDU_SIZE);
971 lldpmib = (u8 *)mem.va;
972 ret = i40e_aq_get_lldp_mib(hw, 0, 0, (void *)lldpmib,
973 I40E_LLDPDU_SIZE, NULL, NULL, NULL);
975 if (ret == I40E_SUCCESS) {
976 *lldp_status = I40E_GET_FW_LLDP_STATUS_ENABLED;
977 } else if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT) {
978 /* MIB is not available yet but the agent is running */
979 *lldp_status = I40E_GET_FW_LLDP_STATUS_ENABLED;
981 } else if (hw->aq.asq_last_status == I40E_AQ_RC_EPERM) {
982 *lldp_status = I40E_GET_FW_LLDP_STATUS_DISABLED;
986 i40e_free_virt_mem(hw, &mem);
992 * i40e_add_ieee_ets_tlv - Prepare ETS TLV in IEEE format
993 * @tlv: Fill the ETS config data in IEEE format
994 * @dcbcfg: Local store which holds the DCB Config
996 * Prepare IEEE 802.1Qaz ETS CFG TLV
998 static void i40e_add_ieee_ets_tlv(struct i40e_lldp_org_tlv *tlv,
999 struct i40e_dcbx_config *dcbcfg)
1001 u8 priority0, priority1, maxtcwilling = 0;
1002 struct i40e_dcb_ets_config *etscfg;
1003 u16 offset = 0, typelength, i;
1004 u8 *buf = tlv->tlvinfo;
1007 typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) |
1008 I40E_IEEE_ETS_TLV_LENGTH);
1009 tlv->typelength = I40E_HTONS(typelength);
1011 ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) |
1012 I40E_IEEE_SUBTYPE_ETS_CFG);
1013 tlv->ouisubtype = I40E_HTONL(ouisubtype);
1015 /* First Octet post subtype
1016 * --------------------------
1017 * |will-|CBS | Re- | Max |
1018 * |ing | |served| TCs |
1019 * --------------------------
1020 * |1bit | 1bit|3 bits|3bits|
1022 etscfg = &dcbcfg->etscfg;
1023 if (etscfg->willing)
1024 maxtcwilling = BIT(I40E_IEEE_ETS_WILLING_SHIFT);
1025 maxtcwilling |= etscfg->maxtcs & I40E_IEEE_ETS_MAXTC_MASK;
1026 buf[offset] = maxtcwilling;
1028 /* Move offset to Priority Assignment Table */
1031 /* Priority Assignment Table (4 octets)
1032 * Octets:| 1 | 2 | 3 | 4 |
1033 * -----------------------------------------
1034 * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
1035 * -----------------------------------------
1036 * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0|
1037 * -----------------------------------------
1039 for (i = 0; i < 4; i++) {
1040 priority0 = etscfg->prioritytable[i * 2] & 0xF;
1041 priority1 = etscfg->prioritytable[i * 2 + 1] & 0xF;
1042 buf[offset] = (priority0 << I40E_IEEE_ETS_PRIO_1_SHIFT) |
1047 /* TC Bandwidth Table (8 octets)
1048 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
1049 * ---------------------------------
1050 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
1051 * ---------------------------------
1053 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
1054 buf[offset++] = etscfg->tcbwtable[i];
1056 /* TSA Assignment Table (8 octets)
1057 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
1058 * ---------------------------------
1059 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
1060 * ---------------------------------
1062 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
1063 buf[offset++] = etscfg->tsatable[i];
1067 * i40e_add_ieee_etsrec_tlv - Prepare ETS Recommended TLV in IEEE format
1068 * @tlv: Fill ETS Recommended TLV in IEEE format
1069 * @dcbcfg: Local store which holds the DCB Config
1071 * Prepare IEEE 802.1Qaz ETS REC TLV
1073 static void i40e_add_ieee_etsrec_tlv(struct i40e_lldp_org_tlv *tlv,
1074 struct i40e_dcbx_config *dcbcfg)
1076 struct i40e_dcb_ets_config *etsrec;
1077 u16 offset = 0, typelength, i;
1078 u8 priority0, priority1;
1079 u8 *buf = tlv->tlvinfo;
1082 typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) |
1083 I40E_IEEE_ETS_TLV_LENGTH);
1084 tlv->typelength = I40E_HTONS(typelength);
1086 ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) |
1087 I40E_IEEE_SUBTYPE_ETS_REC);
1088 tlv->ouisubtype = I40E_HTONL(ouisubtype);
1090 etsrec = &dcbcfg->etsrec;
1091 /* First Octet is reserved */
1092 /* Move offset to Priority Assignment Table */
1095 /* Priority Assignment Table (4 octets)
1096 * Octets:| 1 | 2 | 3 | 4 |
1097 * -----------------------------------------
1098 * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
1099 * -----------------------------------------
1100 * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0|
1101 * -----------------------------------------
1103 for (i = 0; i < 4; i++) {
1104 priority0 = etsrec->prioritytable[i * 2] & 0xF;
1105 priority1 = etsrec->prioritytable[i * 2 + 1] & 0xF;
1106 buf[offset] = (priority0 << I40E_IEEE_ETS_PRIO_1_SHIFT) |
1111 /* TC Bandwidth Table (8 octets)
1112 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
1113 * ---------------------------------
1114 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
1115 * ---------------------------------
1117 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
1118 buf[offset++] = etsrec->tcbwtable[i];
1120 /* TSA Assignment Table (8 octets)
1121 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
1122 * ---------------------------------
1123 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
1124 * ---------------------------------
1126 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
1127 buf[offset++] = etsrec->tsatable[i];
1131 * i40e_add_ieee_pfc_tlv - Prepare PFC TLV in IEEE format
1132 * @tlv: Fill PFC TLV in IEEE format
1133 * @dcbcfg: Local store to get PFC CFG data
1135 * Prepare IEEE 802.1Qaz PFC CFG TLV
1137 static void i40e_add_ieee_pfc_tlv(struct i40e_lldp_org_tlv *tlv,
1138 struct i40e_dcbx_config *dcbcfg)
1140 u8 *buf = tlv->tlvinfo;
1144 typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) |
1145 I40E_IEEE_PFC_TLV_LENGTH);
1146 tlv->typelength = I40E_HTONS(typelength);
1148 ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) |
1149 I40E_IEEE_SUBTYPE_PFC_CFG);
1150 tlv->ouisubtype = I40E_HTONL(ouisubtype);
1152 /* ----------------------------------------
1153 * |will-|MBC | Re- | PFC | PFC Enable |
1154 * |ing | |served| cap | |
1155 * -----------------------------------------
1156 * |1bit | 1bit|2 bits|4bits| 1 octet |
1158 if (dcbcfg->pfc.willing)
1159 buf[0] = BIT(I40E_IEEE_PFC_WILLING_SHIFT);
1161 if (dcbcfg->pfc.mbc)
1162 buf[0] |= BIT(I40E_IEEE_PFC_MBC_SHIFT);
1164 buf[0] |= dcbcfg->pfc.pfccap & 0xF;
1165 buf[1] = dcbcfg->pfc.pfcenable;
1169 * i40e_add_ieee_app_pri_tlv - Prepare APP TLV in IEEE format
1170 * @tlv: Fill APP TLV in IEEE format
1171 * @dcbcfg: Local store to get APP CFG data
1173 * Prepare IEEE 802.1Qaz APP CFG TLV
1175 static void i40e_add_ieee_app_pri_tlv(struct i40e_lldp_org_tlv *tlv,
1176 struct i40e_dcbx_config *dcbcfg)
1178 u16 typelength, length, offset = 0;
1179 u8 priority, selector, i = 0;
1180 u8 *buf = tlv->tlvinfo;
1183 /* No APP TLVs then just return */
1184 if (dcbcfg->numapps == 0)
1186 ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) |
1187 I40E_IEEE_SUBTYPE_APP_PRI);
1188 tlv->ouisubtype = I40E_HTONL(ouisubtype);
1190 /* Move offset to App Priority Table */
1192 /* Application Priority Table (3 octets)
1193 * Octets:| 1 | 2 | 3 |
1194 * -----------------------------------------
1195 * |Priority|Rsrvd| Sel | Protocol ID |
1196 * -----------------------------------------
1197 * Bits:|23 21|20 19|18 16|15 0|
1198 * -----------------------------------------
1200 while (i < dcbcfg->numapps) {
1201 priority = dcbcfg->app[i].priority & 0x7;
1202 selector = dcbcfg->app[i].selector & 0x7;
1203 buf[offset] = (priority << I40E_IEEE_APP_PRIO_SHIFT) | selector;
1204 buf[offset + 1] = (dcbcfg->app[i].protocolid >> 0x8) & 0xFF;
1205 buf[offset + 2] = dcbcfg->app[i].protocolid & 0xFF;
1206 /* Move to next app */
1209 if (i >= I40E_DCBX_MAX_APPS)
1212 /* length includes size of ouisubtype + 1 reserved + 3*numapps */
1213 length = sizeof(tlv->ouisubtype) + 1 + (i*3);
1214 typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) |
1216 tlv->typelength = I40E_HTONS(typelength);
1220 * i40e_add_dcb_tlv - Add all IEEE TLVs
1221 * @tlv: pointer to org tlv
1223 * add tlv information
1225 static void i40e_add_dcb_tlv(struct i40e_lldp_org_tlv *tlv,
1226 struct i40e_dcbx_config *dcbcfg,
1230 case I40E_IEEE_TLV_ID_ETS_CFG:
1231 i40e_add_ieee_ets_tlv(tlv, dcbcfg);
1233 case I40E_IEEE_TLV_ID_ETS_REC:
1234 i40e_add_ieee_etsrec_tlv(tlv, dcbcfg);
1236 case I40E_IEEE_TLV_ID_PFC_CFG:
1237 i40e_add_ieee_pfc_tlv(tlv, dcbcfg);
1239 case I40E_IEEE_TLV_ID_APP_PRI:
1240 i40e_add_ieee_app_pri_tlv(tlv, dcbcfg);
1248 * i40e_set_dcb_config - Set the local LLDP MIB to FW
1249 * @hw: pointer to the hw struct
1251 * Set DCB configuration to the Firmware
1253 enum i40e_status_code i40e_set_dcb_config(struct i40e_hw *hw)
1255 enum i40e_status_code ret = I40E_SUCCESS;
1256 struct i40e_dcbx_config *dcbcfg;
1257 struct i40e_virt_mem mem;
1258 u8 mib_type, *lldpmib;
1261 /* update the hw local config */
1262 dcbcfg = &hw->local_dcbx_config;
1263 /* Allocate the LLDPDU */
1264 ret = i40e_allocate_virt_mem(hw, &mem, I40E_LLDPDU_SIZE);
1268 mib_type = SET_LOCAL_MIB_AC_TYPE_LOCAL_MIB;
1269 if (dcbcfg->app_mode == I40E_DCBX_APPS_NON_WILLING) {
1270 mib_type |= SET_LOCAL_MIB_AC_TYPE_NON_WILLING_APPS <<
1271 SET_LOCAL_MIB_AC_TYPE_NON_WILLING_APPS_SHIFT;
1273 lldpmib = (u8 *)mem.va;
1274 ret = i40e_dcb_config_to_lldp(lldpmib, &miblen, dcbcfg);
1275 ret = i40e_aq_set_lldp_mib(hw, mib_type, (void *)lldpmib, miblen, NULL);
1277 i40e_free_virt_mem(hw, &mem);
1282 * i40e_dcb_config_to_lldp - Convert Dcbconfig to MIB format
1283 * @hw: pointer to the hw struct
1284 * @dcbcfg: store for LLDPDU data
1286 * send DCB configuration to FW
1288 enum i40e_status_code i40e_dcb_config_to_lldp(u8 *lldpmib, u16 *miblen,
1289 struct i40e_dcbx_config *dcbcfg)
1291 u16 length, offset = 0, tlvid = I40E_TLV_ID_START;
1292 enum i40e_status_code ret = I40E_SUCCESS;
1293 struct i40e_lldp_org_tlv *tlv;
1296 tlv = (struct i40e_lldp_org_tlv *)lldpmib;
1298 i40e_add_dcb_tlv(tlv, dcbcfg, tlvid++);
1299 typelength = I40E_NTOHS(tlv->typelength);
1300 length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
1301 I40E_LLDP_TLV_LEN_SHIFT);
1303 offset += length + 2;
1304 /* END TLV or beyond LLDPDU size */
1305 if ((tlvid >= I40E_TLV_ID_END_OF_LLDPPDU) ||
1306 (offset > I40E_LLDPDU_SIZE))
1308 /* Move to next TLV */
1310 tlv = (struct i40e_lldp_org_tlv *)((char *)tlv +
1311 sizeof(tlv->typelength) + length);
1319 * _i40e_read_lldp_cfg - generic read of LLDP Configuration data from NVM
1320 * @hw: pointer to the HW structure
1321 * @lldp_cfg: pointer to hold lldp configuration variables
1322 * @module: address of the module pointer
1323 * @word_offset: offset of LLDP configuration
1325 * Reads the LLDP configuration data from NVM using passed addresses
1327 static enum i40e_status_code _i40e_read_lldp_cfg(struct i40e_hw *hw,
1328 struct i40e_lldp_variables *lldp_cfg,
1329 u8 module, u32 word_offset)
1331 u32 address, offset = (2 * word_offset);
1332 enum i40e_status_code ret;
1336 ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
1337 if (ret != I40E_SUCCESS)
1340 ret = i40e_aq_read_nvm(hw, 0x0, module * 2, sizeof(raw_mem), &raw_mem,
1342 i40e_release_nvm(hw);
1343 if (ret != I40E_SUCCESS)
1346 mem = LE16_TO_CPU(raw_mem);
1347 /* Check if this pointer needs to be read in word size or 4K sector
1350 if (mem & I40E_PTR_TYPE)
1351 address = (0x7FFF & mem) * 4096;
1353 address = (0x7FFF & mem) * 2;
1355 ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
1356 if (ret != I40E_SUCCESS)
1359 ret = i40e_aq_read_nvm(hw, module, offset, sizeof(raw_mem), &raw_mem,
1361 i40e_release_nvm(hw);
1362 if (ret != I40E_SUCCESS)
1365 mem = LE16_TO_CPU(raw_mem);
1366 offset = mem + word_offset;
1369 ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
1370 if (ret != I40E_SUCCESS)
1373 ret = i40e_aq_read_nvm(hw, 0, address + offset,
1374 sizeof(struct i40e_lldp_variables), lldp_cfg,
1376 i40e_release_nvm(hw);
1383 * i40e_read_lldp_cfg - read LLDP Configuration data from NVM
1384 * @hw: pointer to the HW structure
1385 * @lldp_cfg: pointer to hold lldp configuration variables
1387 * Reads the LLDP configuration data from NVM
1389 enum i40e_status_code i40e_read_lldp_cfg(struct i40e_hw *hw,
1390 struct i40e_lldp_variables *lldp_cfg)
1392 enum i40e_status_code ret = I40E_SUCCESS;
1396 return I40E_ERR_PARAM;
1398 ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
1399 if (ret != I40E_SUCCESS)
1402 ret = i40e_aq_read_nvm(hw, I40E_SR_NVM_CONTROL_WORD, 0, sizeof(mem),
1404 i40e_release_nvm(hw);
1405 if (ret != I40E_SUCCESS)
1408 /* Read a bit that holds information whether we are running flat or
1409 * structured NVM image. Flat image has LLDP configuration in shadow
1410 * ram, so there is a need to pass different addresses for both cases.
1412 if (mem & I40E_SR_NVM_MAP_STRUCTURE_TYPE) {
1414 ret = _i40e_read_lldp_cfg(hw, lldp_cfg, I40E_SR_EMP_MODULE_PTR,
1415 I40E_SR_LLDP_CFG_PTR);
1417 /* Good old structured NVM image */
1418 ret = _i40e_read_lldp_cfg(hw, lldp_cfg, I40E_EMP_MODULE_PTR,
1419 I40E_NVM_LLDP_CFG_PTR);