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