18c2ecf20Sopenharmony_ci/* bnx2x_dcb.c: QLogic Everest network driver.
28c2ecf20Sopenharmony_ci *
38c2ecf20Sopenharmony_ci * Copyright 2009-2013 Broadcom Corporation
48c2ecf20Sopenharmony_ci * Copyright 2014 QLogic Corporation
58c2ecf20Sopenharmony_ci * All rights reserved
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Unless you and QLogic execute a separate written software license
88c2ecf20Sopenharmony_ci * agreement governing use of this software, this software is licensed to you
98c2ecf20Sopenharmony_ci * under the terms of the GNU General Public License version 2, available
108c2ecf20Sopenharmony_ci * at http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL").
118c2ecf20Sopenharmony_ci *
128c2ecf20Sopenharmony_ci * Notwithstanding the above, under no circumstances may you combine this
138c2ecf20Sopenharmony_ci * software in any way with any other QLogic software provided under a
148c2ecf20Sopenharmony_ci * license other than the GPL, without QLogic's express prior written
158c2ecf20Sopenharmony_ci * consent.
168c2ecf20Sopenharmony_ci *
178c2ecf20Sopenharmony_ci * Maintained by: Ariel Elior <ariel.elior@qlogic.com>
188c2ecf20Sopenharmony_ci * Written by: Dmitry Kravkov
198c2ecf20Sopenharmony_ci *
208c2ecf20Sopenharmony_ci */
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci#include <linux/netdevice.h>
258c2ecf20Sopenharmony_ci#include <linux/types.h>
268c2ecf20Sopenharmony_ci#include <linux/errno.h>
278c2ecf20Sopenharmony_ci#include <linux/rtnetlink.h>
288c2ecf20Sopenharmony_ci#include <net/dcbnl.h>
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci#include "bnx2x.h"
318c2ecf20Sopenharmony_ci#include "bnx2x_cmn.h"
328c2ecf20Sopenharmony_ci#include "bnx2x_dcb.h"
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci/* forward declarations of dcbx related functions */
358c2ecf20Sopenharmony_cistatic void bnx2x_pfc_set_pfc(struct bnx2x *bp);
368c2ecf20Sopenharmony_cistatic void bnx2x_dcbx_update_ets_params(struct bnx2x *bp);
378c2ecf20Sopenharmony_cistatic void bnx2x_dcbx_get_ets_pri_pg_tbl(struct bnx2x *bp,
388c2ecf20Sopenharmony_ci					  u32 *set_configuration_ets_pg,
398c2ecf20Sopenharmony_ci					  u32 *pri_pg_tbl);
408c2ecf20Sopenharmony_cistatic void bnx2x_dcbx_get_num_pg_traf_type(struct bnx2x *bp,
418c2ecf20Sopenharmony_ci					    u32 *pg_pri_orginal_spread,
428c2ecf20Sopenharmony_ci					    struct pg_help_data *help_data);
438c2ecf20Sopenharmony_cistatic void bnx2x_dcbx_fill_cos_params(struct bnx2x *bp,
448c2ecf20Sopenharmony_ci				       struct pg_help_data *help_data,
458c2ecf20Sopenharmony_ci				       struct dcbx_ets_feature *ets,
468c2ecf20Sopenharmony_ci				       u32 *pg_pri_orginal_spread);
478c2ecf20Sopenharmony_cistatic void bnx2x_dcbx_separate_pauseable_from_non(struct bnx2x *bp,
488c2ecf20Sopenharmony_ci				struct cos_help_data *cos_data,
498c2ecf20Sopenharmony_ci				u32 *pg_pri_orginal_spread,
508c2ecf20Sopenharmony_ci				struct dcbx_ets_feature *ets);
518c2ecf20Sopenharmony_cistatic void bnx2x_dcbx_fw_struct(struct bnx2x *bp,
528c2ecf20Sopenharmony_ci				 struct bnx2x_func_tx_start_params*);
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci/* helpers: read/write len bytes from addr into buff by REG_RD/REG_WR */
558c2ecf20Sopenharmony_cistatic void bnx2x_read_data(struct bnx2x *bp, u32 *buff,
568c2ecf20Sopenharmony_ci				   u32 addr, u32 len)
578c2ecf20Sopenharmony_ci{
588c2ecf20Sopenharmony_ci	int i;
598c2ecf20Sopenharmony_ci	for (i = 0; i < len; i += 4, buff++)
608c2ecf20Sopenharmony_ci		*buff = REG_RD(bp, addr + i);
618c2ecf20Sopenharmony_ci}
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_cistatic void bnx2x_write_data(struct bnx2x *bp, u32 *buff,
648c2ecf20Sopenharmony_ci				    u32 addr, u32 len)
658c2ecf20Sopenharmony_ci{
668c2ecf20Sopenharmony_ci	int i;
678c2ecf20Sopenharmony_ci	for (i = 0; i < len; i += 4, buff++)
688c2ecf20Sopenharmony_ci		REG_WR(bp, addr + i, *buff);
698c2ecf20Sopenharmony_ci}
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_cistatic void bnx2x_pfc_set(struct bnx2x *bp)
728c2ecf20Sopenharmony_ci{
738c2ecf20Sopenharmony_ci	struct bnx2x_nig_brb_pfc_port_params pfc_params = {0};
748c2ecf20Sopenharmony_ci	u32 pri_bit, val = 0;
758c2ecf20Sopenharmony_ci	int i;
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci	pfc_params.num_of_rx_cos_priority_mask =
788c2ecf20Sopenharmony_ci					bp->dcbx_port_params.ets.num_of_cos;
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci	/* Tx COS configuration */
818c2ecf20Sopenharmony_ci	for (i = 0; i < bp->dcbx_port_params.ets.num_of_cos; i++)
828c2ecf20Sopenharmony_ci		/*
838c2ecf20Sopenharmony_ci		 * We configure only the pauseable bits (non pauseable aren't
848c2ecf20Sopenharmony_ci		 * configured at all) it's done to avoid false pauses from
858c2ecf20Sopenharmony_ci		 * network
868c2ecf20Sopenharmony_ci		 */
878c2ecf20Sopenharmony_ci		pfc_params.rx_cos_priority_mask[i] =
888c2ecf20Sopenharmony_ci			bp->dcbx_port_params.ets.cos_params[i].pri_bitmask
898c2ecf20Sopenharmony_ci				& DCBX_PFC_PRI_PAUSE_MASK(bp);
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci	/*
928c2ecf20Sopenharmony_ci	 * Rx COS configuration
938c2ecf20Sopenharmony_ci	 * Changing PFC RX configuration .
948c2ecf20Sopenharmony_ci	 * In RX COS0 will always be configured to lossless and COS1 to lossy
958c2ecf20Sopenharmony_ci	 */
968c2ecf20Sopenharmony_ci	for (i = 0 ; i < MAX_PFC_PRIORITIES ; i++) {
978c2ecf20Sopenharmony_ci		pri_bit = 1 << i;
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci		if (!(pri_bit & DCBX_PFC_PRI_PAUSE_MASK(bp)))
1008c2ecf20Sopenharmony_ci			val |= 1 << (i * 4);
1018c2ecf20Sopenharmony_ci	}
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci	pfc_params.pkt_priority_to_cos = val;
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci	/* RX COS0 */
1068c2ecf20Sopenharmony_ci	pfc_params.llfc_low_priority_classes = DCBX_PFC_PRI_PAUSE_MASK(bp);
1078c2ecf20Sopenharmony_ci	/* RX COS1 */
1088c2ecf20Sopenharmony_ci	pfc_params.llfc_high_priority_classes = 0;
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci	bnx2x_acquire_phy_lock(bp);
1118c2ecf20Sopenharmony_ci	bp->link_params.feature_config_flags |= FEATURE_CONFIG_PFC_ENABLED;
1128c2ecf20Sopenharmony_ci	bnx2x_update_pfc(&bp->link_params, &bp->link_vars, &pfc_params);
1138c2ecf20Sopenharmony_ci	bnx2x_release_phy_lock(bp);
1148c2ecf20Sopenharmony_ci}
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_cistatic void bnx2x_pfc_clear(struct bnx2x *bp)
1178c2ecf20Sopenharmony_ci{
1188c2ecf20Sopenharmony_ci	struct bnx2x_nig_brb_pfc_port_params nig_params = {0};
1198c2ecf20Sopenharmony_ci	nig_params.pause_enable = 1;
1208c2ecf20Sopenharmony_ci	bnx2x_acquire_phy_lock(bp);
1218c2ecf20Sopenharmony_ci	bp->link_params.feature_config_flags &= ~FEATURE_CONFIG_PFC_ENABLED;
1228c2ecf20Sopenharmony_ci	bnx2x_update_pfc(&bp->link_params, &bp->link_vars, &nig_params);
1238c2ecf20Sopenharmony_ci	bnx2x_release_phy_lock(bp);
1248c2ecf20Sopenharmony_ci}
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_cistatic void  bnx2x_dump_dcbx_drv_param(struct bnx2x *bp,
1278c2ecf20Sopenharmony_ci				       struct dcbx_features *features,
1288c2ecf20Sopenharmony_ci				       u32 error)
1298c2ecf20Sopenharmony_ci{
1308c2ecf20Sopenharmony_ci	u8 i = 0;
1318c2ecf20Sopenharmony_ci	DP(NETIF_MSG_LINK, "local_mib.error %x\n", error);
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ci	/* PG */
1348c2ecf20Sopenharmony_ci	DP(NETIF_MSG_LINK,
1358c2ecf20Sopenharmony_ci	   "local_mib.features.ets.enabled %x\n", features->ets.enabled);
1368c2ecf20Sopenharmony_ci	for (i = 0; i < DCBX_MAX_NUM_PG_BW_ENTRIES; i++)
1378c2ecf20Sopenharmony_ci		DP(NETIF_MSG_LINK,
1388c2ecf20Sopenharmony_ci		   "local_mib.features.ets.pg_bw_tbl[%d] %d\n", i,
1398c2ecf20Sopenharmony_ci		   DCBX_PG_BW_GET(features->ets.pg_bw_tbl, i));
1408c2ecf20Sopenharmony_ci	for (i = 0; i < DCBX_MAX_NUM_PRI_PG_ENTRIES; i++)
1418c2ecf20Sopenharmony_ci		DP(NETIF_MSG_LINK,
1428c2ecf20Sopenharmony_ci		   "local_mib.features.ets.pri_pg_tbl[%d] %d\n", i,
1438c2ecf20Sopenharmony_ci		   DCBX_PRI_PG_GET(features->ets.pri_pg_tbl, i));
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci	/* pfc */
1468c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_DCB, "dcbx_features.pfc.pri_en_bitmap %x\n",
1478c2ecf20Sopenharmony_ci					features->pfc.pri_en_bitmap);
1488c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_DCB, "dcbx_features.pfc.pfc_caps %x\n",
1498c2ecf20Sopenharmony_ci					features->pfc.pfc_caps);
1508c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_DCB, "dcbx_features.pfc.enabled %x\n",
1518c2ecf20Sopenharmony_ci					features->pfc.enabled);
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_DCB, "dcbx_features.app.default_pri %x\n",
1548c2ecf20Sopenharmony_ci					features->app.default_pri);
1558c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_DCB, "dcbx_features.app.tc_supported %x\n",
1568c2ecf20Sopenharmony_ci					features->app.tc_supported);
1578c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_DCB, "dcbx_features.app.enabled %x\n",
1588c2ecf20Sopenharmony_ci					features->app.enabled);
1598c2ecf20Sopenharmony_ci	for (i = 0; i < DCBX_MAX_APP_PROTOCOL; i++) {
1608c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_DCB,
1618c2ecf20Sopenharmony_ci		   "dcbx_features.app.app_pri_tbl[%x].app_id %x\n",
1628c2ecf20Sopenharmony_ci		   i, features->app.app_pri_tbl[i].app_id);
1638c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_DCB,
1648c2ecf20Sopenharmony_ci		   "dcbx_features.app.app_pri_tbl[%x].pri_bitmap %x\n",
1658c2ecf20Sopenharmony_ci		   i, features->app.app_pri_tbl[i].pri_bitmap);
1668c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_DCB,
1678c2ecf20Sopenharmony_ci		   "dcbx_features.app.app_pri_tbl[%x].appBitfield %x\n",
1688c2ecf20Sopenharmony_ci		   i, features->app.app_pri_tbl[i].appBitfield);
1698c2ecf20Sopenharmony_ci	}
1708c2ecf20Sopenharmony_ci}
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_cistatic void bnx2x_dcbx_get_ap_priority(struct bnx2x *bp,
1738c2ecf20Sopenharmony_ci				       u8 pri_bitmap,
1748c2ecf20Sopenharmony_ci				       u8 llfc_traf_type)
1758c2ecf20Sopenharmony_ci{
1768c2ecf20Sopenharmony_ci	u32 pri = MAX_PFC_PRIORITIES;
1778c2ecf20Sopenharmony_ci	u32 index = MAX_PFC_PRIORITIES - 1;
1788c2ecf20Sopenharmony_ci	u32 pri_mask;
1798c2ecf20Sopenharmony_ci	u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority;
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci	/* Choose the highest priority */
1828c2ecf20Sopenharmony_ci	while ((MAX_PFC_PRIORITIES == pri) && (0 != index)) {
1838c2ecf20Sopenharmony_ci		pri_mask = 1 << index;
1848c2ecf20Sopenharmony_ci		if (GET_FLAGS(pri_bitmap, pri_mask))
1858c2ecf20Sopenharmony_ci			pri = index ;
1868c2ecf20Sopenharmony_ci		index--;
1878c2ecf20Sopenharmony_ci	}
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci	if (pri < MAX_PFC_PRIORITIES)
1908c2ecf20Sopenharmony_ci		ttp[llfc_traf_type] = max_t(u32, ttp[llfc_traf_type], pri);
1918c2ecf20Sopenharmony_ci}
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_cistatic void bnx2x_dcbx_get_ap_feature(struct bnx2x *bp,
1948c2ecf20Sopenharmony_ci				   struct dcbx_app_priority_feature *app,
1958c2ecf20Sopenharmony_ci				   u32 error) {
1968c2ecf20Sopenharmony_ci	u8 index;
1978c2ecf20Sopenharmony_ci	u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority;
1988c2ecf20Sopenharmony_ci	u8 iscsi_pri_found = 0, fcoe_pri_found = 0;
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci	if (GET_FLAGS(error, DCBX_LOCAL_APP_ERROR))
2018c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_DCB, "DCBX_LOCAL_APP_ERROR\n");
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_ci	if (GET_FLAGS(error, DCBX_LOCAL_APP_MISMATCH))
2048c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_DCB, "DCBX_LOCAL_APP_MISMATCH\n");
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci	if (GET_FLAGS(error, DCBX_REMOTE_APP_TLV_NOT_FOUND))
2078c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_DCB, "DCBX_REMOTE_APP_TLV_NOT_FOUND\n");
2088c2ecf20Sopenharmony_ci	if (app->enabled &&
2098c2ecf20Sopenharmony_ci	    !GET_FLAGS(error, DCBX_LOCAL_APP_ERROR | DCBX_LOCAL_APP_MISMATCH |
2108c2ecf20Sopenharmony_ci			      DCBX_REMOTE_APP_TLV_NOT_FOUND)) {
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci		bp->dcbx_port_params.app.enabled = true;
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_ci		/* Use 0 as the default application priority for all. */
2158c2ecf20Sopenharmony_ci		for (index = 0 ; index < LLFC_DRIVER_TRAFFIC_TYPE_MAX; index++)
2168c2ecf20Sopenharmony_ci			ttp[index] = 0;
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_ci		for (index = 0 ; index < DCBX_MAX_APP_PROTOCOL; index++) {
2198c2ecf20Sopenharmony_ci			struct dcbx_app_priority_entry *entry =
2208c2ecf20Sopenharmony_ci							app->app_pri_tbl;
2218c2ecf20Sopenharmony_ci			enum traffic_type type = MAX_TRAFFIC_TYPE;
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_ci			if (GET_FLAGS(entry[index].appBitfield,
2248c2ecf20Sopenharmony_ci				      DCBX_APP_SF_DEFAULT) &&
2258c2ecf20Sopenharmony_ci			    GET_FLAGS(entry[index].appBitfield,
2268c2ecf20Sopenharmony_ci				      DCBX_APP_SF_ETH_TYPE)) {
2278c2ecf20Sopenharmony_ci				type = LLFC_TRAFFIC_TYPE_NW;
2288c2ecf20Sopenharmony_ci			} else if (GET_FLAGS(entry[index].appBitfield,
2298c2ecf20Sopenharmony_ci					     DCBX_APP_SF_PORT) &&
2308c2ecf20Sopenharmony_ci				   TCP_PORT_ISCSI == entry[index].app_id) {
2318c2ecf20Sopenharmony_ci				type = LLFC_TRAFFIC_TYPE_ISCSI;
2328c2ecf20Sopenharmony_ci				iscsi_pri_found = 1;
2338c2ecf20Sopenharmony_ci			} else if (GET_FLAGS(entry[index].appBitfield,
2348c2ecf20Sopenharmony_ci					     DCBX_APP_SF_ETH_TYPE) &&
2358c2ecf20Sopenharmony_ci				   ETH_TYPE_FCOE == entry[index].app_id) {
2368c2ecf20Sopenharmony_ci				type = LLFC_TRAFFIC_TYPE_FCOE;
2378c2ecf20Sopenharmony_ci				fcoe_pri_found = 1;
2388c2ecf20Sopenharmony_ci			}
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci			if (type == MAX_TRAFFIC_TYPE)
2418c2ecf20Sopenharmony_ci				continue;
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci			bnx2x_dcbx_get_ap_priority(bp,
2448c2ecf20Sopenharmony_ci						   entry[index].pri_bitmap,
2458c2ecf20Sopenharmony_ci						   type);
2468c2ecf20Sopenharmony_ci		}
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_ci		/* If we have received a non-zero default application
2498c2ecf20Sopenharmony_ci		 * priority, then use that for applications which are
2508c2ecf20Sopenharmony_ci		 * not configured with any priority.
2518c2ecf20Sopenharmony_ci		 */
2528c2ecf20Sopenharmony_ci		if (ttp[LLFC_TRAFFIC_TYPE_NW] != 0) {
2538c2ecf20Sopenharmony_ci			if (!iscsi_pri_found) {
2548c2ecf20Sopenharmony_ci				ttp[LLFC_TRAFFIC_TYPE_ISCSI] =
2558c2ecf20Sopenharmony_ci					ttp[LLFC_TRAFFIC_TYPE_NW];
2568c2ecf20Sopenharmony_ci				DP(BNX2X_MSG_DCB,
2578c2ecf20Sopenharmony_ci				   "ISCSI is using default priority.\n");
2588c2ecf20Sopenharmony_ci			}
2598c2ecf20Sopenharmony_ci			if (!fcoe_pri_found) {
2608c2ecf20Sopenharmony_ci				ttp[LLFC_TRAFFIC_TYPE_FCOE] =
2618c2ecf20Sopenharmony_ci					ttp[LLFC_TRAFFIC_TYPE_NW];
2628c2ecf20Sopenharmony_ci				DP(BNX2X_MSG_DCB,
2638c2ecf20Sopenharmony_ci				   "FCoE is using default priority.\n");
2648c2ecf20Sopenharmony_ci			}
2658c2ecf20Sopenharmony_ci		}
2668c2ecf20Sopenharmony_ci	} else {
2678c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_DCB, "DCBX_LOCAL_APP_DISABLED\n");
2688c2ecf20Sopenharmony_ci		bp->dcbx_port_params.app.enabled = false;
2698c2ecf20Sopenharmony_ci		for (index = 0 ; index < LLFC_DRIVER_TRAFFIC_TYPE_MAX; index++)
2708c2ecf20Sopenharmony_ci			ttp[index] = INVALID_TRAFFIC_TYPE_PRIORITY;
2718c2ecf20Sopenharmony_ci	}
2728c2ecf20Sopenharmony_ci}
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_cistatic void bnx2x_dcbx_get_ets_feature(struct bnx2x *bp,
2758c2ecf20Sopenharmony_ci				       struct dcbx_ets_feature *ets,
2768c2ecf20Sopenharmony_ci				       u32 error) {
2778c2ecf20Sopenharmony_ci	int i = 0;
2788c2ecf20Sopenharmony_ci	u32 pg_pri_orginal_spread[DCBX_MAX_NUM_PG_BW_ENTRIES] = {0};
2798c2ecf20Sopenharmony_ci	struct pg_help_data pg_help_data;
2808c2ecf20Sopenharmony_ci	struct bnx2x_dcbx_cos_params *cos_params =
2818c2ecf20Sopenharmony_ci			bp->dcbx_port_params.ets.cos_params;
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_ci	memset(&pg_help_data, 0, sizeof(struct pg_help_data));
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_ci	if (GET_FLAGS(error, DCBX_LOCAL_ETS_ERROR))
2868c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_DCB, "DCBX_LOCAL_ETS_ERROR\n");
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci	if (GET_FLAGS(error, DCBX_REMOTE_ETS_TLV_NOT_FOUND))
2898c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_DCB, "DCBX_REMOTE_ETS_TLV_NOT_FOUND\n");
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ci	/* Clean up old settings of ets on COS */
2928c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(bp->dcbx_port_params.ets.cos_params) ; i++) {
2938c2ecf20Sopenharmony_ci		cos_params[i].pauseable = false;
2948c2ecf20Sopenharmony_ci		cos_params[i].strict = BNX2X_DCBX_STRICT_INVALID;
2958c2ecf20Sopenharmony_ci		cos_params[i].bw_tbl = DCBX_INVALID_COS_BW;
2968c2ecf20Sopenharmony_ci		cos_params[i].pri_bitmask = 0;
2978c2ecf20Sopenharmony_ci	}
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci	if (bp->dcbx_port_params.app.enabled && ets->enabled &&
3008c2ecf20Sopenharmony_ci	   !GET_FLAGS(error,
3018c2ecf20Sopenharmony_ci		      DCBX_LOCAL_ETS_ERROR | DCBX_REMOTE_ETS_TLV_NOT_FOUND)) {
3028c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_DCB, "DCBX_LOCAL_ETS_ENABLE\n");
3038c2ecf20Sopenharmony_ci		bp->dcbx_port_params.ets.enabled = true;
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci		bnx2x_dcbx_get_ets_pri_pg_tbl(bp,
3068c2ecf20Sopenharmony_ci					      pg_pri_orginal_spread,
3078c2ecf20Sopenharmony_ci					      ets->pri_pg_tbl);
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_ci		bnx2x_dcbx_get_num_pg_traf_type(bp,
3108c2ecf20Sopenharmony_ci						pg_pri_orginal_spread,
3118c2ecf20Sopenharmony_ci						&pg_help_data);
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_ci		bnx2x_dcbx_fill_cos_params(bp, &pg_help_data,
3148c2ecf20Sopenharmony_ci					   ets, pg_pri_orginal_spread);
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_ci	} else {
3178c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_DCB, "DCBX_LOCAL_ETS_DISABLED\n");
3188c2ecf20Sopenharmony_ci		bp->dcbx_port_params.ets.enabled = false;
3198c2ecf20Sopenharmony_ci		ets->pri_pg_tbl[0] = 0;
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_ci		for (i = 0; i < DCBX_MAX_NUM_PRI_PG_ENTRIES ; i++)
3228c2ecf20Sopenharmony_ci			DCBX_PG_BW_SET(ets->pg_bw_tbl, i, 1);
3238c2ecf20Sopenharmony_ci	}
3248c2ecf20Sopenharmony_ci}
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_cistatic void  bnx2x_dcbx_get_pfc_feature(struct bnx2x *bp,
3278c2ecf20Sopenharmony_ci					struct dcbx_pfc_feature *pfc, u32 error)
3288c2ecf20Sopenharmony_ci{
3298c2ecf20Sopenharmony_ci	if (GET_FLAGS(error, DCBX_LOCAL_PFC_ERROR))
3308c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_DCB, "DCBX_LOCAL_PFC_ERROR\n");
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci	if (GET_FLAGS(error, DCBX_REMOTE_PFC_TLV_NOT_FOUND))
3338c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_DCB, "DCBX_REMOTE_PFC_TLV_NOT_FOUND\n");
3348c2ecf20Sopenharmony_ci	if (bp->dcbx_port_params.app.enabled && pfc->enabled &&
3358c2ecf20Sopenharmony_ci	   !GET_FLAGS(error, DCBX_LOCAL_PFC_ERROR | DCBX_LOCAL_PFC_MISMATCH |
3368c2ecf20Sopenharmony_ci			     DCBX_REMOTE_PFC_TLV_NOT_FOUND)) {
3378c2ecf20Sopenharmony_ci		bp->dcbx_port_params.pfc.enabled = true;
3388c2ecf20Sopenharmony_ci		bp->dcbx_port_params.pfc.priority_non_pauseable_mask =
3398c2ecf20Sopenharmony_ci			~(pfc->pri_en_bitmap);
3408c2ecf20Sopenharmony_ci	} else {
3418c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_DCB, "DCBX_LOCAL_PFC_DISABLED\n");
3428c2ecf20Sopenharmony_ci		bp->dcbx_port_params.pfc.enabled = false;
3438c2ecf20Sopenharmony_ci		bp->dcbx_port_params.pfc.priority_non_pauseable_mask = 0;
3448c2ecf20Sopenharmony_ci	}
3458c2ecf20Sopenharmony_ci}
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_ci/* maps unmapped priorities to to the same COS as L2 */
3488c2ecf20Sopenharmony_cistatic void bnx2x_dcbx_map_nw(struct bnx2x *bp)
3498c2ecf20Sopenharmony_ci{
3508c2ecf20Sopenharmony_ci	int i;
3518c2ecf20Sopenharmony_ci	u32 unmapped = (1 << MAX_PFC_PRIORITIES) - 1; /* all ones */
3528c2ecf20Sopenharmony_ci	u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority;
3538c2ecf20Sopenharmony_ci	u32 nw_prio = 1 << ttp[LLFC_TRAFFIC_TYPE_NW];
3548c2ecf20Sopenharmony_ci	struct bnx2x_dcbx_cos_params *cos_params =
3558c2ecf20Sopenharmony_ci			bp->dcbx_port_params.ets.cos_params;
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_ci	/* get unmapped priorities by clearing mapped bits */
3588c2ecf20Sopenharmony_ci	for (i = 0; i < LLFC_DRIVER_TRAFFIC_TYPE_MAX; i++)
3598c2ecf20Sopenharmony_ci		unmapped &= ~(1 << ttp[i]);
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_ci	/* find cos for nw prio and extend it with unmapped */
3628c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(bp->dcbx_port_params.ets.cos_params); i++) {
3638c2ecf20Sopenharmony_ci		if (cos_params[i].pri_bitmask & nw_prio) {
3648c2ecf20Sopenharmony_ci			/* extend the bitmask with unmapped */
3658c2ecf20Sopenharmony_ci			DP(BNX2X_MSG_DCB,
3668c2ecf20Sopenharmony_ci			   "cos %d extended with 0x%08x\n", i, unmapped);
3678c2ecf20Sopenharmony_ci			cos_params[i].pri_bitmask |= unmapped;
3688c2ecf20Sopenharmony_ci			break;
3698c2ecf20Sopenharmony_ci		}
3708c2ecf20Sopenharmony_ci	}
3718c2ecf20Sopenharmony_ci}
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_cistatic void bnx2x_get_dcbx_drv_param(struct bnx2x *bp,
3748c2ecf20Sopenharmony_ci				     struct dcbx_features *features,
3758c2ecf20Sopenharmony_ci				     u32 error)
3768c2ecf20Sopenharmony_ci{
3778c2ecf20Sopenharmony_ci	bnx2x_dcbx_get_ap_feature(bp, &features->app, error);
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_ci	bnx2x_dcbx_get_pfc_feature(bp, &features->pfc, error);
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_ci	bnx2x_dcbx_get_ets_feature(bp, &features->ets, error);
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_ci	bnx2x_dcbx_map_nw(bp);
3848c2ecf20Sopenharmony_ci}
3858c2ecf20Sopenharmony_ci
3868c2ecf20Sopenharmony_ci#define DCBX_LOCAL_MIB_MAX_TRY_READ		(100)
3878c2ecf20Sopenharmony_cistatic int bnx2x_dcbx_read_mib(struct bnx2x *bp,
3888c2ecf20Sopenharmony_ci			       u32 *base_mib_addr,
3898c2ecf20Sopenharmony_ci			       u32 offset,
3908c2ecf20Sopenharmony_ci			       int read_mib_type)
3918c2ecf20Sopenharmony_ci{
3928c2ecf20Sopenharmony_ci	int max_try_read = 0;
3938c2ecf20Sopenharmony_ci	u32 mib_size, prefix_seq_num, suffix_seq_num;
3948c2ecf20Sopenharmony_ci	struct lldp_remote_mib *remote_mib ;
3958c2ecf20Sopenharmony_ci	struct lldp_local_mib  *local_mib;
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_ci	switch (read_mib_type) {
3988c2ecf20Sopenharmony_ci	case DCBX_READ_LOCAL_MIB:
3998c2ecf20Sopenharmony_ci		mib_size = sizeof(struct lldp_local_mib);
4008c2ecf20Sopenharmony_ci		break;
4018c2ecf20Sopenharmony_ci	case DCBX_READ_REMOTE_MIB:
4028c2ecf20Sopenharmony_ci		mib_size = sizeof(struct lldp_remote_mib);
4038c2ecf20Sopenharmony_ci		break;
4048c2ecf20Sopenharmony_ci	default:
4058c2ecf20Sopenharmony_ci		return 1; /*error*/
4068c2ecf20Sopenharmony_ci	}
4078c2ecf20Sopenharmony_ci
4088c2ecf20Sopenharmony_ci	offset += BP_PORT(bp) * mib_size;
4098c2ecf20Sopenharmony_ci
4108c2ecf20Sopenharmony_ci	do {
4118c2ecf20Sopenharmony_ci		bnx2x_read_data(bp, base_mib_addr, offset, mib_size);
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_ci		max_try_read++;
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_ci		switch (read_mib_type) {
4168c2ecf20Sopenharmony_ci		case DCBX_READ_LOCAL_MIB:
4178c2ecf20Sopenharmony_ci			local_mib = (struct lldp_local_mib *) base_mib_addr;
4188c2ecf20Sopenharmony_ci			prefix_seq_num = local_mib->prefix_seq_num;
4198c2ecf20Sopenharmony_ci			suffix_seq_num = local_mib->suffix_seq_num;
4208c2ecf20Sopenharmony_ci			break;
4218c2ecf20Sopenharmony_ci		case DCBX_READ_REMOTE_MIB:
4228c2ecf20Sopenharmony_ci			remote_mib = (struct lldp_remote_mib *) base_mib_addr;
4238c2ecf20Sopenharmony_ci			prefix_seq_num = remote_mib->prefix_seq_num;
4248c2ecf20Sopenharmony_ci			suffix_seq_num = remote_mib->suffix_seq_num;
4258c2ecf20Sopenharmony_ci			break;
4268c2ecf20Sopenharmony_ci		default:
4278c2ecf20Sopenharmony_ci			return 1; /*error*/
4288c2ecf20Sopenharmony_ci		}
4298c2ecf20Sopenharmony_ci	} while ((prefix_seq_num != suffix_seq_num) &&
4308c2ecf20Sopenharmony_ci	       (max_try_read < DCBX_LOCAL_MIB_MAX_TRY_READ));
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_ci	if (max_try_read >= DCBX_LOCAL_MIB_MAX_TRY_READ) {
4338c2ecf20Sopenharmony_ci		BNX2X_ERR("MIB could not be read\n");
4348c2ecf20Sopenharmony_ci		return 1;
4358c2ecf20Sopenharmony_ci	}
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_ci	return 0;
4388c2ecf20Sopenharmony_ci}
4398c2ecf20Sopenharmony_ci
4408c2ecf20Sopenharmony_cistatic void bnx2x_pfc_set_pfc(struct bnx2x *bp)
4418c2ecf20Sopenharmony_ci{
4428c2ecf20Sopenharmony_ci	int mfw_configured = SHMEM2_HAS(bp, drv_flags) &&
4438c2ecf20Sopenharmony_ci			     GET_FLAGS(SHMEM2_RD(bp, drv_flags),
4448c2ecf20Sopenharmony_ci				       1 << DRV_FLAGS_DCB_MFW_CONFIGURED);
4458c2ecf20Sopenharmony_ci
4468c2ecf20Sopenharmony_ci	if (bp->dcbx_port_params.pfc.enabled &&
4478c2ecf20Sopenharmony_ci	    (!(bp->dcbx_error & DCBX_REMOTE_MIB_ERROR) || mfw_configured))
4488c2ecf20Sopenharmony_ci		/*
4498c2ecf20Sopenharmony_ci		 * 1. Fills up common PFC structures if required
4508c2ecf20Sopenharmony_ci		 * 2. Configure NIG, MAC and BRB via the elink
4518c2ecf20Sopenharmony_ci		 */
4528c2ecf20Sopenharmony_ci		bnx2x_pfc_set(bp);
4538c2ecf20Sopenharmony_ci	else
4548c2ecf20Sopenharmony_ci		bnx2x_pfc_clear(bp);
4558c2ecf20Sopenharmony_ci}
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_ciint bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp)
4588c2ecf20Sopenharmony_ci{
4598c2ecf20Sopenharmony_ci	struct bnx2x_func_state_params func_params = {NULL};
4608c2ecf20Sopenharmony_ci	int rc;
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_ci	func_params.f_obj = &bp->func_obj;
4638c2ecf20Sopenharmony_ci	func_params.cmd = BNX2X_F_CMD_TX_STOP;
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_ci	__set_bit(RAMROD_COMP_WAIT, &func_params.ramrod_flags);
4668c2ecf20Sopenharmony_ci	__set_bit(RAMROD_RETRY, &func_params.ramrod_flags);
4678c2ecf20Sopenharmony_ci
4688c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_DCB, "STOP TRAFFIC\n");
4698c2ecf20Sopenharmony_ci
4708c2ecf20Sopenharmony_ci	rc = bnx2x_func_state_change(bp, &func_params);
4718c2ecf20Sopenharmony_ci	if (rc) {
4728c2ecf20Sopenharmony_ci		BNX2X_ERR("Unable to hold traffic for HW configuration\n");
4738c2ecf20Sopenharmony_ci		bnx2x_panic();
4748c2ecf20Sopenharmony_ci	}
4758c2ecf20Sopenharmony_ci
4768c2ecf20Sopenharmony_ci	return rc;
4778c2ecf20Sopenharmony_ci}
4788c2ecf20Sopenharmony_ci
4798c2ecf20Sopenharmony_ciint bnx2x_dcbx_resume_hw_tx(struct bnx2x *bp)
4808c2ecf20Sopenharmony_ci{
4818c2ecf20Sopenharmony_ci	struct bnx2x_func_state_params func_params = {NULL};
4828c2ecf20Sopenharmony_ci	struct bnx2x_func_tx_start_params *tx_params =
4838c2ecf20Sopenharmony_ci		&func_params.params.tx_start;
4848c2ecf20Sopenharmony_ci	int rc;
4858c2ecf20Sopenharmony_ci
4868c2ecf20Sopenharmony_ci	func_params.f_obj = &bp->func_obj;
4878c2ecf20Sopenharmony_ci	func_params.cmd = BNX2X_F_CMD_TX_START;
4888c2ecf20Sopenharmony_ci
4898c2ecf20Sopenharmony_ci	__set_bit(RAMROD_COMP_WAIT, &func_params.ramrod_flags);
4908c2ecf20Sopenharmony_ci	__set_bit(RAMROD_RETRY, &func_params.ramrod_flags);
4918c2ecf20Sopenharmony_ci
4928c2ecf20Sopenharmony_ci	bnx2x_dcbx_fw_struct(bp, tx_params);
4938c2ecf20Sopenharmony_ci
4948c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_DCB, "START TRAFFIC\n");
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ci	rc = bnx2x_func_state_change(bp, &func_params);
4978c2ecf20Sopenharmony_ci	if (rc) {
4988c2ecf20Sopenharmony_ci		BNX2X_ERR("Unable to resume traffic after HW configuration\n");
4998c2ecf20Sopenharmony_ci		bnx2x_panic();
5008c2ecf20Sopenharmony_ci	}
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_ci	return rc;
5038c2ecf20Sopenharmony_ci}
5048c2ecf20Sopenharmony_ci
5058c2ecf20Sopenharmony_cistatic void bnx2x_dcbx_2cos_limit_update_ets_config(struct bnx2x *bp)
5068c2ecf20Sopenharmony_ci{
5078c2ecf20Sopenharmony_ci	struct bnx2x_dcbx_pg_params *ets = &(bp->dcbx_port_params.ets);
5088c2ecf20Sopenharmony_ci	int rc = 0;
5098c2ecf20Sopenharmony_ci
5108c2ecf20Sopenharmony_ci	if (ets->num_of_cos == 0 || ets->num_of_cos > DCBX_COS_MAX_NUM_E2) {
5118c2ecf20Sopenharmony_ci		BNX2X_ERR("Illegal number of COSes %d\n", ets->num_of_cos);
5128c2ecf20Sopenharmony_ci		return;
5138c2ecf20Sopenharmony_ci	}
5148c2ecf20Sopenharmony_ci
5158c2ecf20Sopenharmony_ci	/* valid COS entries */
5168c2ecf20Sopenharmony_ci	if (ets->num_of_cos == 1)   /* no ETS */
5178c2ecf20Sopenharmony_ci		return;
5188c2ecf20Sopenharmony_ci
5198c2ecf20Sopenharmony_ci	/* sanity */
5208c2ecf20Sopenharmony_ci	if (((BNX2X_DCBX_STRICT_INVALID == ets->cos_params[0].strict) &&
5218c2ecf20Sopenharmony_ci	     (DCBX_INVALID_COS_BW == ets->cos_params[0].bw_tbl)) ||
5228c2ecf20Sopenharmony_ci	    ((BNX2X_DCBX_STRICT_INVALID == ets->cos_params[1].strict) &&
5238c2ecf20Sopenharmony_ci	     (DCBX_INVALID_COS_BW == ets->cos_params[1].bw_tbl))) {
5248c2ecf20Sopenharmony_ci		BNX2X_ERR("all COS should have at least bw_limit or strict"
5258c2ecf20Sopenharmony_ci			    "ets->cos_params[0].strict= %x"
5268c2ecf20Sopenharmony_ci			    "ets->cos_params[0].bw_tbl= %x"
5278c2ecf20Sopenharmony_ci			    "ets->cos_params[1].strict= %x"
5288c2ecf20Sopenharmony_ci			    "ets->cos_params[1].bw_tbl= %x",
5298c2ecf20Sopenharmony_ci			  ets->cos_params[0].strict,
5308c2ecf20Sopenharmony_ci			  ets->cos_params[0].bw_tbl,
5318c2ecf20Sopenharmony_ci			  ets->cos_params[1].strict,
5328c2ecf20Sopenharmony_ci			  ets->cos_params[1].bw_tbl);
5338c2ecf20Sopenharmony_ci		return;
5348c2ecf20Sopenharmony_ci	}
5358c2ecf20Sopenharmony_ci	/* If we join a group and there is bw_tbl and strict then bw rules */
5368c2ecf20Sopenharmony_ci	if ((DCBX_INVALID_COS_BW != ets->cos_params[0].bw_tbl) &&
5378c2ecf20Sopenharmony_ci	    (DCBX_INVALID_COS_BW != ets->cos_params[1].bw_tbl)) {
5388c2ecf20Sopenharmony_ci		u32 bw_tbl_0 = ets->cos_params[0].bw_tbl;
5398c2ecf20Sopenharmony_ci		u32 bw_tbl_1 = ets->cos_params[1].bw_tbl;
5408c2ecf20Sopenharmony_ci		/* Do not allow 0-100 configuration
5418c2ecf20Sopenharmony_ci		 * since PBF does not support it
5428c2ecf20Sopenharmony_ci		 * force 1-99 instead
5438c2ecf20Sopenharmony_ci		 */
5448c2ecf20Sopenharmony_ci		if (bw_tbl_0 == 0) {
5458c2ecf20Sopenharmony_ci			bw_tbl_0 = 1;
5468c2ecf20Sopenharmony_ci			bw_tbl_1 = 99;
5478c2ecf20Sopenharmony_ci		} else if (bw_tbl_1 == 0) {
5488c2ecf20Sopenharmony_ci			bw_tbl_1 = 1;
5498c2ecf20Sopenharmony_ci			bw_tbl_0 = 99;
5508c2ecf20Sopenharmony_ci		}
5518c2ecf20Sopenharmony_ci
5528c2ecf20Sopenharmony_ci		bnx2x_ets_bw_limit(&bp->link_params, bw_tbl_0, bw_tbl_1);
5538c2ecf20Sopenharmony_ci	} else {
5548c2ecf20Sopenharmony_ci		if (ets->cos_params[0].strict == BNX2X_DCBX_STRICT_COS_HIGHEST)
5558c2ecf20Sopenharmony_ci			rc = bnx2x_ets_strict(&bp->link_params, 0);
5568c2ecf20Sopenharmony_ci		else if (ets->cos_params[1].strict
5578c2ecf20Sopenharmony_ci					== BNX2X_DCBX_STRICT_COS_HIGHEST)
5588c2ecf20Sopenharmony_ci			rc = bnx2x_ets_strict(&bp->link_params, 1);
5598c2ecf20Sopenharmony_ci		if (rc)
5608c2ecf20Sopenharmony_ci			BNX2X_ERR("update_ets_params failed\n");
5618c2ecf20Sopenharmony_ci	}
5628c2ecf20Sopenharmony_ci}
5638c2ecf20Sopenharmony_ci
5648c2ecf20Sopenharmony_ci/*
5658c2ecf20Sopenharmony_ci * In E3B0 the configuration may have more than 2 COS.
5668c2ecf20Sopenharmony_ci */
5678c2ecf20Sopenharmony_cistatic void bnx2x_dcbx_update_ets_config(struct bnx2x *bp)
5688c2ecf20Sopenharmony_ci{
5698c2ecf20Sopenharmony_ci	struct bnx2x_dcbx_pg_params *ets = &(bp->dcbx_port_params.ets);
5708c2ecf20Sopenharmony_ci	struct bnx2x_ets_params ets_params = { 0 };
5718c2ecf20Sopenharmony_ci	u8 i;
5728c2ecf20Sopenharmony_ci
5738c2ecf20Sopenharmony_ci	ets_params.num_of_cos = ets->num_of_cos;
5748c2ecf20Sopenharmony_ci
5758c2ecf20Sopenharmony_ci	for (i = 0; i < ets->num_of_cos; i++) {
5768c2ecf20Sopenharmony_ci		/* COS is SP */
5778c2ecf20Sopenharmony_ci		if (ets->cos_params[i].strict != BNX2X_DCBX_STRICT_INVALID) {
5788c2ecf20Sopenharmony_ci			if (ets->cos_params[i].bw_tbl != DCBX_INVALID_COS_BW) {
5798c2ecf20Sopenharmony_ci				BNX2X_ERR("COS can't be not BW and not SP\n");
5808c2ecf20Sopenharmony_ci				return;
5818c2ecf20Sopenharmony_ci			}
5828c2ecf20Sopenharmony_ci
5838c2ecf20Sopenharmony_ci			ets_params.cos[i].state = bnx2x_cos_state_strict;
5848c2ecf20Sopenharmony_ci			ets_params.cos[i].params.sp_params.pri =
5858c2ecf20Sopenharmony_ci						ets->cos_params[i].strict;
5868c2ecf20Sopenharmony_ci		} else { /* COS is BW */
5878c2ecf20Sopenharmony_ci			if (ets->cos_params[i].bw_tbl == DCBX_INVALID_COS_BW) {
5888c2ecf20Sopenharmony_ci				BNX2X_ERR("COS can't be not BW and not SP\n");
5898c2ecf20Sopenharmony_ci				return;
5908c2ecf20Sopenharmony_ci			}
5918c2ecf20Sopenharmony_ci			ets_params.cos[i].state = bnx2x_cos_state_bw;
5928c2ecf20Sopenharmony_ci			ets_params.cos[i].params.bw_params.bw =
5938c2ecf20Sopenharmony_ci						(u8)ets->cos_params[i].bw_tbl;
5948c2ecf20Sopenharmony_ci		}
5958c2ecf20Sopenharmony_ci	}
5968c2ecf20Sopenharmony_ci
5978c2ecf20Sopenharmony_ci	/* Configure the ETS in HW */
5988c2ecf20Sopenharmony_ci	if (bnx2x_ets_e3b0_config(&bp->link_params, &bp->link_vars,
5998c2ecf20Sopenharmony_ci				  &ets_params)) {
6008c2ecf20Sopenharmony_ci		BNX2X_ERR("bnx2x_ets_e3b0_config failed\n");
6018c2ecf20Sopenharmony_ci		bnx2x_ets_disabled(&bp->link_params, &bp->link_vars);
6028c2ecf20Sopenharmony_ci	}
6038c2ecf20Sopenharmony_ci}
6048c2ecf20Sopenharmony_ci
6058c2ecf20Sopenharmony_cistatic void bnx2x_dcbx_update_ets_params(struct bnx2x *bp)
6068c2ecf20Sopenharmony_ci{
6078c2ecf20Sopenharmony_ci	int mfw_configured = SHMEM2_HAS(bp, drv_flags) &&
6088c2ecf20Sopenharmony_ci			     GET_FLAGS(SHMEM2_RD(bp, drv_flags),
6098c2ecf20Sopenharmony_ci				       1 << DRV_FLAGS_DCB_MFW_CONFIGURED);
6108c2ecf20Sopenharmony_ci
6118c2ecf20Sopenharmony_ci	bnx2x_ets_disabled(&bp->link_params, &bp->link_vars);
6128c2ecf20Sopenharmony_ci
6138c2ecf20Sopenharmony_ci	if (!bp->dcbx_port_params.ets.enabled ||
6148c2ecf20Sopenharmony_ci	    ((bp->dcbx_error & DCBX_REMOTE_MIB_ERROR) && !mfw_configured))
6158c2ecf20Sopenharmony_ci		return;
6168c2ecf20Sopenharmony_ci
6178c2ecf20Sopenharmony_ci	if (CHIP_IS_E3B0(bp))
6188c2ecf20Sopenharmony_ci		bnx2x_dcbx_update_ets_config(bp);
6198c2ecf20Sopenharmony_ci	else
6208c2ecf20Sopenharmony_ci		bnx2x_dcbx_2cos_limit_update_ets_config(bp);
6218c2ecf20Sopenharmony_ci}
6228c2ecf20Sopenharmony_ci
6238c2ecf20Sopenharmony_ci#ifdef BCM_DCBNL
6248c2ecf20Sopenharmony_cistatic int bnx2x_dcbx_read_shmem_remote_mib(struct bnx2x *bp)
6258c2ecf20Sopenharmony_ci{
6268c2ecf20Sopenharmony_ci	struct lldp_remote_mib remote_mib = {0};
6278c2ecf20Sopenharmony_ci	u32 dcbx_remote_mib_offset = SHMEM2_RD(bp, dcbx_remote_mib_offset);
6288c2ecf20Sopenharmony_ci	int rc;
6298c2ecf20Sopenharmony_ci
6308c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_DCB, "dcbx_remote_mib_offset 0x%x\n",
6318c2ecf20Sopenharmony_ci	   dcbx_remote_mib_offset);
6328c2ecf20Sopenharmony_ci
6338c2ecf20Sopenharmony_ci	if (SHMEM_DCBX_REMOTE_MIB_NONE == dcbx_remote_mib_offset) {
6348c2ecf20Sopenharmony_ci		BNX2X_ERR("FW doesn't support dcbx_remote_mib_offset\n");
6358c2ecf20Sopenharmony_ci		return -EINVAL;
6368c2ecf20Sopenharmony_ci	}
6378c2ecf20Sopenharmony_ci
6388c2ecf20Sopenharmony_ci	rc = bnx2x_dcbx_read_mib(bp, (u32 *)&remote_mib, dcbx_remote_mib_offset,
6398c2ecf20Sopenharmony_ci				 DCBX_READ_REMOTE_MIB);
6408c2ecf20Sopenharmony_ci
6418c2ecf20Sopenharmony_ci	if (rc) {
6428c2ecf20Sopenharmony_ci		BNX2X_ERR("Failed to read remote mib from FW\n");
6438c2ecf20Sopenharmony_ci		return rc;
6448c2ecf20Sopenharmony_ci	}
6458c2ecf20Sopenharmony_ci
6468c2ecf20Sopenharmony_ci	/* save features and flags */
6478c2ecf20Sopenharmony_ci	bp->dcbx_remote_feat = remote_mib.features;
6488c2ecf20Sopenharmony_ci	bp->dcbx_remote_flags = remote_mib.flags;
6498c2ecf20Sopenharmony_ci	return 0;
6508c2ecf20Sopenharmony_ci}
6518c2ecf20Sopenharmony_ci#endif
6528c2ecf20Sopenharmony_ci
6538c2ecf20Sopenharmony_cistatic int bnx2x_dcbx_read_shmem_neg_results(struct bnx2x *bp)
6548c2ecf20Sopenharmony_ci{
6558c2ecf20Sopenharmony_ci	struct lldp_local_mib local_mib = {0};
6568c2ecf20Sopenharmony_ci	u32 dcbx_neg_res_offset = SHMEM2_RD(bp, dcbx_neg_res_offset);
6578c2ecf20Sopenharmony_ci	int rc;
6588c2ecf20Sopenharmony_ci
6598c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_DCB, "dcbx_neg_res_offset 0x%x\n", dcbx_neg_res_offset);
6608c2ecf20Sopenharmony_ci
6618c2ecf20Sopenharmony_ci	if (SHMEM_DCBX_NEG_RES_NONE == dcbx_neg_res_offset) {
6628c2ecf20Sopenharmony_ci		BNX2X_ERR("FW doesn't support dcbx_neg_res_offset\n");
6638c2ecf20Sopenharmony_ci		return -EINVAL;
6648c2ecf20Sopenharmony_ci	}
6658c2ecf20Sopenharmony_ci
6668c2ecf20Sopenharmony_ci	rc = bnx2x_dcbx_read_mib(bp, (u32 *)&local_mib, dcbx_neg_res_offset,
6678c2ecf20Sopenharmony_ci				 DCBX_READ_LOCAL_MIB);
6688c2ecf20Sopenharmony_ci
6698c2ecf20Sopenharmony_ci	if (rc) {
6708c2ecf20Sopenharmony_ci		BNX2X_ERR("Failed to read local mib from FW\n");
6718c2ecf20Sopenharmony_ci		return rc;
6728c2ecf20Sopenharmony_ci	}
6738c2ecf20Sopenharmony_ci
6748c2ecf20Sopenharmony_ci	/* save features and error */
6758c2ecf20Sopenharmony_ci	bp->dcbx_local_feat = local_mib.features;
6768c2ecf20Sopenharmony_ci	bp->dcbx_error = local_mib.error;
6778c2ecf20Sopenharmony_ci	return 0;
6788c2ecf20Sopenharmony_ci}
6798c2ecf20Sopenharmony_ci
6808c2ecf20Sopenharmony_ci#ifdef BCM_DCBNL
6818c2ecf20Sopenharmony_cistatic inline
6828c2ecf20Sopenharmony_ciu8 bnx2x_dcbx_dcbnl_app_up(struct dcbx_app_priority_entry *ent)
6838c2ecf20Sopenharmony_ci{
6848c2ecf20Sopenharmony_ci	u8 pri;
6858c2ecf20Sopenharmony_ci
6868c2ecf20Sopenharmony_ci	/* Choose the highest priority */
6878c2ecf20Sopenharmony_ci	for (pri = MAX_PFC_PRIORITIES - 1; pri > 0; pri--)
6888c2ecf20Sopenharmony_ci		if (ent->pri_bitmap & (1 << pri))
6898c2ecf20Sopenharmony_ci			break;
6908c2ecf20Sopenharmony_ci	return pri;
6918c2ecf20Sopenharmony_ci}
6928c2ecf20Sopenharmony_ci
6938c2ecf20Sopenharmony_cistatic inline
6948c2ecf20Sopenharmony_ciu8 bnx2x_dcbx_dcbnl_app_idtype(struct dcbx_app_priority_entry *ent)
6958c2ecf20Sopenharmony_ci{
6968c2ecf20Sopenharmony_ci	return ((ent->appBitfield & DCBX_APP_ENTRY_SF_MASK) ==
6978c2ecf20Sopenharmony_ci		DCBX_APP_SF_PORT) ? DCB_APP_IDTYPE_PORTNUM :
6988c2ecf20Sopenharmony_ci		DCB_APP_IDTYPE_ETHTYPE;
6998c2ecf20Sopenharmony_ci}
7008c2ecf20Sopenharmony_ci
7018c2ecf20Sopenharmony_ciint bnx2x_dcbnl_update_applist(struct bnx2x *bp, bool delall)
7028c2ecf20Sopenharmony_ci{
7038c2ecf20Sopenharmony_ci	int i, err = 0;
7048c2ecf20Sopenharmony_ci
7058c2ecf20Sopenharmony_ci	for (i = 0; i < DCBX_MAX_APP_PROTOCOL && err == 0; i++) {
7068c2ecf20Sopenharmony_ci		struct dcbx_app_priority_entry *ent =
7078c2ecf20Sopenharmony_ci			&bp->dcbx_local_feat.app.app_pri_tbl[i];
7088c2ecf20Sopenharmony_ci
7098c2ecf20Sopenharmony_ci		if (ent->appBitfield & DCBX_APP_ENTRY_VALID) {
7108c2ecf20Sopenharmony_ci			u8 up = bnx2x_dcbx_dcbnl_app_up(ent);
7118c2ecf20Sopenharmony_ci
7128c2ecf20Sopenharmony_ci			/* avoid invalid user-priority */
7138c2ecf20Sopenharmony_ci			if (up) {
7148c2ecf20Sopenharmony_ci				struct dcb_app app;
7158c2ecf20Sopenharmony_ci				app.selector = bnx2x_dcbx_dcbnl_app_idtype(ent);
7168c2ecf20Sopenharmony_ci				app.protocol = ent->app_id;
7178c2ecf20Sopenharmony_ci				app.priority = delall ? 0 : up;
7188c2ecf20Sopenharmony_ci				err = dcb_setapp(bp->dev, &app);
7198c2ecf20Sopenharmony_ci			}
7208c2ecf20Sopenharmony_ci		}
7218c2ecf20Sopenharmony_ci	}
7228c2ecf20Sopenharmony_ci	return err;
7238c2ecf20Sopenharmony_ci}
7248c2ecf20Sopenharmony_ci#endif
7258c2ecf20Sopenharmony_ci
7268c2ecf20Sopenharmony_cistatic inline void bnx2x_dcbx_update_tc_mapping(struct bnx2x *bp)
7278c2ecf20Sopenharmony_ci{
7288c2ecf20Sopenharmony_ci	u8 prio, cos;
7298c2ecf20Sopenharmony_ci	for (cos = 0; cos < bp->dcbx_port_params.ets.num_of_cos; cos++) {
7308c2ecf20Sopenharmony_ci		for (prio = 0; prio < BNX2X_MAX_PRIORITY; prio++) {
7318c2ecf20Sopenharmony_ci			if (bp->dcbx_port_params.ets.cos_params[cos].pri_bitmask
7328c2ecf20Sopenharmony_ci			    & (1 << prio)) {
7338c2ecf20Sopenharmony_ci				bp->prio_to_cos[prio] = cos;
7348c2ecf20Sopenharmony_ci				DP(BNX2X_MSG_DCB,
7358c2ecf20Sopenharmony_ci				   "tx_mapping %d --> %d\n", prio, cos);
7368c2ecf20Sopenharmony_ci			}
7378c2ecf20Sopenharmony_ci		}
7388c2ecf20Sopenharmony_ci	}
7398c2ecf20Sopenharmony_ci
7408c2ecf20Sopenharmony_ci	/* setup tc must be called under rtnl lock, but we can't take it here
7418c2ecf20Sopenharmony_ci	 * as we are handling an attention on a work queue which must be
7428c2ecf20Sopenharmony_ci	 * flushed at some rtnl-locked contexts (e.g. if down)
7438c2ecf20Sopenharmony_ci	 */
7448c2ecf20Sopenharmony_ci	bnx2x_schedule_sp_rtnl(bp, BNX2X_SP_RTNL_SETUP_TC, 0);
7458c2ecf20Sopenharmony_ci}
7468c2ecf20Sopenharmony_ci
7478c2ecf20Sopenharmony_civoid bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state)
7488c2ecf20Sopenharmony_ci{
7498c2ecf20Sopenharmony_ci	switch (state) {
7508c2ecf20Sopenharmony_ci	case BNX2X_DCBX_STATE_NEG_RECEIVED:
7518c2ecf20Sopenharmony_ci		{
7528c2ecf20Sopenharmony_ci			DP(BNX2X_MSG_DCB, "BNX2X_DCBX_STATE_NEG_RECEIVED\n");
7538c2ecf20Sopenharmony_ci#ifdef BCM_DCBNL
7548c2ecf20Sopenharmony_ci			/**
7558c2ecf20Sopenharmony_ci			 * Delete app tlvs from dcbnl before reading new
7568c2ecf20Sopenharmony_ci			 * negotiation results
7578c2ecf20Sopenharmony_ci			 */
7588c2ecf20Sopenharmony_ci			bnx2x_dcbnl_update_applist(bp, true);
7598c2ecf20Sopenharmony_ci
7608c2ecf20Sopenharmony_ci			/* Read remote mib if dcbx is in the FW */
7618c2ecf20Sopenharmony_ci			if (bnx2x_dcbx_read_shmem_remote_mib(bp))
7628c2ecf20Sopenharmony_ci				return;
7638c2ecf20Sopenharmony_ci#endif
7648c2ecf20Sopenharmony_ci			/* Read neg results if dcbx is in the FW */
7658c2ecf20Sopenharmony_ci			if (bnx2x_dcbx_read_shmem_neg_results(bp))
7668c2ecf20Sopenharmony_ci				return;
7678c2ecf20Sopenharmony_ci
7688c2ecf20Sopenharmony_ci			bnx2x_dump_dcbx_drv_param(bp, &bp->dcbx_local_feat,
7698c2ecf20Sopenharmony_ci						  bp->dcbx_error);
7708c2ecf20Sopenharmony_ci
7718c2ecf20Sopenharmony_ci			bnx2x_get_dcbx_drv_param(bp, &bp->dcbx_local_feat,
7728c2ecf20Sopenharmony_ci						 bp->dcbx_error);
7738c2ecf20Sopenharmony_ci
7748c2ecf20Sopenharmony_ci			/* mark DCBX result for PMF migration */
7758c2ecf20Sopenharmony_ci			bnx2x_update_drv_flags(bp,
7768c2ecf20Sopenharmony_ci					       1 << DRV_FLAGS_DCB_CONFIGURED,
7778c2ecf20Sopenharmony_ci					       1);
7788c2ecf20Sopenharmony_ci#ifdef BCM_DCBNL
7798c2ecf20Sopenharmony_ci			/*
7808c2ecf20Sopenharmony_ci			 * Add new app tlvs to dcbnl
7818c2ecf20Sopenharmony_ci			 */
7828c2ecf20Sopenharmony_ci			bnx2x_dcbnl_update_applist(bp, false);
7838c2ecf20Sopenharmony_ci#endif
7848c2ecf20Sopenharmony_ci			/*
7858c2ecf20Sopenharmony_ci			 * reconfigure the netdevice with the results of the new
7868c2ecf20Sopenharmony_ci			 * dcbx negotiation.
7878c2ecf20Sopenharmony_ci			 */
7888c2ecf20Sopenharmony_ci			bnx2x_dcbx_update_tc_mapping(bp);
7898c2ecf20Sopenharmony_ci
7908c2ecf20Sopenharmony_ci			/*
7918c2ecf20Sopenharmony_ci			 * allow other functions to update their netdevices
7928c2ecf20Sopenharmony_ci			 * accordingly
7938c2ecf20Sopenharmony_ci			 */
7948c2ecf20Sopenharmony_ci			if (IS_MF(bp))
7958c2ecf20Sopenharmony_ci				bnx2x_link_sync_notify(bp);
7968c2ecf20Sopenharmony_ci
7978c2ecf20Sopenharmony_ci			bnx2x_schedule_sp_rtnl(bp, BNX2X_SP_RTNL_TX_STOP, 0);
7988c2ecf20Sopenharmony_ci			return;
7998c2ecf20Sopenharmony_ci		}
8008c2ecf20Sopenharmony_ci	case BNX2X_DCBX_STATE_TX_PAUSED:
8018c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_DCB, "BNX2X_DCBX_STATE_TX_PAUSED\n");
8028c2ecf20Sopenharmony_ci		bnx2x_pfc_set_pfc(bp);
8038c2ecf20Sopenharmony_ci
8048c2ecf20Sopenharmony_ci		bnx2x_dcbx_update_ets_params(bp);
8058c2ecf20Sopenharmony_ci
8068c2ecf20Sopenharmony_ci		/* ets may affect cmng configuration: reinit it in hw */
8078c2ecf20Sopenharmony_ci		bnx2x_set_local_cmng(bp);
8088c2ecf20Sopenharmony_ci		return;
8098c2ecf20Sopenharmony_ci	case BNX2X_DCBX_STATE_TX_RELEASED:
8108c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_DCB, "BNX2X_DCBX_STATE_TX_RELEASED\n");
8118c2ecf20Sopenharmony_ci		bnx2x_fw_command(bp, DRV_MSG_CODE_DCBX_PMF_DRV_OK, 0);
8128c2ecf20Sopenharmony_ci#ifdef BCM_DCBNL
8138c2ecf20Sopenharmony_ci		/*
8148c2ecf20Sopenharmony_ci		 * Send a notification for the new negotiated parameters
8158c2ecf20Sopenharmony_ci		 */
8168c2ecf20Sopenharmony_ci		dcbnl_cee_notify(bp->dev, RTM_GETDCB, DCB_CMD_CEE_GET, 0, 0);
8178c2ecf20Sopenharmony_ci#endif
8188c2ecf20Sopenharmony_ci		return;
8198c2ecf20Sopenharmony_ci	default:
8208c2ecf20Sopenharmony_ci		BNX2X_ERR("Unknown DCBX_STATE\n");
8218c2ecf20Sopenharmony_ci	}
8228c2ecf20Sopenharmony_ci}
8238c2ecf20Sopenharmony_ci
8248c2ecf20Sopenharmony_ci#define LLDP_ADMIN_MIB_OFFSET(bp)	(PORT_MAX*sizeof(struct lldp_params) + \
8258c2ecf20Sopenharmony_ci				      BP_PORT(bp)*sizeof(struct lldp_admin_mib))
8268c2ecf20Sopenharmony_ci
8278c2ecf20Sopenharmony_cistatic void bnx2x_dcbx_admin_mib_updated_params(struct bnx2x *bp,
8288c2ecf20Sopenharmony_ci				u32 dcbx_lldp_params_offset)
8298c2ecf20Sopenharmony_ci{
8308c2ecf20Sopenharmony_ci	struct lldp_admin_mib admin_mib;
8318c2ecf20Sopenharmony_ci	u32 i, other_traf_type = PREDEFINED_APP_IDX_MAX, traf_type = 0;
8328c2ecf20Sopenharmony_ci	u32 offset = dcbx_lldp_params_offset + LLDP_ADMIN_MIB_OFFSET(bp);
8338c2ecf20Sopenharmony_ci
8348c2ecf20Sopenharmony_ci	/*shortcuts*/
8358c2ecf20Sopenharmony_ci	struct dcbx_features *af = &admin_mib.features;
8368c2ecf20Sopenharmony_ci	struct bnx2x_config_dcbx_params *dp = &bp->dcbx_config_params;
8378c2ecf20Sopenharmony_ci
8388c2ecf20Sopenharmony_ci	memset(&admin_mib, 0, sizeof(struct lldp_admin_mib));
8398c2ecf20Sopenharmony_ci
8408c2ecf20Sopenharmony_ci	/* Read the data first */
8418c2ecf20Sopenharmony_ci	bnx2x_read_data(bp, (u32 *)&admin_mib, offset,
8428c2ecf20Sopenharmony_ci			sizeof(struct lldp_admin_mib));
8438c2ecf20Sopenharmony_ci
8448c2ecf20Sopenharmony_ci	if (bp->dcbx_enabled == BNX2X_DCBX_ENABLED_ON_NEG_ON)
8458c2ecf20Sopenharmony_ci		SET_FLAGS(admin_mib.ver_cfg_flags, DCBX_DCBX_ENABLED);
8468c2ecf20Sopenharmony_ci	else
8478c2ecf20Sopenharmony_ci		RESET_FLAGS(admin_mib.ver_cfg_flags, DCBX_DCBX_ENABLED);
8488c2ecf20Sopenharmony_ci
8498c2ecf20Sopenharmony_ci	if (dp->overwrite_settings == BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE) {
8508c2ecf20Sopenharmony_ci
8518c2ecf20Sopenharmony_ci		RESET_FLAGS(admin_mib.ver_cfg_flags, DCBX_CEE_VERSION_MASK);
8528c2ecf20Sopenharmony_ci		admin_mib.ver_cfg_flags |=
8538c2ecf20Sopenharmony_ci			(dp->admin_dcbx_version << DCBX_CEE_VERSION_SHIFT) &
8548c2ecf20Sopenharmony_ci			 DCBX_CEE_VERSION_MASK;
8558c2ecf20Sopenharmony_ci
8568c2ecf20Sopenharmony_ci		af->ets.enabled = (u8)dp->admin_ets_enable;
8578c2ecf20Sopenharmony_ci
8588c2ecf20Sopenharmony_ci		af->pfc.enabled = (u8)dp->admin_pfc_enable;
8598c2ecf20Sopenharmony_ci
8608c2ecf20Sopenharmony_ci		/* FOR IEEE dp->admin_tc_supported_tx_enable */
8618c2ecf20Sopenharmony_ci		if (dp->admin_ets_configuration_tx_enable)
8628c2ecf20Sopenharmony_ci			SET_FLAGS(admin_mib.ver_cfg_flags,
8638c2ecf20Sopenharmony_ci				  DCBX_ETS_CONFIG_TX_ENABLED);
8648c2ecf20Sopenharmony_ci		else
8658c2ecf20Sopenharmony_ci			RESET_FLAGS(admin_mib.ver_cfg_flags,
8668c2ecf20Sopenharmony_ci				    DCBX_ETS_CONFIG_TX_ENABLED);
8678c2ecf20Sopenharmony_ci		/* For IEEE admin_ets_recommendation_tx_enable */
8688c2ecf20Sopenharmony_ci		if (dp->admin_pfc_tx_enable)
8698c2ecf20Sopenharmony_ci			SET_FLAGS(admin_mib.ver_cfg_flags,
8708c2ecf20Sopenharmony_ci				  DCBX_PFC_CONFIG_TX_ENABLED);
8718c2ecf20Sopenharmony_ci		else
8728c2ecf20Sopenharmony_ci			RESET_FLAGS(admin_mib.ver_cfg_flags,
8738c2ecf20Sopenharmony_ci				  DCBX_PFC_CONFIG_TX_ENABLED);
8748c2ecf20Sopenharmony_ci
8758c2ecf20Sopenharmony_ci		if (dp->admin_application_priority_tx_enable)
8768c2ecf20Sopenharmony_ci			SET_FLAGS(admin_mib.ver_cfg_flags,
8778c2ecf20Sopenharmony_ci				  DCBX_APP_CONFIG_TX_ENABLED);
8788c2ecf20Sopenharmony_ci		else
8798c2ecf20Sopenharmony_ci			RESET_FLAGS(admin_mib.ver_cfg_flags,
8808c2ecf20Sopenharmony_ci				  DCBX_APP_CONFIG_TX_ENABLED);
8818c2ecf20Sopenharmony_ci
8828c2ecf20Sopenharmony_ci		if (dp->admin_ets_willing)
8838c2ecf20Sopenharmony_ci			SET_FLAGS(admin_mib.ver_cfg_flags, DCBX_ETS_WILLING);
8848c2ecf20Sopenharmony_ci		else
8858c2ecf20Sopenharmony_ci			RESET_FLAGS(admin_mib.ver_cfg_flags, DCBX_ETS_WILLING);
8868c2ecf20Sopenharmony_ci		/* For IEEE admin_ets_reco_valid */
8878c2ecf20Sopenharmony_ci		if (dp->admin_pfc_willing)
8888c2ecf20Sopenharmony_ci			SET_FLAGS(admin_mib.ver_cfg_flags, DCBX_PFC_WILLING);
8898c2ecf20Sopenharmony_ci		else
8908c2ecf20Sopenharmony_ci			RESET_FLAGS(admin_mib.ver_cfg_flags, DCBX_PFC_WILLING);
8918c2ecf20Sopenharmony_ci
8928c2ecf20Sopenharmony_ci		if (dp->admin_app_priority_willing)
8938c2ecf20Sopenharmony_ci			SET_FLAGS(admin_mib.ver_cfg_flags, DCBX_APP_WILLING);
8948c2ecf20Sopenharmony_ci		else
8958c2ecf20Sopenharmony_ci			RESET_FLAGS(admin_mib.ver_cfg_flags, DCBX_APP_WILLING);
8968c2ecf20Sopenharmony_ci
8978c2ecf20Sopenharmony_ci		for (i = 0 ; i < DCBX_MAX_NUM_PG_BW_ENTRIES; i++) {
8988c2ecf20Sopenharmony_ci			DCBX_PG_BW_SET(af->ets.pg_bw_tbl, i,
8998c2ecf20Sopenharmony_ci				(u8)dp->admin_configuration_bw_precentage[i]);
9008c2ecf20Sopenharmony_ci
9018c2ecf20Sopenharmony_ci			DP(BNX2X_MSG_DCB, "pg_bw_tbl[%d] = %02x\n",
9028c2ecf20Sopenharmony_ci			   i, DCBX_PG_BW_GET(af->ets.pg_bw_tbl, i));
9038c2ecf20Sopenharmony_ci		}
9048c2ecf20Sopenharmony_ci
9058c2ecf20Sopenharmony_ci		for (i = 0; i < DCBX_MAX_NUM_PRI_PG_ENTRIES; i++) {
9068c2ecf20Sopenharmony_ci			DCBX_PRI_PG_SET(af->ets.pri_pg_tbl, i,
9078c2ecf20Sopenharmony_ci					(u8)dp->admin_configuration_ets_pg[i]);
9088c2ecf20Sopenharmony_ci
9098c2ecf20Sopenharmony_ci			DP(BNX2X_MSG_DCB, "pri_pg_tbl[%d] = %02x\n",
9108c2ecf20Sopenharmony_ci			   i, DCBX_PRI_PG_GET(af->ets.pri_pg_tbl, i));
9118c2ecf20Sopenharmony_ci		}
9128c2ecf20Sopenharmony_ci
9138c2ecf20Sopenharmony_ci		/*For IEEE admin_recommendation_bw_percentage
9148c2ecf20Sopenharmony_ci		 *For IEEE admin_recommendation_ets_pg */
9158c2ecf20Sopenharmony_ci		af->pfc.pri_en_bitmap = (u8)dp->admin_pfc_bitmap;
9168c2ecf20Sopenharmony_ci		for (i = 0; i < DCBX_CONFIG_MAX_APP_PROTOCOL; i++) {
9178c2ecf20Sopenharmony_ci			if (dp->admin_priority_app_table[i].valid) {
9188c2ecf20Sopenharmony_ci				struct bnx2x_admin_priority_app_table *table =
9198c2ecf20Sopenharmony_ci					dp->admin_priority_app_table;
9208c2ecf20Sopenharmony_ci				if ((ETH_TYPE_FCOE == table[i].app_id) &&
9218c2ecf20Sopenharmony_ci				   (TRAFFIC_TYPE_ETH == table[i].traffic_type))
9228c2ecf20Sopenharmony_ci					traf_type = FCOE_APP_IDX;
9238c2ecf20Sopenharmony_ci				else if ((TCP_PORT_ISCSI == table[i].app_id) &&
9248c2ecf20Sopenharmony_ci				   (TRAFFIC_TYPE_PORT == table[i].traffic_type))
9258c2ecf20Sopenharmony_ci					traf_type = ISCSI_APP_IDX;
9268c2ecf20Sopenharmony_ci				else
9278c2ecf20Sopenharmony_ci					traf_type = other_traf_type++;
9288c2ecf20Sopenharmony_ci
9298c2ecf20Sopenharmony_ci				af->app.app_pri_tbl[traf_type].app_id =
9308c2ecf20Sopenharmony_ci					table[i].app_id;
9318c2ecf20Sopenharmony_ci
9328c2ecf20Sopenharmony_ci				af->app.app_pri_tbl[traf_type].pri_bitmap =
9338c2ecf20Sopenharmony_ci					(u8)(1 << table[i].priority);
9348c2ecf20Sopenharmony_ci
9358c2ecf20Sopenharmony_ci				af->app.app_pri_tbl[traf_type].appBitfield =
9368c2ecf20Sopenharmony_ci				    (DCBX_APP_ENTRY_VALID);
9378c2ecf20Sopenharmony_ci
9388c2ecf20Sopenharmony_ci				af->app.app_pri_tbl[traf_type].appBitfield |=
9398c2ecf20Sopenharmony_ci				   (TRAFFIC_TYPE_ETH == table[i].traffic_type) ?
9408c2ecf20Sopenharmony_ci					DCBX_APP_SF_ETH_TYPE : DCBX_APP_SF_PORT;
9418c2ecf20Sopenharmony_ci			}
9428c2ecf20Sopenharmony_ci		}
9438c2ecf20Sopenharmony_ci
9448c2ecf20Sopenharmony_ci		af->app.default_pri = (u8)dp->admin_default_priority;
9458c2ecf20Sopenharmony_ci	}
9468c2ecf20Sopenharmony_ci
9478c2ecf20Sopenharmony_ci	/* Write the data. */
9488c2ecf20Sopenharmony_ci	bnx2x_write_data(bp, (u32 *)&admin_mib, offset,
9498c2ecf20Sopenharmony_ci			 sizeof(struct lldp_admin_mib));
9508c2ecf20Sopenharmony_ci}
9518c2ecf20Sopenharmony_ci
9528c2ecf20Sopenharmony_civoid bnx2x_dcbx_set_state(struct bnx2x *bp, bool dcb_on, u32 dcbx_enabled)
9538c2ecf20Sopenharmony_ci{
9548c2ecf20Sopenharmony_ci	if (!CHIP_IS_E1x(bp)) {
9558c2ecf20Sopenharmony_ci		bp->dcb_state = dcb_on;
9568c2ecf20Sopenharmony_ci		bp->dcbx_enabled = dcbx_enabled;
9578c2ecf20Sopenharmony_ci	} else {
9588c2ecf20Sopenharmony_ci		bp->dcb_state = false;
9598c2ecf20Sopenharmony_ci		bp->dcbx_enabled = BNX2X_DCBX_ENABLED_INVALID;
9608c2ecf20Sopenharmony_ci	}
9618c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_DCB, "DCB state [%s:%s]\n",
9628c2ecf20Sopenharmony_ci	   dcb_on ? "ON" : "OFF",
9638c2ecf20Sopenharmony_ci	   dcbx_enabled == BNX2X_DCBX_ENABLED_OFF ? "user-mode" :
9648c2ecf20Sopenharmony_ci	   dcbx_enabled == BNX2X_DCBX_ENABLED_ON_NEG_OFF ? "on-chip static" :
9658c2ecf20Sopenharmony_ci	   dcbx_enabled == BNX2X_DCBX_ENABLED_ON_NEG_ON ?
9668c2ecf20Sopenharmony_ci	   "on-chip with negotiation" : "invalid");
9678c2ecf20Sopenharmony_ci}
9688c2ecf20Sopenharmony_ci
9698c2ecf20Sopenharmony_civoid bnx2x_dcbx_init_params(struct bnx2x *bp)
9708c2ecf20Sopenharmony_ci{
9718c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_dcbx_version = 0x0; /* 0 - CEE; 1 - IEEE */
9728c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_ets_willing = 1;
9738c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_pfc_willing = 1;
9748c2ecf20Sopenharmony_ci	bp->dcbx_config_params.overwrite_settings = 1;
9758c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_ets_enable = 1;
9768c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_pfc_enable = 1;
9778c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_tc_supported_tx_enable = 1;
9788c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_ets_configuration_tx_enable = 1;
9798c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_pfc_tx_enable = 1;
9808c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_application_priority_tx_enable = 1;
9818c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_ets_reco_valid = 1;
9828c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_app_priority_willing = 1;
9838c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_configuration_bw_precentage[0] = 100;
9848c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_configuration_bw_precentage[1] = 0;
9858c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_configuration_bw_precentage[2] = 0;
9868c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_configuration_bw_precentage[3] = 0;
9878c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_configuration_bw_precentage[4] = 0;
9888c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_configuration_bw_precentage[5] = 0;
9898c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_configuration_bw_precentage[6] = 0;
9908c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_configuration_bw_precentage[7] = 0;
9918c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_configuration_ets_pg[0] = 0;
9928c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_configuration_ets_pg[1] = 0;
9938c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_configuration_ets_pg[2] = 0;
9948c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_configuration_ets_pg[3] = 0;
9958c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_configuration_ets_pg[4] = 0;
9968c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_configuration_ets_pg[5] = 0;
9978c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_configuration_ets_pg[6] = 0;
9988c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_configuration_ets_pg[7] = 0;
9998c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_recommendation_bw_precentage[0] = 100;
10008c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_recommendation_bw_precentage[1] = 0;
10018c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_recommendation_bw_precentage[2] = 0;
10028c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_recommendation_bw_precentage[3] = 0;
10038c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_recommendation_bw_precentage[4] = 0;
10048c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_recommendation_bw_precentage[5] = 0;
10058c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_recommendation_bw_precentage[6] = 0;
10068c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_recommendation_bw_precentage[7] = 0;
10078c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_recommendation_ets_pg[0] = 0;
10088c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_recommendation_ets_pg[1] = 1;
10098c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_recommendation_ets_pg[2] = 2;
10108c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_recommendation_ets_pg[3] = 3;
10118c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_recommendation_ets_pg[4] = 4;
10128c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_recommendation_ets_pg[5] = 5;
10138c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_recommendation_ets_pg[6] = 6;
10148c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_recommendation_ets_pg[7] = 7;
10158c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_pfc_bitmap = 0x0;
10168c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_priority_app_table[0].valid = 0;
10178c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_priority_app_table[1].valid = 0;
10188c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_priority_app_table[2].valid = 0;
10198c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_priority_app_table[3].valid = 0;
10208c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_default_priority = 0;
10218c2ecf20Sopenharmony_ci}
10228c2ecf20Sopenharmony_ci
10238c2ecf20Sopenharmony_civoid bnx2x_dcbx_init(struct bnx2x *bp, bool update_shmem)
10248c2ecf20Sopenharmony_ci{
10258c2ecf20Sopenharmony_ci	u32 dcbx_lldp_params_offset = SHMEM_LLDP_DCBX_PARAMS_NONE;
10268c2ecf20Sopenharmony_ci
10278c2ecf20Sopenharmony_ci	/* only PMF can send ADMIN msg to MFW in old MFW versions */
10288c2ecf20Sopenharmony_ci	if ((!bp->port.pmf) && (!(bp->flags & BC_SUPPORTS_DCBX_MSG_NON_PMF)))
10298c2ecf20Sopenharmony_ci		return;
10308c2ecf20Sopenharmony_ci
10318c2ecf20Sopenharmony_ci	if (bp->dcbx_enabled <= 0)
10328c2ecf20Sopenharmony_ci		return;
10338c2ecf20Sopenharmony_ci
10348c2ecf20Sopenharmony_ci	/* validate:
10358c2ecf20Sopenharmony_ci	 * chip of good for dcbx version,
10368c2ecf20Sopenharmony_ci	 * dcb is wanted
10378c2ecf20Sopenharmony_ci	 * shmem2 contains DCBX support fields
10388c2ecf20Sopenharmony_ci	 */
10398c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_DCB, "dcb_state %d bp->port.pmf %d\n",
10408c2ecf20Sopenharmony_ci	   bp->dcb_state, bp->port.pmf);
10418c2ecf20Sopenharmony_ci
10428c2ecf20Sopenharmony_ci	if (bp->dcb_state == BNX2X_DCB_STATE_ON &&
10438c2ecf20Sopenharmony_ci	    SHMEM2_HAS(bp, dcbx_lldp_params_offset)) {
10448c2ecf20Sopenharmony_ci		dcbx_lldp_params_offset =
10458c2ecf20Sopenharmony_ci			SHMEM2_RD(bp, dcbx_lldp_params_offset);
10468c2ecf20Sopenharmony_ci
10478c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_DCB, "dcbx_lldp_params_offset 0x%x\n",
10488c2ecf20Sopenharmony_ci		   dcbx_lldp_params_offset);
10498c2ecf20Sopenharmony_ci
10508c2ecf20Sopenharmony_ci		bnx2x_update_drv_flags(bp, 1 << DRV_FLAGS_DCB_CONFIGURED, 0);
10518c2ecf20Sopenharmony_ci
10528c2ecf20Sopenharmony_ci		if (SHMEM_LLDP_DCBX_PARAMS_NONE != dcbx_lldp_params_offset) {
10538c2ecf20Sopenharmony_ci			/* need HW lock to avoid scenario of two drivers
10548c2ecf20Sopenharmony_ci			 * writing in parallel to shmem
10558c2ecf20Sopenharmony_ci			 */
10568c2ecf20Sopenharmony_ci			bnx2x_acquire_hw_lock(bp,
10578c2ecf20Sopenharmony_ci					      HW_LOCK_RESOURCE_DCBX_ADMIN_MIB);
10588c2ecf20Sopenharmony_ci			if (update_shmem)
10598c2ecf20Sopenharmony_ci				bnx2x_dcbx_admin_mib_updated_params(bp,
10608c2ecf20Sopenharmony_ci					dcbx_lldp_params_offset);
10618c2ecf20Sopenharmony_ci
10628c2ecf20Sopenharmony_ci			/* Let HW start negotiation */
10638c2ecf20Sopenharmony_ci			bnx2x_fw_command(bp,
10648c2ecf20Sopenharmony_ci					 DRV_MSG_CODE_DCBX_ADMIN_PMF_MSG, 0);
10658c2ecf20Sopenharmony_ci			/* release HW lock only after MFW acks that it finished
10668c2ecf20Sopenharmony_ci			 * reading values from shmem
10678c2ecf20Sopenharmony_ci			 */
10688c2ecf20Sopenharmony_ci			bnx2x_release_hw_lock(bp,
10698c2ecf20Sopenharmony_ci					      HW_LOCK_RESOURCE_DCBX_ADMIN_MIB);
10708c2ecf20Sopenharmony_ci		}
10718c2ecf20Sopenharmony_ci	}
10728c2ecf20Sopenharmony_ci}
10738c2ecf20Sopenharmony_cistatic void
10748c2ecf20Sopenharmony_cibnx2x_dcbx_print_cos_params(struct bnx2x *bp,
10758c2ecf20Sopenharmony_ci			    struct bnx2x_func_tx_start_params *pfc_fw_cfg)
10768c2ecf20Sopenharmony_ci{
10778c2ecf20Sopenharmony_ci	u8 pri = 0;
10788c2ecf20Sopenharmony_ci	u8 cos = 0;
10798c2ecf20Sopenharmony_ci
10808c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_DCB,
10818c2ecf20Sopenharmony_ci	   "pfc_fw_cfg->dcb_version %x\n", pfc_fw_cfg->dcb_version);
10828c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_DCB,
10838c2ecf20Sopenharmony_ci	   "pdev->params.dcbx_port_params.pfc.priority_non_pauseable_mask %x\n",
10848c2ecf20Sopenharmony_ci	   bp->dcbx_port_params.pfc.priority_non_pauseable_mask);
10858c2ecf20Sopenharmony_ci
10868c2ecf20Sopenharmony_ci	for (cos = 0 ; cos < bp->dcbx_port_params.ets.num_of_cos ; cos++) {
10878c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_DCB,
10888c2ecf20Sopenharmony_ci		   "pdev->params.dcbx_port_params.ets.cos_params[%d].pri_bitmask %x\n",
10898c2ecf20Sopenharmony_ci		   cos, bp->dcbx_port_params.ets.cos_params[cos].pri_bitmask);
10908c2ecf20Sopenharmony_ci
10918c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_DCB,
10928c2ecf20Sopenharmony_ci		   "pdev->params.dcbx_port_params.ets.cos_params[%d].bw_tbl %x\n",
10938c2ecf20Sopenharmony_ci		   cos, bp->dcbx_port_params.ets.cos_params[cos].bw_tbl);
10948c2ecf20Sopenharmony_ci
10958c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_DCB,
10968c2ecf20Sopenharmony_ci		   "pdev->params.dcbx_port_params.ets.cos_params[%d].strict %x\n",
10978c2ecf20Sopenharmony_ci		   cos, bp->dcbx_port_params.ets.cos_params[cos].strict);
10988c2ecf20Sopenharmony_ci
10998c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_DCB,
11008c2ecf20Sopenharmony_ci		   "pdev->params.dcbx_port_params.ets.cos_params[%d].pauseable %x\n",
11018c2ecf20Sopenharmony_ci		   cos, bp->dcbx_port_params.ets.cos_params[cos].pauseable);
11028c2ecf20Sopenharmony_ci	}
11038c2ecf20Sopenharmony_ci
11048c2ecf20Sopenharmony_ci	for (pri = 0; pri < LLFC_DRIVER_TRAFFIC_TYPE_MAX; pri++) {
11058c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_DCB,
11068c2ecf20Sopenharmony_ci		   "pfc_fw_cfg->traffic_type_to_priority_cos[%d].priority %x\n",
11078c2ecf20Sopenharmony_ci		   pri, pfc_fw_cfg->traffic_type_to_priority_cos[pri].priority);
11088c2ecf20Sopenharmony_ci
11098c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_DCB,
11108c2ecf20Sopenharmony_ci		   "pfc_fw_cfg->traffic_type_to_priority_cos[%d].cos %x\n",
11118c2ecf20Sopenharmony_ci		   pri, pfc_fw_cfg->traffic_type_to_priority_cos[pri].cos);
11128c2ecf20Sopenharmony_ci	}
11138c2ecf20Sopenharmony_ci}
11148c2ecf20Sopenharmony_ci
11158c2ecf20Sopenharmony_ci/* fills help_data according to pg_info */
11168c2ecf20Sopenharmony_cistatic void bnx2x_dcbx_get_num_pg_traf_type(struct bnx2x *bp,
11178c2ecf20Sopenharmony_ci					    u32 *pg_pri_orginal_spread,
11188c2ecf20Sopenharmony_ci					    struct pg_help_data *help_data)
11198c2ecf20Sopenharmony_ci{
11208c2ecf20Sopenharmony_ci	bool pg_found  = false;
11218c2ecf20Sopenharmony_ci	u32 i, traf_type, add_traf_type, add_pg;
11228c2ecf20Sopenharmony_ci	u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority;
11238c2ecf20Sopenharmony_ci	struct pg_entry_help_data *data = help_data->data; /*shortcut*/
11248c2ecf20Sopenharmony_ci
11258c2ecf20Sopenharmony_ci	/* Set to invalid */
11268c2ecf20Sopenharmony_ci	for (i = 0; i < LLFC_DRIVER_TRAFFIC_TYPE_MAX; i++)
11278c2ecf20Sopenharmony_ci		data[i].pg = DCBX_ILLEGAL_PG;
11288c2ecf20Sopenharmony_ci
11298c2ecf20Sopenharmony_ci	for (add_traf_type = 0;
11308c2ecf20Sopenharmony_ci	     add_traf_type < LLFC_DRIVER_TRAFFIC_TYPE_MAX; add_traf_type++) {
11318c2ecf20Sopenharmony_ci		pg_found = false;
11328c2ecf20Sopenharmony_ci		if (ttp[add_traf_type] < MAX_PFC_PRIORITIES) {
11338c2ecf20Sopenharmony_ci			add_pg = (u8)pg_pri_orginal_spread[ttp[add_traf_type]];
11348c2ecf20Sopenharmony_ci			for (traf_type = 0;
11358c2ecf20Sopenharmony_ci			     traf_type < LLFC_DRIVER_TRAFFIC_TYPE_MAX;
11368c2ecf20Sopenharmony_ci			     traf_type++) {
11378c2ecf20Sopenharmony_ci				if (data[traf_type].pg == add_pg) {
11388c2ecf20Sopenharmony_ci					if (!(data[traf_type].pg_priority &
11398c2ecf20Sopenharmony_ci					     (1 << ttp[add_traf_type])))
11408c2ecf20Sopenharmony_ci						data[traf_type].
11418c2ecf20Sopenharmony_ci							num_of_dif_pri++;
11428c2ecf20Sopenharmony_ci					data[traf_type].pg_priority |=
11438c2ecf20Sopenharmony_ci						(1 << ttp[add_traf_type]);
11448c2ecf20Sopenharmony_ci					pg_found = true;
11458c2ecf20Sopenharmony_ci					break;
11468c2ecf20Sopenharmony_ci				}
11478c2ecf20Sopenharmony_ci			}
11488c2ecf20Sopenharmony_ci			if (!pg_found) {
11498c2ecf20Sopenharmony_ci				data[help_data->num_of_pg].pg = add_pg;
11508c2ecf20Sopenharmony_ci				data[help_data->num_of_pg].pg_priority =
11518c2ecf20Sopenharmony_ci						(1 << ttp[add_traf_type]);
11528c2ecf20Sopenharmony_ci				data[help_data->num_of_pg].num_of_dif_pri = 1;
11538c2ecf20Sopenharmony_ci				help_data->num_of_pg++;
11548c2ecf20Sopenharmony_ci			}
11558c2ecf20Sopenharmony_ci		}
11568c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_DCB,
11578c2ecf20Sopenharmony_ci		   "add_traf_type %d pg_found %s num_of_pg %d\n",
11588c2ecf20Sopenharmony_ci		   add_traf_type, !pg_found ? "NO" : "YES",
11598c2ecf20Sopenharmony_ci		   help_data->num_of_pg);
11608c2ecf20Sopenharmony_ci	}
11618c2ecf20Sopenharmony_ci}
11628c2ecf20Sopenharmony_ci
11638c2ecf20Sopenharmony_cistatic void bnx2x_dcbx_ets_disabled_entry_data(struct bnx2x *bp,
11648c2ecf20Sopenharmony_ci					       struct cos_help_data *cos_data,
11658c2ecf20Sopenharmony_ci					       u32 pri_join_mask)
11668c2ecf20Sopenharmony_ci{
11678c2ecf20Sopenharmony_ci	/* Only one priority than only one COS */
11688c2ecf20Sopenharmony_ci	cos_data->data[0].pausable =
11698c2ecf20Sopenharmony_ci		IS_DCBX_PFC_PRI_ONLY_PAUSE(bp, pri_join_mask);
11708c2ecf20Sopenharmony_ci	cos_data->data[0].pri_join_mask = pri_join_mask;
11718c2ecf20Sopenharmony_ci	cos_data->data[0].cos_bw = 100;
11728c2ecf20Sopenharmony_ci	cos_data->num_of_cos = 1;
11738c2ecf20Sopenharmony_ci}
11748c2ecf20Sopenharmony_ci
11758c2ecf20Sopenharmony_cistatic inline void bnx2x_dcbx_add_to_cos_bw(struct bnx2x *bp,
11768c2ecf20Sopenharmony_ci					    struct cos_entry_help_data *data,
11778c2ecf20Sopenharmony_ci					    u8 pg_bw)
11788c2ecf20Sopenharmony_ci{
11798c2ecf20Sopenharmony_ci	if (data->cos_bw == DCBX_INVALID_COS_BW)
11808c2ecf20Sopenharmony_ci		data->cos_bw = pg_bw;
11818c2ecf20Sopenharmony_ci	else
11828c2ecf20Sopenharmony_ci		data->cos_bw += pg_bw;
11838c2ecf20Sopenharmony_ci}
11848c2ecf20Sopenharmony_ci
11858c2ecf20Sopenharmony_cistatic void bnx2x_dcbx_separate_pauseable_from_non(struct bnx2x *bp,
11868c2ecf20Sopenharmony_ci			struct cos_help_data *cos_data,
11878c2ecf20Sopenharmony_ci			u32 *pg_pri_orginal_spread,
11888c2ecf20Sopenharmony_ci			struct dcbx_ets_feature *ets)
11898c2ecf20Sopenharmony_ci{
11908c2ecf20Sopenharmony_ci	u32	pri_tested	= 0;
11918c2ecf20Sopenharmony_ci	u8	i		= 0;
11928c2ecf20Sopenharmony_ci	u8	entry		= 0;
11938c2ecf20Sopenharmony_ci	u8	pg_entry	= 0;
11948c2ecf20Sopenharmony_ci	u8	num_of_pri	= LLFC_DRIVER_TRAFFIC_TYPE_MAX;
11958c2ecf20Sopenharmony_ci
11968c2ecf20Sopenharmony_ci	cos_data->data[0].pausable = true;
11978c2ecf20Sopenharmony_ci	cos_data->data[1].pausable = false;
11988c2ecf20Sopenharmony_ci	cos_data->data[0].pri_join_mask = cos_data->data[1].pri_join_mask = 0;
11998c2ecf20Sopenharmony_ci
12008c2ecf20Sopenharmony_ci	for (i = 0 ; i < num_of_pri ; i++) {
12018c2ecf20Sopenharmony_ci		pri_tested = 1 << bp->dcbx_port_params.
12028c2ecf20Sopenharmony_ci					app.traffic_type_priority[i];
12038c2ecf20Sopenharmony_ci
12048c2ecf20Sopenharmony_ci		if (pri_tested & DCBX_PFC_PRI_NON_PAUSE_MASK(bp)) {
12058c2ecf20Sopenharmony_ci			cos_data->data[1].pri_join_mask |= pri_tested;
12068c2ecf20Sopenharmony_ci			entry = 1;
12078c2ecf20Sopenharmony_ci		} else {
12088c2ecf20Sopenharmony_ci			cos_data->data[0].pri_join_mask |= pri_tested;
12098c2ecf20Sopenharmony_ci			entry = 0;
12108c2ecf20Sopenharmony_ci		}
12118c2ecf20Sopenharmony_ci		pg_entry = (u8)pg_pri_orginal_spread[bp->dcbx_port_params.
12128c2ecf20Sopenharmony_ci						app.traffic_type_priority[i]];
12138c2ecf20Sopenharmony_ci		/* There can be only one strict pg */
12148c2ecf20Sopenharmony_ci		if (pg_entry < DCBX_MAX_NUM_PG_BW_ENTRIES)
12158c2ecf20Sopenharmony_ci			bnx2x_dcbx_add_to_cos_bw(bp, &cos_data->data[entry],
12168c2ecf20Sopenharmony_ci				DCBX_PG_BW_GET(ets->pg_bw_tbl, pg_entry));
12178c2ecf20Sopenharmony_ci		else
12188c2ecf20Sopenharmony_ci			/* If we join a group and one is strict
12198c2ecf20Sopenharmony_ci			 * than the bw rules
12208c2ecf20Sopenharmony_ci			 */
12218c2ecf20Sopenharmony_ci			cos_data->data[entry].strict =
12228c2ecf20Sopenharmony_ci						BNX2X_DCBX_STRICT_COS_HIGHEST;
12238c2ecf20Sopenharmony_ci	}
12248c2ecf20Sopenharmony_ci	if ((0 == cos_data->data[0].pri_join_mask) &&
12258c2ecf20Sopenharmony_ci	    (0 == cos_data->data[1].pri_join_mask))
12268c2ecf20Sopenharmony_ci		BNX2X_ERR("dcbx error: Both groups must have priorities\n");
12278c2ecf20Sopenharmony_ci}
12288c2ecf20Sopenharmony_ci
12298c2ecf20Sopenharmony_ci#ifndef POWER_OF_2
12308c2ecf20Sopenharmony_ci#define POWER_OF_2(x)	((0 != x) && (0 == (x & (x-1))))
12318c2ecf20Sopenharmony_ci#endif
12328c2ecf20Sopenharmony_ci
12338c2ecf20Sopenharmony_cistatic void bnx2x_dcbx_2cos_limit_cee_single_pg_to_cos_params(struct bnx2x *bp,
12348c2ecf20Sopenharmony_ci					      struct pg_help_data *pg_help_data,
12358c2ecf20Sopenharmony_ci					      struct cos_help_data *cos_data,
12368c2ecf20Sopenharmony_ci					      u32 pri_join_mask,
12378c2ecf20Sopenharmony_ci					      u8 num_of_dif_pri)
12388c2ecf20Sopenharmony_ci{
12398c2ecf20Sopenharmony_ci	u8 i = 0;
12408c2ecf20Sopenharmony_ci	u32 pri_tested = 0;
12418c2ecf20Sopenharmony_ci	u32 pri_mask_without_pri = 0;
12428c2ecf20Sopenharmony_ci	u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority;
12438c2ecf20Sopenharmony_ci	/*debug*/
12448c2ecf20Sopenharmony_ci	if (num_of_dif_pri == 1) {
12458c2ecf20Sopenharmony_ci		bnx2x_dcbx_ets_disabled_entry_data(bp, cos_data, pri_join_mask);
12468c2ecf20Sopenharmony_ci		return;
12478c2ecf20Sopenharmony_ci	}
12488c2ecf20Sopenharmony_ci	/* single priority group */
12498c2ecf20Sopenharmony_ci	if (pg_help_data->data[0].pg < DCBX_MAX_NUM_PG_BW_ENTRIES) {
12508c2ecf20Sopenharmony_ci		/* If there are both pauseable and non-pauseable priorities,
12518c2ecf20Sopenharmony_ci		 * the pauseable priorities go to the first queue and
12528c2ecf20Sopenharmony_ci		 * the non-pauseable priorities go to the second queue.
12538c2ecf20Sopenharmony_ci		 */
12548c2ecf20Sopenharmony_ci		if (IS_DCBX_PFC_PRI_MIX_PAUSE(bp, pri_join_mask)) {
12558c2ecf20Sopenharmony_ci			/* Pauseable */
12568c2ecf20Sopenharmony_ci			cos_data->data[0].pausable = true;
12578c2ecf20Sopenharmony_ci			/* Non pauseable.*/
12588c2ecf20Sopenharmony_ci			cos_data->data[1].pausable = false;
12598c2ecf20Sopenharmony_ci
12608c2ecf20Sopenharmony_ci			if (2 == num_of_dif_pri) {
12618c2ecf20Sopenharmony_ci				cos_data->data[0].cos_bw = 50;
12628c2ecf20Sopenharmony_ci				cos_data->data[1].cos_bw = 50;
12638c2ecf20Sopenharmony_ci			}
12648c2ecf20Sopenharmony_ci
12658c2ecf20Sopenharmony_ci			if (3 == num_of_dif_pri) {
12668c2ecf20Sopenharmony_ci				if (POWER_OF_2(DCBX_PFC_PRI_GET_PAUSE(bp,
12678c2ecf20Sopenharmony_ci							pri_join_mask))) {
12688c2ecf20Sopenharmony_ci					cos_data->data[0].cos_bw = 33;
12698c2ecf20Sopenharmony_ci					cos_data->data[1].cos_bw = 67;
12708c2ecf20Sopenharmony_ci				} else {
12718c2ecf20Sopenharmony_ci					cos_data->data[0].cos_bw = 67;
12728c2ecf20Sopenharmony_ci					cos_data->data[1].cos_bw = 33;
12738c2ecf20Sopenharmony_ci				}
12748c2ecf20Sopenharmony_ci			}
12758c2ecf20Sopenharmony_ci
12768c2ecf20Sopenharmony_ci		} else if (IS_DCBX_PFC_PRI_ONLY_PAUSE(bp, pri_join_mask)) {
12778c2ecf20Sopenharmony_ci			/* If there are only pauseable priorities,
12788c2ecf20Sopenharmony_ci			 * then one/two priorities go to the first queue
12798c2ecf20Sopenharmony_ci			 * and one priority goes to the second queue.
12808c2ecf20Sopenharmony_ci			 */
12818c2ecf20Sopenharmony_ci			if (2 == num_of_dif_pri) {
12828c2ecf20Sopenharmony_ci				cos_data->data[0].cos_bw = 50;
12838c2ecf20Sopenharmony_ci				cos_data->data[1].cos_bw = 50;
12848c2ecf20Sopenharmony_ci			} else {
12858c2ecf20Sopenharmony_ci				cos_data->data[0].cos_bw = 67;
12868c2ecf20Sopenharmony_ci				cos_data->data[1].cos_bw = 33;
12878c2ecf20Sopenharmony_ci			}
12888c2ecf20Sopenharmony_ci			cos_data->data[1].pausable = true;
12898c2ecf20Sopenharmony_ci			cos_data->data[0].pausable = true;
12908c2ecf20Sopenharmony_ci			/* All priorities except FCOE */
12918c2ecf20Sopenharmony_ci			cos_data->data[0].pri_join_mask = (pri_join_mask &
12928c2ecf20Sopenharmony_ci				((u8)~(1 << ttp[LLFC_TRAFFIC_TYPE_FCOE])));
12938c2ecf20Sopenharmony_ci			/* Only FCOE priority.*/
12948c2ecf20Sopenharmony_ci			cos_data->data[1].pri_join_mask =
12958c2ecf20Sopenharmony_ci				(1 << ttp[LLFC_TRAFFIC_TYPE_FCOE]);
12968c2ecf20Sopenharmony_ci		} else
12978c2ecf20Sopenharmony_ci			/* If there are only non-pauseable priorities,
12988c2ecf20Sopenharmony_ci			 * they will all go to the same queue.
12998c2ecf20Sopenharmony_ci			 */
13008c2ecf20Sopenharmony_ci			bnx2x_dcbx_ets_disabled_entry_data(bp,
13018c2ecf20Sopenharmony_ci						cos_data, pri_join_mask);
13028c2ecf20Sopenharmony_ci	} else {
13038c2ecf20Sopenharmony_ci		/* priority group which is not BW limited (PG#15):*/
13048c2ecf20Sopenharmony_ci		if (IS_DCBX_PFC_PRI_MIX_PAUSE(bp, pri_join_mask)) {
13058c2ecf20Sopenharmony_ci			/* If there are both pauseable and non-pauseable
13068c2ecf20Sopenharmony_ci			 * priorities, the pauseable priorities go to the first
13078c2ecf20Sopenharmony_ci			 * queue and the non-pauseable priorities
13088c2ecf20Sopenharmony_ci			 * go to the second queue.
13098c2ecf20Sopenharmony_ci			 */
13108c2ecf20Sopenharmony_ci			if (DCBX_PFC_PRI_GET_PAUSE(bp, pri_join_mask) >
13118c2ecf20Sopenharmony_ci			    DCBX_PFC_PRI_GET_NON_PAUSE(bp, pri_join_mask)) {
13128c2ecf20Sopenharmony_ci				cos_data->data[0].strict =
13138c2ecf20Sopenharmony_ci					BNX2X_DCBX_STRICT_COS_HIGHEST;
13148c2ecf20Sopenharmony_ci				cos_data->data[1].strict =
13158c2ecf20Sopenharmony_ci					BNX2X_DCBX_STRICT_COS_NEXT_LOWER_PRI(
13168c2ecf20Sopenharmony_ci						BNX2X_DCBX_STRICT_COS_HIGHEST);
13178c2ecf20Sopenharmony_ci			} else {
13188c2ecf20Sopenharmony_ci				cos_data->data[0].strict =
13198c2ecf20Sopenharmony_ci					BNX2X_DCBX_STRICT_COS_NEXT_LOWER_PRI(
13208c2ecf20Sopenharmony_ci						BNX2X_DCBX_STRICT_COS_HIGHEST);
13218c2ecf20Sopenharmony_ci				cos_data->data[1].strict =
13228c2ecf20Sopenharmony_ci					BNX2X_DCBX_STRICT_COS_HIGHEST;
13238c2ecf20Sopenharmony_ci			}
13248c2ecf20Sopenharmony_ci			/* Pauseable */
13258c2ecf20Sopenharmony_ci			cos_data->data[0].pausable = true;
13268c2ecf20Sopenharmony_ci			/* Non pause-able.*/
13278c2ecf20Sopenharmony_ci			cos_data->data[1].pausable = false;
13288c2ecf20Sopenharmony_ci		} else {
13298c2ecf20Sopenharmony_ci			/* If there are only pauseable priorities or
13308c2ecf20Sopenharmony_ci			 * only non-pauseable,* the lower priorities go
13318c2ecf20Sopenharmony_ci			 * to the first queue and the higher priorities go
13328c2ecf20Sopenharmony_ci			 * to the second queue.
13338c2ecf20Sopenharmony_ci			 */
13348c2ecf20Sopenharmony_ci			cos_data->data[0].pausable =
13358c2ecf20Sopenharmony_ci				cos_data->data[1].pausable =
13368c2ecf20Sopenharmony_ci				IS_DCBX_PFC_PRI_ONLY_PAUSE(bp, pri_join_mask);
13378c2ecf20Sopenharmony_ci
13388c2ecf20Sopenharmony_ci			for (i = 0 ; i < LLFC_DRIVER_TRAFFIC_TYPE_MAX; i++) {
13398c2ecf20Sopenharmony_ci				pri_tested = 1 << bp->dcbx_port_params.
13408c2ecf20Sopenharmony_ci					app.traffic_type_priority[i];
13418c2ecf20Sopenharmony_ci				/* Remove priority tested */
13428c2ecf20Sopenharmony_ci				pri_mask_without_pri =
13438c2ecf20Sopenharmony_ci					(pri_join_mask & ((u8)(~pri_tested)));
13448c2ecf20Sopenharmony_ci				if (pri_mask_without_pri < pri_tested)
13458c2ecf20Sopenharmony_ci					break;
13468c2ecf20Sopenharmony_ci			}
13478c2ecf20Sopenharmony_ci
13488c2ecf20Sopenharmony_ci			if (i == LLFC_DRIVER_TRAFFIC_TYPE_MAX)
13498c2ecf20Sopenharmony_ci				BNX2X_ERR("Invalid value for pri_join_mask - could not find a priority\n");
13508c2ecf20Sopenharmony_ci
13518c2ecf20Sopenharmony_ci			cos_data->data[0].pri_join_mask = pri_mask_without_pri;
13528c2ecf20Sopenharmony_ci			cos_data->data[1].pri_join_mask = pri_tested;
13538c2ecf20Sopenharmony_ci			/* Both queues are strict priority,
13548c2ecf20Sopenharmony_ci			 * and that with the highest priority
13558c2ecf20Sopenharmony_ci			 * gets the highest strict priority in the arbiter.
13568c2ecf20Sopenharmony_ci			 */
13578c2ecf20Sopenharmony_ci			cos_data->data[0].strict =
13588c2ecf20Sopenharmony_ci					BNX2X_DCBX_STRICT_COS_NEXT_LOWER_PRI(
13598c2ecf20Sopenharmony_ci						BNX2X_DCBX_STRICT_COS_HIGHEST);
13608c2ecf20Sopenharmony_ci			cos_data->data[1].strict =
13618c2ecf20Sopenharmony_ci					BNX2X_DCBX_STRICT_COS_HIGHEST;
13628c2ecf20Sopenharmony_ci		}
13638c2ecf20Sopenharmony_ci	}
13648c2ecf20Sopenharmony_ci}
13658c2ecf20Sopenharmony_ci
13668c2ecf20Sopenharmony_cistatic void bnx2x_dcbx_2cos_limit_cee_two_pg_to_cos_params(
13678c2ecf20Sopenharmony_ci			    struct bnx2x		*bp,
13688c2ecf20Sopenharmony_ci			    struct  pg_help_data	*pg_help_data,
13698c2ecf20Sopenharmony_ci			    struct dcbx_ets_feature	*ets,
13708c2ecf20Sopenharmony_ci			    struct cos_help_data	*cos_data,
13718c2ecf20Sopenharmony_ci			    u32			*pg_pri_orginal_spread,
13728c2ecf20Sopenharmony_ci			    u32				pri_join_mask,
13738c2ecf20Sopenharmony_ci			    u8				num_of_dif_pri)
13748c2ecf20Sopenharmony_ci{
13758c2ecf20Sopenharmony_ci	u8 i = 0;
13768c2ecf20Sopenharmony_ci	u8 pg[DCBX_COS_MAX_NUM_E2] = { 0 };
13778c2ecf20Sopenharmony_ci
13788c2ecf20Sopenharmony_ci	/* If there are both pauseable and non-pauseable priorities,
13798c2ecf20Sopenharmony_ci	 * the pauseable priorities go to the first queue and
13808c2ecf20Sopenharmony_ci	 * the non-pauseable priorities go to the second queue.
13818c2ecf20Sopenharmony_ci	 */
13828c2ecf20Sopenharmony_ci	if (IS_DCBX_PFC_PRI_MIX_PAUSE(bp, pri_join_mask)) {
13838c2ecf20Sopenharmony_ci		if (IS_DCBX_PFC_PRI_MIX_PAUSE(bp,
13848c2ecf20Sopenharmony_ci					 pg_help_data->data[0].pg_priority) ||
13858c2ecf20Sopenharmony_ci		    IS_DCBX_PFC_PRI_MIX_PAUSE(bp,
13868c2ecf20Sopenharmony_ci					 pg_help_data->data[1].pg_priority)) {
13878c2ecf20Sopenharmony_ci			/* If one PG contains both pauseable and
13888c2ecf20Sopenharmony_ci			 * non-pauseable priorities then ETS is disabled.
13898c2ecf20Sopenharmony_ci			 */
13908c2ecf20Sopenharmony_ci			bnx2x_dcbx_separate_pauseable_from_non(bp, cos_data,
13918c2ecf20Sopenharmony_ci					pg_pri_orginal_spread, ets);
13928c2ecf20Sopenharmony_ci			bp->dcbx_port_params.ets.enabled = false;
13938c2ecf20Sopenharmony_ci			return;
13948c2ecf20Sopenharmony_ci		}
13958c2ecf20Sopenharmony_ci
13968c2ecf20Sopenharmony_ci		/* Pauseable */
13978c2ecf20Sopenharmony_ci		cos_data->data[0].pausable = true;
13988c2ecf20Sopenharmony_ci		/* Non pauseable. */
13998c2ecf20Sopenharmony_ci		cos_data->data[1].pausable = false;
14008c2ecf20Sopenharmony_ci		if (IS_DCBX_PFC_PRI_ONLY_PAUSE(bp,
14018c2ecf20Sopenharmony_ci				pg_help_data->data[0].pg_priority)) {
14028c2ecf20Sopenharmony_ci			/* 0 is pauseable */
14038c2ecf20Sopenharmony_ci			cos_data->data[0].pri_join_mask =
14048c2ecf20Sopenharmony_ci				pg_help_data->data[0].pg_priority;
14058c2ecf20Sopenharmony_ci			pg[0] = pg_help_data->data[0].pg;
14068c2ecf20Sopenharmony_ci			cos_data->data[1].pri_join_mask =
14078c2ecf20Sopenharmony_ci				pg_help_data->data[1].pg_priority;
14088c2ecf20Sopenharmony_ci			pg[1] = pg_help_data->data[1].pg;
14098c2ecf20Sopenharmony_ci		} else {/* 1 is pauseable */
14108c2ecf20Sopenharmony_ci			cos_data->data[0].pri_join_mask =
14118c2ecf20Sopenharmony_ci				pg_help_data->data[1].pg_priority;
14128c2ecf20Sopenharmony_ci			pg[0] = pg_help_data->data[1].pg;
14138c2ecf20Sopenharmony_ci			cos_data->data[1].pri_join_mask =
14148c2ecf20Sopenharmony_ci				pg_help_data->data[0].pg_priority;
14158c2ecf20Sopenharmony_ci			pg[1] = pg_help_data->data[0].pg;
14168c2ecf20Sopenharmony_ci		}
14178c2ecf20Sopenharmony_ci	} else {
14188c2ecf20Sopenharmony_ci		/* If there are only pauseable priorities or
14198c2ecf20Sopenharmony_ci		 * only non-pauseable, each PG goes to a queue.
14208c2ecf20Sopenharmony_ci		 */
14218c2ecf20Sopenharmony_ci		cos_data->data[0].pausable = cos_data->data[1].pausable =
14228c2ecf20Sopenharmony_ci			IS_DCBX_PFC_PRI_ONLY_PAUSE(bp, pri_join_mask);
14238c2ecf20Sopenharmony_ci		cos_data->data[0].pri_join_mask =
14248c2ecf20Sopenharmony_ci			pg_help_data->data[0].pg_priority;
14258c2ecf20Sopenharmony_ci		pg[0] = pg_help_data->data[0].pg;
14268c2ecf20Sopenharmony_ci		cos_data->data[1].pri_join_mask =
14278c2ecf20Sopenharmony_ci			pg_help_data->data[1].pg_priority;
14288c2ecf20Sopenharmony_ci		pg[1] = pg_help_data->data[1].pg;
14298c2ecf20Sopenharmony_ci	}
14308c2ecf20Sopenharmony_ci
14318c2ecf20Sopenharmony_ci	/* There can be only one strict pg */
14328c2ecf20Sopenharmony_ci	for (i = 0 ; i < ARRAY_SIZE(pg); i++) {
14338c2ecf20Sopenharmony_ci		if (pg[i] < DCBX_MAX_NUM_PG_BW_ENTRIES)
14348c2ecf20Sopenharmony_ci			cos_data->data[i].cos_bw =
14358c2ecf20Sopenharmony_ci				DCBX_PG_BW_GET(ets->pg_bw_tbl, pg[i]);
14368c2ecf20Sopenharmony_ci		else
14378c2ecf20Sopenharmony_ci			cos_data->data[i].strict =
14388c2ecf20Sopenharmony_ci						BNX2X_DCBX_STRICT_COS_HIGHEST;
14398c2ecf20Sopenharmony_ci	}
14408c2ecf20Sopenharmony_ci}
14418c2ecf20Sopenharmony_ci
14428c2ecf20Sopenharmony_cistatic int bnx2x_dcbx_join_pgs(
14438c2ecf20Sopenharmony_ci			      struct bnx2x            *bp,
14448c2ecf20Sopenharmony_ci			      struct dcbx_ets_feature *ets,
14458c2ecf20Sopenharmony_ci			      struct pg_help_data     *pg_help_data,
14468c2ecf20Sopenharmony_ci			      u8                      required_num_of_pg)
14478c2ecf20Sopenharmony_ci{
14488c2ecf20Sopenharmony_ci	u8 entry_joined    = pg_help_data->num_of_pg - 1;
14498c2ecf20Sopenharmony_ci	u8 entry_removed   = entry_joined + 1;
14508c2ecf20Sopenharmony_ci	u8 pg_joined       = 0;
14518c2ecf20Sopenharmony_ci
14528c2ecf20Sopenharmony_ci	if (required_num_of_pg == 0 || ARRAY_SIZE(pg_help_data->data)
14538c2ecf20Sopenharmony_ci						<= pg_help_data->num_of_pg) {
14548c2ecf20Sopenharmony_ci
14558c2ecf20Sopenharmony_ci		BNX2X_ERR("required_num_of_pg can't be zero\n");
14568c2ecf20Sopenharmony_ci		return -EINVAL;
14578c2ecf20Sopenharmony_ci	}
14588c2ecf20Sopenharmony_ci
14598c2ecf20Sopenharmony_ci	while (required_num_of_pg < pg_help_data->num_of_pg) {
14608c2ecf20Sopenharmony_ci		entry_joined = pg_help_data->num_of_pg - 2;
14618c2ecf20Sopenharmony_ci		entry_removed = entry_joined + 1;
14628c2ecf20Sopenharmony_ci		/* protect index */
14638c2ecf20Sopenharmony_ci		entry_removed %= ARRAY_SIZE(pg_help_data->data);
14648c2ecf20Sopenharmony_ci
14658c2ecf20Sopenharmony_ci		pg_help_data->data[entry_joined].pg_priority |=
14668c2ecf20Sopenharmony_ci			pg_help_data->data[entry_removed].pg_priority;
14678c2ecf20Sopenharmony_ci
14688c2ecf20Sopenharmony_ci		pg_help_data->data[entry_joined].num_of_dif_pri +=
14698c2ecf20Sopenharmony_ci			pg_help_data->data[entry_removed].num_of_dif_pri;
14708c2ecf20Sopenharmony_ci
14718c2ecf20Sopenharmony_ci		if (pg_help_data->data[entry_joined].pg == DCBX_STRICT_PRI_PG ||
14728c2ecf20Sopenharmony_ci		    pg_help_data->data[entry_removed].pg == DCBX_STRICT_PRI_PG)
14738c2ecf20Sopenharmony_ci			/* Entries joined strict priority rules */
14748c2ecf20Sopenharmony_ci			pg_help_data->data[entry_joined].pg =
14758c2ecf20Sopenharmony_ci							DCBX_STRICT_PRI_PG;
14768c2ecf20Sopenharmony_ci		else {
14778c2ecf20Sopenharmony_ci			/* Entries can be joined join BW */
14788c2ecf20Sopenharmony_ci			pg_joined = DCBX_PG_BW_GET(ets->pg_bw_tbl,
14798c2ecf20Sopenharmony_ci					pg_help_data->data[entry_joined].pg) +
14808c2ecf20Sopenharmony_ci				    DCBX_PG_BW_GET(ets->pg_bw_tbl,
14818c2ecf20Sopenharmony_ci					pg_help_data->data[entry_removed].pg);
14828c2ecf20Sopenharmony_ci
14838c2ecf20Sopenharmony_ci			DCBX_PG_BW_SET(ets->pg_bw_tbl,
14848c2ecf20Sopenharmony_ci				pg_help_data->data[entry_joined].pg, pg_joined);
14858c2ecf20Sopenharmony_ci		}
14868c2ecf20Sopenharmony_ci		/* Joined the entries */
14878c2ecf20Sopenharmony_ci		pg_help_data->num_of_pg--;
14888c2ecf20Sopenharmony_ci	}
14898c2ecf20Sopenharmony_ci
14908c2ecf20Sopenharmony_ci	return 0;
14918c2ecf20Sopenharmony_ci}
14928c2ecf20Sopenharmony_ci
14938c2ecf20Sopenharmony_cistatic void bnx2x_dcbx_2cos_limit_cee_three_pg_to_cos_params(
14948c2ecf20Sopenharmony_ci			      struct bnx2x		*bp,
14958c2ecf20Sopenharmony_ci			      struct pg_help_data	*pg_help_data,
14968c2ecf20Sopenharmony_ci			      struct dcbx_ets_feature	*ets,
14978c2ecf20Sopenharmony_ci			      struct cos_help_data	*cos_data,
14988c2ecf20Sopenharmony_ci			      u32			*pg_pri_orginal_spread,
14998c2ecf20Sopenharmony_ci			      u32			pri_join_mask,
15008c2ecf20Sopenharmony_ci			      u8			num_of_dif_pri)
15018c2ecf20Sopenharmony_ci{
15028c2ecf20Sopenharmony_ci	u8 i = 0;
15038c2ecf20Sopenharmony_ci	u32 pri_tested = 0;
15048c2ecf20Sopenharmony_ci	u8 entry = 0;
15058c2ecf20Sopenharmony_ci	u8 pg_entry = 0;
15068c2ecf20Sopenharmony_ci	bool b_found_strict = false;
15078c2ecf20Sopenharmony_ci	u8 num_of_pri = LLFC_DRIVER_TRAFFIC_TYPE_MAX;
15088c2ecf20Sopenharmony_ci
15098c2ecf20Sopenharmony_ci	cos_data->data[0].pri_join_mask = cos_data->data[1].pri_join_mask = 0;
15108c2ecf20Sopenharmony_ci	/* If there are both pauseable and non-pauseable priorities,
15118c2ecf20Sopenharmony_ci	 * the pauseable priorities go to the first queue and the
15128c2ecf20Sopenharmony_ci	 * non-pauseable priorities go to the second queue.
15138c2ecf20Sopenharmony_ci	 */
15148c2ecf20Sopenharmony_ci	if (IS_DCBX_PFC_PRI_MIX_PAUSE(bp, pri_join_mask))
15158c2ecf20Sopenharmony_ci		bnx2x_dcbx_separate_pauseable_from_non(bp,
15168c2ecf20Sopenharmony_ci				cos_data, pg_pri_orginal_spread, ets);
15178c2ecf20Sopenharmony_ci	else {
15188c2ecf20Sopenharmony_ci		/* If two BW-limited PG-s were combined to one queue,
15198c2ecf20Sopenharmony_ci		 * the BW is their sum.
15208c2ecf20Sopenharmony_ci		 *
15218c2ecf20Sopenharmony_ci		 * If there are only pauseable priorities or only non-pauseable,
15228c2ecf20Sopenharmony_ci		 * and there are both BW-limited and non-BW-limited PG-s,
15238c2ecf20Sopenharmony_ci		 * the BW-limited PG/s go to one queue and the non-BW-limited
15248c2ecf20Sopenharmony_ci		 * PG/s go to the second queue.
15258c2ecf20Sopenharmony_ci		 *
15268c2ecf20Sopenharmony_ci		 * If there are only pauseable priorities or only non-pauseable
15278c2ecf20Sopenharmony_ci		 * and all are BW limited, then	two priorities go to the first
15288c2ecf20Sopenharmony_ci		 * queue and one priority goes to the second queue.
15298c2ecf20Sopenharmony_ci		 *
15308c2ecf20Sopenharmony_ci		 * We will join this two cases:
15318c2ecf20Sopenharmony_ci		 * if one is BW limited it will go to the second queue
15328c2ecf20Sopenharmony_ci		 * otherwise the last priority will get it
15338c2ecf20Sopenharmony_ci		 */
15348c2ecf20Sopenharmony_ci
15358c2ecf20Sopenharmony_ci		cos_data->data[0].pausable = cos_data->data[1].pausable =
15368c2ecf20Sopenharmony_ci			IS_DCBX_PFC_PRI_ONLY_PAUSE(bp, pri_join_mask);
15378c2ecf20Sopenharmony_ci
15388c2ecf20Sopenharmony_ci		for (i = 0 ; i < num_of_pri; i++) {
15398c2ecf20Sopenharmony_ci			pri_tested = 1 << bp->dcbx_port_params.
15408c2ecf20Sopenharmony_ci				app.traffic_type_priority[i];
15418c2ecf20Sopenharmony_ci			pg_entry = (u8)pg_pri_orginal_spread[bp->
15428c2ecf20Sopenharmony_ci				dcbx_port_params.app.traffic_type_priority[i]];
15438c2ecf20Sopenharmony_ci
15448c2ecf20Sopenharmony_ci			if (pg_entry < DCBX_MAX_NUM_PG_BW_ENTRIES) {
15458c2ecf20Sopenharmony_ci				entry = 0;
15468c2ecf20Sopenharmony_ci
15478c2ecf20Sopenharmony_ci				if (i == (num_of_pri-1) && !b_found_strict)
15488c2ecf20Sopenharmony_ci					/* last entry will be handled separately
15498c2ecf20Sopenharmony_ci					 * If no priority is strict than last
15508c2ecf20Sopenharmony_ci					 * entry goes to last queue.
15518c2ecf20Sopenharmony_ci					 */
15528c2ecf20Sopenharmony_ci					entry = 1;
15538c2ecf20Sopenharmony_ci				cos_data->data[entry].pri_join_mask |=
15548c2ecf20Sopenharmony_ci								pri_tested;
15558c2ecf20Sopenharmony_ci				bnx2x_dcbx_add_to_cos_bw(bp,
15568c2ecf20Sopenharmony_ci					&cos_data->data[entry],
15578c2ecf20Sopenharmony_ci					DCBX_PG_BW_GET(ets->pg_bw_tbl,
15588c2ecf20Sopenharmony_ci						       pg_entry));
15598c2ecf20Sopenharmony_ci			} else {
15608c2ecf20Sopenharmony_ci				b_found_strict = true;
15618c2ecf20Sopenharmony_ci				cos_data->data[1].pri_join_mask |= pri_tested;
15628c2ecf20Sopenharmony_ci				/* If we join a group and one is strict
15638c2ecf20Sopenharmony_ci				 * than the bw rules
15648c2ecf20Sopenharmony_ci				 */
15658c2ecf20Sopenharmony_ci				cos_data->data[1].strict =
15668c2ecf20Sopenharmony_ci					BNX2X_DCBX_STRICT_COS_HIGHEST;
15678c2ecf20Sopenharmony_ci			}
15688c2ecf20Sopenharmony_ci		}
15698c2ecf20Sopenharmony_ci	}
15708c2ecf20Sopenharmony_ci}
15718c2ecf20Sopenharmony_ci
15728c2ecf20Sopenharmony_cistatic void bnx2x_dcbx_2cos_limit_cee_fill_cos_params(struct bnx2x *bp,
15738c2ecf20Sopenharmony_ci				       struct pg_help_data *help_data,
15748c2ecf20Sopenharmony_ci				       struct dcbx_ets_feature *ets,
15758c2ecf20Sopenharmony_ci				       struct cos_help_data *cos_data,
15768c2ecf20Sopenharmony_ci				       u32 *pg_pri_orginal_spread,
15778c2ecf20Sopenharmony_ci				       u32 pri_join_mask,
15788c2ecf20Sopenharmony_ci				       u8 num_of_dif_pri)
15798c2ecf20Sopenharmony_ci{
15808c2ecf20Sopenharmony_ci	/* default E2 settings */
15818c2ecf20Sopenharmony_ci	cos_data->num_of_cos = DCBX_COS_MAX_NUM_E2;
15828c2ecf20Sopenharmony_ci
15838c2ecf20Sopenharmony_ci	switch (help_data->num_of_pg) {
15848c2ecf20Sopenharmony_ci	case 1:
15858c2ecf20Sopenharmony_ci		bnx2x_dcbx_2cos_limit_cee_single_pg_to_cos_params(
15868c2ecf20Sopenharmony_ci					       bp,
15878c2ecf20Sopenharmony_ci					       help_data,
15888c2ecf20Sopenharmony_ci					       cos_data,
15898c2ecf20Sopenharmony_ci					       pri_join_mask,
15908c2ecf20Sopenharmony_ci					       num_of_dif_pri);
15918c2ecf20Sopenharmony_ci		break;
15928c2ecf20Sopenharmony_ci	case 2:
15938c2ecf20Sopenharmony_ci		bnx2x_dcbx_2cos_limit_cee_two_pg_to_cos_params(
15948c2ecf20Sopenharmony_ci					    bp,
15958c2ecf20Sopenharmony_ci					    help_data,
15968c2ecf20Sopenharmony_ci					    ets,
15978c2ecf20Sopenharmony_ci					    cos_data,
15988c2ecf20Sopenharmony_ci					    pg_pri_orginal_spread,
15998c2ecf20Sopenharmony_ci					    pri_join_mask,
16008c2ecf20Sopenharmony_ci					    num_of_dif_pri);
16018c2ecf20Sopenharmony_ci		break;
16028c2ecf20Sopenharmony_ci
16038c2ecf20Sopenharmony_ci	case 3:
16048c2ecf20Sopenharmony_ci		bnx2x_dcbx_2cos_limit_cee_three_pg_to_cos_params(
16058c2ecf20Sopenharmony_ci					      bp,
16068c2ecf20Sopenharmony_ci					      help_data,
16078c2ecf20Sopenharmony_ci					      ets,
16088c2ecf20Sopenharmony_ci					      cos_data,
16098c2ecf20Sopenharmony_ci					      pg_pri_orginal_spread,
16108c2ecf20Sopenharmony_ci					      pri_join_mask,
16118c2ecf20Sopenharmony_ci					      num_of_dif_pri);
16128c2ecf20Sopenharmony_ci		break;
16138c2ecf20Sopenharmony_ci	default:
16148c2ecf20Sopenharmony_ci		BNX2X_ERR("Wrong pg_help_data.num_of_pg\n");
16158c2ecf20Sopenharmony_ci		bnx2x_dcbx_ets_disabled_entry_data(bp,
16168c2ecf20Sopenharmony_ci						   cos_data, pri_join_mask);
16178c2ecf20Sopenharmony_ci	}
16188c2ecf20Sopenharmony_ci}
16198c2ecf20Sopenharmony_ci
16208c2ecf20Sopenharmony_cistatic int bnx2x_dcbx_spread_strict_pri(struct bnx2x *bp,
16218c2ecf20Sopenharmony_ci					struct cos_help_data *cos_data,
16228c2ecf20Sopenharmony_ci					u8 entry,
16238c2ecf20Sopenharmony_ci					u8 num_spread_of_entries,
16248c2ecf20Sopenharmony_ci					u8 strict_app_pris)
16258c2ecf20Sopenharmony_ci{
16268c2ecf20Sopenharmony_ci	u8 strict_pri = BNX2X_DCBX_STRICT_COS_HIGHEST;
16278c2ecf20Sopenharmony_ci	u8 num_of_app_pri = MAX_PFC_PRIORITIES;
16288c2ecf20Sopenharmony_ci	u8 app_pri_bit = 0;
16298c2ecf20Sopenharmony_ci
16308c2ecf20Sopenharmony_ci	while (num_spread_of_entries && num_of_app_pri > 0) {
16318c2ecf20Sopenharmony_ci		app_pri_bit = 1 << (num_of_app_pri - 1);
16328c2ecf20Sopenharmony_ci		if (app_pri_bit & strict_app_pris) {
16338c2ecf20Sopenharmony_ci			struct cos_entry_help_data *data = &cos_data->
16348c2ecf20Sopenharmony_ci								data[entry];
16358c2ecf20Sopenharmony_ci			num_spread_of_entries--;
16368c2ecf20Sopenharmony_ci			if (num_spread_of_entries == 0) {
16378c2ecf20Sopenharmony_ci				/* last entry needed put all the entries left */
16388c2ecf20Sopenharmony_ci				data->cos_bw = DCBX_INVALID_COS_BW;
16398c2ecf20Sopenharmony_ci				data->strict = strict_pri;
16408c2ecf20Sopenharmony_ci				data->pri_join_mask = strict_app_pris;
16418c2ecf20Sopenharmony_ci				data->pausable = DCBX_IS_PFC_PRI_SOME_PAUSE(bp,
16428c2ecf20Sopenharmony_ci							data->pri_join_mask);
16438c2ecf20Sopenharmony_ci			} else {
16448c2ecf20Sopenharmony_ci				strict_app_pris &= ~app_pri_bit;
16458c2ecf20Sopenharmony_ci
16468c2ecf20Sopenharmony_ci				data->cos_bw = DCBX_INVALID_COS_BW;
16478c2ecf20Sopenharmony_ci				data->strict = strict_pri;
16488c2ecf20Sopenharmony_ci				data->pri_join_mask = app_pri_bit;
16498c2ecf20Sopenharmony_ci				data->pausable = DCBX_IS_PFC_PRI_SOME_PAUSE(bp,
16508c2ecf20Sopenharmony_ci							data->pri_join_mask);
16518c2ecf20Sopenharmony_ci			}
16528c2ecf20Sopenharmony_ci
16538c2ecf20Sopenharmony_ci			strict_pri =
16548c2ecf20Sopenharmony_ci			    BNX2X_DCBX_STRICT_COS_NEXT_LOWER_PRI(strict_pri);
16558c2ecf20Sopenharmony_ci			entry++;
16568c2ecf20Sopenharmony_ci		}
16578c2ecf20Sopenharmony_ci
16588c2ecf20Sopenharmony_ci		num_of_app_pri--;
16598c2ecf20Sopenharmony_ci	}
16608c2ecf20Sopenharmony_ci
16618c2ecf20Sopenharmony_ci	if (num_spread_of_entries) {
16628c2ecf20Sopenharmony_ci		BNX2X_ERR("Didn't succeed to spread strict priorities\n");
16638c2ecf20Sopenharmony_ci		return -EINVAL;
16648c2ecf20Sopenharmony_ci	}
16658c2ecf20Sopenharmony_ci
16668c2ecf20Sopenharmony_ci	return 0;
16678c2ecf20Sopenharmony_ci}
16688c2ecf20Sopenharmony_ci
16698c2ecf20Sopenharmony_cistatic u8 bnx2x_dcbx_cee_fill_strict_pri(struct bnx2x *bp,
16708c2ecf20Sopenharmony_ci					 struct cos_help_data *cos_data,
16718c2ecf20Sopenharmony_ci					 u8 entry,
16728c2ecf20Sopenharmony_ci					 u8 num_spread_of_entries,
16738c2ecf20Sopenharmony_ci					 u8 strict_app_pris)
16748c2ecf20Sopenharmony_ci{
16758c2ecf20Sopenharmony_ci	if (bnx2x_dcbx_spread_strict_pri(bp, cos_data, entry,
16768c2ecf20Sopenharmony_ci					 num_spread_of_entries,
16778c2ecf20Sopenharmony_ci					 strict_app_pris)) {
16788c2ecf20Sopenharmony_ci		struct cos_entry_help_data *data = &cos_data->
16798c2ecf20Sopenharmony_ci						    data[entry];
16808c2ecf20Sopenharmony_ci		/* Fill BW entry */
16818c2ecf20Sopenharmony_ci		data->cos_bw = DCBX_INVALID_COS_BW;
16828c2ecf20Sopenharmony_ci		data->strict = BNX2X_DCBX_STRICT_COS_HIGHEST;
16838c2ecf20Sopenharmony_ci		data->pri_join_mask = strict_app_pris;
16848c2ecf20Sopenharmony_ci		data->pausable = DCBX_IS_PFC_PRI_SOME_PAUSE(bp,
16858c2ecf20Sopenharmony_ci				 data->pri_join_mask);
16868c2ecf20Sopenharmony_ci		return 1;
16878c2ecf20Sopenharmony_ci	}
16888c2ecf20Sopenharmony_ci
16898c2ecf20Sopenharmony_ci	return num_spread_of_entries;
16908c2ecf20Sopenharmony_ci}
16918c2ecf20Sopenharmony_ci
16928c2ecf20Sopenharmony_cistatic void bnx2x_dcbx_cee_fill_cos_params(struct bnx2x *bp,
16938c2ecf20Sopenharmony_ci					   struct pg_help_data *help_data,
16948c2ecf20Sopenharmony_ci					   struct dcbx_ets_feature *ets,
16958c2ecf20Sopenharmony_ci					   struct cos_help_data *cos_data,
16968c2ecf20Sopenharmony_ci					   u32 pri_join_mask)
16978c2ecf20Sopenharmony_ci
16988c2ecf20Sopenharmony_ci{
16998c2ecf20Sopenharmony_ci	u8 need_num_of_entries = 0;
17008c2ecf20Sopenharmony_ci	u8 i = 0;
17018c2ecf20Sopenharmony_ci	u8 entry = 0;
17028c2ecf20Sopenharmony_ci
17038c2ecf20Sopenharmony_ci	/*
17048c2ecf20Sopenharmony_ci	 * if the number of requested PG-s in CEE is greater than 3
17058c2ecf20Sopenharmony_ci	 * then the results are not determined since this is a violation
17068c2ecf20Sopenharmony_ci	 * of the standard.
17078c2ecf20Sopenharmony_ci	 */
17088c2ecf20Sopenharmony_ci	if (help_data->num_of_pg > DCBX_COS_MAX_NUM_E3B0) {
17098c2ecf20Sopenharmony_ci		if (bnx2x_dcbx_join_pgs(bp, ets, help_data,
17108c2ecf20Sopenharmony_ci					DCBX_COS_MAX_NUM_E3B0)) {
17118c2ecf20Sopenharmony_ci			BNX2X_ERR("Unable to reduce the number of PGs - we will disables ETS\n");
17128c2ecf20Sopenharmony_ci			bnx2x_dcbx_ets_disabled_entry_data(bp, cos_data,
17138c2ecf20Sopenharmony_ci							   pri_join_mask);
17148c2ecf20Sopenharmony_ci			return;
17158c2ecf20Sopenharmony_ci		}
17168c2ecf20Sopenharmony_ci	}
17178c2ecf20Sopenharmony_ci
17188c2ecf20Sopenharmony_ci	for (i = 0 ; i < help_data->num_of_pg; i++) {
17198c2ecf20Sopenharmony_ci		struct pg_entry_help_data *pg =  &help_data->data[i];
17208c2ecf20Sopenharmony_ci		if (pg->pg < DCBX_MAX_NUM_PG_BW_ENTRIES) {
17218c2ecf20Sopenharmony_ci			struct cos_entry_help_data *data = &cos_data->
17228c2ecf20Sopenharmony_ci							    data[entry];
17238c2ecf20Sopenharmony_ci			/* Fill BW entry */
17248c2ecf20Sopenharmony_ci			data->cos_bw = DCBX_PG_BW_GET(ets->pg_bw_tbl, pg->pg);
17258c2ecf20Sopenharmony_ci			data->strict = BNX2X_DCBX_STRICT_INVALID;
17268c2ecf20Sopenharmony_ci			data->pri_join_mask = pg->pg_priority;
17278c2ecf20Sopenharmony_ci			data->pausable = DCBX_IS_PFC_PRI_SOME_PAUSE(bp,
17288c2ecf20Sopenharmony_ci						data->pri_join_mask);
17298c2ecf20Sopenharmony_ci
17308c2ecf20Sopenharmony_ci			entry++;
17318c2ecf20Sopenharmony_ci		} else {
17328c2ecf20Sopenharmony_ci			need_num_of_entries =  min_t(u8,
17338c2ecf20Sopenharmony_ci				(u8)pg->num_of_dif_pri,
17348c2ecf20Sopenharmony_ci				(u8)DCBX_COS_MAX_NUM_E3B0 -
17358c2ecf20Sopenharmony_ci						 help_data->num_of_pg + 1);
17368c2ecf20Sopenharmony_ci			/*
17378c2ecf20Sopenharmony_ci			 * If there are still VOQ-s which have no associated PG,
17388c2ecf20Sopenharmony_ci			 * then associate these VOQ-s to PG15. These PG-s will
17398c2ecf20Sopenharmony_ci			 * be used for SP between priorities on PG15.
17408c2ecf20Sopenharmony_ci			 */
17418c2ecf20Sopenharmony_ci			entry += bnx2x_dcbx_cee_fill_strict_pri(bp, cos_data,
17428c2ecf20Sopenharmony_ci				entry, need_num_of_entries, pg->pg_priority);
17438c2ecf20Sopenharmony_ci		}
17448c2ecf20Sopenharmony_ci	}
17458c2ecf20Sopenharmony_ci
17468c2ecf20Sopenharmony_ci	/* the entry will represent the number of COSes used */
17478c2ecf20Sopenharmony_ci	cos_data->num_of_cos = entry;
17488c2ecf20Sopenharmony_ci}
17498c2ecf20Sopenharmony_cistatic void bnx2x_dcbx_fill_cos_params(struct bnx2x *bp,
17508c2ecf20Sopenharmony_ci				       struct pg_help_data *help_data,
17518c2ecf20Sopenharmony_ci				       struct dcbx_ets_feature *ets,
17528c2ecf20Sopenharmony_ci				       u32 *pg_pri_orginal_spread)
17538c2ecf20Sopenharmony_ci{
17548c2ecf20Sopenharmony_ci	struct cos_help_data         cos_data;
17558c2ecf20Sopenharmony_ci	u8                    i                           = 0;
17568c2ecf20Sopenharmony_ci	u32                   pri_join_mask               = 0;
17578c2ecf20Sopenharmony_ci	u8                    num_of_dif_pri              = 0;
17588c2ecf20Sopenharmony_ci
17598c2ecf20Sopenharmony_ci	memset(&cos_data, 0, sizeof(cos_data));
17608c2ecf20Sopenharmony_ci
17618c2ecf20Sopenharmony_ci	/* Validate the pg value */
17628c2ecf20Sopenharmony_ci	for (i = 0; i < help_data->num_of_pg ; i++) {
17638c2ecf20Sopenharmony_ci		if (DCBX_STRICT_PRIORITY != help_data->data[i].pg &&
17648c2ecf20Sopenharmony_ci		    DCBX_MAX_NUM_PG_BW_ENTRIES <= help_data->data[i].pg)
17658c2ecf20Sopenharmony_ci			BNX2X_ERR("Invalid pg[%d] data %x\n", i,
17668c2ecf20Sopenharmony_ci				  help_data->data[i].pg);
17678c2ecf20Sopenharmony_ci		pri_join_mask   |=  help_data->data[i].pg_priority;
17688c2ecf20Sopenharmony_ci		num_of_dif_pri  += help_data->data[i].num_of_dif_pri;
17698c2ecf20Sopenharmony_ci	}
17708c2ecf20Sopenharmony_ci
17718c2ecf20Sopenharmony_ci	/* defaults */
17728c2ecf20Sopenharmony_ci	cos_data.num_of_cos = 1;
17738c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(cos_data.data); i++) {
17748c2ecf20Sopenharmony_ci		cos_data.data[i].pri_join_mask = 0;
17758c2ecf20Sopenharmony_ci		cos_data.data[i].pausable = false;
17768c2ecf20Sopenharmony_ci		cos_data.data[i].strict = BNX2X_DCBX_STRICT_INVALID;
17778c2ecf20Sopenharmony_ci		cos_data.data[i].cos_bw = DCBX_INVALID_COS_BW;
17788c2ecf20Sopenharmony_ci	}
17798c2ecf20Sopenharmony_ci
17808c2ecf20Sopenharmony_ci	if (CHIP_IS_E3B0(bp))
17818c2ecf20Sopenharmony_ci		bnx2x_dcbx_cee_fill_cos_params(bp, help_data, ets,
17828c2ecf20Sopenharmony_ci					       &cos_data, pri_join_mask);
17838c2ecf20Sopenharmony_ci	else /* E2 + E3A0 */
17848c2ecf20Sopenharmony_ci		bnx2x_dcbx_2cos_limit_cee_fill_cos_params(bp,
17858c2ecf20Sopenharmony_ci							  help_data, ets,
17868c2ecf20Sopenharmony_ci							  &cos_data,
17878c2ecf20Sopenharmony_ci							  pg_pri_orginal_spread,
17888c2ecf20Sopenharmony_ci							  pri_join_mask,
17898c2ecf20Sopenharmony_ci							  num_of_dif_pri);
17908c2ecf20Sopenharmony_ci
17918c2ecf20Sopenharmony_ci	for (i = 0; i < cos_data.num_of_cos ; i++) {
17928c2ecf20Sopenharmony_ci		struct bnx2x_dcbx_cos_params *p =
17938c2ecf20Sopenharmony_ci			&bp->dcbx_port_params.ets.cos_params[i];
17948c2ecf20Sopenharmony_ci
17958c2ecf20Sopenharmony_ci		p->strict = cos_data.data[i].strict;
17968c2ecf20Sopenharmony_ci		p->bw_tbl = cos_data.data[i].cos_bw;
17978c2ecf20Sopenharmony_ci		p->pri_bitmask = cos_data.data[i].pri_join_mask;
17988c2ecf20Sopenharmony_ci		p->pauseable = cos_data.data[i].pausable;
17998c2ecf20Sopenharmony_ci
18008c2ecf20Sopenharmony_ci		/* sanity */
18018c2ecf20Sopenharmony_ci		if (p->bw_tbl != DCBX_INVALID_COS_BW ||
18028c2ecf20Sopenharmony_ci		    p->strict != BNX2X_DCBX_STRICT_INVALID) {
18038c2ecf20Sopenharmony_ci			if (p->pri_bitmask == 0)
18048c2ecf20Sopenharmony_ci				BNX2X_ERR("Invalid pri_bitmask for %d\n", i);
18058c2ecf20Sopenharmony_ci
18068c2ecf20Sopenharmony_ci			if (CHIP_IS_E2(bp) || CHIP_IS_E3A0(bp)) {
18078c2ecf20Sopenharmony_ci
18088c2ecf20Sopenharmony_ci				if (p->pauseable &&
18098c2ecf20Sopenharmony_ci				    DCBX_PFC_PRI_GET_NON_PAUSE(bp,
18108c2ecf20Sopenharmony_ci						p->pri_bitmask) != 0)
18118c2ecf20Sopenharmony_ci					BNX2X_ERR("Inconsistent config for pausable COS %d\n",
18128c2ecf20Sopenharmony_ci						  i);
18138c2ecf20Sopenharmony_ci
18148c2ecf20Sopenharmony_ci				if (!p->pauseable &&
18158c2ecf20Sopenharmony_ci				    DCBX_PFC_PRI_GET_PAUSE(bp,
18168c2ecf20Sopenharmony_ci						p->pri_bitmask) != 0)
18178c2ecf20Sopenharmony_ci					BNX2X_ERR("Inconsistent config for nonpausable COS %d\n",
18188c2ecf20Sopenharmony_ci						  i);
18198c2ecf20Sopenharmony_ci			}
18208c2ecf20Sopenharmony_ci		}
18218c2ecf20Sopenharmony_ci
18228c2ecf20Sopenharmony_ci		if (p->pauseable)
18238c2ecf20Sopenharmony_ci			DP(BNX2X_MSG_DCB, "COS %d PAUSABLE prijoinmask 0x%x\n",
18248c2ecf20Sopenharmony_ci				  i, cos_data.data[i].pri_join_mask);
18258c2ecf20Sopenharmony_ci		else
18268c2ecf20Sopenharmony_ci			DP(BNX2X_MSG_DCB,
18278c2ecf20Sopenharmony_ci			   "COS %d NONPAUSABLE prijoinmask 0x%x\n",
18288c2ecf20Sopenharmony_ci			   i, cos_data.data[i].pri_join_mask);
18298c2ecf20Sopenharmony_ci	}
18308c2ecf20Sopenharmony_ci
18318c2ecf20Sopenharmony_ci	bp->dcbx_port_params.ets.num_of_cos = cos_data.num_of_cos ;
18328c2ecf20Sopenharmony_ci}
18338c2ecf20Sopenharmony_ci
18348c2ecf20Sopenharmony_cistatic void bnx2x_dcbx_get_ets_pri_pg_tbl(struct bnx2x *bp,
18358c2ecf20Sopenharmony_ci				u32 *set_configuration_ets_pg,
18368c2ecf20Sopenharmony_ci				u32 *pri_pg_tbl)
18378c2ecf20Sopenharmony_ci{
18388c2ecf20Sopenharmony_ci	int i;
18398c2ecf20Sopenharmony_ci
18408c2ecf20Sopenharmony_ci	for (i = 0; i < DCBX_MAX_NUM_PRI_PG_ENTRIES; i++) {
18418c2ecf20Sopenharmony_ci		set_configuration_ets_pg[i] = DCBX_PRI_PG_GET(pri_pg_tbl, i);
18428c2ecf20Sopenharmony_ci
18438c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_DCB, "set_configuration_ets_pg[%d] = 0x%x\n",
18448c2ecf20Sopenharmony_ci		   i, set_configuration_ets_pg[i]);
18458c2ecf20Sopenharmony_ci	}
18468c2ecf20Sopenharmony_ci}
18478c2ecf20Sopenharmony_ci
18488c2ecf20Sopenharmony_cistatic void bnx2x_dcbx_fw_struct(struct bnx2x *bp,
18498c2ecf20Sopenharmony_ci				 struct bnx2x_func_tx_start_params *pfc_fw_cfg)
18508c2ecf20Sopenharmony_ci{
18518c2ecf20Sopenharmony_ci	u16 pri_bit = 0;
18528c2ecf20Sopenharmony_ci	u8 cos = 0, pri = 0;
18538c2ecf20Sopenharmony_ci	struct priority_cos *tt2cos;
18548c2ecf20Sopenharmony_ci	u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority;
18558c2ecf20Sopenharmony_ci	int mfw_configured = SHMEM2_HAS(bp, drv_flags) &&
18568c2ecf20Sopenharmony_ci			     GET_FLAGS(SHMEM2_RD(bp, drv_flags),
18578c2ecf20Sopenharmony_ci				       1 << DRV_FLAGS_DCB_MFW_CONFIGURED);
18588c2ecf20Sopenharmony_ci
18598c2ecf20Sopenharmony_ci	memset(pfc_fw_cfg, 0, sizeof(*pfc_fw_cfg));
18608c2ecf20Sopenharmony_ci
18618c2ecf20Sopenharmony_ci	/* to disable DCB - the structure must be zeroed */
18628c2ecf20Sopenharmony_ci	if ((bp->dcbx_error & DCBX_REMOTE_MIB_ERROR) && !mfw_configured)
18638c2ecf20Sopenharmony_ci		return;
18648c2ecf20Sopenharmony_ci
18658c2ecf20Sopenharmony_ci	/*shortcut*/
18668c2ecf20Sopenharmony_ci	tt2cos = pfc_fw_cfg->traffic_type_to_priority_cos;
18678c2ecf20Sopenharmony_ci
18688c2ecf20Sopenharmony_ci	/* Fw version should be incremented each update */
18698c2ecf20Sopenharmony_ci	pfc_fw_cfg->dcb_version = ++bp->dcb_version;
18708c2ecf20Sopenharmony_ci	pfc_fw_cfg->dcb_enabled = 1;
18718c2ecf20Sopenharmony_ci
18728c2ecf20Sopenharmony_ci	/* Fill priority parameters */
18738c2ecf20Sopenharmony_ci	for (pri = 0; pri < LLFC_DRIVER_TRAFFIC_TYPE_MAX; pri++) {
18748c2ecf20Sopenharmony_ci		tt2cos[pri].priority = ttp[pri];
18758c2ecf20Sopenharmony_ci		pri_bit = 1 << tt2cos[pri].priority;
18768c2ecf20Sopenharmony_ci
18778c2ecf20Sopenharmony_ci		/* Fill COS parameters based on COS calculated to
18788c2ecf20Sopenharmony_ci		 * make it more general for future use */
18798c2ecf20Sopenharmony_ci		for (cos = 0; cos < bp->dcbx_port_params.ets.num_of_cos; cos++)
18808c2ecf20Sopenharmony_ci			if (bp->dcbx_port_params.ets.cos_params[cos].
18818c2ecf20Sopenharmony_ci						pri_bitmask & pri_bit)
18828c2ecf20Sopenharmony_ci					tt2cos[pri].cos = cos;
18838c2ecf20Sopenharmony_ci
18848c2ecf20Sopenharmony_ci		pfc_fw_cfg->dcb_outer_pri[pri]  = ttp[pri];
18858c2ecf20Sopenharmony_ci	}
18868c2ecf20Sopenharmony_ci
18878c2ecf20Sopenharmony_ci	/* we never want the FW to add a 0 vlan tag */
18888c2ecf20Sopenharmony_ci	pfc_fw_cfg->dont_add_pri_0_en = 1;
18898c2ecf20Sopenharmony_ci
18908c2ecf20Sopenharmony_ci	bnx2x_dcbx_print_cos_params(bp,	pfc_fw_cfg);
18918c2ecf20Sopenharmony_ci}
18928c2ecf20Sopenharmony_ci
18938c2ecf20Sopenharmony_civoid bnx2x_dcbx_pmf_update(struct bnx2x *bp)
18948c2ecf20Sopenharmony_ci{
18958c2ecf20Sopenharmony_ci	/* if we need to synchronize DCBX result from prev PMF
18968c2ecf20Sopenharmony_ci	 * read it from shmem and update bp and netdev accordingly
18978c2ecf20Sopenharmony_ci	 */
18988c2ecf20Sopenharmony_ci	if (SHMEM2_HAS(bp, drv_flags) &&
18998c2ecf20Sopenharmony_ci	   GET_FLAGS(SHMEM2_RD(bp, drv_flags), 1 << DRV_FLAGS_DCB_CONFIGURED)) {
19008c2ecf20Sopenharmony_ci		/* Read neg results if dcbx is in the FW */
19018c2ecf20Sopenharmony_ci		if (bnx2x_dcbx_read_shmem_neg_results(bp))
19028c2ecf20Sopenharmony_ci			return;
19038c2ecf20Sopenharmony_ci
19048c2ecf20Sopenharmony_ci		bnx2x_dump_dcbx_drv_param(bp, &bp->dcbx_local_feat,
19058c2ecf20Sopenharmony_ci					  bp->dcbx_error);
19068c2ecf20Sopenharmony_ci		bnx2x_get_dcbx_drv_param(bp, &bp->dcbx_local_feat,
19078c2ecf20Sopenharmony_ci					 bp->dcbx_error);
19088c2ecf20Sopenharmony_ci#ifdef BCM_DCBNL
19098c2ecf20Sopenharmony_ci		/*
19108c2ecf20Sopenharmony_ci		 * Add new app tlvs to dcbnl
19118c2ecf20Sopenharmony_ci		 */
19128c2ecf20Sopenharmony_ci		bnx2x_dcbnl_update_applist(bp, false);
19138c2ecf20Sopenharmony_ci		/*
19148c2ecf20Sopenharmony_ci		 * Send a notification for the new negotiated parameters
19158c2ecf20Sopenharmony_ci		 */
19168c2ecf20Sopenharmony_ci		dcbnl_cee_notify(bp->dev, RTM_GETDCB, DCB_CMD_CEE_GET, 0, 0);
19178c2ecf20Sopenharmony_ci#endif
19188c2ecf20Sopenharmony_ci		/*
19198c2ecf20Sopenharmony_ci		 * reconfigure the netdevice with the results of the new
19208c2ecf20Sopenharmony_ci		 * dcbx negotiation.
19218c2ecf20Sopenharmony_ci		 */
19228c2ecf20Sopenharmony_ci		bnx2x_dcbx_update_tc_mapping(bp);
19238c2ecf20Sopenharmony_ci	}
19248c2ecf20Sopenharmony_ci}
19258c2ecf20Sopenharmony_ci
19268c2ecf20Sopenharmony_ci/* DCB netlink */
19278c2ecf20Sopenharmony_ci#ifdef BCM_DCBNL
19288c2ecf20Sopenharmony_ci
19298c2ecf20Sopenharmony_ci#define BNX2X_DCBX_CAPS		(DCB_CAP_DCBX_LLD_MANAGED | \
19308c2ecf20Sopenharmony_ci				DCB_CAP_DCBX_VER_CEE | DCB_CAP_DCBX_STATIC)
19318c2ecf20Sopenharmony_ci
19328c2ecf20Sopenharmony_cistatic inline bool bnx2x_dcbnl_set_valid(struct bnx2x *bp)
19338c2ecf20Sopenharmony_ci{
19348c2ecf20Sopenharmony_ci	/* validate dcbnl call that may change HW state:
19358c2ecf20Sopenharmony_ci	 * DCB is on and DCBX mode was SUCCESSFULLY set by the user.
19368c2ecf20Sopenharmony_ci	 */
19378c2ecf20Sopenharmony_ci	return bp->dcb_state && bp->dcbx_mode_uset;
19388c2ecf20Sopenharmony_ci}
19398c2ecf20Sopenharmony_ci
19408c2ecf20Sopenharmony_cistatic u8 bnx2x_dcbnl_get_state(struct net_device *netdev)
19418c2ecf20Sopenharmony_ci{
19428c2ecf20Sopenharmony_ci	struct bnx2x *bp = netdev_priv(netdev);
19438c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_DCB, "state = %d\n", bp->dcb_state);
19448c2ecf20Sopenharmony_ci	return bp->dcb_state;
19458c2ecf20Sopenharmony_ci}
19468c2ecf20Sopenharmony_ci
19478c2ecf20Sopenharmony_cistatic u8 bnx2x_dcbnl_set_state(struct net_device *netdev, u8 state)
19488c2ecf20Sopenharmony_ci{
19498c2ecf20Sopenharmony_ci	struct bnx2x *bp = netdev_priv(netdev);
19508c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_DCB, "state = %s\n", state ? "on" : "off");
19518c2ecf20Sopenharmony_ci
19528c2ecf20Sopenharmony_ci	/* Fail to set state to "enabled" if dcbx is disabled in nvram */
19538c2ecf20Sopenharmony_ci	if (state && ((bp->dcbx_enabled == BNX2X_DCBX_ENABLED_OFF) ||
19548c2ecf20Sopenharmony_ci		      (bp->dcbx_enabled == BNX2X_DCBX_ENABLED_INVALID))) {
19558c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_DCB, "Can not set dcbx to enabled while it is disabled in nvm\n");
19568c2ecf20Sopenharmony_ci		return 1;
19578c2ecf20Sopenharmony_ci	}
19588c2ecf20Sopenharmony_ci
19598c2ecf20Sopenharmony_ci	bnx2x_dcbx_set_state(bp, (state ? true : false), bp->dcbx_enabled);
19608c2ecf20Sopenharmony_ci	return 0;
19618c2ecf20Sopenharmony_ci}
19628c2ecf20Sopenharmony_ci
19638c2ecf20Sopenharmony_cistatic void bnx2x_dcbnl_get_perm_hw_addr(struct net_device *netdev,
19648c2ecf20Sopenharmony_ci					 u8 *perm_addr)
19658c2ecf20Sopenharmony_ci{
19668c2ecf20Sopenharmony_ci	struct bnx2x *bp = netdev_priv(netdev);
19678c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_DCB, "GET-PERM-ADDR\n");
19688c2ecf20Sopenharmony_ci
19698c2ecf20Sopenharmony_ci	/* first the HW mac address */
19708c2ecf20Sopenharmony_ci	memcpy(perm_addr, netdev->dev_addr, netdev->addr_len);
19718c2ecf20Sopenharmony_ci
19728c2ecf20Sopenharmony_ci	if (CNIC_LOADED(bp))
19738c2ecf20Sopenharmony_ci		/* second SAN address */
19748c2ecf20Sopenharmony_ci		memcpy(perm_addr+netdev->addr_len, bp->fip_mac,
19758c2ecf20Sopenharmony_ci		       netdev->addr_len);
19768c2ecf20Sopenharmony_ci}
19778c2ecf20Sopenharmony_ci
19788c2ecf20Sopenharmony_cistatic void bnx2x_dcbnl_set_pg_tccfg_tx(struct net_device *netdev, int prio,
19798c2ecf20Sopenharmony_ci					u8 prio_type, u8 pgid, u8 bw_pct,
19808c2ecf20Sopenharmony_ci					u8 up_map)
19818c2ecf20Sopenharmony_ci{
19828c2ecf20Sopenharmony_ci	struct bnx2x *bp = netdev_priv(netdev);
19838c2ecf20Sopenharmony_ci
19848c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_DCB, "prio[%d] = %d\n", prio, pgid);
19858c2ecf20Sopenharmony_ci	if (!bnx2x_dcbnl_set_valid(bp) || prio >= DCBX_MAX_NUM_PRI_PG_ENTRIES)
19868c2ecf20Sopenharmony_ci		return;
19878c2ecf20Sopenharmony_ci
19888c2ecf20Sopenharmony_ci	/**
19898c2ecf20Sopenharmony_ci	 * bw_pct ignored -	band-width percentage devision between user
19908c2ecf20Sopenharmony_ci	 *			priorities within the same group is not
19918c2ecf20Sopenharmony_ci	 *			standard and hence not supported
19928c2ecf20Sopenharmony_ci	 *
19938c2ecf20Sopenharmony_ci	 * prio_type ignored -	priority levels within the same group are not
19948c2ecf20Sopenharmony_ci	 *			standard and hence are not supported. According
19958c2ecf20Sopenharmony_ci	 *			to the standard pgid 15 is dedicated to strict
19968c2ecf20Sopenharmony_ci	 *			priority traffic (on the port level).
19978c2ecf20Sopenharmony_ci	 *
19988c2ecf20Sopenharmony_ci	 * up_map ignored
19998c2ecf20Sopenharmony_ci	 */
20008c2ecf20Sopenharmony_ci
20018c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_configuration_ets_pg[prio] = pgid;
20028c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_ets_configuration_tx_enable = 1;
20038c2ecf20Sopenharmony_ci}
20048c2ecf20Sopenharmony_ci
20058c2ecf20Sopenharmony_cistatic void bnx2x_dcbnl_set_pg_bwgcfg_tx(struct net_device *netdev,
20068c2ecf20Sopenharmony_ci					 int pgid, u8 bw_pct)
20078c2ecf20Sopenharmony_ci{
20088c2ecf20Sopenharmony_ci	struct bnx2x *bp = netdev_priv(netdev);
20098c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_DCB, "pgid[%d] = %d\n", pgid, bw_pct);
20108c2ecf20Sopenharmony_ci
20118c2ecf20Sopenharmony_ci	if (!bnx2x_dcbnl_set_valid(bp) || pgid >= DCBX_MAX_NUM_PG_BW_ENTRIES)
20128c2ecf20Sopenharmony_ci		return;
20138c2ecf20Sopenharmony_ci
20148c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_configuration_bw_precentage[pgid] = bw_pct;
20158c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_ets_configuration_tx_enable = 1;
20168c2ecf20Sopenharmony_ci}
20178c2ecf20Sopenharmony_ci
20188c2ecf20Sopenharmony_cistatic void bnx2x_dcbnl_set_pg_tccfg_rx(struct net_device *netdev, int prio,
20198c2ecf20Sopenharmony_ci					u8 prio_type, u8 pgid, u8 bw_pct,
20208c2ecf20Sopenharmony_ci					u8 up_map)
20218c2ecf20Sopenharmony_ci{
20228c2ecf20Sopenharmony_ci	struct bnx2x *bp = netdev_priv(netdev);
20238c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_DCB, "Nothing to set; No RX support\n");
20248c2ecf20Sopenharmony_ci}
20258c2ecf20Sopenharmony_ci
20268c2ecf20Sopenharmony_cistatic void bnx2x_dcbnl_set_pg_bwgcfg_rx(struct net_device *netdev,
20278c2ecf20Sopenharmony_ci					 int pgid, u8 bw_pct)
20288c2ecf20Sopenharmony_ci{
20298c2ecf20Sopenharmony_ci	struct bnx2x *bp = netdev_priv(netdev);
20308c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_DCB, "Nothing to set; No RX support\n");
20318c2ecf20Sopenharmony_ci}
20328c2ecf20Sopenharmony_ci
20338c2ecf20Sopenharmony_cistatic void bnx2x_dcbnl_get_pg_tccfg_tx(struct net_device *netdev, int prio,
20348c2ecf20Sopenharmony_ci					u8 *prio_type, u8 *pgid, u8 *bw_pct,
20358c2ecf20Sopenharmony_ci					u8 *up_map)
20368c2ecf20Sopenharmony_ci{
20378c2ecf20Sopenharmony_ci	struct bnx2x *bp = netdev_priv(netdev);
20388c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_DCB, "prio = %d\n", prio);
20398c2ecf20Sopenharmony_ci
20408c2ecf20Sopenharmony_ci	/**
20418c2ecf20Sopenharmony_ci	 * bw_pct ignored -	band-width percentage devision between user
20428c2ecf20Sopenharmony_ci	 *			priorities within the same group is not
20438c2ecf20Sopenharmony_ci	 *			standard and hence not supported
20448c2ecf20Sopenharmony_ci	 *
20458c2ecf20Sopenharmony_ci	 * prio_type ignored -	priority levels within the same group are not
20468c2ecf20Sopenharmony_ci	 *			standard and hence are not supported. According
20478c2ecf20Sopenharmony_ci	 *			to the standard pgid 15 is dedicated to strict
20488c2ecf20Sopenharmony_ci	 *			priority traffic (on the port level).
20498c2ecf20Sopenharmony_ci	 *
20508c2ecf20Sopenharmony_ci	 * up_map ignored
20518c2ecf20Sopenharmony_ci	 */
20528c2ecf20Sopenharmony_ci	*up_map = *bw_pct = *prio_type = *pgid = 0;
20538c2ecf20Sopenharmony_ci
20548c2ecf20Sopenharmony_ci	if (!bp->dcb_state || prio >= DCBX_MAX_NUM_PRI_PG_ENTRIES)
20558c2ecf20Sopenharmony_ci		return;
20568c2ecf20Sopenharmony_ci
20578c2ecf20Sopenharmony_ci	*pgid = DCBX_PRI_PG_GET(bp->dcbx_local_feat.ets.pri_pg_tbl, prio);
20588c2ecf20Sopenharmony_ci}
20598c2ecf20Sopenharmony_ci
20608c2ecf20Sopenharmony_cistatic void bnx2x_dcbnl_get_pg_bwgcfg_tx(struct net_device *netdev,
20618c2ecf20Sopenharmony_ci					 int pgid, u8 *bw_pct)
20628c2ecf20Sopenharmony_ci{
20638c2ecf20Sopenharmony_ci	struct bnx2x *bp = netdev_priv(netdev);
20648c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_DCB, "pgid = %d\n", pgid);
20658c2ecf20Sopenharmony_ci
20668c2ecf20Sopenharmony_ci	*bw_pct = 0;
20678c2ecf20Sopenharmony_ci
20688c2ecf20Sopenharmony_ci	if (!bp->dcb_state || pgid >= DCBX_MAX_NUM_PG_BW_ENTRIES)
20698c2ecf20Sopenharmony_ci		return;
20708c2ecf20Sopenharmony_ci
20718c2ecf20Sopenharmony_ci	*bw_pct = DCBX_PG_BW_GET(bp->dcbx_local_feat.ets.pg_bw_tbl, pgid);
20728c2ecf20Sopenharmony_ci}
20738c2ecf20Sopenharmony_ci
20748c2ecf20Sopenharmony_cistatic void bnx2x_dcbnl_get_pg_tccfg_rx(struct net_device *netdev, int prio,
20758c2ecf20Sopenharmony_ci					u8 *prio_type, u8 *pgid, u8 *bw_pct,
20768c2ecf20Sopenharmony_ci					u8 *up_map)
20778c2ecf20Sopenharmony_ci{
20788c2ecf20Sopenharmony_ci	struct bnx2x *bp = netdev_priv(netdev);
20798c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_DCB, "Nothing to get; No RX support\n");
20808c2ecf20Sopenharmony_ci
20818c2ecf20Sopenharmony_ci	*prio_type = *pgid = *bw_pct = *up_map = 0;
20828c2ecf20Sopenharmony_ci}
20838c2ecf20Sopenharmony_ci
20848c2ecf20Sopenharmony_cistatic void bnx2x_dcbnl_get_pg_bwgcfg_rx(struct net_device *netdev,
20858c2ecf20Sopenharmony_ci					 int pgid, u8 *bw_pct)
20868c2ecf20Sopenharmony_ci{
20878c2ecf20Sopenharmony_ci	struct bnx2x *bp = netdev_priv(netdev);
20888c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_DCB, "Nothing to get; No RX support\n");
20898c2ecf20Sopenharmony_ci
20908c2ecf20Sopenharmony_ci	*bw_pct = 0;
20918c2ecf20Sopenharmony_ci}
20928c2ecf20Sopenharmony_ci
20938c2ecf20Sopenharmony_cistatic void bnx2x_dcbnl_set_pfc_cfg(struct net_device *netdev, int prio,
20948c2ecf20Sopenharmony_ci				    u8 setting)
20958c2ecf20Sopenharmony_ci{
20968c2ecf20Sopenharmony_ci	struct bnx2x *bp = netdev_priv(netdev);
20978c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_DCB, "prio[%d] = %d\n", prio, setting);
20988c2ecf20Sopenharmony_ci
20998c2ecf20Sopenharmony_ci	if (!bnx2x_dcbnl_set_valid(bp) || prio >= MAX_PFC_PRIORITIES)
21008c2ecf20Sopenharmony_ci		return;
21018c2ecf20Sopenharmony_ci
21028c2ecf20Sopenharmony_ci	if (setting) {
21038c2ecf20Sopenharmony_ci		bp->dcbx_config_params.admin_pfc_bitmap |= (1 << prio);
21048c2ecf20Sopenharmony_ci		bp->dcbx_config_params.admin_pfc_tx_enable = 1;
21058c2ecf20Sopenharmony_ci	} else {
21068c2ecf20Sopenharmony_ci		bp->dcbx_config_params.admin_pfc_bitmap &= ~(1 << prio);
21078c2ecf20Sopenharmony_ci	}
21088c2ecf20Sopenharmony_ci}
21098c2ecf20Sopenharmony_ci
21108c2ecf20Sopenharmony_cistatic void bnx2x_dcbnl_get_pfc_cfg(struct net_device *netdev, int prio,
21118c2ecf20Sopenharmony_ci				    u8 *setting)
21128c2ecf20Sopenharmony_ci{
21138c2ecf20Sopenharmony_ci	struct bnx2x *bp = netdev_priv(netdev);
21148c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_DCB, "prio = %d\n", prio);
21158c2ecf20Sopenharmony_ci
21168c2ecf20Sopenharmony_ci	*setting = 0;
21178c2ecf20Sopenharmony_ci
21188c2ecf20Sopenharmony_ci	if (!bp->dcb_state || prio >= MAX_PFC_PRIORITIES)
21198c2ecf20Sopenharmony_ci		return;
21208c2ecf20Sopenharmony_ci
21218c2ecf20Sopenharmony_ci	*setting = (bp->dcbx_local_feat.pfc.pri_en_bitmap >> prio) & 0x1;
21228c2ecf20Sopenharmony_ci}
21238c2ecf20Sopenharmony_ci
21248c2ecf20Sopenharmony_cistatic u8 bnx2x_dcbnl_set_all(struct net_device *netdev)
21258c2ecf20Sopenharmony_ci{
21268c2ecf20Sopenharmony_ci	struct bnx2x *bp = netdev_priv(netdev);
21278c2ecf20Sopenharmony_ci
21288c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_DCB, "SET-ALL\n");
21298c2ecf20Sopenharmony_ci
21308c2ecf20Sopenharmony_ci	if (!bnx2x_dcbnl_set_valid(bp))
21318c2ecf20Sopenharmony_ci		return 1;
21328c2ecf20Sopenharmony_ci
21338c2ecf20Sopenharmony_ci	if (bp->recovery_state != BNX2X_RECOVERY_DONE) {
21348c2ecf20Sopenharmony_ci		netdev_err(bp->dev,
21358c2ecf20Sopenharmony_ci			   "Handling parity error recovery. Try again later\n");
21368c2ecf20Sopenharmony_ci		return 1;
21378c2ecf20Sopenharmony_ci	}
21388c2ecf20Sopenharmony_ci	if (netif_running(bp->dev)) {
21398c2ecf20Sopenharmony_ci		bnx2x_update_drv_flags(bp,
21408c2ecf20Sopenharmony_ci				       1 << DRV_FLAGS_DCB_MFW_CONFIGURED,
21418c2ecf20Sopenharmony_ci				       1);
21428c2ecf20Sopenharmony_ci		bnx2x_dcbx_init(bp, true);
21438c2ecf20Sopenharmony_ci	}
21448c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_DCB, "set_dcbx_params done\n");
21458c2ecf20Sopenharmony_ci
21468c2ecf20Sopenharmony_ci	return 0;
21478c2ecf20Sopenharmony_ci}
21488c2ecf20Sopenharmony_ci
21498c2ecf20Sopenharmony_cistatic u8 bnx2x_dcbnl_get_cap(struct net_device *netdev, int capid, u8 *cap)
21508c2ecf20Sopenharmony_ci{
21518c2ecf20Sopenharmony_ci	struct bnx2x *bp = netdev_priv(netdev);
21528c2ecf20Sopenharmony_ci	u8 rval = 0;
21538c2ecf20Sopenharmony_ci
21548c2ecf20Sopenharmony_ci	if (bp->dcb_state) {
21558c2ecf20Sopenharmony_ci		switch (capid) {
21568c2ecf20Sopenharmony_ci		case DCB_CAP_ATTR_PG:
21578c2ecf20Sopenharmony_ci			*cap = true;
21588c2ecf20Sopenharmony_ci			break;
21598c2ecf20Sopenharmony_ci		case DCB_CAP_ATTR_PFC:
21608c2ecf20Sopenharmony_ci			*cap = true;
21618c2ecf20Sopenharmony_ci			break;
21628c2ecf20Sopenharmony_ci		case DCB_CAP_ATTR_UP2TC:
21638c2ecf20Sopenharmony_ci			*cap = false;
21648c2ecf20Sopenharmony_ci			break;
21658c2ecf20Sopenharmony_ci		case DCB_CAP_ATTR_PG_TCS:
21668c2ecf20Sopenharmony_ci			*cap = 0x80;	/* 8 priorities for PGs */
21678c2ecf20Sopenharmony_ci			break;
21688c2ecf20Sopenharmony_ci		case DCB_CAP_ATTR_PFC_TCS:
21698c2ecf20Sopenharmony_ci			*cap = 0x80;	/* 8 priorities for PFC */
21708c2ecf20Sopenharmony_ci			break;
21718c2ecf20Sopenharmony_ci		case DCB_CAP_ATTR_GSP:
21728c2ecf20Sopenharmony_ci			*cap = true;
21738c2ecf20Sopenharmony_ci			break;
21748c2ecf20Sopenharmony_ci		case DCB_CAP_ATTR_BCN:
21758c2ecf20Sopenharmony_ci			*cap = false;
21768c2ecf20Sopenharmony_ci			break;
21778c2ecf20Sopenharmony_ci		case DCB_CAP_ATTR_DCBX:
21788c2ecf20Sopenharmony_ci			*cap = BNX2X_DCBX_CAPS;
21798c2ecf20Sopenharmony_ci			break;
21808c2ecf20Sopenharmony_ci		default:
21818c2ecf20Sopenharmony_ci			BNX2X_ERR("Non valid capability ID\n");
21828c2ecf20Sopenharmony_ci			rval = 1;
21838c2ecf20Sopenharmony_ci			break;
21848c2ecf20Sopenharmony_ci		}
21858c2ecf20Sopenharmony_ci	} else {
21868c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_DCB, "DCB disabled\n");
21878c2ecf20Sopenharmony_ci		rval = 1;
21888c2ecf20Sopenharmony_ci	}
21898c2ecf20Sopenharmony_ci
21908c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_DCB, "capid %d:%x\n", capid, *cap);
21918c2ecf20Sopenharmony_ci	return rval;
21928c2ecf20Sopenharmony_ci}
21938c2ecf20Sopenharmony_ci
21948c2ecf20Sopenharmony_cistatic int bnx2x_dcbnl_get_numtcs(struct net_device *netdev, int tcid, u8 *num)
21958c2ecf20Sopenharmony_ci{
21968c2ecf20Sopenharmony_ci	struct bnx2x *bp = netdev_priv(netdev);
21978c2ecf20Sopenharmony_ci	u8 rval = 0;
21988c2ecf20Sopenharmony_ci
21998c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_DCB, "tcid %d\n", tcid);
22008c2ecf20Sopenharmony_ci
22018c2ecf20Sopenharmony_ci	if (bp->dcb_state) {
22028c2ecf20Sopenharmony_ci		switch (tcid) {
22038c2ecf20Sopenharmony_ci		case DCB_NUMTCS_ATTR_PG:
22048c2ecf20Sopenharmony_ci			*num = CHIP_IS_E3B0(bp) ? DCBX_COS_MAX_NUM_E3B0 :
22058c2ecf20Sopenharmony_ci						  DCBX_COS_MAX_NUM_E2;
22068c2ecf20Sopenharmony_ci			break;
22078c2ecf20Sopenharmony_ci		case DCB_NUMTCS_ATTR_PFC:
22088c2ecf20Sopenharmony_ci			*num = CHIP_IS_E3B0(bp) ? DCBX_COS_MAX_NUM_E3B0 :
22098c2ecf20Sopenharmony_ci						  DCBX_COS_MAX_NUM_E2;
22108c2ecf20Sopenharmony_ci			break;
22118c2ecf20Sopenharmony_ci		default:
22128c2ecf20Sopenharmony_ci			BNX2X_ERR("Non valid TC-ID\n");
22138c2ecf20Sopenharmony_ci			rval = 1;
22148c2ecf20Sopenharmony_ci			break;
22158c2ecf20Sopenharmony_ci		}
22168c2ecf20Sopenharmony_ci	} else {
22178c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_DCB, "DCB disabled\n");
22188c2ecf20Sopenharmony_ci		rval = 1;
22198c2ecf20Sopenharmony_ci	}
22208c2ecf20Sopenharmony_ci
22218c2ecf20Sopenharmony_ci	return rval;
22228c2ecf20Sopenharmony_ci}
22238c2ecf20Sopenharmony_ci
22248c2ecf20Sopenharmony_cistatic int bnx2x_dcbnl_set_numtcs(struct net_device *netdev, int tcid, u8 num)
22258c2ecf20Sopenharmony_ci{
22268c2ecf20Sopenharmony_ci	struct bnx2x *bp = netdev_priv(netdev);
22278c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_DCB, "num tcs = %d; Not supported\n", num);
22288c2ecf20Sopenharmony_ci	return -EINVAL;
22298c2ecf20Sopenharmony_ci}
22308c2ecf20Sopenharmony_ci
22318c2ecf20Sopenharmony_cistatic u8 bnx2x_dcbnl_get_pfc_state(struct net_device *netdev)
22328c2ecf20Sopenharmony_ci{
22338c2ecf20Sopenharmony_ci	struct bnx2x *bp = netdev_priv(netdev);
22348c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_DCB, "state = %d\n", bp->dcbx_local_feat.pfc.enabled);
22358c2ecf20Sopenharmony_ci
22368c2ecf20Sopenharmony_ci	if (!bp->dcb_state)
22378c2ecf20Sopenharmony_ci		return 0;
22388c2ecf20Sopenharmony_ci
22398c2ecf20Sopenharmony_ci	return bp->dcbx_local_feat.pfc.enabled;
22408c2ecf20Sopenharmony_ci}
22418c2ecf20Sopenharmony_ci
22428c2ecf20Sopenharmony_cistatic void bnx2x_dcbnl_set_pfc_state(struct net_device *netdev, u8 state)
22438c2ecf20Sopenharmony_ci{
22448c2ecf20Sopenharmony_ci	struct bnx2x *bp = netdev_priv(netdev);
22458c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_DCB, "state = %s\n", state ? "on" : "off");
22468c2ecf20Sopenharmony_ci
22478c2ecf20Sopenharmony_ci	if (!bnx2x_dcbnl_set_valid(bp))
22488c2ecf20Sopenharmony_ci		return;
22498c2ecf20Sopenharmony_ci
22508c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_pfc_tx_enable =
22518c2ecf20Sopenharmony_ci	bp->dcbx_config_params.admin_pfc_enable = (state ? 1 : 0);
22528c2ecf20Sopenharmony_ci}
22538c2ecf20Sopenharmony_ci
22548c2ecf20Sopenharmony_cistatic void bnx2x_admin_app_set_ent(
22558c2ecf20Sopenharmony_ci	struct bnx2x_admin_priority_app_table *app_ent,
22568c2ecf20Sopenharmony_ci	u8 idtype, u16 idval, u8 up)
22578c2ecf20Sopenharmony_ci{
22588c2ecf20Sopenharmony_ci	app_ent->valid = 1;
22598c2ecf20Sopenharmony_ci
22608c2ecf20Sopenharmony_ci	switch (idtype) {
22618c2ecf20Sopenharmony_ci	case DCB_APP_IDTYPE_ETHTYPE:
22628c2ecf20Sopenharmony_ci		app_ent->traffic_type = TRAFFIC_TYPE_ETH;
22638c2ecf20Sopenharmony_ci		break;
22648c2ecf20Sopenharmony_ci	case DCB_APP_IDTYPE_PORTNUM:
22658c2ecf20Sopenharmony_ci		app_ent->traffic_type = TRAFFIC_TYPE_PORT;
22668c2ecf20Sopenharmony_ci		break;
22678c2ecf20Sopenharmony_ci	default:
22688c2ecf20Sopenharmony_ci		break; /* never gets here */
22698c2ecf20Sopenharmony_ci	}
22708c2ecf20Sopenharmony_ci	app_ent->app_id = idval;
22718c2ecf20Sopenharmony_ci	app_ent->priority = up;
22728c2ecf20Sopenharmony_ci}
22738c2ecf20Sopenharmony_ci
22748c2ecf20Sopenharmony_cistatic bool bnx2x_admin_app_is_equal(
22758c2ecf20Sopenharmony_ci	struct bnx2x_admin_priority_app_table *app_ent,
22768c2ecf20Sopenharmony_ci	u8 idtype, u16 idval)
22778c2ecf20Sopenharmony_ci{
22788c2ecf20Sopenharmony_ci	if (!app_ent->valid)
22798c2ecf20Sopenharmony_ci		return false;
22808c2ecf20Sopenharmony_ci
22818c2ecf20Sopenharmony_ci	switch (idtype) {
22828c2ecf20Sopenharmony_ci	case DCB_APP_IDTYPE_ETHTYPE:
22838c2ecf20Sopenharmony_ci		if (app_ent->traffic_type != TRAFFIC_TYPE_ETH)
22848c2ecf20Sopenharmony_ci			return false;
22858c2ecf20Sopenharmony_ci		break;
22868c2ecf20Sopenharmony_ci	case DCB_APP_IDTYPE_PORTNUM:
22878c2ecf20Sopenharmony_ci		if (app_ent->traffic_type != TRAFFIC_TYPE_PORT)
22888c2ecf20Sopenharmony_ci			return false;
22898c2ecf20Sopenharmony_ci		break;
22908c2ecf20Sopenharmony_ci	default:
22918c2ecf20Sopenharmony_ci		return false;
22928c2ecf20Sopenharmony_ci	}
22938c2ecf20Sopenharmony_ci	if (app_ent->app_id != idval)
22948c2ecf20Sopenharmony_ci		return false;
22958c2ecf20Sopenharmony_ci
22968c2ecf20Sopenharmony_ci	return true;
22978c2ecf20Sopenharmony_ci}
22988c2ecf20Sopenharmony_ci
22998c2ecf20Sopenharmony_cistatic int bnx2x_set_admin_app_up(struct bnx2x *bp, u8 idtype, u16 idval, u8 up)
23008c2ecf20Sopenharmony_ci{
23018c2ecf20Sopenharmony_ci	int i, ff;
23028c2ecf20Sopenharmony_ci
23038c2ecf20Sopenharmony_ci	/* iterate over the app entries looking for idtype and idval */
23048c2ecf20Sopenharmony_ci	for (i = 0, ff = -1; i < DCBX_CONFIG_MAX_APP_PROTOCOL; i++) {
23058c2ecf20Sopenharmony_ci		struct bnx2x_admin_priority_app_table *app_ent =
23068c2ecf20Sopenharmony_ci			&bp->dcbx_config_params.admin_priority_app_table[i];
23078c2ecf20Sopenharmony_ci		if (bnx2x_admin_app_is_equal(app_ent, idtype, idval))
23088c2ecf20Sopenharmony_ci			break;
23098c2ecf20Sopenharmony_ci
23108c2ecf20Sopenharmony_ci		if (ff < 0 && !app_ent->valid)
23118c2ecf20Sopenharmony_ci			ff = i;
23128c2ecf20Sopenharmony_ci	}
23138c2ecf20Sopenharmony_ci	if (i < DCBX_CONFIG_MAX_APP_PROTOCOL)
23148c2ecf20Sopenharmony_ci		/* if found overwrite up */
23158c2ecf20Sopenharmony_ci		bp->dcbx_config_params.
23168c2ecf20Sopenharmony_ci			admin_priority_app_table[i].priority = up;
23178c2ecf20Sopenharmony_ci	else if (ff >= 0)
23188c2ecf20Sopenharmony_ci		/* not found use first-free */
23198c2ecf20Sopenharmony_ci		bnx2x_admin_app_set_ent(
23208c2ecf20Sopenharmony_ci			&bp->dcbx_config_params.admin_priority_app_table[ff],
23218c2ecf20Sopenharmony_ci			idtype, idval, up);
23228c2ecf20Sopenharmony_ci	else {
23238c2ecf20Sopenharmony_ci		/* app table is full */
23248c2ecf20Sopenharmony_ci		BNX2X_ERR("Application table is too large\n");
23258c2ecf20Sopenharmony_ci		return -EBUSY;
23268c2ecf20Sopenharmony_ci	}
23278c2ecf20Sopenharmony_ci
23288c2ecf20Sopenharmony_ci	/* up configured, if not 0 make sure feature is enabled */
23298c2ecf20Sopenharmony_ci	if (up)
23308c2ecf20Sopenharmony_ci		bp->dcbx_config_params.admin_application_priority_tx_enable = 1;
23318c2ecf20Sopenharmony_ci
23328c2ecf20Sopenharmony_ci	return 0;
23338c2ecf20Sopenharmony_ci}
23348c2ecf20Sopenharmony_ci
23358c2ecf20Sopenharmony_cistatic int bnx2x_dcbnl_set_app_up(struct net_device *netdev, u8 idtype,
23368c2ecf20Sopenharmony_ci				  u16 idval, u8 up)
23378c2ecf20Sopenharmony_ci{
23388c2ecf20Sopenharmony_ci	struct bnx2x *bp = netdev_priv(netdev);
23398c2ecf20Sopenharmony_ci
23408c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_DCB, "app_type %d, app_id %x, prio bitmap %d\n",
23418c2ecf20Sopenharmony_ci	   idtype, idval, up);
23428c2ecf20Sopenharmony_ci
23438c2ecf20Sopenharmony_ci	if (!bnx2x_dcbnl_set_valid(bp)) {
23448c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_DCB, "dcbnl call not valid\n");
23458c2ecf20Sopenharmony_ci		return -EINVAL;
23468c2ecf20Sopenharmony_ci	}
23478c2ecf20Sopenharmony_ci
23488c2ecf20Sopenharmony_ci	/* verify idtype */
23498c2ecf20Sopenharmony_ci	switch (idtype) {
23508c2ecf20Sopenharmony_ci	case DCB_APP_IDTYPE_ETHTYPE:
23518c2ecf20Sopenharmony_ci	case DCB_APP_IDTYPE_PORTNUM:
23528c2ecf20Sopenharmony_ci		break;
23538c2ecf20Sopenharmony_ci	default:
23548c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_DCB, "Wrong ID type\n");
23558c2ecf20Sopenharmony_ci		return -EINVAL;
23568c2ecf20Sopenharmony_ci	}
23578c2ecf20Sopenharmony_ci	return bnx2x_set_admin_app_up(bp, idtype, idval, up);
23588c2ecf20Sopenharmony_ci}
23598c2ecf20Sopenharmony_ci
23608c2ecf20Sopenharmony_cistatic u8 bnx2x_dcbnl_get_dcbx(struct net_device *netdev)
23618c2ecf20Sopenharmony_ci{
23628c2ecf20Sopenharmony_ci	struct bnx2x *bp = netdev_priv(netdev);
23638c2ecf20Sopenharmony_ci	u8 state;
23648c2ecf20Sopenharmony_ci
23658c2ecf20Sopenharmony_ci	state = DCB_CAP_DCBX_LLD_MANAGED | DCB_CAP_DCBX_VER_CEE;
23668c2ecf20Sopenharmony_ci
23678c2ecf20Sopenharmony_ci	if (bp->dcbx_enabled == BNX2X_DCBX_ENABLED_ON_NEG_OFF)
23688c2ecf20Sopenharmony_ci		state |= DCB_CAP_DCBX_STATIC;
23698c2ecf20Sopenharmony_ci
23708c2ecf20Sopenharmony_ci	return state;
23718c2ecf20Sopenharmony_ci}
23728c2ecf20Sopenharmony_ci
23738c2ecf20Sopenharmony_cistatic u8 bnx2x_dcbnl_set_dcbx(struct net_device *netdev, u8 state)
23748c2ecf20Sopenharmony_ci{
23758c2ecf20Sopenharmony_ci	struct bnx2x *bp = netdev_priv(netdev);
23768c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_DCB, "state = %02x\n", state);
23778c2ecf20Sopenharmony_ci
23788c2ecf20Sopenharmony_ci	/* set dcbx mode */
23798c2ecf20Sopenharmony_ci
23808c2ecf20Sopenharmony_ci	if ((state & BNX2X_DCBX_CAPS) != state) {
23818c2ecf20Sopenharmony_ci		BNX2X_ERR("Requested DCBX mode %x is beyond advertised capabilities\n",
23828c2ecf20Sopenharmony_ci			  state);
23838c2ecf20Sopenharmony_ci		return 1;
23848c2ecf20Sopenharmony_ci	}
23858c2ecf20Sopenharmony_ci
23868c2ecf20Sopenharmony_ci	if (bp->dcb_state != BNX2X_DCB_STATE_ON) {
23878c2ecf20Sopenharmony_ci		BNX2X_ERR("DCB turned off, DCBX configuration is invalid\n");
23888c2ecf20Sopenharmony_ci		return 1;
23898c2ecf20Sopenharmony_ci	}
23908c2ecf20Sopenharmony_ci
23918c2ecf20Sopenharmony_ci	if (state & DCB_CAP_DCBX_STATIC)
23928c2ecf20Sopenharmony_ci		bp->dcbx_enabled = BNX2X_DCBX_ENABLED_ON_NEG_OFF;
23938c2ecf20Sopenharmony_ci	else
23948c2ecf20Sopenharmony_ci		bp->dcbx_enabled = BNX2X_DCBX_ENABLED_ON_NEG_ON;
23958c2ecf20Sopenharmony_ci
23968c2ecf20Sopenharmony_ci	bp->dcbx_mode_uset = true;
23978c2ecf20Sopenharmony_ci	return 0;
23988c2ecf20Sopenharmony_ci}
23998c2ecf20Sopenharmony_ci
24008c2ecf20Sopenharmony_cistatic u8 bnx2x_dcbnl_get_featcfg(struct net_device *netdev, int featid,
24018c2ecf20Sopenharmony_ci				  u8 *flags)
24028c2ecf20Sopenharmony_ci{
24038c2ecf20Sopenharmony_ci	struct bnx2x *bp = netdev_priv(netdev);
24048c2ecf20Sopenharmony_ci	u8 rval = 0;
24058c2ecf20Sopenharmony_ci
24068c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_DCB, "featid %d\n", featid);
24078c2ecf20Sopenharmony_ci
24088c2ecf20Sopenharmony_ci	if (bp->dcb_state) {
24098c2ecf20Sopenharmony_ci		*flags = 0;
24108c2ecf20Sopenharmony_ci		switch (featid) {
24118c2ecf20Sopenharmony_ci		case DCB_FEATCFG_ATTR_PG:
24128c2ecf20Sopenharmony_ci			if (bp->dcbx_local_feat.ets.enabled)
24138c2ecf20Sopenharmony_ci				*flags |= DCB_FEATCFG_ENABLE;
24148c2ecf20Sopenharmony_ci			if (bp->dcbx_error & (DCBX_LOCAL_ETS_ERROR |
24158c2ecf20Sopenharmony_ci					      DCBX_REMOTE_MIB_ERROR))
24168c2ecf20Sopenharmony_ci				*flags |= DCB_FEATCFG_ERROR;
24178c2ecf20Sopenharmony_ci			break;
24188c2ecf20Sopenharmony_ci		case DCB_FEATCFG_ATTR_PFC:
24198c2ecf20Sopenharmony_ci			if (bp->dcbx_local_feat.pfc.enabled)
24208c2ecf20Sopenharmony_ci				*flags |= DCB_FEATCFG_ENABLE;
24218c2ecf20Sopenharmony_ci			if (bp->dcbx_error & (DCBX_LOCAL_PFC_ERROR |
24228c2ecf20Sopenharmony_ci					      DCBX_LOCAL_PFC_MISMATCH |
24238c2ecf20Sopenharmony_ci					      DCBX_REMOTE_MIB_ERROR))
24248c2ecf20Sopenharmony_ci				*flags |= DCB_FEATCFG_ERROR;
24258c2ecf20Sopenharmony_ci			break;
24268c2ecf20Sopenharmony_ci		case DCB_FEATCFG_ATTR_APP:
24278c2ecf20Sopenharmony_ci			if (bp->dcbx_local_feat.app.enabled)
24288c2ecf20Sopenharmony_ci				*flags |= DCB_FEATCFG_ENABLE;
24298c2ecf20Sopenharmony_ci			if (bp->dcbx_error & (DCBX_LOCAL_APP_ERROR |
24308c2ecf20Sopenharmony_ci					      DCBX_LOCAL_APP_MISMATCH |
24318c2ecf20Sopenharmony_ci					      DCBX_REMOTE_MIB_ERROR))
24328c2ecf20Sopenharmony_ci				*flags |= DCB_FEATCFG_ERROR;
24338c2ecf20Sopenharmony_ci			break;
24348c2ecf20Sopenharmony_ci		default:
24358c2ecf20Sopenharmony_ci			BNX2X_ERR("Non valid feature-ID\n");
24368c2ecf20Sopenharmony_ci			rval = 1;
24378c2ecf20Sopenharmony_ci			break;
24388c2ecf20Sopenharmony_ci		}
24398c2ecf20Sopenharmony_ci	} else {
24408c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_DCB, "DCB disabled\n");
24418c2ecf20Sopenharmony_ci		rval = 1;
24428c2ecf20Sopenharmony_ci	}
24438c2ecf20Sopenharmony_ci
24448c2ecf20Sopenharmony_ci	return rval;
24458c2ecf20Sopenharmony_ci}
24468c2ecf20Sopenharmony_ci
24478c2ecf20Sopenharmony_cistatic u8 bnx2x_dcbnl_set_featcfg(struct net_device *netdev, int featid,
24488c2ecf20Sopenharmony_ci				  u8 flags)
24498c2ecf20Sopenharmony_ci{
24508c2ecf20Sopenharmony_ci	struct bnx2x *bp = netdev_priv(netdev);
24518c2ecf20Sopenharmony_ci	u8 rval = 0;
24528c2ecf20Sopenharmony_ci
24538c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_DCB, "featid = %d flags = %02x\n", featid, flags);
24548c2ecf20Sopenharmony_ci
24558c2ecf20Sopenharmony_ci	/* ignore the 'advertise' flag */
24568c2ecf20Sopenharmony_ci	if (bnx2x_dcbnl_set_valid(bp)) {
24578c2ecf20Sopenharmony_ci		switch (featid) {
24588c2ecf20Sopenharmony_ci		case DCB_FEATCFG_ATTR_PG:
24598c2ecf20Sopenharmony_ci			bp->dcbx_config_params.admin_ets_enable =
24608c2ecf20Sopenharmony_ci				flags & DCB_FEATCFG_ENABLE ? 1 : 0;
24618c2ecf20Sopenharmony_ci			bp->dcbx_config_params.admin_ets_willing =
24628c2ecf20Sopenharmony_ci				flags & DCB_FEATCFG_WILLING ? 1 : 0;
24638c2ecf20Sopenharmony_ci			break;
24648c2ecf20Sopenharmony_ci		case DCB_FEATCFG_ATTR_PFC:
24658c2ecf20Sopenharmony_ci			bp->dcbx_config_params.admin_pfc_enable =
24668c2ecf20Sopenharmony_ci				flags & DCB_FEATCFG_ENABLE ? 1 : 0;
24678c2ecf20Sopenharmony_ci			bp->dcbx_config_params.admin_pfc_willing =
24688c2ecf20Sopenharmony_ci				flags & DCB_FEATCFG_WILLING ? 1 : 0;
24698c2ecf20Sopenharmony_ci			break;
24708c2ecf20Sopenharmony_ci		case DCB_FEATCFG_ATTR_APP:
24718c2ecf20Sopenharmony_ci			/* ignore enable, always enabled */
24728c2ecf20Sopenharmony_ci			bp->dcbx_config_params.admin_app_priority_willing =
24738c2ecf20Sopenharmony_ci				flags & DCB_FEATCFG_WILLING ? 1 : 0;
24748c2ecf20Sopenharmony_ci			break;
24758c2ecf20Sopenharmony_ci		default:
24768c2ecf20Sopenharmony_ci			BNX2X_ERR("Non valid feature-ID\n");
24778c2ecf20Sopenharmony_ci			rval = 1;
24788c2ecf20Sopenharmony_ci			break;
24798c2ecf20Sopenharmony_ci		}
24808c2ecf20Sopenharmony_ci	} else {
24818c2ecf20Sopenharmony_ci		DP(BNX2X_MSG_DCB, "dcbnl call not valid\n");
24828c2ecf20Sopenharmony_ci		rval = 1;
24838c2ecf20Sopenharmony_ci	}
24848c2ecf20Sopenharmony_ci
24858c2ecf20Sopenharmony_ci	return rval;
24868c2ecf20Sopenharmony_ci}
24878c2ecf20Sopenharmony_ci
24888c2ecf20Sopenharmony_cistatic int bnx2x_peer_appinfo(struct net_device *netdev,
24898c2ecf20Sopenharmony_ci			      struct dcb_peer_app_info *info, u16* app_count)
24908c2ecf20Sopenharmony_ci{
24918c2ecf20Sopenharmony_ci	int i;
24928c2ecf20Sopenharmony_ci	struct bnx2x *bp = netdev_priv(netdev);
24938c2ecf20Sopenharmony_ci
24948c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_DCB, "APP-INFO\n");
24958c2ecf20Sopenharmony_ci
24968c2ecf20Sopenharmony_ci	info->willing = (bp->dcbx_remote_flags & DCBX_APP_REM_WILLING) ?: 0;
24978c2ecf20Sopenharmony_ci	info->error = (bp->dcbx_remote_flags & DCBX_APP_RX_ERROR) ?: 0;
24988c2ecf20Sopenharmony_ci	*app_count = 0;
24998c2ecf20Sopenharmony_ci
25008c2ecf20Sopenharmony_ci	for (i = 0; i < DCBX_MAX_APP_PROTOCOL; i++)
25018c2ecf20Sopenharmony_ci		if (bp->dcbx_remote_feat.app.app_pri_tbl[i].appBitfield &
25028c2ecf20Sopenharmony_ci		    DCBX_APP_ENTRY_VALID)
25038c2ecf20Sopenharmony_ci			(*app_count)++;
25048c2ecf20Sopenharmony_ci	return 0;
25058c2ecf20Sopenharmony_ci}
25068c2ecf20Sopenharmony_ci
25078c2ecf20Sopenharmony_cistatic int bnx2x_peer_apptable(struct net_device *netdev,
25088c2ecf20Sopenharmony_ci			       struct dcb_app *table)
25098c2ecf20Sopenharmony_ci{
25108c2ecf20Sopenharmony_ci	int i, j;
25118c2ecf20Sopenharmony_ci	struct bnx2x *bp = netdev_priv(netdev);
25128c2ecf20Sopenharmony_ci
25138c2ecf20Sopenharmony_ci	DP(BNX2X_MSG_DCB, "APP-TABLE\n");
25148c2ecf20Sopenharmony_ci
25158c2ecf20Sopenharmony_ci	for (i = 0, j = 0; i < DCBX_MAX_APP_PROTOCOL; i++) {
25168c2ecf20Sopenharmony_ci		struct dcbx_app_priority_entry *ent =
25178c2ecf20Sopenharmony_ci			&bp->dcbx_remote_feat.app.app_pri_tbl[i];
25188c2ecf20Sopenharmony_ci
25198c2ecf20Sopenharmony_ci		if (ent->appBitfield & DCBX_APP_ENTRY_VALID) {
25208c2ecf20Sopenharmony_ci			table[j].selector = bnx2x_dcbx_dcbnl_app_idtype(ent);
25218c2ecf20Sopenharmony_ci			table[j].priority = bnx2x_dcbx_dcbnl_app_up(ent);
25228c2ecf20Sopenharmony_ci			table[j++].protocol = ent->app_id;
25238c2ecf20Sopenharmony_ci		}
25248c2ecf20Sopenharmony_ci	}
25258c2ecf20Sopenharmony_ci	return 0;
25268c2ecf20Sopenharmony_ci}
25278c2ecf20Sopenharmony_ci
25288c2ecf20Sopenharmony_cistatic int bnx2x_cee_peer_getpg(struct net_device *netdev, struct cee_pg *pg)
25298c2ecf20Sopenharmony_ci{
25308c2ecf20Sopenharmony_ci	int i;
25318c2ecf20Sopenharmony_ci	struct bnx2x *bp = netdev_priv(netdev);
25328c2ecf20Sopenharmony_ci
25338c2ecf20Sopenharmony_ci	pg->willing = (bp->dcbx_remote_flags & DCBX_ETS_REM_WILLING) ?: 0;
25348c2ecf20Sopenharmony_ci
25358c2ecf20Sopenharmony_ci	for (i = 0; i < CEE_DCBX_MAX_PGS; i++) {
25368c2ecf20Sopenharmony_ci		pg->pg_bw[i] =
25378c2ecf20Sopenharmony_ci			DCBX_PG_BW_GET(bp->dcbx_remote_feat.ets.pg_bw_tbl, i);
25388c2ecf20Sopenharmony_ci		pg->prio_pg[i] =
25398c2ecf20Sopenharmony_ci			DCBX_PRI_PG_GET(bp->dcbx_remote_feat.ets.pri_pg_tbl, i);
25408c2ecf20Sopenharmony_ci	}
25418c2ecf20Sopenharmony_ci	return 0;
25428c2ecf20Sopenharmony_ci}
25438c2ecf20Sopenharmony_ci
25448c2ecf20Sopenharmony_cistatic int bnx2x_cee_peer_getpfc(struct net_device *netdev,
25458c2ecf20Sopenharmony_ci				 struct cee_pfc *pfc)
25468c2ecf20Sopenharmony_ci{
25478c2ecf20Sopenharmony_ci	struct bnx2x *bp = netdev_priv(netdev);
25488c2ecf20Sopenharmony_ci	pfc->tcs_supported = bp->dcbx_remote_feat.pfc.pfc_caps;
25498c2ecf20Sopenharmony_ci	pfc->pfc_en = bp->dcbx_remote_feat.pfc.pri_en_bitmap;
25508c2ecf20Sopenharmony_ci	return 0;
25518c2ecf20Sopenharmony_ci}
25528c2ecf20Sopenharmony_ci
25538c2ecf20Sopenharmony_ciconst struct dcbnl_rtnl_ops bnx2x_dcbnl_ops = {
25548c2ecf20Sopenharmony_ci	.getstate		= bnx2x_dcbnl_get_state,
25558c2ecf20Sopenharmony_ci	.setstate		= bnx2x_dcbnl_set_state,
25568c2ecf20Sopenharmony_ci	.getpermhwaddr		= bnx2x_dcbnl_get_perm_hw_addr,
25578c2ecf20Sopenharmony_ci	.setpgtccfgtx		= bnx2x_dcbnl_set_pg_tccfg_tx,
25588c2ecf20Sopenharmony_ci	.setpgbwgcfgtx		= bnx2x_dcbnl_set_pg_bwgcfg_tx,
25598c2ecf20Sopenharmony_ci	.setpgtccfgrx		= bnx2x_dcbnl_set_pg_tccfg_rx,
25608c2ecf20Sopenharmony_ci	.setpgbwgcfgrx		= bnx2x_dcbnl_set_pg_bwgcfg_rx,
25618c2ecf20Sopenharmony_ci	.getpgtccfgtx		= bnx2x_dcbnl_get_pg_tccfg_tx,
25628c2ecf20Sopenharmony_ci	.getpgbwgcfgtx		= bnx2x_dcbnl_get_pg_bwgcfg_tx,
25638c2ecf20Sopenharmony_ci	.getpgtccfgrx		= bnx2x_dcbnl_get_pg_tccfg_rx,
25648c2ecf20Sopenharmony_ci	.getpgbwgcfgrx		= bnx2x_dcbnl_get_pg_bwgcfg_rx,
25658c2ecf20Sopenharmony_ci	.setpfccfg		= bnx2x_dcbnl_set_pfc_cfg,
25668c2ecf20Sopenharmony_ci	.getpfccfg		= bnx2x_dcbnl_get_pfc_cfg,
25678c2ecf20Sopenharmony_ci	.setall			= bnx2x_dcbnl_set_all,
25688c2ecf20Sopenharmony_ci	.getcap			= bnx2x_dcbnl_get_cap,
25698c2ecf20Sopenharmony_ci	.getnumtcs		= bnx2x_dcbnl_get_numtcs,
25708c2ecf20Sopenharmony_ci	.setnumtcs		= bnx2x_dcbnl_set_numtcs,
25718c2ecf20Sopenharmony_ci	.getpfcstate		= bnx2x_dcbnl_get_pfc_state,
25728c2ecf20Sopenharmony_ci	.setpfcstate		= bnx2x_dcbnl_set_pfc_state,
25738c2ecf20Sopenharmony_ci	.setapp			= bnx2x_dcbnl_set_app_up,
25748c2ecf20Sopenharmony_ci	.getdcbx		= bnx2x_dcbnl_get_dcbx,
25758c2ecf20Sopenharmony_ci	.setdcbx		= bnx2x_dcbnl_set_dcbx,
25768c2ecf20Sopenharmony_ci	.getfeatcfg		= bnx2x_dcbnl_get_featcfg,
25778c2ecf20Sopenharmony_ci	.setfeatcfg		= bnx2x_dcbnl_set_featcfg,
25788c2ecf20Sopenharmony_ci	.peer_getappinfo	= bnx2x_peer_appinfo,
25798c2ecf20Sopenharmony_ci	.peer_getapptable	= bnx2x_peer_apptable,
25808c2ecf20Sopenharmony_ci	.cee_peer_getpg		= bnx2x_cee_peer_getpg,
25818c2ecf20Sopenharmony_ci	.cee_peer_getpfc	= bnx2x_cee_peer_getpfc,
25828c2ecf20Sopenharmony_ci};
25838c2ecf20Sopenharmony_ci
25848c2ecf20Sopenharmony_ci#endif /* BCM_DCBNL */
2585