1 /* bnx2x_dcb.c: Broadcom Everest network driver.
2  *
3  * Copyright 2009-2010 Broadcom Corporation
4  *
5  * Unless you and Broadcom execute a separate written software license
6  * agreement governing use of this software, this software is licensed to you
7  * under the terms of the GNU General Public License version 2, available
8  * at http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL").
9  *
10  * Notwithstanding the above, under no circumstances may you combine this
11  * software in any way with any other Broadcom software provided under a
12  * license other than the GPL, without Broadcom's express prior written
13  * consent.
14  *
15  * Maintained by: Eilon Greenstein <eilong@broadcom.com>
16  * Written by: Dmitry Kravkov
17  *
18  */
19 #include <linux/netdevice.h>
20 #include <linux/types.h>
21 #include <linux/errno.h>
22 #ifdef BCM_DCBNL
23 #include <linux/dcbnl.h>
24 #endif
25 
26 #include "bnx2x.h"
27 #include "bnx2x_cmn.h"
28 #include "bnx2x_dcb.h"
29 
30 
31 /* forward declarations of dcbx related functions */
32 static void bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp);
33 static void bnx2x_pfc_set_pfc(struct bnx2x *bp);
34 static void bnx2x_dcbx_update_ets_params(struct bnx2x *bp);
35 static void bnx2x_dcbx_resume_hw_tx(struct bnx2x *bp);
36 static void bnx2x_dcbx_get_ets_pri_pg_tbl(struct bnx2x *bp,
37 					  u32 *set_configuration_ets_pg,
38 					  u32 *pri_pg_tbl);
39 static void bnx2x_dcbx_get_num_pg_traf_type(struct bnx2x *bp,
40 					    u32 *pg_pri_orginal_spread,
41 					    struct pg_help_data *help_data);
42 static void bnx2x_dcbx_fill_cos_params(struct bnx2x *bp,
43 				       struct pg_help_data *help_data,
44 				       struct dcbx_ets_feature *ets,
45 				       u32 *pg_pri_orginal_spread);
46 static void bnx2x_dcbx_separate_pauseable_from_non(struct bnx2x *bp,
47 				struct cos_help_data *cos_data,
48 				u32 *pg_pri_orginal_spread,
49 				struct dcbx_ets_feature *ets);
50 static void bnx2x_pfc_fw_struct_e2(struct bnx2x *bp);
51 
52 
bnx2x_pfc_set(struct bnx2x * bp)53 static void bnx2x_pfc_set(struct bnx2x *bp)
54 {
55 	struct bnx2x_nig_brb_pfc_port_params pfc_params = {0};
56 	u32 pri_bit, val = 0;
57 	u8 pri;
58 
59 	/* Tx COS configuration */
60 	if (bp->dcbx_port_params.ets.cos_params[0].pauseable)
61 		pfc_params.rx_cos0_priority_mask =
62 			bp->dcbx_port_params.ets.cos_params[0].pri_bitmask;
63 	if (bp->dcbx_port_params.ets.cos_params[1].pauseable)
64 		pfc_params.rx_cos1_priority_mask =
65 			bp->dcbx_port_params.ets.cos_params[1].pri_bitmask;
66 
67 
68 	/**
69 	 * Rx COS configuration
70 	 * Changing PFC RX configuration .
71 	 * In RX COS0 will always be configured to lossy and COS1 to lossless
72 	 */
73 	for (pri = 0 ; pri < MAX_PFC_PRIORITIES ; pri++) {
74 		pri_bit = 1 << pri;
75 
76 		if (pri_bit & DCBX_PFC_PRI_PAUSE_MASK(bp))
77 			val |= 1 << (pri * 4);
78 	}
79 
80 	pfc_params.pkt_priority_to_cos = val;
81 
82 	/* RX COS0 */
83 	pfc_params.llfc_low_priority_classes = 0;
84 	/* RX COS1 */
85 	pfc_params.llfc_high_priority_classes = DCBX_PFC_PRI_PAUSE_MASK(bp);
86 
87 	/* BRB configuration */
88 	pfc_params.cos0_pauseable = false;
89 	pfc_params.cos1_pauseable = true;
90 
91 	bnx2x_acquire_phy_lock(bp);
92 	bp->link_params.feature_config_flags |= FEATURE_CONFIG_PFC_ENABLED;
93 	bnx2x_update_pfc(&bp->link_params, &bp->link_vars, &pfc_params);
94 	bnx2x_release_phy_lock(bp);
95 }
96 
bnx2x_pfc_clear(struct bnx2x * bp)97 static void bnx2x_pfc_clear(struct bnx2x *bp)
98 {
99 	struct bnx2x_nig_brb_pfc_port_params nig_params = {0};
100 	nig_params.pause_enable = 1;
101 #ifdef BNX2X_SAFC
102 	if (bp->flags & SAFC_TX_FLAG) {
103 		u32 high = 0, low = 0;
104 		int i;
105 
106 		for (i = 0; i < BNX2X_MAX_PRIORITY; i++) {
107 			if (bp->pri_map[i] == 1)
108 				high |= (1 << i);
109 			if (bp->pri_map[i] == 0)
110 				low |= (1 << i);
111 		}
112 
113 		nig_params.llfc_low_priority_classes = high;
114 		nig_params.llfc_low_priority_classes = low;
115 
116 		nig_params.pause_enable = 0;
117 		nig_params.llfc_enable = 1;
118 		nig_params.llfc_out_en = 1;
119 	}
120 #endif /* BNX2X_SAFC */
121 	bnx2x_acquire_phy_lock(bp);
122 	bp->link_params.feature_config_flags &= ~FEATURE_CONFIG_PFC_ENABLED;
123 	bnx2x_update_pfc(&bp->link_params, &bp->link_vars, &nig_params);
124 	bnx2x_release_phy_lock(bp);
125 }
126 
bnx2x_dump_dcbx_drv_param(struct bnx2x * bp,struct dcbx_features * features,u32 error)127 static void  bnx2x_dump_dcbx_drv_param(struct bnx2x *bp,
128 				       struct dcbx_features *features,
129 				       u32 error)
130 {
131 	u8 i = 0;
132 	DP(NETIF_MSG_LINK, "local_mib.error %x\n", error);
133 
134 	/* PG */
135 	DP(NETIF_MSG_LINK,
136 	   "local_mib.features.ets.enabled %x\n", features->ets.enabled);
137 	for (i = 0; i < DCBX_MAX_NUM_PG_BW_ENTRIES; i++)
138 		DP(NETIF_MSG_LINK,
139 		   "local_mib.features.ets.pg_bw_tbl[%d] %d\n", i,
140 		   DCBX_PG_BW_GET(features->ets.pg_bw_tbl, i));
141 	for (i = 0; i < DCBX_MAX_NUM_PRI_PG_ENTRIES; i++)
142 		DP(NETIF_MSG_LINK,
143 		   "local_mib.features.ets.pri_pg_tbl[%d] %d\n", i,
144 		   DCBX_PRI_PG_GET(features->ets.pri_pg_tbl, i));
145 
146 	/* pfc */
147 	DP(NETIF_MSG_LINK, "dcbx_features.pfc.pri_en_bitmap %x\n",
148 					features->pfc.pri_en_bitmap);
149 	DP(NETIF_MSG_LINK, "dcbx_features.pfc.pfc_caps %x\n",
150 					features->pfc.pfc_caps);
151 	DP(NETIF_MSG_LINK, "dcbx_features.pfc.enabled %x\n",
152 					features->pfc.enabled);
153 
154 	DP(NETIF_MSG_LINK, "dcbx_features.app.default_pri %x\n",
155 					features->app.default_pri);
156 	DP(NETIF_MSG_LINK, "dcbx_features.app.tc_supported %x\n",
157 					features->app.tc_supported);
158 	DP(NETIF_MSG_LINK, "dcbx_features.app.enabled %x\n",
159 					features->app.enabled);
160 	for (i = 0; i < DCBX_MAX_APP_PROTOCOL; i++) {
161 		DP(NETIF_MSG_LINK,
162 		   "dcbx_features.app.app_pri_tbl[%x].app_id %x\n",
163 		   i, features->app.app_pri_tbl[i].app_id);
164 		DP(NETIF_MSG_LINK,
165 		   "dcbx_features.app.app_pri_tbl[%x].pri_bitmap %x\n",
166 		   i, features->app.app_pri_tbl[i].pri_bitmap);
167 		DP(NETIF_MSG_LINK,
168 		   "dcbx_features.app.app_pri_tbl[%x].appBitfield %x\n",
169 		   i, features->app.app_pri_tbl[i].appBitfield);
170 	}
171 }
172 
bnx2x_dcbx_get_ap_priority(struct bnx2x * bp,u8 pri_bitmap,u8 llfc_traf_type)173 static void bnx2x_dcbx_get_ap_priority(struct bnx2x *bp,
174 				       u8 pri_bitmap,
175 				       u8 llfc_traf_type)
176 {
177 	u32 pri = MAX_PFC_PRIORITIES;
178 	u32 index = MAX_PFC_PRIORITIES - 1;
179 	u32 pri_mask;
180 	u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority;
181 
182 	/* Choose the highest priority */
183 	while ((MAX_PFC_PRIORITIES == pri) && (0 != index)) {
184 		pri_mask = 1 << index;
185 		if (GET_FLAGS(pri_bitmap, pri_mask))
186 			pri = index ;
187 		index--;
188 	}
189 
190 	if (pri < MAX_PFC_PRIORITIES)
191 		ttp[llfc_traf_type] = max_t(u32, ttp[llfc_traf_type], pri);
192 }
193 
bnx2x_dcbx_get_ap_feature(struct bnx2x * bp,struct dcbx_app_priority_feature * app,u32 error)194 static void bnx2x_dcbx_get_ap_feature(struct bnx2x *bp,
195 				   struct dcbx_app_priority_feature *app,
196 				   u32 error) {
197 	u8 index;
198 	u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority;
199 
200 	if (GET_FLAGS(error, DCBX_LOCAL_APP_ERROR))
201 		DP(NETIF_MSG_LINK, "DCBX_LOCAL_APP_ERROR\n");
202 
203 	if (app->enabled && !GET_FLAGS(error, DCBX_LOCAL_APP_ERROR)) {
204 
205 		bp->dcbx_port_params.app.enabled = true;
206 
207 		for (index = 0 ; index < LLFC_DRIVER_TRAFFIC_TYPE_MAX; index++)
208 			ttp[index] = 0;
209 
210 		if (app->default_pri < MAX_PFC_PRIORITIES)
211 			ttp[LLFC_TRAFFIC_TYPE_NW] = app->default_pri;
212 
213 		for (index = 0 ; index < DCBX_MAX_APP_PROTOCOL; index++) {
214 			struct dcbx_app_priority_entry *entry =
215 							app->app_pri_tbl;
216 
217 			if (GET_FLAGS(entry[index].appBitfield,
218 				     DCBX_APP_SF_ETH_TYPE) &&
219 			   ETH_TYPE_FCOE == entry[index].app_id)
220 				bnx2x_dcbx_get_ap_priority(bp,
221 						entry[index].pri_bitmap,
222 						LLFC_TRAFFIC_TYPE_FCOE);
223 
224 			if (GET_FLAGS(entry[index].appBitfield,
225 				     DCBX_APP_SF_PORT) &&
226 			   TCP_PORT_ISCSI == entry[index].app_id)
227 				bnx2x_dcbx_get_ap_priority(bp,
228 						entry[index].pri_bitmap,
229 						LLFC_TRAFFIC_TYPE_ISCSI);
230 		}
231 	} else {
232 		DP(NETIF_MSG_LINK, "DCBX_LOCAL_APP_DISABLED\n");
233 		bp->dcbx_port_params.app.enabled = false;
234 		for (index = 0 ; index < LLFC_DRIVER_TRAFFIC_TYPE_MAX; index++)
235 			ttp[index] = INVALID_TRAFFIC_TYPE_PRIORITY;
236 	}
237 }
238 
bnx2x_dcbx_get_ets_feature(struct bnx2x * bp,struct dcbx_ets_feature * ets,u32 error)239 static void bnx2x_dcbx_get_ets_feature(struct bnx2x *bp,
240 				       struct dcbx_ets_feature *ets,
241 				       u32 error) {
242 	int i = 0;
243 	u32 pg_pri_orginal_spread[DCBX_MAX_NUM_PG_BW_ENTRIES] = {0};
244 	struct pg_help_data pg_help_data;
245 	struct bnx2x_dcbx_cos_params *cos_params =
246 			bp->dcbx_port_params.ets.cos_params;
247 
248 	memset(&pg_help_data, 0, sizeof(struct pg_help_data));
249 
250 
251 	if (GET_FLAGS(error, DCBX_LOCAL_ETS_ERROR))
252 		DP(NETIF_MSG_LINK, "DCBX_LOCAL_ETS_ERROR\n");
253 
254 
255 	/* Clean up old settings of ets on COS */
256 	for (i = 0; i < E2_NUM_OF_COS ; i++) {
257 
258 		cos_params[i].pauseable = false;
259 		cos_params[i].strict = BNX2X_DCBX_COS_NOT_STRICT;
260 		cos_params[i].bw_tbl = DCBX_INVALID_COS_BW;
261 		cos_params[i].pri_bitmask = DCBX_PFC_PRI_GET_NON_PAUSE(bp, 0);
262 	}
263 
264 	if (bp->dcbx_port_params.app.enabled &&
265 	   !GET_FLAGS(error, DCBX_LOCAL_ETS_ERROR) &&
266 	   ets->enabled) {
267 		DP(NETIF_MSG_LINK, "DCBX_LOCAL_ETS_ENABLE\n");
268 		bp->dcbx_port_params.ets.enabled = true;
269 
270 		bnx2x_dcbx_get_ets_pri_pg_tbl(bp,
271 					      pg_pri_orginal_spread,
272 					      ets->pri_pg_tbl);
273 
274 		bnx2x_dcbx_get_num_pg_traf_type(bp,
275 						pg_pri_orginal_spread,
276 						&pg_help_data);
277 
278 		bnx2x_dcbx_fill_cos_params(bp, &pg_help_data,
279 					   ets, pg_pri_orginal_spread);
280 
281 	} else {
282 		DP(NETIF_MSG_LINK, "DCBX_LOCAL_ETS_DISABLED\n");
283 		bp->dcbx_port_params.ets.enabled = false;
284 		ets->pri_pg_tbl[0] = 0;
285 
286 		for (i = 0; i < DCBX_MAX_NUM_PRI_PG_ENTRIES ; i++)
287 			DCBX_PG_BW_SET(ets->pg_bw_tbl, i, 1);
288 	}
289 }
290 
bnx2x_dcbx_get_pfc_feature(struct bnx2x * bp,struct dcbx_pfc_feature * pfc,u32 error)291 static void  bnx2x_dcbx_get_pfc_feature(struct bnx2x *bp,
292 					struct dcbx_pfc_feature *pfc, u32 error)
293 {
294 
295 	if (GET_FLAGS(error, DCBX_LOCAL_PFC_ERROR))
296 		DP(NETIF_MSG_LINK, "DCBX_LOCAL_PFC_ERROR\n");
297 
298 	if (bp->dcbx_port_params.app.enabled &&
299 	   !GET_FLAGS(error, DCBX_LOCAL_PFC_ERROR) &&
300 	   pfc->enabled) {
301 		bp->dcbx_port_params.pfc.enabled = true;
302 		bp->dcbx_port_params.pfc.priority_non_pauseable_mask =
303 			~(pfc->pri_en_bitmap);
304 	} else {
305 		DP(NETIF_MSG_LINK, "DCBX_LOCAL_PFC_DISABLED\n");
306 		bp->dcbx_port_params.pfc.enabled = false;
307 		bp->dcbx_port_params.pfc.priority_non_pauseable_mask = 0;
308 	}
309 }
310 
bnx2x_get_dcbx_drv_param(struct bnx2x * bp,struct dcbx_features * features,u32 error)311 static void bnx2x_get_dcbx_drv_param(struct bnx2x *bp,
312 				     struct dcbx_features *features,
313 				     u32 error)
314 {
315 	bnx2x_dcbx_get_ap_feature(bp, &features->app, error);
316 
317 	bnx2x_dcbx_get_pfc_feature(bp, &features->pfc, error);
318 
319 	bnx2x_dcbx_get_ets_feature(bp, &features->ets, error);
320 }
321 
322 #define DCBX_LOCAL_MIB_MAX_TRY_READ		(100)
bnx2x_dcbx_read_mib(struct bnx2x * bp,u32 * base_mib_addr,u32 offset,int read_mib_type)323 static int bnx2x_dcbx_read_mib(struct bnx2x *bp,
324 			       u32 *base_mib_addr,
325 			       u32 offset,
326 			       int read_mib_type)
327 {
328 	int max_try_read = 0, i;
329 	u32 *buff, mib_size, prefix_seq_num, suffix_seq_num;
330 	struct lldp_remote_mib *remote_mib ;
331 	struct lldp_local_mib  *local_mib;
332 
333 
334 	switch (read_mib_type) {
335 	case DCBX_READ_LOCAL_MIB:
336 		mib_size = sizeof(struct lldp_local_mib);
337 		break;
338 	case DCBX_READ_REMOTE_MIB:
339 		mib_size = sizeof(struct lldp_remote_mib);
340 		break;
341 	default:
342 		return 1; /*error*/
343 	}
344 
345 	offset += BP_PORT(bp) * mib_size;
346 
347 	do {
348 		buff = base_mib_addr;
349 		for (i = 0; i < mib_size; i += 4, buff++)
350 			*buff = REG_RD(bp, offset + i);
351 
352 		max_try_read++;
353 
354 		switch (read_mib_type) {
355 		case DCBX_READ_LOCAL_MIB:
356 			local_mib = (struct lldp_local_mib *) base_mib_addr;
357 			prefix_seq_num = local_mib->prefix_seq_num;
358 			suffix_seq_num = local_mib->suffix_seq_num;
359 			break;
360 		case DCBX_READ_REMOTE_MIB:
361 			remote_mib = (struct lldp_remote_mib *) base_mib_addr;
362 			prefix_seq_num = remote_mib->prefix_seq_num;
363 			suffix_seq_num = remote_mib->suffix_seq_num;
364 			break;
365 		default:
366 			return 1; /*error*/
367 		}
368 	} while ((prefix_seq_num != suffix_seq_num) &&
369 	       (max_try_read < DCBX_LOCAL_MIB_MAX_TRY_READ));
370 
371 	if (max_try_read >= DCBX_LOCAL_MIB_MAX_TRY_READ) {
372 		BNX2X_ERR("MIB could not be read\n");
373 		return 1;
374 	}
375 
376 	return 0;
377 }
378 
bnx2x_pfc_set_pfc(struct bnx2x * bp)379 static void bnx2x_pfc_set_pfc(struct bnx2x *bp)
380 {
381 	if (CHIP_IS_E2(bp)) {
382 		if (BP_PORT(bp)) {
383 			BNX2X_ERR("4 port mode is not supported");
384 			return;
385 		}
386 
387 		if (bp->dcbx_port_params.pfc.enabled)
388 
389 			/* 1. Fills up common PFC structures if required.*/
390 			/* 2. Configure NIG, MAC and BRB via the elink:
391 			 *    elink must first check if BMAC is not in reset
392 			 *    and only then configures the BMAC
393 			 *    Or, configure EMAC.
394 			 */
395 			bnx2x_pfc_set(bp);
396 
397 		else
398 			bnx2x_pfc_clear(bp);
399 	}
400 }
401 
bnx2x_dcbx_stop_hw_tx(struct bnx2x * bp)402 static void bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp)
403 {
404 	DP(NETIF_MSG_LINK, "sending STOP TRAFFIC\n");
405 	bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_STOP_TRAFFIC,
406 		      0 /* connectionless */,
407 		      0 /* dataHi is zero */,
408 		      0 /* dataLo is zero */,
409 		      1 /* common */);
410 }
411 
bnx2x_dcbx_resume_hw_tx(struct bnx2x * bp)412 static void bnx2x_dcbx_resume_hw_tx(struct bnx2x *bp)
413 {
414 	bnx2x_pfc_fw_struct_e2(bp);
415 	DP(NETIF_MSG_LINK, "sending START TRAFFIC\n");
416 	bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_START_TRAFFIC,
417 		      0, /* connectionless */
418 		      U64_HI(bnx2x_sp_mapping(bp, pfc_config)),
419 		      U64_LO(bnx2x_sp_mapping(bp, pfc_config)),
420 		      1  /* commmon */);
421 }
422 
bnx2x_dcbx_update_ets_params(struct bnx2x * bp)423 static void bnx2x_dcbx_update_ets_params(struct bnx2x *bp)
424 {
425 	struct bnx2x_dcbx_pg_params *ets = &(bp->dcbx_port_params.ets);
426 	u8	status = 0;
427 
428 	bnx2x_ets_disabled(&bp->link_params);
429 
430 	if (!ets->enabled)
431 		return;
432 
433 	if ((ets->num_of_cos == 0) || (ets->num_of_cos > E2_NUM_OF_COS)) {
434 		BNX2X_ERR("illegal num of cos= %x", ets->num_of_cos);
435 		return;
436 	}
437 
438 	/* valid COS entries */
439 	if (ets->num_of_cos == 1)   /* no ETS */
440 		return;
441 
442 	/* sanity */
443 	if (((BNX2X_DCBX_COS_NOT_STRICT == ets->cos_params[0].strict) &&
444 	     (DCBX_INVALID_COS_BW == ets->cos_params[0].bw_tbl)) ||
445 	    ((BNX2X_DCBX_COS_NOT_STRICT == ets->cos_params[1].strict) &&
446 	     (DCBX_INVALID_COS_BW == ets->cos_params[1].bw_tbl))) {
447 		BNX2X_ERR("all COS should have at least bw_limit or strict"
448 			    "ets->cos_params[0].strict= %x"
449 			    "ets->cos_params[0].bw_tbl= %x"
450 			    "ets->cos_params[1].strict= %x"
451 			    "ets->cos_params[1].bw_tbl= %x",
452 			  ets->cos_params[0].strict,
453 			  ets->cos_params[0].bw_tbl,
454 			  ets->cos_params[1].strict,
455 			  ets->cos_params[1].bw_tbl);
456 		return;
457 	}
458 	/* If we join a group and there is bw_tbl and strict then bw rules */
459 	if ((DCBX_INVALID_COS_BW != ets->cos_params[0].bw_tbl) &&
460 	    (DCBX_INVALID_COS_BW != ets->cos_params[1].bw_tbl)) {
461 		u32 bw_tbl_0 = ets->cos_params[0].bw_tbl;
462 		u32 bw_tbl_1 = ets->cos_params[1].bw_tbl;
463 		/* Do not allow 0-100 configuration
464 		 * since PBF does not support it
465 		 * force 1-99 instead
466 		 */
467 		if (bw_tbl_0 == 0) {
468 			bw_tbl_0 = 1;
469 			bw_tbl_1 = 99;
470 		} else if (bw_tbl_1 == 0) {
471 			bw_tbl_1 = 1;
472 			bw_tbl_0 = 99;
473 		}
474 
475 		bnx2x_ets_bw_limit(&bp->link_params, bw_tbl_0, bw_tbl_1);
476 	} else {
477 		if (ets->cos_params[0].strict == BNX2X_DCBX_COS_HIGH_STRICT)
478 			status = bnx2x_ets_strict(&bp->link_params, 0);
479 		else if (ets->cos_params[1].strict
480 						== BNX2X_DCBX_COS_HIGH_STRICT)
481 			status = bnx2x_ets_strict(&bp->link_params, 1);
482 
483 		if (status)
484 			BNX2X_ERR("update_ets_params failed\n");
485 	}
486 }
487 
bnx2x_dcbx_read_shmem_neg_results(struct bnx2x * bp)488 static int bnx2x_dcbx_read_shmem_neg_results(struct bnx2x *bp)
489 {
490 	struct lldp_local_mib local_mib = {0};
491 	u32 dcbx_neg_res_offset = SHMEM2_RD(bp, dcbx_neg_res_offset);
492 	int rc;
493 
494 	DP(NETIF_MSG_LINK, "dcbx_neg_res_offset 0x%x\n", dcbx_neg_res_offset);
495 
496 	if (SHMEM_DCBX_NEG_RES_NONE == dcbx_neg_res_offset) {
497 		BNX2X_ERR("FW doesn't support dcbx_neg_res_offset\n");
498 		return -EINVAL;
499 	}
500 	rc = bnx2x_dcbx_read_mib(bp, (u32 *)&local_mib, dcbx_neg_res_offset,
501 				 DCBX_READ_LOCAL_MIB);
502 
503 	if (rc) {
504 		BNX2X_ERR("Faild to read local mib from FW\n");
505 		return rc;
506 	}
507 
508 	/* save features and error */
509 	bp->dcbx_local_feat = local_mib.features;
510 	bp->dcbx_error = local_mib.error;
511 	return 0;
512 }
513 
514 
515 #ifdef BCM_DCBNL
516 static inline
bnx2x_dcbx_dcbnl_app_up(struct dcbx_app_priority_entry * ent)517 u8 bnx2x_dcbx_dcbnl_app_up(struct dcbx_app_priority_entry *ent)
518 {
519 	u8 pri;
520 
521 	/* Choose the highest priority */
522 	for (pri = MAX_PFC_PRIORITIES - 1; pri > 0; pri--)
523 		if (ent->pri_bitmap & (1 << pri))
524 			break;
525 	return pri;
526 }
527 
528 static inline
bnx2x_dcbx_dcbnl_app_idtype(struct dcbx_app_priority_entry * ent)529 u8 bnx2x_dcbx_dcbnl_app_idtype(struct dcbx_app_priority_entry *ent)
530 {
531 	return ((ent->appBitfield & DCBX_APP_ENTRY_SF_MASK) ==
532 		DCBX_APP_SF_PORT) ? DCB_APP_IDTYPE_PORTNUM :
533 		DCB_APP_IDTYPE_ETHTYPE;
534 }
535 
536 static inline
bnx2x_dcbx_invalidate_local_apps(struct bnx2x * bp)537 void bnx2x_dcbx_invalidate_local_apps(struct bnx2x *bp)
538 {
539 	int i;
540 	for (i = 0; i < DCBX_MAX_APP_PROTOCOL; i++)
541 		bp->dcbx_local_feat.app.app_pri_tbl[i].appBitfield &=
542 							~DCBX_APP_ENTRY_VALID;
543 }
544 
bnx2x_dcbnl_update_applist(struct bnx2x * bp,bool delall)545 int bnx2x_dcbnl_update_applist(struct bnx2x *bp, bool delall)
546 {
547 	int i, err = 0;
548 
549 	for (i = 0; i < DCBX_MAX_APP_PROTOCOL && err == 0; i++) {
550 		struct dcbx_app_priority_entry *ent =
551 			&bp->dcbx_local_feat.app.app_pri_tbl[i];
552 
553 		if (ent->appBitfield & DCBX_APP_ENTRY_VALID) {
554 			u8 up = bnx2x_dcbx_dcbnl_app_up(ent);
555 
556 			/* avoid invalid user-priority */
557 			if (up) {
558 				struct dcb_app app;
559 				app.selector = bnx2x_dcbx_dcbnl_app_idtype(ent);
560 				app.protocol = ent->app_id;
561 				app.priority = delall ? 0 : up;
562 				err = dcb_setapp(bp->dev, &app);
563 			}
564 		}
565 	}
566 	return err;
567 }
568 #endif
569 
bnx2x_dcbx_set_params(struct bnx2x * bp,u32 state)570 void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state)
571 {
572 	switch (state) {
573 	case BNX2X_DCBX_STATE_NEG_RECEIVED:
574 		{
575 			DP(NETIF_MSG_LINK, "BNX2X_DCBX_STATE_NEG_RECEIVED\n");
576 #ifdef BCM_DCBNL
577 			/**
578 			 * Delete app tlvs from dcbnl before reading new
579 			 * negotiation results
580 			 */
581 			bnx2x_dcbnl_update_applist(bp, true);
582 #endif
583 			/* Read neg results if dcbx is in the FW */
584 			if (bnx2x_dcbx_read_shmem_neg_results(bp))
585 				return;
586 
587 			bnx2x_dump_dcbx_drv_param(bp, &bp->dcbx_local_feat,
588 						  bp->dcbx_error);
589 
590 			bnx2x_get_dcbx_drv_param(bp, &bp->dcbx_local_feat,
591 						 bp->dcbx_error);
592 
593 			if (bp->state != BNX2X_STATE_OPENING_WAIT4_LOAD) {
594 #ifdef BCM_DCBNL
595 				/**
596 				 * Add new app tlvs to dcbnl
597 				 */
598 				bnx2x_dcbnl_update_applist(bp, false);
599 #endif
600 				bnx2x_dcbx_stop_hw_tx(bp);
601 				return;
602 			}
603 			/* fall through */
604 #ifdef BCM_DCBNL
605 			/**
606 			 * Invalidate the local app tlvs if they are not added
607 			 * to the dcbnl app list to avoid deleting them from
608 			 * the list later on
609 			 */
610 			bnx2x_dcbx_invalidate_local_apps(bp);
611 #endif
612 		}
613 	case BNX2X_DCBX_STATE_TX_PAUSED:
614 		DP(NETIF_MSG_LINK, "BNX2X_DCBX_STATE_TX_PAUSED\n");
615 		bnx2x_pfc_set_pfc(bp);
616 
617 		bnx2x_dcbx_update_ets_params(bp);
618 		if (bp->state != BNX2X_STATE_OPENING_WAIT4_LOAD) {
619 			bnx2x_dcbx_resume_hw_tx(bp);
620 			return;
621 		}
622 		/* fall through */
623 	case BNX2X_DCBX_STATE_TX_RELEASED:
624 		DP(NETIF_MSG_LINK, "BNX2X_DCBX_STATE_TX_RELEASED\n");
625 		if (bp->state != BNX2X_STATE_OPENING_WAIT4_LOAD)
626 			bnx2x_fw_command(bp, DRV_MSG_CODE_DCBX_PMF_DRV_OK, 0);
627 
628 		return;
629 	default:
630 		BNX2X_ERR("Unknown DCBX_STATE\n");
631 	}
632 }
633 
634 
635 #define LLDP_STATS_OFFSET(bp)		(BP_PORT(bp)*\
636 					sizeof(struct lldp_dcbx_stat))
637 
638 /* calculate struct offset in array according to chip information */
639 #define LLDP_PARAMS_OFFSET(bp)		(BP_PORT(bp)*sizeof(struct lldp_params))
640 
641 #define LLDP_ADMIN_MIB_OFFSET(bp)	(PORT_MAX*sizeof(struct lldp_params) + \
642 				      BP_PORT(bp)*sizeof(struct lldp_admin_mib))
643 
bnx2x_dcbx_lldp_updated_params(struct bnx2x * bp,u32 dcbx_lldp_params_offset)644 static void bnx2x_dcbx_lldp_updated_params(struct bnx2x *bp,
645 					   u32 dcbx_lldp_params_offset)
646 {
647 	struct lldp_params lldp_params = {0};
648 	u32 i = 0, *buff = NULL;
649 	u32 offset = dcbx_lldp_params_offset + LLDP_PARAMS_OFFSET(bp);
650 
651 	DP(NETIF_MSG_LINK, "lldp_offset 0x%x\n", offset);
652 
653 	if ((bp->lldp_config_params.overwrite_settings ==
654 				BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE)) {
655 		/* Read the data first */
656 		buff = (u32 *)&lldp_params;
657 		for (i = 0; i < sizeof(struct lldp_params); i += 4,  buff++)
658 			*buff = REG_RD(bp, (offset + i));
659 
660 		lldp_params.msg_tx_hold =
661 			(u8)bp->lldp_config_params.msg_tx_hold;
662 		lldp_params.msg_fast_tx_interval =
663 			(u8)bp->lldp_config_params.msg_fast_tx;
664 		lldp_params.tx_crd_max =
665 			(u8)bp->lldp_config_params.tx_credit_max;
666 		lldp_params.msg_tx_interval =
667 			(u8)bp->lldp_config_params.msg_tx_interval;
668 		lldp_params.tx_fast =
669 			(u8)bp->lldp_config_params.tx_fast;
670 
671 		/* Write the data.*/
672 		buff = (u32 *)&lldp_params;
673 		for (i = 0; i < sizeof(struct lldp_params); i += 4, buff++)
674 			REG_WR(bp, (offset + i) , *buff);
675 
676 
677 	} else if (BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE ==
678 				bp->lldp_config_params.overwrite_settings)
679 		bp->lldp_config_params.overwrite_settings =
680 				BNX2X_DCBX_OVERWRITE_SETTINGS_INVALID;
681 }
682 
bnx2x_dcbx_admin_mib_updated_params(struct bnx2x * bp,u32 dcbx_lldp_params_offset)683 static void bnx2x_dcbx_admin_mib_updated_params(struct bnx2x *bp,
684 				u32 dcbx_lldp_params_offset)
685 {
686 	struct lldp_admin_mib admin_mib;
687 	u32 i, other_traf_type = PREDEFINED_APP_IDX_MAX, traf_type = 0;
688 	u32 *buff;
689 	u32 offset = dcbx_lldp_params_offset + LLDP_ADMIN_MIB_OFFSET(bp);
690 
691 	/*shortcuts*/
692 	struct dcbx_features *af = &admin_mib.features;
693 	struct bnx2x_config_dcbx_params *dp = &bp->dcbx_config_params;
694 
695 	memset(&admin_mib, 0, sizeof(struct lldp_admin_mib));
696 	buff = (u32 *)&admin_mib;
697 	/* Read the data first */
698 	for (i = 0; i < sizeof(struct lldp_admin_mib); i += 4, buff++)
699 		*buff = REG_RD(bp, (offset + i));
700 
701 	if (bp->dcbx_enabled == BNX2X_DCBX_ENABLED_ON_NEG_ON)
702 		SET_FLAGS(admin_mib.ver_cfg_flags, DCBX_DCBX_ENABLED);
703 	else
704 		RESET_FLAGS(admin_mib.ver_cfg_flags, DCBX_DCBX_ENABLED);
705 
706 	if ((BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE ==
707 				dp->overwrite_settings)) {
708 		RESET_FLAGS(admin_mib.ver_cfg_flags, DCBX_CEE_VERSION_MASK);
709 		admin_mib.ver_cfg_flags |=
710 			(dp->admin_dcbx_version << DCBX_CEE_VERSION_SHIFT) &
711 			 DCBX_CEE_VERSION_MASK;
712 
713 		af->ets.enabled = (u8)dp->admin_ets_enable;
714 
715 		af->pfc.enabled = (u8)dp->admin_pfc_enable;
716 
717 		/* FOR IEEE dp->admin_tc_supported_tx_enable */
718 		if (dp->admin_ets_configuration_tx_enable)
719 			SET_FLAGS(admin_mib.ver_cfg_flags,
720 				  DCBX_ETS_CONFIG_TX_ENABLED);
721 		else
722 			RESET_FLAGS(admin_mib.ver_cfg_flags,
723 				    DCBX_ETS_CONFIG_TX_ENABLED);
724 		/* For IEEE admin_ets_recommendation_tx_enable */
725 		if (dp->admin_pfc_tx_enable)
726 			SET_FLAGS(admin_mib.ver_cfg_flags,
727 				  DCBX_PFC_CONFIG_TX_ENABLED);
728 		else
729 			RESET_FLAGS(admin_mib.ver_cfg_flags,
730 				  DCBX_PFC_CONFIG_TX_ENABLED);
731 
732 		if (dp->admin_application_priority_tx_enable)
733 			SET_FLAGS(admin_mib.ver_cfg_flags,
734 				  DCBX_APP_CONFIG_TX_ENABLED);
735 		else
736 			RESET_FLAGS(admin_mib.ver_cfg_flags,
737 				  DCBX_APP_CONFIG_TX_ENABLED);
738 
739 		if (dp->admin_ets_willing)
740 			SET_FLAGS(admin_mib.ver_cfg_flags, DCBX_ETS_WILLING);
741 		else
742 			RESET_FLAGS(admin_mib.ver_cfg_flags, DCBX_ETS_WILLING);
743 		/* For IEEE admin_ets_reco_valid */
744 		if (dp->admin_pfc_willing)
745 			SET_FLAGS(admin_mib.ver_cfg_flags, DCBX_PFC_WILLING);
746 		else
747 			RESET_FLAGS(admin_mib.ver_cfg_flags, DCBX_PFC_WILLING);
748 
749 		if (dp->admin_app_priority_willing)
750 			SET_FLAGS(admin_mib.ver_cfg_flags, DCBX_APP_WILLING);
751 		else
752 			RESET_FLAGS(admin_mib.ver_cfg_flags, DCBX_APP_WILLING);
753 
754 		for (i = 0 ; i < DCBX_MAX_NUM_PG_BW_ENTRIES; i++) {
755 			DCBX_PG_BW_SET(af->ets.pg_bw_tbl, i,
756 				(u8)dp->admin_configuration_bw_precentage[i]);
757 
758 			DP(NETIF_MSG_LINK, "pg_bw_tbl[%d] = %02x\n",
759 			   i, DCBX_PG_BW_GET(af->ets.pg_bw_tbl, i));
760 		}
761 
762 		for (i = 0; i < DCBX_MAX_NUM_PRI_PG_ENTRIES; i++) {
763 			DCBX_PRI_PG_SET(af->ets.pri_pg_tbl, i,
764 					(u8)dp->admin_configuration_ets_pg[i]);
765 
766 			DP(NETIF_MSG_LINK, "pri_pg_tbl[%d] = %02x\n",
767 			   i, DCBX_PRI_PG_GET(af->ets.pri_pg_tbl, i));
768 		}
769 
770 		/*For IEEE admin_recommendation_bw_precentage
771 		 *For IEEE admin_recommendation_ets_pg */
772 		af->pfc.pri_en_bitmap = (u8)dp->admin_pfc_bitmap;
773 		for (i = 0; i < 4; i++) {
774 			if (dp->admin_priority_app_table[i].valid) {
775 				struct bnx2x_admin_priority_app_table *table =
776 					dp->admin_priority_app_table;
777 				if ((ETH_TYPE_FCOE == table[i].app_id) &&
778 				   (TRAFFIC_TYPE_ETH == table[i].traffic_type))
779 					traf_type = FCOE_APP_IDX;
780 				else if ((TCP_PORT_ISCSI == table[i].app_id) &&
781 				   (TRAFFIC_TYPE_PORT == table[i].traffic_type))
782 					traf_type = ISCSI_APP_IDX;
783 				else
784 					traf_type = other_traf_type++;
785 
786 				af->app.app_pri_tbl[traf_type].app_id =
787 					table[i].app_id;
788 
789 				af->app.app_pri_tbl[traf_type].pri_bitmap =
790 					(u8)(1 << table[i].priority);
791 
792 				af->app.app_pri_tbl[traf_type].appBitfield =
793 				    (DCBX_APP_ENTRY_VALID);
794 
795 				af->app.app_pri_tbl[traf_type].appBitfield |=
796 				   (TRAFFIC_TYPE_ETH == table[i].traffic_type) ?
797 					DCBX_APP_SF_ETH_TYPE : DCBX_APP_SF_PORT;
798 			}
799 		}
800 
801 		af->app.default_pri = (u8)dp->admin_default_priority;
802 
803 	} else if (BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE ==
804 						dp->overwrite_settings)
805 		dp->overwrite_settings = BNX2X_DCBX_OVERWRITE_SETTINGS_INVALID;
806 
807 	/* Write the data. */
808 	buff = (u32 *)&admin_mib;
809 	for (i = 0; i < sizeof(struct lldp_admin_mib); i += 4, buff++)
810 		REG_WR(bp, (offset + i), *buff);
811 }
812 
bnx2x_dcbx_set_state(struct bnx2x * bp,bool dcb_on,u32 dcbx_enabled)813 void bnx2x_dcbx_set_state(struct bnx2x *bp, bool dcb_on, u32 dcbx_enabled)
814 {
815 	if (CHIP_IS_E2(bp) && !CHIP_MODE_IS_4_PORT(bp)) {
816 		bp->dcb_state = dcb_on;
817 		bp->dcbx_enabled = dcbx_enabled;
818 	} else {
819 		bp->dcb_state = false;
820 		bp->dcbx_enabled = BNX2X_DCBX_ENABLED_INVALID;
821 	}
822 	DP(NETIF_MSG_LINK, "DCB state [%s:%s]\n",
823 	   dcb_on ? "ON" : "OFF",
824 	   dcbx_enabled == BNX2X_DCBX_ENABLED_OFF ? "user-mode" :
825 	   dcbx_enabled == BNX2X_DCBX_ENABLED_ON_NEG_OFF ? "on-chip static" :
826 	   dcbx_enabled == BNX2X_DCBX_ENABLED_ON_NEG_ON ?
827 	   "on-chip with negotiation" : "invalid");
828 }
829 
bnx2x_dcbx_init_params(struct bnx2x * bp)830 void bnx2x_dcbx_init_params(struct bnx2x *bp)
831 {
832 	bp->dcbx_config_params.admin_dcbx_version = 0x0; /* 0 - CEE; 1 - IEEE */
833 	bp->dcbx_config_params.admin_ets_willing = 1;
834 	bp->dcbx_config_params.admin_pfc_willing = 1;
835 	bp->dcbx_config_params.overwrite_settings = 1;
836 	bp->dcbx_config_params.admin_ets_enable = 1;
837 	bp->dcbx_config_params.admin_pfc_enable = 1;
838 	bp->dcbx_config_params.admin_tc_supported_tx_enable = 1;
839 	bp->dcbx_config_params.admin_ets_configuration_tx_enable = 1;
840 	bp->dcbx_config_params.admin_pfc_tx_enable = 1;
841 	bp->dcbx_config_params.admin_application_priority_tx_enable = 1;
842 	bp->dcbx_config_params.admin_ets_reco_valid = 1;
843 	bp->dcbx_config_params.admin_app_priority_willing = 1;
844 	bp->dcbx_config_params.admin_configuration_bw_precentage[0] = 00;
845 	bp->dcbx_config_params.admin_configuration_bw_precentage[1] = 50;
846 	bp->dcbx_config_params.admin_configuration_bw_precentage[2] = 50;
847 	bp->dcbx_config_params.admin_configuration_bw_precentage[3] = 0;
848 	bp->dcbx_config_params.admin_configuration_bw_precentage[4] = 0;
849 	bp->dcbx_config_params.admin_configuration_bw_precentage[5] = 0;
850 	bp->dcbx_config_params.admin_configuration_bw_precentage[6] = 0;
851 	bp->dcbx_config_params.admin_configuration_bw_precentage[7] = 0;
852 	bp->dcbx_config_params.admin_configuration_ets_pg[0] = 1;
853 	bp->dcbx_config_params.admin_configuration_ets_pg[1] = 0;
854 	bp->dcbx_config_params.admin_configuration_ets_pg[2] = 0;
855 	bp->dcbx_config_params.admin_configuration_ets_pg[3] = 2;
856 	bp->dcbx_config_params.admin_configuration_ets_pg[4] = 0;
857 	bp->dcbx_config_params.admin_configuration_ets_pg[5] = 0;
858 	bp->dcbx_config_params.admin_configuration_ets_pg[6] = 0;
859 	bp->dcbx_config_params.admin_configuration_ets_pg[7] = 0;
860 	bp->dcbx_config_params.admin_recommendation_bw_precentage[0] = 0;
861 	bp->dcbx_config_params.admin_recommendation_bw_precentage[1] = 1;
862 	bp->dcbx_config_params.admin_recommendation_bw_precentage[2] = 2;
863 	bp->dcbx_config_params.admin_recommendation_bw_precentage[3] = 0;
864 	bp->dcbx_config_params.admin_recommendation_bw_precentage[4] = 7;
865 	bp->dcbx_config_params.admin_recommendation_bw_precentage[5] = 5;
866 	bp->dcbx_config_params.admin_recommendation_bw_precentage[6] = 6;
867 	bp->dcbx_config_params.admin_recommendation_bw_precentage[7] = 7;
868 	bp->dcbx_config_params.admin_recommendation_ets_pg[0] = 0;
869 	bp->dcbx_config_params.admin_recommendation_ets_pg[1] = 1;
870 	bp->dcbx_config_params.admin_recommendation_ets_pg[2] = 2;
871 	bp->dcbx_config_params.admin_recommendation_ets_pg[3] = 3;
872 	bp->dcbx_config_params.admin_recommendation_ets_pg[4] = 4;
873 	bp->dcbx_config_params.admin_recommendation_ets_pg[5] = 5;
874 	bp->dcbx_config_params.admin_recommendation_ets_pg[6] = 6;
875 	bp->dcbx_config_params.admin_recommendation_ets_pg[7] = 7;
876 	bp->dcbx_config_params.admin_pfc_bitmap = 0x8; /* FCoE(3) enable */
877 	bp->dcbx_config_params.admin_priority_app_table[0].valid = 1;
878 	bp->dcbx_config_params.admin_priority_app_table[1].valid = 1;
879 	bp->dcbx_config_params.admin_priority_app_table[2].valid = 0;
880 	bp->dcbx_config_params.admin_priority_app_table[3].valid = 0;
881 	bp->dcbx_config_params.admin_priority_app_table[0].priority = 3;
882 	bp->dcbx_config_params.admin_priority_app_table[1].priority = 0;
883 	bp->dcbx_config_params.admin_priority_app_table[2].priority = 0;
884 	bp->dcbx_config_params.admin_priority_app_table[3].priority = 0;
885 	bp->dcbx_config_params.admin_priority_app_table[0].traffic_type = 0;
886 	bp->dcbx_config_params.admin_priority_app_table[1].traffic_type = 1;
887 	bp->dcbx_config_params.admin_priority_app_table[2].traffic_type = 0;
888 	bp->dcbx_config_params.admin_priority_app_table[3].traffic_type = 0;
889 	bp->dcbx_config_params.admin_priority_app_table[0].app_id = 0x8906;
890 	bp->dcbx_config_params.admin_priority_app_table[1].app_id = 3260;
891 	bp->dcbx_config_params.admin_priority_app_table[2].app_id = 0;
892 	bp->dcbx_config_params.admin_priority_app_table[3].app_id = 0;
893 	bp->dcbx_config_params.admin_default_priority =
894 		bp->dcbx_config_params.admin_priority_app_table[1].priority;
895 }
896 
bnx2x_dcbx_init(struct bnx2x * bp)897 void bnx2x_dcbx_init(struct bnx2x *bp)
898 {
899 	u32 dcbx_lldp_params_offset = SHMEM_LLDP_DCBX_PARAMS_NONE;
900 
901 	if (bp->dcbx_enabled <= 0)
902 		return;
903 
904 	/* validate:
905 	 * chip of good for dcbx version,
906 	 * dcb is wanted
907 	 * the function is pmf
908 	 * shmem2 contains DCBX support fields
909 	 */
910 	DP(NETIF_MSG_LINK, "dcb_state %d bp->port.pmf %d\n",
911 	   bp->dcb_state, bp->port.pmf);
912 
913 	if (bp->dcb_state ==  BNX2X_DCB_STATE_ON && bp->port.pmf &&
914 	    SHMEM2_HAS(bp, dcbx_lldp_params_offset)) {
915 		dcbx_lldp_params_offset =
916 			SHMEM2_RD(bp, dcbx_lldp_params_offset);
917 
918 		DP(NETIF_MSG_LINK, "dcbx_lldp_params_offset 0x%x\n",
919 		   dcbx_lldp_params_offset);
920 
921 		if (SHMEM_LLDP_DCBX_PARAMS_NONE != dcbx_lldp_params_offset) {
922 			bnx2x_dcbx_lldp_updated_params(bp,
923 						       dcbx_lldp_params_offset);
924 
925 			bnx2x_dcbx_admin_mib_updated_params(bp,
926 				dcbx_lldp_params_offset);
927 
928 			/* set default configuration BC has */
929 			bnx2x_dcbx_set_params(bp,
930 					      BNX2X_DCBX_STATE_NEG_RECEIVED);
931 
932 			bnx2x_fw_command(bp,
933 					 DRV_MSG_CODE_DCBX_ADMIN_PMF_MSG, 0);
934 		}
935 	}
936 }
937 
bnx2x_dcb_init_intmem_pfc(struct bnx2x * bp)938 void bnx2x_dcb_init_intmem_pfc(struct bnx2x *bp)
939 {
940 	struct priority_cos pricos[MAX_PFC_TRAFFIC_TYPES];
941 	u32 i = 0, addr;
942 	memset(pricos, 0, sizeof(pricos));
943 	/* Default initialization */
944 	for (i = 0; i < MAX_PFC_TRAFFIC_TYPES; i++)
945 		pricos[i].priority = LLFC_TRAFFIC_TYPE_TO_PRIORITY_UNMAPPED;
946 
947 	/* Store per port struct to internal memory */
948 	addr = BAR_XSTRORM_INTMEM +
949 			XSTORM_CMNG_PER_PORT_VARS_OFFSET(BP_PORT(bp)) +
950 			offsetof(struct cmng_struct_per_port,
951 				 traffic_type_to_priority_cos);
952 	__storm_memset_struct(bp, addr, sizeof(pricos), (u32 *)pricos);
953 
954 
955 	/* LLFC disabled.*/
956 	REG_WR8(bp , BAR_XSTRORM_INTMEM +
957 		    XSTORM_CMNG_PER_PORT_VARS_OFFSET(BP_PORT(bp)) +
958 		    offsetof(struct cmng_struct_per_port, llfc_mode),
959 			LLFC_MODE_NONE);
960 
961 	/* DCBX disabled.*/
962 	REG_WR8(bp , BAR_XSTRORM_INTMEM +
963 		    XSTORM_CMNG_PER_PORT_VARS_OFFSET(BP_PORT(bp)) +
964 		    offsetof(struct cmng_struct_per_port, dcb_enabled),
965 			DCB_DISABLED);
966 }
967 
968 static void
bnx2x_dcbx_print_cos_params(struct bnx2x * bp,struct flow_control_configuration * pfc_fw_cfg)969 bnx2x_dcbx_print_cos_params(struct bnx2x *bp,
970 			    struct flow_control_configuration *pfc_fw_cfg)
971 {
972 	u8 pri = 0;
973 	u8 cos = 0;
974 
975 	DP(NETIF_MSG_LINK,
976 	   "pfc_fw_cfg->dcb_version %x\n", pfc_fw_cfg->dcb_version);
977 	DP(NETIF_MSG_LINK,
978 	   "pdev->params.dcbx_port_params.pfc."
979 	   "priority_non_pauseable_mask %x\n",
980 	   bp->dcbx_port_params.pfc.priority_non_pauseable_mask);
981 
982 	for (cos = 0 ; cos < bp->dcbx_port_params.ets.num_of_cos ; cos++) {
983 		DP(NETIF_MSG_LINK, "pdev->params.dcbx_port_params.ets."
984 		   "cos_params[%d].pri_bitmask %x\n", cos,
985 		   bp->dcbx_port_params.ets.cos_params[cos].pri_bitmask);
986 
987 		DP(NETIF_MSG_LINK, "pdev->params.dcbx_port_params.ets."
988 		   "cos_params[%d].bw_tbl %x\n", cos,
989 		   bp->dcbx_port_params.ets.cos_params[cos].bw_tbl);
990 
991 		DP(NETIF_MSG_LINK, "pdev->params.dcbx_port_params.ets."
992 		   "cos_params[%d].strict %x\n", cos,
993 		   bp->dcbx_port_params.ets.cos_params[cos].strict);
994 
995 		DP(NETIF_MSG_LINK, "pdev->params.dcbx_port_params.ets."
996 		   "cos_params[%d].pauseable %x\n", cos,
997 		   bp->dcbx_port_params.ets.cos_params[cos].pauseable);
998 	}
999 
1000 	for (pri = 0; pri < LLFC_DRIVER_TRAFFIC_TYPE_MAX; pri++) {
1001 		DP(NETIF_MSG_LINK,
1002 		   "pfc_fw_cfg->traffic_type_to_priority_cos[%d]."
1003 		   "priority %x\n", pri,
1004 		   pfc_fw_cfg->traffic_type_to_priority_cos[pri].priority);
1005 
1006 		DP(NETIF_MSG_LINK,
1007 		   "pfc_fw_cfg->traffic_type_to_priority_cos[%d].cos %x\n",
1008 		   pri, pfc_fw_cfg->traffic_type_to_priority_cos[pri].cos);
1009 	}
1010 }
1011 
1012 /* fills help_data according to pg_info */
bnx2x_dcbx_get_num_pg_traf_type(struct bnx2x * bp,u32 * pg_pri_orginal_spread,struct pg_help_data * help_data)1013 static void bnx2x_dcbx_get_num_pg_traf_type(struct bnx2x *bp,
1014 					    u32 *pg_pri_orginal_spread,
1015 					    struct pg_help_data *help_data)
1016 {
1017 	bool pg_found  = false;
1018 	u32 i, traf_type, add_traf_type, add_pg;
1019 	u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority;
1020 	struct pg_entry_help_data *data = help_data->data; /*shotcut*/
1021 
1022 	/* Set to invalid */
1023 	for (i = 0; i < LLFC_DRIVER_TRAFFIC_TYPE_MAX; i++)
1024 		data[i].pg = DCBX_ILLEGAL_PG;
1025 
1026 	for (add_traf_type = 0;
1027 	     add_traf_type < LLFC_DRIVER_TRAFFIC_TYPE_MAX; add_traf_type++) {
1028 		pg_found = false;
1029 		if (ttp[add_traf_type] < MAX_PFC_PRIORITIES) {
1030 			add_pg = (u8)pg_pri_orginal_spread[ttp[add_traf_type]];
1031 			for (traf_type = 0;
1032 			     traf_type < LLFC_DRIVER_TRAFFIC_TYPE_MAX;
1033 			     traf_type++) {
1034 				if (data[traf_type].pg == add_pg) {
1035 					if (!(data[traf_type].pg_priority &
1036 					     (1 << ttp[add_traf_type])))
1037 						data[traf_type].
1038 							num_of_dif_pri++;
1039 					data[traf_type].pg_priority |=
1040 						(1 << ttp[add_traf_type]);
1041 					pg_found = true;
1042 					break;
1043 				}
1044 			}
1045 			if (false == pg_found) {
1046 				data[help_data->num_of_pg].pg = add_pg;
1047 				data[help_data->num_of_pg].pg_priority =
1048 						(1 << ttp[add_traf_type]);
1049 				data[help_data->num_of_pg].num_of_dif_pri = 1;
1050 				help_data->num_of_pg++;
1051 			}
1052 		}
1053 		DP(NETIF_MSG_LINK,
1054 		   "add_traf_type %d pg_found %s num_of_pg %d\n",
1055 		   add_traf_type, (false == pg_found) ? "NO" : "YES",
1056 		   help_data->num_of_pg);
1057 	}
1058 }
1059 
1060 
1061 /*******************************************************************************
1062  * Description: single priority group
1063  *
1064  * Return:
1065  ******************************************************************************/
bnx2x_dcbx_ets_disabled_entry_data(struct bnx2x * bp,struct cos_help_data * cos_data,u32 pri_join_mask)1066 static void bnx2x_dcbx_ets_disabled_entry_data(struct bnx2x *bp,
1067 					       struct cos_help_data *cos_data,
1068 					       u32 pri_join_mask)
1069 {
1070 	/* Only one priority than only one COS */
1071 	cos_data->data[0].pausable =
1072 		IS_DCBX_PFC_PRI_ONLY_PAUSE(bp, pri_join_mask);
1073 	cos_data->data[0].pri_join_mask = pri_join_mask;
1074 	cos_data->data[0].cos_bw = 100;
1075 	cos_data->num_of_cos = 1;
1076 }
1077 
1078 /*******************************************************************************
1079  * Description: updating the cos bw
1080  *
1081  * Return:
1082  ******************************************************************************/
bnx2x_dcbx_add_to_cos_bw(struct bnx2x * bp,struct cos_entry_help_data * data,u8 pg_bw)1083 static inline void bnx2x_dcbx_add_to_cos_bw(struct bnx2x *bp,
1084 					    struct cos_entry_help_data *data,
1085 					    u8 pg_bw)
1086 {
1087 	if (data->cos_bw == DCBX_INVALID_COS_BW)
1088 		data->cos_bw = pg_bw;
1089 	else
1090 		data->cos_bw += pg_bw;
1091 }
1092 
1093 /*******************************************************************************
1094  * Description: single priority group
1095  *
1096  * Return:
1097  ******************************************************************************/
bnx2x_dcbx_separate_pauseable_from_non(struct bnx2x * bp,struct cos_help_data * cos_data,u32 * pg_pri_orginal_spread,struct dcbx_ets_feature * ets)1098 static void bnx2x_dcbx_separate_pauseable_from_non(struct bnx2x *bp,
1099 			struct cos_help_data *cos_data,
1100 			u32 *pg_pri_orginal_spread,
1101 			struct dcbx_ets_feature *ets)
1102 {
1103 	u32	pri_tested	= 0;
1104 	u8	i		= 0;
1105 	u8	entry		= 0;
1106 	u8	pg_entry	= 0;
1107 	u8	num_of_pri	= LLFC_DRIVER_TRAFFIC_TYPE_MAX;
1108 
1109 	cos_data->data[0].pausable = true;
1110 	cos_data->data[1].pausable = false;
1111 	cos_data->data[0].pri_join_mask = cos_data->data[1].pri_join_mask = 0;
1112 
1113 	for (i = 0 ; i < num_of_pri ; i++) {
1114 		pri_tested = 1 << bp->dcbx_port_params.
1115 					app.traffic_type_priority[i];
1116 
1117 		if (pri_tested & DCBX_PFC_PRI_NON_PAUSE_MASK(bp)) {
1118 			cos_data->data[1].pri_join_mask |= pri_tested;
1119 			entry = 1;
1120 		} else {
1121 			cos_data->data[0].pri_join_mask |= pri_tested;
1122 			entry = 0;
1123 		}
1124 		pg_entry = (u8)pg_pri_orginal_spread[bp->dcbx_port_params.
1125 						app.traffic_type_priority[i]];
1126 		/* There can be only one strict pg */
1127 		if (pg_entry < DCBX_MAX_NUM_PG_BW_ENTRIES)
1128 			bnx2x_dcbx_add_to_cos_bw(bp, &cos_data->data[entry],
1129 				DCBX_PG_BW_GET(ets->pg_bw_tbl, pg_entry));
1130 		else
1131 			/* If we join a group and one is strict
1132 			 * than the bw rulls */
1133 			cos_data->data[entry].strict =
1134 						BNX2X_DCBX_COS_HIGH_STRICT;
1135 	}
1136 	if ((0 == cos_data->data[0].pri_join_mask) &&
1137 	    (0 == cos_data->data[1].pri_join_mask))
1138 		BNX2X_ERR("dcbx error: Both groups must have priorities\n");
1139 }
1140 
1141 
1142 #ifndef POWER_OF_2
1143 #define POWER_OF_2(x)	((0 != x) && (0 == (x & (x-1))))
1144 #endif
1145 
bxn2x_dcbx_single_pg_to_cos_params(struct bnx2x * bp,struct pg_help_data * pg_help_data,struct cos_help_data * cos_data,u32 pri_join_mask,u8 num_of_dif_pri)1146 static void bxn2x_dcbx_single_pg_to_cos_params(struct bnx2x *bp,
1147 					      struct pg_help_data *pg_help_data,
1148 					      struct cos_help_data *cos_data,
1149 					      u32 pri_join_mask,
1150 					      u8 num_of_dif_pri)
1151 {
1152 	u8 i = 0;
1153 	u32 pri_tested = 0;
1154 	u32 pri_mask_without_pri = 0;
1155 	u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority;
1156 	/*debug*/
1157 	if (num_of_dif_pri == 1) {
1158 		bnx2x_dcbx_ets_disabled_entry_data(bp, cos_data, pri_join_mask);
1159 		return;
1160 	}
1161 	/* single priority group */
1162 	if (pg_help_data->data[0].pg < DCBX_MAX_NUM_PG_BW_ENTRIES) {
1163 		/* If there are both pauseable and non-pauseable priorities,
1164 		 * the pauseable priorities go to the first queue and
1165 		 * the non-pauseable priorities go to the second queue.
1166 		 */
1167 		if (IS_DCBX_PFC_PRI_MIX_PAUSE(bp, pri_join_mask)) {
1168 			/* Pauseable */
1169 			cos_data->data[0].pausable = true;
1170 			/* Non pauseable.*/
1171 			cos_data->data[1].pausable = false;
1172 
1173 			if (2 == num_of_dif_pri) {
1174 				cos_data->data[0].cos_bw = 50;
1175 				cos_data->data[1].cos_bw = 50;
1176 			}
1177 
1178 			if (3 == num_of_dif_pri) {
1179 				if (POWER_OF_2(DCBX_PFC_PRI_GET_PAUSE(bp,
1180 							pri_join_mask))) {
1181 					cos_data->data[0].cos_bw = 33;
1182 					cos_data->data[1].cos_bw = 67;
1183 				} else {
1184 					cos_data->data[0].cos_bw = 67;
1185 					cos_data->data[1].cos_bw = 33;
1186 				}
1187 			}
1188 
1189 		} else if (IS_DCBX_PFC_PRI_ONLY_PAUSE(bp, pri_join_mask)) {
1190 			/* If there are only pauseable priorities,
1191 			 * then one/two priorities go to the first queue
1192 			 * and one priority goes to the second queue.
1193 			 */
1194 			if (2 == num_of_dif_pri) {
1195 				cos_data->data[0].cos_bw = 50;
1196 				cos_data->data[1].cos_bw = 50;
1197 			} else {
1198 				cos_data->data[0].cos_bw = 67;
1199 				cos_data->data[1].cos_bw = 33;
1200 			}
1201 			cos_data->data[1].pausable = true;
1202 			cos_data->data[0].pausable = true;
1203 			/* All priorities except FCOE */
1204 			cos_data->data[0].pri_join_mask = (pri_join_mask &
1205 				((u8)~(1 << ttp[LLFC_TRAFFIC_TYPE_FCOE])));
1206 			/* Only FCOE priority.*/
1207 			cos_data->data[1].pri_join_mask =
1208 				(1 << ttp[LLFC_TRAFFIC_TYPE_FCOE]);
1209 		} else
1210 			/* If there are only non-pauseable priorities,
1211 			 * they will all go to the same queue.
1212 			 */
1213 			bnx2x_dcbx_ets_disabled_entry_data(bp,
1214 						cos_data, pri_join_mask);
1215 	} else {
1216 		/* priority group which is not BW limited (PG#15):*/
1217 		if (IS_DCBX_PFC_PRI_MIX_PAUSE(bp, pri_join_mask)) {
1218 			/* If there are both pauseable and non-pauseable
1219 			 * priorities, the pauseable priorities go to the first
1220 			 * queue and the non-pauseable priorities
1221 			 * go to the second queue.
1222 			 */
1223 			if (DCBX_PFC_PRI_GET_PAUSE(bp, pri_join_mask) >
1224 			    DCBX_PFC_PRI_GET_NON_PAUSE(bp, pri_join_mask)) {
1225 				cos_data->data[0].strict =
1226 					BNX2X_DCBX_COS_HIGH_STRICT;
1227 				cos_data->data[1].strict =
1228 					BNX2X_DCBX_COS_LOW_STRICT;
1229 			} else {
1230 				cos_data->data[0].strict =
1231 					BNX2X_DCBX_COS_LOW_STRICT;
1232 				cos_data->data[1].strict =
1233 					BNX2X_DCBX_COS_HIGH_STRICT;
1234 			}
1235 			/* Pauseable */
1236 			cos_data->data[0].pausable = true;
1237 			/* Non pause-able.*/
1238 			cos_data->data[1].pausable = false;
1239 		} else {
1240 			/* If there are only pauseable priorities or
1241 			 * only non-pauseable,* the lower priorities go
1242 			 * to the first queue and the higherpriorities go
1243 			 * to the second queue.
1244 			 */
1245 			cos_data->data[0].pausable =
1246 				cos_data->data[1].pausable =
1247 				IS_DCBX_PFC_PRI_ONLY_PAUSE(bp, pri_join_mask);
1248 
1249 			for (i = 0 ; i < LLFC_DRIVER_TRAFFIC_TYPE_MAX; i++) {
1250 				pri_tested = 1 << bp->dcbx_port_params.
1251 					app.traffic_type_priority[i];
1252 				/* Remove priority tested */
1253 				pri_mask_without_pri =
1254 					(pri_join_mask & ((u8)(~pri_tested)));
1255 				if (pri_mask_without_pri < pri_tested)
1256 					break;
1257 			}
1258 
1259 			if (i == LLFC_DRIVER_TRAFFIC_TYPE_MAX)
1260 				BNX2X_ERR("Invalid value for pri_join_mask -"
1261 					  " could not find a priority\n");
1262 
1263 			cos_data->data[0].pri_join_mask = pri_mask_without_pri;
1264 			cos_data->data[1].pri_join_mask = pri_tested;
1265 			/* Both queues are strict priority,
1266 			 * and that with the highest priority
1267 			 * gets the highest strict priority in the arbiter.
1268 			 */
1269 			cos_data->data[0].strict = BNX2X_DCBX_COS_LOW_STRICT;
1270 			cos_data->data[1].strict = BNX2X_DCBX_COS_HIGH_STRICT;
1271 		}
1272 	}
1273 }
1274 
bnx2x_dcbx_two_pg_to_cos_params(struct bnx2x * bp,struct pg_help_data * pg_help_data,struct dcbx_ets_feature * ets,struct cos_help_data * cos_data,u32 * pg_pri_orginal_spread,u32 pri_join_mask,u8 num_of_dif_pri)1275 static void bnx2x_dcbx_two_pg_to_cos_params(
1276 			    struct bnx2x		*bp,
1277 			    struct  pg_help_data	*pg_help_data,
1278 			    struct dcbx_ets_feature	*ets,
1279 			    struct cos_help_data	*cos_data,
1280 			    u32			*pg_pri_orginal_spread,
1281 			    u32				pri_join_mask,
1282 			    u8				num_of_dif_pri)
1283 {
1284 	u8 i = 0;
1285 	u8 pg[E2_NUM_OF_COS] = {0};
1286 
1287 	/* If there are both pauseable and non-pauseable priorities,
1288 	 * the pauseable priorities go to the first queue and
1289 	 * the non-pauseable priorities go to the second queue.
1290 	 */
1291 	if (IS_DCBX_PFC_PRI_MIX_PAUSE(bp, pri_join_mask)) {
1292 		if (IS_DCBX_PFC_PRI_MIX_PAUSE(bp,
1293 					 pg_help_data->data[0].pg_priority) ||
1294 		    IS_DCBX_PFC_PRI_MIX_PAUSE(bp,
1295 					 pg_help_data->data[1].pg_priority)) {
1296 			/* If one PG contains both pauseable and
1297 			 * non-pauseable priorities then ETS is disabled.
1298 			 */
1299 			bnx2x_dcbx_separate_pauseable_from_non(bp, cos_data,
1300 					pg_pri_orginal_spread, ets);
1301 			bp->dcbx_port_params.ets.enabled = false;
1302 			return;
1303 		}
1304 
1305 		/* Pauseable */
1306 		cos_data->data[0].pausable = true;
1307 		/* Non pauseable. */
1308 		cos_data->data[1].pausable = false;
1309 		if (IS_DCBX_PFC_PRI_ONLY_PAUSE(bp,
1310 				pg_help_data->data[0].pg_priority)) {
1311 			/* 0 is pauseable */
1312 			cos_data->data[0].pri_join_mask =
1313 				pg_help_data->data[0].pg_priority;
1314 			pg[0] = pg_help_data->data[0].pg;
1315 			cos_data->data[1].pri_join_mask =
1316 				pg_help_data->data[1].pg_priority;
1317 			pg[1] = pg_help_data->data[1].pg;
1318 		} else {/* 1 is pauseable */
1319 			cos_data->data[0].pri_join_mask =
1320 				pg_help_data->data[1].pg_priority;
1321 			pg[0] = pg_help_data->data[1].pg;
1322 			cos_data->data[1].pri_join_mask =
1323 				pg_help_data->data[0].pg_priority;
1324 			pg[1] = pg_help_data->data[0].pg;
1325 		}
1326 	} else {
1327 		/* If there are only pauseable priorities or
1328 		 * only non-pauseable, each PG goes to a queue.
1329 		 */
1330 		cos_data->data[0].pausable = cos_data->data[1].pausable =
1331 			IS_DCBX_PFC_PRI_ONLY_PAUSE(bp, pri_join_mask);
1332 		cos_data->data[0].pri_join_mask =
1333 			pg_help_data->data[0].pg_priority;
1334 		pg[0] = pg_help_data->data[0].pg;
1335 		cos_data->data[1].pri_join_mask =
1336 			pg_help_data->data[1].pg_priority;
1337 		pg[1] = pg_help_data->data[1].pg;
1338 	}
1339 
1340 	/* There can be only one strict pg */
1341 	for (i = 0 ; i < E2_NUM_OF_COS; i++) {
1342 		if (pg[i] < DCBX_MAX_NUM_PG_BW_ENTRIES)
1343 			cos_data->data[i].cos_bw =
1344 				DCBX_PG_BW_GET(ets->pg_bw_tbl, pg[i]);
1345 		else
1346 			cos_data->data[i].strict = BNX2X_DCBX_COS_HIGH_STRICT;
1347 	}
1348 }
1349 
1350 /*******************************************************************************
1351  * Description: Still
1352  *
1353  * Return:
1354  ******************************************************************************/
bnx2x_dcbx_three_pg_to_cos_params(struct bnx2x * bp,struct pg_help_data * pg_help_data,struct dcbx_ets_feature * ets,struct cos_help_data * cos_data,u32 * pg_pri_orginal_spread,u32 pri_join_mask,u8 num_of_dif_pri)1355 static void bnx2x_dcbx_three_pg_to_cos_params(
1356 			      struct bnx2x		*bp,
1357 			      struct pg_help_data	*pg_help_data,
1358 			      struct dcbx_ets_feature	*ets,
1359 			      struct cos_help_data	*cos_data,
1360 			      u32			*pg_pri_orginal_spread,
1361 			      u32			pri_join_mask,
1362 			      u8			num_of_dif_pri)
1363 {
1364 	u8 i = 0;
1365 	u32 pri_tested = 0;
1366 	u8 entry = 0;
1367 	u8 pg_entry = 0;
1368 	bool b_found_strict = false;
1369 	u8 num_of_pri = LLFC_DRIVER_TRAFFIC_TYPE_MAX;
1370 
1371 	cos_data->data[0].pri_join_mask = cos_data->data[1].pri_join_mask = 0;
1372 	/* If there are both pauseable and non-pauseable priorities,
1373 	 * the pauseable priorities go to the first queue and the
1374 	 * non-pauseable priorities go to the second queue.
1375 	 */
1376 	if (IS_DCBX_PFC_PRI_MIX_PAUSE(bp, pri_join_mask))
1377 		bnx2x_dcbx_separate_pauseable_from_non(bp,
1378 				cos_data, pg_pri_orginal_spread, ets);
1379 	else {
1380 		/* If two BW-limited PG-s were combined to one queue,
1381 		 * the BW is their sum.
1382 		 *
1383 		 * If there are only pauseable priorities or only non-pauseable,
1384 		 * and there are both BW-limited and non-BW-limited PG-s,
1385 		 * the BW-limited PG/s go to one queue and the non-BW-limited
1386 		 * PG/s go to the second queue.
1387 		 *
1388 		 * If there are only pauseable priorities or only non-pauseable
1389 		 * and all are BW limited, then	two priorities go to the first
1390 		 * queue and one priority goes to the second queue.
1391 		 *
1392 		 * We will join this two cases:
1393 		 * if one is BW limited it will go to the secoend queue
1394 		 * otherwise the last priority will get it
1395 		 */
1396 
1397 		cos_data->data[0].pausable = cos_data->data[1].pausable =
1398 			IS_DCBX_PFC_PRI_ONLY_PAUSE(bp, pri_join_mask);
1399 
1400 		for (i = 0 ; i < num_of_pri; i++) {
1401 			pri_tested = 1 << bp->dcbx_port_params.
1402 				app.traffic_type_priority[i];
1403 			pg_entry = (u8)pg_pri_orginal_spread[bp->
1404 				dcbx_port_params.app.traffic_type_priority[i]];
1405 
1406 			if (pg_entry < DCBX_MAX_NUM_PG_BW_ENTRIES) {
1407 				entry = 0;
1408 
1409 				if (i == (num_of_pri-1) &&
1410 				    false == b_found_strict)
1411 					/* last entry will be handled separately
1412 					 * If no priority is strict than last
1413 					 * enty goes to last queue.*/
1414 					entry = 1;
1415 				cos_data->data[entry].pri_join_mask |=
1416 								pri_tested;
1417 				bnx2x_dcbx_add_to_cos_bw(bp,
1418 					&cos_data->data[entry],
1419 					DCBX_PG_BW_GET(ets->pg_bw_tbl,
1420 						       pg_entry));
1421 			} else {
1422 				b_found_strict = true;
1423 				cos_data->data[1].pri_join_mask |= pri_tested;
1424 				/* If we join a group and one is strict
1425 				 * than the bw rulls */
1426 				cos_data->data[1].strict =
1427 					BNX2X_DCBX_COS_HIGH_STRICT;
1428 			}
1429 		}
1430 	}
1431 }
1432 
1433 
bnx2x_dcbx_fill_cos_params(struct bnx2x * bp,struct pg_help_data * help_data,struct dcbx_ets_feature * ets,u32 * pg_pri_orginal_spread)1434 static void bnx2x_dcbx_fill_cos_params(struct bnx2x *bp,
1435 				       struct pg_help_data *help_data,
1436 				       struct dcbx_ets_feature *ets,
1437 				       u32 *pg_pri_orginal_spread)
1438 {
1439 	struct cos_help_data         cos_data ;
1440 	u8                    i                           = 0;
1441 	u32                   pri_join_mask               = 0;
1442 	u8                    num_of_dif_pri              = 0;
1443 
1444 	memset(&cos_data, 0, sizeof(cos_data));
1445 	/* Validate the pg value */
1446 	for (i = 0; i < help_data->num_of_pg ; i++) {
1447 		if (DCBX_STRICT_PRIORITY != help_data->data[i].pg &&
1448 		    DCBX_MAX_NUM_PG_BW_ENTRIES <= help_data->data[i].pg)
1449 			BNX2X_ERR("Invalid pg[%d] data %x\n", i,
1450 				  help_data->data[i].pg);
1451 		pri_join_mask   |=  help_data->data[i].pg_priority;
1452 		num_of_dif_pri  += help_data->data[i].num_of_dif_pri;
1453 	}
1454 
1455 	/* default settings */
1456 	cos_data.num_of_cos = 2;
1457 	for (i = 0; i < E2_NUM_OF_COS ; i++) {
1458 		cos_data.data[i].pri_join_mask    = pri_join_mask;
1459 		cos_data.data[i].pausable         = false;
1460 		cos_data.data[i].strict           = BNX2X_DCBX_COS_NOT_STRICT;
1461 		cos_data.data[i].cos_bw           = DCBX_INVALID_COS_BW;
1462 	}
1463 
1464 	switch (help_data->num_of_pg) {
1465 	case 1:
1466 
1467 		bxn2x_dcbx_single_pg_to_cos_params(
1468 					       bp,
1469 					       help_data,
1470 					       &cos_data,
1471 					       pri_join_mask,
1472 					       num_of_dif_pri);
1473 		break;
1474 	case 2:
1475 		bnx2x_dcbx_two_pg_to_cos_params(
1476 					    bp,
1477 					    help_data,
1478 					    ets,
1479 					    &cos_data,
1480 					    pg_pri_orginal_spread,
1481 					    pri_join_mask,
1482 					    num_of_dif_pri);
1483 		break;
1484 
1485 	case 3:
1486 		bnx2x_dcbx_three_pg_to_cos_params(
1487 					      bp,
1488 					      help_data,
1489 					      ets,
1490 					      &cos_data,
1491 					      pg_pri_orginal_spread,
1492 					      pri_join_mask,
1493 					      num_of_dif_pri);
1494 
1495 		break;
1496 	default:
1497 		BNX2X_ERR("Wrong pg_help_data.num_of_pg\n");
1498 		bnx2x_dcbx_ets_disabled_entry_data(bp,
1499 						   &cos_data, pri_join_mask);
1500 	}
1501 
1502 	for (i = 0; i < cos_data.num_of_cos ; i++) {
1503 		struct bnx2x_dcbx_cos_params *params =
1504 			&bp->dcbx_port_params.ets.cos_params[i];
1505 
1506 		params->pauseable = cos_data.data[i].pausable;
1507 		params->strict = cos_data.data[i].strict;
1508 		params->bw_tbl = cos_data.data[i].cos_bw;
1509 		if (params->pauseable) {
1510 			params->pri_bitmask =
1511 			DCBX_PFC_PRI_GET_PAUSE(bp,
1512 					cos_data.data[i].pri_join_mask);
1513 			DP(NETIF_MSG_LINK, "COS %d PAUSABLE prijoinmask 0x%x\n",
1514 				  i, cos_data.data[i].pri_join_mask);
1515 		} else {
1516 			params->pri_bitmask =
1517 			DCBX_PFC_PRI_GET_NON_PAUSE(bp,
1518 					cos_data.data[i].pri_join_mask);
1519 			DP(NETIF_MSG_LINK, "COS %d NONPAUSABLE prijoinmask "
1520 					  "0x%x\n",
1521 				  i, cos_data.data[i].pri_join_mask);
1522 		}
1523 	}
1524 
1525 	bp->dcbx_port_params.ets.num_of_cos = cos_data.num_of_cos ;
1526 }
1527 
bnx2x_dcbx_get_ets_pri_pg_tbl(struct bnx2x * bp,u32 * set_configuration_ets_pg,u32 * pri_pg_tbl)1528 static void bnx2x_dcbx_get_ets_pri_pg_tbl(struct bnx2x *bp,
1529 				u32 *set_configuration_ets_pg,
1530 				u32 *pri_pg_tbl)
1531 {
1532 	int i;
1533 
1534 	for (i = 0; i < DCBX_MAX_NUM_PRI_PG_ENTRIES; i++) {
1535 		set_configuration_ets_pg[i] = DCBX_PRI_PG_GET(pri_pg_tbl, i);
1536 
1537 		DP(NETIF_MSG_LINK, "set_configuration_ets_pg[%d] = 0x%x\n",
1538 		   i, set_configuration_ets_pg[i]);
1539 	}
1540 }
1541 
1542 /*******************************************************************************
1543  * Description: Fill pfc_config struct that will be sent in DCBX start ramrod
1544  *
1545  * Return:
1546  ******************************************************************************/
bnx2x_pfc_fw_struct_e2(struct bnx2x * bp)1547 static void bnx2x_pfc_fw_struct_e2(struct bnx2x *bp)
1548 {
1549 	struct flow_control_configuration   *pfc_fw_cfg = NULL;
1550 	u16 pri_bit = 0;
1551 	u8 cos = 0, pri = 0;
1552 	struct priority_cos *tt2cos;
1553 	u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority;
1554 
1555 	pfc_fw_cfg = (struct flow_control_configuration *)
1556 					bnx2x_sp(bp, pfc_config);
1557 	memset(pfc_fw_cfg, 0, sizeof(struct flow_control_configuration));
1558 
1559 	/*shortcut*/
1560 	tt2cos = pfc_fw_cfg->traffic_type_to_priority_cos;
1561 
1562 	/* Fw version should be incremented each update */
1563 	pfc_fw_cfg->dcb_version = ++bp->dcb_version;
1564 	pfc_fw_cfg->dcb_enabled = DCB_ENABLED;
1565 
1566 	/* Default initialization */
1567 	for (pri = 0; pri < MAX_PFC_TRAFFIC_TYPES ; pri++) {
1568 		tt2cos[pri].priority = LLFC_TRAFFIC_TYPE_TO_PRIORITY_UNMAPPED;
1569 		tt2cos[pri].cos = 0;
1570 	}
1571 
1572 	/* Fill priority parameters */
1573 	for (pri = 0; pri < LLFC_DRIVER_TRAFFIC_TYPE_MAX; pri++) {
1574 		tt2cos[pri].priority = ttp[pri];
1575 		pri_bit = 1 << tt2cos[pri].priority;
1576 
1577 		/* Fill COS parameters based on COS calculated to
1578 		 * make it more generally for future use */
1579 		for (cos = 0; cos < bp->dcbx_port_params.ets.num_of_cos; cos++)
1580 			if (bp->dcbx_port_params.ets.cos_params[cos].
1581 						pri_bitmask & pri_bit)
1582 					tt2cos[pri].cos = cos;
1583 	}
1584 	bnx2x_dcbx_print_cos_params(bp,	pfc_fw_cfg);
1585 }
1586 /* DCB netlink */
1587 #ifdef BCM_DCBNL
1588 
1589 #define BNX2X_DCBX_CAPS		(DCB_CAP_DCBX_LLD_MANAGED | \
1590 				DCB_CAP_DCBX_VER_CEE | DCB_CAP_DCBX_STATIC)
1591 
bnx2x_dcbnl_set_valid(struct bnx2x * bp)1592 static inline bool bnx2x_dcbnl_set_valid(struct bnx2x *bp)
1593 {
1594 	/* validate dcbnl call that may change HW state:
1595 	 * DCB is on and DCBX mode was SUCCESSFULLY set by the user.
1596 	 */
1597 	return bp->dcb_state && bp->dcbx_mode_uset;
1598 }
1599 
bnx2x_dcbnl_get_state(struct net_device * netdev)1600 static u8 bnx2x_dcbnl_get_state(struct net_device *netdev)
1601 {
1602 	struct bnx2x *bp = netdev_priv(netdev);
1603 	DP(NETIF_MSG_LINK, "state = %d\n", bp->dcb_state);
1604 	return bp->dcb_state;
1605 }
1606 
bnx2x_dcbnl_set_state(struct net_device * netdev,u8 state)1607 static u8 bnx2x_dcbnl_set_state(struct net_device *netdev, u8 state)
1608 {
1609 	struct bnx2x *bp = netdev_priv(netdev);
1610 	DP(NETIF_MSG_LINK, "state = %s\n", state ? "on" : "off");
1611 
1612 	bnx2x_dcbx_set_state(bp, (state ? true : false), bp->dcbx_enabled);
1613 	return 0;
1614 }
1615 
bnx2x_dcbnl_get_perm_hw_addr(struct net_device * netdev,u8 * perm_addr)1616 static void bnx2x_dcbnl_get_perm_hw_addr(struct net_device *netdev,
1617 					 u8 *perm_addr)
1618 {
1619 	struct bnx2x *bp = netdev_priv(netdev);
1620 	DP(NETIF_MSG_LINK, "GET-PERM-ADDR\n");
1621 
1622 	/* first the HW mac address */
1623 	memcpy(perm_addr, netdev->dev_addr, netdev->addr_len);
1624 
1625 #ifdef BCM_CNIC
1626 	/* second SAN address */
1627 	memcpy(perm_addr+netdev->addr_len, bp->fip_mac, netdev->addr_len);
1628 #endif
1629 }
1630 
bnx2x_dcbnl_set_pg_tccfg_tx(struct net_device * netdev,int prio,u8 prio_type,u8 pgid,u8 bw_pct,u8 up_map)1631 static void bnx2x_dcbnl_set_pg_tccfg_tx(struct net_device *netdev, int prio,
1632 					u8 prio_type, u8 pgid, u8 bw_pct,
1633 					u8 up_map)
1634 {
1635 	struct bnx2x *bp = netdev_priv(netdev);
1636 
1637 	DP(NETIF_MSG_LINK, "prio[%d] = %d\n", prio, pgid);
1638 	if (!bnx2x_dcbnl_set_valid(bp) || prio >= DCBX_MAX_NUM_PRI_PG_ENTRIES)
1639 		return;
1640 
1641 	/**
1642 	 * bw_pct ingnored -	band-width percentage devision between user
1643 	 *			priorities within the same group is not
1644 	 *			standard and hence not supported
1645 	 *
1646 	 * prio_type igonred -	priority levels within the same group are not
1647 	 *			standard and hence are not supported. According
1648 	 *			to the standard pgid 15 is dedicated to strict
1649 	 *			prioirty traffic (on the port level).
1650 	 *
1651 	 * up_map ignored
1652 	 */
1653 
1654 	bp->dcbx_config_params.admin_configuration_ets_pg[prio] = pgid;
1655 	bp->dcbx_config_params.admin_ets_configuration_tx_enable = 1;
1656 }
1657 
bnx2x_dcbnl_set_pg_bwgcfg_tx(struct net_device * netdev,int pgid,u8 bw_pct)1658 static void bnx2x_dcbnl_set_pg_bwgcfg_tx(struct net_device *netdev,
1659 					 int pgid, u8 bw_pct)
1660 {
1661 	struct bnx2x *bp = netdev_priv(netdev);
1662 	DP(NETIF_MSG_LINK, "pgid[%d] = %d\n", pgid, bw_pct);
1663 
1664 	if (!bnx2x_dcbnl_set_valid(bp) || pgid >= DCBX_MAX_NUM_PG_BW_ENTRIES)
1665 		return;
1666 
1667 	bp->dcbx_config_params.admin_configuration_bw_precentage[pgid] = bw_pct;
1668 	bp->dcbx_config_params.admin_ets_configuration_tx_enable = 1;
1669 }
1670 
bnx2x_dcbnl_set_pg_tccfg_rx(struct net_device * netdev,int prio,u8 prio_type,u8 pgid,u8 bw_pct,u8 up_map)1671 static void bnx2x_dcbnl_set_pg_tccfg_rx(struct net_device *netdev, int prio,
1672 					u8 prio_type, u8 pgid, u8 bw_pct,
1673 					u8 up_map)
1674 {
1675 	struct bnx2x *bp = netdev_priv(netdev);
1676 	DP(NETIF_MSG_LINK, "Nothing to set; No RX support\n");
1677 }
1678 
bnx2x_dcbnl_set_pg_bwgcfg_rx(struct net_device * netdev,int pgid,u8 bw_pct)1679 static void bnx2x_dcbnl_set_pg_bwgcfg_rx(struct net_device *netdev,
1680 					 int pgid, u8 bw_pct)
1681 {
1682 	struct bnx2x *bp = netdev_priv(netdev);
1683 	DP(NETIF_MSG_LINK, "Nothing to set; No RX support\n");
1684 }
1685 
bnx2x_dcbnl_get_pg_tccfg_tx(struct net_device * netdev,int prio,u8 * prio_type,u8 * pgid,u8 * bw_pct,u8 * up_map)1686 static void bnx2x_dcbnl_get_pg_tccfg_tx(struct net_device *netdev, int prio,
1687 					u8 *prio_type, u8 *pgid, u8 *bw_pct,
1688 					u8 *up_map)
1689 {
1690 	struct bnx2x *bp = netdev_priv(netdev);
1691 	DP(NETIF_MSG_LINK, "prio = %d\n", prio);
1692 
1693 	/**
1694 	 * bw_pct ingnored -	band-width percentage devision between user
1695 	 *			priorities within the same group is not
1696 	 *			standard and hence not supported
1697 	 *
1698 	 * prio_type igonred -	priority levels within the same group are not
1699 	 *			standard and hence are not supported. According
1700 	 *			to the standard pgid 15 is dedicated to strict
1701 	 *			prioirty traffic (on the port level).
1702 	 *
1703 	 * up_map ignored
1704 	 */
1705 	*up_map = *bw_pct = *prio_type = *pgid = 0;
1706 
1707 	if (!bp->dcb_state || prio >= DCBX_MAX_NUM_PRI_PG_ENTRIES)
1708 		return;
1709 
1710 	*pgid = DCBX_PRI_PG_GET(bp->dcbx_local_feat.ets.pri_pg_tbl, prio);
1711 }
1712 
bnx2x_dcbnl_get_pg_bwgcfg_tx(struct net_device * netdev,int pgid,u8 * bw_pct)1713 static void bnx2x_dcbnl_get_pg_bwgcfg_tx(struct net_device *netdev,
1714 					 int pgid, u8 *bw_pct)
1715 {
1716 	struct bnx2x *bp = netdev_priv(netdev);
1717 	DP(NETIF_MSG_LINK, "pgid = %d\n", pgid);
1718 
1719 	*bw_pct = 0;
1720 
1721 	if (!bp->dcb_state || pgid >= DCBX_MAX_NUM_PG_BW_ENTRIES)
1722 		return;
1723 
1724 	*bw_pct = DCBX_PG_BW_GET(bp->dcbx_local_feat.ets.pg_bw_tbl, pgid);
1725 }
1726 
bnx2x_dcbnl_get_pg_tccfg_rx(struct net_device * netdev,int prio,u8 * prio_type,u8 * pgid,u8 * bw_pct,u8 * up_map)1727 static void bnx2x_dcbnl_get_pg_tccfg_rx(struct net_device *netdev, int prio,
1728 					u8 *prio_type, u8 *pgid, u8 *bw_pct,
1729 					u8 *up_map)
1730 {
1731 	struct bnx2x *bp = netdev_priv(netdev);
1732 	DP(NETIF_MSG_LINK, "Nothing to get; No RX support\n");
1733 
1734 	*prio_type = *pgid = *bw_pct = *up_map = 0;
1735 }
1736 
bnx2x_dcbnl_get_pg_bwgcfg_rx(struct net_device * netdev,int pgid,u8 * bw_pct)1737 static void bnx2x_dcbnl_get_pg_bwgcfg_rx(struct net_device *netdev,
1738 					 int pgid, u8 *bw_pct)
1739 {
1740 	struct bnx2x *bp = netdev_priv(netdev);
1741 	DP(NETIF_MSG_LINK, "Nothing to get; No RX support\n");
1742 
1743 	*bw_pct = 0;
1744 }
1745 
bnx2x_dcbnl_set_pfc_cfg(struct net_device * netdev,int prio,u8 setting)1746 static void bnx2x_dcbnl_set_pfc_cfg(struct net_device *netdev, int prio,
1747 				    u8 setting)
1748 {
1749 	struct bnx2x *bp = netdev_priv(netdev);
1750 	DP(NETIF_MSG_LINK, "prio[%d] = %d\n", prio, setting);
1751 
1752 	if (!bnx2x_dcbnl_set_valid(bp) || prio >= MAX_PFC_PRIORITIES)
1753 		return;
1754 
1755 	bp->dcbx_config_params.admin_pfc_bitmap |= ((setting ? 1 : 0) << prio);
1756 
1757 	if (setting)
1758 		bp->dcbx_config_params.admin_pfc_tx_enable = 1;
1759 }
1760 
bnx2x_dcbnl_get_pfc_cfg(struct net_device * netdev,int prio,u8 * setting)1761 static void bnx2x_dcbnl_get_pfc_cfg(struct net_device *netdev, int prio,
1762 				    u8 *setting)
1763 {
1764 	struct bnx2x *bp = netdev_priv(netdev);
1765 	DP(NETIF_MSG_LINK, "prio = %d\n", prio);
1766 
1767 	*setting = 0;
1768 
1769 	if (!bp->dcb_state || prio >= MAX_PFC_PRIORITIES)
1770 		return;
1771 
1772 	*setting = (bp->dcbx_local_feat.pfc.pri_en_bitmap >> prio) & 0x1;
1773 }
1774 
bnx2x_dcbnl_set_all(struct net_device * netdev)1775 static u8 bnx2x_dcbnl_set_all(struct net_device *netdev)
1776 {
1777 	struct bnx2x *bp = netdev_priv(netdev);
1778 	int rc = 0;
1779 
1780 	DP(NETIF_MSG_LINK, "SET-ALL\n");
1781 
1782 	if (!bnx2x_dcbnl_set_valid(bp))
1783 		return 1;
1784 
1785 	if (bp->recovery_state != BNX2X_RECOVERY_DONE) {
1786 		netdev_err(bp->dev, "Handling parity error recovery. "
1787 				"Try again later\n");
1788 		return 1;
1789 	}
1790 	if (netif_running(bp->dev)) {
1791 		bnx2x_nic_unload(bp, UNLOAD_NORMAL);
1792 		rc = bnx2x_nic_load(bp, LOAD_NORMAL);
1793 	}
1794 	DP(NETIF_MSG_LINK, "set_dcbx_params done (%d)\n", rc);
1795 	if (rc)
1796 		return 1;
1797 
1798 	return 0;
1799 }
1800 
bnx2x_dcbnl_get_cap(struct net_device * netdev,int capid,u8 * cap)1801 static u8 bnx2x_dcbnl_get_cap(struct net_device *netdev, int capid, u8 *cap)
1802 {
1803 	struct bnx2x *bp = netdev_priv(netdev);
1804 	u8 rval = 0;
1805 
1806 	if (bp->dcb_state) {
1807 		switch (capid) {
1808 		case DCB_CAP_ATTR_PG:
1809 			*cap = true;
1810 			break;
1811 		case DCB_CAP_ATTR_PFC:
1812 			*cap = true;
1813 			break;
1814 		case DCB_CAP_ATTR_UP2TC:
1815 			*cap = false;
1816 			break;
1817 		case DCB_CAP_ATTR_PG_TCS:
1818 			*cap = 0x80;	/* 8 priorities for PGs */
1819 			break;
1820 		case DCB_CAP_ATTR_PFC_TCS:
1821 			*cap = 0x80;	/* 8 priorities for PFC */
1822 			break;
1823 		case DCB_CAP_ATTR_GSP:
1824 			*cap = true;
1825 			break;
1826 		case DCB_CAP_ATTR_BCN:
1827 			*cap = false;
1828 			break;
1829 		case DCB_CAP_ATTR_DCBX:
1830 			*cap = BNX2X_DCBX_CAPS;
1831 		default:
1832 			rval = -EINVAL;
1833 			break;
1834 		}
1835 	} else
1836 		rval = -EINVAL;
1837 
1838 	DP(NETIF_MSG_LINK, "capid %d:%x\n", capid, *cap);
1839 	return rval;
1840 }
1841 
bnx2x_dcbnl_get_numtcs(struct net_device * netdev,int tcid,u8 * num)1842 static u8 bnx2x_dcbnl_get_numtcs(struct net_device *netdev, int tcid, u8 *num)
1843 {
1844 	struct bnx2x *bp = netdev_priv(netdev);
1845 	u8 rval = 0;
1846 
1847 	DP(NETIF_MSG_LINK, "tcid %d\n", tcid);
1848 
1849 	if (bp->dcb_state) {
1850 		switch (tcid) {
1851 		case DCB_NUMTCS_ATTR_PG:
1852 			*num = E2_NUM_OF_COS;
1853 			break;
1854 		case DCB_NUMTCS_ATTR_PFC:
1855 			*num = E2_NUM_OF_COS;
1856 			break;
1857 		default:
1858 			rval = -EINVAL;
1859 			break;
1860 		}
1861 	} else
1862 		rval = -EINVAL;
1863 
1864 	return rval;
1865 }
1866 
bnx2x_dcbnl_set_numtcs(struct net_device * netdev,int tcid,u8 num)1867 static u8 bnx2x_dcbnl_set_numtcs(struct net_device *netdev, int tcid, u8 num)
1868 {
1869 	struct bnx2x *bp = netdev_priv(netdev);
1870 	DP(NETIF_MSG_LINK, "num tcs = %d; Not supported\n", num);
1871 	return -EINVAL;
1872 }
1873 
bnx2x_dcbnl_get_pfc_state(struct net_device * netdev)1874 static u8  bnx2x_dcbnl_get_pfc_state(struct net_device *netdev)
1875 {
1876 	struct bnx2x *bp = netdev_priv(netdev);
1877 	DP(NETIF_MSG_LINK, "state = %d\n", bp->dcbx_local_feat.pfc.enabled);
1878 
1879 	if (!bp->dcb_state)
1880 		return 0;
1881 
1882 	return bp->dcbx_local_feat.pfc.enabled;
1883 }
1884 
bnx2x_dcbnl_set_pfc_state(struct net_device * netdev,u8 state)1885 static void bnx2x_dcbnl_set_pfc_state(struct net_device *netdev, u8 state)
1886 {
1887 	struct bnx2x *bp = netdev_priv(netdev);
1888 	DP(NETIF_MSG_LINK, "state = %s\n", state ? "on" : "off");
1889 
1890 	if (!bnx2x_dcbnl_set_valid(bp))
1891 		return;
1892 
1893 	bp->dcbx_config_params.admin_pfc_tx_enable =
1894 	bp->dcbx_config_params.admin_pfc_enable = (state ? 1 : 0);
1895 }
1896 
bnx2x_admin_app_set_ent(struct bnx2x_admin_priority_app_table * app_ent,u8 idtype,u16 idval,u8 up)1897 static void bnx2x_admin_app_set_ent(
1898 	struct bnx2x_admin_priority_app_table *app_ent,
1899 	u8 idtype, u16 idval, u8 up)
1900 {
1901 	app_ent->valid = 1;
1902 
1903 	switch (idtype) {
1904 	case DCB_APP_IDTYPE_ETHTYPE:
1905 		app_ent->traffic_type = TRAFFIC_TYPE_ETH;
1906 		break;
1907 	case DCB_APP_IDTYPE_PORTNUM:
1908 		app_ent->traffic_type = TRAFFIC_TYPE_PORT;
1909 		break;
1910 	default:
1911 		break; /* never gets here */
1912 	}
1913 	app_ent->app_id = idval;
1914 	app_ent->priority = up;
1915 }
1916 
bnx2x_admin_app_is_equal(struct bnx2x_admin_priority_app_table * app_ent,u8 idtype,u16 idval)1917 static bool bnx2x_admin_app_is_equal(
1918 	struct bnx2x_admin_priority_app_table *app_ent,
1919 	u8 idtype, u16 idval)
1920 {
1921 	if (!app_ent->valid)
1922 		return false;
1923 
1924 	switch (idtype) {
1925 	case DCB_APP_IDTYPE_ETHTYPE:
1926 		if (app_ent->traffic_type != TRAFFIC_TYPE_ETH)
1927 			return false;
1928 		break;
1929 	case DCB_APP_IDTYPE_PORTNUM:
1930 		if (app_ent->traffic_type != TRAFFIC_TYPE_PORT)
1931 			return false;
1932 		break;
1933 	default:
1934 		return false;
1935 	}
1936 	if (app_ent->app_id != idval)
1937 		return false;
1938 
1939 	return true;
1940 }
1941 
bnx2x_set_admin_app_up(struct bnx2x * bp,u8 idtype,u16 idval,u8 up)1942 static int bnx2x_set_admin_app_up(struct bnx2x *bp, u8 idtype, u16 idval, u8 up)
1943 {
1944 	int i, ff;
1945 
1946 	/* iterate over the app entries looking for idtype and idval */
1947 	for (i = 0, ff = -1; i < 4; i++) {
1948 		struct bnx2x_admin_priority_app_table *app_ent =
1949 			&bp->dcbx_config_params.admin_priority_app_table[i];
1950 		if (bnx2x_admin_app_is_equal(app_ent, idtype, idval))
1951 			break;
1952 
1953 		if (ff < 0 && !app_ent->valid)
1954 			ff = i;
1955 	}
1956 	if (i < 4)
1957 		/* if found overwrite up */
1958 		bp->dcbx_config_params.
1959 			admin_priority_app_table[i].priority = up;
1960 	else if (ff >= 0)
1961 		/* not found use first-free */
1962 		bnx2x_admin_app_set_ent(
1963 			&bp->dcbx_config_params.admin_priority_app_table[ff],
1964 			idtype, idval, up);
1965 	else
1966 		/* app table is full */
1967 		return -EBUSY;
1968 
1969 	/* up configured, if not 0 make sure feature is enabled */
1970 	if (up)
1971 		bp->dcbx_config_params.admin_application_priority_tx_enable = 1;
1972 
1973 	return 0;
1974 }
1975 
bnx2x_dcbnl_set_app_up(struct net_device * netdev,u8 idtype,u16 idval,u8 up)1976 static u8 bnx2x_dcbnl_set_app_up(struct net_device *netdev, u8 idtype,
1977 				 u16 idval, u8 up)
1978 {
1979 	struct bnx2x *bp = netdev_priv(netdev);
1980 
1981 	DP(NETIF_MSG_LINK, "app_type %d, app_id %x, prio bitmap %d\n",
1982 	   idtype, idval, up);
1983 
1984 	if (!bnx2x_dcbnl_set_valid(bp))
1985 		return -EINVAL;
1986 
1987 	/* verify idtype */
1988 	switch (idtype) {
1989 	case DCB_APP_IDTYPE_ETHTYPE:
1990 	case DCB_APP_IDTYPE_PORTNUM:
1991 		break;
1992 	default:
1993 		return -EINVAL;
1994 	}
1995 	return bnx2x_set_admin_app_up(bp, idtype, idval, up);
1996 }
1997 
bnx2x_dcbnl_get_dcbx(struct net_device * netdev)1998 static u8 bnx2x_dcbnl_get_dcbx(struct net_device *netdev)
1999 {
2000 	struct bnx2x *bp = netdev_priv(netdev);
2001 	u8 state;
2002 
2003 	state = DCB_CAP_DCBX_LLD_MANAGED | DCB_CAP_DCBX_VER_CEE;
2004 
2005 	if (bp->dcbx_enabled == BNX2X_DCBX_ENABLED_ON_NEG_OFF)
2006 		state |= DCB_CAP_DCBX_STATIC;
2007 
2008 	return state;
2009 }
2010 
bnx2x_dcbnl_set_dcbx(struct net_device * netdev,u8 state)2011 static u8 bnx2x_dcbnl_set_dcbx(struct net_device *netdev, u8 state)
2012 {
2013 	struct bnx2x *bp = netdev_priv(netdev);
2014 	DP(NETIF_MSG_LINK, "state = %02x\n", state);
2015 
2016 	/* set dcbx mode */
2017 
2018 	if ((state & BNX2X_DCBX_CAPS) != state) {
2019 		BNX2X_ERR("Requested DCBX mode %x is beyond advertised "
2020 			  "capabilities\n", state);
2021 		return 1;
2022 	}
2023 
2024 	if (bp->dcb_state != BNX2X_DCB_STATE_ON) {
2025 		BNX2X_ERR("DCB turned off, DCBX configuration is invalid\n");
2026 		return 1;
2027 	}
2028 
2029 	if (state & DCB_CAP_DCBX_STATIC)
2030 		bp->dcbx_enabled = BNX2X_DCBX_ENABLED_ON_NEG_OFF;
2031 	else
2032 		bp->dcbx_enabled = BNX2X_DCBX_ENABLED_ON_NEG_ON;
2033 
2034 	bp->dcbx_mode_uset = true;
2035 	return 0;
2036 }
2037 
2038 
bnx2x_dcbnl_get_featcfg(struct net_device * netdev,int featid,u8 * flags)2039 static u8 bnx2x_dcbnl_get_featcfg(struct net_device *netdev, int featid,
2040 				  u8 *flags)
2041 {
2042 	struct bnx2x *bp = netdev_priv(netdev);
2043 	u8 rval = 0;
2044 
2045 	DP(NETIF_MSG_LINK, "featid %d\n", featid);
2046 
2047 	if (bp->dcb_state) {
2048 		*flags = 0;
2049 		switch (featid) {
2050 		case DCB_FEATCFG_ATTR_PG:
2051 			if (bp->dcbx_local_feat.ets.enabled)
2052 				*flags |= DCB_FEATCFG_ENABLE;
2053 			if (bp->dcbx_error & DCBX_LOCAL_ETS_ERROR)
2054 				*flags |= DCB_FEATCFG_ERROR;
2055 			break;
2056 		case DCB_FEATCFG_ATTR_PFC:
2057 			if (bp->dcbx_local_feat.pfc.enabled)
2058 				*flags |= DCB_FEATCFG_ENABLE;
2059 			if (bp->dcbx_error & (DCBX_LOCAL_PFC_ERROR |
2060 			    DCBX_LOCAL_PFC_MISMATCH))
2061 				*flags |= DCB_FEATCFG_ERROR;
2062 			break;
2063 		case DCB_FEATCFG_ATTR_APP:
2064 			if (bp->dcbx_local_feat.app.enabled)
2065 				*flags |= DCB_FEATCFG_ENABLE;
2066 			if (bp->dcbx_error & (DCBX_LOCAL_APP_ERROR |
2067 			    DCBX_LOCAL_APP_MISMATCH))
2068 				*flags |= DCB_FEATCFG_ERROR;
2069 			break;
2070 		default:
2071 			rval = -EINVAL;
2072 			break;
2073 		}
2074 	} else
2075 		rval = -EINVAL;
2076 
2077 	return rval;
2078 }
2079 
bnx2x_dcbnl_set_featcfg(struct net_device * netdev,int featid,u8 flags)2080 static u8 bnx2x_dcbnl_set_featcfg(struct net_device *netdev, int featid,
2081 				  u8 flags)
2082 {
2083 	struct bnx2x *bp = netdev_priv(netdev);
2084 	u8 rval = 0;
2085 
2086 	DP(NETIF_MSG_LINK, "featid = %d flags = %02x\n", featid, flags);
2087 
2088 	/* ignore the 'advertise' flag */
2089 	if (bnx2x_dcbnl_set_valid(bp)) {
2090 		switch (featid) {
2091 		case DCB_FEATCFG_ATTR_PG:
2092 			bp->dcbx_config_params.admin_ets_enable =
2093 				flags & DCB_FEATCFG_ENABLE ? 1 : 0;
2094 			bp->dcbx_config_params.admin_ets_willing =
2095 				flags & DCB_FEATCFG_WILLING ? 1 : 0;
2096 			break;
2097 		case DCB_FEATCFG_ATTR_PFC:
2098 			bp->dcbx_config_params.admin_pfc_enable =
2099 				flags & DCB_FEATCFG_ENABLE ? 1 : 0;
2100 			bp->dcbx_config_params.admin_pfc_willing =
2101 				flags & DCB_FEATCFG_WILLING ? 1 : 0;
2102 			break;
2103 		case DCB_FEATCFG_ATTR_APP:
2104 			/* ignore enable, always enabled */
2105 			bp->dcbx_config_params.admin_app_priority_willing =
2106 				flags & DCB_FEATCFG_WILLING ? 1 : 0;
2107 			break;
2108 		default:
2109 			rval = -EINVAL;
2110 			break;
2111 		}
2112 	} else
2113 		rval = -EINVAL;
2114 
2115 	return rval;
2116 }
2117 
2118 const struct dcbnl_rtnl_ops bnx2x_dcbnl_ops = {
2119 	.getstate       = bnx2x_dcbnl_get_state,
2120 	.setstate       = bnx2x_dcbnl_set_state,
2121 	.getpermhwaddr  = bnx2x_dcbnl_get_perm_hw_addr,
2122 	.setpgtccfgtx   = bnx2x_dcbnl_set_pg_tccfg_tx,
2123 	.setpgbwgcfgtx  = bnx2x_dcbnl_set_pg_bwgcfg_tx,
2124 	.setpgtccfgrx   = bnx2x_dcbnl_set_pg_tccfg_rx,
2125 	.setpgbwgcfgrx  = bnx2x_dcbnl_set_pg_bwgcfg_rx,
2126 	.getpgtccfgtx   = bnx2x_dcbnl_get_pg_tccfg_tx,
2127 	.getpgbwgcfgtx  = bnx2x_dcbnl_get_pg_bwgcfg_tx,
2128 	.getpgtccfgrx   = bnx2x_dcbnl_get_pg_tccfg_rx,
2129 	.getpgbwgcfgrx  = bnx2x_dcbnl_get_pg_bwgcfg_rx,
2130 	.setpfccfg      = bnx2x_dcbnl_set_pfc_cfg,
2131 	.getpfccfg      = bnx2x_dcbnl_get_pfc_cfg,
2132 	.setall         = bnx2x_dcbnl_set_all,
2133 	.getcap         = bnx2x_dcbnl_get_cap,
2134 	.getnumtcs      = bnx2x_dcbnl_get_numtcs,
2135 	.setnumtcs      = bnx2x_dcbnl_set_numtcs,
2136 	.getpfcstate    = bnx2x_dcbnl_get_pfc_state,
2137 	.setpfcstate    = bnx2x_dcbnl_set_pfc_state,
2138 	.setapp         = bnx2x_dcbnl_set_app_up,
2139 	.getdcbx        = bnx2x_dcbnl_get_dcbx,
2140 	.setdcbx        = bnx2x_dcbnl_set_dcbx,
2141 	.getfeatcfg     = bnx2x_dcbnl_get_featcfg,
2142 	.setfeatcfg     = bnx2x_dcbnl_set_featcfg,
2143 };
2144 
2145 #endif /* BCM_DCBNL */
2146