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