en_dcb_nl.c (19994B)
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};