brintos

brintos / linux-shallow public Read only

0
0
Text · 19.5 KiB · 752a724 Raw
754 lines · c
1/*2 * Copyright (c) 2011 Mellanox Technologies. All rights reserved.3 *4 * This software is available to you under a choice of one of two5 * licenses.  You may choose to be licensed under the terms of the GNU6 * General Public License (GPL) Version 2, available from the file7 * COPYING in the main directory of this source tree, or the8 * OpenIB.org BSD license below:9 *10 *     Redistribution and use in source and binary forms, with or11 *     without modification, are permitted provided that the following12 *     conditions are met:13 *14 *      - Redistributions of source code must retain the above15 *        copyright notice, this list of conditions and the following16 *        disclaimer.17 *18 *      - Redistributions in binary form must reproduce the above19 *        copyright notice, this list of conditions and the following20 *        disclaimer in the documentation and/or other materials21 *        provided with the distribution.22 *23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE30 * SOFTWARE.31 *32 */33 34#include <linux/dcbnl.h>35#include <linux/math64.h>36 37#include "mlx4_en.h"38#include "fw_qos.h"39 40enum {41	MLX4_CEE_STATE_DOWN   = 0,42	MLX4_CEE_STATE_UP     = 1,43};44 45/* Definitions for QCN46 */47 48struct mlx4_congestion_control_mb_prio_802_1_qau_params {49	__be32 modify_enable_high;50	__be32 modify_enable_low;51	__be32 reserved1;52	__be32 extended_enable;53	__be32 rppp_max_rps;54	__be32 rpg_time_reset;55	__be32 rpg_byte_reset;56	__be32 rpg_threshold;57	__be32 rpg_max_rate;58	__be32 rpg_ai_rate;59	__be32 rpg_hai_rate;60	__be32 rpg_gd;61	__be32 rpg_min_dec_fac;62	__be32 rpg_min_rate;63	__be32 max_time_rise;64	__be32 max_byte_rise;65	__be32 max_qdelta;66	__be32 min_qoffset;67	__be32 gd_coefficient;68	__be32 reserved2[5];69	__be32 cp_sample_base;70	__be32 reserved3[39];71};72 73struct mlx4_congestion_control_mb_prio_802_1_qau_statistics {74	__be64 rppp_rp_centiseconds;75	__be32 reserved1;76	__be32 ignored_cnm;77	__be32 rppp_created_rps;78	__be32 estimated_total_rate;79	__be32 max_active_rate_limiter_index;80	__be32 dropped_cnms_busy_fw;81	__be32 reserved2;82	__be32 cnms_handled_successfully;83	__be32 min_total_limiters_rate;84	__be32 max_total_limiters_rate;85	__be32 reserved3[4];86};87 88static u8 mlx4_en_dcbnl_getcap(struct net_device *dev, int capid, u8 *cap)89{90	struct mlx4_en_priv *priv = netdev_priv(dev);91 92	switch (capid) {93	case DCB_CAP_ATTR_PFC:94		*cap = true;95		break;96	case DCB_CAP_ATTR_DCBX:97		*cap = priv->dcbx_cap;98		break;99	case DCB_CAP_ATTR_PFC_TCS:100		*cap = 1 <<  mlx4_max_tc(priv->mdev->dev);101		break;102	default:103		*cap = false;104		break;105	}106 107	return 0;108}109 110static u8 mlx4_en_dcbnl_getpfcstate(struct net_device *netdev)111{112	struct mlx4_en_priv *priv = netdev_priv(netdev);113 114	return priv->cee_config.pfc_state;115}116 117static void mlx4_en_dcbnl_setpfcstate(struct net_device *netdev, u8 state)118{119	struct mlx4_en_priv *priv = netdev_priv(netdev);120 121	priv->cee_config.pfc_state = state;122}123 124static void mlx4_en_dcbnl_get_pfc_cfg(struct net_device *netdev, int priority,125				      u8 *setting)126{127	struct mlx4_en_priv *priv = netdev_priv(netdev);128 129	*setting = priv->cee_config.dcb_pfc[priority];130}131 132static void mlx4_en_dcbnl_set_pfc_cfg(struct net_device *netdev, int priority,133				      u8 setting)134{135	struct mlx4_en_priv *priv = netdev_priv(netdev);136 137	priv->cee_config.dcb_pfc[priority] = setting;138	priv->cee_config.pfc_state = true;139}140 141static int mlx4_en_dcbnl_getnumtcs(struct net_device *netdev, int tcid, u8 *num)142{143	struct mlx4_en_priv *priv = netdev_priv(netdev);144 145	if (!(priv->flags & MLX4_EN_FLAG_DCB_ENABLED))146		return -EINVAL;147 148	if (tcid == DCB_NUMTCS_ATTR_PFC)149		*num = mlx4_max_tc(priv->mdev->dev);150	else151		*num = 0;152 153	return 0;154}155 156static u8 mlx4_en_dcbnl_set_all(struct net_device *netdev)157{158	struct mlx4_en_priv *priv = netdev_priv(netdev);159	struct mlx4_en_port_profile *prof = priv->prof;160	struct mlx4_en_dev *mdev = priv->mdev;161	u8 tx_pause, tx_ppp, rx_pause, rx_ppp;162 163	if (!(priv->dcbx_cap & DCB_CAP_DCBX_VER_CEE))164		return 1;165 166	if (priv->cee_config.pfc_state) {167		int tc;168		rx_ppp = prof->rx_ppp;169		tx_ppp = prof->tx_ppp;170 171		for (tc = 0; tc < CEE_DCBX_MAX_PRIO; tc++) {172			u8 tc_mask = 1 << tc;173 174			switch (priv->cee_config.dcb_pfc[tc]) {175			case pfc_disabled:176				tx_ppp &= ~tc_mask;177				rx_ppp &= ~tc_mask;178				break;179			case pfc_enabled_full:180				tx_ppp |= tc_mask;181				rx_ppp |= tc_mask;182				break;183			case pfc_enabled_tx:184				tx_ppp |= tc_mask;185				rx_ppp &= ~tc_mask;186				break;187			case pfc_enabled_rx:188				tx_ppp &= ~tc_mask;189				rx_ppp |= tc_mask;190				break;191			default:192				break;193			}194		}195		rx_pause = !!(rx_ppp || tx_ppp) ? 0 : prof->rx_pause;196		tx_pause = !!(rx_ppp || tx_ppp) ? 0 : prof->tx_pause;197	} else {198		rx_ppp = 0;199		tx_ppp = 0;200		rx_pause = prof->rx_pause;201		tx_pause = prof->tx_pause;202	}203 204	if (mlx4_SET_PORT_general(mdev->dev, priv->port,205				  priv->rx_skb_size + ETH_FCS_LEN,206				  tx_pause, tx_ppp, rx_pause, rx_ppp)) {207		en_err(priv, "Failed setting pause params\n");208		return 1;209	}210 211	prof->tx_ppp = tx_ppp;212	prof->rx_ppp = rx_ppp;213	prof->tx_pause = tx_pause;214	prof->rx_pause = rx_pause;215 216	return 0;217}218 219static u8 mlx4_en_dcbnl_get_state(struct net_device *dev)220{221	struct mlx4_en_priv *priv = netdev_priv(dev);222 223	if (priv->flags & MLX4_EN_FLAG_DCB_ENABLED)224		return MLX4_CEE_STATE_UP;225 226	return MLX4_CEE_STATE_DOWN;227}228 229static u8 mlx4_en_dcbnl_set_state(struct net_device *dev, u8 state)230{231	struct mlx4_en_priv *priv = netdev_priv(dev);232	int num_tcs = 0;233 234	if (!(priv->dcbx_cap & DCB_CAP_DCBX_VER_CEE))235		return 1;236 237	if (!!(state) == !!(priv->flags & MLX4_EN_FLAG_DCB_ENABLED))238		return 0;239 240	if (state) {241		priv->flags |= MLX4_EN_FLAG_DCB_ENABLED;242		num_tcs = IEEE_8021QAZ_MAX_TCS;243	} else {244		priv->flags &= ~MLX4_EN_FLAG_DCB_ENABLED;245	}246 247	if (mlx4_en_alloc_tx_queue_per_tc(dev, num_tcs))248		return 1;249 250	return 0;251}252 253/* On success returns a non-zero 802.1p user priority bitmap254 * otherwise returns 0 as the invalid user priority bitmap to255 * indicate an error.256 */257static int mlx4_en_dcbnl_getapp(struct net_device *netdev, u8 idtype, u16 id)258{259	struct mlx4_en_priv *priv = netdev_priv(netdev);260	struct dcb_app app = {261				.selector = idtype,262				.protocol = id,263			     };264	if (!(priv->dcbx_cap & DCB_CAP_DCBX_VER_CEE))265		return 0;266 267	return dcb_getapp(netdev, &app);268}269 270static int mlx4_en_dcbnl_setapp(struct net_device *netdev, u8 idtype,271				u16 id, u8 up)272{273	struct mlx4_en_priv *priv = netdev_priv(netdev);274	struct dcb_app app;275 276	if (!(priv->dcbx_cap & DCB_CAP_DCBX_VER_CEE))277		return -EINVAL;278 279	memset(&app, 0, sizeof(struct dcb_app));280	app.selector = idtype;281	app.protocol = id;282	app.priority = up;283 284	return dcb_setapp(netdev, &app);285}286 287static int mlx4_en_dcbnl_ieee_getets(struct net_device *dev,288				   struct ieee_ets *ets)289{290	struct mlx4_en_priv *priv = netdev_priv(dev);291	struct ieee_ets *my_ets = &priv->ets;292 293	if (!my_ets)294		return -EINVAL;295 296	ets->ets_cap = IEEE_8021QAZ_MAX_TCS;297	ets->cbs = my_ets->cbs;298	memcpy(ets->tc_tx_bw, my_ets->tc_tx_bw, sizeof(ets->tc_tx_bw));299	memcpy(ets->tc_tsa, my_ets->tc_tsa, sizeof(ets->tc_tsa));300	memcpy(ets->prio_tc, my_ets->prio_tc, sizeof(ets->prio_tc));301 302	return 0;303}304 305static int mlx4_en_ets_validate(struct mlx4_en_priv *priv, struct ieee_ets *ets)306{307	int i;308	int total_ets_bw = 0;309	int has_ets_tc = 0;310 311	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {312		if (ets->prio_tc[i] >= MLX4_EN_NUM_UP_HIGH) {313			en_err(priv, "Bad priority in UP <=> TC mapping. TC: %d, UP: %d\n",314					i, ets->prio_tc[i]);315			return -EINVAL;316		}317 318		switch (ets->tc_tsa[i]) {319		case IEEE_8021QAZ_TSA_VENDOR:320		case IEEE_8021QAZ_TSA_STRICT:321			break;322		case IEEE_8021QAZ_TSA_ETS:323			has_ets_tc = 1;324			total_ets_bw += ets->tc_tx_bw[i];325			break;326		default:327			en_err(priv, "TC[%d]: Not supported TSA: %d\n",328					i, ets->tc_tsa[i]);329			return -EOPNOTSUPP;330		}331	}332 333	if (has_ets_tc && total_ets_bw != MLX4_EN_BW_MAX) {334		en_err(priv, "Bad ETS BW sum: %d. Should be exactly 100%%\n",335				total_ets_bw);336		return -EINVAL;337	}338 339	return 0;340}341 342static int mlx4_en_config_port_scheduler(struct mlx4_en_priv *priv,343		struct ieee_ets *ets, u16 *ratelimit)344{345	struct mlx4_en_dev *mdev = priv->mdev;346	int num_strict = 0;347	int i;348	__u8 tc_tx_bw[IEEE_8021QAZ_MAX_TCS] = { 0 };349	__u8 pg[IEEE_8021QAZ_MAX_TCS] = { 0 };350 351	ets = ets ?: &priv->ets;352	ratelimit = ratelimit ?: priv->maxrate;353 354	/* higher TC means higher priority => lower pg */355	for (i = IEEE_8021QAZ_MAX_TCS - 1; i >= 0; i--) {356		switch (ets->tc_tsa[i]) {357		case IEEE_8021QAZ_TSA_VENDOR:358			pg[i] = MLX4_EN_TC_VENDOR;359			tc_tx_bw[i] = MLX4_EN_BW_MAX;360			break;361		case IEEE_8021QAZ_TSA_STRICT:362			pg[i] = num_strict++;363			tc_tx_bw[i] = MLX4_EN_BW_MAX;364			break;365		case IEEE_8021QAZ_TSA_ETS:366			pg[i] = MLX4_EN_TC_ETS;367			tc_tx_bw[i] = ets->tc_tx_bw[i] ?: MLX4_EN_BW_MIN;368			break;369		}370	}371 372	return mlx4_SET_PORT_SCHEDULER(mdev->dev, priv->port, tc_tx_bw, pg,373			ratelimit);374}375 376static int377mlx4_en_dcbnl_ieee_setets(struct net_device *dev, struct ieee_ets *ets)378{379	struct mlx4_en_priv *priv = netdev_priv(dev);380	struct mlx4_en_dev *mdev = priv->mdev;381	int err;382 383	err = mlx4_en_ets_validate(priv, ets);384	if (err)385		return err;386 387	err = mlx4_SET_PORT_PRIO2TC(mdev->dev, priv->port, ets->prio_tc);388	if (err)389		return err;390 391	err = mlx4_en_config_port_scheduler(priv, ets, NULL);392	if (err)393		return err;394 395	memcpy(&priv->ets, ets, sizeof(priv->ets));396 397	return 0;398}399 400static int mlx4_en_dcbnl_ieee_getpfc(struct net_device *dev,401		struct ieee_pfc *pfc)402{403	struct mlx4_en_priv *priv = netdev_priv(dev);404 405	pfc->pfc_cap = IEEE_8021QAZ_MAX_TCS;406	pfc->pfc_en = priv->prof->tx_ppp;407 408	return 0;409}410 411static int mlx4_en_dcbnl_ieee_setpfc(struct net_device *dev,412		struct ieee_pfc *pfc)413{414	struct mlx4_en_priv *priv = netdev_priv(dev);415	struct mlx4_en_port_profile *prof = priv->prof;416	struct mlx4_en_dev *mdev = priv->mdev;417	u32 tx_pause, tx_ppp, rx_pause, rx_ppp;418	int err;419 420	en_dbg(DRV, priv, "cap: 0x%x en: 0x%x mbc: 0x%x delay: %d\n",421			pfc->pfc_cap,422			pfc->pfc_en,423			pfc->mbc,424			pfc->delay);425 426	rx_pause = prof->rx_pause && !pfc->pfc_en;427	tx_pause = prof->tx_pause && !pfc->pfc_en;428	rx_ppp = pfc->pfc_en;429	tx_ppp = pfc->pfc_en;430 431	err = mlx4_SET_PORT_general(mdev->dev, priv->port,432				    priv->rx_skb_size + ETH_FCS_LEN,433				    tx_pause, tx_ppp, rx_pause, rx_ppp);434	if (err) {435		en_err(priv, "Failed setting pause params\n");436		return err;437	}438 439	mlx4_en_update_pfc_stats_bitmap(mdev->dev, &priv->stats_bitmap,440					rx_ppp, rx_pause, tx_ppp, tx_pause);441 442	prof->tx_ppp = tx_ppp;443	prof->rx_ppp = rx_ppp;444	prof->rx_pause = rx_pause;445	prof->tx_pause = tx_pause;446 447	return err;448}449 450static u8 mlx4_en_dcbnl_getdcbx(struct net_device *dev)451{452	struct mlx4_en_priv *priv = netdev_priv(dev);453 454	return priv->dcbx_cap;455}456 457static u8 mlx4_en_dcbnl_setdcbx(struct net_device *dev, u8 mode)458{459	struct mlx4_en_priv *priv = netdev_priv(dev);460	struct ieee_ets ets = {0};461	struct ieee_pfc pfc = {0};462 463	if (mode == priv->dcbx_cap)464		return 0;465 466	if ((mode & DCB_CAP_DCBX_LLD_MANAGED) ||467	    ((mode & DCB_CAP_DCBX_VER_IEEE) &&468	     (mode & DCB_CAP_DCBX_VER_CEE)) ||469	    !(mode & DCB_CAP_DCBX_HOST))470		goto err;471 472	priv->dcbx_cap = mode;473 474	ets.ets_cap = IEEE_8021QAZ_MAX_TCS;475	pfc.pfc_cap = IEEE_8021QAZ_MAX_TCS;476 477	if (mode & DCB_CAP_DCBX_VER_IEEE) {478		if (mlx4_en_dcbnl_ieee_setets(dev, &ets))479			goto err;480		if (mlx4_en_dcbnl_ieee_setpfc(dev, &pfc))481			goto err;482	} else if (mode & DCB_CAP_DCBX_VER_CEE) {483		if (mlx4_en_dcbnl_set_all(dev))484			goto err;485	} else {486		if (mlx4_en_dcbnl_ieee_setets(dev, &ets))487			goto err;488		if (mlx4_en_dcbnl_ieee_setpfc(dev, &pfc))489			goto err;490		if (mlx4_en_alloc_tx_queue_per_tc(dev, 0))491			goto err;492	}493 494	return 0;495err:496	return 1;497}498 499#define MLX4_RATELIMIT_UNITS_IN_KB 100000 /* rate-limit HW unit in Kbps */500static int mlx4_en_dcbnl_ieee_getmaxrate(struct net_device *dev,501				   struct ieee_maxrate *maxrate)502{503	struct mlx4_en_priv *priv = netdev_priv(dev);504	int i;505 506	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++)507		maxrate->tc_maxrate[i] =508			priv->maxrate[i] * MLX4_RATELIMIT_UNITS_IN_KB;509 510	return 0;511}512 513static int mlx4_en_dcbnl_ieee_setmaxrate(struct net_device *dev,514		struct ieee_maxrate *maxrate)515{516	struct mlx4_en_priv *priv = netdev_priv(dev);517	u16 tmp[IEEE_8021QAZ_MAX_TCS];518	int i, err;519 520	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {521		/* Convert from Kbps into HW units, rounding result up.522		 * Setting to 0, means unlimited BW.523		 */524		tmp[i] = div_u64(maxrate->tc_maxrate[i] +525				 MLX4_RATELIMIT_UNITS_IN_KB - 1,526				 MLX4_RATELIMIT_UNITS_IN_KB);527	}528 529	err = mlx4_en_config_port_scheduler(priv, NULL, tmp);530	if (err)531		return err;532 533	memcpy(priv->maxrate, tmp, sizeof(priv->maxrate));534 535	return 0;536}537 538#define RPG_ENABLE_BIT	31539#define CN_TAG_BIT	30540 541static int mlx4_en_dcbnl_ieee_getqcn(struct net_device *dev,542				     struct ieee_qcn *qcn)543{544	struct mlx4_en_priv *priv = netdev_priv(dev);545	struct mlx4_congestion_control_mb_prio_802_1_qau_params *hw_qcn;546	struct mlx4_cmd_mailbox *mailbox_out = NULL;547	u64 mailbox_in_dma = 0;548	u32 inmod = 0;549	int i, err;550 551	if (!(priv->mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_QCN))552		return -EOPNOTSUPP;553 554	mailbox_out = mlx4_alloc_cmd_mailbox(priv->mdev->dev);555	if (IS_ERR(mailbox_out))556		return -ENOMEM;557	hw_qcn =558	(struct mlx4_congestion_control_mb_prio_802_1_qau_params *)559	mailbox_out->buf;560 561	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {562		inmod = priv->port | ((1 << i) << 8) |563			 (MLX4_CTRL_ALGO_802_1_QAU_REACTION_POINT << 16);564		err = mlx4_cmd_box(priv->mdev->dev, mailbox_in_dma,565				   mailbox_out->dma,566				   inmod, MLX4_CONGESTION_CONTROL_GET_PARAMS,567				   MLX4_CMD_CONGESTION_CTRL_OPCODE,568				   MLX4_CMD_TIME_CLASS_C,569				   MLX4_CMD_NATIVE);570		if (err) {571			mlx4_free_cmd_mailbox(priv->mdev->dev, mailbox_out);572			return err;573		}574 575		qcn->rpg_enable[i] =576			be32_to_cpu(hw_qcn->extended_enable) >> RPG_ENABLE_BIT;577		qcn->rppp_max_rps[i] =578			be32_to_cpu(hw_qcn->rppp_max_rps);579		qcn->rpg_time_reset[i] =580			be32_to_cpu(hw_qcn->rpg_time_reset);581		qcn->rpg_byte_reset[i] =582			be32_to_cpu(hw_qcn->rpg_byte_reset);583		qcn->rpg_threshold[i] =584			be32_to_cpu(hw_qcn->rpg_threshold);585		qcn->rpg_max_rate[i] =586			be32_to_cpu(hw_qcn->rpg_max_rate);587		qcn->rpg_ai_rate[i] =588			be32_to_cpu(hw_qcn->rpg_ai_rate);589		qcn->rpg_hai_rate[i] =590			be32_to_cpu(hw_qcn->rpg_hai_rate);591		qcn->rpg_gd[i] =592			be32_to_cpu(hw_qcn->rpg_gd);593		qcn->rpg_min_dec_fac[i] =594			be32_to_cpu(hw_qcn->rpg_min_dec_fac);595		qcn->rpg_min_rate[i] =596			be32_to_cpu(hw_qcn->rpg_min_rate);597		qcn->cndd_state_machine[i] =598			priv->cndd_state[i];599	}600	mlx4_free_cmd_mailbox(priv->mdev->dev, mailbox_out);601	return 0;602}603 604static int mlx4_en_dcbnl_ieee_setqcn(struct net_device *dev,605				     struct ieee_qcn *qcn)606{607	struct mlx4_en_priv *priv = netdev_priv(dev);608	struct mlx4_congestion_control_mb_prio_802_1_qau_params *hw_qcn;609	struct mlx4_cmd_mailbox *mailbox_in = NULL;610	u64 mailbox_in_dma = 0;611	u32 inmod = 0;612	int i, err;613#define MODIFY_ENABLE_HIGH_MASK 0xc0000000614#define MODIFY_ENABLE_LOW_MASK 0xffc00000615 616	if (!(priv->mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_QCN))617		return -EOPNOTSUPP;618 619	mailbox_in = mlx4_alloc_cmd_mailbox(priv->mdev->dev);620	if (IS_ERR(mailbox_in))621		return -ENOMEM;622 623	mailbox_in_dma = mailbox_in->dma;624	hw_qcn =625	(struct mlx4_congestion_control_mb_prio_802_1_qau_params *)mailbox_in->buf;626	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {627		inmod = priv->port | ((1 << i) << 8) |628			 (MLX4_CTRL_ALGO_802_1_QAU_REACTION_POINT << 16);629 630		/* Before updating QCN parameter,631		 * need to set it's modify enable bit to 1632		 */633 634		hw_qcn->modify_enable_high = cpu_to_be32(635						MODIFY_ENABLE_HIGH_MASK);636		hw_qcn->modify_enable_low = cpu_to_be32(MODIFY_ENABLE_LOW_MASK);637 638		hw_qcn->extended_enable = cpu_to_be32(qcn->rpg_enable[i] << RPG_ENABLE_BIT);639		hw_qcn->rppp_max_rps = cpu_to_be32(qcn->rppp_max_rps[i]);640		hw_qcn->rpg_time_reset = cpu_to_be32(qcn->rpg_time_reset[i]);641		hw_qcn->rpg_byte_reset = cpu_to_be32(qcn->rpg_byte_reset[i]);642		hw_qcn->rpg_threshold = cpu_to_be32(qcn->rpg_threshold[i]);643		hw_qcn->rpg_max_rate = cpu_to_be32(qcn->rpg_max_rate[i]);644		hw_qcn->rpg_ai_rate = cpu_to_be32(qcn->rpg_ai_rate[i]);645		hw_qcn->rpg_hai_rate = cpu_to_be32(qcn->rpg_hai_rate[i]);646		hw_qcn->rpg_gd = cpu_to_be32(qcn->rpg_gd[i]);647		hw_qcn->rpg_min_dec_fac = cpu_to_be32(qcn->rpg_min_dec_fac[i]);648		hw_qcn->rpg_min_rate = cpu_to_be32(qcn->rpg_min_rate[i]);649		priv->cndd_state[i] = qcn->cndd_state_machine[i];650		if (qcn->cndd_state_machine[i] == DCB_CNDD_INTERIOR_READY)651			hw_qcn->extended_enable |= cpu_to_be32(1 << CN_TAG_BIT);652 653		err = mlx4_cmd(priv->mdev->dev, mailbox_in_dma, inmod,654			       MLX4_CONGESTION_CONTROL_SET_PARAMS,655			       MLX4_CMD_CONGESTION_CTRL_OPCODE,656			       MLX4_CMD_TIME_CLASS_C,657			       MLX4_CMD_NATIVE);658		if (err) {659			mlx4_free_cmd_mailbox(priv->mdev->dev, mailbox_in);660			return err;661		}662	}663	mlx4_free_cmd_mailbox(priv->mdev->dev, mailbox_in);664	return 0;665}666 667static int mlx4_en_dcbnl_ieee_getqcnstats(struct net_device *dev,668					  struct ieee_qcn_stats *qcn_stats)669{670	struct mlx4_en_priv *priv = netdev_priv(dev);671	struct mlx4_congestion_control_mb_prio_802_1_qau_statistics *hw_qcn_stats;672	struct mlx4_cmd_mailbox *mailbox_out = NULL;673	u64 mailbox_in_dma = 0;674	u32 inmod = 0;675	int i, err;676 677	if (!(priv->mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_QCN))678		return -EOPNOTSUPP;679 680	mailbox_out = mlx4_alloc_cmd_mailbox(priv->mdev->dev);681	if (IS_ERR(mailbox_out))682		return -ENOMEM;683 684	hw_qcn_stats =685	(struct mlx4_congestion_control_mb_prio_802_1_qau_statistics *)686	mailbox_out->buf;687 688	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {689		inmod = priv->port | ((1 << i) << 8) |690			 (MLX4_CTRL_ALGO_802_1_QAU_REACTION_POINT << 16);691		err = mlx4_cmd_box(priv->mdev->dev, mailbox_in_dma,692				   mailbox_out->dma, inmod,693				   MLX4_CONGESTION_CONTROL_GET_STATISTICS,694				   MLX4_CMD_CONGESTION_CTRL_OPCODE,695				   MLX4_CMD_TIME_CLASS_C,696				   MLX4_CMD_NATIVE);697		if (err) {698			mlx4_free_cmd_mailbox(priv->mdev->dev, mailbox_out);699			return err;700		}701		qcn_stats->rppp_rp_centiseconds[i] =702			be64_to_cpu(hw_qcn_stats->rppp_rp_centiseconds);703		qcn_stats->rppp_created_rps[i] =704			be32_to_cpu(hw_qcn_stats->rppp_created_rps);705	}706	mlx4_free_cmd_mailbox(priv->mdev->dev, mailbox_out);707	return 0;708}709 710const struct dcbnl_rtnl_ops mlx4_en_dcbnl_ops = {711	.ieee_getets		= mlx4_en_dcbnl_ieee_getets,712	.ieee_setets		= mlx4_en_dcbnl_ieee_setets,713	.ieee_getmaxrate	= mlx4_en_dcbnl_ieee_getmaxrate,714	.ieee_setmaxrate	= mlx4_en_dcbnl_ieee_setmaxrate,715	.ieee_getqcn		= mlx4_en_dcbnl_ieee_getqcn,716	.ieee_setqcn		= mlx4_en_dcbnl_ieee_setqcn,717	.ieee_getqcnstats	= mlx4_en_dcbnl_ieee_getqcnstats,718	.ieee_getpfc		= mlx4_en_dcbnl_ieee_getpfc,719	.ieee_setpfc		= mlx4_en_dcbnl_ieee_setpfc,720 721	.getstate	= mlx4_en_dcbnl_get_state,722	.setstate	= mlx4_en_dcbnl_set_state,723	.getpfccfg	= mlx4_en_dcbnl_get_pfc_cfg,724	.setpfccfg	= mlx4_en_dcbnl_set_pfc_cfg,725	.setall		= mlx4_en_dcbnl_set_all,726	.getcap		= mlx4_en_dcbnl_getcap,727	.getnumtcs	= mlx4_en_dcbnl_getnumtcs,728	.getpfcstate	= mlx4_en_dcbnl_getpfcstate,729	.setpfcstate	= mlx4_en_dcbnl_setpfcstate,730	.getapp		= mlx4_en_dcbnl_getapp,731	.setapp		= mlx4_en_dcbnl_setapp,732 733	.getdcbx	= mlx4_en_dcbnl_getdcbx,734	.setdcbx	= mlx4_en_dcbnl_setdcbx,735};736 737const struct dcbnl_rtnl_ops mlx4_en_dcbnl_pfc_ops = {738	.ieee_getpfc	= mlx4_en_dcbnl_ieee_getpfc,739	.ieee_setpfc	= mlx4_en_dcbnl_ieee_setpfc,740 741	.setstate	= mlx4_en_dcbnl_set_state,742	.getpfccfg	= mlx4_en_dcbnl_get_pfc_cfg,743	.setpfccfg	= mlx4_en_dcbnl_set_pfc_cfg,744	.setall		= mlx4_en_dcbnl_set_all,745	.getnumtcs	= mlx4_en_dcbnl_getnumtcs,746	.getpfcstate	= mlx4_en_dcbnl_getpfcstate,747	.setpfcstate	= mlx4_en_dcbnl_setpfcstate,748	.getapp		= mlx4_en_dcbnl_getapp,749	.setapp		= mlx4_en_dcbnl_setapp,750 751	.getdcbx	= mlx4_en_dcbnl_getdcbx,752	.setdcbx	= mlx4_en_dcbnl_setdcbx,753};754