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