linux/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
<<
>>
Prefs
   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
  47enum {
  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
  56static int mlx5e_set_trust_state(struct mlx5e_priv *priv, u8 trust_state);
  57static 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 */
  61static 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
  79static 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
  98static 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
 154static 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
 193static 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 */
 241int 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
 277static 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
 312static 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
 332static 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
 352static 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
 399static 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
 406static 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
 439static 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
 489fw_err:
 490        mlx5e_set_trust_state(priv, MLX5_QPTS_TRUST_PCP);
 491        return err;
 492}
 493
 494static 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
 533fw_err:
 534        mlx5e_set_trust_state(priv, MLX5_QPTS_TRUST_PCP);
 535        return err;
 536}
 537
 538static 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
 573static 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
 611static 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        }
 664out:
 665        return err ? MLX5_DCB_NO_CHG : MLX5_DCB_CHG_RESET;
 666}
 667
 668static u8 mlx5e_dcbnl_getstate(struct net_device *netdev)
 669{
 670        return MLX5E_CEE_STATE_UP;
 671}
 672
 673static 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_nic_vport_mac_address(priv->mdev, 0, perm_addr);
 684}
 685
 686static 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
 708static 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
 723static 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
 749static 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
 764static 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
 782static int
 783mlx5e_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
 799static 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
 814static 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
 857static 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
 875static 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
 885static 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
 896static 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
 926static 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
 980const 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
1012static 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
1029static 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
1058enum {
1059        INIT,
1060        DELETE,
1061};
1062
1063static 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
1091void mlx5e_dcbnl_init_app(struct mlx5e_priv *priv)
1092{
1093        mlx5e_dcbnl_dscp_app(priv, INIT);
1094}
1095
1096void mlx5e_dcbnl_delete_app(struct mlx5e_priv *priv)
1097{
1098        mlx5e_dcbnl_dscp_app(priv, DELETE);
1099}
1100
1101static void mlx5e_trust_update_tx_min_inline_mode(struct mlx5e_priv *priv,
1102                                                  struct mlx5e_params *params)
1103{
1104        params->tx_min_inline_mode = mlx5e_params_calculate_tx_min_inline(priv->mdev);
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
1110static 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        if (mlx5e_open_channels(priv, &new_channels))
1130                goto out;
1131        mlx5e_switch_priv_channels(priv, &new_channels, NULL);
1132
1133out:
1134        mutex_unlock(&priv->state_lock);
1135}
1136
1137static int mlx5e_set_trust_state(struct mlx5e_priv *priv, u8 trust_state)
1138{
1139        int err;
1140
1141        err = mlx5_set_trust_state(priv->mdev, trust_state);
1142        if (err)
1143                return err;
1144        priv->dcbx_dp.trust_state = trust_state;
1145        mlx5e_trust_update_sq_inline_mode(priv);
1146
1147        return err;
1148}
1149
1150static int mlx5e_set_dscp2prio(struct mlx5e_priv *priv, u8 dscp, u8 prio)
1151{
1152        int err;
1153
1154        err = mlx5_set_dscp2prio(priv->mdev, dscp, prio);
1155        if (err)
1156                return err;
1157
1158        priv->dcbx_dp.dscp2prio[dscp] = prio;
1159        return err;
1160}
1161
1162static int mlx5e_trust_initialize(struct mlx5e_priv *priv)
1163{
1164        struct mlx5_core_dev *mdev = priv->mdev;
1165        int err;
1166
1167        priv->dcbx_dp.trust_state = MLX5_QPTS_TRUST_PCP;
1168
1169        if (!MLX5_DSCP_SUPPORTED(mdev))
1170                return 0;
1171
1172        err = mlx5_query_trust_state(priv->mdev, &priv->dcbx_dp.trust_state);
1173        if (err)
1174                return err;
1175
1176        mlx5e_trust_update_tx_min_inline_mode(priv, &priv->channels.params);
1177
1178        err = mlx5_query_dscp2prio(priv->mdev, priv->dcbx_dp.dscp2prio);
1179        if (err)
1180                return err;
1181
1182        return 0;
1183}
1184
1185void mlx5e_dcbnl_initialize(struct mlx5e_priv *priv)
1186{
1187        struct mlx5e_dcbx *dcbx = &priv->dcbx;
1188
1189        mlx5e_trust_initialize(priv);
1190
1191        if (!MLX5_CAP_GEN(priv->mdev, qos))
1192                return;
1193
1194        if (MLX5_CAP_GEN(priv->mdev, dcbx))
1195                mlx5e_dcbnl_query_dcbx_mode(priv, &dcbx->mode);
1196
1197        priv->dcbx.cap = DCB_CAP_DCBX_VER_CEE |
1198                         DCB_CAP_DCBX_VER_IEEE;
1199        if (priv->dcbx.mode == MLX5E_DCBX_PARAM_VER_OPER_HOST)
1200                priv->dcbx.cap |= DCB_CAP_DCBX_HOST;
1201
1202        priv->dcbx.manual_buffer = false;
1203        priv->dcbx.cable_len = MLX5E_DEFAULT_CABLE_LEN;
1204
1205        mlx5e_ets_init(priv);
1206}
1207