File Index
Files and directories
Sign in
FILE

en_dcbnl.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c C
   1/*
   2 * Copyright (c) 2016, Mellanox Technologies. All rights reserved.
   3 *
   4 * This software is available to you under a choice of one of two
   5 * licenses.  You may choose to be licensed under the terms of the GNU
   6 * General Public License (GPL) Version 2, available from the file
   7 * COPYING in the main directory of this source tree, or the
   8 * OpenIB.org BSD license below:
   9 *
  10 *     Redistribution and use in source and binary forms, with or
  11 *     without modification, are permitted provided that the following
  12 *     conditions are met:
  13 *
  14 *      - Redistributions of source code must retain the above
  15 *        copyright notice, this list of conditions and the following
  16 *        disclaimer.
  17 *
  18 *      - Redistributions in binary form must reproduce the above
  19 *        copyright notice, this list of conditions and the following
  20 *        disclaimer in the documentation and/or other materials
  21 *        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 OF
  25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  30 * SOFTWARE.
  31 */
  32#include <linux/device.h>
  33#include <linux/netdevice.h>
  34#include <linux/units.h>
  35#include "en.h"
  36#include "en/port.h"
  37#include "en/port_buffer.h"
  38
  39#define MLX5E_MAX_BW_ALLOC 100 /* Max percentage of BW allocation */
  40
  41#define MLX5E_100MB_TO_KB (100 * MEGA / KILO)
  42#define MLX5E_1GB_TO_KB   (GIGA / KILO)
  43
  44#define MLX5E_CEE_STATE_UP    1
  45#define MLX5E_CEE_STATE_DOWN  0
  46
  47/* Max supported cable length is 1000 meters */
  48#define MLX5E_MAX_CABLE_LENGTH 1000
  49
  50enum {
  51	MLX5E_VENDOR_TC_GROUP_NUM = 7,
  52	MLX5E_LOWEST_PRIO_GROUP   = 0,
  53};
  54
  55enum {
  56	MLX5_DCB_CHG_RESET,
  57	MLX5_DCB_NO_CHG,
  58	MLX5_DCB_CHG_NO_RESET,
  59};
  60
  61#define MLX5_DSCP_SUPPORTED(mdev) (MLX5_CAP_GEN(mdev, qcam_reg)  && \
  62				   MLX5_CAP_QCAM_REG(mdev, qpts) && \
  63				   MLX5_CAP_QCAM_REG(mdev, qpdpm))
  64
  65static int mlx5e_set_trust_state(struct mlx5e_priv *priv, u8 trust_state);
  66static int mlx5e_set_dscp2prio(struct mlx5e_priv *priv, u8 dscp, u8 prio);
  67
  68/* If dcbx mode is non-host set the dcbx mode to host.
  69 */
  70static int mlx5e_dcbnl_set_dcbx_mode(struct mlx5e_priv *priv,
  71				     enum mlx5_dcbx_oper_mode mode)
  72{
  73	struct mlx5_core_dev *mdev = priv->mdev;
  74	u32 param[MLX5_ST_SZ_DW(dcbx_param)];
  75	int err;
  76
  77	err = mlx5_query_port_dcbx_param(mdev, param);
  78	if (err)
  79		return err;
  80
  81	MLX5_SET(dcbx_param, param, version_admin, mode);
  82	if (mode != MLX5E_DCBX_PARAM_VER_OPER_HOST)
  83		MLX5_SET(dcbx_param, param, willing_admin, 1);
  84
  85	return mlx5_set_port_dcbx_param(mdev, param);
  86}
  87
  88static int mlx5e_dcbnl_switch_to_host_mode(struct mlx5e_priv *priv)
  89{
  90	struct mlx5e_dcbx *dcbx = &priv->dcbx;
  91	int err;
  92
  93	if (!MLX5_CAP_GEN(priv->mdev, dcbx))
  94		return 0;
  95
  96	if (dcbx->mode == MLX5E_DCBX_PARAM_VER_OPER_HOST)
  97		return 0;
  98
  99	err = mlx5e_dcbnl_set_dcbx_mode(priv, MLX5E_DCBX_PARAM_VER_OPER_HOST);
 100	if (err)
 101		return err;
 102
 103	dcbx->mode = MLX5E_DCBX_PARAM_VER_OPER_HOST;
 104	return 0;
 105}
 106
 107static int mlx5e_dcbnl_ieee_getets(struct net_device *netdev,
 108				   struct ieee_ets *ets)
 109{
 110	struct mlx5e_priv *priv = netdev_priv(netdev);
 111	struct mlx5_core_dev *mdev = priv->mdev;
 112	u8 tc_group[IEEE_8021QAZ_MAX_TCS];
 113	bool is_tc_group_6_exist = false;
 114	bool is_zero_bw_ets_tc = false;
 115	int err = 0;
 116	int i;
 117
 118	if (!MLX5_CAP_GEN(priv->mdev, ets))
 119		return -EOPNOTSUPP;
 120
 121	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
 122		err = mlx5_query_port_prio_tc(mdev, i, &ets->prio_tc[i]);
 123		if (err)
 124			return err;
 125	}
 126
 127	ets->ets_cap = mlx5_max_tc(priv->mdev) + 1;
 128	for (i = 0; i < ets->ets_cap; i++) {
 129		err = mlx5_query_port_tc_group(mdev, i, &tc_group[i]);
 130		if (err)
 131			return err;
 132
 133		err = mlx5_query_port_tc_bw_alloc(mdev, i, &ets->tc_tx_bw[i]);
 134		if (err)
 135			return err;
 136
 137		if (ets->tc_tx_bw[i] < MLX5E_MAX_BW_ALLOC &&
 138		    tc_group[i] == (MLX5E_LOWEST_PRIO_GROUP + 1))
 139			is_zero_bw_ets_tc = true;
 140
 141		if (tc_group[i] == (MLX5E_VENDOR_TC_GROUP_NUM - 1))
 142			is_tc_group_6_exist = true;
 143	}
 144
 145	/* Report 0% ets tc if exits*/
 146	if (is_zero_bw_ets_tc) {
 147		for (i = 0; i < ets->ets_cap; i++)
 148			if (tc_group[i] == MLX5E_LOWEST_PRIO_GROUP)
 149				ets->tc_tx_bw[i] = 0;
 150	}
 151
 152	/* Update tc_tsa based on fw setting*/
 153	for (i = 0; i < ets->ets_cap; i++) {
 154		if (ets->tc_tx_bw[i] < MLX5E_MAX_BW_ALLOC)
 155			priv->dcbx.tc_tsa[i] = IEEE_8021QAZ_TSA_ETS;
 156		else if (tc_group[i] == MLX5E_VENDOR_TC_GROUP_NUM &&
 157			 !is_tc_group_6_exist)
 158			priv->dcbx.tc_tsa[i] = IEEE_8021QAZ_TSA_VENDOR;
 159	}
 160	memcpy(ets->tc_tsa, priv->dcbx.tc_tsa, sizeof(ets->tc_tsa));
 161
 162	return err;
 163}
 164
 165static void mlx5e_build_tc_group(struct ieee_ets *ets, u8 *tc_group, int max_tc)
 166{
 167	bool any_tc_mapped_to_ets = false;
 168	bool ets_zero_bw = false;
 169	int strict_group;
 170	int i;
 171
 172	for (i = 0; i <= max_tc; i++) {
 173		if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_ETS) {
 174			any_tc_mapped_to_ets = true;
 175			if (!ets->tc_tx_bw[i])
 176				ets_zero_bw = true;
 177		}
 178	}
 179
 180	/* strict group has higher priority than ets group */
 181	strict_group = MLX5E_LOWEST_PRIO_GROUP;
 182	if (any_tc_mapped_to_ets)
 183		strict_group++;
 184	if (ets_zero_bw)
 185		strict_group++;
 186
 187	for (i = 0; i <= max_tc; i++) {
 188		switch (ets->tc_tsa[i]) {
 189		case IEEE_8021QAZ_TSA_VENDOR:
 190			tc_group[i] = MLX5E_VENDOR_TC_GROUP_NUM;
 191			break;
 192		case IEEE_8021QAZ_TSA_STRICT:
 193			tc_group[i] = strict_group++;
 194			break;
 195		case IEEE_8021QAZ_TSA_ETS:
 196			tc_group[i] = MLX5E_LOWEST_PRIO_GROUP;
 197			if (ets->tc_tx_bw[i] && ets_zero_bw)
 198				tc_group[i] = MLX5E_LOWEST_PRIO_GROUP + 1;
 199			break;
 200		}
 201	}
 202}
 203
 204static void mlx5e_build_tc_tx_bw(struct ieee_ets *ets, u8 *tc_tx_bw,
 205				 u8 *tc_group, int max_tc)
 206{
 207	int bw_for_ets_zero_bw_tc = 0;
 208	int last_ets_zero_bw_tc = -1;
 209	int num_ets_zero_bw = 0;
 210	int i;
 211
 212	for (i = 0; i <= max_tc; i++) {
 213		if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_ETS &&
 214		    !ets->tc_tx_bw[i]) {
 215			num_ets_zero_bw++;
 216			last_ets_zero_bw_tc = i;
 217		}
 218	}
 219
 220	if (num_ets_zero_bw)
 221		bw_for_ets_zero_bw_tc = MLX5E_MAX_BW_ALLOC / num_ets_zero_bw;
 222
 223	for (i = 0; i <= max_tc; i++) {
 224		switch (ets->tc_tsa[i]) {
 225		case IEEE_8021QAZ_TSA_VENDOR:
 226			tc_tx_bw[i] = MLX5E_MAX_BW_ALLOC;
 227			break;
 228		case IEEE_8021QAZ_TSA_STRICT:
 229			tc_tx_bw[i] = MLX5E_MAX_BW_ALLOC;
 230			break;
 231		case IEEE_8021QAZ_TSA_ETS:
 232			tc_tx_bw[i] = ets->tc_tx_bw[i] ?
 233				      ets->tc_tx_bw[i] :
 234				      bw_for_ets_zero_bw_tc;
 235			break;
 236		}
 237	}
 238
 239	/* Make sure the total bw for ets zero bw group is 100% */
 240	if (last_ets_zero_bw_tc != -1)
 241		tc_tx_bw[last_ets_zero_bw_tc] +=
 242			MLX5E_MAX_BW_ALLOC % num_ets_zero_bw;
 243}
 244
 245/* If there are ETS BW 0,
 246 *   Set ETS group # to 1 for all ETS non zero BW tcs. Their sum must be 100%.
 247 *   Set group #0 to all the ETS BW 0 tcs and
 248 *     equally splits the 100% BW between them
 249 *   Report both group #0 and #1 as ETS type.
 250 *     All the tcs in group #0 will be reported with 0% BW.
 251 */
 252static int mlx5e_dcbnl_ieee_setets_core(struct mlx5e_priv *priv, struct ieee_ets *ets)
 253{
 254	struct mlx5_core_dev *mdev = priv->mdev;
 255	u8 tc_tx_bw[IEEE_8021QAZ_MAX_TCS];
 256	u8 tc_group[IEEE_8021QAZ_MAX_TCS];
 257	int max_tc = mlx5_max_tc(mdev);
 258	int err, i;
 259
 260	mlx5e_build_tc_group(ets, tc_group, max_tc);
 261	mlx5e_build_tc_tx_bw(ets, tc_tx_bw, tc_group, max_tc);
 262
 263	err = mlx5_set_port_prio_tc(mdev, ets->prio_tc);
 264	if (err)
 265		return err;
 266
 267	err = mlx5_set_port_tc_group(mdev, tc_group);
 268	if (err)
 269		return err;
 270
 271	err = mlx5_set_port_tc_bw_alloc(mdev, tc_tx_bw);
 272
 273	if (err)
 274		return err;
 275
 276	memcpy(priv->dcbx.tc_tsa, ets->tc_tsa, sizeof(ets->tc_tsa));
 277
 278	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
 279		netdev_dbg(priv->netdev, "%s: prio_%d <=> tc_%d\n",
 280			   __func__, i, ets->prio_tc[i]);
 281		netdev_dbg(priv->netdev, "%s: tc_%d <=> tx_bw_%d%%, group_%d\n",
 282			   __func__, i, tc_tx_bw[i], tc_group[i]);
 283	}
 284
 285	return err;
 286}
 287
 288static int mlx5e_dbcnl_validate_ets(struct net_device *netdev,
 289				    struct ieee_ets *ets,
 290				    bool zero_sum_allowed)
 291{
 292	bool have_ets_tc = false;
 293	int bw_sum = 0;
 294	int i;
 295
 296	/* Validate Priority */
 297	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
 298		if (ets->prio_tc[i] >= MLX5E_MAX_PRIORITY) {
 299			netdev_err(netdev,
 300				   "Failed to validate ETS: priority value greater than max(%d)\n",
 301				    MLX5E_MAX_PRIORITY);
 302			return -EINVAL;
 303		}
 304	}
 305
 306	/* Validate Bandwidth Sum */
 307	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
 308		if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_ETS) {
 309			have_ets_tc = true;
 310			bw_sum += ets->tc_tx_bw[i];
 311		}
 312	}
 313
 314	if (have_ets_tc && bw_sum != 100) {
 315		if (bw_sum || (!bw_sum && !zero_sum_allowed))
 316			netdev_err(netdev,
 317				   "Failed to validate ETS: BW sum is illegal\n");
 318		return -EINVAL;
 319	}
 320	return 0;
 321}
 322
 323static int mlx5e_dcbnl_ieee_setets(struct net_device *netdev,
 324				   struct ieee_ets *ets)
 325{
 326	struct mlx5e_priv *priv = netdev_priv(netdev);
 327	int err;
 328
 329	if (!MLX5_CAP_GEN(priv->mdev, ets))
 330		return -EOPNOTSUPP;
 331
 332	err = mlx5e_dbcnl_validate_ets(netdev, ets, false);
 333	if (err)
 334		return err;
 335
 336	err = mlx5e_dcbnl_ieee_setets_core(priv, ets);
 337	if (err)
 338		return err;
 339
 340	return 0;
 341}
 342
 343static int mlx5e_dcbnl_ieee_getpfc(struct net_device *dev,
 344				   struct ieee_pfc *pfc)
 345{
 346	struct mlx5e_priv *priv = netdev_priv(dev);
 347	struct mlx5_core_dev *mdev = priv->mdev;
 348	struct mlx5e_pport_stats *pstats = &priv->stats.pport;
 349	int i;
 350
 351	pfc->pfc_cap = mlx5_max_tc(mdev) + 1;
 352	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
 353		pfc->requests[i]    = PPORT_PER_PRIO_GET(pstats, i, tx_pause);
 354		pfc->indications[i] = PPORT_PER_PRIO_GET(pstats, i, rx_pause);
 355	}
 356
 357	if (MLX5_BUFFER_SUPPORTED(mdev))
 358		pfc->delay = priv->dcbx.cable_len;
 359
 360	return mlx5_query_port_pfc(mdev, &pfc->pfc_en, NULL);
 361}
 362
 363static int mlx5e_dcbnl_ieee_setpfc(struct net_device *dev,
 364				   struct ieee_pfc *pfc)
 365{
 366	u8 buffer_ownership = MLX5_BUF_OWNERSHIP_UNKNOWN;
 367	struct mlx5e_priv *priv = netdev_priv(dev);
 368	struct mlx5_core_dev *mdev = priv->mdev;
 369	u32 old_cable_len = priv->dcbx.cable_len;
 370	struct ieee_pfc pfc_new;
 371	u32 changed = 0;
 372	u8 curr_pfc_en;
 373	int ret = 0;
 374
 375	/* pfc_en */
 376	mlx5_query_port_pfc(mdev, &curr_pfc_en, NULL);
 377	if (pfc->pfc_en != curr_pfc_en) {
 378		ret = mlx5_set_port_pfc(mdev, pfc->pfc_en, pfc->pfc_en);
 379		if (ret)
 380			return ret;
 381		mlx5_toggle_port_link(mdev);
 382		changed |= MLX5E_PORT_BUFFER_PFC;
 383	}
 384
 385	if (pfc->delay &&
 386	    pfc->delay < MLX5E_MAX_CABLE_LENGTH &&
 387	    pfc->delay != priv->dcbx.cable_len) {
 388		priv->dcbx.cable_len = pfc->delay;
 389		changed |= MLX5E_PORT_BUFFER_CABLE_LEN;
 390	}
 391
 392	if (MLX5_BUFFER_SUPPORTED(mdev)) {
 393		pfc_new.pfc_en = (changed & MLX5E_PORT_BUFFER_PFC) ? pfc->pfc_en : curr_pfc_en;
 394		ret = mlx5_query_port_buffer_ownership(mdev,
 395						       &buffer_ownership);
 396		if (ret)
 397			netdev_err(dev,
 398				   "%s, Failed to get buffer ownership: %d\n",
 399				   __func__, ret);
 400
 401		if (buffer_ownership == MLX5_BUF_OWNERSHIP_SW_OWNED)
 402			ret = mlx5e_port_manual_buffer_config(priv, changed,
 403							      dev->mtu, &pfc_new,
 404							      NULL, NULL);
 405
 406		if (ret && (changed & MLX5E_PORT_BUFFER_CABLE_LEN))
 407			priv->dcbx.cable_len = old_cable_len;
 408	}
 409
 410	if (!ret) {
 411		netdev_dbg(dev,
 412			   "%s: PFC per priority bit mask: 0x%x\n",
 413			   __func__, pfc->pfc_en);
 414	}
 415	return ret;
 416}
 417
 418static u8 mlx5e_dcbnl_getdcbx(struct net_device *dev)
 419{
 420	struct mlx5e_priv *priv = netdev_priv(dev);
 421
 422	return priv->dcbx.cap;
 423}
 424
 425static u8 mlx5e_dcbnl_setdcbx(struct net_device *dev, u8 mode)
 426{
 427	struct mlx5e_priv *priv = netdev_priv(dev);
 428	struct mlx5e_dcbx *dcbx = &priv->dcbx;
 429
 430	if (mode & DCB_CAP_DCBX_LLD_MANAGED)
 431		return 1;
 432
 433	if ((!mode) && MLX5_CAP_GEN(priv->mdev, dcbx)) {
 434		if (dcbx->mode == MLX5E_DCBX_PARAM_VER_OPER_AUTO)
 435			return 0;
 436
 437		/* set dcbx to fw controlled */
 438		if (!mlx5e_dcbnl_set_dcbx_mode(priv, MLX5E_DCBX_PARAM_VER_OPER_AUTO)) {
 439			dcbx->mode = MLX5E_DCBX_PARAM_VER_OPER_AUTO;
 440			dcbx->cap &= ~DCB_CAP_DCBX_HOST;
 441			return 0;
 442		}
 443
 444		return 1;
 445	}
 446
 447	if (!(mode & DCB_CAP_DCBX_HOST))
 448		return 1;
 449
 450	if (mlx5e_dcbnl_switch_to_host_mode(netdev_priv(dev)))
 451		return 1;
 452
 453	dcbx->cap = mode;
 454
 455	return 0;
 456}
 457
 458static int mlx5e_dcbnl_ieee_setapp(struct net_device *dev, struct dcb_app *app)
 459{
 460	struct mlx5e_priv *priv = netdev_priv(dev);
 461	struct dcb_app temp;
 462	bool is_new;
 463	int err;
 464
 465	if (!MLX5_CAP_GEN(priv->mdev, vport_group_manager) ||
 466	    !MLX5_DSCP_SUPPORTED(priv->mdev))
 467		return -EOPNOTSUPP;
 468
 469	if ((app->selector != IEEE_8021QAZ_APP_SEL_DSCP) ||
 470	    (app->protocol >= MLX5E_MAX_DSCP))
 471		return -EINVAL;
 472
 473	/* Save the old entry info */
 474	temp.selector = IEEE_8021QAZ_APP_SEL_DSCP;
 475	temp.protocol = app->protocol;
 476	temp.priority = priv->dcbx_dp.dscp2prio[app->protocol];
 477
 478	/* Check if need to switch to dscp trust state */
 479	if (!priv->dcbx.dscp_app_cnt) {
 480		err =  mlx5e_set_trust_state(priv, MLX5_QPTS_TRUST_DSCP);
 481		if (err)
 482			return err;
 483	}
 484
 485	/* Skip the fw command if new and old mapping are the same */
 486	if (app->priority != priv->dcbx_dp.dscp2prio[app->protocol]) {
 487		err = mlx5e_set_dscp2prio(priv, app->protocol, app->priority);
 488		if (err)
 489			goto fw_err;
 490	}
 491
 492	/* Delete the old entry if exists */
 493	is_new = false;
 494	err = dcb_ieee_delapp(dev, &temp);
 495	if (err)
 496		is_new = true;
 497
 498	/* Add new entry and update counter */
 499	err = dcb_ieee_setapp(dev, app);
 500	if (err)
 501		return err;
 502
 503	if (is_new)
 504		priv->dcbx.dscp_app_cnt++;
 505
 506	return err;
 507
 508fw_err:
 509	mlx5e_set_trust_state(priv, MLX5_QPTS_TRUST_PCP);
 510	return err;
 511}
 512
 513static int mlx5e_dcbnl_ieee_delapp(struct net_device *dev, struct dcb_app *app)
 514{
 515	struct mlx5e_priv *priv = netdev_priv(dev);
 516	int err;
 517
 518	if  (!MLX5_CAP_GEN(priv->mdev, vport_group_manager) ||
 519	     !MLX5_DSCP_SUPPORTED(priv->mdev))
 520		return -EOPNOTSUPP;
 521
 522	if ((app->selector != IEEE_8021QAZ_APP_SEL_DSCP) ||
 523	    (app->protocol >= MLX5E_MAX_DSCP))
 524		return -EINVAL;
 525
 526	/* Skip if no dscp app entry */
 527	if (!priv->dcbx.dscp_app_cnt)
 528		return -ENOENT;
 529
 530	/* Check if the entry matches fw setting */
 531	if (app->priority != priv->dcbx_dp.dscp2prio[app->protocol])
 532		return -ENOENT;
 533
 534	/* Delete the app entry */
 535	err = dcb_ieee_delapp(dev, app);
 536	if (err)
 537		return err;
 538
 539	/* Reset the priority mapping back to zero */
 540	err = mlx5e_set_dscp2prio(priv, app->protocol, 0);
 541	if (err)
 542		goto fw_err;
 543
 544	priv->dcbx.dscp_app_cnt--;
 545
 546	/* Check if need to switch to pcp trust state */
 547	if (!priv->dcbx.dscp_app_cnt)
 548		err = mlx5e_set_trust_state(priv, MLX5_QPTS_TRUST_PCP);
 549
 550	return err;
 551
 552fw_err:
 553	mlx5e_set_trust_state(priv, MLX5_QPTS_TRUST_PCP);
 554	return err;
 555}
 556
 557static int mlx5e_dcbnl_ieee_getmaxrate(struct net_device *netdev,
 558				       struct ieee_maxrate *maxrate)
 559{
 560	struct mlx5e_priv *priv    = netdev_priv(netdev);
 561	struct mlx5_core_dev *mdev = priv->mdev;
 562	u8 max_bw_value[IEEE_8021QAZ_MAX_TCS];
 563	u8 max_bw_unit[IEEE_8021QAZ_MAX_TCS];
 564	int err;
 565	int i;
 566
 567	err = mlx5_query_port_ets_rate_limit(mdev, max_bw_value, max_bw_unit);
 568	if (err)
 569		return err;
 570
 571	memset(maxrate->tc_maxrate, 0, sizeof(maxrate->tc_maxrate));
 572
 573	for (i = 0; i <= mlx5_max_tc(mdev); i++) {
 574		switch (max_bw_unit[i]) {
 575		case MLX5_100_MBPS_UNIT:
 576			maxrate->tc_maxrate[i] = max_bw_value[i] * MLX5E_100MB_TO_KB;
 577			break;
 578		case MLX5_GBPS_UNIT:
 579			maxrate->tc_maxrate[i] = max_bw_value[i] * MLX5E_1GB_TO_KB;
 580			break;
 581		case MLX5_BW_NO_LIMIT:
 582			break;
 583		default:
 584			WARN(true, "non-supported BW unit");
 585			break;
 586		}
 587	}
 588
 589	return 0;
 590}
 591
 592static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev,
 593				       struct ieee_maxrate *maxrate)
 594{
 595	struct mlx5e_priv *priv    = netdev_priv(netdev);
 596	struct mlx5_core_dev *mdev = priv->mdev;
 597	u8 max_bw_value[IEEE_8021QAZ_MAX_TCS];
 598	u8 max_bw_unit[IEEE_8021QAZ_MAX_TCS];
 599	u64 upper_limit_100mbps;
 600	u64 upper_limit_gbps;
 601	int i;
 602	struct {
 603		int scale;
 604		const char *units_str;
 605	} units[] = {
 606		[MLX5_100_MBPS_UNIT] = {
 607			.scale = 100,
 608			.units_str = "Mbps",
 609		},
 610		[MLX5_GBPS_UNIT] = {
 611			.scale = 1,
 612			.units_str = "Gbps",
 613		},
 614	};
 615
 616	memset(max_bw_value, 0, sizeof(max_bw_value));
 617	memset(max_bw_unit, 0, sizeof(max_bw_unit));
 618	upper_limit_100mbps = U8_MAX * MLX5E_100MB_TO_KB;
 619	upper_limit_gbps = U8_MAX * MLX5E_1GB_TO_KB;
 620
 621	for (i = 0; i <= mlx5_max_tc(mdev); i++) {
 622		if (!maxrate->tc_maxrate[i]) {
 623			max_bw_unit[i]  = MLX5_BW_NO_LIMIT;
 624			continue;
 625		}
 626		if (maxrate->tc_maxrate[i] <= upper_limit_100mbps) {
 627			max_bw_value[i] = div_u64(maxrate->tc_maxrate[i],
 628						  MLX5E_100MB_TO_KB);
 629			max_bw_value[i] = max_bw_value[i] ? max_bw_value[i] : 1;
 630			max_bw_unit[i]  = MLX5_100_MBPS_UNIT;
 631		} else if (maxrate->tc_maxrate[i] <= upper_limit_gbps) {
 632			max_bw_value[i] = div_u64(maxrate->tc_maxrate[i],
 633						  MLX5E_1GB_TO_KB);
 634			max_bw_unit[i]  = MLX5_GBPS_UNIT;
 635		} else {
 636			netdev_err(netdev,
 637				   "tc_%d maxrate %llu Kbps exceeds limit %llu\n",
 638				   i, maxrate->tc_maxrate[i],
 639				   upper_limit_gbps);
 640			return -EINVAL;
 641		}
 642	}
 643
 644	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
 645		netdev_dbg(netdev, "%s: tc_%d <=> max_bw %u %s\n", __func__, i,
 646			   max_bw_value[i] * units[max_bw_unit[i]].scale,
 647			   units[max_bw_unit[i]].units_str);
 648	}
 649
 650	return mlx5_modify_port_ets_rate_limit(mdev, max_bw_value, max_bw_unit);
 651}
 652
 653static u8 mlx5e_dcbnl_setall(struct net_device *netdev)
 654{
 655	struct mlx5e_priv *priv = netdev_priv(netdev);
 656	struct mlx5e_cee_config *cee_cfg = &priv->dcbx.cee_cfg;
 657	struct mlx5_core_dev *mdev = priv->mdev;
 658	struct ieee_ets ets;
 659	struct ieee_pfc pfc;
 660	int err = -EOPNOTSUPP;
 661	int i;
 662
 663	if (!MLX5_CAP_GEN(mdev, ets))
 664		goto out;
 665
 666	memset(&ets, 0, sizeof(ets));
 667	memset(&pfc, 0, sizeof(pfc));
 668
 669	ets.ets_cap = IEEE_8021QAZ_MAX_TCS;
 670	for (i = 0; i < CEE_DCBX_MAX_PGS; i++) {
 671		ets.tc_tx_bw[i] = cee_cfg->pg_bw_pct[i];
 672		ets.tc_rx_bw[i] = cee_cfg->pg_bw_pct[i];
 673		ets.tc_tsa[i]   = IEEE_8021QAZ_TSA_ETS;
 674		ets.prio_tc[i]  = cee_cfg->prio_to_pg_map[i];
 675		netdev_dbg(netdev,
 676			   "%s: Priority group %d: tx_bw %d, rx_bw %d, prio_tc %d\n",
 677			   __func__, i, ets.tc_tx_bw[i], ets.tc_rx_bw[i],
 678			   ets.prio_tc[i]);
 679	}
 680
 681	err = mlx5e_dbcnl_validate_ets(netdev, &ets, true);
 682	if (err)
 683		goto out;
 684
 685	err = mlx5e_dcbnl_ieee_setets_core(priv, &ets);
 686	if (err) {
 687		netdev_err(netdev,
 688			   "%s, Failed to set ETS: %d\n", __func__, err);
 689		goto out;
 690	}
 691
 692	/* Set PFC */
 693	pfc.pfc_cap = mlx5_max_tc(mdev) + 1;
 694	if (!cee_cfg->pfc_enable)
 695		pfc.pfc_en = 0;
 696	else
 697		for (i = 0; i < CEE_DCBX_MAX_PRIO; i++)
 698			pfc.pfc_en |= cee_cfg->pfc_setting[i] << i;
 699
 700	err = mlx5e_dcbnl_ieee_setpfc(netdev, &pfc);
 701	if (err) {
 702		netdev_err(netdev,
 703			   "%s, Failed to set PFC: %d\n", __func__, err);
 704		goto out;
 705	}
 706out:
 707	return err ? MLX5_DCB_NO_CHG : MLX5_DCB_CHG_RESET;
 708}
 709
 710static u8 mlx5e_dcbnl_getstate(struct net_device *netdev)
 711{
 712	return MLX5E_CEE_STATE_UP;
 713}
 714
 715static void mlx5e_dcbnl_getpermhwaddr(struct net_device *netdev,
 716				      u8 *perm_addr)
 717{
 718	struct mlx5e_priv *priv = netdev_priv(netdev);
 719
 720	if (!perm_addr)
 721		return;
 722
 723	memset(perm_addr, 0xff, MAX_ADDR_LEN);
 724
 725	mlx5_query_mac_address(priv->mdev, perm_addr);
 726}
 727
 728static void mlx5e_dcbnl_setpgtccfgtx(struct net_device *netdev,
 729				     int priority, u8 prio_type,
 730				     u8 pgid, u8 bw_pct, u8 up_map)
 731{
 732	struct mlx5e_priv *priv = netdev_priv(netdev);
 733	struct mlx5e_cee_config *cee_cfg = &priv->dcbx.cee_cfg;
 734
 735	if (priority >= CEE_DCBX_MAX_PRIO) {
 736		netdev_err(netdev,
 737			   "%s, priority is out of range\n", __func__);
 738		return;
 739	}
 740
 741	if (pgid >= CEE_DCBX_MAX_PGS) {
 742		netdev_err(netdev,
 743			   "%s, priority group is out of range\n", __func__);
 744		return;
 745	}
 746
 747	cee_cfg->prio_to_pg_map[priority] = pgid;
 748}
 749
 750static void mlx5e_dcbnl_setpgbwgcfgtx(struct net_device *netdev,
 751				      int pgid, u8 bw_pct)
 752{
 753	struct mlx5e_priv *priv = netdev_priv(netdev);
 754	struct mlx5e_cee_config *cee_cfg = &priv->dcbx.cee_cfg;
 755
 756	if (pgid >= CEE_DCBX_MAX_PGS) {
 757		netdev_err(netdev,
 758			   "%s, priority group is out of range\n", __func__);
 759		return;
 760	}
 761
 762	cee_cfg->pg_bw_pct[pgid] = bw_pct;
 763}
 764
 765static void mlx5e_dcbnl_getpgtccfgtx(struct net_device *netdev,
 766				     int priority, u8 *prio_type,
 767				     u8 *pgid, u8 *bw_pct, u8 *up_map)
 768{
 769	struct mlx5e_priv *priv = netdev_priv(netdev);
 770	struct mlx5_core_dev *mdev = priv->mdev;
 771
 772	if (!MLX5_CAP_GEN(priv->mdev, ets)) {
 773		netdev_err(netdev, "%s, ets is not supported\n", __func__);
 774		return;
 775	}
 776
 777	if (priority >= CEE_DCBX_MAX_PRIO) {
 778		netdev_err(netdev,
 779			   "%s, priority is out of range\n", __func__);
 780		return;
 781	}
 782
 783	*prio_type = 0;
 784	*bw_pct = 0;
 785	*up_map = 0;
 786
 787	if (mlx5_query_port_prio_tc(mdev, priority, pgid))
 788		*pgid = 0;
 789}
 790
 791static void mlx5e_dcbnl_getpgbwgcfgtx(struct net_device *netdev,
 792				      int pgid, u8 *bw_pct)
 793{
 794	struct ieee_ets ets;
 795
 796	if (pgid >= CEE_DCBX_MAX_PGS) {
 797		netdev_err(netdev,
 798			   "%s, priority group is out of range\n", __func__);
 799		return;
 800	}
 801
 802	mlx5e_dcbnl_ieee_getets(netdev, &ets);
 803	*bw_pct = ets.tc_tx_bw[pgid];
 804}
 805
 806static void mlx5e_dcbnl_setpfccfg(struct net_device *netdev,
 807				  int priority, u8 setting)
 808{
 809	struct mlx5e_priv *priv = netdev_priv(netdev);
 810	struct mlx5e_cee_config *cee_cfg = &priv->dcbx.cee_cfg;
 811
 812	if (priority >= CEE_DCBX_MAX_PRIO) {
 813		netdev_err(netdev,
 814			   "%s, priority is out of range\n", __func__);
 815		return;
 816	}
 817
 818	if (setting > 1)
 819		return;
 820
 821	cee_cfg->pfc_setting[priority] = setting;
 822}
 823
 824static int
 825mlx5e_dcbnl_get_priority_pfc(struct net_device *netdev,
 826			     int priority, u8 *setting)
 827{
 828	struct ieee_pfc pfc;
 829	int err;
 830
 831	err = mlx5e_dcbnl_ieee_getpfc(netdev, &pfc);
 832
 833	if (err)
 834		*setting = 0;
 835	else
 836		*setting = (pfc.pfc_en >> priority) & 0x01;
 837
 838	return err;
 839}
 840
 841static void mlx5e_dcbnl_getpfccfg(struct net_device *netdev,
 842				  int priority, u8 *setting)
 843{
 844	if (priority >= CEE_DCBX_MAX_PRIO) {
 845		netdev_err(netdev,
 846			   "%s, priority is out of range\n", __func__);
 847		return;
 848	}
 849
 850	if (!setting)
 851		return;
 852
 853	mlx5e_dcbnl_get_priority_pfc(netdev, priority, setting);
 854}
 855
 856static u8 mlx5e_dcbnl_getcap(struct net_device *netdev,
 857			     int capid, u8 *cap)
 858{
 859	struct mlx5e_priv *priv = netdev_priv(netdev);
 860	struct mlx5_core_dev *mdev = priv->mdev;
 861	u8 rval = 0;
 862
 863	switch (capid) {
 864	case DCB_CAP_ATTR_PG:
 865		*cap = true;
 866		break;
 867	case DCB_CAP_ATTR_PFC:
 868		*cap = true;
 869		break;
 870	case DCB_CAP_ATTR_UP2TC:
 871		*cap = false;
 872		break;
 873	case DCB_CAP_ATTR_PG_TCS:
 874		*cap = 1 << mlx5_max_tc(mdev);
 875		break;
 876	case DCB_CAP_ATTR_PFC_TCS:
 877		*cap = 1 << mlx5_max_tc(mdev);
 878		break;
 879	case DCB_CAP_ATTR_GSP:
 880		*cap = false;
 881		break;
 882	case DCB_CAP_ATTR_BCN:
 883		*cap = false;
 884		break;
 885	case DCB_CAP_ATTR_DCBX:
 886		*cap = priv->dcbx.cap |
 887		       DCB_CAP_DCBX_VER_CEE |
 888		       DCB_CAP_DCBX_VER_IEEE;
 889		break;
 890	default:
 891		*cap = 0;
 892		rval = 1;
 893		break;
 894	}
 895
 896	return rval;
 897}
 898
 899static int mlx5e_dcbnl_getnumtcs(struct net_device *netdev,
 900				 int tcs_id, u8 *num)
 901{
 902	struct mlx5e_priv *priv = netdev_priv(netdev);
 903	struct mlx5_core_dev *mdev = priv->mdev;
 904
 905	switch (tcs_id) {
 906	case DCB_NUMTCS_ATTR_PG:
 907	case DCB_NUMTCS_ATTR_PFC:
 908		*num = mlx5_max_tc(mdev) + 1;
 909		break;
 910	default:
 911		return -EINVAL;
 912	}
 913
 914	return 0;
 915}
 916
 917static u8 mlx5e_dcbnl_getpfcstate(struct net_device *netdev)
 918{
 919	struct ieee_pfc pfc;
 920
 921	if (mlx5e_dcbnl_ieee_getpfc(netdev, &pfc))
 922		return MLX5E_CEE_STATE_DOWN;
 923
 924	return pfc.pfc_en ? MLX5E_CEE_STATE_UP : MLX5E_CEE_STATE_DOWN;
 925}
 926
 927static void mlx5e_dcbnl_setpfcstate(struct net_device *netdev, u8 state)
 928{
 929	struct mlx5e_priv *priv = netdev_priv(netdev);
 930	struct mlx5e_cee_config *cee_cfg = &priv->dcbx.cee_cfg;
 931
 932	if ((state != MLX5E_CEE_STATE_UP) && (state != MLX5E_CEE_STATE_DOWN))
 933		return;
 934
 935	cee_cfg->pfc_enable = state;
 936}
 937
 938static int mlx5e_dcbnl_getbuffer(struct net_device *dev,
 939				 struct dcbnl_buffer *dcb_buffer)
 940{
 941	struct mlx5e_priv *priv = netdev_priv(dev);
 942	struct mlx5_core_dev *mdev = priv->mdev;
 943	struct mlx5e_port_buffer port_buffer;
 944	u8 buffer[MLX5E_MAX_PRIORITY];
 945	int i, err;
 946
 947	if (!MLX5_BUFFER_SUPPORTED(mdev))
 948		return -EOPNOTSUPP;
 949
 950	err = mlx5e_port_query_priority2buffer(mdev, buffer);
 951	if (err)
 952		return err;
 953
 954	for (i = 0; i < MLX5E_MAX_PRIORITY; i++)
 955		dcb_buffer->prio2buffer[i] = buffer[i];
 956
 957	err = mlx5e_port_query_buffer(priv, &port_buffer);
 958	if (err)
 959		return err;
 960
 961	for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++)
 962		dcb_buffer->buffer_size[i] = port_buffer.buffer[i].size;
 963	dcb_buffer->total_size = port_buffer.port_buffer_size -
 964				 port_buffer.internal_buffers_size;
 965
 966	return 0;
 967}
 968
 969static int mlx5e_dcbnl_setbuffer(struct net_device *dev,
 970				 struct dcbnl_buffer *dcb_buffer)
 971{
 972	struct mlx5e_priv *priv = netdev_priv(dev);
 973	struct mlx5_core_dev *mdev = priv->mdev;
 974	struct mlx5e_port_buffer port_buffer;
 975	u8 old_prio2buffer[MLX5E_MAX_PRIORITY];
 976	u32 *buffer_size = NULL;
 977	u8 *prio2buffer = NULL;
 978	u32 changed = 0;
 979	int i, err;
 980
 981	if (!MLX5_BUFFER_SUPPORTED(mdev))
 982		return -EOPNOTSUPP;
 983
 984	for (i = 0; i < DCBX_MAX_BUFFERS; i++)
 985		mlx5_core_dbg(mdev, "buffer[%d]=%d\n", i, dcb_buffer->buffer_size[i]);
 986
 987	for (i = 0; i < MLX5E_MAX_PRIORITY; i++)
 988		mlx5_core_dbg(mdev, "priority %d buffer%d\n", i, dcb_buffer->prio2buffer[i]);
 989
 990	err = mlx5e_port_query_priority2buffer(mdev, old_prio2buffer);
 991	if (err)
 992		return err;
 993
 994	for (i = 0; i < MLX5E_MAX_PRIORITY; i++) {
 995		if (dcb_buffer->prio2buffer[i] != old_prio2buffer[i]) {
 996			changed |= MLX5E_PORT_BUFFER_PRIO2BUFFER;
 997			prio2buffer = dcb_buffer->prio2buffer;
 998			break;
 999		}
1000	}
1001
1002	err = mlx5e_port_query_buffer(priv, &port_buffer);
1003	if (err)
1004		return err;
1005
1006	for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) {
1007		if (port_buffer.buffer[i].size != dcb_buffer->buffer_size[i]) {
1008			changed |= MLX5E_PORT_BUFFER_SIZE;
1009			buffer_size = dcb_buffer->buffer_size;
1010			break;
1011		}
1012	}
1013
1014	if (!changed)
1015		return 0;
1016
1017	err = mlx5e_port_manual_buffer_config(priv, changed, dev->mtu, NULL,
1018					      buffer_size, prio2buffer);
1019	return err;
1020}
1021
1022static const struct dcbnl_rtnl_ops mlx5e_dcbnl_ops = {
1023	.ieee_getets	= mlx5e_dcbnl_ieee_getets,
1024	.ieee_setets	= mlx5e_dcbnl_ieee_setets,
1025	.ieee_getmaxrate = mlx5e_dcbnl_ieee_getmaxrate,
1026	.ieee_setmaxrate = mlx5e_dcbnl_ieee_setmaxrate,
1027	.ieee_getpfc	= mlx5e_dcbnl_ieee_getpfc,
1028	.ieee_setpfc	= mlx5e_dcbnl_ieee_setpfc,
1029	.ieee_setapp    = mlx5e_dcbnl_ieee_setapp,
1030	.ieee_delapp    = mlx5e_dcbnl_ieee_delapp,
1031	.getdcbx	= mlx5e_dcbnl_getdcbx,
1032	.setdcbx	= mlx5e_dcbnl_setdcbx,
1033	.dcbnl_getbuffer = mlx5e_dcbnl_getbuffer,
1034	.dcbnl_setbuffer = mlx5e_dcbnl_setbuffer,
1035
1036/* CEE interfaces */
1037	.setall         = mlx5e_dcbnl_setall,
1038	.getstate       = mlx5e_dcbnl_getstate,
1039	.getpermhwaddr  = mlx5e_dcbnl_getpermhwaddr,
1040
1041	.setpgtccfgtx   = mlx5e_dcbnl_setpgtccfgtx,
1042	.setpgbwgcfgtx  = mlx5e_dcbnl_setpgbwgcfgtx,
1043	.getpgtccfgtx   = mlx5e_dcbnl_getpgtccfgtx,
1044	.getpgbwgcfgtx  = mlx5e_dcbnl_getpgbwgcfgtx,
1045
1046	.setpfccfg      = mlx5e_dcbnl_setpfccfg,
1047	.getpfccfg      = mlx5e_dcbnl_getpfccfg,
1048	.getcap         = mlx5e_dcbnl_getcap,
1049	.getnumtcs      = mlx5e_dcbnl_getnumtcs,
1050	.getpfcstate    = mlx5e_dcbnl_getpfcstate,
1051	.setpfcstate    = mlx5e_dcbnl_setpfcstate,
1052};
1053
1054void mlx5e_dcbnl_build_netdev(struct net_device *netdev)
1055{
1056	struct mlx5e_priv *priv = netdev_priv(netdev);
1057	struct mlx5_core_dev *mdev = priv->mdev;
1058
1059	if (MLX5_CAP_GEN(mdev, vport_group_manager) && MLX5_CAP_GEN(mdev, qos))
1060		netdev->dcbnl_ops = &mlx5e_dcbnl_ops;
1061}
1062
1063static void mlx5e_dcbnl_query_dcbx_mode(struct mlx5e_priv *priv,
1064					enum mlx5_dcbx_oper_mode *mode)
1065{
1066	u32 out[MLX5_ST_SZ_DW(dcbx_param)];
1067
1068	*mode = MLX5E_DCBX_PARAM_VER_OPER_HOST;
1069
1070	if (!mlx5_query_port_dcbx_param(priv->mdev, out))
1071		*mode = MLX5_GET(dcbx_param, out, version_oper);
1072
1073	/* From driver's point of view, we only care if the mode
1074	 * is host (HOST) or non-host (AUTO)
1075	 */
1076	if (*mode != MLX5E_DCBX_PARAM_VER_OPER_HOST)
1077		*mode = MLX5E_DCBX_PARAM_VER_OPER_AUTO;
1078}
1079
1080static void mlx5e_ets_init(struct mlx5e_priv *priv)
1081{
1082	struct ieee_ets ets;
1083	int err;
1084	int i;
1085
1086	if (!MLX5_CAP_GEN(priv->mdev, ets))
1087		return;
1088
1089	memset(&ets, 0, sizeof(ets));
1090	ets.ets_cap = mlx5_max_tc(priv->mdev) + 1;
1091	for (i = 0; i < ets.ets_cap; i++) {
1092		ets.tc_tx_bw[i] = MLX5E_MAX_BW_ALLOC;
1093		ets.tc_tsa[i] = IEEE_8021QAZ_TSA_VENDOR;
1094		ets.prio_tc[i] = i;
1095	}
1096
1097	if (ets.ets_cap > 1) {
1098		/* tclass[prio=0]=1, tclass[prio=1]=0, tclass[prio=i]=i (for i>1) */
1099		ets.prio_tc[0] = 1;
1100		ets.prio_tc[1] = 0;
1101	}
1102
1103	err = mlx5e_dcbnl_ieee_setets_core(priv, &ets);
1104	if (err)
1105		netdev_err(priv->netdev,
1106			   "%s, Failed to init ETS: %d\n", __func__, err);
1107}
1108
1109enum {
1110	INIT,
1111	DELETE,
1112};
1113
1114static void mlx5e_dcbnl_dscp_app(struct mlx5e_priv *priv, int action)
1115{
1116	struct dcb_app temp;
1117	int i;
1118
1119	if (!MLX5_CAP_GEN(priv->mdev, vport_group_manager))
1120		return;
1121
1122	if (!MLX5_DSCP_SUPPORTED(priv->mdev))
1123		return;
1124
1125	/* No SEL_DSCP entry in non DSCP state */
1126	if (priv->dcbx_dp.trust_state != MLX5_QPTS_TRUST_DSCP)
1127		return;
1128
1129	temp.selector = IEEE_8021QAZ_APP_SEL_DSCP;
1130	for (i = 0; i < MLX5E_MAX_DSCP; i++) {
1131		temp.protocol = i;
1132		temp.priority = priv->dcbx_dp.dscp2prio[i];
1133		if (action == INIT)
1134			dcb_ieee_setapp(priv->netdev, &temp);
1135		else
1136			dcb_ieee_delapp(priv->netdev, &temp);
1137	}
1138
1139	priv->dcbx.dscp_app_cnt = (action == INIT) ? MLX5E_MAX_DSCP : 0;
1140}
1141
1142void mlx5e_dcbnl_init_app(struct mlx5e_priv *priv)
1143{
1144	mlx5e_dcbnl_dscp_app(priv, INIT);
1145}
1146
1147void mlx5e_dcbnl_delete_app(struct mlx5e_priv *priv)
1148{
1149	mlx5e_dcbnl_dscp_app(priv, DELETE);
1150}
1151
1152static void mlx5e_params_calc_trust_tx_min_inline_mode(struct mlx5_core_dev *mdev,
1153						       struct mlx5e_params *params,
1154						       u8 trust_state)
1155{
1156	mlx5_query_min_inline(mdev, &params->tx_min_inline_mode);
1157	if (trust_state == MLX5_QPTS_TRUST_DSCP &&
1158	    params->tx_min_inline_mode == MLX5_INLINE_MODE_L2)
1159		params->tx_min_inline_mode = MLX5_INLINE_MODE_IP;
1160}
1161
1162static int mlx5e_update_trust_state_hw(struct mlx5e_priv *priv, void *context)
1163{
1164	u8 *trust_state = context;
1165	int err;
1166
1167	err = mlx5_set_trust_state(priv->mdev, *trust_state);
1168	if (err)
1169		return err;
1170	WRITE_ONCE(priv->dcbx_dp.trust_state, *trust_state);
1171
1172	return 0;
1173}
1174
1175static int mlx5e_set_trust_state(struct mlx5e_priv *priv, u8 trust_state)
1176{
1177	struct mlx5e_params new_params;
1178	bool reset = true;
1179	int err;
1180
1181	netdev_lock(priv->netdev);
1182	mutex_lock(&priv->state_lock);
1183
1184	new_params = priv->channels.params;
1185	mlx5e_params_calc_trust_tx_min_inline_mode(priv->mdev, &new_params,
1186						   trust_state);
1187
1188	/* Skip if tx_min_inline is the same */
1189	if (new_params.tx_min_inline_mode == priv->channels.params.tx_min_inline_mode)
1190		reset = false;
1191
1192	err = mlx5e_safe_switch_params(priv, &new_params,
1193				       mlx5e_update_trust_state_hw,
1194				       &trust_state, reset);
1195
1196	mutex_unlock(&priv->state_lock);
1197	netdev_unlock(priv->netdev);
1198
1199	return err;
1200}
1201
1202static int mlx5e_set_dscp2prio(struct mlx5e_priv *priv, u8 dscp, u8 prio)
1203{
1204	int err;
1205
1206	err = mlx5_set_dscp2prio(priv->mdev, dscp, prio);
1207	if (err)
1208		return err;
1209
1210	priv->dcbx_dp.dscp2prio[dscp] = prio;
1211	return err;
1212}
1213
1214static int mlx5e_trust_initialize(struct mlx5e_priv *priv)
1215{
1216	struct mlx5_core_dev *mdev = priv->mdev;
1217	u8 trust_state;
1218	int err;
1219
1220	if (!MLX5_DSCP_SUPPORTED(mdev)) {
1221		WRITE_ONCE(priv->dcbx_dp.trust_state, MLX5_QPTS_TRUST_PCP);
1222		return 0;
1223	}
1224
1225	err = mlx5_query_trust_state(priv->mdev, &trust_state);
1226	if (err)
1227		return err;
1228	WRITE_ONCE(priv->dcbx_dp.trust_state, trust_state);
1229
1230	if (priv->dcbx_dp.trust_state == MLX5_QPTS_TRUST_PCP && priv->dcbx.dscp_app_cnt) {
1231		/*
1232		 * Align the driver state with the register state.
1233		 * Temporary state change is required to enable the app list reset.
1234		 */
1235		priv->dcbx_dp.trust_state = MLX5_QPTS_TRUST_DSCP;
1236		mlx5e_dcbnl_delete_app(priv);
1237		priv->dcbx_dp.trust_state = MLX5_QPTS_TRUST_PCP;
1238	}
1239
1240	mlx5e_params_calc_trust_tx_min_inline_mode(priv->mdev, &priv->channels.params,
1241						   priv->dcbx_dp.trust_state);
1242
1243	err = mlx5_query_dscp2prio(priv->mdev, priv->dcbx_dp.dscp2prio);
1244	if (err)
1245		return err;
1246
1247	return 0;
1248}
1249
1250#define MLX5E_BUFFER_CELL_SHIFT 7
1251
1252static u16 mlx5e_query_port_buffers_cell_size(struct mlx5e_priv *priv)
1253{
1254	struct mlx5_core_dev *mdev = priv->mdev;
1255	u32 out[MLX5_ST_SZ_DW(sbcam_reg)] = {};
1256	u32 in[MLX5_ST_SZ_DW(sbcam_reg)] = {};
1257
1258	if (!MLX5_CAP_GEN(mdev, sbcam_reg))
1259		return (1 << MLX5E_BUFFER_CELL_SHIFT);
1260
1261	if (mlx5_core_access_reg(mdev, in, sizeof(in), out, sizeof(out),
1262				 MLX5_REG_SBCAM, 0, 0))
1263		return (1 << MLX5E_BUFFER_CELL_SHIFT);
1264
1265	return MLX5_GET(sbcam_reg, out, cap_cell_size);
1266}
1267
1268void mlx5e_dcbnl_initialize(struct mlx5e_priv *priv)
1269{
1270	struct mlx5e_dcbx *dcbx = &priv->dcbx;
1271
1272	mlx5e_trust_initialize(priv);
1273
1274	if (!MLX5_CAP_GEN(priv->mdev, qos))
1275		return;
1276
1277	if (MLX5_CAP_GEN(priv->mdev, dcbx))
1278		mlx5e_dcbnl_query_dcbx_mode(priv, &dcbx->mode);
1279
1280	priv->dcbx.cap = DCB_CAP_DCBX_VER_CEE |
1281			 DCB_CAP_DCBX_VER_IEEE;
1282	if (priv->dcbx.mode == MLX5E_DCBX_PARAM_VER_OPER_HOST)
1283		priv->dcbx.cap |= DCB_CAP_DCBX_HOST;
1284
1285	priv->dcbx.port_buff_cell_sz = mlx5e_query_port_buffers_cell_size(priv);
1286	priv->dcbx.cable_len = MLX5E_DEFAULT_CABLE_LEN;
1287
1288	mlx5e_ets_init(priv);
1289}
~/ Read-only file preview.