18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *  Copyright (C) 2013-2014 Chelsio Communications.  All rights reserved.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci *  Written by Anish Bhatt (anish@chelsio.com)
68c2ecf20Sopenharmony_ci *	       Casey Leedom (leedom@chelsio.com)
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include "cxgb4.h"
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci/* DCBx version control
128c2ecf20Sopenharmony_ci */
138c2ecf20Sopenharmony_ciconst char * const dcb_ver_array[] = {
148c2ecf20Sopenharmony_ci	"Unknown",
158c2ecf20Sopenharmony_ci	"DCBx-CIN",
168c2ecf20Sopenharmony_ci	"DCBx-CEE 1.01",
178c2ecf20Sopenharmony_ci	"DCBx-IEEE",
188c2ecf20Sopenharmony_ci	"", "", "",
198c2ecf20Sopenharmony_ci	"Auto Negotiated"
208c2ecf20Sopenharmony_ci};
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_cistatic inline bool cxgb4_dcb_state_synced(enum cxgb4_dcb_state state)
238c2ecf20Sopenharmony_ci{
248c2ecf20Sopenharmony_ci	if (state == CXGB4_DCB_STATE_FW_ALLSYNCED ||
258c2ecf20Sopenharmony_ci	    state == CXGB4_DCB_STATE_HOST)
268c2ecf20Sopenharmony_ci		return true;
278c2ecf20Sopenharmony_ci	else
288c2ecf20Sopenharmony_ci		return false;
298c2ecf20Sopenharmony_ci}
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci/* Initialize a port's Data Center Bridging state.
328c2ecf20Sopenharmony_ci */
338c2ecf20Sopenharmony_civoid cxgb4_dcb_state_init(struct net_device *dev)
348c2ecf20Sopenharmony_ci{
358c2ecf20Sopenharmony_ci	struct port_info *pi = netdev2pinfo(dev);
368c2ecf20Sopenharmony_ci	struct port_dcb_info *dcb = &pi->dcb;
378c2ecf20Sopenharmony_ci	int version_temp = dcb->dcb_version;
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci	memset(dcb, 0, sizeof(struct port_dcb_info));
408c2ecf20Sopenharmony_ci	dcb->state = CXGB4_DCB_STATE_START;
418c2ecf20Sopenharmony_ci	if (version_temp)
428c2ecf20Sopenharmony_ci		dcb->dcb_version = version_temp;
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci	netdev_dbg(dev, "%s: Initializing DCB state for port[%d]\n",
458c2ecf20Sopenharmony_ci		    __func__, pi->port_id);
468c2ecf20Sopenharmony_ci}
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_civoid cxgb4_dcb_version_init(struct net_device *dev)
498c2ecf20Sopenharmony_ci{
508c2ecf20Sopenharmony_ci	struct port_info *pi = netdev2pinfo(dev);
518c2ecf20Sopenharmony_ci	struct port_dcb_info *dcb = &pi->dcb;
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci	/* Any writes here are only done on kernels that exlicitly need
548c2ecf20Sopenharmony_ci	 * a specific version, say < 2.6.38 which only support CEE
558c2ecf20Sopenharmony_ci	 */
568c2ecf20Sopenharmony_ci	dcb->dcb_version = FW_PORT_DCB_VER_AUTO;
578c2ecf20Sopenharmony_ci}
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_cistatic void cxgb4_dcb_cleanup_apps(struct net_device *dev)
608c2ecf20Sopenharmony_ci{
618c2ecf20Sopenharmony_ci	struct port_info *pi = netdev2pinfo(dev);
628c2ecf20Sopenharmony_ci	struct adapter *adap = pi->adapter;
638c2ecf20Sopenharmony_ci	struct port_dcb_info *dcb = &pi->dcb;
648c2ecf20Sopenharmony_ci	struct dcb_app app;
658c2ecf20Sopenharmony_ci	int i, err;
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci	/* zero priority implies remove */
688c2ecf20Sopenharmony_ci	app.priority = 0;
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci	for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) {
718c2ecf20Sopenharmony_ci		/* Check if app list is exhausted */
728c2ecf20Sopenharmony_ci		if (!dcb->app_priority[i].protocolid)
738c2ecf20Sopenharmony_ci			break;
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci		app.protocol = dcb->app_priority[i].protocolid;
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci		if (dcb->dcb_version == FW_PORT_DCB_VER_IEEE) {
788c2ecf20Sopenharmony_ci			app.priority = dcb->app_priority[i].user_prio_map;
798c2ecf20Sopenharmony_ci			app.selector = dcb->app_priority[i].sel_field + 1;
808c2ecf20Sopenharmony_ci			err = dcb_ieee_delapp(dev, &app);
818c2ecf20Sopenharmony_ci		} else {
828c2ecf20Sopenharmony_ci			app.selector = !!(dcb->app_priority[i].sel_field);
838c2ecf20Sopenharmony_ci			err = dcb_setapp(dev, &app);
848c2ecf20Sopenharmony_ci		}
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci		if (err) {
878c2ecf20Sopenharmony_ci			dev_err(adap->pdev_dev,
888c2ecf20Sopenharmony_ci				"Failed DCB Clear %s Application Priority: sel=%d, prot=%d, , err=%d\n",
898c2ecf20Sopenharmony_ci				dcb_ver_array[dcb->dcb_version], app.selector,
908c2ecf20Sopenharmony_ci				app.protocol, -err);
918c2ecf20Sopenharmony_ci			break;
928c2ecf20Sopenharmony_ci		}
938c2ecf20Sopenharmony_ci	}
948c2ecf20Sopenharmony_ci}
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci/* Reset a port's Data Center Bridging state.  Typically used after a
978c2ecf20Sopenharmony_ci * Link Down event.
988c2ecf20Sopenharmony_ci */
998c2ecf20Sopenharmony_civoid cxgb4_dcb_reset(struct net_device *dev)
1008c2ecf20Sopenharmony_ci{
1018c2ecf20Sopenharmony_ci	cxgb4_dcb_cleanup_apps(dev);
1028c2ecf20Sopenharmony_ci	cxgb4_dcb_state_init(dev);
1038c2ecf20Sopenharmony_ci}
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci/* update the dcb port support, if version is IEEE then set it to
1068c2ecf20Sopenharmony_ci * FW_PORT_DCB_VER_IEEE and if DCB_CAP_DCBX_VER_CEE is already set then
1078c2ecf20Sopenharmony_ci * clear that. and if it is set to CEE then set dcb supported to
1088c2ecf20Sopenharmony_ci * DCB_CAP_DCBX_VER_CEE & if DCB_CAP_DCBX_VER_IEEE is set, clear it
1098c2ecf20Sopenharmony_ci */
1108c2ecf20Sopenharmony_cistatic inline void cxgb4_dcb_update_support(struct port_dcb_info *dcb)
1118c2ecf20Sopenharmony_ci{
1128c2ecf20Sopenharmony_ci	if (dcb->dcb_version == FW_PORT_DCB_VER_IEEE) {
1138c2ecf20Sopenharmony_ci		if (dcb->supported & DCB_CAP_DCBX_VER_CEE)
1148c2ecf20Sopenharmony_ci			dcb->supported &= ~DCB_CAP_DCBX_VER_CEE;
1158c2ecf20Sopenharmony_ci		dcb->supported |= DCB_CAP_DCBX_VER_IEEE;
1168c2ecf20Sopenharmony_ci	} else if (dcb->dcb_version == FW_PORT_DCB_VER_CEE1D01) {
1178c2ecf20Sopenharmony_ci		if (dcb->supported & DCB_CAP_DCBX_VER_IEEE)
1188c2ecf20Sopenharmony_ci			dcb->supported &= ~DCB_CAP_DCBX_VER_IEEE;
1198c2ecf20Sopenharmony_ci		dcb->supported |= DCB_CAP_DCBX_VER_CEE;
1208c2ecf20Sopenharmony_ci	}
1218c2ecf20Sopenharmony_ci}
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci/* Finite State machine for Data Center Bridging.
1248c2ecf20Sopenharmony_ci */
1258c2ecf20Sopenharmony_civoid cxgb4_dcb_state_fsm(struct net_device *dev,
1268c2ecf20Sopenharmony_ci			 enum cxgb4_dcb_state_input transition_to)
1278c2ecf20Sopenharmony_ci{
1288c2ecf20Sopenharmony_ci	struct port_info *pi = netdev2pinfo(dev);
1298c2ecf20Sopenharmony_ci	struct port_dcb_info *dcb = &pi->dcb;
1308c2ecf20Sopenharmony_ci	struct adapter *adap = pi->adapter;
1318c2ecf20Sopenharmony_ci	enum cxgb4_dcb_state current_state = dcb->state;
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ci	netdev_dbg(dev, "%s: State change from %d to %d for %s\n",
1348c2ecf20Sopenharmony_ci		    __func__, dcb->state, transition_to, dev->name);
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci	switch (current_state) {
1378c2ecf20Sopenharmony_ci	case CXGB4_DCB_STATE_START: {
1388c2ecf20Sopenharmony_ci		switch (transition_to) {
1398c2ecf20Sopenharmony_ci		case CXGB4_DCB_INPUT_FW_DISABLED: {
1408c2ecf20Sopenharmony_ci			/* we're going to use Host DCB */
1418c2ecf20Sopenharmony_ci			dcb->state = CXGB4_DCB_STATE_HOST;
1428c2ecf20Sopenharmony_ci			dcb->supported = CXGB4_DCBX_HOST_SUPPORT;
1438c2ecf20Sopenharmony_ci			break;
1448c2ecf20Sopenharmony_ci		}
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci		case CXGB4_DCB_INPUT_FW_ENABLED: {
1478c2ecf20Sopenharmony_ci			/* we're going to use Firmware DCB */
1488c2ecf20Sopenharmony_ci			dcb->state = CXGB4_DCB_STATE_FW_INCOMPLETE;
1498c2ecf20Sopenharmony_ci			dcb->supported = DCB_CAP_DCBX_LLD_MANAGED;
1508c2ecf20Sopenharmony_ci			if (dcb->dcb_version == FW_PORT_DCB_VER_IEEE)
1518c2ecf20Sopenharmony_ci				dcb->supported |= DCB_CAP_DCBX_VER_IEEE;
1528c2ecf20Sopenharmony_ci			else
1538c2ecf20Sopenharmony_ci				dcb->supported |= DCB_CAP_DCBX_VER_CEE;
1548c2ecf20Sopenharmony_ci			break;
1558c2ecf20Sopenharmony_ci		}
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci		case CXGB4_DCB_INPUT_FW_INCOMPLETE: {
1588c2ecf20Sopenharmony_ci			/* expected transition */
1598c2ecf20Sopenharmony_ci			break;
1608c2ecf20Sopenharmony_ci		}
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci		case CXGB4_DCB_INPUT_FW_ALLSYNCED: {
1638c2ecf20Sopenharmony_ci			dcb->state = CXGB4_DCB_STATE_FW_ALLSYNCED;
1648c2ecf20Sopenharmony_ci			break;
1658c2ecf20Sopenharmony_ci		}
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci		default:
1688c2ecf20Sopenharmony_ci			goto bad_state_input;
1698c2ecf20Sopenharmony_ci		}
1708c2ecf20Sopenharmony_ci		break;
1718c2ecf20Sopenharmony_ci	}
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci	case CXGB4_DCB_STATE_FW_INCOMPLETE: {
1748c2ecf20Sopenharmony_ci		if (transition_to != CXGB4_DCB_INPUT_FW_DISABLED) {
1758c2ecf20Sopenharmony_ci			/* during this CXGB4_DCB_STATE_FW_INCOMPLETE state,
1768c2ecf20Sopenharmony_ci			 * check if the dcb version is changed (there can be
1778c2ecf20Sopenharmony_ci			 * mismatch in default config & the negotiated switch
1788c2ecf20Sopenharmony_ci			 * configuration at FW, so update the dcb support
1798c2ecf20Sopenharmony_ci			 * accordingly.
1808c2ecf20Sopenharmony_ci			 */
1818c2ecf20Sopenharmony_ci			cxgb4_dcb_update_support(dcb);
1828c2ecf20Sopenharmony_ci		}
1838c2ecf20Sopenharmony_ci		switch (transition_to) {
1848c2ecf20Sopenharmony_ci		case CXGB4_DCB_INPUT_FW_ENABLED: {
1858c2ecf20Sopenharmony_ci			/* we're alreaady in firmware DCB mode */
1868c2ecf20Sopenharmony_ci			break;
1878c2ecf20Sopenharmony_ci		}
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci		case CXGB4_DCB_INPUT_FW_INCOMPLETE: {
1908c2ecf20Sopenharmony_ci			/* we're already incomplete */
1918c2ecf20Sopenharmony_ci			break;
1928c2ecf20Sopenharmony_ci		}
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci		case CXGB4_DCB_INPUT_FW_ALLSYNCED: {
1958c2ecf20Sopenharmony_ci			dcb->state = CXGB4_DCB_STATE_FW_ALLSYNCED;
1968c2ecf20Sopenharmony_ci			dcb->enabled = 1;
1978c2ecf20Sopenharmony_ci			linkwatch_fire_event(dev);
1988c2ecf20Sopenharmony_ci			break;
1998c2ecf20Sopenharmony_ci		}
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ci		default:
2028c2ecf20Sopenharmony_ci			goto bad_state_input;
2038c2ecf20Sopenharmony_ci		}
2048c2ecf20Sopenharmony_ci		break;
2058c2ecf20Sopenharmony_ci	}
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci	case CXGB4_DCB_STATE_FW_ALLSYNCED: {
2088c2ecf20Sopenharmony_ci		switch (transition_to) {
2098c2ecf20Sopenharmony_ci		case CXGB4_DCB_INPUT_FW_ENABLED: {
2108c2ecf20Sopenharmony_ci			/* we're alreaady in firmware DCB mode */
2118c2ecf20Sopenharmony_ci			break;
2128c2ecf20Sopenharmony_ci		}
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_ci		case CXGB4_DCB_INPUT_FW_INCOMPLETE: {
2158c2ecf20Sopenharmony_ci			/* We were successfully running with firmware DCB but
2168c2ecf20Sopenharmony_ci			 * now it's telling us that it's in an "incomplete
2178c2ecf20Sopenharmony_ci			 * state.  We need to reset back to a ground state
2188c2ecf20Sopenharmony_ci			 * of incomplete.
2198c2ecf20Sopenharmony_ci			 */
2208c2ecf20Sopenharmony_ci			cxgb4_dcb_reset(dev);
2218c2ecf20Sopenharmony_ci			dcb->state = CXGB4_DCB_STATE_FW_INCOMPLETE;
2228c2ecf20Sopenharmony_ci			dcb->supported = CXGB4_DCBX_FW_SUPPORT;
2238c2ecf20Sopenharmony_ci			linkwatch_fire_event(dev);
2248c2ecf20Sopenharmony_ci			break;
2258c2ecf20Sopenharmony_ci		}
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_ci		case CXGB4_DCB_INPUT_FW_ALLSYNCED: {
2288c2ecf20Sopenharmony_ci			/* we're already all sync'ed
2298c2ecf20Sopenharmony_ci			 * this is only applicable for IEEE or
2308c2ecf20Sopenharmony_ci			 * when another VI already completed negotiaton
2318c2ecf20Sopenharmony_ci			 */
2328c2ecf20Sopenharmony_ci			dcb->enabled = 1;
2338c2ecf20Sopenharmony_ci			linkwatch_fire_event(dev);
2348c2ecf20Sopenharmony_ci			break;
2358c2ecf20Sopenharmony_ci		}
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ci		default:
2388c2ecf20Sopenharmony_ci			goto bad_state_input;
2398c2ecf20Sopenharmony_ci		}
2408c2ecf20Sopenharmony_ci		break;
2418c2ecf20Sopenharmony_ci	}
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci	case CXGB4_DCB_STATE_HOST: {
2448c2ecf20Sopenharmony_ci		switch (transition_to) {
2458c2ecf20Sopenharmony_ci		case CXGB4_DCB_INPUT_FW_DISABLED: {
2468c2ecf20Sopenharmony_ci			/* we're alreaady in Host DCB mode */
2478c2ecf20Sopenharmony_ci			break;
2488c2ecf20Sopenharmony_ci		}
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci		default:
2518c2ecf20Sopenharmony_ci			goto bad_state_input;
2528c2ecf20Sopenharmony_ci		}
2538c2ecf20Sopenharmony_ci		break;
2548c2ecf20Sopenharmony_ci	}
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci	default:
2578c2ecf20Sopenharmony_ci		goto bad_state_transition;
2588c2ecf20Sopenharmony_ci	}
2598c2ecf20Sopenharmony_ci	return;
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_cibad_state_input:
2628c2ecf20Sopenharmony_ci	dev_err(adap->pdev_dev, "cxgb4_dcb_state_fsm: illegal input symbol %d\n",
2638c2ecf20Sopenharmony_ci		transition_to);
2648c2ecf20Sopenharmony_ci	return;
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_cibad_state_transition:
2678c2ecf20Sopenharmony_ci	dev_err(adap->pdev_dev, "cxgb4_dcb_state_fsm: bad state transition, state = %d, input = %d\n",
2688c2ecf20Sopenharmony_ci		current_state, transition_to);
2698c2ecf20Sopenharmony_ci}
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci/* Handle a DCB/DCBX update message from the firmware.
2728c2ecf20Sopenharmony_ci */
2738c2ecf20Sopenharmony_civoid cxgb4_dcb_handle_fw_update(struct adapter *adap,
2748c2ecf20Sopenharmony_ci				const struct fw_port_cmd *pcmd)
2758c2ecf20Sopenharmony_ci{
2768c2ecf20Sopenharmony_ci	const union fw_port_dcb *fwdcb = &pcmd->u.dcb;
2778c2ecf20Sopenharmony_ci	int port = FW_PORT_CMD_PORTID_G(be32_to_cpu(pcmd->op_to_portid));
2788c2ecf20Sopenharmony_ci	struct net_device *dev = adap->port[adap->chan_map[port]];
2798c2ecf20Sopenharmony_ci	struct port_info *pi = netdev_priv(dev);
2808c2ecf20Sopenharmony_ci	struct port_dcb_info *dcb = &pi->dcb;
2818c2ecf20Sopenharmony_ci	int dcb_type = pcmd->u.dcb.pgid.type;
2828c2ecf20Sopenharmony_ci	int dcb_running_version;
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci	/* Handle Firmware DCB Control messages separately since they drive
2858c2ecf20Sopenharmony_ci	 * our state machine.
2868c2ecf20Sopenharmony_ci	 */
2878c2ecf20Sopenharmony_ci	if (dcb_type == FW_PORT_DCB_TYPE_CONTROL) {
2888c2ecf20Sopenharmony_ci		enum cxgb4_dcb_state_input input =
2898c2ecf20Sopenharmony_ci			((pcmd->u.dcb.control.all_syncd_pkd &
2908c2ecf20Sopenharmony_ci			  FW_PORT_CMD_ALL_SYNCD_F)
2918c2ecf20Sopenharmony_ci			 ? CXGB4_DCB_INPUT_FW_ALLSYNCED
2928c2ecf20Sopenharmony_ci			 : CXGB4_DCB_INPUT_FW_INCOMPLETE);
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci		if (dcb->dcb_version != FW_PORT_DCB_VER_UNKNOWN) {
2958c2ecf20Sopenharmony_ci			dcb_running_version = FW_PORT_CMD_DCB_VERSION_G(
2968c2ecf20Sopenharmony_ci				be16_to_cpu(
2978c2ecf20Sopenharmony_ci				pcmd->u.dcb.control.dcb_version_to_app_state));
2988c2ecf20Sopenharmony_ci			if (dcb_running_version == FW_PORT_DCB_VER_CEE1D01 ||
2998c2ecf20Sopenharmony_ci			    dcb_running_version == FW_PORT_DCB_VER_IEEE) {
3008c2ecf20Sopenharmony_ci				dcb->dcb_version = dcb_running_version;
3018c2ecf20Sopenharmony_ci				dev_warn(adap->pdev_dev, "Interface %s is running %s\n",
3028c2ecf20Sopenharmony_ci					 dev->name,
3038c2ecf20Sopenharmony_ci					 dcb_ver_array[dcb->dcb_version]);
3048c2ecf20Sopenharmony_ci			} else {
3058c2ecf20Sopenharmony_ci				dev_warn(adap->pdev_dev,
3068c2ecf20Sopenharmony_ci					 "Something screwed up, requested firmware for %s, but firmware returned %s instead\n",
3078c2ecf20Sopenharmony_ci					 dcb_ver_array[dcb->dcb_version],
3088c2ecf20Sopenharmony_ci					 dcb_ver_array[dcb_running_version]);
3098c2ecf20Sopenharmony_ci				dcb->dcb_version = FW_PORT_DCB_VER_UNKNOWN;
3108c2ecf20Sopenharmony_ci			}
3118c2ecf20Sopenharmony_ci		}
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_ci		cxgb4_dcb_state_fsm(dev, input);
3148c2ecf20Sopenharmony_ci		return;
3158c2ecf20Sopenharmony_ci	}
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci	/* It's weird, and almost certainly an error, to get Firmware DCB
3188c2ecf20Sopenharmony_ci	 * messages when we either haven't been told whether we're going to be
3198c2ecf20Sopenharmony_ci	 * doing Host or Firmware DCB; and even worse when we've been told
3208c2ecf20Sopenharmony_ci	 * that we're doing Host DCB!
3218c2ecf20Sopenharmony_ci	 */
3228c2ecf20Sopenharmony_ci	if (dcb->state == CXGB4_DCB_STATE_START ||
3238c2ecf20Sopenharmony_ci	    dcb->state == CXGB4_DCB_STATE_HOST) {
3248c2ecf20Sopenharmony_ci		dev_err(adap->pdev_dev, "Receiving Firmware DCB messages in State %d\n",
3258c2ecf20Sopenharmony_ci			dcb->state);
3268c2ecf20Sopenharmony_ci		return;
3278c2ecf20Sopenharmony_ci	}
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_ci	/* Now handle the general Firmware DCB update messages ...
3308c2ecf20Sopenharmony_ci	 */
3318c2ecf20Sopenharmony_ci	switch (dcb_type) {
3328c2ecf20Sopenharmony_ci	case FW_PORT_DCB_TYPE_PGID:
3338c2ecf20Sopenharmony_ci		dcb->pgid = be32_to_cpu(fwdcb->pgid.pgid);
3348c2ecf20Sopenharmony_ci		dcb->msgs |= CXGB4_DCB_FW_PGID;
3358c2ecf20Sopenharmony_ci		break;
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_ci	case FW_PORT_DCB_TYPE_PGRATE:
3388c2ecf20Sopenharmony_ci		dcb->pg_num_tcs_supported = fwdcb->pgrate.num_tcs_supported;
3398c2ecf20Sopenharmony_ci		memcpy(dcb->pgrate, &fwdcb->pgrate.pgrate,
3408c2ecf20Sopenharmony_ci		       sizeof(dcb->pgrate));
3418c2ecf20Sopenharmony_ci		memcpy(dcb->tsa, &fwdcb->pgrate.tsa,
3428c2ecf20Sopenharmony_ci		       sizeof(dcb->tsa));
3438c2ecf20Sopenharmony_ci		dcb->msgs |= CXGB4_DCB_FW_PGRATE;
3448c2ecf20Sopenharmony_ci		if (dcb->msgs & CXGB4_DCB_FW_PGID)
3458c2ecf20Sopenharmony_ci			IEEE_FAUX_SYNC(dev, dcb);
3468c2ecf20Sopenharmony_ci		break;
3478c2ecf20Sopenharmony_ci
3488c2ecf20Sopenharmony_ci	case FW_PORT_DCB_TYPE_PRIORATE:
3498c2ecf20Sopenharmony_ci		memcpy(dcb->priorate, &fwdcb->priorate.strict_priorate,
3508c2ecf20Sopenharmony_ci		       sizeof(dcb->priorate));
3518c2ecf20Sopenharmony_ci		dcb->msgs |= CXGB4_DCB_FW_PRIORATE;
3528c2ecf20Sopenharmony_ci		break;
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_ci	case FW_PORT_DCB_TYPE_PFC:
3558c2ecf20Sopenharmony_ci		dcb->pfcen = fwdcb->pfc.pfcen;
3568c2ecf20Sopenharmony_ci		dcb->pfc_num_tcs_supported = fwdcb->pfc.max_pfc_tcs;
3578c2ecf20Sopenharmony_ci		dcb->msgs |= CXGB4_DCB_FW_PFC;
3588c2ecf20Sopenharmony_ci		IEEE_FAUX_SYNC(dev, dcb);
3598c2ecf20Sopenharmony_ci		break;
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_ci	case FW_PORT_DCB_TYPE_APP_ID: {
3628c2ecf20Sopenharmony_ci		const struct fw_port_app_priority *fwap = &fwdcb->app_priority;
3638c2ecf20Sopenharmony_ci		int idx = fwap->idx;
3648c2ecf20Sopenharmony_ci		struct app_priority *ap = &dcb->app_priority[idx];
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_ci		struct dcb_app app = {
3678c2ecf20Sopenharmony_ci			.protocol = be16_to_cpu(fwap->protocolid),
3688c2ecf20Sopenharmony_ci		};
3698c2ecf20Sopenharmony_ci		int err;
3708c2ecf20Sopenharmony_ci
3718c2ecf20Sopenharmony_ci		/* Convert from firmware format to relevant format
3728c2ecf20Sopenharmony_ci		 * when using app selector
3738c2ecf20Sopenharmony_ci		 */
3748c2ecf20Sopenharmony_ci		if (dcb->dcb_version == FW_PORT_DCB_VER_IEEE) {
3758c2ecf20Sopenharmony_ci			app.selector = (fwap->sel_field + 1);
3768c2ecf20Sopenharmony_ci			app.priority = ffs(fwap->user_prio_map) - 1;
3778c2ecf20Sopenharmony_ci			err = dcb_ieee_setapp(dev, &app);
3788c2ecf20Sopenharmony_ci			IEEE_FAUX_SYNC(dev, dcb);
3798c2ecf20Sopenharmony_ci		} else {
3808c2ecf20Sopenharmony_ci			/* Default is CEE */
3818c2ecf20Sopenharmony_ci			app.selector = !!(fwap->sel_field);
3828c2ecf20Sopenharmony_ci			app.priority = fwap->user_prio_map;
3838c2ecf20Sopenharmony_ci			err = dcb_setapp(dev, &app);
3848c2ecf20Sopenharmony_ci		}
3858c2ecf20Sopenharmony_ci
3868c2ecf20Sopenharmony_ci		if (err)
3878c2ecf20Sopenharmony_ci			dev_err(adap->pdev_dev,
3888c2ecf20Sopenharmony_ci				"Failed DCB Set Application Priority: sel=%d, prot=%d, prio=%d, err=%d\n",
3898c2ecf20Sopenharmony_ci				app.selector, app.protocol, app.priority, -err);
3908c2ecf20Sopenharmony_ci
3918c2ecf20Sopenharmony_ci		ap->user_prio_map = fwap->user_prio_map;
3928c2ecf20Sopenharmony_ci		ap->sel_field = fwap->sel_field;
3938c2ecf20Sopenharmony_ci		ap->protocolid = be16_to_cpu(fwap->protocolid);
3948c2ecf20Sopenharmony_ci		dcb->msgs |= CXGB4_DCB_FW_APP_ID;
3958c2ecf20Sopenharmony_ci		break;
3968c2ecf20Sopenharmony_ci	}
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_ci	default:
3998c2ecf20Sopenharmony_ci		dev_err(adap->pdev_dev, "Unknown DCB update type received %x\n",
4008c2ecf20Sopenharmony_ci			dcb_type);
4018c2ecf20Sopenharmony_ci		break;
4028c2ecf20Sopenharmony_ci	}
4038c2ecf20Sopenharmony_ci}
4048c2ecf20Sopenharmony_ci
4058c2ecf20Sopenharmony_ci/* Data Center Bridging netlink operations.
4068c2ecf20Sopenharmony_ci */
4078c2ecf20Sopenharmony_ci
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_ci/* Get current DCB enabled/disabled state.
4108c2ecf20Sopenharmony_ci */
4118c2ecf20Sopenharmony_cistatic u8 cxgb4_getstate(struct net_device *dev)
4128c2ecf20Sopenharmony_ci{
4138c2ecf20Sopenharmony_ci	struct port_info *pi = netdev2pinfo(dev);
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_ci	return pi->dcb.enabled;
4168c2ecf20Sopenharmony_ci}
4178c2ecf20Sopenharmony_ci
4188c2ecf20Sopenharmony_ci/* Set DCB enabled/disabled.
4198c2ecf20Sopenharmony_ci */
4208c2ecf20Sopenharmony_cistatic u8 cxgb4_setstate(struct net_device *dev, u8 enabled)
4218c2ecf20Sopenharmony_ci{
4228c2ecf20Sopenharmony_ci	struct port_info *pi = netdev2pinfo(dev);
4238c2ecf20Sopenharmony_ci
4248c2ecf20Sopenharmony_ci	/* If DCBx is host-managed, dcb is enabled by outside lldp agents */
4258c2ecf20Sopenharmony_ci	if (pi->dcb.state == CXGB4_DCB_STATE_HOST) {
4268c2ecf20Sopenharmony_ci		pi->dcb.enabled = enabled;
4278c2ecf20Sopenharmony_ci		return 0;
4288c2ecf20Sopenharmony_ci	}
4298c2ecf20Sopenharmony_ci
4308c2ecf20Sopenharmony_ci	/* Firmware doesn't provide any mechanism to control the DCB state.
4318c2ecf20Sopenharmony_ci	 */
4328c2ecf20Sopenharmony_ci	if (enabled != (pi->dcb.state == CXGB4_DCB_STATE_FW_ALLSYNCED))
4338c2ecf20Sopenharmony_ci		return 1;
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_ci	return 0;
4368c2ecf20Sopenharmony_ci}
4378c2ecf20Sopenharmony_ci
4388c2ecf20Sopenharmony_cistatic void cxgb4_getpgtccfg(struct net_device *dev, int tc,
4398c2ecf20Sopenharmony_ci			     u8 *prio_type, u8 *pgid, u8 *bw_per,
4408c2ecf20Sopenharmony_ci			     u8 *up_tc_map, int local)
4418c2ecf20Sopenharmony_ci{
4428c2ecf20Sopenharmony_ci	struct fw_port_cmd pcmd;
4438c2ecf20Sopenharmony_ci	struct port_info *pi = netdev2pinfo(dev);
4448c2ecf20Sopenharmony_ci	struct adapter *adap = pi->adapter;
4458c2ecf20Sopenharmony_ci	int err;
4468c2ecf20Sopenharmony_ci
4478c2ecf20Sopenharmony_ci	*prio_type = *pgid = *bw_per = *up_tc_map = 0;
4488c2ecf20Sopenharmony_ci
4498c2ecf20Sopenharmony_ci	if (local)
4508c2ecf20Sopenharmony_ci		INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
4518c2ecf20Sopenharmony_ci	else
4528c2ecf20Sopenharmony_ci		INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ci	pcmd.u.dcb.pgid.type = FW_PORT_DCB_TYPE_PGID;
4558c2ecf20Sopenharmony_ci	err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
4568c2ecf20Sopenharmony_ci	if (err != FW_PORT_DCB_CFG_SUCCESS) {
4578c2ecf20Sopenharmony_ci		dev_err(adap->pdev_dev, "DCB read PGID failed with %d\n", -err);
4588c2ecf20Sopenharmony_ci		return;
4598c2ecf20Sopenharmony_ci	}
4608c2ecf20Sopenharmony_ci	*pgid = (be32_to_cpu(pcmd.u.dcb.pgid.pgid) >> (tc * 4)) & 0xf;
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_ci	if (local)
4638c2ecf20Sopenharmony_ci		INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
4648c2ecf20Sopenharmony_ci	else
4658c2ecf20Sopenharmony_ci		INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
4668c2ecf20Sopenharmony_ci	pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE;
4678c2ecf20Sopenharmony_ci	err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
4688c2ecf20Sopenharmony_ci	if (err != FW_PORT_DCB_CFG_SUCCESS) {
4698c2ecf20Sopenharmony_ci		dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n",
4708c2ecf20Sopenharmony_ci			-err);
4718c2ecf20Sopenharmony_ci		return;
4728c2ecf20Sopenharmony_ci	}
4738c2ecf20Sopenharmony_ci
4748c2ecf20Sopenharmony_ci	*bw_per = pcmd.u.dcb.pgrate.pgrate[*pgid];
4758c2ecf20Sopenharmony_ci	*up_tc_map = (1 << tc);
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ci	/* prio_type is link strict */
4788c2ecf20Sopenharmony_ci	if (*pgid != 0xF)
4798c2ecf20Sopenharmony_ci		*prio_type = 0x2;
4808c2ecf20Sopenharmony_ci}
4818c2ecf20Sopenharmony_ci
4828c2ecf20Sopenharmony_cistatic void cxgb4_getpgtccfg_tx(struct net_device *dev, int tc,
4838c2ecf20Sopenharmony_ci				u8 *prio_type, u8 *pgid, u8 *bw_per,
4848c2ecf20Sopenharmony_ci				u8 *up_tc_map)
4858c2ecf20Sopenharmony_ci{
4868c2ecf20Sopenharmony_ci	/* tc 0 is written at MSB position */
4878c2ecf20Sopenharmony_ci	return cxgb4_getpgtccfg(dev, (7 - tc), prio_type, pgid, bw_per,
4888c2ecf20Sopenharmony_ci				up_tc_map, 1);
4898c2ecf20Sopenharmony_ci}
4908c2ecf20Sopenharmony_ci
4918c2ecf20Sopenharmony_ci
4928c2ecf20Sopenharmony_cistatic void cxgb4_getpgtccfg_rx(struct net_device *dev, int tc,
4938c2ecf20Sopenharmony_ci				u8 *prio_type, u8 *pgid, u8 *bw_per,
4948c2ecf20Sopenharmony_ci				u8 *up_tc_map)
4958c2ecf20Sopenharmony_ci{
4968c2ecf20Sopenharmony_ci	/* tc 0 is written at MSB position */
4978c2ecf20Sopenharmony_ci	return cxgb4_getpgtccfg(dev, (7 - tc), prio_type, pgid, bw_per,
4988c2ecf20Sopenharmony_ci				up_tc_map, 0);
4998c2ecf20Sopenharmony_ci}
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_cistatic void cxgb4_setpgtccfg_tx(struct net_device *dev, int tc,
5028c2ecf20Sopenharmony_ci				u8 prio_type, u8 pgid, u8 bw_per,
5038c2ecf20Sopenharmony_ci				u8 up_tc_map)
5048c2ecf20Sopenharmony_ci{
5058c2ecf20Sopenharmony_ci	struct fw_port_cmd pcmd;
5068c2ecf20Sopenharmony_ci	struct port_info *pi = netdev2pinfo(dev);
5078c2ecf20Sopenharmony_ci	struct adapter *adap = pi->adapter;
5088c2ecf20Sopenharmony_ci	int fw_tc = 7 - tc;
5098c2ecf20Sopenharmony_ci	u32 _pgid;
5108c2ecf20Sopenharmony_ci	int err;
5118c2ecf20Sopenharmony_ci
5128c2ecf20Sopenharmony_ci	if (pgid == DCB_ATTR_VALUE_UNDEFINED)
5138c2ecf20Sopenharmony_ci		return;
5148c2ecf20Sopenharmony_ci	if (bw_per == DCB_ATTR_VALUE_UNDEFINED)
5158c2ecf20Sopenharmony_ci		return;
5168c2ecf20Sopenharmony_ci
5178c2ecf20Sopenharmony_ci	INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
5188c2ecf20Sopenharmony_ci	pcmd.u.dcb.pgid.type = FW_PORT_DCB_TYPE_PGID;
5198c2ecf20Sopenharmony_ci
5208c2ecf20Sopenharmony_ci	err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
5218c2ecf20Sopenharmony_ci	if (err != FW_PORT_DCB_CFG_SUCCESS) {
5228c2ecf20Sopenharmony_ci		dev_err(adap->pdev_dev, "DCB read PGID failed with %d\n", -err);
5238c2ecf20Sopenharmony_ci		return;
5248c2ecf20Sopenharmony_ci	}
5258c2ecf20Sopenharmony_ci
5268c2ecf20Sopenharmony_ci	_pgid = be32_to_cpu(pcmd.u.dcb.pgid.pgid);
5278c2ecf20Sopenharmony_ci	_pgid &= ~(0xF << (fw_tc * 4));
5288c2ecf20Sopenharmony_ci	_pgid |= pgid << (fw_tc * 4);
5298c2ecf20Sopenharmony_ci	pcmd.u.dcb.pgid.pgid = cpu_to_be32(_pgid);
5308c2ecf20Sopenharmony_ci
5318c2ecf20Sopenharmony_ci	INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id);
5328c2ecf20Sopenharmony_ci
5338c2ecf20Sopenharmony_ci	err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
5348c2ecf20Sopenharmony_ci	if (err != FW_PORT_DCB_CFG_SUCCESS) {
5358c2ecf20Sopenharmony_ci		dev_err(adap->pdev_dev, "DCB write PGID failed with %d\n",
5368c2ecf20Sopenharmony_ci			-err);
5378c2ecf20Sopenharmony_ci		return;
5388c2ecf20Sopenharmony_ci	}
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_ci	memset(&pcmd, 0, sizeof(struct fw_port_cmd));
5418c2ecf20Sopenharmony_ci
5428c2ecf20Sopenharmony_ci	INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
5438c2ecf20Sopenharmony_ci	pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE;
5448c2ecf20Sopenharmony_ci
5458c2ecf20Sopenharmony_ci	err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
5468c2ecf20Sopenharmony_ci	if (err != FW_PORT_DCB_CFG_SUCCESS) {
5478c2ecf20Sopenharmony_ci		dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n",
5488c2ecf20Sopenharmony_ci			-err);
5498c2ecf20Sopenharmony_ci		return;
5508c2ecf20Sopenharmony_ci	}
5518c2ecf20Sopenharmony_ci
5528c2ecf20Sopenharmony_ci	pcmd.u.dcb.pgrate.pgrate[pgid] = bw_per;
5538c2ecf20Sopenharmony_ci
5548c2ecf20Sopenharmony_ci	INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id);
5558c2ecf20Sopenharmony_ci	if (pi->dcb.state == CXGB4_DCB_STATE_HOST)
5568c2ecf20Sopenharmony_ci		pcmd.op_to_portid |= cpu_to_be32(FW_PORT_CMD_APPLY_F);
5578c2ecf20Sopenharmony_ci
5588c2ecf20Sopenharmony_ci	err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
5598c2ecf20Sopenharmony_ci	if (err != FW_PORT_DCB_CFG_SUCCESS)
5608c2ecf20Sopenharmony_ci		dev_err(adap->pdev_dev, "DCB write PGRATE failed with %d\n",
5618c2ecf20Sopenharmony_ci			-err);
5628c2ecf20Sopenharmony_ci}
5638c2ecf20Sopenharmony_ci
5648c2ecf20Sopenharmony_cistatic void cxgb4_getpgbwgcfg(struct net_device *dev, int pgid, u8 *bw_per,
5658c2ecf20Sopenharmony_ci			      int local)
5668c2ecf20Sopenharmony_ci{
5678c2ecf20Sopenharmony_ci	struct fw_port_cmd pcmd;
5688c2ecf20Sopenharmony_ci	struct port_info *pi = netdev2pinfo(dev);
5698c2ecf20Sopenharmony_ci	struct adapter *adap = pi->adapter;
5708c2ecf20Sopenharmony_ci	int err;
5718c2ecf20Sopenharmony_ci
5728c2ecf20Sopenharmony_ci	if (local)
5738c2ecf20Sopenharmony_ci		INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
5748c2ecf20Sopenharmony_ci	else
5758c2ecf20Sopenharmony_ci		INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
5768c2ecf20Sopenharmony_ci
5778c2ecf20Sopenharmony_ci	pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE;
5788c2ecf20Sopenharmony_ci	err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
5798c2ecf20Sopenharmony_ci	if (err != FW_PORT_DCB_CFG_SUCCESS) {
5808c2ecf20Sopenharmony_ci		dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n",
5818c2ecf20Sopenharmony_ci			-err);
5828c2ecf20Sopenharmony_ci		return;
5838c2ecf20Sopenharmony_ci	}
5848c2ecf20Sopenharmony_ci
5858c2ecf20Sopenharmony_ci	*bw_per = pcmd.u.dcb.pgrate.pgrate[pgid];
5868c2ecf20Sopenharmony_ci}
5878c2ecf20Sopenharmony_ci
5888c2ecf20Sopenharmony_cistatic void cxgb4_getpgbwgcfg_tx(struct net_device *dev, int pgid, u8 *bw_per)
5898c2ecf20Sopenharmony_ci{
5908c2ecf20Sopenharmony_ci	return cxgb4_getpgbwgcfg(dev, pgid, bw_per, 1);
5918c2ecf20Sopenharmony_ci}
5928c2ecf20Sopenharmony_ci
5938c2ecf20Sopenharmony_cistatic void cxgb4_getpgbwgcfg_rx(struct net_device *dev, int pgid, u8 *bw_per)
5948c2ecf20Sopenharmony_ci{
5958c2ecf20Sopenharmony_ci	return cxgb4_getpgbwgcfg(dev, pgid, bw_per, 0);
5968c2ecf20Sopenharmony_ci}
5978c2ecf20Sopenharmony_ci
5988c2ecf20Sopenharmony_cistatic void cxgb4_setpgbwgcfg_tx(struct net_device *dev, int pgid,
5998c2ecf20Sopenharmony_ci				 u8 bw_per)
6008c2ecf20Sopenharmony_ci{
6018c2ecf20Sopenharmony_ci	struct fw_port_cmd pcmd;
6028c2ecf20Sopenharmony_ci	struct port_info *pi = netdev2pinfo(dev);
6038c2ecf20Sopenharmony_ci	struct adapter *adap = pi->adapter;
6048c2ecf20Sopenharmony_ci	int err;
6058c2ecf20Sopenharmony_ci
6068c2ecf20Sopenharmony_ci	INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
6078c2ecf20Sopenharmony_ci	pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE;
6088c2ecf20Sopenharmony_ci
6098c2ecf20Sopenharmony_ci	err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
6108c2ecf20Sopenharmony_ci	if (err != FW_PORT_DCB_CFG_SUCCESS) {
6118c2ecf20Sopenharmony_ci		dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n",
6128c2ecf20Sopenharmony_ci			-err);
6138c2ecf20Sopenharmony_ci		return;
6148c2ecf20Sopenharmony_ci	}
6158c2ecf20Sopenharmony_ci
6168c2ecf20Sopenharmony_ci	pcmd.u.dcb.pgrate.pgrate[pgid] = bw_per;
6178c2ecf20Sopenharmony_ci
6188c2ecf20Sopenharmony_ci	INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id);
6198c2ecf20Sopenharmony_ci	if (pi->dcb.state == CXGB4_DCB_STATE_HOST)
6208c2ecf20Sopenharmony_ci		pcmd.op_to_portid |= cpu_to_be32(FW_PORT_CMD_APPLY_F);
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_ci	err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
6238c2ecf20Sopenharmony_ci
6248c2ecf20Sopenharmony_ci	if (err != FW_PORT_DCB_CFG_SUCCESS)
6258c2ecf20Sopenharmony_ci		dev_err(adap->pdev_dev, "DCB write PGRATE failed with %d\n",
6268c2ecf20Sopenharmony_ci			-err);
6278c2ecf20Sopenharmony_ci}
6288c2ecf20Sopenharmony_ci
6298c2ecf20Sopenharmony_ci/* Return whether the specified Traffic Class Priority has Priority Pause
6308c2ecf20Sopenharmony_ci * Frames enabled.
6318c2ecf20Sopenharmony_ci */
6328c2ecf20Sopenharmony_cistatic void cxgb4_getpfccfg(struct net_device *dev, int priority, u8 *pfccfg)
6338c2ecf20Sopenharmony_ci{
6348c2ecf20Sopenharmony_ci	struct port_info *pi = netdev2pinfo(dev);
6358c2ecf20Sopenharmony_ci	struct port_dcb_info *dcb = &pi->dcb;
6368c2ecf20Sopenharmony_ci
6378c2ecf20Sopenharmony_ci	if (!cxgb4_dcb_state_synced(dcb->state) ||
6388c2ecf20Sopenharmony_ci	    priority >= CXGB4_MAX_PRIORITY)
6398c2ecf20Sopenharmony_ci		*pfccfg = 0;
6408c2ecf20Sopenharmony_ci	else
6418c2ecf20Sopenharmony_ci		*pfccfg = (pi->dcb.pfcen >> (7 - priority)) & 1;
6428c2ecf20Sopenharmony_ci}
6438c2ecf20Sopenharmony_ci
6448c2ecf20Sopenharmony_ci/* Enable/disable Priority Pause Frames for the specified Traffic Class
6458c2ecf20Sopenharmony_ci * Priority.
6468c2ecf20Sopenharmony_ci */
6478c2ecf20Sopenharmony_cistatic void cxgb4_setpfccfg(struct net_device *dev, int priority, u8 pfccfg)
6488c2ecf20Sopenharmony_ci{
6498c2ecf20Sopenharmony_ci	struct fw_port_cmd pcmd;
6508c2ecf20Sopenharmony_ci	struct port_info *pi = netdev2pinfo(dev);
6518c2ecf20Sopenharmony_ci	struct adapter *adap = pi->adapter;
6528c2ecf20Sopenharmony_ci	int err;
6538c2ecf20Sopenharmony_ci
6548c2ecf20Sopenharmony_ci	if (!cxgb4_dcb_state_synced(pi->dcb.state) ||
6558c2ecf20Sopenharmony_ci	    priority >= CXGB4_MAX_PRIORITY)
6568c2ecf20Sopenharmony_ci		return;
6578c2ecf20Sopenharmony_ci
6588c2ecf20Sopenharmony_ci	INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id);
6598c2ecf20Sopenharmony_ci	if (pi->dcb.state == CXGB4_DCB_STATE_HOST)
6608c2ecf20Sopenharmony_ci		pcmd.op_to_portid |= cpu_to_be32(FW_PORT_CMD_APPLY_F);
6618c2ecf20Sopenharmony_ci
6628c2ecf20Sopenharmony_ci	pcmd.u.dcb.pfc.type = FW_PORT_DCB_TYPE_PFC;
6638c2ecf20Sopenharmony_ci	pcmd.u.dcb.pfc.pfcen = pi->dcb.pfcen;
6648c2ecf20Sopenharmony_ci
6658c2ecf20Sopenharmony_ci	if (pfccfg)
6668c2ecf20Sopenharmony_ci		pcmd.u.dcb.pfc.pfcen |= (1 << (7 - priority));
6678c2ecf20Sopenharmony_ci	else
6688c2ecf20Sopenharmony_ci		pcmd.u.dcb.pfc.pfcen &= (~(1 << (7 - priority)));
6698c2ecf20Sopenharmony_ci
6708c2ecf20Sopenharmony_ci	err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
6718c2ecf20Sopenharmony_ci	if (err != FW_PORT_DCB_CFG_SUCCESS) {
6728c2ecf20Sopenharmony_ci		dev_err(adap->pdev_dev, "DCB PFC write failed with %d\n", -err);
6738c2ecf20Sopenharmony_ci		return;
6748c2ecf20Sopenharmony_ci	}
6758c2ecf20Sopenharmony_ci
6768c2ecf20Sopenharmony_ci	pi->dcb.pfcen = pcmd.u.dcb.pfc.pfcen;
6778c2ecf20Sopenharmony_ci}
6788c2ecf20Sopenharmony_ci
6798c2ecf20Sopenharmony_cistatic u8 cxgb4_setall(struct net_device *dev)
6808c2ecf20Sopenharmony_ci{
6818c2ecf20Sopenharmony_ci	return 0;
6828c2ecf20Sopenharmony_ci}
6838c2ecf20Sopenharmony_ci
6848c2ecf20Sopenharmony_ci/* Return DCB capabilities.
6858c2ecf20Sopenharmony_ci */
6868c2ecf20Sopenharmony_cistatic u8 cxgb4_getcap(struct net_device *dev, int cap_id, u8 *caps)
6878c2ecf20Sopenharmony_ci{
6888c2ecf20Sopenharmony_ci	struct port_info *pi = netdev2pinfo(dev);
6898c2ecf20Sopenharmony_ci
6908c2ecf20Sopenharmony_ci	switch (cap_id) {
6918c2ecf20Sopenharmony_ci	case DCB_CAP_ATTR_PG:
6928c2ecf20Sopenharmony_ci	case DCB_CAP_ATTR_PFC:
6938c2ecf20Sopenharmony_ci		*caps = true;
6948c2ecf20Sopenharmony_ci		break;
6958c2ecf20Sopenharmony_ci
6968c2ecf20Sopenharmony_ci	case DCB_CAP_ATTR_PG_TCS:
6978c2ecf20Sopenharmony_ci		/* 8 priorities for PG represented by bitmap */
6988c2ecf20Sopenharmony_ci		*caps = 0x80;
6998c2ecf20Sopenharmony_ci		break;
7008c2ecf20Sopenharmony_ci
7018c2ecf20Sopenharmony_ci	case DCB_CAP_ATTR_PFC_TCS:
7028c2ecf20Sopenharmony_ci		/* 8 priorities for PFC represented by bitmap */
7038c2ecf20Sopenharmony_ci		*caps = 0x80;
7048c2ecf20Sopenharmony_ci		break;
7058c2ecf20Sopenharmony_ci
7068c2ecf20Sopenharmony_ci	case DCB_CAP_ATTR_GSP:
7078c2ecf20Sopenharmony_ci		*caps = true;
7088c2ecf20Sopenharmony_ci		break;
7098c2ecf20Sopenharmony_ci
7108c2ecf20Sopenharmony_ci	case DCB_CAP_ATTR_UP2TC:
7118c2ecf20Sopenharmony_ci	case DCB_CAP_ATTR_BCN:
7128c2ecf20Sopenharmony_ci		*caps = false;
7138c2ecf20Sopenharmony_ci		break;
7148c2ecf20Sopenharmony_ci
7158c2ecf20Sopenharmony_ci	case DCB_CAP_ATTR_DCBX:
7168c2ecf20Sopenharmony_ci		*caps = pi->dcb.supported;
7178c2ecf20Sopenharmony_ci		break;
7188c2ecf20Sopenharmony_ci
7198c2ecf20Sopenharmony_ci	default:
7208c2ecf20Sopenharmony_ci		*caps = false;
7218c2ecf20Sopenharmony_ci	}
7228c2ecf20Sopenharmony_ci
7238c2ecf20Sopenharmony_ci	return 0;
7248c2ecf20Sopenharmony_ci}
7258c2ecf20Sopenharmony_ci
7268c2ecf20Sopenharmony_ci/* Return the number of Traffic Classes for the indicated Traffic Class ID.
7278c2ecf20Sopenharmony_ci */
7288c2ecf20Sopenharmony_cistatic int cxgb4_getnumtcs(struct net_device *dev, int tcs_id, u8 *num)
7298c2ecf20Sopenharmony_ci{
7308c2ecf20Sopenharmony_ci	struct port_info *pi = netdev2pinfo(dev);
7318c2ecf20Sopenharmony_ci
7328c2ecf20Sopenharmony_ci	switch (tcs_id) {
7338c2ecf20Sopenharmony_ci	case DCB_NUMTCS_ATTR_PG:
7348c2ecf20Sopenharmony_ci		if (pi->dcb.msgs & CXGB4_DCB_FW_PGRATE)
7358c2ecf20Sopenharmony_ci			*num = pi->dcb.pg_num_tcs_supported;
7368c2ecf20Sopenharmony_ci		else
7378c2ecf20Sopenharmony_ci			*num = 0x8;
7388c2ecf20Sopenharmony_ci		break;
7398c2ecf20Sopenharmony_ci
7408c2ecf20Sopenharmony_ci	case DCB_NUMTCS_ATTR_PFC:
7418c2ecf20Sopenharmony_ci		*num = 0x8;
7428c2ecf20Sopenharmony_ci		break;
7438c2ecf20Sopenharmony_ci
7448c2ecf20Sopenharmony_ci	default:
7458c2ecf20Sopenharmony_ci		return -EINVAL;
7468c2ecf20Sopenharmony_ci	}
7478c2ecf20Sopenharmony_ci
7488c2ecf20Sopenharmony_ci	return 0;
7498c2ecf20Sopenharmony_ci}
7508c2ecf20Sopenharmony_ci
7518c2ecf20Sopenharmony_ci/* Set the number of Traffic Classes supported for the indicated Traffic Class
7528c2ecf20Sopenharmony_ci * ID.
7538c2ecf20Sopenharmony_ci */
7548c2ecf20Sopenharmony_cistatic int cxgb4_setnumtcs(struct net_device *dev, int tcs_id, u8 num)
7558c2ecf20Sopenharmony_ci{
7568c2ecf20Sopenharmony_ci	/* Setting the number of Traffic Classes isn't supported.
7578c2ecf20Sopenharmony_ci	 */
7588c2ecf20Sopenharmony_ci	return -ENOSYS;
7598c2ecf20Sopenharmony_ci}
7608c2ecf20Sopenharmony_ci
7618c2ecf20Sopenharmony_ci/* Return whether Priority Flow Control is enabled.  */
7628c2ecf20Sopenharmony_cistatic u8 cxgb4_getpfcstate(struct net_device *dev)
7638c2ecf20Sopenharmony_ci{
7648c2ecf20Sopenharmony_ci	struct port_info *pi = netdev2pinfo(dev);
7658c2ecf20Sopenharmony_ci
7668c2ecf20Sopenharmony_ci	if (!cxgb4_dcb_state_synced(pi->dcb.state))
7678c2ecf20Sopenharmony_ci		return false;
7688c2ecf20Sopenharmony_ci
7698c2ecf20Sopenharmony_ci	return pi->dcb.pfcen != 0;
7708c2ecf20Sopenharmony_ci}
7718c2ecf20Sopenharmony_ci
7728c2ecf20Sopenharmony_ci/* Enable/disable Priority Flow Control. */
7738c2ecf20Sopenharmony_cistatic void cxgb4_setpfcstate(struct net_device *dev, u8 state)
7748c2ecf20Sopenharmony_ci{
7758c2ecf20Sopenharmony_ci	/* We can't enable/disable Priority Flow Control but we also can't
7768c2ecf20Sopenharmony_ci	 * return an error ...
7778c2ecf20Sopenharmony_ci	 */
7788c2ecf20Sopenharmony_ci}
7798c2ecf20Sopenharmony_ci
7808c2ecf20Sopenharmony_ci/* Return the Application User Priority Map associated with the specified
7818c2ecf20Sopenharmony_ci * Application ID.
7828c2ecf20Sopenharmony_ci */
7838c2ecf20Sopenharmony_cistatic int __cxgb4_getapp(struct net_device *dev, u8 app_idtype, u16 app_id,
7848c2ecf20Sopenharmony_ci			  int peer)
7858c2ecf20Sopenharmony_ci{
7868c2ecf20Sopenharmony_ci	struct port_info *pi = netdev2pinfo(dev);
7878c2ecf20Sopenharmony_ci	struct adapter *adap = pi->adapter;
7888c2ecf20Sopenharmony_ci	int i;
7898c2ecf20Sopenharmony_ci
7908c2ecf20Sopenharmony_ci	if (!cxgb4_dcb_state_synced(pi->dcb.state))
7918c2ecf20Sopenharmony_ci		return 0;
7928c2ecf20Sopenharmony_ci
7938c2ecf20Sopenharmony_ci	for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) {
7948c2ecf20Sopenharmony_ci		struct fw_port_cmd pcmd;
7958c2ecf20Sopenharmony_ci		int err;
7968c2ecf20Sopenharmony_ci
7978c2ecf20Sopenharmony_ci		if (peer)
7988c2ecf20Sopenharmony_ci			INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
7998c2ecf20Sopenharmony_ci		else
8008c2ecf20Sopenharmony_ci			INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
8018c2ecf20Sopenharmony_ci
8028c2ecf20Sopenharmony_ci		pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID;
8038c2ecf20Sopenharmony_ci		pcmd.u.dcb.app_priority.idx = i;
8048c2ecf20Sopenharmony_ci
8058c2ecf20Sopenharmony_ci		err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
8068c2ecf20Sopenharmony_ci		if (err != FW_PORT_DCB_CFG_SUCCESS) {
8078c2ecf20Sopenharmony_ci			dev_err(adap->pdev_dev, "DCB APP read failed with %d\n",
8088c2ecf20Sopenharmony_ci				-err);
8098c2ecf20Sopenharmony_ci			return err;
8108c2ecf20Sopenharmony_ci		}
8118c2ecf20Sopenharmony_ci		if (be16_to_cpu(pcmd.u.dcb.app_priority.protocolid) == app_id)
8128c2ecf20Sopenharmony_ci			if (pcmd.u.dcb.app_priority.sel_field == app_idtype)
8138c2ecf20Sopenharmony_ci				return pcmd.u.dcb.app_priority.user_prio_map;
8148c2ecf20Sopenharmony_ci
8158c2ecf20Sopenharmony_ci		/* exhausted app list */
8168c2ecf20Sopenharmony_ci		if (!pcmd.u.dcb.app_priority.protocolid)
8178c2ecf20Sopenharmony_ci			break;
8188c2ecf20Sopenharmony_ci	}
8198c2ecf20Sopenharmony_ci
8208c2ecf20Sopenharmony_ci	return -EEXIST;
8218c2ecf20Sopenharmony_ci}
8228c2ecf20Sopenharmony_ci
8238c2ecf20Sopenharmony_ci/* Return the Application User Priority Map associated with the specified
8248c2ecf20Sopenharmony_ci * Application ID.
8258c2ecf20Sopenharmony_ci */
8268c2ecf20Sopenharmony_cistatic int cxgb4_getapp(struct net_device *dev, u8 app_idtype, u16 app_id)
8278c2ecf20Sopenharmony_ci{
8288c2ecf20Sopenharmony_ci	/* Convert app_idtype to firmware format before querying */
8298c2ecf20Sopenharmony_ci	return __cxgb4_getapp(dev, app_idtype == DCB_APP_IDTYPE_ETHTYPE ?
8308c2ecf20Sopenharmony_ci			      app_idtype : 3, app_id, 0);
8318c2ecf20Sopenharmony_ci}
8328c2ecf20Sopenharmony_ci
8338c2ecf20Sopenharmony_ci/* Write a new Application User Priority Map for the specified Application ID
8348c2ecf20Sopenharmony_ci */
8358c2ecf20Sopenharmony_cistatic int __cxgb4_setapp(struct net_device *dev, u8 app_idtype, u16 app_id,
8368c2ecf20Sopenharmony_ci			  u8 app_prio)
8378c2ecf20Sopenharmony_ci{
8388c2ecf20Sopenharmony_ci	struct fw_port_cmd pcmd;
8398c2ecf20Sopenharmony_ci	struct port_info *pi = netdev2pinfo(dev);
8408c2ecf20Sopenharmony_ci	struct adapter *adap = pi->adapter;
8418c2ecf20Sopenharmony_ci	int i, err;
8428c2ecf20Sopenharmony_ci
8438c2ecf20Sopenharmony_ci
8448c2ecf20Sopenharmony_ci	if (!cxgb4_dcb_state_synced(pi->dcb.state))
8458c2ecf20Sopenharmony_ci		return -EINVAL;
8468c2ecf20Sopenharmony_ci
8478c2ecf20Sopenharmony_ci	/* DCB info gets thrown away on link up */
8488c2ecf20Sopenharmony_ci	if (!netif_carrier_ok(dev))
8498c2ecf20Sopenharmony_ci		return -ENOLINK;
8508c2ecf20Sopenharmony_ci
8518c2ecf20Sopenharmony_ci	for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) {
8528c2ecf20Sopenharmony_ci		INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
8538c2ecf20Sopenharmony_ci		pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID;
8548c2ecf20Sopenharmony_ci		pcmd.u.dcb.app_priority.idx = i;
8558c2ecf20Sopenharmony_ci		err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
8568c2ecf20Sopenharmony_ci
8578c2ecf20Sopenharmony_ci		if (err != FW_PORT_DCB_CFG_SUCCESS) {
8588c2ecf20Sopenharmony_ci			dev_err(adap->pdev_dev, "DCB app table read failed with %d\n",
8598c2ecf20Sopenharmony_ci				-err);
8608c2ecf20Sopenharmony_ci			return err;
8618c2ecf20Sopenharmony_ci		}
8628c2ecf20Sopenharmony_ci		if (be16_to_cpu(pcmd.u.dcb.app_priority.protocolid) == app_id) {
8638c2ecf20Sopenharmony_ci			/* overwrite existing app table */
8648c2ecf20Sopenharmony_ci			pcmd.u.dcb.app_priority.protocolid = 0;
8658c2ecf20Sopenharmony_ci			break;
8668c2ecf20Sopenharmony_ci		}
8678c2ecf20Sopenharmony_ci		/* find first empty slot */
8688c2ecf20Sopenharmony_ci		if (!pcmd.u.dcb.app_priority.protocolid)
8698c2ecf20Sopenharmony_ci			break;
8708c2ecf20Sopenharmony_ci	}
8718c2ecf20Sopenharmony_ci
8728c2ecf20Sopenharmony_ci	if (i == CXGB4_MAX_DCBX_APP_SUPPORTED) {
8738c2ecf20Sopenharmony_ci		/* no empty slots available */
8748c2ecf20Sopenharmony_ci		dev_err(adap->pdev_dev, "DCB app table full\n");
8758c2ecf20Sopenharmony_ci		return -EBUSY;
8768c2ecf20Sopenharmony_ci	}
8778c2ecf20Sopenharmony_ci
8788c2ecf20Sopenharmony_ci	/* write out new app table entry */
8798c2ecf20Sopenharmony_ci	INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id);
8808c2ecf20Sopenharmony_ci	if (pi->dcb.state == CXGB4_DCB_STATE_HOST)
8818c2ecf20Sopenharmony_ci		pcmd.op_to_portid |= cpu_to_be32(FW_PORT_CMD_APPLY_F);
8828c2ecf20Sopenharmony_ci
8838c2ecf20Sopenharmony_ci	pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID;
8848c2ecf20Sopenharmony_ci	pcmd.u.dcb.app_priority.protocolid = cpu_to_be16(app_id);
8858c2ecf20Sopenharmony_ci	pcmd.u.dcb.app_priority.sel_field = app_idtype;
8868c2ecf20Sopenharmony_ci	pcmd.u.dcb.app_priority.user_prio_map = app_prio;
8878c2ecf20Sopenharmony_ci	pcmd.u.dcb.app_priority.idx = i;
8888c2ecf20Sopenharmony_ci
8898c2ecf20Sopenharmony_ci	err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
8908c2ecf20Sopenharmony_ci	if (err != FW_PORT_DCB_CFG_SUCCESS) {
8918c2ecf20Sopenharmony_ci		dev_err(adap->pdev_dev, "DCB app table write failed with %d\n",
8928c2ecf20Sopenharmony_ci			-err);
8938c2ecf20Sopenharmony_ci		return err;
8948c2ecf20Sopenharmony_ci	}
8958c2ecf20Sopenharmony_ci
8968c2ecf20Sopenharmony_ci	return 0;
8978c2ecf20Sopenharmony_ci}
8988c2ecf20Sopenharmony_ci
8998c2ecf20Sopenharmony_ci/* Priority for CEE inside dcb_app is bitmask, with 0 being an invalid value */
9008c2ecf20Sopenharmony_cistatic int cxgb4_setapp(struct net_device *dev, u8 app_idtype, u16 app_id,
9018c2ecf20Sopenharmony_ci			u8 app_prio)
9028c2ecf20Sopenharmony_ci{
9038c2ecf20Sopenharmony_ci	int ret;
9048c2ecf20Sopenharmony_ci	struct dcb_app app = {
9058c2ecf20Sopenharmony_ci		.selector = app_idtype,
9068c2ecf20Sopenharmony_ci		.protocol = app_id,
9078c2ecf20Sopenharmony_ci		.priority = app_prio,
9088c2ecf20Sopenharmony_ci	};
9098c2ecf20Sopenharmony_ci
9108c2ecf20Sopenharmony_ci	if (app_idtype != DCB_APP_IDTYPE_ETHTYPE &&
9118c2ecf20Sopenharmony_ci	    app_idtype != DCB_APP_IDTYPE_PORTNUM)
9128c2ecf20Sopenharmony_ci		return -EINVAL;
9138c2ecf20Sopenharmony_ci
9148c2ecf20Sopenharmony_ci	/* Convert app_idtype to a format that firmware understands */
9158c2ecf20Sopenharmony_ci	ret = __cxgb4_setapp(dev, app_idtype == DCB_APP_IDTYPE_ETHTYPE ?
9168c2ecf20Sopenharmony_ci			      app_idtype : 3, app_id, app_prio);
9178c2ecf20Sopenharmony_ci	if (ret)
9188c2ecf20Sopenharmony_ci		return ret;
9198c2ecf20Sopenharmony_ci
9208c2ecf20Sopenharmony_ci	return dcb_setapp(dev, &app);
9218c2ecf20Sopenharmony_ci}
9228c2ecf20Sopenharmony_ci
9238c2ecf20Sopenharmony_ci/* Return whether IEEE Data Center Bridging has been negotiated.
9248c2ecf20Sopenharmony_ci */
9258c2ecf20Sopenharmony_cistatic inline int
9268c2ecf20Sopenharmony_cicxgb4_ieee_negotiation_complete(struct net_device *dev,
9278c2ecf20Sopenharmony_ci				enum cxgb4_dcb_fw_msgs dcb_subtype)
9288c2ecf20Sopenharmony_ci{
9298c2ecf20Sopenharmony_ci	struct port_info *pi = netdev2pinfo(dev);
9308c2ecf20Sopenharmony_ci	struct port_dcb_info *dcb = &pi->dcb;
9318c2ecf20Sopenharmony_ci
9328c2ecf20Sopenharmony_ci	if (dcb->state == CXGB4_DCB_STATE_FW_ALLSYNCED)
9338c2ecf20Sopenharmony_ci		if (dcb_subtype && !(dcb->msgs & dcb_subtype))
9348c2ecf20Sopenharmony_ci			return 0;
9358c2ecf20Sopenharmony_ci
9368c2ecf20Sopenharmony_ci	return (cxgb4_dcb_state_synced(dcb->state) &&
9378c2ecf20Sopenharmony_ci		(dcb->supported & DCB_CAP_DCBX_VER_IEEE));
9388c2ecf20Sopenharmony_ci}
9398c2ecf20Sopenharmony_ci
9408c2ecf20Sopenharmony_cistatic int cxgb4_ieee_read_ets(struct net_device *dev, struct ieee_ets *ets,
9418c2ecf20Sopenharmony_ci			       int local)
9428c2ecf20Sopenharmony_ci{
9438c2ecf20Sopenharmony_ci	struct port_info *pi = netdev2pinfo(dev);
9448c2ecf20Sopenharmony_ci	struct port_dcb_info *dcb = &pi->dcb;
9458c2ecf20Sopenharmony_ci	struct adapter *adap = pi->adapter;
9468c2ecf20Sopenharmony_ci	uint32_t tc_info;
9478c2ecf20Sopenharmony_ci	struct fw_port_cmd pcmd;
9488c2ecf20Sopenharmony_ci	int i, bwg, err;
9498c2ecf20Sopenharmony_ci
9508c2ecf20Sopenharmony_ci	if (!(dcb->msgs & (CXGB4_DCB_FW_PGID | CXGB4_DCB_FW_PGRATE)))
9518c2ecf20Sopenharmony_ci		return 0;
9528c2ecf20Sopenharmony_ci
9538c2ecf20Sopenharmony_ci	ets->ets_cap =  dcb->pg_num_tcs_supported;
9548c2ecf20Sopenharmony_ci
9558c2ecf20Sopenharmony_ci	if (local) {
9568c2ecf20Sopenharmony_ci		ets->willing = 1;
9578c2ecf20Sopenharmony_ci		INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
9588c2ecf20Sopenharmony_ci	} else {
9598c2ecf20Sopenharmony_ci		INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
9608c2ecf20Sopenharmony_ci	}
9618c2ecf20Sopenharmony_ci
9628c2ecf20Sopenharmony_ci	pcmd.u.dcb.pgid.type = FW_PORT_DCB_TYPE_PGID;
9638c2ecf20Sopenharmony_ci	err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
9648c2ecf20Sopenharmony_ci	if (err != FW_PORT_DCB_CFG_SUCCESS) {
9658c2ecf20Sopenharmony_ci		dev_err(adap->pdev_dev, "DCB read PGID failed with %d\n", -err);
9668c2ecf20Sopenharmony_ci		return err;
9678c2ecf20Sopenharmony_ci	}
9688c2ecf20Sopenharmony_ci
9698c2ecf20Sopenharmony_ci	tc_info = be32_to_cpu(pcmd.u.dcb.pgid.pgid);
9708c2ecf20Sopenharmony_ci
9718c2ecf20Sopenharmony_ci	if (local)
9728c2ecf20Sopenharmony_ci		INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
9738c2ecf20Sopenharmony_ci	else
9748c2ecf20Sopenharmony_ci		INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
9758c2ecf20Sopenharmony_ci
9768c2ecf20Sopenharmony_ci	pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE;
9778c2ecf20Sopenharmony_ci	err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
9788c2ecf20Sopenharmony_ci	if (err != FW_PORT_DCB_CFG_SUCCESS) {
9798c2ecf20Sopenharmony_ci		dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n",
9808c2ecf20Sopenharmony_ci			-err);
9818c2ecf20Sopenharmony_ci		return err;
9828c2ecf20Sopenharmony_ci	}
9838c2ecf20Sopenharmony_ci
9848c2ecf20Sopenharmony_ci	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
9858c2ecf20Sopenharmony_ci		bwg = (tc_info >> ((7 - i) * 4)) & 0xF;
9868c2ecf20Sopenharmony_ci		ets->prio_tc[i] = bwg;
9878c2ecf20Sopenharmony_ci		ets->tc_tx_bw[i] = pcmd.u.dcb.pgrate.pgrate[i];
9888c2ecf20Sopenharmony_ci		ets->tc_rx_bw[i] = ets->tc_tx_bw[i];
9898c2ecf20Sopenharmony_ci		ets->tc_tsa[i] = pcmd.u.dcb.pgrate.tsa[i];
9908c2ecf20Sopenharmony_ci	}
9918c2ecf20Sopenharmony_ci
9928c2ecf20Sopenharmony_ci	return 0;
9938c2ecf20Sopenharmony_ci}
9948c2ecf20Sopenharmony_ci
9958c2ecf20Sopenharmony_cistatic int cxgb4_ieee_get_ets(struct net_device *dev, struct ieee_ets *ets)
9968c2ecf20Sopenharmony_ci{
9978c2ecf20Sopenharmony_ci	return cxgb4_ieee_read_ets(dev, ets, 1);
9988c2ecf20Sopenharmony_ci}
9998c2ecf20Sopenharmony_ci
10008c2ecf20Sopenharmony_ci/* We reuse this for peer PFC as well, as we can't have it enabled one way */
10018c2ecf20Sopenharmony_cistatic int cxgb4_ieee_get_pfc(struct net_device *dev, struct ieee_pfc *pfc)
10028c2ecf20Sopenharmony_ci{
10038c2ecf20Sopenharmony_ci	struct port_info *pi = netdev2pinfo(dev);
10048c2ecf20Sopenharmony_ci	struct port_dcb_info *dcb = &pi->dcb;
10058c2ecf20Sopenharmony_ci
10068c2ecf20Sopenharmony_ci	memset(pfc, 0, sizeof(struct ieee_pfc));
10078c2ecf20Sopenharmony_ci
10088c2ecf20Sopenharmony_ci	if (!(dcb->msgs & CXGB4_DCB_FW_PFC))
10098c2ecf20Sopenharmony_ci		return 0;
10108c2ecf20Sopenharmony_ci
10118c2ecf20Sopenharmony_ci	pfc->pfc_cap = dcb->pfc_num_tcs_supported;
10128c2ecf20Sopenharmony_ci	pfc->pfc_en = bitswap_1(dcb->pfcen);
10138c2ecf20Sopenharmony_ci
10148c2ecf20Sopenharmony_ci	return 0;
10158c2ecf20Sopenharmony_ci}
10168c2ecf20Sopenharmony_ci
10178c2ecf20Sopenharmony_cistatic int cxgb4_ieee_peer_ets(struct net_device *dev, struct ieee_ets *ets)
10188c2ecf20Sopenharmony_ci{
10198c2ecf20Sopenharmony_ci	return cxgb4_ieee_read_ets(dev, ets, 0);
10208c2ecf20Sopenharmony_ci}
10218c2ecf20Sopenharmony_ci
10228c2ecf20Sopenharmony_ci/* Fill in the Application User Priority Map associated with the
10238c2ecf20Sopenharmony_ci * specified Application.
10248c2ecf20Sopenharmony_ci * Priority for IEEE dcb_app is an integer, with 0 being a valid value
10258c2ecf20Sopenharmony_ci */
10268c2ecf20Sopenharmony_cistatic int cxgb4_ieee_getapp(struct net_device *dev, struct dcb_app *app)
10278c2ecf20Sopenharmony_ci{
10288c2ecf20Sopenharmony_ci	int prio;
10298c2ecf20Sopenharmony_ci
10308c2ecf20Sopenharmony_ci	if (!cxgb4_ieee_negotiation_complete(dev, CXGB4_DCB_FW_APP_ID))
10318c2ecf20Sopenharmony_ci		return -EINVAL;
10328c2ecf20Sopenharmony_ci	if (!(app->selector && app->protocol))
10338c2ecf20Sopenharmony_ci		return -EINVAL;
10348c2ecf20Sopenharmony_ci
10358c2ecf20Sopenharmony_ci	/* Try querying firmware first, use firmware format */
10368c2ecf20Sopenharmony_ci	prio = __cxgb4_getapp(dev, app->selector - 1, app->protocol, 0);
10378c2ecf20Sopenharmony_ci
10388c2ecf20Sopenharmony_ci	if (prio < 0)
10398c2ecf20Sopenharmony_ci		prio = dcb_ieee_getapp_mask(dev, app);
10408c2ecf20Sopenharmony_ci
10418c2ecf20Sopenharmony_ci	app->priority = ffs(prio) - 1;
10428c2ecf20Sopenharmony_ci	return 0;
10438c2ecf20Sopenharmony_ci}
10448c2ecf20Sopenharmony_ci
10458c2ecf20Sopenharmony_ci/* Write a new Application User Priority Map for the specified Application ID.
10468c2ecf20Sopenharmony_ci * Priority for IEEE dcb_app is an integer, with 0 being a valid value
10478c2ecf20Sopenharmony_ci */
10488c2ecf20Sopenharmony_cistatic int cxgb4_ieee_setapp(struct net_device *dev, struct dcb_app *app)
10498c2ecf20Sopenharmony_ci{
10508c2ecf20Sopenharmony_ci	int ret;
10518c2ecf20Sopenharmony_ci
10528c2ecf20Sopenharmony_ci	if (!cxgb4_ieee_negotiation_complete(dev, CXGB4_DCB_FW_APP_ID))
10538c2ecf20Sopenharmony_ci		return -EINVAL;
10548c2ecf20Sopenharmony_ci	if (!(app->selector && app->protocol))
10558c2ecf20Sopenharmony_ci		return -EINVAL;
10568c2ecf20Sopenharmony_ci
10578c2ecf20Sopenharmony_ci	if (!(app->selector > IEEE_8021QAZ_APP_SEL_ETHERTYPE  &&
10588c2ecf20Sopenharmony_ci	      app->selector < IEEE_8021QAZ_APP_SEL_ANY))
10598c2ecf20Sopenharmony_ci		return -EINVAL;
10608c2ecf20Sopenharmony_ci
10618c2ecf20Sopenharmony_ci	/* change selector to a format that firmware understands */
10628c2ecf20Sopenharmony_ci	ret = __cxgb4_setapp(dev, app->selector - 1, app->protocol,
10638c2ecf20Sopenharmony_ci			     (1 << app->priority));
10648c2ecf20Sopenharmony_ci	if (ret)
10658c2ecf20Sopenharmony_ci		return ret;
10668c2ecf20Sopenharmony_ci
10678c2ecf20Sopenharmony_ci	return dcb_ieee_setapp(dev, app);
10688c2ecf20Sopenharmony_ci}
10698c2ecf20Sopenharmony_ci
10708c2ecf20Sopenharmony_ci/* Return our DCBX parameters.
10718c2ecf20Sopenharmony_ci */
10728c2ecf20Sopenharmony_cistatic u8 cxgb4_getdcbx(struct net_device *dev)
10738c2ecf20Sopenharmony_ci{
10748c2ecf20Sopenharmony_ci	struct port_info *pi = netdev2pinfo(dev);
10758c2ecf20Sopenharmony_ci
10768c2ecf20Sopenharmony_ci	/* This is already set by cxgb4_set_dcb_caps, so just return it */
10778c2ecf20Sopenharmony_ci	return pi->dcb.supported;
10788c2ecf20Sopenharmony_ci}
10798c2ecf20Sopenharmony_ci
10808c2ecf20Sopenharmony_ci/* Set our DCBX parameters.
10818c2ecf20Sopenharmony_ci */
10828c2ecf20Sopenharmony_cistatic u8 cxgb4_setdcbx(struct net_device *dev, u8 dcb_request)
10838c2ecf20Sopenharmony_ci{
10848c2ecf20Sopenharmony_ci	struct port_info *pi = netdev2pinfo(dev);
10858c2ecf20Sopenharmony_ci
10868c2ecf20Sopenharmony_ci	/* Filter out requests which exceed our capabilities.
10878c2ecf20Sopenharmony_ci	 */
10888c2ecf20Sopenharmony_ci	if ((dcb_request & (CXGB4_DCBX_FW_SUPPORT | CXGB4_DCBX_HOST_SUPPORT))
10898c2ecf20Sopenharmony_ci	    != dcb_request)
10908c2ecf20Sopenharmony_ci		return 1;
10918c2ecf20Sopenharmony_ci
10928c2ecf20Sopenharmony_ci	/* Can't enable DCB if we haven't successfully negotiated it.
10938c2ecf20Sopenharmony_ci	 */
10948c2ecf20Sopenharmony_ci	if (!cxgb4_dcb_state_synced(pi->dcb.state))
10958c2ecf20Sopenharmony_ci		return 1;
10968c2ecf20Sopenharmony_ci
10978c2ecf20Sopenharmony_ci	/* There's currently no mechanism to allow for the firmware DCBX
10988c2ecf20Sopenharmony_ci	 * negotiation to be changed from the Host Driver.  If the caller
10998c2ecf20Sopenharmony_ci	 * requests exactly the same parameters that we already have then
11008c2ecf20Sopenharmony_ci	 * we'll allow them to be successfully "set" ...
11018c2ecf20Sopenharmony_ci	 */
11028c2ecf20Sopenharmony_ci	if (dcb_request != pi->dcb.supported)
11038c2ecf20Sopenharmony_ci		return 1;
11048c2ecf20Sopenharmony_ci
11058c2ecf20Sopenharmony_ci	pi->dcb.supported = dcb_request;
11068c2ecf20Sopenharmony_ci	return 0;
11078c2ecf20Sopenharmony_ci}
11088c2ecf20Sopenharmony_ci
11098c2ecf20Sopenharmony_cistatic int cxgb4_getpeer_app(struct net_device *dev,
11108c2ecf20Sopenharmony_ci			     struct dcb_peer_app_info *info, u16 *app_count)
11118c2ecf20Sopenharmony_ci{
11128c2ecf20Sopenharmony_ci	struct fw_port_cmd pcmd;
11138c2ecf20Sopenharmony_ci	struct port_info *pi = netdev2pinfo(dev);
11148c2ecf20Sopenharmony_ci	struct adapter *adap = pi->adapter;
11158c2ecf20Sopenharmony_ci	int i, err = 0;
11168c2ecf20Sopenharmony_ci
11178c2ecf20Sopenharmony_ci	if (!cxgb4_dcb_state_synced(pi->dcb.state))
11188c2ecf20Sopenharmony_ci		return 1;
11198c2ecf20Sopenharmony_ci
11208c2ecf20Sopenharmony_ci	info->willing = 0;
11218c2ecf20Sopenharmony_ci	info->error = 0;
11228c2ecf20Sopenharmony_ci
11238c2ecf20Sopenharmony_ci	*app_count = 0;
11248c2ecf20Sopenharmony_ci	for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) {
11258c2ecf20Sopenharmony_ci		INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
11268c2ecf20Sopenharmony_ci		pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID;
11278c2ecf20Sopenharmony_ci		pcmd.u.dcb.app_priority.idx = *app_count;
11288c2ecf20Sopenharmony_ci		err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
11298c2ecf20Sopenharmony_ci
11308c2ecf20Sopenharmony_ci		if (err != FW_PORT_DCB_CFG_SUCCESS) {
11318c2ecf20Sopenharmony_ci			dev_err(adap->pdev_dev, "DCB app table read failed with %d\n",
11328c2ecf20Sopenharmony_ci				-err);
11338c2ecf20Sopenharmony_ci			return err;
11348c2ecf20Sopenharmony_ci		}
11358c2ecf20Sopenharmony_ci
11368c2ecf20Sopenharmony_ci		/* find first empty slot */
11378c2ecf20Sopenharmony_ci		if (!pcmd.u.dcb.app_priority.protocolid)
11388c2ecf20Sopenharmony_ci			break;
11398c2ecf20Sopenharmony_ci	}
11408c2ecf20Sopenharmony_ci	*app_count = i;
11418c2ecf20Sopenharmony_ci	return err;
11428c2ecf20Sopenharmony_ci}
11438c2ecf20Sopenharmony_ci
11448c2ecf20Sopenharmony_cistatic int cxgb4_getpeerapp_tbl(struct net_device *dev, struct dcb_app *table)
11458c2ecf20Sopenharmony_ci{
11468c2ecf20Sopenharmony_ci	struct fw_port_cmd pcmd;
11478c2ecf20Sopenharmony_ci	struct port_info *pi = netdev2pinfo(dev);
11488c2ecf20Sopenharmony_ci	struct adapter *adap = pi->adapter;
11498c2ecf20Sopenharmony_ci	int i, err = 0;
11508c2ecf20Sopenharmony_ci
11518c2ecf20Sopenharmony_ci	if (!cxgb4_dcb_state_synced(pi->dcb.state))
11528c2ecf20Sopenharmony_ci		return 1;
11538c2ecf20Sopenharmony_ci
11548c2ecf20Sopenharmony_ci	for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) {
11558c2ecf20Sopenharmony_ci		INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
11568c2ecf20Sopenharmony_ci		pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID;
11578c2ecf20Sopenharmony_ci		pcmd.u.dcb.app_priority.idx = i;
11588c2ecf20Sopenharmony_ci		err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
11598c2ecf20Sopenharmony_ci
11608c2ecf20Sopenharmony_ci		if (err != FW_PORT_DCB_CFG_SUCCESS) {
11618c2ecf20Sopenharmony_ci			dev_err(adap->pdev_dev, "DCB app table read failed with %d\n",
11628c2ecf20Sopenharmony_ci				-err);
11638c2ecf20Sopenharmony_ci			return err;
11648c2ecf20Sopenharmony_ci		}
11658c2ecf20Sopenharmony_ci
11668c2ecf20Sopenharmony_ci		/* find first empty slot */
11678c2ecf20Sopenharmony_ci		if (!pcmd.u.dcb.app_priority.protocolid)
11688c2ecf20Sopenharmony_ci			break;
11698c2ecf20Sopenharmony_ci
11708c2ecf20Sopenharmony_ci		table[i].selector = (pcmd.u.dcb.app_priority.sel_field + 1);
11718c2ecf20Sopenharmony_ci		table[i].protocol =
11728c2ecf20Sopenharmony_ci			be16_to_cpu(pcmd.u.dcb.app_priority.protocolid);
11738c2ecf20Sopenharmony_ci		table[i].priority =
11748c2ecf20Sopenharmony_ci			ffs(pcmd.u.dcb.app_priority.user_prio_map) - 1;
11758c2ecf20Sopenharmony_ci	}
11768c2ecf20Sopenharmony_ci	return err;
11778c2ecf20Sopenharmony_ci}
11788c2ecf20Sopenharmony_ci
11798c2ecf20Sopenharmony_ci/* Return Priority Group information.
11808c2ecf20Sopenharmony_ci */
11818c2ecf20Sopenharmony_cistatic int cxgb4_cee_peer_getpg(struct net_device *dev, struct cee_pg *pg)
11828c2ecf20Sopenharmony_ci{
11838c2ecf20Sopenharmony_ci	struct fw_port_cmd pcmd;
11848c2ecf20Sopenharmony_ci	struct port_info *pi = netdev2pinfo(dev);
11858c2ecf20Sopenharmony_ci	struct adapter *adap = pi->adapter;
11868c2ecf20Sopenharmony_ci	u32 pgid;
11878c2ecf20Sopenharmony_ci	int i, err;
11888c2ecf20Sopenharmony_ci
11898c2ecf20Sopenharmony_ci	/* We're always "willing" -- the Switch Fabric always dictates the
11908c2ecf20Sopenharmony_ci	 * DCBX parameters to us.
11918c2ecf20Sopenharmony_ci	 */
11928c2ecf20Sopenharmony_ci	pg->willing = true;
11938c2ecf20Sopenharmony_ci
11948c2ecf20Sopenharmony_ci	INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
11958c2ecf20Sopenharmony_ci	pcmd.u.dcb.pgid.type = FW_PORT_DCB_TYPE_PGID;
11968c2ecf20Sopenharmony_ci	err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
11978c2ecf20Sopenharmony_ci	if (err != FW_PORT_DCB_CFG_SUCCESS) {
11988c2ecf20Sopenharmony_ci		dev_err(adap->pdev_dev, "DCB read PGID failed with %d\n", -err);
11998c2ecf20Sopenharmony_ci		return err;
12008c2ecf20Sopenharmony_ci	}
12018c2ecf20Sopenharmony_ci	pgid = be32_to_cpu(pcmd.u.dcb.pgid.pgid);
12028c2ecf20Sopenharmony_ci
12038c2ecf20Sopenharmony_ci	for (i = 0; i < CXGB4_MAX_PRIORITY; i++)
12048c2ecf20Sopenharmony_ci		pg->prio_pg[7 - i] = (pgid >> (i * 4)) & 0xF;
12058c2ecf20Sopenharmony_ci
12068c2ecf20Sopenharmony_ci	INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
12078c2ecf20Sopenharmony_ci	pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE;
12088c2ecf20Sopenharmony_ci	err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
12098c2ecf20Sopenharmony_ci	if (err != FW_PORT_DCB_CFG_SUCCESS) {
12108c2ecf20Sopenharmony_ci		dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n",
12118c2ecf20Sopenharmony_ci			-err);
12128c2ecf20Sopenharmony_ci		return err;
12138c2ecf20Sopenharmony_ci	}
12148c2ecf20Sopenharmony_ci
12158c2ecf20Sopenharmony_ci	for (i = 0; i < CXGB4_MAX_PRIORITY; i++)
12168c2ecf20Sopenharmony_ci		pg->pg_bw[i] = pcmd.u.dcb.pgrate.pgrate[i];
12178c2ecf20Sopenharmony_ci
12188c2ecf20Sopenharmony_ci	pg->tcs_supported = pcmd.u.dcb.pgrate.num_tcs_supported;
12198c2ecf20Sopenharmony_ci
12208c2ecf20Sopenharmony_ci	return 0;
12218c2ecf20Sopenharmony_ci}
12228c2ecf20Sopenharmony_ci
12238c2ecf20Sopenharmony_ci/* Return Priority Flow Control information.
12248c2ecf20Sopenharmony_ci */
12258c2ecf20Sopenharmony_cistatic int cxgb4_cee_peer_getpfc(struct net_device *dev, struct cee_pfc *pfc)
12268c2ecf20Sopenharmony_ci{
12278c2ecf20Sopenharmony_ci	struct port_info *pi = netdev2pinfo(dev);
12288c2ecf20Sopenharmony_ci
12298c2ecf20Sopenharmony_ci	cxgb4_getnumtcs(dev, DCB_NUMTCS_ATTR_PFC, &(pfc->tcs_supported));
12308c2ecf20Sopenharmony_ci
12318c2ecf20Sopenharmony_ci	/* Firmware sends this to us in a formwat that is a bit flipped version
12328c2ecf20Sopenharmony_ci	 * of spec, correct it before we send it to host. This is taken care of
12338c2ecf20Sopenharmony_ci	 * by bit shifting in other uses of pfcen
12348c2ecf20Sopenharmony_ci	 */
12358c2ecf20Sopenharmony_ci	pfc->pfc_en = bitswap_1(pi->dcb.pfcen);
12368c2ecf20Sopenharmony_ci
12378c2ecf20Sopenharmony_ci	pfc->tcs_supported = pi->dcb.pfc_num_tcs_supported;
12388c2ecf20Sopenharmony_ci
12398c2ecf20Sopenharmony_ci	return 0;
12408c2ecf20Sopenharmony_ci}
12418c2ecf20Sopenharmony_ci
12428c2ecf20Sopenharmony_ciconst struct dcbnl_rtnl_ops cxgb4_dcb_ops = {
12438c2ecf20Sopenharmony_ci	.ieee_getets		= cxgb4_ieee_get_ets,
12448c2ecf20Sopenharmony_ci	.ieee_getpfc		= cxgb4_ieee_get_pfc,
12458c2ecf20Sopenharmony_ci	.ieee_getapp		= cxgb4_ieee_getapp,
12468c2ecf20Sopenharmony_ci	.ieee_setapp		= cxgb4_ieee_setapp,
12478c2ecf20Sopenharmony_ci	.ieee_peer_getets	= cxgb4_ieee_peer_ets,
12488c2ecf20Sopenharmony_ci	.ieee_peer_getpfc	= cxgb4_ieee_get_pfc,
12498c2ecf20Sopenharmony_ci
12508c2ecf20Sopenharmony_ci	/* CEE std */
12518c2ecf20Sopenharmony_ci	.getstate		= cxgb4_getstate,
12528c2ecf20Sopenharmony_ci	.setstate		= cxgb4_setstate,
12538c2ecf20Sopenharmony_ci	.getpgtccfgtx		= cxgb4_getpgtccfg_tx,
12548c2ecf20Sopenharmony_ci	.getpgbwgcfgtx		= cxgb4_getpgbwgcfg_tx,
12558c2ecf20Sopenharmony_ci	.getpgtccfgrx		= cxgb4_getpgtccfg_rx,
12568c2ecf20Sopenharmony_ci	.getpgbwgcfgrx		= cxgb4_getpgbwgcfg_rx,
12578c2ecf20Sopenharmony_ci	.setpgtccfgtx		= cxgb4_setpgtccfg_tx,
12588c2ecf20Sopenharmony_ci	.setpgbwgcfgtx		= cxgb4_setpgbwgcfg_tx,
12598c2ecf20Sopenharmony_ci	.setpfccfg		= cxgb4_setpfccfg,
12608c2ecf20Sopenharmony_ci	.getpfccfg		= cxgb4_getpfccfg,
12618c2ecf20Sopenharmony_ci	.setall			= cxgb4_setall,
12628c2ecf20Sopenharmony_ci	.getcap			= cxgb4_getcap,
12638c2ecf20Sopenharmony_ci	.getnumtcs		= cxgb4_getnumtcs,
12648c2ecf20Sopenharmony_ci	.setnumtcs		= cxgb4_setnumtcs,
12658c2ecf20Sopenharmony_ci	.getpfcstate		= cxgb4_getpfcstate,
12668c2ecf20Sopenharmony_ci	.setpfcstate		= cxgb4_setpfcstate,
12678c2ecf20Sopenharmony_ci	.getapp			= cxgb4_getapp,
12688c2ecf20Sopenharmony_ci	.setapp			= cxgb4_setapp,
12698c2ecf20Sopenharmony_ci
12708c2ecf20Sopenharmony_ci	/* DCBX configuration */
12718c2ecf20Sopenharmony_ci	.getdcbx		= cxgb4_getdcbx,
12728c2ecf20Sopenharmony_ci	.setdcbx		= cxgb4_setdcbx,
12738c2ecf20Sopenharmony_ci
12748c2ecf20Sopenharmony_ci	/* peer apps */
12758c2ecf20Sopenharmony_ci	.peer_getappinfo	= cxgb4_getpeer_app,
12768c2ecf20Sopenharmony_ci	.peer_getapptable	= cxgb4_getpeerapp_tbl,
12778c2ecf20Sopenharmony_ci
12788c2ecf20Sopenharmony_ci	/* CEE peer */
12798c2ecf20Sopenharmony_ci	.cee_peer_getpg		= cxgb4_cee_peer_getpg,
12808c2ecf20Sopenharmony_ci	.cee_peer_getpfc	= cxgb4_cee_peer_getpfc,
12818c2ecf20Sopenharmony_ci};
1282