root/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mlx5e_dcbnl_set_dcbx_mode
  2. mlx5e_dcbnl_switch_to_host_mode
  3. mlx5e_dcbnl_ieee_getets
  4. mlx5e_build_tc_group
  5. mlx5e_build_tc_tx_bw
  6. mlx5e_dcbnl_ieee_setets_core
  7. mlx5e_dbcnl_validate_ets
  8. mlx5e_dcbnl_ieee_setets
  9. mlx5e_dcbnl_ieee_getpfc
  10. mlx5e_dcbnl_ieee_setpfc
  11. mlx5e_dcbnl_getdcbx
  12. mlx5e_dcbnl_setdcbx
  13. mlx5e_dcbnl_ieee_setapp
  14. mlx5e_dcbnl_ieee_delapp
  15. mlx5e_dcbnl_ieee_getmaxrate
  16. mlx5e_dcbnl_ieee_setmaxrate
  17. mlx5e_dcbnl_setall
  18. mlx5e_dcbnl_getstate
  19. mlx5e_dcbnl_getpermhwaddr
  20. mlx5e_dcbnl_setpgtccfgtx
  21. mlx5e_dcbnl_setpgbwgcfgtx
  22. mlx5e_dcbnl_getpgtccfgtx
  23. mlx5e_dcbnl_getpgbwgcfgtx
  24. mlx5e_dcbnl_setpfccfg
  25. mlx5e_dcbnl_get_priority_pfc
  26. mlx5e_dcbnl_getpfccfg
  27. mlx5e_dcbnl_getcap
  28. mlx5e_dcbnl_getnumtcs
  29. mlx5e_dcbnl_getpfcstate
  30. mlx5e_dcbnl_setpfcstate
  31. mlx5e_dcbnl_getbuffer
  32. mlx5e_dcbnl_setbuffer
  33. mlx5e_dcbnl_query_dcbx_mode
  34. mlx5e_ets_init
  35. mlx5e_dcbnl_dscp_app
  36. mlx5e_dcbnl_init_app
  37. mlx5e_dcbnl_delete_app
  38. mlx5e_trust_update_tx_min_inline_mode
  39. mlx5e_trust_update_sq_inline_mode
  40. mlx5e_set_trust_state
  41. mlx5e_set_dscp2prio
  42. mlx5e_trust_initialize
  43. mlx5e_dcbnl_initialize

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

/* [<][>][^][v][top][bottom][index][help] */