mlx5_en_ethtool.c revision 353202
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: stable/11/sys/dev/mlx5/mlx5_en/mlx5_en_ethtool.c 353202 2019-10-07 08:57:39Z hselasky $ 26 */ 27 28#include "en.h" 29#include <net/sff8472.h> 30 31void 32mlx5e_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 51static void 52mlx5e_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 87static int 88mlx5e_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 } 118done: 119 PRIV_UNLOCK(priv); 120 return (err); 121} 122 123static int 124mlx5e_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 146static int 147mlx5e_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; 165done: 166 PRIV_UNLOCK(priv); 167 return (err); 168} 169 170static void 171mlx5e_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 200static int 201mlx5e_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)); 238done: 239 PRIV_UNLOCK(priv); 240 return (err); 241} 242 243static int 244mlx5e_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)); 283done: 284 PRIV_UNLOCK(priv); 285 return (err); 286} 287 288static int 289mlx5e_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 310static int 311mlx5e_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 } 343done: 344 PRIV_UNLOCK(priv); 345 return (err); 346} 347 348static int 349mlx5e_trust_state_handler(SYSCTL_HANDLER_ARGS) 350{ 351 struct mlx5e_priv *priv = arg1; 352 struct mlx5_core_dev *mdev = priv->mdev; 353 int err; 354 u8 result; 355 356 PRIV_LOCK(priv); 357 result = priv->params_ethtool.trust_state; 358 err = sysctl_handle_8(oidp, &result, 0, req); 359 if (err || !req->newptr || 360 result == priv->params_ethtool.trust_state) 361 goto done; 362 363 switch (result) { 364 case MLX5_QPTS_TRUST_PCP: 365 case MLX5_QPTS_TRUST_DSCP: 366 break; 367 case MLX5_QPTS_TRUST_BOTH: 368 if (!MLX5_CAP_QCAM_FEATURE(mdev, qpts_trust_both)) { 369 err = EOPNOTSUPP; 370 goto done; 371 } 372 break; 373 default: 374 err = ERANGE; 375 goto done; 376 } 377 378 err = -mlx5_set_trust_state(mdev, result); 379 if (err) 380 goto done; 381 382 priv->params_ethtool.trust_state = result; 383 384 /* update inline mode */ 385 mlx5e_refresh_sq_inline(priv); 386#ifdef RATELIMIT 387 mlx5e_rl_refresh_sq_inline(&priv->rl); 388#endif 389done: 390 PRIV_UNLOCK(priv); 391 return (err); 392} 393 394static int 395mlx5e_dscp_prio_handler(SYSCTL_HANDLER_ARGS) 396{ 397 struct mlx5e_priv *priv = arg1; 398 int prio_index = arg2; 399 struct mlx5_core_dev *mdev = priv->mdev; 400 uint8_t dscp2prio[MLX5_MAX_SUPPORTED_DSCP]; 401 uint8_t x; 402 int err; 403 404 PRIV_LOCK(priv); 405 err = SYSCTL_OUT(req, priv->params_ethtool.dscp2prio + prio_index, 406 sizeof(priv->params_ethtool.dscp2prio) / 8); 407 if (err || !req->newptr) 408 goto done; 409 410 memcpy(dscp2prio, priv->params_ethtool.dscp2prio, sizeof(dscp2prio)); 411 err = SYSCTL_IN(req, dscp2prio + prio_index, sizeof(dscp2prio) / 8); 412 if (err) 413 goto done; 414 for (x = 0; x != MLX5_MAX_SUPPORTED_DSCP; x++) { 415 if (dscp2prio[x] > 7) { 416 err = ERANGE; 417 goto done; 418 } 419 } 420 err = -mlx5_set_dscp2prio(mdev, dscp2prio); 421 if (err) 422 goto done; 423 424 /* update local array */ 425 memcpy(priv->params_ethtool.dscp2prio, dscp2prio, 426 sizeof(priv->params_ethtool.dscp2prio)); 427done: 428 PRIV_UNLOCK(priv); 429 return (err); 430} 431 432#define MLX5_PARAM_OFFSET(n) \ 433 __offsetof(struct mlx5e_priv, params_ethtool.n) 434 435static int 436mlx5e_ethtool_handler(SYSCTL_HANDLER_ARGS) 437{ 438 struct mlx5e_priv *priv = arg1; 439 uint64_t value; 440 int mode_modify; 441 int was_opened; 442 int error; 443 444 PRIV_LOCK(priv); 445 value = priv->params_ethtool.arg[arg2]; 446 if (req != NULL) { 447 error = sysctl_handle_64(oidp, &value, 0, req); 448 if (error || req->newptr == NULL || 449 value == priv->params_ethtool.arg[arg2]) 450 goto done; 451 452 /* assign new value */ 453 priv->params_ethtool.arg[arg2] = value; 454 } else { 455 error = 0; 456 } 457 /* check if device is gone */ 458 if (priv->gone) { 459 error = ENXIO; 460 goto done; 461 } 462 was_opened = test_bit(MLX5E_STATE_OPENED, &priv->state); 463 mode_modify = MLX5_CAP_GEN(priv->mdev, cq_period_mode_modify); 464 465 switch (MLX5_PARAM_OFFSET(arg[arg2])) { 466 case MLX5_PARAM_OFFSET(rx_coalesce_usecs): 467 /* import RX coal time */ 468 if (priv->params_ethtool.rx_coalesce_usecs < 1) 469 priv->params_ethtool.rx_coalesce_usecs = 0; 470 else if (priv->params_ethtool.rx_coalesce_usecs > 471 MLX5E_FLD_MAX(cqc, cq_period)) { 472 priv->params_ethtool.rx_coalesce_usecs = 473 MLX5E_FLD_MAX(cqc, cq_period); 474 } 475 priv->params.rx_cq_moderation_usec = 476 priv->params_ethtool.rx_coalesce_usecs; 477 478 /* check to avoid down and up the network interface */ 479 if (was_opened) 480 error = mlx5e_refresh_channel_params(priv); 481 break; 482 483 case MLX5_PARAM_OFFSET(rx_coalesce_pkts): 484 /* import RX coal pkts */ 485 if (priv->params_ethtool.rx_coalesce_pkts < 1) 486 priv->params_ethtool.rx_coalesce_pkts = 0; 487 else if (priv->params_ethtool.rx_coalesce_pkts > 488 MLX5E_FLD_MAX(cqc, cq_max_count)) { 489 priv->params_ethtool.rx_coalesce_pkts = 490 MLX5E_FLD_MAX(cqc, cq_max_count); 491 } 492 priv->params.rx_cq_moderation_pkts = 493 priv->params_ethtool.rx_coalesce_pkts; 494 495 /* check to avoid down and up the network interface */ 496 if (was_opened) 497 error = mlx5e_refresh_channel_params(priv); 498 break; 499 500 case MLX5_PARAM_OFFSET(tx_coalesce_usecs): 501 /* import TX coal time */ 502 if (priv->params_ethtool.tx_coalesce_usecs < 1) 503 priv->params_ethtool.tx_coalesce_usecs = 0; 504 else if (priv->params_ethtool.tx_coalesce_usecs > 505 MLX5E_FLD_MAX(cqc, cq_period)) { 506 priv->params_ethtool.tx_coalesce_usecs = 507 MLX5E_FLD_MAX(cqc, cq_period); 508 } 509 priv->params.tx_cq_moderation_usec = 510 priv->params_ethtool.tx_coalesce_usecs; 511 512 /* check to avoid down and up the network interface */ 513 if (was_opened) 514 error = mlx5e_refresh_channel_params(priv); 515 break; 516 517 case MLX5_PARAM_OFFSET(tx_coalesce_pkts): 518 /* import TX coal pkts */ 519 if (priv->params_ethtool.tx_coalesce_pkts < 1) 520 priv->params_ethtool.tx_coalesce_pkts = 0; 521 else if (priv->params_ethtool.tx_coalesce_pkts > 522 MLX5E_FLD_MAX(cqc, cq_max_count)) { 523 priv->params_ethtool.tx_coalesce_pkts = 524 MLX5E_FLD_MAX(cqc, cq_max_count); 525 } 526 priv->params.tx_cq_moderation_pkts = 527 priv->params_ethtool.tx_coalesce_pkts; 528 529 /* check to avoid down and up the network interface */ 530 if (was_opened) 531 error = mlx5e_refresh_channel_params(priv); 532 break; 533 534 case MLX5_PARAM_OFFSET(tx_queue_size): 535 /* network interface must be down */ 536 if (was_opened) 537 mlx5e_close_locked(priv->ifp); 538 539 /* import TX queue size */ 540 if (priv->params_ethtool.tx_queue_size < 541 (1 << MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE)) { 542 priv->params_ethtool.tx_queue_size = 543 (1 << MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE); 544 } else if (priv->params_ethtool.tx_queue_size > 545 priv->params_ethtool.tx_queue_size_max) { 546 priv->params_ethtool.tx_queue_size = 547 priv->params_ethtool.tx_queue_size_max; 548 } 549 /* store actual TX queue size */ 550 priv->params.log_sq_size = 551 order_base_2(priv->params_ethtool.tx_queue_size); 552 priv->params_ethtool.tx_queue_size = 553 1 << priv->params.log_sq_size; 554 555 /* verify TX completion factor */ 556 mlx5e_ethtool_sync_tx_completion_fact(priv); 557 558 /* restart network interface, if any */ 559 if (was_opened) 560 mlx5e_open_locked(priv->ifp); 561 break; 562 563 case MLX5_PARAM_OFFSET(rx_queue_size): 564 /* network interface must be down */ 565 if (was_opened) 566 mlx5e_close_locked(priv->ifp); 567 568 /* import RX queue size */ 569 if (priv->params_ethtool.rx_queue_size < 570 (1 << MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE)) { 571 priv->params_ethtool.rx_queue_size = 572 (1 << MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE); 573 } else if (priv->params_ethtool.rx_queue_size > 574 priv->params_ethtool.rx_queue_size_max) { 575 priv->params_ethtool.rx_queue_size = 576 priv->params_ethtool.rx_queue_size_max; 577 } 578 /* store actual RX queue size */ 579 priv->params.log_rq_size = 580 order_base_2(priv->params_ethtool.rx_queue_size); 581 priv->params_ethtool.rx_queue_size = 582 1 << priv->params.log_rq_size; 583 584 /* update least number of RX WQEs */ 585 priv->params.min_rx_wqes = min( 586 priv->params_ethtool.rx_queue_size - 1, 587 MLX5E_PARAMS_DEFAULT_MIN_RX_WQES); 588 589 /* restart network interface, if any */ 590 if (was_opened) 591 mlx5e_open_locked(priv->ifp); 592 break; 593 594 case MLX5_PARAM_OFFSET(channels_rsss): 595 /* network interface must be down */ 596 if (was_opened) 597 mlx5e_close_locked(priv->ifp); 598 599 /* import number of channels */ 600 if (priv->params_ethtool.channels_rsss < 1) 601 priv->params_ethtool.channels_rsss = 1; 602 else if (priv->params_ethtool.channels_rsss > 128) 603 priv->params_ethtool.channels_rsss = 128; 604 605 priv->params.channels_rsss = priv->params_ethtool.channels_rsss; 606 607 /* restart network interface, if any */ 608 if (was_opened) 609 mlx5e_open_locked(priv->ifp); 610 break; 611 612 case MLX5_PARAM_OFFSET(channels): 613 /* network interface must be down */ 614 if (was_opened) 615 mlx5e_close_locked(priv->ifp); 616 617 /* import number of channels */ 618 if (priv->params_ethtool.channels < 1) 619 priv->params_ethtool.channels = 1; 620 else if (priv->params_ethtool.channels > 621 (u64) priv->mdev->priv.eq_table.num_comp_vectors) { 622 priv->params_ethtool.channels = 623 (u64) priv->mdev->priv.eq_table.num_comp_vectors; 624 } 625 priv->params.num_channels = priv->params_ethtool.channels; 626 627 /* restart network interface, if any */ 628 if (was_opened) 629 mlx5e_open_locked(priv->ifp); 630 break; 631 632 case MLX5_PARAM_OFFSET(rx_coalesce_mode): 633 /* network interface must be down */ 634 if (was_opened != 0 && mode_modify == 0) 635 mlx5e_close_locked(priv->ifp); 636 637 /* import RX coalesce mode */ 638 if (priv->params_ethtool.rx_coalesce_mode > 3) 639 priv->params_ethtool.rx_coalesce_mode = 3; 640 priv->params.rx_cq_moderation_mode = 641 priv->params_ethtool.rx_coalesce_mode; 642 643 /* restart network interface, if any */ 644 if (was_opened != 0) { 645 if (mode_modify == 0) 646 mlx5e_open_locked(priv->ifp); 647 else 648 error = mlx5e_refresh_channel_params(priv); 649 } 650 break; 651 652 case MLX5_PARAM_OFFSET(tx_coalesce_mode): 653 /* network interface must be down */ 654 if (was_opened != 0 && mode_modify == 0) 655 mlx5e_close_locked(priv->ifp); 656 657 /* import TX coalesce mode */ 658 if (priv->params_ethtool.tx_coalesce_mode != 0) 659 priv->params_ethtool.tx_coalesce_mode = 1; 660 priv->params.tx_cq_moderation_mode = 661 priv->params_ethtool.tx_coalesce_mode; 662 663 /* restart network interface, if any */ 664 if (was_opened != 0) { 665 if (mode_modify == 0) 666 mlx5e_open_locked(priv->ifp); 667 else 668 error = mlx5e_refresh_channel_params(priv); 669 } 670 break; 671 672 case MLX5_PARAM_OFFSET(hw_lro): 673 /* network interface must be down */ 674 if (was_opened) 675 mlx5e_close_locked(priv->ifp); 676 677 /* import HW LRO mode */ 678 if (priv->params_ethtool.hw_lro != 0 && 679 MLX5_CAP_ETH(priv->mdev, lro_cap)) { 680 priv->params_ethtool.hw_lro = 1; 681 /* check if feature should actually be enabled */ 682 if (priv->ifp->if_capenable & IFCAP_LRO) { 683 priv->params.hw_lro_en = true; 684 } else { 685 priv->params.hw_lro_en = false; 686 687 if_printf(priv->ifp, "To enable HW LRO " 688 "please also enable LRO via ifconfig(8).\n"); 689 } 690 } else { 691 /* return an error if HW does not support this feature */ 692 if (priv->params_ethtool.hw_lro != 0) 693 error = EINVAL; 694 priv->params.hw_lro_en = false; 695 priv->params_ethtool.hw_lro = 0; 696 } 697 /* restart network interface, if any */ 698 if (was_opened) 699 mlx5e_open_locked(priv->ifp); 700 break; 701 702 case MLX5_PARAM_OFFSET(cqe_zipping): 703 /* network interface must be down */ 704 if (was_opened) 705 mlx5e_close_locked(priv->ifp); 706 707 /* import CQE zipping mode */ 708 if (priv->params_ethtool.cqe_zipping && 709 MLX5_CAP_GEN(priv->mdev, cqe_compression)) { 710 priv->params.cqe_zipping_en = true; 711 priv->params_ethtool.cqe_zipping = 1; 712 } else { 713 priv->params.cqe_zipping_en = false; 714 priv->params_ethtool.cqe_zipping = 0; 715 } 716 /* restart network interface, if any */ 717 if (was_opened) 718 mlx5e_open_locked(priv->ifp); 719 break; 720 721 case MLX5_PARAM_OFFSET(tx_completion_fact): 722 /* network interface must be down */ 723 if (was_opened) 724 mlx5e_close_locked(priv->ifp); 725 726 /* verify parameter */ 727 mlx5e_ethtool_sync_tx_completion_fact(priv); 728 729 /* restart network interface, if any */ 730 if (was_opened) 731 mlx5e_open_locked(priv->ifp); 732 break; 733 734 case MLX5_PARAM_OFFSET(modify_tx_dma): 735 /* check if network interface is opened */ 736 if (was_opened) { 737 priv->params_ethtool.modify_tx_dma = 738 priv->params_ethtool.modify_tx_dma ? 1 : 0; 739 /* modify tx according to value */ 740 mlx5e_modify_tx_dma(priv, value != 0); 741 } else { 742 /* if closed force enable tx */ 743 priv->params_ethtool.modify_tx_dma = 0; 744 } 745 break; 746 747 case MLX5_PARAM_OFFSET(modify_rx_dma): 748 /* check if network interface is opened */ 749 if (was_opened) { 750 priv->params_ethtool.modify_rx_dma = 751 priv->params_ethtool.modify_rx_dma ? 1 : 0; 752 /* modify rx according to value */ 753 mlx5e_modify_rx_dma(priv, value != 0); 754 } else { 755 /* if closed force enable rx */ 756 priv->params_ethtool.modify_rx_dma = 0; 757 } 758 break; 759 760 case MLX5_PARAM_OFFSET(diag_pci_enable): 761 priv->params_ethtool.diag_pci_enable = 762 priv->params_ethtool.diag_pci_enable ? 1 : 0; 763 764 error = -mlx5_core_set_diagnostics_full(priv->mdev, 765 priv->params_ethtool.diag_pci_enable, 766 priv->params_ethtool.diag_general_enable); 767 break; 768 769 case MLX5_PARAM_OFFSET(diag_general_enable): 770 priv->params_ethtool.diag_general_enable = 771 priv->params_ethtool.diag_general_enable ? 1 : 0; 772 773 error = -mlx5_core_set_diagnostics_full(priv->mdev, 774 priv->params_ethtool.diag_pci_enable, 775 priv->params_ethtool.diag_general_enable); 776 break; 777 778 case MLX5_PARAM_OFFSET(mc_local_lb): 779 priv->params_ethtool.mc_local_lb = 780 priv->params_ethtool.mc_local_lb ? 1 : 0; 781 782 if (MLX5_CAP_GEN(priv->mdev, disable_local_lb)) { 783 error = mlx5_nic_vport_modify_local_lb(priv->mdev, 784 MLX5_LOCAL_MC_LB, priv->params_ethtool.mc_local_lb); 785 } else { 786 error = EOPNOTSUPP; 787 } 788 break; 789 790 case MLX5_PARAM_OFFSET(uc_local_lb): 791 priv->params_ethtool.uc_local_lb = 792 priv->params_ethtool.uc_local_lb ? 1 : 0; 793 794 if (MLX5_CAP_GEN(priv->mdev, disable_local_lb)) { 795 error = mlx5_nic_vport_modify_local_lb(priv->mdev, 796 MLX5_LOCAL_UC_LB, priv->params_ethtool.uc_local_lb); 797 } else { 798 error = EOPNOTSUPP; 799 } 800 break; 801 802 default: 803 break; 804 } 805done: 806 PRIV_UNLOCK(priv); 807 return (error); 808} 809 810/* 811 * Read the first three bytes of the eeprom in order to get the needed info 812 * for the whole reading. 813 * Byte 0 - Identifier byte 814 * Byte 1 - Revision byte 815 * Byte 2 - Status byte 816 */ 817static int 818mlx5e_get_eeprom_info(struct mlx5e_priv *priv, struct mlx5e_eeprom *eeprom) 819{ 820 struct mlx5_core_dev *dev = priv->mdev; 821 u32 data = 0; 822 int size_read = 0; 823 int ret; 824 825 ret = mlx5_query_module_num(dev, &eeprom->module_num); 826 if (ret) { 827 if_printf(priv->ifp, "%s:%d: Failed query module error=%d\n", 828 __func__, __LINE__, ret); 829 return (ret); 830 } 831 832 /* Read the first three bytes to get Identifier, Revision and Status */ 833 ret = mlx5_query_eeprom(dev, eeprom->i2c_addr, eeprom->page_num, 834 eeprom->device_addr, MLX5E_EEPROM_INFO_BYTES, eeprom->module_num, &data, 835 &size_read); 836 if (ret) { 837 if_printf(priv->ifp, "%s:%d: Failed query eeprom module error=0x%x\n", 838 __func__, __LINE__, ret); 839 return (ret); 840 } 841 842 switch (data & MLX5_EEPROM_IDENTIFIER_BYTE_MASK) { 843 case SFF_8024_ID_QSFP: 844 eeprom->type = MLX5E_ETH_MODULE_SFF_8436; 845 eeprom->len = MLX5E_ETH_MODULE_SFF_8436_LEN; 846 break; 847 case SFF_8024_ID_QSFPPLUS: 848 case SFF_8024_ID_QSFP28: 849 if ((data & MLX5_EEPROM_IDENTIFIER_BYTE_MASK) == SFF_8024_ID_QSFP28 || 850 ((data & MLX5_EEPROM_REVISION_ID_BYTE_MASK) >> 8) >= 0x3) { 851 eeprom->type = MLX5E_ETH_MODULE_SFF_8636; 852 eeprom->len = MLX5E_ETH_MODULE_SFF_8636_LEN; 853 } else { 854 eeprom->type = MLX5E_ETH_MODULE_SFF_8436; 855 eeprom->len = MLX5E_ETH_MODULE_SFF_8436_LEN; 856 } 857 if ((data & MLX5_EEPROM_PAGE_3_VALID_BIT_MASK) == 0) 858 eeprom->page_valid = 1; 859 break; 860 case SFF_8024_ID_SFP: 861 eeprom->type = MLX5E_ETH_MODULE_SFF_8472; 862 eeprom->len = MLX5E_ETH_MODULE_SFF_8472_LEN; 863 break; 864 default: 865 if_printf(priv->ifp, "%s:%d: Not recognized cable type = 0x%x(%s)\n", 866 __func__, __LINE__, data & MLX5_EEPROM_IDENTIFIER_BYTE_MASK, 867 sff_8024_id[data & MLX5_EEPROM_IDENTIFIER_BYTE_MASK]); 868 return (EINVAL); 869 } 870 return (0); 871} 872 873/* Read both low and high pages of the eeprom */ 874static int 875mlx5e_get_eeprom(struct mlx5e_priv *priv, struct mlx5e_eeprom *ee) 876{ 877 struct mlx5_core_dev *dev = priv->mdev; 878 int size_read = 0; 879 int ret; 880 881 if (ee->len == 0) 882 return (EINVAL); 883 884 /* Read low page of the eeprom */ 885 while (ee->device_addr < ee->len) { 886 ret = mlx5_query_eeprom(dev, ee->i2c_addr, ee->page_num, ee->device_addr, 887 ee->len - ee->device_addr, ee->module_num, 888 ee->data + (ee->device_addr / 4), &size_read); 889 if (ret) { 890 if_printf(priv->ifp, "%s:%d: Failed reading eeprom, " 891 "error = 0x%02x\n", __func__, __LINE__, ret); 892 return (ret); 893 } 894 ee->device_addr += size_read; 895 } 896 897 /* Read high page of the eeprom */ 898 if (ee->page_valid) { 899 ee->device_addr = MLX5E_EEPROM_HIGH_PAGE_OFFSET; 900 ee->page_num = MLX5E_EEPROM_HIGH_PAGE; 901 size_read = 0; 902 while (ee->device_addr < MLX5E_EEPROM_PAGE_LENGTH) { 903 ret = mlx5_query_eeprom(dev, ee->i2c_addr, ee->page_num, 904 ee->device_addr, MLX5E_EEPROM_PAGE_LENGTH - ee->device_addr, 905 ee->module_num, ee->data + (ee->len / 4) + 906 ((ee->device_addr - MLX5E_EEPROM_HIGH_PAGE_OFFSET) / 4), 907 &size_read); 908 if (ret) { 909 if_printf(priv->ifp, "%s:%d: Failed reading eeprom, " 910 "error = 0x%02x\n", __func__, __LINE__, ret); 911 return (ret); 912 } 913 ee->device_addr += size_read; 914 } 915 } 916 return (0); 917} 918 919static void 920mlx5e_print_eeprom(struct mlx5e_eeprom *eeprom) 921{ 922 int row; 923 int index_in_row; 924 int byte_to_write = 0; 925 int line_length = 16; 926 927 printf("\nOffset\t\tValues\n"); 928 printf("------\t\t------"); 929 while (byte_to_write < eeprom->len) { 930 printf("\n0x%04X\t\t", byte_to_write); 931 for (index_in_row = 0; index_in_row < line_length; index_in_row++) { 932 printf("%02X ", ((u8 *)eeprom->data)[byte_to_write]); 933 byte_to_write++; 934 } 935 } 936 937 if (eeprom->page_valid) { 938 row = MLX5E_EEPROM_HIGH_PAGE_OFFSET; 939 printf("\n\nUpper Page 0x03\n"); 940 printf("\nOffset\t\tValues\n"); 941 printf("------\t\t------"); 942 while (row < MLX5E_EEPROM_PAGE_LENGTH) { 943 printf("\n0x%04X\t\t", row); 944 for (index_in_row = 0; index_in_row < line_length; index_in_row++) { 945 printf("%02X ", ((u8 *)eeprom->data)[byte_to_write]); 946 byte_to_write++; 947 row++; 948 } 949 } 950 } 951} 952 953/* 954 * Read cable EEPROM module information by first inspecting the first 955 * three bytes to get the initial information for a whole reading. 956 * Information will be printed to dmesg. 957 */ 958static int 959mlx5e_read_eeprom(SYSCTL_HANDLER_ARGS) 960{ 961 struct mlx5e_priv *priv = arg1; 962 struct mlx5e_eeprom eeprom; 963 int error; 964 int result = 0; 965 966 PRIV_LOCK(priv); 967 error = sysctl_handle_int(oidp, &result, 0, req); 968 if (error || !req->newptr) 969 goto done; 970 971 /* Check if device is gone */ 972 if (priv->gone) { 973 error = ENXIO; 974 goto done; 975 } 976 977 if (result == 1) { 978 eeprom.i2c_addr = MLX5E_I2C_ADDR_LOW; 979 eeprom.device_addr = 0; 980 eeprom.page_num = MLX5E_EEPROM_LOW_PAGE; 981 eeprom.page_valid = 0; 982 983 /* Read three first bytes to get important info */ 984 error = mlx5e_get_eeprom_info(priv, &eeprom); 985 if (error) { 986 if_printf(priv->ifp, "%s:%d: Failed reading eeprom's " 987 "initial information\n", __func__, __LINE__); 988 error = 0; 989 goto done; 990 } 991 /* 992 * Allocate needed length buffer and additional space for 993 * page 0x03 994 */ 995 eeprom.data = malloc(eeprom.len + MLX5E_EEPROM_PAGE_LENGTH, 996 M_MLX5EN, M_WAITOK | M_ZERO); 997 998 /* Read the whole eeprom information */ 999 error = mlx5e_get_eeprom(priv, &eeprom); 1000 if (error) { 1001 if_printf(priv->ifp, "%s:%d: Failed reading eeprom\n", 1002 __func__, __LINE__); 1003 error = 0; 1004 /* 1005 * Continue printing partial information in case of 1006 * an error 1007 */ 1008 } 1009 mlx5e_print_eeprom(&eeprom); 1010 free(eeprom.data, M_MLX5EN); 1011 } 1012done: 1013 PRIV_UNLOCK(priv); 1014 return (error); 1015} 1016 1017static const char *mlx5e_params_desc[] = { 1018 MLX5E_PARAMS(MLX5E_STATS_DESC) 1019}; 1020 1021static const char *mlx5e_port_stats_debug_desc[] = { 1022 MLX5E_PORT_STATS_DEBUG(MLX5E_STATS_DESC) 1023}; 1024 1025static int 1026mlx5e_ethtool_debug_channel_info(SYSCTL_HANDLER_ARGS) 1027{ 1028 struct mlx5e_priv *priv; 1029 struct sbuf sb; 1030 struct mlx5e_channel *c; 1031 struct mlx5e_sq *sq; 1032 struct mlx5e_rq *rq; 1033 int error, i, tc; 1034 bool opened; 1035 1036 priv = arg1; 1037 error = sysctl_wire_old_buffer(req, 0); 1038 if (error != 0) 1039 return (error); 1040 if (sbuf_new_for_sysctl(&sb, NULL, 1024, req) == NULL) 1041 return (ENOMEM); 1042 sbuf_clear_flags(&sb, SBUF_INCLUDENUL); 1043 1044 PRIV_LOCK(priv); 1045 opened = test_bit(MLX5E_STATE_OPENED, &priv->state); 1046 1047 sbuf_printf(&sb, "pages irq %d\n", 1048 priv->mdev->priv.msix_arr[MLX5_EQ_VEC_PAGES].vector); 1049 sbuf_printf(&sb, "command irq %d\n", 1050 priv->mdev->priv.msix_arr[MLX5_EQ_VEC_CMD].vector); 1051 sbuf_printf(&sb, "async irq %d\n", 1052 priv->mdev->priv.msix_arr[MLX5_EQ_VEC_ASYNC].vector); 1053 1054 for (i = 0; i != priv->params.num_channels; i++) { 1055 int eqn_not_used = -1; 1056 int irqn = MLX5_EQ_VEC_COMP_BASE; 1057 1058 if (mlx5_vector2eqn(priv->mdev, i, &eqn_not_used, &irqn) != 0) 1059 continue; 1060 1061 c = opened ? &priv->channel[i] : NULL; 1062 rq = opened ? &c->rq : NULL; 1063 sbuf_printf(&sb, "channel %d rq %d cq %d irq %d\n", i, 1064 opened ? rq->rqn : -1, 1065 opened ? rq->cq.mcq.cqn : -1, 1066 priv->mdev->priv.msix_arr[irqn].vector); 1067 1068 for (tc = 0; tc != priv->num_tc; tc++) { 1069 sq = opened ? &c->sq[tc] : NULL; 1070 sbuf_printf(&sb, "channel %d tc %d sq %d cq %d irq %d\n", 1071 i, tc, 1072 opened ? sq->sqn : -1, 1073 opened ? sq->cq.mcq.cqn : -1, 1074 priv->mdev->priv.msix_arr[irqn].vector); 1075 } 1076 } 1077 PRIV_UNLOCK(priv); 1078 error = sbuf_finish(&sb); 1079 sbuf_delete(&sb); 1080 return (error); 1081} 1082 1083static int 1084mlx5e_ethtool_debug_stats(SYSCTL_HANDLER_ARGS) 1085{ 1086 struct mlx5e_priv *priv = arg1; 1087 int sys_debug; 1088 int error; 1089 1090 PRIV_LOCK(priv); 1091 if (priv->gone != 0) { 1092 error = ENODEV; 1093 goto done; 1094 } 1095 sys_debug = priv->sysctl_debug; 1096 error = sysctl_handle_int(oidp, &sys_debug, 0, req); 1097 if (error != 0 || !req->newptr) 1098 goto done; 1099 sys_debug = sys_debug ? 1 : 0; 1100 if (sys_debug == priv->sysctl_debug) 1101 goto done; 1102 1103 if ((priv->sysctl_debug = sys_debug)) { 1104 mlx5e_create_stats(&priv->stats.port_stats_debug.ctx, 1105 SYSCTL_CHILDREN(priv->sysctl_ifnet), "debug_stats", 1106 mlx5e_port_stats_debug_desc, MLX5E_PORT_STATS_DEBUG_NUM, 1107 priv->stats.port_stats_debug.arg); 1108 SYSCTL_ADD_PROC(&priv->stats.port_stats_debug.ctx, 1109 SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO, 1110 "hw_ctx_debug", 1111 CTLFLAG_RD | CTLFLAG_MPSAFE | CTLTYPE_STRING, priv, 0, 1112 mlx5e_ethtool_debug_channel_info, "S", ""); 1113 } else { 1114 sysctl_ctx_free(&priv->stats.port_stats_debug.ctx); 1115 } 1116done: 1117 PRIV_UNLOCK(priv); 1118 return (error); 1119} 1120 1121static void 1122mlx5e_create_diagnostics(struct mlx5e_priv *priv) 1123{ 1124 struct mlx5_core_diagnostics_entry entry; 1125 struct sysctl_ctx_list *ctx; 1126 struct sysctl_oid *node; 1127 int x; 1128 1129 /* sysctl context we are using */ 1130 ctx = &priv->sysctl_ctx; 1131 1132 /* create root node */ 1133 node = SYSCTL_ADD_NODE(ctx, 1134 SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO, 1135 "diagnostics", CTLFLAG_RD, NULL, "Diagnostics"); 1136 if (node == NULL) 1137 return; 1138 1139 /* create PCI diagnostics */ 1140 for (x = 0; x != MLX5_CORE_PCI_DIAGNOSTICS_NUM; x++) { 1141 entry = mlx5_core_pci_diagnostics_table[x]; 1142 if (mlx5_core_supports_diagnostics(priv->mdev, entry.counter_id) == 0) 1143 continue; 1144 SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO, 1145 entry.desc, CTLFLAG_RD, priv->params_pci.array + x, 1146 "PCI diagnostics counter"); 1147 } 1148 1149 /* create general diagnostics */ 1150 for (x = 0; x != MLX5_CORE_GENERAL_DIAGNOSTICS_NUM; x++) { 1151 entry = mlx5_core_general_diagnostics_table[x]; 1152 if (mlx5_core_supports_diagnostics(priv->mdev, entry.counter_id) == 0) 1153 continue; 1154 SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO, 1155 entry.desc, CTLFLAG_RD, priv->params_general.array + x, 1156 "General diagnostics counter"); 1157 } 1158} 1159 1160void 1161mlx5e_create_ethtool(struct mlx5e_priv *priv) 1162{ 1163 struct sysctl_oid *node, *qos_node; 1164 const char *pnameunit; 1165 unsigned x; 1166 int i; 1167 1168 /* set some defaults */ 1169 priv->params_ethtool.tx_queue_size_max = 1 << MLX5E_PARAMS_MAXIMUM_LOG_SQ_SIZE; 1170 priv->params_ethtool.rx_queue_size_max = 1 << MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE; 1171 priv->params_ethtool.tx_queue_size = 1 << priv->params.log_sq_size; 1172 priv->params_ethtool.rx_queue_size = 1 << priv->params.log_rq_size; 1173 priv->params_ethtool.channels = priv->params.num_channels; 1174 priv->params_ethtool.channels_rsss = priv->params.channels_rsss; 1175 priv->params_ethtool.coalesce_pkts_max = MLX5E_FLD_MAX(cqc, cq_max_count); 1176 priv->params_ethtool.coalesce_usecs_max = MLX5E_FLD_MAX(cqc, cq_period); 1177 priv->params_ethtool.rx_coalesce_mode = priv->params.rx_cq_moderation_mode; 1178 priv->params_ethtool.rx_coalesce_usecs = priv->params.rx_cq_moderation_usec; 1179 priv->params_ethtool.rx_coalesce_pkts = priv->params.rx_cq_moderation_pkts; 1180 priv->params_ethtool.tx_coalesce_mode = priv->params.tx_cq_moderation_mode; 1181 priv->params_ethtool.tx_coalesce_usecs = priv->params.tx_cq_moderation_usec; 1182 priv->params_ethtool.tx_coalesce_pkts = priv->params.tx_cq_moderation_pkts; 1183 priv->params_ethtool.hw_lro = priv->params.hw_lro_en; 1184 priv->params_ethtool.cqe_zipping = priv->params.cqe_zipping_en; 1185 mlx5e_ethtool_sync_tx_completion_fact(priv); 1186 1187 /* get default values for local loopback, if any */ 1188 if (MLX5_CAP_GEN(priv->mdev, disable_local_lb)) { 1189 int err; 1190 u8 val; 1191 1192 err = mlx5_nic_vport_query_local_lb(priv->mdev, MLX5_LOCAL_MC_LB, &val); 1193 if (err == 0) 1194 priv->params_ethtool.mc_local_lb = val; 1195 1196 err = mlx5_nic_vport_query_local_lb(priv->mdev, MLX5_LOCAL_UC_LB, &val); 1197 if (err == 0) 1198 priv->params_ethtool.uc_local_lb = val; 1199 } 1200 1201 /* create root node */ 1202 node = SYSCTL_ADD_NODE(&priv->sysctl_ctx, 1203 SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO, 1204 "conf", CTLFLAG_RW, NULL, "Configuration"); 1205 if (node == NULL) 1206 return; 1207 for (x = 0; x != MLX5E_PARAMS_NUM; x++) { 1208 /* check for read-only parameter */ 1209 if (strstr(mlx5e_params_desc[2 * x], "_max") != NULL || 1210 strstr(mlx5e_params_desc[2 * x], "_mtu") != NULL) { 1211 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO, 1212 mlx5e_params_desc[2 * x], CTLTYPE_U64 | CTLFLAG_RD | 1213 CTLFLAG_MPSAFE, priv, x, &mlx5e_ethtool_handler, "QU", 1214 mlx5e_params_desc[2 * x + 1]); 1215 } else { 1216#if (__FreeBSD_version < 1100000) 1217 char path[64]; 1218#endif 1219 /* 1220 * NOTE: In FreeBSD-11 and newer the 1221 * CTLFLAG_RWTUN flag will take care of 1222 * loading default sysctl value from the 1223 * kernel environment, if any: 1224 */ 1225 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO, 1226 mlx5e_params_desc[2 * x], CTLTYPE_U64 | CTLFLAG_RWTUN | 1227 CTLFLAG_MPSAFE, priv, x, &mlx5e_ethtool_handler, "QU", 1228 mlx5e_params_desc[2 * x + 1]); 1229 1230#if (__FreeBSD_version < 1100000) 1231 /* compute path for sysctl */ 1232 snprintf(path, sizeof(path), "dev.mce.%d.conf.%s", 1233 device_get_unit(priv->mdev->pdev->dev.bsddev), 1234 mlx5e_params_desc[2 * x]); 1235 1236 /* try to fetch tunable, if any */ 1237 if (TUNABLE_QUAD_FETCH(path, &priv->params_ethtool.arg[x])) 1238 mlx5e_ethtool_handler(NULL, priv, x, NULL); 1239#endif 1240 } 1241 } 1242 1243 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO, 1244 "debug_stats", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 1245 0, &mlx5e_ethtool_debug_stats, "I", "Extended debug statistics"); 1246 1247 pnameunit = device_get_nameunit(priv->mdev->pdev->dev.bsddev); 1248 1249 SYSCTL_ADD_STRING(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), 1250 OID_AUTO, "device_name", CTLFLAG_RD, 1251 __DECONST(void *, pnameunit), 0, 1252 "PCI device name"); 1253 1254 /* EEPROM support */ 1255 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO, "eeprom_info", 1256 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 0, 1257 mlx5e_read_eeprom, "I", "EEPROM information"); 1258 1259 /* Diagnostics support */ 1260 mlx5e_create_diagnostics(priv); 1261 1262 /* create qos node */ 1263 qos_node = SYSCTL_ADD_NODE(&priv->sysctl_ctx, 1264 SYSCTL_CHILDREN(node), OID_AUTO, 1265 "qos", CTLFLAG_RW, NULL, "Quality Of Service configuration"); 1266 if (qos_node == NULL) 1267 return; 1268 1269 /* Priority rate limit support */ 1270 if (mlx5e_getmaxrate(priv) == 0) { 1271 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1272 OID_AUTO, "tc_max_rate", CTLTYPE_U64 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1273 priv, 0, mlx5e_tc_maxrate_handler, "QU", 1274 "Max rate for priority, specified in kilobits, where kilo=1000, " 1275 "max_rate must be divisible by 100000"); 1276 } 1277 1278 /* Bandwidth limiting by ratio */ 1279 if (mlx5e_get_max_alloc(priv) == 0) { 1280 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1281 OID_AUTO, "tc_rate_share", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1282 priv, 0, mlx5e_tc_rate_share_handler, "QU", 1283 "Specify bandwidth ratio from 1 to 100 " 1284 "for the available traffic classes"); 1285 } 1286 1287 /* Priority to traffic class mapping */ 1288 if (mlx5e_get_prio_tc(priv) == 0) { 1289 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1290 OID_AUTO, "prio_0_7_tc", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1291 priv, 0, mlx5e_prio_to_tc_handler, "CU", 1292 "Set traffic class 0 to 7 for priority 0 to 7 inclusivly"); 1293 } 1294 1295 /* DSCP support */ 1296 if (mlx5e_get_dscp(priv) == 0) { 1297 for (i = 0; i != MLX5_MAX_SUPPORTED_DSCP; i += 8) { 1298 char name[32]; 1299 snprintf(name, sizeof(name), "dscp_%d_%d_prio", i, i + 7); 1300 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1301 OID_AUTO, name, CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1302 priv, i, mlx5e_dscp_prio_handler, "CU", 1303 "Set DSCP to priority mapping, 0..7"); 1304 } 1305#define A "Set trust state, 1:PCP 2:DSCP" 1306#define B " 3:BOTH" 1307 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1308 OID_AUTO, "trust_state", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1309 priv, 0, mlx5e_trust_state_handler, "CU", 1310 MLX5_CAP_QCAM_FEATURE(priv->mdev, qpts_trust_both) ? 1311 A B : A); 1312#undef B 1313#undef A 1314 } 1315} 1316