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