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