1 /*- 2 * Copyright (c) 2015-2019 Mellanox Technologies. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS' AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 * 25 * $FreeBSD$ 26 */ 27 28 #include "en.h" 29 #include "port_buffer.h" 30 #include <net/sff8472.h> 31 32 void 33 mlx5e_create_stats(struct sysctl_ctx_list *ctx, 34 struct sysctl_oid_list *parent, const char *buffer, 35 const char **desc, unsigned num, u64 * arg) 36 { 37 struct sysctl_oid *node; 38 unsigned x; 39 40 sysctl_ctx_init(ctx); 41 42 node = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, 43 buffer, CTLFLAG_RD, NULL, "Statistics"); 44 if (node == NULL) 45 return; 46 for (x = 0; x != num; x++) { 47 SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO, 48 desc[2 * x], CTLFLAG_RD, arg + x, desc[2 * x + 1]); 49 } 50 } 51 52 static void 53 mlx5e_ethtool_sync_tx_completion_fact(struct mlx5e_priv *priv) 54 { 55 /* 56 * Limit the maximum distance between completion events to 57 * half of the currently set TX queue size. 58 * 59 * The maximum number of queue entries a single IP packet can 60 * consume is given by MLX5_SEND_WQE_MAX_WQEBBS. 61 * 62 * The worst case max value is then given as below: 63 */ 64 uint64_t max = priv->params_ethtool.tx_queue_size / 65 (2 * MLX5_SEND_WQE_MAX_WQEBBS); 66 67 /* 68 * Update the maximum completion factor value in case the 69 * tx_queue_size field changed. Ensure we don't overflow 70 * 16-bits. 71 */ 72 if (max < 1) 73 max = 1; 74 else if (max > 65535) 75 max = 65535; 76 priv->params_ethtool.tx_completion_fact_max = max; 77 78 /* 79 * Verify that the current TX completion factor is within the 80 * given limits: 81 */ 82 if (priv->params_ethtool.tx_completion_fact < 1) 83 priv->params_ethtool.tx_completion_fact = 1; 84 else if (priv->params_ethtool.tx_completion_fact > max) 85 priv->params_ethtool.tx_completion_fact = max; 86 } 87 88 static int 89 mlx5e_getmaxrate(struct mlx5e_priv *priv) 90 { 91 struct mlx5_core_dev *mdev = priv->mdev; 92 u8 max_bw_unit[IEEE_8021QAZ_MAX_TCS]; 93 u8 max_bw_value[IEEE_8021QAZ_MAX_TCS]; 94 int err; 95 int i; 96 97 PRIV_LOCK(priv); 98 err = -mlx5_query_port_tc_rate_limit(mdev, max_bw_value, max_bw_unit); 99 if (err) 100 goto done; 101 102 for (i = 0; i <= mlx5_max_tc(mdev); i++) { 103 switch (max_bw_unit[i]) { 104 case MLX5_100_MBPS_UNIT: 105 priv->params_ethtool.max_bw_value[i] = max_bw_value[i] * MLX5E_100MB; 106 break; 107 case MLX5_GBPS_UNIT: 108 priv->params_ethtool.max_bw_value[i] = max_bw_value[i] * MLX5E_1GB; 109 break; 110 case MLX5_BW_NO_LIMIT: 111 priv->params_ethtool.max_bw_value[i] = 0; 112 break; 113 default: 114 priv->params_ethtool.max_bw_value[i] = -1; 115 WARN_ONCE(true, "non-supported BW unit"); 116 break; 117 } 118 } 119 done: 120 PRIV_UNLOCK(priv); 121 return (err); 122 } 123 124 static int 125 mlx5e_get_max_alloc(struct mlx5e_priv *priv) 126 { 127 struct mlx5_core_dev *mdev = priv->mdev; 128 int err; 129 int x; 130 131 PRIV_LOCK(priv); 132 err = -mlx5_query_port_tc_bw_alloc(mdev, priv->params_ethtool.max_bw_share); 133 if (err == 0) { 134 /* set default value */ 135 for (x = 0; x != IEEE_8021QAZ_MAX_TCS; x++) { 136 priv->params_ethtool.max_bw_share[x] = 137 100 / IEEE_8021QAZ_MAX_TCS; 138 } 139 err = -mlx5_set_port_tc_bw_alloc(mdev, 140 priv->params_ethtool.max_bw_share); 141 } 142 PRIV_UNLOCK(priv); 143 144 return (err); 145 } 146 147 static int 148 mlx5e_get_dscp(struct mlx5e_priv *priv) 149 { 150 struct mlx5_core_dev *mdev = priv->mdev; 151 int err; 152 153 if (MLX5_CAP_GEN(mdev, qcam_reg) == 0 || 154 MLX5_CAP_QCAM_REG(mdev, qpts) == 0 || 155 MLX5_CAP_QCAM_REG(mdev, qpdpm) == 0) 156 return (EOPNOTSUPP); 157 158 PRIV_LOCK(priv); 159 err = -mlx5_query_dscp2prio(mdev, priv->params_ethtool.dscp2prio); 160 if (err) 161 goto done; 162 163 err = -mlx5_query_trust_state(mdev, &priv->params_ethtool.trust_state); 164 if (err) 165 goto done; 166 done: 167 PRIV_UNLOCK(priv); 168 return (err); 169 } 170 171 static void 172 mlx5e_tc_get_parameters(struct mlx5e_priv *priv, 173 u64 *new_bw_value, u8 *max_bw_value, u8 *max_bw_unit) 174 { 175 const u64 upper_limit_mbps = 255 * MLX5E_100MB; 176 const u64 upper_limit_gbps = 255 * MLX5E_1GB; 177 u64 temp; 178 int i; 179 180 memset(max_bw_value, 0, IEEE_8021QAZ_MAX_TCS); 181 memset(max_bw_unit, 0, IEEE_8021QAZ_MAX_TCS); 182 183 for (i = 0; i <= mlx5_max_tc(priv->mdev); i++) { 184 temp = (new_bw_value != NULL) ? 185 new_bw_value[i] : priv->params_ethtool.max_bw_value[i]; 186 187 if (!temp) { 188 max_bw_unit[i] = MLX5_BW_NO_LIMIT; 189 } else if (temp > upper_limit_gbps) { 190 max_bw_unit[i] = MLX5_BW_NO_LIMIT; 191 } else if (temp <= upper_limit_mbps) { 192 max_bw_value[i] = howmany(temp, MLX5E_100MB); 193 max_bw_unit[i] = MLX5_100_MBPS_UNIT; 194 } else { 195 max_bw_value[i] = howmany(temp, MLX5E_1GB); 196 max_bw_unit[i] = MLX5_GBPS_UNIT; 197 } 198 } 199 } 200 201 static int 202 mlx5e_tc_maxrate_handler(SYSCTL_HANDLER_ARGS) 203 { 204 struct mlx5e_priv *priv = arg1; 205 struct mlx5_core_dev *mdev = priv->mdev; 206 u8 max_bw_unit[IEEE_8021QAZ_MAX_TCS]; 207 u8 max_bw_value[IEEE_8021QAZ_MAX_TCS]; 208 u64 new_bw_value[IEEE_8021QAZ_MAX_TCS]; 209 u8 max_rates = mlx5_max_tc(mdev) + 1; 210 u8 x; 211 int err; 212 213 PRIV_LOCK(priv); 214 err = SYSCTL_OUT(req, priv->params_ethtool.max_bw_value, 215 sizeof(priv->params_ethtool.max_bw_value[0]) * max_rates); 216 if (err || !req->newptr) 217 goto done; 218 err = SYSCTL_IN(req, new_bw_value, 219 sizeof(new_bw_value[0]) * max_rates); 220 if (err) 221 goto done; 222 223 /* range check input value */ 224 for (x = 0; x != max_rates; x++) { 225 if (new_bw_value[x] % MLX5E_100MB) { 226 err = ERANGE; 227 goto done; 228 } 229 } 230 231 mlx5e_tc_get_parameters(priv, new_bw_value, max_bw_value, max_bw_unit); 232 233 err = -mlx5_modify_port_tc_rate_limit(mdev, max_bw_value, max_bw_unit); 234 if (err) 235 goto done; 236 237 memcpy(priv->params_ethtool.max_bw_value, new_bw_value, 238 sizeof(priv->params_ethtool.max_bw_value)); 239 done: 240 PRIV_UNLOCK(priv); 241 return (err); 242 } 243 244 static int 245 mlx5e_tc_rate_share_handler(SYSCTL_HANDLER_ARGS) 246 { 247 struct mlx5e_priv *priv = arg1; 248 struct mlx5_core_dev *mdev = priv->mdev; 249 u8 max_bw_share[IEEE_8021QAZ_MAX_TCS]; 250 u8 max_rates = mlx5_max_tc(mdev) + 1; 251 int i; 252 int err; 253 int sum; 254 255 PRIV_LOCK(priv); 256 err = SYSCTL_OUT(req, priv->params_ethtool.max_bw_share, max_rates); 257 if (err || !req->newptr) 258 goto done; 259 err = SYSCTL_IN(req, max_bw_share, max_rates); 260 if (err) 261 goto done; 262 263 /* range check input value */ 264 for (sum = i = 0; i != max_rates; i++) { 265 if (max_bw_share[i] < 1 || max_bw_share[i] > 100) { 266 err = ERANGE; 267 goto done; 268 } 269 sum += max_bw_share[i]; 270 } 271 272 /* sum of values should be as close to 100 as possible */ 273 if (sum < (100 - max_rates + 1) || sum > 100) { 274 err = ERANGE; 275 goto done; 276 } 277 278 err = -mlx5_set_port_tc_bw_alloc(mdev, max_bw_share); 279 if (err) 280 goto done; 281 282 memcpy(priv->params_ethtool.max_bw_share, max_bw_share, 283 sizeof(priv->params_ethtool.max_bw_share)); 284 done: 285 PRIV_UNLOCK(priv); 286 return (err); 287 } 288 289 static int 290 mlx5e_get_prio_tc(struct mlx5e_priv *priv) 291 { 292 struct mlx5_core_dev *mdev = priv->mdev; 293 int err = 0; 294 int i; 295 296 PRIV_LOCK(priv); 297 if (!MLX5_CAP_GEN(priv->mdev, ets)) { 298 PRIV_UNLOCK(priv); 299 return (EOPNOTSUPP); 300 } 301 302 for (i = 0; i != MLX5E_MAX_PRIORITY; i++) { 303 err = -mlx5_query_port_prio_tc(mdev, i, priv->params_ethtool.prio_tc + i); 304 if (err) 305 break; 306 } 307 PRIV_UNLOCK(priv); 308 return (err); 309 } 310 311 static int 312 mlx5e_prio_to_tc_handler(SYSCTL_HANDLER_ARGS) 313 { 314 struct mlx5e_priv *priv = arg1; 315 struct mlx5_core_dev *mdev = priv->mdev; 316 uint8_t temp[MLX5E_MAX_PRIORITY]; 317 int err; 318 int i; 319 320 PRIV_LOCK(priv); 321 err = SYSCTL_OUT(req, priv->params_ethtool.prio_tc, MLX5E_MAX_PRIORITY); 322 if (err || !req->newptr) 323 goto done; 324 err = SYSCTL_IN(req, temp, MLX5E_MAX_PRIORITY); 325 if (err) 326 goto done; 327 328 for (i = 0; i != MLX5E_MAX_PRIORITY; i++) { 329 if (temp[i] > mlx5_max_tc(mdev)) { 330 err = ERANGE; 331 goto done; 332 } 333 } 334 335 for (i = 0; i != MLX5E_MAX_PRIORITY; i++) { 336 if (temp[i] == priv->params_ethtool.prio_tc[i]) 337 continue; 338 err = -mlx5_set_port_prio_tc(mdev, i, temp[i]); 339 if (err) 340 goto done; 341 /* update cached value */ 342 priv->params_ethtool.prio_tc[i] = temp[i]; 343 } 344 done: 345 PRIV_UNLOCK(priv); 346 return (err); 347 } 348 349 int 350 mlx5e_fec_update(struct mlx5e_priv *priv) 351 { 352 struct mlx5_core_dev *mdev = priv->mdev; 353 u32 in[MLX5_ST_SZ_DW(pplm_reg)] = {}; 354 const int sz = MLX5_ST_SZ_BYTES(pplm_reg); 355 int err; 356 357 if (!MLX5_CAP_GEN(mdev, pcam_reg)) 358 return (EOPNOTSUPP); 359 360 if (!MLX5_CAP_PCAM_REG(mdev, pplm)) 361 return (EOPNOTSUPP); 362 363 MLX5_SET(pplm_reg, in, local_port, 1); 364 365 err = -mlx5_core_access_reg(mdev, in, sz, in, sz, MLX5_REG_PPLM, 0, 0); 366 if (err) 367 return (err); 368 369 /* get 10x..25x mask */ 370 priv->params_ethtool.fec_mask_10x_25x[0] = 371 MLX5_GET(pplm_reg, in, fec_override_admin_10g_40g); 372 priv->params_ethtool.fec_mask_10x_25x[1] = 373 MLX5_GET(pplm_reg, in, fec_override_admin_25g) & 374 MLX5_GET(pplm_reg, in, fec_override_admin_50g); 375 priv->params_ethtool.fec_mask_10x_25x[2] = 376 MLX5_GET(pplm_reg, in, fec_override_admin_56g); 377 priv->params_ethtool.fec_mask_10x_25x[3] = 378 MLX5_GET(pplm_reg, in, fec_override_admin_100g); 379 380 /* get 10x..25x available bits */ 381 priv->params_ethtool.fec_avail_10x_25x[0] = 382 MLX5_GET(pplm_reg, in, fec_override_cap_10g_40g); 383 priv->params_ethtool.fec_avail_10x_25x[1] = 384 MLX5_GET(pplm_reg, in, fec_override_cap_25g) & 385 MLX5_GET(pplm_reg, in, fec_override_cap_50g); 386 priv->params_ethtool.fec_avail_10x_25x[2] = 387 MLX5_GET(pplm_reg, in, fec_override_cap_56g); 388 priv->params_ethtool.fec_avail_10x_25x[3] = 389 MLX5_GET(pplm_reg, in, fec_override_cap_100g); 390 391 /* get 50x mask */ 392 priv->params_ethtool.fec_mask_50x[0] = 393 MLX5_GET(pplm_reg, in, fec_override_admin_50g_1x); 394 priv->params_ethtool.fec_mask_50x[1] = 395 MLX5_GET(pplm_reg, in, fec_override_admin_100g_2x); 396 priv->params_ethtool.fec_mask_50x[2] = 397 MLX5_GET(pplm_reg, in, fec_override_admin_200g_4x); 398 priv->params_ethtool.fec_mask_50x[3] = 399 MLX5_GET(pplm_reg, in, fec_override_admin_400g_8x); 400 401 /* get 50x available bits */ 402 priv->params_ethtool.fec_avail_50x[0] = 403 MLX5_GET(pplm_reg, in, fec_override_cap_50g_1x); 404 priv->params_ethtool.fec_avail_50x[1] = 405 MLX5_GET(pplm_reg, in, fec_override_cap_100g_2x); 406 priv->params_ethtool.fec_avail_50x[2] = 407 MLX5_GET(pplm_reg, in, fec_override_cap_200g_4x); 408 priv->params_ethtool.fec_avail_50x[3] = 409 MLX5_GET(pplm_reg, in, fec_override_cap_400g_8x); 410 411 /* get current FEC mask */ 412 priv->params_ethtool.fec_mode_active = 413 MLX5_GET(pplm_reg, in, fec_mode_active); 414 415 return (0); 416 } 417 418 static int 419 mlx5e_fec_mask_10x_25x_handler(SYSCTL_HANDLER_ARGS) 420 { 421 struct mlx5e_priv *priv = arg1; 422 struct mlx5_core_dev *mdev = priv->mdev; 423 u32 out[MLX5_ST_SZ_DW(pplm_reg)] = {}; 424 u32 in[MLX5_ST_SZ_DW(pplm_reg)] = {}; 425 const int sz = MLX5_ST_SZ_BYTES(pplm_reg); 426 u8 fec_mask_10x_25x[MLX5E_MAX_FEC_10X_25X]; 427 u8 fec_cap_changed = 0; 428 u8 x; 429 int err; 430 431 PRIV_LOCK(priv); 432 err = SYSCTL_OUT(req, priv->params_ethtool.fec_mask_10x_25x, 433 sizeof(priv->params_ethtool.fec_mask_10x_25x)); 434 if (err || !req->newptr) 435 goto done; 436 437 err = SYSCTL_IN(req, fec_mask_10x_25x, 438 sizeof(fec_mask_10x_25x)); 439 if (err) 440 goto done; 441 442 if (!MLX5_CAP_GEN(mdev, pcam_reg)) { 443 err = EOPNOTSUPP; 444 goto done; 445 } 446 447 if (!MLX5_CAP_PCAM_REG(mdev, pplm)) { 448 err = EOPNOTSUPP; 449 goto done; 450 } 451 452 MLX5_SET(pplm_reg, in, local_port, 1); 453 454 err = -mlx5_core_access_reg(mdev, in, sz, in, sz, MLX5_REG_PPLM, 0, 0); 455 if (err) 456 goto done; 457 458 /* range check input value */ 459 for (x = 0; x != MLX5E_MAX_FEC_10X_25X; x++) { 460 /* check only one bit is set, if any */ 461 if (fec_mask_10x_25x[x] & (fec_mask_10x_25x[x] - 1)) { 462 err = ERANGE; 463 goto done; 464 } 465 /* check a supported bit is set, if any */ 466 if (fec_mask_10x_25x[x] & 467 ~priv->params_ethtool.fec_avail_10x_25x[x]) { 468 err = ERANGE; 469 goto done; 470 } 471 fec_cap_changed |= (fec_mask_10x_25x[x] ^ 472 priv->params_ethtool.fec_mask_10x_25x[x]); 473 } 474 475 /* check for no changes */ 476 if (fec_cap_changed == 0) 477 goto done; 478 479 memset(in, 0, sizeof(in)); 480 481 MLX5_SET(pplm_reg, in, local_port, 1); 482 483 /* set new values */ 484 MLX5_SET(pplm_reg, in, fec_override_admin_10g_40g, fec_mask_10x_25x[0]); 485 MLX5_SET(pplm_reg, in, fec_override_admin_25g, fec_mask_10x_25x[1]); 486 MLX5_SET(pplm_reg, in, fec_override_admin_50g, fec_mask_10x_25x[1]); 487 MLX5_SET(pplm_reg, in, fec_override_admin_56g, fec_mask_10x_25x[2]); 488 MLX5_SET(pplm_reg, in, fec_override_admin_100g, fec_mask_10x_25x[3]); 489 490 /* preserve other values */ 491 MLX5_SET(pplm_reg, in, fec_override_admin_50g_1x, priv->params_ethtool.fec_mask_50x[0]); 492 MLX5_SET(pplm_reg, in, fec_override_admin_100g_2x, priv->params_ethtool.fec_mask_50x[1]); 493 MLX5_SET(pplm_reg, in, fec_override_admin_200g_4x, priv->params_ethtool.fec_mask_50x[2]); 494 MLX5_SET(pplm_reg, in, fec_override_admin_400g_8x, priv->params_ethtool.fec_mask_50x[3]); 495 496 /* send new value to the firmware */ 497 err = -mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPLM, 0, 1); 498 if (err) 499 goto done; 500 501 memcpy(priv->params_ethtool.fec_mask_10x_25x, fec_mask_10x_25x, 502 sizeof(priv->params_ethtool.fec_mask_10x_25x)); 503 504 mlx5_toggle_port_link(priv->mdev); 505 done: 506 PRIV_UNLOCK(priv); 507 return (err); 508 } 509 510 static int 511 mlx5e_fec_avail_10x_25x_handler(SYSCTL_HANDLER_ARGS) 512 { 513 struct mlx5e_priv *priv = arg1; 514 int err; 515 516 PRIV_LOCK(priv); 517 err = SYSCTL_OUT(req, priv->params_ethtool.fec_avail_10x_25x, 518 sizeof(priv->params_ethtool.fec_avail_10x_25x)); 519 PRIV_UNLOCK(priv); 520 return (err); 521 } 522 523 static int 524 mlx5e_fec_mask_50x_handler(SYSCTL_HANDLER_ARGS) 525 { 526 struct mlx5e_priv *priv = arg1; 527 struct mlx5_core_dev *mdev = priv->mdev; 528 u32 out[MLX5_ST_SZ_DW(pplm_reg)] = {}; 529 u32 in[MLX5_ST_SZ_DW(pplm_reg)] = {}; 530 const int sz = MLX5_ST_SZ_BYTES(pplm_reg); 531 u16 fec_mask_50x[MLX5E_MAX_FEC_50X]; 532 u16 fec_cap_changed = 0; 533 u8 x; 534 int err; 535 536 PRIV_LOCK(priv); 537 err = SYSCTL_OUT(req, priv->params_ethtool.fec_mask_50x, 538 sizeof(priv->params_ethtool.fec_mask_50x)); 539 if (err || !req->newptr) 540 goto done; 541 542 err = SYSCTL_IN(req, fec_mask_50x, 543 sizeof(fec_mask_50x)); 544 if (err) 545 goto done; 546 547 if (!MLX5_CAP_GEN(mdev, pcam_reg)) { 548 err = EOPNOTSUPP; 549 goto done; 550 } 551 552 if (!MLX5_CAP_PCAM_REG(mdev, pplm)) { 553 err = EOPNOTSUPP; 554 goto done; 555 } 556 557 MLX5_SET(pplm_reg, in, local_port, 1); 558 559 err = -mlx5_core_access_reg(mdev, in, sz, in, sz, MLX5_REG_PPLM, 0, 0); 560 if (err) 561 goto done; 562 563 /* range check input value */ 564 for (x = 0; x != MLX5E_MAX_FEC_50X; x++) { 565 /* check only one bit is set, if any */ 566 if (fec_mask_50x[x] & (fec_mask_50x[x] - 1)) { 567 err = ERANGE; 568 goto done; 569 } 570 /* check a supported bit is set, if any */ 571 if (fec_mask_50x[x] & 572 ~priv->params_ethtool.fec_avail_50x[x]) { 573 err = ERANGE; 574 goto done; 575 } 576 fec_cap_changed |= (fec_mask_50x[x] ^ 577 priv->params_ethtool.fec_mask_50x[x]); 578 } 579 580 /* check for no changes */ 581 if (fec_cap_changed == 0) 582 goto done; 583 584 memset(in, 0, sizeof(in)); 585 586 MLX5_SET(pplm_reg, in, local_port, 1); 587 588 /* set new values */ 589 MLX5_SET(pplm_reg, in, fec_override_admin_50g_1x, fec_mask_50x[0]); 590 MLX5_SET(pplm_reg, in, fec_override_admin_100g_2x, fec_mask_50x[1]); 591 MLX5_SET(pplm_reg, in, fec_override_admin_200g_4x, fec_mask_50x[2]); 592 MLX5_SET(pplm_reg, in, fec_override_admin_400g_8x, fec_mask_50x[3]); 593 594 /* preserve other values */ 595 MLX5_SET(pplm_reg, in, fec_override_admin_10g_40g, priv->params_ethtool.fec_mask_10x_25x[0]); 596 MLX5_SET(pplm_reg, in, fec_override_admin_25g, priv->params_ethtool.fec_mask_10x_25x[1]); 597 MLX5_SET(pplm_reg, in, fec_override_admin_50g, priv->params_ethtool.fec_mask_10x_25x[1]); 598 MLX5_SET(pplm_reg, in, fec_override_admin_56g, priv->params_ethtool.fec_mask_10x_25x[2]); 599 MLX5_SET(pplm_reg, in, fec_override_admin_100g, priv->params_ethtool.fec_mask_10x_25x[3]); 600 601 /* send new value to the firmware */ 602 err = -mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPLM, 0, 1); 603 if (err) 604 goto done; 605 606 memcpy(priv->params_ethtool.fec_mask_50x, fec_mask_50x, 607 sizeof(priv->params_ethtool.fec_mask_50x)); 608 609 mlx5_toggle_port_link(priv->mdev); 610 done: 611 PRIV_UNLOCK(priv); 612 return (err); 613 } 614 615 static int 616 mlx5e_fec_avail_50x_handler(SYSCTL_HANDLER_ARGS) 617 { 618 struct mlx5e_priv *priv = arg1; 619 int err; 620 621 PRIV_LOCK(priv); 622 err = SYSCTL_OUT(req, priv->params_ethtool.fec_avail_50x, 623 sizeof(priv->params_ethtool.fec_avail_50x)); 624 PRIV_UNLOCK(priv); 625 return (err); 626 } 627 628 static int 629 mlx5e_trust_state_handler(SYSCTL_HANDLER_ARGS) 630 { 631 struct mlx5e_priv *priv = arg1; 632 struct mlx5_core_dev *mdev = priv->mdev; 633 int err; 634 u8 result; 635 636 PRIV_LOCK(priv); 637 result = priv->params_ethtool.trust_state; 638 err = sysctl_handle_8(oidp, &result, 0, req); 639 if (err || !req->newptr || 640 result == priv->params_ethtool.trust_state) 641 goto done; 642 643 switch (result) { 644 case MLX5_QPTS_TRUST_PCP: 645 case MLX5_QPTS_TRUST_DSCP: 646 break; 647 case MLX5_QPTS_TRUST_BOTH: 648 if (!MLX5_CAP_QCAM_FEATURE(mdev, qpts_trust_both)) { 649 err = EOPNOTSUPP; 650 goto done; 651 } 652 break; 653 default: 654 err = ERANGE; 655 goto done; 656 } 657 658 err = -mlx5_set_trust_state(mdev, result); 659 if (err) 660 goto done; 661 662 priv->params_ethtool.trust_state = result; 663 664 /* update inline mode */ 665 mlx5e_refresh_sq_inline(priv); 666 #ifdef RATELIMIT 667 mlx5e_rl_refresh_sq_inline(&priv->rl); 668 #endif 669 done: 670 PRIV_UNLOCK(priv); 671 return (err); 672 } 673 674 static int 675 mlx5e_dscp_prio_handler(SYSCTL_HANDLER_ARGS) 676 { 677 struct mlx5e_priv *priv = arg1; 678 int prio_index = arg2; 679 struct mlx5_core_dev *mdev = priv->mdev; 680 uint8_t dscp2prio[MLX5_MAX_SUPPORTED_DSCP]; 681 uint8_t x; 682 int err; 683 684 PRIV_LOCK(priv); 685 err = SYSCTL_OUT(req, priv->params_ethtool.dscp2prio + prio_index, 686 sizeof(priv->params_ethtool.dscp2prio) / 8); 687 if (err || !req->newptr) 688 goto done; 689 690 memcpy(dscp2prio, priv->params_ethtool.dscp2prio, sizeof(dscp2prio)); 691 err = SYSCTL_IN(req, dscp2prio + prio_index, sizeof(dscp2prio) / 8); 692 if (err) 693 goto done; 694 for (x = 0; x != MLX5_MAX_SUPPORTED_DSCP; x++) { 695 if (dscp2prio[x] > 7) { 696 err = ERANGE; 697 goto done; 698 } 699 } 700 err = -mlx5_set_dscp2prio(mdev, dscp2prio); 701 if (err) 702 goto done; 703 704 /* update local array */ 705 memcpy(priv->params_ethtool.dscp2prio, dscp2prio, 706 sizeof(priv->params_ethtool.dscp2prio)); 707 done: 708 PRIV_UNLOCK(priv); 709 return (err); 710 } 711 712 int 713 mlx5e_update_buf_lossy(struct mlx5e_priv *priv) 714 { 715 struct ieee_pfc pfc; 716 717 PRIV_ASSERT_LOCKED(priv); 718 bzero(&pfc, sizeof(pfc)); 719 pfc.pfc_en = priv->params.rx_priority_flow_control; 720 return (-mlx5e_port_manual_buffer_config(priv, MLX5E_PORT_BUFFER_PFC, 721 priv->params_ethtool.hw_mtu, &pfc, NULL, NULL)); 722 } 723 724 static int 725 mlx5e_buf_size_handler(SYSCTL_HANDLER_ARGS) 726 { 727 struct mlx5e_priv *priv; 728 u32 buf_size[MLX5E_MAX_BUFFER]; 729 struct mlx5e_port_buffer port_buffer; 730 int error, i; 731 732 priv = arg1; 733 PRIV_LOCK(priv); 734 error = -mlx5e_port_query_buffer(priv, &port_buffer); 735 if (error != 0) 736 goto done; 737 for (i = 0; i < nitems(buf_size); i++) 738 buf_size[i] = port_buffer.buffer[i].size; 739 error = SYSCTL_OUT(req, buf_size, sizeof(buf_size)); 740 if (error != 0 || req->newptr == NULL) 741 goto done; 742 error = SYSCTL_IN(req, buf_size, sizeof(buf_size)); 743 if (error != 0) 744 goto done; 745 error = -mlx5e_port_manual_buffer_config(priv, MLX5E_PORT_BUFFER_SIZE, 746 priv->params_ethtool.hw_mtu, NULL, buf_size, NULL); 747 done: 748 PRIV_UNLOCK(priv); 749 return (error); 750 } 751 752 static int 753 mlx5e_buf_prio_handler(SYSCTL_HANDLER_ARGS) 754 { 755 struct mlx5e_priv *priv; 756 struct mlx5_core_dev *mdev; 757 u8 buffer[MLX5E_MAX_BUFFER]; 758 int error; 759 760 priv = arg1; 761 mdev = priv->mdev; 762 PRIV_LOCK(priv); 763 error = -mlx5e_port_query_priority2buffer(mdev, buffer); 764 if (error != 0) 765 goto done; 766 error = SYSCTL_OUT(req, buffer, MLX5E_MAX_BUFFER); 767 if (error != 0 || req->newptr == NULL) 768 goto done; 769 error = SYSCTL_IN(req, buffer, MLX5E_MAX_BUFFER); 770 if (error != 0) 771 goto done; 772 error = -mlx5e_port_manual_buffer_config(priv, 773 MLX5E_PORT_BUFFER_PRIO2BUFFER, 774 priv->params_ethtool.hw_mtu, NULL, NULL, buffer); 775 if (error == 0) 776 error = mlx5e_update_buf_lossy(priv); 777 done: 778 PRIV_UNLOCK(priv); 779 return (error); 780 } 781 782 static int 783 mlx5e_cable_length_handler(SYSCTL_HANDLER_ARGS) 784 { 785 struct mlx5e_priv *priv; 786 u_int cable_len; 787 int error; 788 789 priv = arg1; 790 PRIV_LOCK(priv); 791 cable_len = priv->dcbx.cable_len; 792 error = sysctl_handle_int(oidp, &cable_len, 0, req); 793 if (error == 0 && req->newptr != NULL && 794 cable_len != priv->dcbx.cable_len) { 795 error = -mlx5e_port_manual_buffer_config(priv, 796 MLX5E_PORT_BUFFER_CABLE_LEN, priv->params_ethtool.hw_mtu, 797 NULL, NULL, NULL); 798 if (error == 0) 799 priv->dcbx.cable_len = cable_len; 800 } 801 PRIV_UNLOCK(priv); 802 return (error); 803 } 804 805 #define MLX5_PARAM_OFFSET(n) \ 806 __offsetof(struct mlx5e_priv, params_ethtool.n) 807 808 static int 809 mlx5e_ethtool_handler(SYSCTL_HANDLER_ARGS) 810 { 811 struct mlx5e_priv *priv = arg1; 812 uint64_t value; 813 int mode_modify; 814 int was_opened; 815 int error; 816 817 PRIV_LOCK(priv); 818 value = priv->params_ethtool.arg[arg2]; 819 if (req != NULL) { 820 error = sysctl_handle_64(oidp, &value, 0, req); 821 if (error || req->newptr == NULL || 822 value == priv->params_ethtool.arg[arg2]) 823 goto done; 824 825 /* assign new value */ 826 priv->params_ethtool.arg[arg2] = value; 827 } else { 828 error = 0; 829 } 830 /* check if device is gone */ 831 if (priv->gone) { 832 error = ENXIO; 833 goto done; 834 } 835 was_opened = test_bit(MLX5E_STATE_OPENED, &priv->state); 836 mode_modify = MLX5_CAP_GEN(priv->mdev, cq_period_mode_modify); 837 838 switch (MLX5_PARAM_OFFSET(arg[arg2])) { 839 case MLX5_PARAM_OFFSET(rx_coalesce_usecs): 840 /* import RX coal time */ 841 if (priv->params_ethtool.rx_coalesce_usecs < 1) 842 priv->params_ethtool.rx_coalesce_usecs = 0; 843 else if (priv->params_ethtool.rx_coalesce_usecs > 844 MLX5E_FLD_MAX(cqc, cq_period)) { 845 priv->params_ethtool.rx_coalesce_usecs = 846 MLX5E_FLD_MAX(cqc, cq_period); 847 } 848 priv->params.rx_cq_moderation_usec = 849 priv->params_ethtool.rx_coalesce_usecs; 850 851 /* check to avoid down and up the network interface */ 852 if (was_opened) 853 error = mlx5e_refresh_channel_params(priv); 854 break; 855 856 case MLX5_PARAM_OFFSET(rx_coalesce_pkts): 857 /* import RX coal pkts */ 858 if (priv->params_ethtool.rx_coalesce_pkts < 1) 859 priv->params_ethtool.rx_coalesce_pkts = 0; 860 else if (priv->params_ethtool.rx_coalesce_pkts > 861 MLX5E_FLD_MAX(cqc, cq_max_count)) { 862 priv->params_ethtool.rx_coalesce_pkts = 863 MLX5E_FLD_MAX(cqc, cq_max_count); 864 } 865 priv->params.rx_cq_moderation_pkts = 866 priv->params_ethtool.rx_coalesce_pkts; 867 868 /* check to avoid down and up the network interface */ 869 if (was_opened) 870 error = mlx5e_refresh_channel_params(priv); 871 break; 872 873 case MLX5_PARAM_OFFSET(tx_coalesce_usecs): 874 /* import TX coal time */ 875 if (priv->params_ethtool.tx_coalesce_usecs < 1) 876 priv->params_ethtool.tx_coalesce_usecs = 0; 877 else if (priv->params_ethtool.tx_coalesce_usecs > 878 MLX5E_FLD_MAX(cqc, cq_period)) { 879 priv->params_ethtool.tx_coalesce_usecs = 880 MLX5E_FLD_MAX(cqc, cq_period); 881 } 882 priv->params.tx_cq_moderation_usec = 883 priv->params_ethtool.tx_coalesce_usecs; 884 885 /* check to avoid down and up the network interface */ 886 if (was_opened) 887 error = mlx5e_refresh_channel_params(priv); 888 break; 889 890 case MLX5_PARAM_OFFSET(tx_coalesce_pkts): 891 /* import TX coal pkts */ 892 if (priv->params_ethtool.tx_coalesce_pkts < 1) 893 priv->params_ethtool.tx_coalesce_pkts = 0; 894 else if (priv->params_ethtool.tx_coalesce_pkts > 895 MLX5E_FLD_MAX(cqc, cq_max_count)) { 896 priv->params_ethtool.tx_coalesce_pkts = 897 MLX5E_FLD_MAX(cqc, cq_max_count); 898 } 899 priv->params.tx_cq_moderation_pkts = 900 priv->params_ethtool.tx_coalesce_pkts; 901 902 /* check to avoid down and up the network interface */ 903 if (was_opened) 904 error = mlx5e_refresh_channel_params(priv); 905 break; 906 907 case MLX5_PARAM_OFFSET(tx_queue_size): 908 /* network interface must be down */ 909 if (was_opened) 910 mlx5e_close_locked(priv->ifp); 911 912 /* import TX queue size */ 913 if (priv->params_ethtool.tx_queue_size < 914 (1 << MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE)) { 915 priv->params_ethtool.tx_queue_size = 916 (1 << MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE); 917 } else if (priv->params_ethtool.tx_queue_size > 918 priv->params_ethtool.tx_queue_size_max) { 919 priv->params_ethtool.tx_queue_size = 920 priv->params_ethtool.tx_queue_size_max; 921 } 922 /* store actual TX queue size */ 923 priv->params.log_sq_size = 924 order_base_2(priv->params_ethtool.tx_queue_size); 925 priv->params_ethtool.tx_queue_size = 926 1 << priv->params.log_sq_size; 927 928 /* verify TX completion factor */ 929 mlx5e_ethtool_sync_tx_completion_fact(priv); 930 931 /* restart network interface, if any */ 932 if (was_opened) 933 mlx5e_open_locked(priv->ifp); 934 break; 935 936 case MLX5_PARAM_OFFSET(rx_queue_size): 937 /* network interface must be down */ 938 if (was_opened) 939 mlx5e_close_locked(priv->ifp); 940 941 /* import RX queue size */ 942 if (priv->params_ethtool.rx_queue_size < 943 (1 << MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE)) { 944 priv->params_ethtool.rx_queue_size = 945 (1 << MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE); 946 } else if (priv->params_ethtool.rx_queue_size > 947 priv->params_ethtool.rx_queue_size_max) { 948 priv->params_ethtool.rx_queue_size = 949 priv->params_ethtool.rx_queue_size_max; 950 } 951 /* store actual RX queue size */ 952 priv->params.log_rq_size = 953 order_base_2(priv->params_ethtool.rx_queue_size); 954 priv->params_ethtool.rx_queue_size = 955 1 << priv->params.log_rq_size; 956 957 /* update least number of RX WQEs */ 958 priv->params.min_rx_wqes = min( 959 priv->params_ethtool.rx_queue_size - 1, 960 MLX5E_PARAMS_DEFAULT_MIN_RX_WQES); 961 962 /* restart network interface, if any */ 963 if (was_opened) 964 mlx5e_open_locked(priv->ifp); 965 break; 966 967 case MLX5_PARAM_OFFSET(channels_rsss): 968 /* network interface must be down */ 969 if (was_opened) 970 mlx5e_close_locked(priv->ifp); 971 972 /* import number of channels */ 973 if (priv->params_ethtool.channels_rsss < 1) 974 priv->params_ethtool.channels_rsss = 1; 975 else if (priv->params_ethtool.channels_rsss > 128) 976 priv->params_ethtool.channels_rsss = 128; 977 978 priv->params.channels_rsss = priv->params_ethtool.channels_rsss; 979 980 /* restart network interface, if any */ 981 if (was_opened) 982 mlx5e_open_locked(priv->ifp); 983 break; 984 985 case MLX5_PARAM_OFFSET(channels): 986 /* network interface must be down */ 987 if (was_opened) 988 mlx5e_close_locked(priv->ifp); 989 990 /* import number of channels */ 991 if (priv->params_ethtool.channels < 1) 992 priv->params_ethtool.channels = 1; 993 else if (priv->params_ethtool.channels > 994 (u64) priv->mdev->priv.eq_table.num_comp_vectors) { 995 priv->params_ethtool.channels = 996 (u64) priv->mdev->priv.eq_table.num_comp_vectors; 997 } 998 priv->params.num_channels = priv->params_ethtool.channels; 999 1000 /* restart network interface, if any */ 1001 if (was_opened) 1002 mlx5e_open_locked(priv->ifp); 1003 break; 1004 1005 case MLX5_PARAM_OFFSET(rx_coalesce_mode): 1006 /* network interface must be down */ 1007 if (was_opened != 0 && mode_modify == 0) 1008 mlx5e_close_locked(priv->ifp); 1009 1010 /* import RX coalesce mode */ 1011 if (priv->params_ethtool.rx_coalesce_mode > 3) 1012 priv->params_ethtool.rx_coalesce_mode = 3; 1013 priv->params.rx_cq_moderation_mode = 1014 priv->params_ethtool.rx_coalesce_mode; 1015 1016 /* restart network interface, if any */ 1017 if (was_opened != 0) { 1018 if (mode_modify == 0) 1019 mlx5e_open_locked(priv->ifp); 1020 else 1021 error = mlx5e_refresh_channel_params(priv); 1022 } 1023 break; 1024 1025 case MLX5_PARAM_OFFSET(tx_coalesce_mode): 1026 /* network interface must be down */ 1027 if (was_opened != 0 && mode_modify == 0) 1028 mlx5e_close_locked(priv->ifp); 1029 1030 /* import TX coalesce mode */ 1031 if (priv->params_ethtool.tx_coalesce_mode != 0) 1032 priv->params_ethtool.tx_coalesce_mode = 1; 1033 priv->params.tx_cq_moderation_mode = 1034 priv->params_ethtool.tx_coalesce_mode; 1035 1036 /* restart network interface, if any */ 1037 if (was_opened != 0) { 1038 if (mode_modify == 0) 1039 mlx5e_open_locked(priv->ifp); 1040 else 1041 error = mlx5e_refresh_channel_params(priv); 1042 } 1043 break; 1044 1045 case MLX5_PARAM_OFFSET(hw_lro): 1046 /* network interface must be down */ 1047 if (was_opened) 1048 mlx5e_close_locked(priv->ifp); 1049 1050 /* import HW LRO mode */ 1051 if (priv->params_ethtool.hw_lro != 0 && 1052 MLX5_CAP_ETH(priv->mdev, lro_cap)) { 1053 priv->params_ethtool.hw_lro = 1; 1054 /* check if feature should actually be enabled */ 1055 if (priv->ifp->if_capenable & IFCAP_LRO) { 1056 priv->params.hw_lro_en = true; 1057 } else { 1058 priv->params.hw_lro_en = false; 1059 1060 mlx5_en_warn(priv->ifp, "To enable HW LRO " 1061 "please also enable LRO via ifconfig(8).\n"); 1062 } 1063 } else { 1064 /* return an error if HW does not support this feature */ 1065 if (priv->params_ethtool.hw_lro != 0) 1066 error = EINVAL; 1067 priv->params.hw_lro_en = false; 1068 priv->params_ethtool.hw_lro = 0; 1069 } 1070 /* restart network interface, if any */ 1071 if (was_opened) 1072 mlx5e_open_locked(priv->ifp); 1073 break; 1074 1075 case MLX5_PARAM_OFFSET(cqe_zipping): 1076 /* network interface must be down */ 1077 if (was_opened) 1078 mlx5e_close_locked(priv->ifp); 1079 1080 /* import CQE zipping mode */ 1081 if (priv->params_ethtool.cqe_zipping && 1082 MLX5_CAP_GEN(priv->mdev, cqe_compression)) { 1083 priv->params.cqe_zipping_en = true; 1084 priv->params_ethtool.cqe_zipping = 1; 1085 } else { 1086 priv->params.cqe_zipping_en = false; 1087 priv->params_ethtool.cqe_zipping = 0; 1088 } 1089 /* restart network interface, if any */ 1090 if (was_opened) 1091 mlx5e_open_locked(priv->ifp); 1092 break; 1093 1094 case MLX5_PARAM_OFFSET(tx_completion_fact): 1095 /* network interface must be down */ 1096 if (was_opened) 1097 mlx5e_close_locked(priv->ifp); 1098 1099 /* verify parameter */ 1100 mlx5e_ethtool_sync_tx_completion_fact(priv); 1101 1102 /* restart network interface, if any */ 1103 if (was_opened) 1104 mlx5e_open_locked(priv->ifp); 1105 break; 1106 1107 case MLX5_PARAM_OFFSET(modify_tx_dma): 1108 /* check if network interface is opened */ 1109 if (was_opened) { 1110 priv->params_ethtool.modify_tx_dma = 1111 priv->params_ethtool.modify_tx_dma ? 1 : 0; 1112 /* modify tx according to value */ 1113 mlx5e_modify_tx_dma(priv, value != 0); 1114 } else { 1115 /* if closed force enable tx */ 1116 priv->params_ethtool.modify_tx_dma = 0; 1117 } 1118 break; 1119 1120 case MLX5_PARAM_OFFSET(modify_rx_dma): 1121 /* check if network interface is opened */ 1122 if (was_opened) { 1123 priv->params_ethtool.modify_rx_dma = 1124 priv->params_ethtool.modify_rx_dma ? 1 : 0; 1125 /* modify rx according to value */ 1126 mlx5e_modify_rx_dma(priv, value != 0); 1127 } else { 1128 /* if closed force enable rx */ 1129 priv->params_ethtool.modify_rx_dma = 0; 1130 } 1131 break; 1132 1133 case MLX5_PARAM_OFFSET(diag_pci_enable): 1134 priv->params_ethtool.diag_pci_enable = 1135 priv->params_ethtool.diag_pci_enable ? 1 : 0; 1136 1137 error = -mlx5_core_set_diagnostics_full(priv->mdev, 1138 priv->params_ethtool.diag_pci_enable, 1139 priv->params_ethtool.diag_general_enable); 1140 break; 1141 1142 case MLX5_PARAM_OFFSET(diag_general_enable): 1143 priv->params_ethtool.diag_general_enable = 1144 priv->params_ethtool.diag_general_enable ? 1 : 0; 1145 1146 error = -mlx5_core_set_diagnostics_full(priv->mdev, 1147 priv->params_ethtool.diag_pci_enable, 1148 priv->params_ethtool.diag_general_enable); 1149 break; 1150 1151 case MLX5_PARAM_OFFSET(mc_local_lb): 1152 priv->params_ethtool.mc_local_lb = 1153 priv->params_ethtool.mc_local_lb ? 1 : 0; 1154 1155 if (MLX5_CAP_GEN(priv->mdev, disable_local_lb)) { 1156 error = mlx5_nic_vport_modify_local_lb(priv->mdev, 1157 MLX5_LOCAL_MC_LB, priv->params_ethtool.mc_local_lb); 1158 } else { 1159 error = EOPNOTSUPP; 1160 } 1161 break; 1162 1163 case MLX5_PARAM_OFFSET(uc_local_lb): 1164 priv->params_ethtool.uc_local_lb = 1165 priv->params_ethtool.uc_local_lb ? 1 : 0; 1166 1167 if (MLX5_CAP_GEN(priv->mdev, disable_local_lb)) { 1168 error = mlx5_nic_vport_modify_local_lb(priv->mdev, 1169 MLX5_LOCAL_UC_LB, priv->params_ethtool.uc_local_lb); 1170 } else { 1171 error = EOPNOTSUPP; 1172 } 1173 break; 1174 1175 default: 1176 break; 1177 } 1178 done: 1179 PRIV_UNLOCK(priv); 1180 return (error); 1181 } 1182 1183 static const char *mlx5e_params_desc[] = { 1184 MLX5E_PARAMS(MLX5E_STATS_DESC) 1185 }; 1186 1187 static const char *mlx5e_port_stats_debug_desc[] = { 1188 MLX5E_PORT_STATS_DEBUG(MLX5E_STATS_DESC) 1189 }; 1190 1191 static int 1192 mlx5e_ethtool_debug_channel_info(SYSCTL_HANDLER_ARGS) 1193 { 1194 struct mlx5e_priv *priv; 1195 struct sbuf sb; 1196 struct mlx5e_channel *c; 1197 struct mlx5e_sq *sq; 1198 struct mlx5e_rq *rq; 1199 int error, i, tc; 1200 bool opened; 1201 1202 priv = arg1; 1203 error = sysctl_wire_old_buffer(req, 0); 1204 if (error != 0) 1205 return (error); 1206 if (sbuf_new_for_sysctl(&sb, NULL, 1024, req) == NULL) 1207 return (ENOMEM); 1208 sbuf_clear_flags(&sb, SBUF_INCLUDENUL); 1209 1210 PRIV_LOCK(priv); 1211 opened = test_bit(MLX5E_STATE_OPENED, &priv->state); 1212 1213 sbuf_printf(&sb, "pages irq %d\n", 1214 priv->mdev->priv.msix_arr[MLX5_EQ_VEC_PAGES].vector); 1215 sbuf_printf(&sb, "command irq %d\n", 1216 priv->mdev->priv.msix_arr[MLX5_EQ_VEC_CMD].vector); 1217 sbuf_printf(&sb, "async irq %d\n", 1218 priv->mdev->priv.msix_arr[MLX5_EQ_VEC_ASYNC].vector); 1219 1220 for (i = 0; i != priv->params.num_channels; i++) { 1221 int eqn_not_used = -1; 1222 int irqn = MLX5_EQ_VEC_COMP_BASE; 1223 1224 if (mlx5_vector2eqn(priv->mdev, i, &eqn_not_used, &irqn) != 0) 1225 continue; 1226 1227 c = opened ? &priv->channel[i] : NULL; 1228 rq = opened ? &c->rq : NULL; 1229 sbuf_printf(&sb, "channel %d rq %d cq %d irq %d\n", i, 1230 opened ? rq->rqn : -1, 1231 opened ? rq->cq.mcq.cqn : -1, 1232 priv->mdev->priv.msix_arr[irqn].vector); 1233 1234 for (tc = 0; tc != priv->num_tc; tc++) { 1235 sq = opened ? &c->sq[tc] : NULL; 1236 sbuf_printf(&sb, "channel %d tc %d sq %d cq %d irq %d\n", 1237 i, tc, 1238 opened ? sq->sqn : -1, 1239 opened ? sq->cq.mcq.cqn : -1, 1240 priv->mdev->priv.msix_arr[irqn].vector); 1241 } 1242 } 1243 PRIV_UNLOCK(priv); 1244 error = sbuf_finish(&sb); 1245 sbuf_delete(&sb); 1246 return (error); 1247 } 1248 1249 static int 1250 mlx5e_ethtool_debug_stats(SYSCTL_HANDLER_ARGS) 1251 { 1252 struct mlx5e_priv *priv = arg1; 1253 int sys_debug; 1254 int error; 1255 1256 PRIV_LOCK(priv); 1257 if (priv->gone != 0) { 1258 error = ENODEV; 1259 goto done; 1260 } 1261 sys_debug = priv->sysctl_debug; 1262 error = sysctl_handle_int(oidp, &sys_debug, 0, req); 1263 if (error != 0 || !req->newptr) 1264 goto done; 1265 sys_debug = sys_debug ? 1 : 0; 1266 if (sys_debug == priv->sysctl_debug) 1267 goto done; 1268 1269 if ((priv->sysctl_debug = sys_debug)) { 1270 mlx5e_create_stats(&priv->stats.port_stats_debug.ctx, 1271 SYSCTL_CHILDREN(priv->sysctl_ifnet), "debug_stats", 1272 mlx5e_port_stats_debug_desc, MLX5E_PORT_STATS_DEBUG_NUM, 1273 priv->stats.port_stats_debug.arg); 1274 SYSCTL_ADD_PROC(&priv->stats.port_stats_debug.ctx, 1275 SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO, 1276 "hw_ctx_debug", 1277 CTLFLAG_RD | CTLFLAG_MPSAFE | CTLTYPE_STRING, priv, 0, 1278 mlx5e_ethtool_debug_channel_info, "S", ""); 1279 } else { 1280 sysctl_ctx_free(&priv->stats.port_stats_debug.ctx); 1281 } 1282 done: 1283 PRIV_UNLOCK(priv); 1284 return (error); 1285 } 1286 1287 static void 1288 mlx5e_create_diagnostics(struct mlx5e_priv *priv) 1289 { 1290 struct mlx5_core_diagnostics_entry entry; 1291 struct sysctl_ctx_list *ctx; 1292 struct sysctl_oid *node; 1293 int x; 1294 1295 /* sysctl context we are using */ 1296 ctx = &priv->sysctl_ctx; 1297 1298 /* create root node */ 1299 node = SYSCTL_ADD_NODE(ctx, 1300 SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO, 1301 "diagnostics", CTLFLAG_RD, NULL, "Diagnostics"); 1302 if (node == NULL) 1303 return; 1304 1305 /* create PCI diagnostics */ 1306 for (x = 0; x != MLX5_CORE_PCI_DIAGNOSTICS_NUM; x++) { 1307 entry = mlx5_core_pci_diagnostics_table[x]; 1308 if (mlx5_core_supports_diagnostics(priv->mdev, entry.counter_id) == 0) 1309 continue; 1310 SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO, 1311 entry.desc, CTLFLAG_RD, priv->params_pci.array + x, 1312 "PCI diagnostics counter"); 1313 } 1314 1315 /* create general diagnostics */ 1316 for (x = 0; x != MLX5_CORE_GENERAL_DIAGNOSTICS_NUM; x++) { 1317 entry = mlx5_core_general_diagnostics_table[x]; 1318 if (mlx5_core_supports_diagnostics(priv->mdev, entry.counter_id) == 0) 1319 continue; 1320 SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO, 1321 entry.desc, CTLFLAG_RD, priv->params_general.array + x, 1322 "General diagnostics counter"); 1323 } 1324 } 1325 1326 void 1327 mlx5e_create_ethtool(struct mlx5e_priv *priv) 1328 { 1329 struct sysctl_oid *fec_node; 1330 struct sysctl_oid *qos_node; 1331 struct sysctl_oid *node; 1332 const char *pnameunit; 1333 struct mlx5e_port_buffer port_buffer; 1334 unsigned x; 1335 int i; 1336 1337 /* set some defaults */ 1338 priv->params_ethtool.tx_queue_size_max = 1 << MLX5E_PARAMS_MAXIMUM_LOG_SQ_SIZE; 1339 priv->params_ethtool.rx_queue_size_max = 1 << MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE; 1340 priv->params_ethtool.tx_queue_size = 1 << priv->params.log_sq_size; 1341 priv->params_ethtool.rx_queue_size = 1 << priv->params.log_rq_size; 1342 priv->params_ethtool.channels = priv->params.num_channels; 1343 priv->params_ethtool.channels_rsss = priv->params.channels_rsss; 1344 priv->params_ethtool.coalesce_pkts_max = MLX5E_FLD_MAX(cqc, cq_max_count); 1345 priv->params_ethtool.coalesce_usecs_max = MLX5E_FLD_MAX(cqc, cq_period); 1346 priv->params_ethtool.rx_coalesce_mode = priv->params.rx_cq_moderation_mode; 1347 priv->params_ethtool.rx_coalesce_usecs = priv->params.rx_cq_moderation_usec; 1348 priv->params_ethtool.rx_coalesce_pkts = priv->params.rx_cq_moderation_pkts; 1349 priv->params_ethtool.tx_coalesce_mode = priv->params.tx_cq_moderation_mode; 1350 priv->params_ethtool.tx_coalesce_usecs = priv->params.tx_cq_moderation_usec; 1351 priv->params_ethtool.tx_coalesce_pkts = priv->params.tx_cq_moderation_pkts; 1352 priv->params_ethtool.hw_lro = priv->params.hw_lro_en; 1353 priv->params_ethtool.cqe_zipping = priv->params.cqe_zipping_en; 1354 mlx5e_ethtool_sync_tx_completion_fact(priv); 1355 1356 /* get default values for local loopback, if any */ 1357 if (MLX5_CAP_GEN(priv->mdev, disable_local_lb)) { 1358 int err; 1359 u8 val; 1360 1361 err = mlx5_nic_vport_query_local_lb(priv->mdev, MLX5_LOCAL_MC_LB, &val); 1362 if (err == 0) 1363 priv->params_ethtool.mc_local_lb = val; 1364 1365 err = mlx5_nic_vport_query_local_lb(priv->mdev, MLX5_LOCAL_UC_LB, &val); 1366 if (err == 0) 1367 priv->params_ethtool.uc_local_lb = val; 1368 } 1369 1370 /* create root node */ 1371 node = SYSCTL_ADD_NODE(&priv->sysctl_ctx, 1372 SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO, 1373 "conf", CTLFLAG_RW, NULL, "Configuration"); 1374 if (node == NULL) 1375 return; 1376 for (x = 0; x != MLX5E_PARAMS_NUM; x++) { 1377 /* check for read-only parameter */ 1378 if (strstr(mlx5e_params_desc[2 * x], "_max") != NULL || 1379 strstr(mlx5e_params_desc[2 * x], "_mtu") != NULL) { 1380 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO, 1381 mlx5e_params_desc[2 * x], CTLTYPE_U64 | CTLFLAG_RD | 1382 CTLFLAG_MPSAFE, priv, x, &mlx5e_ethtool_handler, "QU", 1383 mlx5e_params_desc[2 * x + 1]); 1384 } else { 1385 #if (__FreeBSD_version < 1100000) 1386 char path[64]; 1387 #endif 1388 /* 1389 * NOTE: In FreeBSD-11 and newer the 1390 * CTLFLAG_RWTUN flag will take care of 1391 * loading default sysctl value from the 1392 * kernel environment, if any: 1393 */ 1394 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO, 1395 mlx5e_params_desc[2 * x], CTLTYPE_U64 | CTLFLAG_RWTUN | 1396 CTLFLAG_MPSAFE, priv, x, &mlx5e_ethtool_handler, "QU", 1397 mlx5e_params_desc[2 * x + 1]); 1398 1399 #if (__FreeBSD_version < 1100000) 1400 /* compute path for sysctl */ 1401 snprintf(path, sizeof(path), "dev.mce.%d.conf.%s", 1402 device_get_unit(priv->mdev->pdev->dev.bsddev), 1403 mlx5e_params_desc[2 * x]); 1404 1405 /* try to fetch tunable, if any */ 1406 if (TUNABLE_QUAD_FETCH(path, &priv->params_ethtool.arg[x])) 1407 mlx5e_ethtool_handler(NULL, priv, x, NULL); 1408 #endif 1409 } 1410 } 1411 1412 /* create fec node */ 1413 fec_node = SYSCTL_ADD_NODE(&priv->sysctl_ctx, 1414 SYSCTL_CHILDREN(node), OID_AUTO, 1415 "fec", CTLFLAG_RW, NULL, "Forward Error Correction"); 1416 if (fec_node == NULL) 1417 return; 1418 1419 if (mlx5e_fec_update(priv) == 0) { 1420 SYSCTL_ADD_U32(&priv->sysctl_ctx, SYSCTL_CHILDREN(fec_node), OID_AUTO, 1421 "mode_active", CTLFLAG_RD | CTLFLAG_MPSAFE, 1422 &priv->params_ethtool.fec_mode_active, 0, 1423 "Current FEC mode bit, if any."); 1424 1425 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(fec_node), OID_AUTO, 1426 "mask_10x_25x", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1427 priv, 0, &mlx5e_fec_mask_10x_25x_handler, "CU", 1428 "Set FEC masks for 10G_40G, 25G_50G, 56G, 100G respectivly. " 1429 "0:Auto " 1430 "1:NOFEC " 1431 "2:FIRECODE " 1432 "4:RS"); 1433 1434 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(fec_node), OID_AUTO, 1435 "avail_10x_25x", CTLTYPE_U8 | CTLFLAG_RD | CTLFLAG_MPSAFE, 1436 priv, 0, &mlx5e_fec_avail_10x_25x_handler, "CU", 1437 "Get available FEC bits for 10G_40G, 25G_50G, 56G, 100G respectivly. " 1438 "0:Auto " 1439 "1:NOFEC " 1440 "2:FIRECODE " 1441 "4:RS"); 1442 1443 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(fec_node), OID_AUTO, 1444 "mask_50x", CTLTYPE_U16 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1445 priv, 0, &mlx5e_fec_mask_50x_handler, "SU", 1446 "Set FEC masks for 50G 1x, 100G 2x, 200G 4x, 400G 8x respectivly. " 1447 "0:Auto " 1448 "128:RS " 1449 "512:LL RS"); 1450 1451 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(fec_node), OID_AUTO, 1452 "avail_50x", CTLTYPE_U16 | CTLFLAG_RD | CTLFLAG_MPSAFE, 1453 priv, 0, &mlx5e_fec_avail_50x_handler, "SU", 1454 "Get available FEC bits for 50G 1x, 100G 2x, 200G 4x, 400G 8x respectivly. " 1455 "0:Auto " 1456 "128:RS " 1457 "512:LL RS"); 1458 } 1459 1460 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO, 1461 "debug_stats", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 1462 0, &mlx5e_ethtool_debug_stats, "I", "Extended debug statistics"); 1463 1464 pnameunit = device_get_nameunit(priv->mdev->pdev->dev.bsddev); 1465 1466 SYSCTL_ADD_STRING(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), 1467 OID_AUTO, "device_name", CTLFLAG_RD, 1468 __DECONST(void *, pnameunit), 0, 1469 "PCI device name"); 1470 1471 /* Diagnostics support */ 1472 mlx5e_create_diagnostics(priv); 1473 1474 /* create qos node */ 1475 qos_node = SYSCTL_ADD_NODE(&priv->sysctl_ctx, 1476 SYSCTL_CHILDREN(node), OID_AUTO, 1477 "qos", CTLFLAG_RW, NULL, "Quality Of Service configuration"); 1478 if (qos_node == NULL) 1479 return; 1480 1481 /* Priority rate limit support */ 1482 if (mlx5e_getmaxrate(priv) == 0) { 1483 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1484 OID_AUTO, "tc_max_rate", CTLTYPE_U64 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1485 priv, 0, mlx5e_tc_maxrate_handler, "QU", 1486 "Max rate for priority, specified in kilobits, where kilo=1000, " 1487 "max_rate must be divisible by 100000"); 1488 } 1489 1490 /* Bandwidth limiting by ratio */ 1491 if (mlx5e_get_max_alloc(priv) == 0) { 1492 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1493 OID_AUTO, "tc_rate_share", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1494 priv, 0, mlx5e_tc_rate_share_handler, "QU", 1495 "Specify bandwidth ratio from 1 to 100 " 1496 "for the available traffic classes"); 1497 } 1498 1499 /* Priority to traffic class mapping */ 1500 if (mlx5e_get_prio_tc(priv) == 0) { 1501 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1502 OID_AUTO, "prio_0_7_tc", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1503 priv, 0, mlx5e_prio_to_tc_handler, "CU", 1504 "Set traffic class 0 to 7 for priority 0 to 7 inclusivly"); 1505 } 1506 1507 /* DSCP support */ 1508 if (mlx5e_get_dscp(priv) == 0) { 1509 for (i = 0; i != MLX5_MAX_SUPPORTED_DSCP; i += 8) { 1510 char name[32]; 1511 snprintf(name, sizeof(name), "dscp_%d_%d_prio", i, i + 7); 1512 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1513 OID_AUTO, name, CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1514 priv, i, mlx5e_dscp_prio_handler, "CU", 1515 "Set DSCP to priority mapping, 0..7"); 1516 } 1517 #define A "Set trust state, 1:PCP 2:DSCP" 1518 #define B " 3:BOTH" 1519 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1520 OID_AUTO, "trust_state", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1521 priv, 0, mlx5e_trust_state_handler, "CU", 1522 MLX5_CAP_QCAM_FEATURE(priv->mdev, qpts_trust_both) ? 1523 A B : A); 1524 #undef B 1525 #undef A 1526 } 1527 1528 if (mlx5e_port_query_buffer(priv, &port_buffer) == 0) { 1529 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1530 OID_AUTO, "buffers_size", 1531 CTLTYPE_U32 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1532 priv, 0, mlx5e_buf_size_handler, "IU", 1533 "Set buffers sizes"); 1534 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1535 OID_AUTO, "buffers_prio", 1536 CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1537 priv, 0, mlx5e_buf_prio_handler, "CU", 1538 "Set prio to buffers mapping"); 1539 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1540 OID_AUTO, "cable_length", 1541 CTLTYPE_UINT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1542 priv, 0, mlx5e_cable_length_handler, "IU", 1543 "Set cable length in meters for xoff threshold calculation"); 1544 } 1545 } 1546