1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2013 - 2021 Intel Corporation. */
3
4 #include <linux/bitfield.h>
5 #include "i40e_adminq.h"
6 #include "i40e_alloc.h"
7 #include "i40e_dcb.h"
8 #include "i40e_prototype.h"
9
10 /**
11 * i40e_get_dcbx_status
12 * @hw: pointer to the hw struct
13 * @status: Embedded DCBX Engine Status
14 *
15 * Get the DCBX status from the Firmware
16 **/
i40e_get_dcbx_status(struct i40e_hw * hw,u16 * status)17 int i40e_get_dcbx_status(struct i40e_hw *hw, u16 *status)
18 {
19 u32 reg;
20
21 if (!status)
22 return -EINVAL;
23
24 reg = rd32(hw, I40E_PRTDCB_GENS);
25 *status = (u16)((reg & I40E_PRTDCB_GENS_DCBX_STATUS_MASK) >>
26 I40E_PRTDCB_GENS_DCBX_STATUS_SHIFT);
27
28 return 0;
29 }
30
31 /**
32 * i40e_parse_ieee_etscfg_tlv
33 * @tlv: IEEE 802.1Qaz ETS CFG TLV
34 * @dcbcfg: Local store to update ETS CFG data
35 *
36 * Parses IEEE 802.1Qaz ETS CFG TLV
37 **/
i40e_parse_ieee_etscfg_tlv(struct i40e_lldp_org_tlv * tlv,struct i40e_dcbx_config * dcbcfg)38 static void i40e_parse_ieee_etscfg_tlv(struct i40e_lldp_org_tlv *tlv,
39 struct i40e_dcbx_config *dcbcfg)
40 {
41 struct i40e_dcb_ets_config *etscfg;
42 u8 *buf = tlv->tlvinfo;
43 u16 offset = 0;
44 u8 priority;
45 int i;
46
47 /* First Octet post subtype
48 * --------------------------
49 * |will-|CBS | Re- | Max |
50 * |ing | |served| TCs |
51 * --------------------------
52 * |1bit | 1bit|3 bits|3bits|
53 */
54 etscfg = &dcbcfg->etscfg;
55 etscfg->willing = (u8)((buf[offset] & I40E_IEEE_ETS_WILLING_MASK) >>
56 I40E_IEEE_ETS_WILLING_SHIFT);
57 etscfg->cbs = (u8)((buf[offset] & I40E_IEEE_ETS_CBS_MASK) >>
58 I40E_IEEE_ETS_CBS_SHIFT);
59 etscfg->maxtcs = (u8)((buf[offset] & I40E_IEEE_ETS_MAXTC_MASK) >>
60 I40E_IEEE_ETS_MAXTC_SHIFT);
61
62 /* Move offset to Priority Assignment Table */
63 offset++;
64
65 /* Priority Assignment Table (4 octets)
66 * Octets:| 1 | 2 | 3 | 4 |
67 * -----------------------------------------
68 * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
69 * -----------------------------------------
70 * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0|
71 * -----------------------------------------
72 */
73 for (i = 0; i < 4; i++) {
74 priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_1_MASK) >>
75 I40E_IEEE_ETS_PRIO_1_SHIFT);
76 etscfg->prioritytable[i * 2] = priority;
77 priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_0_MASK) >>
78 I40E_IEEE_ETS_PRIO_0_SHIFT);
79 etscfg->prioritytable[i * 2 + 1] = priority;
80 offset++;
81 }
82
83 /* TC Bandwidth Table (8 octets)
84 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
85 * ---------------------------------
86 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
87 * ---------------------------------
88 */
89 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
90 etscfg->tcbwtable[i] = buf[offset++];
91
92 /* TSA Assignment Table (8 octets)
93 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
94 * ---------------------------------
95 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
96 * ---------------------------------
97 */
98 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
99 etscfg->tsatable[i] = buf[offset++];
100 }
101
102 /**
103 * i40e_parse_ieee_etsrec_tlv
104 * @tlv: IEEE 802.1Qaz ETS REC TLV
105 * @dcbcfg: Local store to update ETS REC data
106 *
107 * Parses IEEE 802.1Qaz ETS REC TLV
108 **/
i40e_parse_ieee_etsrec_tlv(struct i40e_lldp_org_tlv * tlv,struct i40e_dcbx_config * dcbcfg)109 static void i40e_parse_ieee_etsrec_tlv(struct i40e_lldp_org_tlv *tlv,
110 struct i40e_dcbx_config *dcbcfg)
111 {
112 u8 *buf = tlv->tlvinfo;
113 u16 offset = 0;
114 u8 priority;
115 int i;
116
117 /* Move offset to priority table */
118 offset++;
119
120 /* Priority Assignment Table (4 octets)
121 * Octets:| 1 | 2 | 3 | 4 |
122 * -----------------------------------------
123 * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
124 * -----------------------------------------
125 * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0|
126 * -----------------------------------------
127 */
128 for (i = 0; i < 4; i++) {
129 priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_1_MASK) >>
130 I40E_IEEE_ETS_PRIO_1_SHIFT);
131 dcbcfg->etsrec.prioritytable[i*2] = priority;
132 priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_0_MASK) >>
133 I40E_IEEE_ETS_PRIO_0_SHIFT);
134 dcbcfg->etsrec.prioritytable[i*2 + 1] = priority;
135 offset++;
136 }
137
138 /* TC Bandwidth Table (8 octets)
139 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
140 * ---------------------------------
141 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
142 * ---------------------------------
143 */
144 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
145 dcbcfg->etsrec.tcbwtable[i] = buf[offset++];
146
147 /* TSA Assignment Table (8 octets)
148 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
149 * ---------------------------------
150 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
151 * ---------------------------------
152 */
153 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
154 dcbcfg->etsrec.tsatable[i] = buf[offset++];
155 }
156
157 /**
158 * i40e_parse_ieee_pfccfg_tlv
159 * @tlv: IEEE 802.1Qaz PFC CFG TLV
160 * @dcbcfg: Local store to update PFC CFG data
161 *
162 * Parses IEEE 802.1Qaz PFC CFG TLV
163 **/
i40e_parse_ieee_pfccfg_tlv(struct i40e_lldp_org_tlv * tlv,struct i40e_dcbx_config * dcbcfg)164 static void i40e_parse_ieee_pfccfg_tlv(struct i40e_lldp_org_tlv *tlv,
165 struct i40e_dcbx_config *dcbcfg)
166 {
167 u8 *buf = tlv->tlvinfo;
168
169 /* ----------------------------------------
170 * |will-|MBC | Re- | PFC | PFC Enable |
171 * |ing | |served| cap | |
172 * -----------------------------------------
173 * |1bit | 1bit|2 bits|4bits| 1 octet |
174 */
175 dcbcfg->pfc.willing = (u8)((buf[0] & I40E_IEEE_PFC_WILLING_MASK) >>
176 I40E_IEEE_PFC_WILLING_SHIFT);
177 dcbcfg->pfc.mbc = (u8)((buf[0] & I40E_IEEE_PFC_MBC_MASK) >>
178 I40E_IEEE_PFC_MBC_SHIFT);
179 dcbcfg->pfc.pfccap = (u8)((buf[0] & I40E_IEEE_PFC_CAP_MASK) >>
180 I40E_IEEE_PFC_CAP_SHIFT);
181 dcbcfg->pfc.pfcenable = buf[1];
182 }
183
184 /**
185 * i40e_parse_ieee_app_tlv
186 * @tlv: IEEE 802.1Qaz APP TLV
187 * @dcbcfg: Local store to update APP PRIO data
188 *
189 * Parses IEEE 802.1Qaz APP PRIO TLV
190 **/
i40e_parse_ieee_app_tlv(struct i40e_lldp_org_tlv * tlv,struct i40e_dcbx_config * dcbcfg)191 static void i40e_parse_ieee_app_tlv(struct i40e_lldp_org_tlv *tlv,
192 struct i40e_dcbx_config *dcbcfg)
193 {
194 u16 typelength;
195 u16 offset = 0;
196 u16 length;
197 int i = 0;
198 u8 *buf;
199
200 typelength = ntohs(tlv->typelength);
201 length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
202 I40E_LLDP_TLV_LEN_SHIFT);
203 buf = tlv->tlvinfo;
204
205 /* The App priority table starts 5 octets after TLV header */
206 length -= (sizeof(tlv->ouisubtype) + 1);
207
208 /* Move offset to App Priority Table */
209 offset++;
210
211 /* Application Priority Table (3 octets)
212 * Octets:| 1 | 2 | 3 |
213 * -----------------------------------------
214 * |Priority|Rsrvd| Sel | Protocol ID |
215 * -----------------------------------------
216 * Bits:|23 21|20 19|18 16|15 0|
217 * -----------------------------------------
218 */
219 while (offset < length) {
220 dcbcfg->app[i].priority = (u8)((buf[offset] &
221 I40E_IEEE_APP_PRIO_MASK) >>
222 I40E_IEEE_APP_PRIO_SHIFT);
223 dcbcfg->app[i].selector = (u8)((buf[offset] &
224 I40E_IEEE_APP_SEL_MASK) >>
225 I40E_IEEE_APP_SEL_SHIFT);
226 dcbcfg->app[i].protocolid = (buf[offset + 1] << 0x8) |
227 buf[offset + 2];
228 /* Move to next app */
229 offset += 3;
230 i++;
231 if (i >= I40E_DCBX_MAX_APPS)
232 break;
233 }
234
235 dcbcfg->numapps = i;
236 }
237
238 /**
239 * i40e_parse_ieee_tlv
240 * @tlv: IEEE 802.1Qaz TLV
241 * @dcbcfg: Local store to update ETS REC data
242 *
243 * Get the TLV subtype and send it to parsing function
244 * based on the subtype value
245 **/
i40e_parse_ieee_tlv(struct i40e_lldp_org_tlv * tlv,struct i40e_dcbx_config * dcbcfg)246 static void i40e_parse_ieee_tlv(struct i40e_lldp_org_tlv *tlv,
247 struct i40e_dcbx_config *dcbcfg)
248 {
249 u32 ouisubtype;
250 u8 subtype;
251
252 ouisubtype = ntohl(tlv->ouisubtype);
253 subtype = (u8)((ouisubtype & I40E_LLDP_TLV_SUBTYPE_MASK) >>
254 I40E_LLDP_TLV_SUBTYPE_SHIFT);
255 switch (subtype) {
256 case I40E_IEEE_SUBTYPE_ETS_CFG:
257 i40e_parse_ieee_etscfg_tlv(tlv, dcbcfg);
258 break;
259 case I40E_IEEE_SUBTYPE_ETS_REC:
260 i40e_parse_ieee_etsrec_tlv(tlv, dcbcfg);
261 break;
262 case I40E_IEEE_SUBTYPE_PFC_CFG:
263 i40e_parse_ieee_pfccfg_tlv(tlv, dcbcfg);
264 break;
265 case I40E_IEEE_SUBTYPE_APP_PRI:
266 i40e_parse_ieee_app_tlv(tlv, dcbcfg);
267 break;
268 default:
269 break;
270 }
271 }
272
273 /**
274 * i40e_parse_cee_pgcfg_tlv
275 * @tlv: CEE DCBX PG CFG TLV
276 * @dcbcfg: Local store to update ETS CFG data
277 *
278 * Parses CEE DCBX PG CFG TLV
279 **/
i40e_parse_cee_pgcfg_tlv(struct i40e_cee_feat_tlv * tlv,struct i40e_dcbx_config * dcbcfg)280 static void i40e_parse_cee_pgcfg_tlv(struct i40e_cee_feat_tlv *tlv,
281 struct i40e_dcbx_config *dcbcfg)
282 {
283 struct i40e_dcb_ets_config *etscfg;
284 u8 *buf = tlv->tlvinfo;
285 u16 offset = 0;
286 u8 priority;
287 int i;
288
289 etscfg = &dcbcfg->etscfg;
290
291 if (tlv->en_will_err & I40E_CEE_FEAT_TLV_WILLING_MASK)
292 etscfg->willing = 1;
293
294 etscfg->cbs = 0;
295 /* Priority Group Table (4 octets)
296 * Octets:| 1 | 2 | 3 | 4 |
297 * -----------------------------------------
298 * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
299 * -----------------------------------------
300 * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0|
301 * -----------------------------------------
302 */
303 for (i = 0; i < 4; i++) {
304 priority = (u8)((buf[offset] & I40E_CEE_PGID_PRIO_1_MASK) >>
305 I40E_CEE_PGID_PRIO_1_SHIFT);
306 etscfg->prioritytable[i * 2] = priority;
307 priority = (u8)((buf[offset] & I40E_CEE_PGID_PRIO_0_MASK) >>
308 I40E_CEE_PGID_PRIO_0_SHIFT);
309 etscfg->prioritytable[i * 2 + 1] = priority;
310 offset++;
311 }
312
313 /* PG Percentage Table (8 octets)
314 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
315 * ---------------------------------
316 * |pg0|pg1|pg2|pg3|pg4|pg5|pg6|pg7|
317 * ---------------------------------
318 */
319 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
320 etscfg->tcbwtable[i] = buf[offset++];
321
322 /* Number of TCs supported (1 octet) */
323 etscfg->maxtcs = buf[offset];
324 }
325
326 /**
327 * i40e_parse_cee_pfccfg_tlv
328 * @tlv: CEE DCBX PFC CFG TLV
329 * @dcbcfg: Local store to update PFC CFG data
330 *
331 * Parses CEE DCBX PFC CFG TLV
332 **/
i40e_parse_cee_pfccfg_tlv(struct i40e_cee_feat_tlv * tlv,struct i40e_dcbx_config * dcbcfg)333 static void i40e_parse_cee_pfccfg_tlv(struct i40e_cee_feat_tlv *tlv,
334 struct i40e_dcbx_config *dcbcfg)
335 {
336 u8 *buf = tlv->tlvinfo;
337
338 if (tlv->en_will_err & I40E_CEE_FEAT_TLV_WILLING_MASK)
339 dcbcfg->pfc.willing = 1;
340
341 /* ------------------------
342 * | PFC Enable | PFC TCs |
343 * ------------------------
344 * | 1 octet | 1 octet |
345 */
346 dcbcfg->pfc.pfcenable = buf[0];
347 dcbcfg->pfc.pfccap = buf[1];
348 }
349
350 /**
351 * i40e_parse_cee_app_tlv
352 * @tlv: CEE DCBX APP TLV
353 * @dcbcfg: Local store to update APP PRIO data
354 *
355 * Parses CEE DCBX APP PRIO TLV
356 **/
i40e_parse_cee_app_tlv(struct i40e_cee_feat_tlv * tlv,struct i40e_dcbx_config * dcbcfg)357 static void i40e_parse_cee_app_tlv(struct i40e_cee_feat_tlv *tlv,
358 struct i40e_dcbx_config *dcbcfg)
359 {
360 u16 length, typelength, offset = 0;
361 struct i40e_cee_app_prio *app;
362 u8 i;
363
364 typelength = ntohs(tlv->hdr.typelen);
365 length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
366 I40E_LLDP_TLV_LEN_SHIFT);
367
368 dcbcfg->numapps = length / sizeof(*app);
369
370 if (!dcbcfg->numapps)
371 return;
372 if (dcbcfg->numapps > I40E_DCBX_MAX_APPS)
373 dcbcfg->numapps = I40E_DCBX_MAX_APPS;
374
375 for (i = 0; i < dcbcfg->numapps; i++) {
376 u8 up, selector;
377
378 app = (struct i40e_cee_app_prio *)(tlv->tlvinfo + offset);
379 for (up = 0; up < I40E_MAX_USER_PRIORITY; up++) {
380 if (app->prio_map & BIT(up))
381 break;
382 }
383 dcbcfg->app[i].priority = up;
384
385 /* Get Selector from lower 2 bits, and convert to IEEE */
386 selector = (app->upper_oui_sel & I40E_CEE_APP_SELECTOR_MASK);
387 switch (selector) {
388 case I40E_CEE_APP_SEL_ETHTYPE:
389 dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE;
390 break;
391 case I40E_CEE_APP_SEL_TCPIP:
392 dcbcfg->app[i].selector = I40E_APP_SEL_TCPIP;
393 break;
394 default:
395 /* Keep selector as it is for unknown types */
396 dcbcfg->app[i].selector = selector;
397 }
398
399 dcbcfg->app[i].protocolid = ntohs(app->protocol);
400 /* Move to next app */
401 offset += sizeof(*app);
402 }
403 }
404
405 /**
406 * i40e_parse_cee_tlv
407 * @tlv: CEE DCBX TLV
408 * @dcbcfg: Local store to update DCBX config data
409 *
410 * Get the TLV subtype and send it to parsing function
411 * based on the subtype value
412 **/
i40e_parse_cee_tlv(struct i40e_lldp_org_tlv * tlv,struct i40e_dcbx_config * dcbcfg)413 static void i40e_parse_cee_tlv(struct i40e_lldp_org_tlv *tlv,
414 struct i40e_dcbx_config *dcbcfg)
415 {
416 u16 len, tlvlen, sublen, typelength;
417 struct i40e_cee_feat_tlv *sub_tlv;
418 u8 subtype, feat_tlv_count = 0;
419 u32 ouisubtype;
420
421 ouisubtype = ntohl(tlv->ouisubtype);
422 subtype = (u8)((ouisubtype & I40E_LLDP_TLV_SUBTYPE_MASK) >>
423 I40E_LLDP_TLV_SUBTYPE_SHIFT);
424 /* Return if not CEE DCBX */
425 if (subtype != I40E_CEE_DCBX_TYPE)
426 return;
427
428 typelength = ntohs(tlv->typelength);
429 tlvlen = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
430 I40E_LLDP_TLV_LEN_SHIFT);
431 len = sizeof(tlv->typelength) + sizeof(ouisubtype) +
432 sizeof(struct i40e_cee_ctrl_tlv);
433 /* Return if no CEE DCBX Feature TLVs */
434 if (tlvlen <= len)
435 return;
436
437 sub_tlv = (struct i40e_cee_feat_tlv *)((char *)tlv + len);
438 while (feat_tlv_count < I40E_CEE_MAX_FEAT_TYPE) {
439 typelength = ntohs(sub_tlv->hdr.typelen);
440 sublen = (u16)((typelength &
441 I40E_LLDP_TLV_LEN_MASK) >>
442 I40E_LLDP_TLV_LEN_SHIFT);
443 subtype = (u8)((typelength & I40E_LLDP_TLV_TYPE_MASK) >>
444 I40E_LLDP_TLV_TYPE_SHIFT);
445 switch (subtype) {
446 case I40E_CEE_SUBTYPE_PG_CFG:
447 i40e_parse_cee_pgcfg_tlv(sub_tlv, dcbcfg);
448 break;
449 case I40E_CEE_SUBTYPE_PFC_CFG:
450 i40e_parse_cee_pfccfg_tlv(sub_tlv, dcbcfg);
451 break;
452 case I40E_CEE_SUBTYPE_APP_PRI:
453 i40e_parse_cee_app_tlv(sub_tlv, dcbcfg);
454 break;
455 default:
456 return; /* Invalid Sub-type return */
457 }
458 feat_tlv_count++;
459 /* Move to next sub TLV */
460 sub_tlv = (struct i40e_cee_feat_tlv *)((char *)sub_tlv +
461 sizeof(sub_tlv->hdr.typelen) +
462 sublen);
463 }
464 }
465
466 /**
467 * i40e_parse_org_tlv
468 * @tlv: Organization specific TLV
469 * @dcbcfg: Local store to update ETS REC data
470 *
471 * Currently only IEEE 802.1Qaz TLV is supported, all others
472 * will be returned
473 **/
i40e_parse_org_tlv(struct i40e_lldp_org_tlv * tlv,struct i40e_dcbx_config * dcbcfg)474 static void i40e_parse_org_tlv(struct i40e_lldp_org_tlv *tlv,
475 struct i40e_dcbx_config *dcbcfg)
476 {
477 u32 ouisubtype;
478 u32 oui;
479
480 ouisubtype = ntohl(tlv->ouisubtype);
481 oui = (u32)((ouisubtype & I40E_LLDP_TLV_OUI_MASK) >>
482 I40E_LLDP_TLV_OUI_SHIFT);
483 switch (oui) {
484 case I40E_IEEE_8021QAZ_OUI:
485 i40e_parse_ieee_tlv(tlv, dcbcfg);
486 break;
487 case I40E_CEE_DCBX_OUI:
488 i40e_parse_cee_tlv(tlv, dcbcfg);
489 break;
490 default:
491 break;
492 }
493 }
494
495 /**
496 * i40e_lldp_to_dcb_config
497 * @lldpmib: LLDPDU to be parsed
498 * @dcbcfg: store for LLDPDU data
499 *
500 * Parse DCB configuration from the LLDPDU
501 **/
i40e_lldp_to_dcb_config(u8 * lldpmib,struct i40e_dcbx_config * dcbcfg)502 int i40e_lldp_to_dcb_config(u8 *lldpmib,
503 struct i40e_dcbx_config *dcbcfg)
504 {
505 struct i40e_lldp_org_tlv *tlv;
506 u16 typelength;
507 u16 offset = 0;
508 int ret = 0;
509 u16 length;
510 u16 type;
511
512 if (!lldpmib || !dcbcfg)
513 return -EINVAL;
514
515 /* set to the start of LLDPDU */
516 lldpmib += ETH_HLEN;
517 tlv = (struct i40e_lldp_org_tlv *)lldpmib;
518 while (1) {
519 typelength = ntohs(tlv->typelength);
520 type = (u16)((typelength & I40E_LLDP_TLV_TYPE_MASK) >>
521 I40E_LLDP_TLV_TYPE_SHIFT);
522 length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
523 I40E_LLDP_TLV_LEN_SHIFT);
524 offset += sizeof(typelength) + length;
525
526 /* END TLV or beyond LLDPDU size */
527 if ((type == I40E_TLV_TYPE_END) || (offset > I40E_LLDPDU_SIZE))
528 break;
529
530 switch (type) {
531 case I40E_TLV_TYPE_ORG:
532 i40e_parse_org_tlv(tlv, dcbcfg);
533 break;
534 default:
535 break;
536 }
537
538 /* Move to next TLV */
539 tlv = (struct i40e_lldp_org_tlv *)((char *)tlv +
540 sizeof(tlv->typelength) +
541 length);
542 }
543
544 return ret;
545 }
546
547 /**
548 * i40e_aq_get_dcb_config
549 * @hw: pointer to the hw struct
550 * @mib_type: mib type for the query
551 * @bridgetype: bridge type for the query (remote)
552 * @dcbcfg: store for LLDPDU data
553 *
554 * Query DCB configuration from the Firmware
555 **/
i40e_aq_get_dcb_config(struct i40e_hw * hw,u8 mib_type,u8 bridgetype,struct i40e_dcbx_config * dcbcfg)556 int i40e_aq_get_dcb_config(struct i40e_hw *hw, u8 mib_type,
557 u8 bridgetype,
558 struct i40e_dcbx_config *dcbcfg)
559 {
560 struct i40e_virt_mem mem;
561 int ret = 0;
562 u8 *lldpmib;
563
564 /* Allocate the LLDPDU */
565 ret = i40e_allocate_virt_mem(hw, &mem, I40E_LLDPDU_SIZE);
566 if (ret)
567 return ret;
568
569 lldpmib = (u8 *)mem.va;
570 ret = i40e_aq_get_lldp_mib(hw, bridgetype, mib_type,
571 (void *)lldpmib, I40E_LLDPDU_SIZE,
572 NULL, NULL, NULL);
573 if (ret)
574 goto free_mem;
575
576 /* Parse LLDP MIB to get dcb configuration */
577 ret = i40e_lldp_to_dcb_config(lldpmib, dcbcfg);
578
579 free_mem:
580 i40e_free_virt_mem(hw, &mem);
581 return ret;
582 }
583
584 /**
585 * i40e_cee_to_dcb_v1_config
586 * @cee_cfg: pointer to CEE v1 response configuration struct
587 * @dcbcfg: DCB configuration struct
588 *
589 * Convert CEE v1 configuration from firmware to DCB configuration
590 **/
i40e_cee_to_dcb_v1_config(struct i40e_aqc_get_cee_dcb_cfg_v1_resp * cee_cfg,struct i40e_dcbx_config * dcbcfg)591 static void i40e_cee_to_dcb_v1_config(
592 struct i40e_aqc_get_cee_dcb_cfg_v1_resp *cee_cfg,
593 struct i40e_dcbx_config *dcbcfg)
594 {
595 u16 status, tlv_status = le16_to_cpu(cee_cfg->tlv_status);
596 u16 app_prio = le16_to_cpu(cee_cfg->oper_app_prio);
597 u8 i, tc, err;
598
599 /* CEE PG data to ETS config */
600 dcbcfg->etscfg.maxtcs = cee_cfg->oper_num_tc;
601
602 /* Note that the FW creates the oper_prio_tc nibbles reversed
603 * from those in the CEE Priority Group sub-TLV.
604 */
605 for (i = 0; i < 4; i++) {
606 tc = (u8)((cee_cfg->oper_prio_tc[i] &
607 I40E_CEE_PGID_PRIO_0_MASK) >>
608 I40E_CEE_PGID_PRIO_0_SHIFT);
609 dcbcfg->etscfg.prioritytable[i * 2] = tc;
610 tc = (u8)((cee_cfg->oper_prio_tc[i] &
611 I40E_CEE_PGID_PRIO_1_MASK) >>
612 I40E_CEE_PGID_PRIO_1_SHIFT);
613 dcbcfg->etscfg.prioritytable[i*2 + 1] = tc;
614 }
615
616 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
617 dcbcfg->etscfg.tcbwtable[i] = cee_cfg->oper_tc_bw[i];
618
619 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
620 if (dcbcfg->etscfg.prioritytable[i] == I40E_CEE_PGID_STRICT) {
621 /* Map it to next empty TC */
622 dcbcfg->etscfg.prioritytable[i] =
623 cee_cfg->oper_num_tc - 1;
624 dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_STRICT;
625 } else {
626 dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS;
627 }
628 }
629
630 /* CEE PFC data to ETS config */
631 dcbcfg->pfc.pfcenable = cee_cfg->oper_pfc_en;
632 dcbcfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;
633
634 status = (tlv_status & I40E_AQC_CEE_APP_STATUS_MASK) >>
635 I40E_AQC_CEE_APP_STATUS_SHIFT;
636 err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
637 /* Add APPs if Error is False */
638 if (!err) {
639 /* CEE operating configuration supports FCoE/iSCSI/FIP only */
640 dcbcfg->numapps = I40E_CEE_OPER_MAX_APPS;
641
642 /* FCoE APP */
643 dcbcfg->app[0].priority =
644 (app_prio & I40E_AQC_CEE_APP_FCOE_MASK) >>
645 I40E_AQC_CEE_APP_FCOE_SHIFT;
646 dcbcfg->app[0].selector = I40E_APP_SEL_ETHTYPE;
647 dcbcfg->app[0].protocolid = I40E_APP_PROTOID_FCOE;
648
649 /* iSCSI APP */
650 dcbcfg->app[1].priority =
651 (app_prio & I40E_AQC_CEE_APP_ISCSI_MASK) >>
652 I40E_AQC_CEE_APP_ISCSI_SHIFT;
653 dcbcfg->app[1].selector = I40E_APP_SEL_TCPIP;
654 dcbcfg->app[1].protocolid = I40E_APP_PROTOID_ISCSI;
655
656 /* FIP APP */
657 dcbcfg->app[2].priority =
658 (app_prio & I40E_AQC_CEE_APP_FIP_MASK) >>
659 I40E_AQC_CEE_APP_FIP_SHIFT;
660 dcbcfg->app[2].selector = I40E_APP_SEL_ETHTYPE;
661 dcbcfg->app[2].protocolid = I40E_APP_PROTOID_FIP;
662 }
663 }
664
665 /**
666 * i40e_cee_to_dcb_config
667 * @cee_cfg: pointer to CEE configuration struct
668 * @dcbcfg: DCB configuration struct
669 *
670 * Convert CEE configuration from firmware to DCB configuration
671 **/
i40e_cee_to_dcb_config(struct i40e_aqc_get_cee_dcb_cfg_resp * cee_cfg,struct i40e_dcbx_config * dcbcfg)672 static void i40e_cee_to_dcb_config(
673 struct i40e_aqc_get_cee_dcb_cfg_resp *cee_cfg,
674 struct i40e_dcbx_config *dcbcfg)
675 {
676 u32 status, tlv_status = le32_to_cpu(cee_cfg->tlv_status);
677 u16 app_prio = le16_to_cpu(cee_cfg->oper_app_prio);
678 u8 i, tc, err, sync, oper;
679
680 /* CEE PG data to ETS config */
681 dcbcfg->etscfg.maxtcs = cee_cfg->oper_num_tc;
682
683 /* Note that the FW creates the oper_prio_tc nibbles reversed
684 * from those in the CEE Priority Group sub-TLV.
685 */
686 for (i = 0; i < 4; i++) {
687 tc = (u8)((cee_cfg->oper_prio_tc[i] &
688 I40E_CEE_PGID_PRIO_0_MASK) >>
689 I40E_CEE_PGID_PRIO_0_SHIFT);
690 dcbcfg->etscfg.prioritytable[i * 2] = tc;
691 tc = (u8)((cee_cfg->oper_prio_tc[i] &
692 I40E_CEE_PGID_PRIO_1_MASK) >>
693 I40E_CEE_PGID_PRIO_1_SHIFT);
694 dcbcfg->etscfg.prioritytable[i * 2 + 1] = tc;
695 }
696
697 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
698 dcbcfg->etscfg.tcbwtable[i] = cee_cfg->oper_tc_bw[i];
699
700 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
701 if (dcbcfg->etscfg.prioritytable[i] == I40E_CEE_PGID_STRICT) {
702 /* Map it to next empty TC */
703 dcbcfg->etscfg.prioritytable[i] =
704 cee_cfg->oper_num_tc - 1;
705 dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_STRICT;
706 } else {
707 dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS;
708 }
709 }
710
711 /* CEE PFC data to ETS config */
712 dcbcfg->pfc.pfcenable = cee_cfg->oper_pfc_en;
713 dcbcfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;
714
715 i = 0;
716 status = (tlv_status & I40E_AQC_CEE_FCOE_STATUS_MASK) >>
717 I40E_AQC_CEE_FCOE_STATUS_SHIFT;
718 err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
719 sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0;
720 oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0;
721 /* Add FCoE APP if Error is False and Oper/Sync is True */
722 if (!err && sync && oper) {
723 /* FCoE APP */
724 dcbcfg->app[i].priority =
725 (app_prio & I40E_AQC_CEE_APP_FCOE_MASK) >>
726 I40E_AQC_CEE_APP_FCOE_SHIFT;
727 dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE;
728 dcbcfg->app[i].protocolid = I40E_APP_PROTOID_FCOE;
729 i++;
730 }
731
732 status = (tlv_status & I40E_AQC_CEE_ISCSI_STATUS_MASK) >>
733 I40E_AQC_CEE_ISCSI_STATUS_SHIFT;
734 err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
735 sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0;
736 oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0;
737 /* Add iSCSI APP if Error is False and Oper/Sync is True */
738 if (!err && sync && oper) {
739 /* iSCSI APP */
740 dcbcfg->app[i].priority =
741 (app_prio & I40E_AQC_CEE_APP_ISCSI_MASK) >>
742 I40E_AQC_CEE_APP_ISCSI_SHIFT;
743 dcbcfg->app[i].selector = I40E_APP_SEL_TCPIP;
744 dcbcfg->app[i].protocolid = I40E_APP_PROTOID_ISCSI;
745 i++;
746 }
747
748 status = (tlv_status & I40E_AQC_CEE_FIP_STATUS_MASK) >>
749 I40E_AQC_CEE_FIP_STATUS_SHIFT;
750 err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
751 sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0;
752 oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0;
753 /* Add FIP APP if Error is False and Oper/Sync is True */
754 if (!err && sync && oper) {
755 /* FIP APP */
756 dcbcfg->app[i].priority =
757 (app_prio & I40E_AQC_CEE_APP_FIP_MASK) >>
758 I40E_AQC_CEE_APP_FIP_SHIFT;
759 dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE;
760 dcbcfg->app[i].protocolid = I40E_APP_PROTOID_FIP;
761 i++;
762 }
763 dcbcfg->numapps = i;
764 }
765
766 /**
767 * i40e_get_ieee_dcb_config
768 * @hw: pointer to the hw struct
769 *
770 * Get IEEE mode DCB configuration from the Firmware
771 **/
i40e_get_ieee_dcb_config(struct i40e_hw * hw)772 static int i40e_get_ieee_dcb_config(struct i40e_hw *hw)
773 {
774 int ret = 0;
775
776 /* IEEE mode */
777 hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_IEEE;
778 /* Get Local DCB Config */
779 ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_LOCAL, 0,
780 &hw->local_dcbx_config);
781 if (ret)
782 goto out;
783
784 /* Get Remote DCB Config */
785 ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_REMOTE,
786 I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE,
787 &hw->remote_dcbx_config);
788 /* Don't treat ENOENT as an error for Remote MIBs */
789 if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT)
790 ret = 0;
791
792 out:
793 return ret;
794 }
795
796 /**
797 * i40e_get_dcb_config
798 * @hw: pointer to the hw struct
799 *
800 * Get DCB configuration from the Firmware
801 **/
i40e_get_dcb_config(struct i40e_hw * hw)802 int i40e_get_dcb_config(struct i40e_hw *hw)
803 {
804 struct i40e_aqc_get_cee_dcb_cfg_v1_resp cee_v1_cfg;
805 struct i40e_aqc_get_cee_dcb_cfg_resp cee_cfg;
806 int ret = 0;
807
808 /* If Firmware version < v4.33 on X710/XL710, IEEE only */
809 if ((hw->mac.type == I40E_MAC_XL710) &&
810 (((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver < 33)) ||
811 (hw->aq.fw_maj_ver < 4)))
812 return i40e_get_ieee_dcb_config(hw);
813
814 /* If Firmware version == v4.33 on X710/XL710, use old CEE struct */
815 if ((hw->mac.type == I40E_MAC_XL710) &&
816 ((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver == 33))) {
817 ret = i40e_aq_get_cee_dcb_config(hw, &cee_v1_cfg,
818 sizeof(cee_v1_cfg), NULL);
819 if (!ret) {
820 /* CEE mode */
821 hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_CEE;
822 hw->local_dcbx_config.tlv_status =
823 le16_to_cpu(cee_v1_cfg.tlv_status);
824 i40e_cee_to_dcb_v1_config(&cee_v1_cfg,
825 &hw->local_dcbx_config);
826 }
827 } else {
828 ret = i40e_aq_get_cee_dcb_config(hw, &cee_cfg,
829 sizeof(cee_cfg), NULL);
830 if (!ret) {
831 /* CEE mode */
832 hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_CEE;
833 hw->local_dcbx_config.tlv_status =
834 le32_to_cpu(cee_cfg.tlv_status);
835 i40e_cee_to_dcb_config(&cee_cfg,
836 &hw->local_dcbx_config);
837 }
838 }
839
840 /* CEE mode not enabled try querying IEEE data */
841 if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT)
842 return i40e_get_ieee_dcb_config(hw);
843
844 if (ret)
845 goto out;
846
847 /* Get CEE DCB Desired Config */
848 ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_LOCAL, 0,
849 &hw->desired_dcbx_config);
850 if (ret)
851 goto out;
852
853 /* Get Remote DCB Config */
854 ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_REMOTE,
855 I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE,
856 &hw->remote_dcbx_config);
857 /* Don't treat ENOENT as an error for Remote MIBs */
858 if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT)
859 ret = 0;
860
861 out:
862 return ret;
863 }
864
865 /**
866 * i40e_init_dcb
867 * @hw: pointer to the hw struct
868 * @enable_mib_change: enable mib change event
869 *
870 * Update DCB configuration from the Firmware
871 **/
i40e_init_dcb(struct i40e_hw * hw,bool enable_mib_change)872 int i40e_init_dcb(struct i40e_hw *hw, bool enable_mib_change)
873 {
874 struct i40e_lldp_variables lldp_cfg;
875 u8 adminstatus = 0;
876 int ret = 0;
877
878 if (!hw->func_caps.dcb)
879 return -EOPNOTSUPP;
880
881 /* Read LLDP NVM area */
882 if (hw->flags & I40E_HW_FLAG_FW_LLDP_PERSISTENT) {
883 u8 offset = 0;
884
885 if (hw->mac.type == I40E_MAC_XL710)
886 offset = I40E_LLDP_CURRENT_STATUS_XL710_OFFSET;
887 else if (hw->mac.type == I40E_MAC_X722)
888 offset = I40E_LLDP_CURRENT_STATUS_X722_OFFSET;
889 else
890 return -EOPNOTSUPP;
891
892 ret = i40e_read_nvm_module_data(hw,
893 I40E_SR_EMP_SR_SETTINGS_PTR,
894 offset,
895 I40E_LLDP_CURRENT_STATUS_OFFSET,
896 I40E_LLDP_CURRENT_STATUS_SIZE,
897 &lldp_cfg.adminstatus);
898 } else {
899 ret = i40e_read_lldp_cfg(hw, &lldp_cfg);
900 }
901 if (ret)
902 return -EBUSY;
903
904 /* Get the LLDP AdminStatus for the current port */
905 adminstatus = lldp_cfg.adminstatus >> (hw->port * 4);
906 adminstatus &= 0xF;
907
908 /* LLDP agent disabled */
909 if (!adminstatus) {
910 hw->dcbx_status = I40E_DCBX_STATUS_DISABLED;
911 return -EBUSY;
912 }
913
914 /* Get DCBX status */
915 ret = i40e_get_dcbx_status(hw, &hw->dcbx_status);
916 if (ret)
917 return ret;
918
919 /* Check the DCBX Status */
920 if (hw->dcbx_status == I40E_DCBX_STATUS_DONE ||
921 hw->dcbx_status == I40E_DCBX_STATUS_IN_PROGRESS) {
922 /* Get current DCBX configuration */
923 ret = i40e_get_dcb_config(hw);
924 if (ret)
925 return ret;
926 } else if (hw->dcbx_status == I40E_DCBX_STATUS_DISABLED) {
927 return -EBUSY;
928 }
929
930 /* Configure the LLDP MIB change event */
931 if (enable_mib_change)
932 ret = i40e_aq_cfg_lldp_mib_change_event(hw, true, NULL);
933
934 return ret;
935 }
936
937 /**
938 * i40e_get_fw_lldp_status
939 * @hw: pointer to the hw struct
940 * @lldp_status: pointer to the status enum
941 *
942 * Get status of FW Link Layer Discovery Protocol (LLDP) Agent.
943 * Status of agent is reported via @lldp_status parameter.
944 **/
945 int
i40e_get_fw_lldp_status(struct i40e_hw * hw,enum i40e_get_fw_lldp_status_resp * lldp_status)946 i40e_get_fw_lldp_status(struct i40e_hw *hw,
947 enum i40e_get_fw_lldp_status_resp *lldp_status)
948 {
949 struct i40e_virt_mem mem;
950 u8 *lldpmib;
951 int ret;
952
953 if (!lldp_status)
954 return -EINVAL;
955
956 /* Allocate buffer for the LLDPDU */
957 ret = i40e_allocate_virt_mem(hw, &mem, I40E_LLDPDU_SIZE);
958 if (ret)
959 return ret;
960
961 lldpmib = (u8 *)mem.va;
962 ret = i40e_aq_get_lldp_mib(hw, 0, 0, (void *)lldpmib,
963 I40E_LLDPDU_SIZE, NULL, NULL, NULL);
964
965 if (!ret) {
966 *lldp_status = I40E_GET_FW_LLDP_STATUS_ENABLED;
967 } else if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT) {
968 /* MIB is not available yet but the agent is running */
969 *lldp_status = I40E_GET_FW_LLDP_STATUS_ENABLED;
970 ret = 0;
971 } else if (hw->aq.asq_last_status == I40E_AQ_RC_EPERM) {
972 *lldp_status = I40E_GET_FW_LLDP_STATUS_DISABLED;
973 ret = 0;
974 }
975
976 i40e_free_virt_mem(hw, &mem);
977 return ret;
978 }
979
980 /**
981 * i40e_add_ieee_ets_tlv - Prepare ETS TLV in IEEE format
982 * @tlv: Fill the ETS config data in IEEE format
983 * @dcbcfg: Local store which holds the DCB Config
984 *
985 * Prepare IEEE 802.1Qaz ETS CFG TLV
986 **/
i40e_add_ieee_ets_tlv(struct i40e_lldp_org_tlv * tlv,struct i40e_dcbx_config * dcbcfg)987 static void i40e_add_ieee_ets_tlv(struct i40e_lldp_org_tlv *tlv,
988 struct i40e_dcbx_config *dcbcfg)
989 {
990 u8 priority0, priority1, maxtcwilling = 0;
991 struct i40e_dcb_ets_config *etscfg;
992 u16 offset = 0, typelength, i;
993 u8 *buf = tlv->tlvinfo;
994 u32 ouisubtype;
995
996 typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) |
997 I40E_IEEE_ETS_TLV_LENGTH);
998 tlv->typelength = htons(typelength);
999
1000 ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) |
1001 I40E_IEEE_SUBTYPE_ETS_CFG);
1002 tlv->ouisubtype = htonl(ouisubtype);
1003
1004 /* First Octet post subtype
1005 * --------------------------
1006 * |will-|CBS | Re- | Max |
1007 * |ing | |served| TCs |
1008 * --------------------------
1009 * |1bit | 1bit|3 bits|3bits|
1010 */
1011 etscfg = &dcbcfg->etscfg;
1012 if (etscfg->willing)
1013 maxtcwilling = BIT(I40E_IEEE_ETS_WILLING_SHIFT);
1014 maxtcwilling |= etscfg->maxtcs & I40E_IEEE_ETS_MAXTC_MASK;
1015 buf[offset] = maxtcwilling;
1016
1017 /* Move offset to Priority Assignment Table */
1018 offset++;
1019
1020 /* Priority Assignment Table (4 octets)
1021 * Octets:| 1 | 2 | 3 | 4 |
1022 * -----------------------------------------
1023 * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
1024 * -----------------------------------------
1025 * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0|
1026 * -----------------------------------------
1027 */
1028 for (i = 0; i < 4; i++) {
1029 priority0 = etscfg->prioritytable[i * 2] & 0xF;
1030 priority1 = etscfg->prioritytable[i * 2 + 1] & 0xF;
1031 buf[offset] = (priority0 << I40E_IEEE_ETS_PRIO_1_SHIFT) |
1032 priority1;
1033 offset++;
1034 }
1035
1036 /* TC Bandwidth Table (8 octets)
1037 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
1038 * ---------------------------------
1039 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
1040 * ---------------------------------
1041 */
1042 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
1043 buf[offset++] = etscfg->tcbwtable[i];
1044
1045 /* TSA Assignment Table (8 octets)
1046 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
1047 * ---------------------------------
1048 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
1049 * ---------------------------------
1050 */
1051 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
1052 buf[offset++] = etscfg->tsatable[i];
1053 }
1054
1055 /**
1056 * i40e_add_ieee_etsrec_tlv - Prepare ETS Recommended TLV in IEEE format
1057 * @tlv: Fill ETS Recommended TLV in IEEE format
1058 * @dcbcfg: Local store which holds the DCB Config
1059 *
1060 * Prepare IEEE 802.1Qaz ETS REC TLV
1061 **/
i40e_add_ieee_etsrec_tlv(struct i40e_lldp_org_tlv * tlv,struct i40e_dcbx_config * dcbcfg)1062 static void i40e_add_ieee_etsrec_tlv(struct i40e_lldp_org_tlv *tlv,
1063 struct i40e_dcbx_config *dcbcfg)
1064 {
1065 struct i40e_dcb_ets_config *etsrec;
1066 u16 offset = 0, typelength, i;
1067 u8 priority0, priority1;
1068 u8 *buf = tlv->tlvinfo;
1069 u32 ouisubtype;
1070
1071 typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) |
1072 I40E_IEEE_ETS_TLV_LENGTH);
1073 tlv->typelength = htons(typelength);
1074
1075 ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) |
1076 I40E_IEEE_SUBTYPE_ETS_REC);
1077 tlv->ouisubtype = htonl(ouisubtype);
1078
1079 etsrec = &dcbcfg->etsrec;
1080 /* First Octet is reserved */
1081 /* Move offset to Priority Assignment Table */
1082 offset++;
1083
1084 /* Priority Assignment Table (4 octets)
1085 * Octets:| 1 | 2 | 3 | 4 |
1086 * -----------------------------------------
1087 * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
1088 * -----------------------------------------
1089 * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0|
1090 * -----------------------------------------
1091 */
1092 for (i = 0; i < 4; i++) {
1093 priority0 = etsrec->prioritytable[i * 2] & 0xF;
1094 priority1 = etsrec->prioritytable[i * 2 + 1] & 0xF;
1095 buf[offset] = (priority0 << I40E_IEEE_ETS_PRIO_1_SHIFT) |
1096 priority1;
1097 offset++;
1098 }
1099
1100 /* TC Bandwidth Table (8 octets)
1101 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
1102 * ---------------------------------
1103 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
1104 * ---------------------------------
1105 */
1106 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
1107 buf[offset++] = etsrec->tcbwtable[i];
1108
1109 /* TSA Assignment Table (8 octets)
1110 * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
1111 * ---------------------------------
1112 * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
1113 * ---------------------------------
1114 */
1115 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
1116 buf[offset++] = etsrec->tsatable[i];
1117 }
1118
1119 /**
1120 * i40e_add_ieee_pfc_tlv - Prepare PFC TLV in IEEE format
1121 * @tlv: Fill PFC TLV in IEEE format
1122 * @dcbcfg: Local store to get PFC CFG data
1123 *
1124 * Prepare IEEE 802.1Qaz PFC CFG TLV
1125 **/
i40e_add_ieee_pfc_tlv(struct i40e_lldp_org_tlv * tlv,struct i40e_dcbx_config * dcbcfg)1126 static void i40e_add_ieee_pfc_tlv(struct i40e_lldp_org_tlv *tlv,
1127 struct i40e_dcbx_config *dcbcfg)
1128 {
1129 u8 *buf = tlv->tlvinfo;
1130 u32 ouisubtype;
1131 u16 typelength;
1132
1133 typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) |
1134 I40E_IEEE_PFC_TLV_LENGTH);
1135 tlv->typelength = htons(typelength);
1136
1137 ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) |
1138 I40E_IEEE_SUBTYPE_PFC_CFG);
1139 tlv->ouisubtype = htonl(ouisubtype);
1140
1141 /* ----------------------------------------
1142 * |will-|MBC | Re- | PFC | PFC Enable |
1143 * |ing | |served| cap | |
1144 * -----------------------------------------
1145 * |1bit | 1bit|2 bits|4bits| 1 octet |
1146 */
1147 if (dcbcfg->pfc.willing)
1148 buf[0] = BIT(I40E_IEEE_PFC_WILLING_SHIFT);
1149
1150 if (dcbcfg->pfc.mbc)
1151 buf[0] |= BIT(I40E_IEEE_PFC_MBC_SHIFT);
1152
1153 buf[0] |= dcbcfg->pfc.pfccap & 0xF;
1154 buf[1] = dcbcfg->pfc.pfcenable;
1155 }
1156
1157 /**
1158 * i40e_add_ieee_app_pri_tlv - Prepare APP TLV in IEEE format
1159 * @tlv: Fill APP TLV in IEEE format
1160 * @dcbcfg: Local store to get APP CFG data
1161 *
1162 * Prepare IEEE 802.1Qaz APP CFG TLV
1163 **/
i40e_add_ieee_app_pri_tlv(struct i40e_lldp_org_tlv * tlv,struct i40e_dcbx_config * dcbcfg)1164 static void i40e_add_ieee_app_pri_tlv(struct i40e_lldp_org_tlv *tlv,
1165 struct i40e_dcbx_config *dcbcfg)
1166 {
1167 u16 typelength, length, offset = 0;
1168 u8 priority, selector, i = 0;
1169 u8 *buf = tlv->tlvinfo;
1170 u32 ouisubtype;
1171
1172 /* No APP TLVs then just return */
1173 if (dcbcfg->numapps == 0)
1174 return;
1175 ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) |
1176 I40E_IEEE_SUBTYPE_APP_PRI);
1177 tlv->ouisubtype = htonl(ouisubtype);
1178
1179 /* Move offset to App Priority Table */
1180 offset++;
1181 /* Application Priority Table (3 octets)
1182 * Octets:| 1 | 2 | 3 |
1183 * -----------------------------------------
1184 * |Priority|Rsrvd| Sel | Protocol ID |
1185 * -----------------------------------------
1186 * Bits:|23 21|20 19|18 16|15 0|
1187 * -----------------------------------------
1188 */
1189 while (i < dcbcfg->numapps) {
1190 priority = dcbcfg->app[i].priority & 0x7;
1191 selector = dcbcfg->app[i].selector & 0x7;
1192 buf[offset] = (priority << I40E_IEEE_APP_PRIO_SHIFT) | selector;
1193 buf[offset + 1] = (dcbcfg->app[i].protocolid >> 0x8) & 0xFF;
1194 buf[offset + 2] = dcbcfg->app[i].protocolid & 0xFF;
1195 /* Move to next app */
1196 offset += 3;
1197 i++;
1198 if (i >= I40E_DCBX_MAX_APPS)
1199 break;
1200 }
1201 /* length includes size of ouisubtype + 1 reserved + 3*numapps */
1202 length = sizeof(tlv->ouisubtype) + 1 + (i * 3);
1203 typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) |
1204 (length & 0x1FF));
1205 tlv->typelength = htons(typelength);
1206 }
1207
1208 /**
1209 * i40e_add_dcb_tlv - Add all IEEE TLVs
1210 * @tlv: pointer to org tlv
1211 * @dcbcfg: pointer to modified dcbx config structure *
1212 * @tlvid: tlv id to be added
1213 * add tlv information
1214 **/
i40e_add_dcb_tlv(struct i40e_lldp_org_tlv * tlv,struct i40e_dcbx_config * dcbcfg,u16 tlvid)1215 static void i40e_add_dcb_tlv(struct i40e_lldp_org_tlv *tlv,
1216 struct i40e_dcbx_config *dcbcfg,
1217 u16 tlvid)
1218 {
1219 switch (tlvid) {
1220 case I40E_IEEE_TLV_ID_ETS_CFG:
1221 i40e_add_ieee_ets_tlv(tlv, dcbcfg);
1222 break;
1223 case I40E_IEEE_TLV_ID_ETS_REC:
1224 i40e_add_ieee_etsrec_tlv(tlv, dcbcfg);
1225 break;
1226 case I40E_IEEE_TLV_ID_PFC_CFG:
1227 i40e_add_ieee_pfc_tlv(tlv, dcbcfg);
1228 break;
1229 case I40E_IEEE_TLV_ID_APP_PRI:
1230 i40e_add_ieee_app_pri_tlv(tlv, dcbcfg);
1231 break;
1232 default:
1233 break;
1234 }
1235 }
1236
1237 /**
1238 * i40e_set_dcb_config - Set the local LLDP MIB to FW
1239 * @hw: pointer to the hw struct
1240 *
1241 * Set DCB configuration to the Firmware
1242 **/
i40e_set_dcb_config(struct i40e_hw * hw)1243 int i40e_set_dcb_config(struct i40e_hw *hw)
1244 {
1245 struct i40e_dcbx_config *dcbcfg;
1246 struct i40e_virt_mem mem;
1247 u8 mib_type, *lldpmib;
1248 u16 miblen;
1249 int ret;
1250
1251 /* update the hw local config */
1252 dcbcfg = &hw->local_dcbx_config;
1253 /* Allocate the LLDPDU */
1254 ret = i40e_allocate_virt_mem(hw, &mem, I40E_LLDPDU_SIZE);
1255 if (ret)
1256 return ret;
1257
1258 mib_type = SET_LOCAL_MIB_AC_TYPE_LOCAL_MIB;
1259 if (dcbcfg->app_mode == I40E_DCBX_APPS_NON_WILLING) {
1260 mib_type |= SET_LOCAL_MIB_AC_TYPE_NON_WILLING_APPS <<
1261 SET_LOCAL_MIB_AC_TYPE_NON_WILLING_APPS_SHIFT;
1262 }
1263 lldpmib = (u8 *)mem.va;
1264 i40e_dcb_config_to_lldp(lldpmib, &miblen, dcbcfg);
1265 ret = i40e_aq_set_lldp_mib(hw, mib_type, (void *)lldpmib, miblen, NULL);
1266
1267 i40e_free_virt_mem(hw, &mem);
1268 return ret;
1269 }
1270
1271 /**
1272 * i40e_dcb_config_to_lldp - Convert Dcbconfig to MIB format
1273 * @lldpmib: pointer to mib to be output
1274 * @miblen: pointer to u16 for length of lldpmib
1275 * @dcbcfg: store for LLDPDU data
1276 *
1277 * send DCB configuration to FW
1278 **/
i40e_dcb_config_to_lldp(u8 * lldpmib,u16 * miblen,struct i40e_dcbx_config * dcbcfg)1279 int i40e_dcb_config_to_lldp(u8 *lldpmib, u16 *miblen,
1280 struct i40e_dcbx_config *dcbcfg)
1281 {
1282 u16 length, offset = 0, tlvid, typelength;
1283 struct i40e_lldp_org_tlv *tlv;
1284
1285 tlv = (struct i40e_lldp_org_tlv *)lldpmib;
1286 tlvid = I40E_TLV_ID_START;
1287 do {
1288 i40e_add_dcb_tlv(tlv, dcbcfg, tlvid++);
1289 typelength = ntohs(tlv->typelength);
1290 length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
1291 I40E_LLDP_TLV_LEN_SHIFT);
1292 if (length)
1293 offset += length + I40E_IEEE_TLV_HEADER_LENGTH;
1294 /* END TLV or beyond LLDPDU size */
1295 if (tlvid >= I40E_TLV_ID_END_OF_LLDPPDU ||
1296 offset >= I40E_LLDPDU_SIZE)
1297 break;
1298 /* Move to next TLV */
1299 if (length)
1300 tlv = (struct i40e_lldp_org_tlv *)((char *)tlv +
1301 sizeof(tlv->typelength) + length);
1302 } while (tlvid < I40E_TLV_ID_END_OF_LLDPPDU);
1303 *miblen = offset;
1304 return 0;
1305 }
1306
1307 /**
1308 * i40e_dcb_hw_rx_fifo_config
1309 * @hw: pointer to the hw struct
1310 * @ets_mode: Strict Priority or Round Robin mode
1311 * @non_ets_mode: Strict Priority or Round Robin
1312 * @max_exponent: Exponent to calculate max refill credits
1313 * @lltc_map: Low latency TC bitmap
1314 *
1315 * Configure HW Rx FIFO as part of DCB configuration.
1316 **/
i40e_dcb_hw_rx_fifo_config(struct i40e_hw * hw,enum i40e_dcb_arbiter_mode ets_mode,enum i40e_dcb_arbiter_mode non_ets_mode,u32 max_exponent,u8 lltc_map)1317 void i40e_dcb_hw_rx_fifo_config(struct i40e_hw *hw,
1318 enum i40e_dcb_arbiter_mode ets_mode,
1319 enum i40e_dcb_arbiter_mode non_ets_mode,
1320 u32 max_exponent,
1321 u8 lltc_map)
1322 {
1323 u32 reg = rd32(hw, I40E_PRTDCB_RETSC);
1324
1325 reg &= ~I40E_PRTDCB_RETSC_ETS_MODE_MASK;
1326 reg |= ((u32)ets_mode << I40E_PRTDCB_RETSC_ETS_MODE_SHIFT) &
1327 I40E_PRTDCB_RETSC_ETS_MODE_MASK;
1328
1329 reg &= ~I40E_PRTDCB_RETSC_NON_ETS_MODE_MASK;
1330 reg |= ((u32)non_ets_mode << I40E_PRTDCB_RETSC_NON_ETS_MODE_SHIFT) &
1331 I40E_PRTDCB_RETSC_NON_ETS_MODE_MASK;
1332
1333 reg &= ~I40E_PRTDCB_RETSC_ETS_MAX_EXP_MASK;
1334 reg |= (max_exponent << I40E_PRTDCB_RETSC_ETS_MAX_EXP_SHIFT) &
1335 I40E_PRTDCB_RETSC_ETS_MAX_EXP_MASK;
1336
1337 reg &= ~I40E_PRTDCB_RETSC_LLTC_MASK;
1338 reg |= (lltc_map << I40E_PRTDCB_RETSC_LLTC_SHIFT) &
1339 I40E_PRTDCB_RETSC_LLTC_MASK;
1340 wr32(hw, I40E_PRTDCB_RETSC, reg);
1341 }
1342
1343 /**
1344 * i40e_dcb_hw_rx_cmd_monitor_config
1345 * @hw: pointer to the hw struct
1346 * @num_tc: Total number of traffic class
1347 * @num_ports: Total number of ports on device
1348 *
1349 * Configure HW Rx command monitor as part of DCB configuration.
1350 **/
i40e_dcb_hw_rx_cmd_monitor_config(struct i40e_hw * hw,u8 num_tc,u8 num_ports)1351 void i40e_dcb_hw_rx_cmd_monitor_config(struct i40e_hw *hw,
1352 u8 num_tc, u8 num_ports)
1353 {
1354 u32 threshold;
1355 u32 fifo_size;
1356 u32 reg;
1357
1358 /* Set the threshold and fifo_size based on number of ports */
1359 switch (num_ports) {
1360 case 1:
1361 threshold = I40E_DCB_1_PORT_THRESHOLD;
1362 fifo_size = I40E_DCB_1_PORT_FIFO_SIZE;
1363 break;
1364 case 2:
1365 if (num_tc > 4) {
1366 threshold = I40E_DCB_2_PORT_THRESHOLD_HIGH_NUM_TC;
1367 fifo_size = I40E_DCB_2_PORT_FIFO_SIZE_HIGH_NUM_TC;
1368 } else {
1369 threshold = I40E_DCB_2_PORT_THRESHOLD_LOW_NUM_TC;
1370 fifo_size = I40E_DCB_2_PORT_FIFO_SIZE_LOW_NUM_TC;
1371 }
1372 break;
1373 case 4:
1374 if (num_tc > 4) {
1375 threshold = I40E_DCB_4_PORT_THRESHOLD_HIGH_NUM_TC;
1376 fifo_size = I40E_DCB_4_PORT_FIFO_SIZE_HIGH_NUM_TC;
1377 } else {
1378 threshold = I40E_DCB_4_PORT_THRESHOLD_LOW_NUM_TC;
1379 fifo_size = I40E_DCB_4_PORT_FIFO_SIZE_LOW_NUM_TC;
1380 }
1381 break;
1382 default:
1383 i40e_debug(hw, I40E_DEBUG_DCB, "Invalid num_ports %u.\n",
1384 (u32)num_ports);
1385 return;
1386 }
1387
1388 /* The hardware manual describes setting up of I40E_PRT_SWR_PM_THR
1389 * based on the number of ports and traffic classes for a given port as
1390 * part of DCB configuration.
1391 */
1392 reg = rd32(hw, I40E_PRT_SWR_PM_THR);
1393 reg &= ~I40E_PRT_SWR_PM_THR_THRESHOLD_MASK;
1394 reg |= (threshold << I40E_PRT_SWR_PM_THR_THRESHOLD_SHIFT) &
1395 I40E_PRT_SWR_PM_THR_THRESHOLD_MASK;
1396 wr32(hw, I40E_PRT_SWR_PM_THR, reg);
1397
1398 reg = rd32(hw, I40E_PRTDCB_RPPMC);
1399 reg &= ~I40E_PRTDCB_RPPMC_RX_FIFO_SIZE_MASK;
1400 reg |= (fifo_size << I40E_PRTDCB_RPPMC_RX_FIFO_SIZE_SHIFT) &
1401 I40E_PRTDCB_RPPMC_RX_FIFO_SIZE_MASK;
1402 wr32(hw, I40E_PRTDCB_RPPMC, reg);
1403 }
1404
1405 /**
1406 * i40e_dcb_hw_pfc_config
1407 * @hw: pointer to the hw struct
1408 * @pfc_en: Bitmap of PFC enabled priorities
1409 * @prio_tc: priority to tc assignment indexed by priority
1410 *
1411 * Configure HW Priority Flow Controller as part of DCB configuration.
1412 **/
i40e_dcb_hw_pfc_config(struct i40e_hw * hw,u8 pfc_en,u8 * prio_tc)1413 void i40e_dcb_hw_pfc_config(struct i40e_hw *hw,
1414 u8 pfc_en, u8 *prio_tc)
1415 {
1416 u16 refresh_time = (u16)I40E_DEFAULT_PAUSE_TIME / 2;
1417 u32 link_speed = hw->phy.link_info.link_speed;
1418 u8 first_pfc_prio = 0;
1419 u8 num_pfc_tc = 0;
1420 u8 tc2pfc = 0;
1421 u32 reg;
1422 u8 i;
1423
1424 /* Get Number of PFC TCs and TC2PFC map */
1425 for (i = 0; i < I40E_MAX_USER_PRIORITY; i++) {
1426 if (pfc_en & BIT(i)) {
1427 if (!first_pfc_prio)
1428 first_pfc_prio = i;
1429 /* Set bit for the PFC TC */
1430 tc2pfc |= BIT(prio_tc[i]);
1431 num_pfc_tc++;
1432 }
1433 }
1434
1435 switch (link_speed) {
1436 case I40E_LINK_SPEED_10GB:
1437 reg = rd32(hw, I40E_PRTDCB_MFLCN);
1438 reg |= BIT(I40E_PRTDCB_MFLCN_DPF_SHIFT) &
1439 I40E_PRTDCB_MFLCN_DPF_MASK;
1440 reg &= ~I40E_PRTDCB_MFLCN_RFCE_MASK;
1441 reg &= ~I40E_PRTDCB_MFLCN_RPFCE_MASK;
1442 if (pfc_en) {
1443 reg |= BIT(I40E_PRTDCB_MFLCN_RPFCM_SHIFT) &
1444 I40E_PRTDCB_MFLCN_RPFCM_MASK;
1445 reg |= ((u32)pfc_en << I40E_PRTDCB_MFLCN_RPFCE_SHIFT) &
1446 I40E_PRTDCB_MFLCN_RPFCE_MASK;
1447 }
1448 wr32(hw, I40E_PRTDCB_MFLCN, reg);
1449
1450 reg = rd32(hw, I40E_PRTDCB_FCCFG);
1451 reg &= ~I40E_PRTDCB_FCCFG_TFCE_MASK;
1452 if (pfc_en)
1453 reg |= (I40E_DCB_PFC_ENABLED <<
1454 I40E_PRTDCB_FCCFG_TFCE_SHIFT) &
1455 I40E_PRTDCB_FCCFG_TFCE_MASK;
1456 wr32(hw, I40E_PRTDCB_FCCFG, reg);
1457
1458 /* FCTTV and FCRTV to be set by default */
1459 break;
1460 case I40E_LINK_SPEED_40GB:
1461 reg = rd32(hw, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP);
1462 reg &= ~I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP_MASK;
1463 wr32(hw, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP, reg);
1464
1465 reg = rd32(hw, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP);
1466 reg &= ~I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP_MASK;
1467 reg |= BIT(I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP_SHIFT) &
1468 I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP_MASK;
1469 wr32(hw, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP, reg);
1470
1471 reg = rd32(hw, I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE);
1472 reg &= ~I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_MASK;
1473 reg |= ((u32)pfc_en <<
1474 I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_SHIFT) &
1475 I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_MASK;
1476 wr32(hw, I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE, reg);
1477
1478 reg = rd32(hw, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE);
1479 reg &= ~I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_MASK;
1480 reg |= ((u32)pfc_en <<
1481 I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_SHIFT) &
1482 I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_MASK;
1483 wr32(hw, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE, reg);
1484
1485 for (i = 0; i < I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_MAX_INDEX; i++) {
1486 reg = rd32(hw, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER(i));
1487 reg &= ~I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_MASK;
1488 if (pfc_en) {
1489 reg |= ((u32)refresh_time <<
1490 I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_SHIFT) &
1491 I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_MASK;
1492 }
1493 wr32(hw, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER(i), reg);
1494 }
1495 /* PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA default value is 0xFFFF
1496 * for all user priorities
1497 */
1498 break;
1499 }
1500
1501 reg = rd32(hw, I40E_PRTDCB_TC2PFC);
1502 reg &= ~I40E_PRTDCB_TC2PFC_TC2PFC_MASK;
1503 reg |= ((u32)tc2pfc << I40E_PRTDCB_TC2PFC_TC2PFC_SHIFT) &
1504 I40E_PRTDCB_TC2PFC_TC2PFC_MASK;
1505 wr32(hw, I40E_PRTDCB_TC2PFC, reg);
1506
1507 reg = rd32(hw, I40E_PRTDCB_RUP);
1508 reg &= ~I40E_PRTDCB_RUP_NOVLANUP_MASK;
1509 reg |= ((u32)first_pfc_prio << I40E_PRTDCB_RUP_NOVLANUP_SHIFT) &
1510 I40E_PRTDCB_RUP_NOVLANUP_MASK;
1511 wr32(hw, I40E_PRTDCB_RUP, reg);
1512
1513 reg = rd32(hw, I40E_PRTDCB_TDPMC);
1514 reg &= ~I40E_PRTDCB_TDPMC_TCPM_MODE_MASK;
1515 if (num_pfc_tc > I40E_DCB_PFC_FORCED_NUM_TC) {
1516 reg |= BIT(I40E_PRTDCB_TDPMC_TCPM_MODE_SHIFT) &
1517 I40E_PRTDCB_TDPMC_TCPM_MODE_MASK;
1518 }
1519 wr32(hw, I40E_PRTDCB_TDPMC, reg);
1520
1521 reg = rd32(hw, I40E_PRTDCB_TCPMC);
1522 reg &= ~I40E_PRTDCB_TCPMC_TCPM_MODE_MASK;
1523 if (num_pfc_tc > I40E_DCB_PFC_FORCED_NUM_TC) {
1524 reg |= BIT(I40E_PRTDCB_TCPMC_TCPM_MODE_SHIFT) &
1525 I40E_PRTDCB_TCPMC_TCPM_MODE_MASK;
1526 }
1527 wr32(hw, I40E_PRTDCB_TCPMC, reg);
1528 }
1529
1530 /**
1531 * i40e_dcb_hw_set_num_tc
1532 * @hw: pointer to the hw struct
1533 * @num_tc: number of traffic classes
1534 *
1535 * Configure number of traffic classes in HW
1536 **/
i40e_dcb_hw_set_num_tc(struct i40e_hw * hw,u8 num_tc)1537 void i40e_dcb_hw_set_num_tc(struct i40e_hw *hw, u8 num_tc)
1538 {
1539 u32 reg = rd32(hw, I40E_PRTDCB_GENC);
1540
1541 reg &= ~I40E_PRTDCB_GENC_NUMTC_MASK;
1542 reg |= ((u32)num_tc << I40E_PRTDCB_GENC_NUMTC_SHIFT) &
1543 I40E_PRTDCB_GENC_NUMTC_MASK;
1544 wr32(hw, I40E_PRTDCB_GENC, reg);
1545 }
1546
1547 /**
1548 * i40e_dcb_hw_get_num_tc
1549 * @hw: pointer to the hw struct
1550 *
1551 * Returns number of traffic classes configured in HW
1552 **/
i40e_dcb_hw_get_num_tc(struct i40e_hw * hw)1553 u8 i40e_dcb_hw_get_num_tc(struct i40e_hw *hw)
1554 {
1555 u32 reg = rd32(hw, I40E_PRTDCB_GENC);
1556
1557 return (u8)((reg & I40E_PRTDCB_GENC_NUMTC_MASK) >>
1558 I40E_PRTDCB_GENC_NUMTC_SHIFT);
1559 }
1560
1561 /**
1562 * i40e_dcb_hw_rx_ets_bw_config
1563 * @hw: pointer to the hw struct
1564 * @bw_share: Bandwidth share indexed per traffic class
1565 * @mode: Strict Priority or Round Robin mode between UP sharing same
1566 * traffic class
1567 * @prio_type: TC is ETS enabled or strict priority
1568 *
1569 * Configure HW Rx ETS bandwidth as part of DCB configuration.
1570 **/
i40e_dcb_hw_rx_ets_bw_config(struct i40e_hw * hw,u8 * bw_share,u8 * mode,u8 * prio_type)1571 void i40e_dcb_hw_rx_ets_bw_config(struct i40e_hw *hw, u8 *bw_share,
1572 u8 *mode, u8 *prio_type)
1573 {
1574 u32 reg;
1575 u8 i;
1576
1577 for (i = 0; i <= I40E_PRTDCB_RETSTCC_MAX_INDEX; i++) {
1578 reg = rd32(hw, I40E_PRTDCB_RETSTCC(i));
1579 reg &= ~(I40E_PRTDCB_RETSTCC_BWSHARE_MASK |
1580 I40E_PRTDCB_RETSTCC_UPINTC_MODE_MASK |
1581 I40E_PRTDCB_RETSTCC_ETSTC_SHIFT);
1582 reg |= ((u32)bw_share[i] << I40E_PRTDCB_RETSTCC_BWSHARE_SHIFT) &
1583 I40E_PRTDCB_RETSTCC_BWSHARE_MASK;
1584 reg |= ((u32)mode[i] << I40E_PRTDCB_RETSTCC_UPINTC_MODE_SHIFT) &
1585 I40E_PRTDCB_RETSTCC_UPINTC_MODE_MASK;
1586 reg |= ((u32)prio_type[i] << I40E_PRTDCB_RETSTCC_ETSTC_SHIFT) &
1587 I40E_PRTDCB_RETSTCC_ETSTC_MASK;
1588 wr32(hw, I40E_PRTDCB_RETSTCC(i), reg);
1589 }
1590 }
1591
1592 /**
1593 * i40e_dcb_hw_rx_up2tc_config
1594 * @hw: pointer to the hw struct
1595 * @prio_tc: priority to tc assignment indexed by priority
1596 *
1597 * Configure HW Rx UP2TC map as part of DCB configuration.
1598 **/
i40e_dcb_hw_rx_up2tc_config(struct i40e_hw * hw,u8 * prio_tc)1599 void i40e_dcb_hw_rx_up2tc_config(struct i40e_hw *hw, u8 *prio_tc)
1600 {
1601 u32 reg = rd32(hw, I40E_PRTDCB_RUP2TC);
1602 #define I40E_UP2TC_REG(val, i) \
1603 (((val) << I40E_PRTDCB_RUP2TC_UP##i##TC_SHIFT) & \
1604 I40E_PRTDCB_RUP2TC_UP##i##TC_MASK)
1605
1606 reg |= I40E_UP2TC_REG(prio_tc[0], 0);
1607 reg |= I40E_UP2TC_REG(prio_tc[1], 1);
1608 reg |= I40E_UP2TC_REG(prio_tc[2], 2);
1609 reg |= I40E_UP2TC_REG(prio_tc[3], 3);
1610 reg |= I40E_UP2TC_REG(prio_tc[4], 4);
1611 reg |= I40E_UP2TC_REG(prio_tc[5], 5);
1612 reg |= I40E_UP2TC_REG(prio_tc[6], 6);
1613 reg |= I40E_UP2TC_REG(prio_tc[7], 7);
1614
1615 wr32(hw, I40E_PRTDCB_RUP2TC, reg);
1616 }
1617
1618 /**
1619 * i40e_dcb_hw_calculate_pool_sizes - configure dcb pool sizes
1620 * @hw: pointer to the hw struct
1621 * @num_ports: Number of available ports on the device
1622 * @eee_enabled: EEE enabled for the given port
1623 * @pfc_en: Bit map of PFC enabled traffic classes
1624 * @mfs_tc: Array of max frame size for each traffic class
1625 * @pb_cfg: pointer to packet buffer configuration
1626 *
1627 * Calculate the shared and dedicated per TC pool sizes,
1628 * watermarks and threshold values.
1629 **/
i40e_dcb_hw_calculate_pool_sizes(struct i40e_hw * hw,u8 num_ports,bool eee_enabled,u8 pfc_en,u32 * mfs_tc,struct i40e_rx_pb_config * pb_cfg)1630 void i40e_dcb_hw_calculate_pool_sizes(struct i40e_hw *hw,
1631 u8 num_ports, bool eee_enabled,
1632 u8 pfc_en, u32 *mfs_tc,
1633 struct i40e_rx_pb_config *pb_cfg)
1634 {
1635 u32 pool_size[I40E_MAX_TRAFFIC_CLASS];
1636 u32 high_wm[I40E_MAX_TRAFFIC_CLASS];
1637 u32 low_wm[I40E_MAX_TRAFFIC_CLASS];
1638 u32 total_pool_size = 0;
1639 int shared_pool_size; /* Need signed variable */
1640 u32 port_pb_size;
1641 u32 mfs_max = 0;
1642 u32 pcirtt;
1643 u8 i;
1644
1645 /* Get the MFS(max) for the port */
1646 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
1647 if (mfs_tc[i] > mfs_max)
1648 mfs_max = mfs_tc[i];
1649 }
1650
1651 pcirtt = I40E_BT2B(I40E_PCIRTT_LINK_SPEED_10G);
1652
1653 /* Calculate effective Rx PB size per port */
1654 port_pb_size = I40E_DEVICE_RPB_SIZE / num_ports;
1655 if (eee_enabled)
1656 port_pb_size -= I40E_BT2B(I40E_EEE_TX_LPI_EXIT_TIME);
1657 port_pb_size -= mfs_max;
1658
1659 /* Step 1 Calculating tc pool/shared pool sizes and watermarks */
1660 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
1661 if (pfc_en & BIT(i)) {
1662 low_wm[i] = (I40E_DCB_WATERMARK_START_FACTOR *
1663 mfs_tc[i]) + pcirtt;
1664 high_wm[i] = low_wm[i];
1665 high_wm[i] += ((mfs_max > I40E_MAX_FRAME_SIZE)
1666 ? mfs_max : I40E_MAX_FRAME_SIZE);
1667 pool_size[i] = high_wm[i];
1668 pool_size[i] += I40E_BT2B(I40E_STD_DV_TC(mfs_max,
1669 mfs_tc[i]));
1670 } else {
1671 low_wm[i] = 0;
1672 pool_size[i] = (I40E_DCB_WATERMARK_START_FACTOR *
1673 mfs_tc[i]) + pcirtt;
1674 high_wm[i] = pool_size[i];
1675 }
1676 total_pool_size += pool_size[i];
1677 }
1678
1679 shared_pool_size = port_pb_size - total_pool_size;
1680 if (shared_pool_size > 0) {
1681 pb_cfg->shared_pool_size = shared_pool_size;
1682 pb_cfg->shared_pool_high_wm = shared_pool_size;
1683 pb_cfg->shared_pool_low_wm = 0;
1684 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
1685 pb_cfg->shared_pool_low_thresh[i] = 0;
1686 pb_cfg->shared_pool_high_thresh[i] = shared_pool_size;
1687 pb_cfg->tc_pool_size[i] = pool_size[i];
1688 pb_cfg->tc_pool_high_wm[i] = high_wm[i];
1689 pb_cfg->tc_pool_low_wm[i] = low_wm[i];
1690 }
1691
1692 } else {
1693 i40e_debug(hw, I40E_DEBUG_DCB,
1694 "The shared pool size for the port is negative %d.\n",
1695 shared_pool_size);
1696 }
1697 }
1698
1699 /**
1700 * i40e_dcb_hw_rx_pb_config
1701 * @hw: pointer to the hw struct
1702 * @old_pb_cfg: Existing Rx Packet buffer configuration
1703 * @new_pb_cfg: New Rx Packet buffer configuration
1704 *
1705 * Program the Rx Packet Buffer registers.
1706 **/
i40e_dcb_hw_rx_pb_config(struct i40e_hw * hw,struct i40e_rx_pb_config * old_pb_cfg,struct i40e_rx_pb_config * new_pb_cfg)1707 void i40e_dcb_hw_rx_pb_config(struct i40e_hw *hw,
1708 struct i40e_rx_pb_config *old_pb_cfg,
1709 struct i40e_rx_pb_config *new_pb_cfg)
1710 {
1711 u32 old_val;
1712 u32 new_val;
1713 u32 reg;
1714 u8 i;
1715
1716 /* The Rx Packet buffer register programming needs to be done in a
1717 * certain order and the following code is based on that
1718 * requirement.
1719 */
1720
1721 /* Program the shared pool low water mark per port if decreasing */
1722 old_val = old_pb_cfg->shared_pool_low_wm;
1723 new_val = new_pb_cfg->shared_pool_low_wm;
1724 if (new_val < old_val) {
1725 reg = rd32(hw, I40E_PRTRPB_SLW);
1726 reg &= ~I40E_PRTRPB_SLW_SLW_MASK;
1727 reg |= (new_val << I40E_PRTRPB_SLW_SLW_SHIFT) &
1728 I40E_PRTRPB_SLW_SLW_MASK;
1729 wr32(hw, I40E_PRTRPB_SLW, reg);
1730 }
1731
1732 /* Program the shared pool low threshold and tc pool
1733 * low water mark per TC that are decreasing.
1734 */
1735 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
1736 old_val = old_pb_cfg->shared_pool_low_thresh[i];
1737 new_val = new_pb_cfg->shared_pool_low_thresh[i];
1738 if (new_val < old_val) {
1739 reg = rd32(hw, I40E_PRTRPB_SLT(i));
1740 reg &= ~I40E_PRTRPB_SLT_SLT_TCN_MASK;
1741 reg |= (new_val << I40E_PRTRPB_SLT_SLT_TCN_SHIFT) &
1742 I40E_PRTRPB_SLT_SLT_TCN_MASK;
1743 wr32(hw, I40E_PRTRPB_SLT(i), reg);
1744 }
1745
1746 old_val = old_pb_cfg->tc_pool_low_wm[i];
1747 new_val = new_pb_cfg->tc_pool_low_wm[i];
1748 if (new_val < old_val) {
1749 reg = rd32(hw, I40E_PRTRPB_DLW(i));
1750 reg &= ~I40E_PRTRPB_DLW_DLW_TCN_MASK;
1751 reg |= (new_val << I40E_PRTRPB_DLW_DLW_TCN_SHIFT) &
1752 I40E_PRTRPB_DLW_DLW_TCN_MASK;
1753 wr32(hw, I40E_PRTRPB_DLW(i), reg);
1754 }
1755 }
1756
1757 /* Program the shared pool high water mark per port if decreasing */
1758 old_val = old_pb_cfg->shared_pool_high_wm;
1759 new_val = new_pb_cfg->shared_pool_high_wm;
1760 if (new_val < old_val) {
1761 reg = rd32(hw, I40E_PRTRPB_SHW);
1762 reg &= ~I40E_PRTRPB_SHW_SHW_MASK;
1763 reg |= (new_val << I40E_PRTRPB_SHW_SHW_SHIFT) &
1764 I40E_PRTRPB_SHW_SHW_MASK;
1765 wr32(hw, I40E_PRTRPB_SHW, reg);
1766 }
1767
1768 /* Program the shared pool high threshold and tc pool
1769 * high water mark per TC that are decreasing.
1770 */
1771 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
1772 old_val = old_pb_cfg->shared_pool_high_thresh[i];
1773 new_val = new_pb_cfg->shared_pool_high_thresh[i];
1774 if (new_val < old_val) {
1775 reg = rd32(hw, I40E_PRTRPB_SHT(i));
1776 reg &= ~I40E_PRTRPB_SHT_SHT_TCN_MASK;
1777 reg |= (new_val << I40E_PRTRPB_SHT_SHT_TCN_SHIFT) &
1778 I40E_PRTRPB_SHT_SHT_TCN_MASK;
1779 wr32(hw, I40E_PRTRPB_SHT(i), reg);
1780 }
1781
1782 old_val = old_pb_cfg->tc_pool_high_wm[i];
1783 new_val = new_pb_cfg->tc_pool_high_wm[i];
1784 if (new_val < old_val) {
1785 reg = rd32(hw, I40E_PRTRPB_DHW(i));
1786 reg &= ~I40E_PRTRPB_DHW_DHW_TCN_MASK;
1787 reg |= (new_val << I40E_PRTRPB_DHW_DHW_TCN_SHIFT) &
1788 I40E_PRTRPB_DHW_DHW_TCN_MASK;
1789 wr32(hw, I40E_PRTRPB_DHW(i), reg);
1790 }
1791 }
1792
1793 /* Write Dedicated Pool Sizes per TC */
1794 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
1795 new_val = new_pb_cfg->tc_pool_size[i];
1796 reg = rd32(hw, I40E_PRTRPB_DPS(i));
1797 reg &= ~I40E_PRTRPB_DPS_DPS_TCN_MASK;
1798 reg |= (new_val << I40E_PRTRPB_DPS_DPS_TCN_SHIFT) &
1799 I40E_PRTRPB_DPS_DPS_TCN_MASK;
1800 wr32(hw, I40E_PRTRPB_DPS(i), reg);
1801 }
1802
1803 /* Write Shared Pool Size per port */
1804 new_val = new_pb_cfg->shared_pool_size;
1805 reg = rd32(hw, I40E_PRTRPB_SPS);
1806 reg &= ~I40E_PRTRPB_SPS_SPS_MASK;
1807 reg |= (new_val << I40E_PRTRPB_SPS_SPS_SHIFT) &
1808 I40E_PRTRPB_SPS_SPS_MASK;
1809 wr32(hw, I40E_PRTRPB_SPS, reg);
1810
1811 /* Program the shared pool low water mark per port if increasing */
1812 old_val = old_pb_cfg->shared_pool_low_wm;
1813 new_val = new_pb_cfg->shared_pool_low_wm;
1814 if (new_val > old_val) {
1815 reg = rd32(hw, I40E_PRTRPB_SLW);
1816 reg &= ~I40E_PRTRPB_SLW_SLW_MASK;
1817 reg |= (new_val << I40E_PRTRPB_SLW_SLW_SHIFT) &
1818 I40E_PRTRPB_SLW_SLW_MASK;
1819 wr32(hw, I40E_PRTRPB_SLW, reg);
1820 }
1821
1822 /* Program the shared pool low threshold and tc pool
1823 * low water mark per TC that are increasing.
1824 */
1825 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
1826 old_val = old_pb_cfg->shared_pool_low_thresh[i];
1827 new_val = new_pb_cfg->shared_pool_low_thresh[i];
1828 if (new_val > old_val) {
1829 reg = rd32(hw, I40E_PRTRPB_SLT(i));
1830 reg &= ~I40E_PRTRPB_SLT_SLT_TCN_MASK;
1831 reg |= (new_val << I40E_PRTRPB_SLT_SLT_TCN_SHIFT) &
1832 I40E_PRTRPB_SLT_SLT_TCN_MASK;
1833 wr32(hw, I40E_PRTRPB_SLT(i), reg);
1834 }
1835
1836 old_val = old_pb_cfg->tc_pool_low_wm[i];
1837 new_val = new_pb_cfg->tc_pool_low_wm[i];
1838 if (new_val > old_val) {
1839 reg = rd32(hw, I40E_PRTRPB_DLW(i));
1840 reg &= ~I40E_PRTRPB_DLW_DLW_TCN_MASK;
1841 reg |= (new_val << I40E_PRTRPB_DLW_DLW_TCN_SHIFT) &
1842 I40E_PRTRPB_DLW_DLW_TCN_MASK;
1843 wr32(hw, I40E_PRTRPB_DLW(i), reg);
1844 }
1845 }
1846
1847 /* Program the shared pool high water mark per port if increasing */
1848 old_val = old_pb_cfg->shared_pool_high_wm;
1849 new_val = new_pb_cfg->shared_pool_high_wm;
1850 if (new_val > old_val) {
1851 reg = rd32(hw, I40E_PRTRPB_SHW);
1852 reg &= ~I40E_PRTRPB_SHW_SHW_MASK;
1853 reg |= (new_val << I40E_PRTRPB_SHW_SHW_SHIFT) &
1854 I40E_PRTRPB_SHW_SHW_MASK;
1855 wr32(hw, I40E_PRTRPB_SHW, reg);
1856 }
1857
1858 /* Program the shared pool high threshold and tc pool
1859 * high water mark per TC that are increasing.
1860 */
1861 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
1862 old_val = old_pb_cfg->shared_pool_high_thresh[i];
1863 new_val = new_pb_cfg->shared_pool_high_thresh[i];
1864 if (new_val > old_val) {
1865 reg = rd32(hw, I40E_PRTRPB_SHT(i));
1866 reg &= ~I40E_PRTRPB_SHT_SHT_TCN_MASK;
1867 reg |= (new_val << I40E_PRTRPB_SHT_SHT_TCN_SHIFT) &
1868 I40E_PRTRPB_SHT_SHT_TCN_MASK;
1869 wr32(hw, I40E_PRTRPB_SHT(i), reg);
1870 }
1871
1872 old_val = old_pb_cfg->tc_pool_high_wm[i];
1873 new_val = new_pb_cfg->tc_pool_high_wm[i];
1874 if (new_val > old_val) {
1875 reg = rd32(hw, I40E_PRTRPB_DHW(i));
1876 reg &= ~I40E_PRTRPB_DHW_DHW_TCN_MASK;
1877 reg |= (new_val << I40E_PRTRPB_DHW_DHW_TCN_SHIFT) &
1878 I40E_PRTRPB_DHW_DHW_TCN_MASK;
1879 wr32(hw, I40E_PRTRPB_DHW(i), reg);
1880 }
1881 }
1882 }
1883
1884 /**
1885 * _i40e_read_lldp_cfg - generic read of LLDP Configuration data from NVM
1886 * @hw: pointer to the HW structure
1887 * @lldp_cfg: pointer to hold lldp configuration variables
1888 * @module: address of the module pointer
1889 * @word_offset: offset of LLDP configuration
1890 *
1891 * Reads the LLDP configuration data from NVM using passed addresses
1892 **/
_i40e_read_lldp_cfg(struct i40e_hw * hw,struct i40e_lldp_variables * lldp_cfg,u8 module,u32 word_offset)1893 static int _i40e_read_lldp_cfg(struct i40e_hw *hw,
1894 struct i40e_lldp_variables *lldp_cfg,
1895 u8 module, u32 word_offset)
1896 {
1897 u32 address, offset = (2 * word_offset);
1898 __le16 raw_mem;
1899 int ret;
1900 u16 mem;
1901
1902 ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
1903 if (ret)
1904 return ret;
1905
1906 ret = i40e_aq_read_nvm(hw, 0x0, module * 2, sizeof(raw_mem), &raw_mem,
1907 true, NULL);
1908 i40e_release_nvm(hw);
1909 if (ret)
1910 return ret;
1911
1912 mem = le16_to_cpu(raw_mem);
1913 /* Check if this pointer needs to be read in word size or 4K sector
1914 * units.
1915 */
1916 if (mem & I40E_PTR_TYPE)
1917 address = (0x7FFF & mem) * 4096;
1918 else
1919 address = (0x7FFF & mem) * 2;
1920
1921 ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
1922 if (ret)
1923 goto err_lldp_cfg;
1924
1925 ret = i40e_aq_read_nvm(hw, module, offset, sizeof(raw_mem), &raw_mem,
1926 true, NULL);
1927 i40e_release_nvm(hw);
1928 if (ret)
1929 return ret;
1930
1931 mem = le16_to_cpu(raw_mem);
1932 offset = mem + word_offset;
1933 offset *= 2;
1934
1935 ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
1936 if (ret)
1937 goto err_lldp_cfg;
1938
1939 ret = i40e_aq_read_nvm(hw, 0, address + offset,
1940 sizeof(struct i40e_lldp_variables), lldp_cfg,
1941 true, NULL);
1942 i40e_release_nvm(hw);
1943
1944 err_lldp_cfg:
1945 return ret;
1946 }
1947
1948 /**
1949 * i40e_read_lldp_cfg - read LLDP Configuration data from NVM
1950 * @hw: pointer to the HW structure
1951 * @lldp_cfg: pointer to hold lldp configuration variables
1952 *
1953 * Reads the LLDP configuration data from NVM
1954 **/
i40e_read_lldp_cfg(struct i40e_hw * hw,struct i40e_lldp_variables * lldp_cfg)1955 int i40e_read_lldp_cfg(struct i40e_hw *hw,
1956 struct i40e_lldp_variables *lldp_cfg)
1957 {
1958 int ret = 0;
1959 u32 mem;
1960
1961 if (!lldp_cfg)
1962 return -EINVAL;
1963
1964 ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
1965 if (ret)
1966 return ret;
1967
1968 ret = i40e_aq_read_nvm(hw, I40E_SR_NVM_CONTROL_WORD, 0, sizeof(mem),
1969 &mem, true, NULL);
1970 i40e_release_nvm(hw);
1971 if (ret)
1972 return ret;
1973
1974 /* Read a bit that holds information whether we are running flat or
1975 * structured NVM image. Flat image has LLDP configuration in shadow
1976 * ram, so there is a need to pass different addresses for both cases.
1977 */
1978 if (mem & I40E_SR_NVM_MAP_STRUCTURE_TYPE) {
1979 /* Flat NVM case */
1980 ret = _i40e_read_lldp_cfg(hw, lldp_cfg, I40E_SR_EMP_MODULE_PTR,
1981 I40E_SR_LLDP_CFG_PTR);
1982 } else {
1983 /* Good old structured NVM image */
1984 ret = _i40e_read_lldp_cfg(hw, lldp_cfg, I40E_EMP_MODULE_PTR,
1985 I40E_NVM_LLDP_CFG_PTR);
1986 }
1987
1988 return ret;
1989 }
1990