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