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$ 26 */ 27 28 #include "en.h" 29 #include <net/sff8472.h> 30 31 void 32 mlx5e_create_stats(struct sysctl_ctx_list *ctx, 33 struct sysctl_oid_list *parent, const char *buffer, 34 const char **desc, unsigned num, u64 * arg) 35 { 36 struct sysctl_oid *node; 37 unsigned x; 38 39 sysctl_ctx_init(ctx); 40 41 node = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, 42 buffer, CTLFLAG_RD, NULL, "Statistics"); 43 if (node == NULL) 44 return; 45 for (x = 0; x != num; x++) { 46 SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO, 47 desc[2 * x], CTLFLAG_RD, arg + x, desc[2 * x + 1]); 48 } 49 } 50 51 static void 52 mlx5e_ethtool_sync_tx_completion_fact(struct mlx5e_priv *priv) 53 { 54 /* 55 * Limit the maximum distance between completion events to 56 * half of the currently set TX queue size. 57 * 58 * The maximum number of queue entries a single IP packet can 59 * consume is given by MLX5_SEND_WQE_MAX_WQEBBS. 60 * 61 * The worst case max value is then given as below: 62 */ 63 uint64_t max = priv->params_ethtool.tx_queue_size / 64 (2 * MLX5_SEND_WQE_MAX_WQEBBS); 65 66 /* 67 * Update the maximum completion factor value in case the 68 * tx_queue_size field changed. Ensure we don't overflow 69 * 16-bits. 70 */ 71 if (max < 1) 72 max = 1; 73 else if (max > 65535) 74 max = 65535; 75 priv->params_ethtool.tx_completion_fact_max = max; 76 77 /* 78 * Verify that the current TX completion factor is within the 79 * given limits: 80 */ 81 if (priv->params_ethtool.tx_completion_fact < 1) 82 priv->params_ethtool.tx_completion_fact = 1; 83 else if (priv->params_ethtool.tx_completion_fact > max) 84 priv->params_ethtool.tx_completion_fact = max; 85 } 86 87 static int 88 mlx5e_getmaxrate(struct mlx5e_priv *priv) 89 { 90 struct mlx5_core_dev *mdev = priv->mdev; 91 u8 max_bw_unit[IEEE_8021QAZ_MAX_TCS]; 92 u8 max_bw_value[IEEE_8021QAZ_MAX_TCS]; 93 int err; 94 int i; 95 96 PRIV_LOCK(priv); 97 err = -mlx5_query_port_tc_rate_limit(mdev, max_bw_value, max_bw_unit); 98 if (err) 99 goto done; 100 101 for (i = 0; i <= mlx5_max_tc(mdev); i++) { 102 switch (max_bw_unit[i]) { 103 case MLX5_100_MBPS_UNIT: 104 priv->params_ethtool.max_bw_value[i] = max_bw_value[i] * MLX5E_100MB; 105 break; 106 case MLX5_GBPS_UNIT: 107 priv->params_ethtool.max_bw_value[i] = max_bw_value[i] * MLX5E_1GB; 108 break; 109 case MLX5_BW_NO_LIMIT: 110 priv->params_ethtool.max_bw_value[i] = 0; 111 break; 112 default: 113 priv->params_ethtool.max_bw_value[i] = -1; 114 WARN_ONCE(true, "non-supported BW unit"); 115 break; 116 } 117 } 118 done: 119 PRIV_UNLOCK(priv); 120 return (err); 121 } 122 123 static int 124 mlx5e_get_max_alloc(struct mlx5e_priv *priv) 125 { 126 struct mlx5_core_dev *mdev = priv->mdev; 127 int err; 128 int x; 129 130 PRIV_LOCK(priv); 131 err = -mlx5_query_port_tc_bw_alloc(mdev, priv->params_ethtool.max_bw_share); 132 if (err == 0) { 133 /* set default value */ 134 for (x = 0; x != IEEE_8021QAZ_MAX_TCS; x++) { 135 priv->params_ethtool.max_bw_share[x] = 136 100 / IEEE_8021QAZ_MAX_TCS; 137 } 138 err = -mlx5_set_port_tc_bw_alloc(mdev, 139 priv->params_ethtool.max_bw_share); 140 } 141 PRIV_UNLOCK(priv); 142 143 return (err); 144 } 145 146 static int 147 mlx5e_get_dscp(struct mlx5e_priv *priv) 148 { 149 struct mlx5_core_dev *mdev = priv->mdev; 150 int err; 151 152 if (MLX5_CAP_GEN(mdev, qcam_reg) == 0 || 153 MLX5_CAP_QCAM_REG(mdev, qpts) == 0 || 154 MLX5_CAP_QCAM_REG(mdev, qpdpm) == 0) 155 return (EOPNOTSUPP); 156 157 PRIV_LOCK(priv); 158 err = -mlx5_query_dscp2prio(mdev, priv->params_ethtool.dscp2prio); 159 if (err) 160 goto done; 161 162 err = -mlx5_query_trust_state(mdev, &priv->params_ethtool.trust_state); 163 if (err) 164 goto done; 165 done: 166 PRIV_UNLOCK(priv); 167 return (err); 168 } 169 170 static void 171 mlx5e_tc_get_parameters(struct mlx5e_priv *priv, 172 u64 *new_bw_value, u8 *max_bw_value, u8 *max_bw_unit) 173 { 174 const u64 upper_limit_mbps = 255 * MLX5E_100MB; 175 const u64 upper_limit_gbps = 255 * MLX5E_1GB; 176 u64 temp; 177 int i; 178 179 memset(max_bw_value, 0, IEEE_8021QAZ_MAX_TCS); 180 memset(max_bw_unit, 0, IEEE_8021QAZ_MAX_TCS); 181 182 for (i = 0; i <= mlx5_max_tc(priv->mdev); i++) { 183 temp = (new_bw_value != NULL) ? 184 new_bw_value[i] : priv->params_ethtool.max_bw_value[i]; 185 186 if (!temp) { 187 max_bw_unit[i] = MLX5_BW_NO_LIMIT; 188 } else if (temp > upper_limit_gbps) { 189 max_bw_unit[i] = MLX5_BW_NO_LIMIT; 190 } else if (temp <= upper_limit_mbps) { 191 max_bw_value[i] = howmany(temp, MLX5E_100MB); 192 max_bw_unit[i] = MLX5_100_MBPS_UNIT; 193 } else { 194 max_bw_value[i] = howmany(temp, MLX5E_1GB); 195 max_bw_unit[i] = MLX5_GBPS_UNIT; 196 } 197 } 198 } 199 200 static int 201 mlx5e_tc_maxrate_handler(SYSCTL_HANDLER_ARGS) 202 { 203 struct mlx5e_priv *priv = arg1; 204 struct mlx5_core_dev *mdev = priv->mdev; 205 u8 max_bw_unit[IEEE_8021QAZ_MAX_TCS]; 206 u8 max_bw_value[IEEE_8021QAZ_MAX_TCS]; 207 u64 new_bw_value[IEEE_8021QAZ_MAX_TCS]; 208 u8 max_rates = mlx5_max_tc(mdev) + 1; 209 u8 x; 210 int err; 211 212 PRIV_LOCK(priv); 213 err = SYSCTL_OUT(req, priv->params_ethtool.max_bw_value, 214 sizeof(priv->params_ethtool.max_bw_value[0]) * max_rates); 215 if (err || !req->newptr) 216 goto done; 217 err = SYSCTL_IN(req, new_bw_value, 218 sizeof(new_bw_value[0]) * max_rates); 219 if (err) 220 goto done; 221 222 /* range check input value */ 223 for (x = 0; x != max_rates; x++) { 224 if (new_bw_value[x] % MLX5E_100MB) { 225 err = ERANGE; 226 goto done; 227 } 228 } 229 230 mlx5e_tc_get_parameters(priv, new_bw_value, max_bw_value, max_bw_unit); 231 232 err = -mlx5_modify_port_tc_rate_limit(mdev, max_bw_value, max_bw_unit); 233 if (err) 234 goto done; 235 236 memcpy(priv->params_ethtool.max_bw_value, new_bw_value, 237 sizeof(priv->params_ethtool.max_bw_value)); 238 done: 239 PRIV_UNLOCK(priv); 240 return (err); 241 } 242 243 static int 244 mlx5e_tc_rate_share_handler(SYSCTL_HANDLER_ARGS) 245 { 246 struct mlx5e_priv *priv = arg1; 247 struct mlx5_core_dev *mdev = priv->mdev; 248 u8 max_bw_share[IEEE_8021QAZ_MAX_TCS]; 249 u8 max_rates = mlx5_max_tc(mdev) + 1; 250 int i; 251 int err; 252 int sum; 253 254 PRIV_LOCK(priv); 255 err = SYSCTL_OUT(req, priv->params_ethtool.max_bw_share, max_rates); 256 if (err || !req->newptr) 257 goto done; 258 err = SYSCTL_IN(req, max_bw_share, max_rates); 259 if (err) 260 goto done; 261 262 /* range check input value */ 263 for (sum = i = 0; i != max_rates; i++) { 264 if (max_bw_share[i] < 1 || max_bw_share[i] > 100) { 265 err = ERANGE; 266 goto done; 267 } 268 sum += max_bw_share[i]; 269 } 270 271 /* sum of values should be as close to 100 as possible */ 272 if (sum < (100 - max_rates + 1) || sum > 100) { 273 err = ERANGE; 274 goto done; 275 } 276 277 err = -mlx5_set_port_tc_bw_alloc(mdev, max_bw_share); 278 if (err) 279 goto done; 280 281 memcpy(priv->params_ethtool.max_bw_share, max_bw_share, 282 sizeof(priv->params_ethtool.max_bw_share)); 283 done: 284 PRIV_UNLOCK(priv); 285 return (err); 286 } 287 288 static int 289 mlx5e_get_prio_tc(struct mlx5e_priv *priv) 290 { 291 struct mlx5_core_dev *mdev = priv->mdev; 292 int err = 0; 293 int i; 294 295 PRIV_LOCK(priv); 296 if (!MLX5_CAP_GEN(priv->mdev, ets)) { 297 PRIV_UNLOCK(priv); 298 return (EOPNOTSUPP); 299 } 300 301 for (i = 0; i != MLX5E_MAX_PRIORITY; i++) { 302 err = -mlx5_query_port_prio_tc(mdev, i, priv->params_ethtool.prio_tc + i); 303 if (err) 304 break; 305 } 306 PRIV_UNLOCK(priv); 307 return (err); 308 } 309 310 static int 311 mlx5e_prio_to_tc_handler(SYSCTL_HANDLER_ARGS) 312 { 313 struct mlx5e_priv *priv = arg1; 314 struct mlx5_core_dev *mdev = priv->mdev; 315 uint8_t temp[MLX5E_MAX_PRIORITY]; 316 int err; 317 int i; 318 319 PRIV_LOCK(priv); 320 err = SYSCTL_OUT(req, priv->params_ethtool.prio_tc, MLX5E_MAX_PRIORITY); 321 if (err || !req->newptr) 322 goto done; 323 err = SYSCTL_IN(req, temp, MLX5E_MAX_PRIORITY); 324 if (err) 325 goto done; 326 327 for (i = 0; i != MLX5E_MAX_PRIORITY; i++) { 328 if (temp[i] > mlx5_max_tc(mdev)) { 329 err = ERANGE; 330 goto done; 331 } 332 } 333 334 for (i = 0; i != MLX5E_MAX_PRIORITY; i++) { 335 if (temp[i] == priv->params_ethtool.prio_tc[i]) 336 continue; 337 err = -mlx5_set_port_prio_tc(mdev, i, temp[i]); 338 if (err) 339 goto done; 340 /* update cached value */ 341 priv->params_ethtool.prio_tc[i] = temp[i]; 342 } 343 done: 344 PRIV_UNLOCK(priv); 345 return (err); 346 } 347 348 static int 349 mlx5e_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 389 done: 390 PRIV_UNLOCK(priv); 391 return (err); 392 } 393 394 static int 395 mlx5e_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)); 427 done: 428 PRIV_UNLOCK(priv); 429 return (err); 430 } 431 432 #define MLX5_PARAM_OFFSET(n) \ 433 __offsetof(struct mlx5e_priv, params_ethtool.n) 434 435 static int 436 mlx5e_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 } 805 done: 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 */ 817 static int 818 mlx5e_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 */ 874 static int 875 mlx5e_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 919 static void 920 mlx5e_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 */ 958 static int 959 mlx5e_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 } 1012 done: 1013 PRIV_UNLOCK(priv); 1014 return (error); 1015 } 1016 1017 static const char *mlx5e_params_desc[] = { 1018 MLX5E_PARAMS(MLX5E_STATS_DESC) 1019 }; 1020 1021 static const char *mlx5e_port_stats_debug_desc[] = { 1022 MLX5E_PORT_STATS_DEBUG(MLX5E_STATS_DESC) 1023 }; 1024 1025 static int 1026 mlx5e_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 1035 priv = arg1; 1036 error = sysctl_wire_old_buffer(req, 0); 1037 if (error != 0) 1038 return (error); 1039 if (sbuf_new_for_sysctl(&sb, NULL, 128, req) == NULL) 1040 return (ENOMEM); 1041 sbuf_clear_flags(&sb, SBUF_INCLUDENUL); 1042 1043 PRIV_LOCK(priv); 1044 if (test_bit(MLX5E_STATE_OPENED, &priv->state) == 0) 1045 goto out; 1046 for (i = 0; i < priv->params.num_channels; i++) { 1047 c = &priv->channel[i]; 1048 rq = &c->rq; 1049 sbuf_printf(&sb, "channel %d rq %d cq %d\n", 1050 c->ix, rq->rqn, rq->cq.mcq.cqn); 1051 for (tc = 0; tc < c->num_tc; tc++) { 1052 sq = &c->sq[tc]; 1053 sbuf_printf(&sb, "channel %d tc %d sq %d cq %d\n", 1054 c->ix, tc, sq->sqn, sq->cq.mcq.cqn); 1055 } 1056 } 1057 out: 1058 PRIV_UNLOCK(priv); 1059 error = sbuf_finish(&sb); 1060 sbuf_delete(&sb); 1061 return (error); 1062 } 1063 1064 static int 1065 mlx5e_ethtool_debug_stats(SYSCTL_HANDLER_ARGS) 1066 { 1067 struct mlx5e_priv *priv = arg1; 1068 int sys_debug; 1069 int error; 1070 1071 PRIV_LOCK(priv); 1072 if (priv->gone != 0) { 1073 error = ENODEV; 1074 goto done; 1075 } 1076 sys_debug = priv->sysctl_debug; 1077 error = sysctl_handle_int(oidp, &sys_debug, 0, req); 1078 if (error != 0 || !req->newptr) 1079 goto done; 1080 sys_debug = sys_debug ? 1 : 0; 1081 if (sys_debug == priv->sysctl_debug) 1082 goto done; 1083 1084 if ((priv->sysctl_debug = sys_debug)) { 1085 mlx5e_create_stats(&priv->stats.port_stats_debug.ctx, 1086 SYSCTL_CHILDREN(priv->sysctl_ifnet), "debug_stats", 1087 mlx5e_port_stats_debug_desc, MLX5E_PORT_STATS_DEBUG_NUM, 1088 priv->stats.port_stats_debug.arg); 1089 SYSCTL_ADD_PROC(&priv->stats.port_stats_debug.ctx, 1090 SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO, 1091 "hw_ctx_debug", 1092 CTLFLAG_RD | CTLFLAG_MPSAFE | CTLTYPE_STRING, priv, 0, 1093 mlx5e_ethtool_debug_channel_info, "S", ""); 1094 } else { 1095 sysctl_ctx_free(&priv->stats.port_stats_debug.ctx); 1096 } 1097 done: 1098 PRIV_UNLOCK(priv); 1099 return (error); 1100 } 1101 1102 static void 1103 mlx5e_create_diagnostics(struct mlx5e_priv *priv) 1104 { 1105 struct mlx5_core_diagnostics_entry entry; 1106 struct sysctl_ctx_list *ctx; 1107 struct sysctl_oid *node; 1108 int x; 1109 1110 /* sysctl context we are using */ 1111 ctx = &priv->sysctl_ctx; 1112 1113 /* create root node */ 1114 node = SYSCTL_ADD_NODE(ctx, 1115 SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO, 1116 "diagnostics", CTLFLAG_RD, NULL, "Diagnostics"); 1117 if (node == NULL) 1118 return; 1119 1120 /* create PCI diagnostics */ 1121 for (x = 0; x != MLX5_CORE_PCI_DIAGNOSTICS_NUM; x++) { 1122 entry = mlx5_core_pci_diagnostics_table[x]; 1123 if (mlx5_core_supports_diagnostics(priv->mdev, entry.counter_id) == 0) 1124 continue; 1125 SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO, 1126 entry.desc, CTLFLAG_RD, priv->params_pci.array + x, 1127 "PCI diagnostics counter"); 1128 } 1129 1130 /* create general diagnostics */ 1131 for (x = 0; x != MLX5_CORE_GENERAL_DIAGNOSTICS_NUM; x++) { 1132 entry = mlx5_core_general_diagnostics_table[x]; 1133 if (mlx5_core_supports_diagnostics(priv->mdev, entry.counter_id) == 0) 1134 continue; 1135 SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO, 1136 entry.desc, CTLFLAG_RD, priv->params_general.array + x, 1137 "General diagnostics counter"); 1138 } 1139 } 1140 1141 void 1142 mlx5e_create_ethtool(struct mlx5e_priv *priv) 1143 { 1144 struct sysctl_oid *node, *qos_node; 1145 const char *pnameunit; 1146 unsigned x; 1147 int i; 1148 1149 /* set some defaults */ 1150 priv->params_ethtool.tx_queue_size_max = 1 << MLX5E_PARAMS_MAXIMUM_LOG_SQ_SIZE; 1151 priv->params_ethtool.rx_queue_size_max = 1 << MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE; 1152 priv->params_ethtool.tx_queue_size = 1 << priv->params.log_sq_size; 1153 priv->params_ethtool.rx_queue_size = 1 << priv->params.log_rq_size; 1154 priv->params_ethtool.channels = priv->params.num_channels; 1155 priv->params_ethtool.channels_rsss = priv->params.channels_rsss; 1156 priv->params_ethtool.coalesce_pkts_max = MLX5E_FLD_MAX(cqc, cq_max_count); 1157 priv->params_ethtool.coalesce_usecs_max = MLX5E_FLD_MAX(cqc, cq_period); 1158 priv->params_ethtool.rx_coalesce_mode = priv->params.rx_cq_moderation_mode; 1159 priv->params_ethtool.rx_coalesce_usecs = priv->params.rx_cq_moderation_usec; 1160 priv->params_ethtool.rx_coalesce_pkts = priv->params.rx_cq_moderation_pkts; 1161 priv->params_ethtool.tx_coalesce_mode = priv->params.tx_cq_moderation_mode; 1162 priv->params_ethtool.tx_coalesce_usecs = priv->params.tx_cq_moderation_usec; 1163 priv->params_ethtool.tx_coalesce_pkts = priv->params.tx_cq_moderation_pkts; 1164 priv->params_ethtool.hw_lro = priv->params.hw_lro_en; 1165 priv->params_ethtool.cqe_zipping = priv->params.cqe_zipping_en; 1166 mlx5e_ethtool_sync_tx_completion_fact(priv); 1167 1168 /* get default values for local loopback, if any */ 1169 if (MLX5_CAP_GEN(priv->mdev, disable_local_lb)) { 1170 int err; 1171 u8 val; 1172 1173 err = mlx5_nic_vport_query_local_lb(priv->mdev, MLX5_LOCAL_MC_LB, &val); 1174 if (err == 0) 1175 priv->params_ethtool.mc_local_lb = val; 1176 1177 err = mlx5_nic_vport_query_local_lb(priv->mdev, MLX5_LOCAL_UC_LB, &val); 1178 if (err == 0) 1179 priv->params_ethtool.uc_local_lb = val; 1180 } 1181 1182 /* create root node */ 1183 node = SYSCTL_ADD_NODE(&priv->sysctl_ctx, 1184 SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO, 1185 "conf", CTLFLAG_RW, NULL, "Configuration"); 1186 if (node == NULL) 1187 return; 1188 for (x = 0; x != MLX5E_PARAMS_NUM; x++) { 1189 /* check for read-only parameter */ 1190 if (strstr(mlx5e_params_desc[2 * x], "_max") != NULL || 1191 strstr(mlx5e_params_desc[2 * x], "_mtu") != NULL) { 1192 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO, 1193 mlx5e_params_desc[2 * x], CTLTYPE_U64 | CTLFLAG_RD | 1194 CTLFLAG_MPSAFE, priv, x, &mlx5e_ethtool_handler, "QU", 1195 mlx5e_params_desc[2 * x + 1]); 1196 } else { 1197 #if (__FreeBSD_version < 1100000) 1198 char path[64]; 1199 #endif 1200 /* 1201 * NOTE: In FreeBSD-11 and newer the 1202 * CTLFLAG_RWTUN flag will take care of 1203 * loading default sysctl value from the 1204 * kernel environment, if any: 1205 */ 1206 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO, 1207 mlx5e_params_desc[2 * x], CTLTYPE_U64 | CTLFLAG_RWTUN | 1208 CTLFLAG_MPSAFE, priv, x, &mlx5e_ethtool_handler, "QU", 1209 mlx5e_params_desc[2 * x + 1]); 1210 1211 #if (__FreeBSD_version < 1100000) 1212 /* compute path for sysctl */ 1213 snprintf(path, sizeof(path), "dev.mce.%d.conf.%s", 1214 device_get_unit(priv->mdev->pdev->dev.bsddev), 1215 mlx5e_params_desc[2 * x]); 1216 1217 /* try to fetch tunable, if any */ 1218 if (TUNABLE_QUAD_FETCH(path, &priv->params_ethtool.arg[x])) 1219 mlx5e_ethtool_handler(NULL, priv, x, NULL); 1220 #endif 1221 } 1222 } 1223 1224 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO, 1225 "debug_stats", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 1226 0, &mlx5e_ethtool_debug_stats, "I", "Extended debug statistics"); 1227 1228 pnameunit = device_get_nameunit(priv->mdev->pdev->dev.bsddev); 1229 1230 SYSCTL_ADD_STRING(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), 1231 OID_AUTO, "device_name", CTLFLAG_RD, 1232 __DECONST(void *, pnameunit), 0, 1233 "PCI device name"); 1234 1235 /* EEPROM support */ 1236 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO, "eeprom_info", 1237 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 0, 1238 mlx5e_read_eeprom, "I", "EEPROM information"); 1239 1240 /* Diagnostics support */ 1241 mlx5e_create_diagnostics(priv); 1242 1243 /* create qos node */ 1244 qos_node = SYSCTL_ADD_NODE(&priv->sysctl_ctx, 1245 SYSCTL_CHILDREN(node), OID_AUTO, 1246 "qos", CTLFLAG_RW, NULL, "Quality Of Service configuration"); 1247 if (qos_node == NULL) 1248 return; 1249 1250 /* Priority rate limit support */ 1251 if (mlx5e_getmaxrate(priv) == 0) { 1252 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1253 OID_AUTO, "tc_max_rate", CTLTYPE_U64 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1254 priv, 0, mlx5e_tc_maxrate_handler, "QU", 1255 "Max rate for priority, specified in kilobits, where kilo=1000, " 1256 "max_rate must be divisible by 100000"); 1257 } 1258 1259 /* Bandwidth limiting by ratio */ 1260 if (mlx5e_get_max_alloc(priv) == 0) { 1261 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1262 OID_AUTO, "tc_rate_share", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1263 priv, 0, mlx5e_tc_rate_share_handler, "QU", 1264 "Specify bandwidth ratio from 1 to 100 " 1265 "for the available traffic classes"); 1266 } 1267 1268 /* Priority to traffic class mapping */ 1269 if (mlx5e_get_prio_tc(priv) == 0) { 1270 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1271 OID_AUTO, "prio_0_7_tc", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1272 priv, 0, mlx5e_prio_to_tc_handler, "CU", 1273 "Set traffic class 0 to 7 for priority 0 to 7 inclusivly"); 1274 } 1275 1276 /* DSCP support */ 1277 if (mlx5e_get_dscp(priv) == 0) { 1278 for (i = 0; i != MLX5_MAX_SUPPORTED_DSCP; i += 8) { 1279 char name[32]; 1280 snprintf(name, sizeof(name), "dscp_%d_%d_prio", i, i + 7); 1281 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1282 OID_AUTO, name, CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1283 priv, i, mlx5e_dscp_prio_handler, "CU", 1284 "Set DSCP to priority mapping, 0..7"); 1285 } 1286 #define A "Set trust state, 1:PCP 2:DSCP" 1287 #define B " 3:BOTH" 1288 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1289 OID_AUTO, "trust_state", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1290 priv, 0, mlx5e_trust_state_handler, "CU", 1291 MLX5_CAP_QCAM_FEATURE(priv->mdev, qpts_trust_both) ? 1292 A B : A); 1293 #undef B 1294 #undef A 1295 } 1296 } 1297