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