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 <= 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 310 static int 311 mlx5e_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 337 done: 338 PRIV_UNLOCK(priv); 339 return (err); 340 } 341 342 static int 343 mlx5e_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 383 done: 384 PRIV_UNLOCK(priv); 385 return (err); 386 } 387 388 static int 389 mlx5e_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)); 421 done: 422 PRIV_UNLOCK(priv); 423 return (err); 424 } 425 426 #define MLX5_PARAM_OFFSET(n) \ 427 __offsetof(struct mlx5e_priv, params_ethtool.n) 428 429 static int 430 mlx5e_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 MLX5_CAP_ETH(priv->mdev, lro_cap)) { 674 priv->params_ethtool.hw_lro = 1; 675 /* check if feature should actually be enabled */ 676 if (priv->ifp->if_capenable & IFCAP_LRO) { 677 priv->params.hw_lro_en = true; 678 } else { 679 priv->params.hw_lro_en = false; 680 681 if_printf(priv->ifp, "To enable HW LRO " 682 "please also enable LRO via ifconfig(8).\n"); 683 } 684 } else { 685 /* return an error if HW does not support this feature */ 686 if (priv->params_ethtool.hw_lro != 0) 687 error = EINVAL; 688 priv->params.hw_lro_en = false; 689 priv->params_ethtool.hw_lro = 0; 690 } 691 /* restart network interface, if any */ 692 if (was_opened) 693 mlx5e_open_locked(priv->ifp); 694 break; 695 696 case MLX5_PARAM_OFFSET(cqe_zipping): 697 /* network interface must be down */ 698 if (was_opened) 699 mlx5e_close_locked(priv->ifp); 700 701 /* import CQE zipping mode */ 702 if (priv->params_ethtool.cqe_zipping && 703 MLX5_CAP_GEN(priv->mdev, cqe_compression)) { 704 priv->params.cqe_zipping_en = true; 705 priv->params_ethtool.cqe_zipping = 1; 706 } else { 707 priv->params.cqe_zipping_en = false; 708 priv->params_ethtool.cqe_zipping = 0; 709 } 710 /* restart network interface, if any */ 711 if (was_opened) 712 mlx5e_open_locked(priv->ifp); 713 break; 714 715 case MLX5_PARAM_OFFSET(tx_completion_fact): 716 /* network interface must be down */ 717 if (was_opened) 718 mlx5e_close_locked(priv->ifp); 719 720 /* verify parameter */ 721 mlx5e_ethtool_sync_tx_completion_fact(priv); 722 723 /* restart network interface, if any */ 724 if (was_opened) 725 mlx5e_open_locked(priv->ifp); 726 break; 727 728 case MLX5_PARAM_OFFSET(modify_tx_dma): 729 /* check if network interface is opened */ 730 if (was_opened) { 731 priv->params_ethtool.modify_tx_dma = 732 priv->params_ethtool.modify_tx_dma ? 1 : 0; 733 /* modify tx according to value */ 734 mlx5e_modify_tx_dma(priv, value != 0); 735 } else { 736 /* if closed force enable tx */ 737 priv->params_ethtool.modify_tx_dma = 0; 738 } 739 break; 740 741 case MLX5_PARAM_OFFSET(modify_rx_dma): 742 /* check if network interface is opened */ 743 if (was_opened) { 744 priv->params_ethtool.modify_rx_dma = 745 priv->params_ethtool.modify_rx_dma ? 1 : 0; 746 /* modify rx according to value */ 747 mlx5e_modify_rx_dma(priv, value != 0); 748 } else { 749 /* if closed force enable rx */ 750 priv->params_ethtool.modify_rx_dma = 0; 751 } 752 break; 753 754 case MLX5_PARAM_OFFSET(diag_pci_enable): 755 priv->params_ethtool.diag_pci_enable = 756 priv->params_ethtool.diag_pci_enable ? 1 : 0; 757 758 error = -mlx5_core_set_diagnostics_full(priv->mdev, 759 priv->params_ethtool.diag_pci_enable, 760 priv->params_ethtool.diag_general_enable); 761 break; 762 763 case MLX5_PARAM_OFFSET(diag_general_enable): 764 priv->params_ethtool.diag_general_enable = 765 priv->params_ethtool.diag_general_enable ? 1 : 0; 766 767 error = -mlx5_core_set_diagnostics_full(priv->mdev, 768 priv->params_ethtool.diag_pci_enable, 769 priv->params_ethtool.diag_general_enable); 770 break; 771 772 case MLX5_PARAM_OFFSET(mc_local_lb): 773 priv->params_ethtool.mc_local_lb = 774 priv->params_ethtool.mc_local_lb ? 1 : 0; 775 776 if (MLX5_CAP_GEN(priv->mdev, disable_local_lb)) { 777 error = mlx5_nic_vport_modify_local_lb(priv->mdev, 778 MLX5_LOCAL_MC_LB, priv->params_ethtool.mc_local_lb); 779 } else { 780 error = EOPNOTSUPP; 781 } 782 break; 783 784 case MLX5_PARAM_OFFSET(uc_local_lb): 785 priv->params_ethtool.uc_local_lb = 786 priv->params_ethtool.uc_local_lb ? 1 : 0; 787 788 if (MLX5_CAP_GEN(priv->mdev, disable_local_lb)) { 789 error = mlx5_nic_vport_modify_local_lb(priv->mdev, 790 MLX5_LOCAL_UC_LB, priv->params_ethtool.uc_local_lb); 791 } else { 792 error = EOPNOTSUPP; 793 } 794 break; 795 796 default: 797 break; 798 } 799 done: 800 PRIV_UNLOCK(priv); 801 return (error); 802 } 803 804 /* 805 * Read the first three bytes of the eeprom in order to get the needed info 806 * for the whole reading. 807 * Byte 0 - Identifier byte 808 * Byte 1 - Revision byte 809 * Byte 2 - Status byte 810 */ 811 static int 812 mlx5e_get_eeprom_info(struct mlx5e_priv *priv, struct mlx5e_eeprom *eeprom) 813 { 814 struct mlx5_core_dev *dev = priv->mdev; 815 u32 data = 0; 816 int size_read = 0; 817 int ret; 818 819 ret = mlx5_query_module_num(dev, &eeprom->module_num); 820 if (ret) { 821 if_printf(priv->ifp, "%s:%d: Failed query module error=%d\n", 822 __func__, __LINE__, ret); 823 return (ret); 824 } 825 826 /* Read the first three bytes to get Identifier, Revision and Status */ 827 ret = mlx5_query_eeprom(dev, eeprom->i2c_addr, eeprom->page_num, 828 eeprom->device_addr, MLX5E_EEPROM_INFO_BYTES, eeprom->module_num, &data, 829 &size_read); 830 if (ret) { 831 if_printf(priv->ifp, "%s:%d: Failed query eeprom module error=0x%x\n", 832 __func__, __LINE__, ret); 833 return (ret); 834 } 835 836 switch (data & MLX5_EEPROM_IDENTIFIER_BYTE_MASK) { 837 case SFF_8024_ID_QSFP: 838 eeprom->type = MLX5E_ETH_MODULE_SFF_8436; 839 eeprom->len = MLX5E_ETH_MODULE_SFF_8436_LEN; 840 break; 841 case SFF_8024_ID_QSFPPLUS: 842 case SFF_8024_ID_QSFP28: 843 if ((data & MLX5_EEPROM_IDENTIFIER_BYTE_MASK) == SFF_8024_ID_QSFP28 || 844 ((data & MLX5_EEPROM_REVISION_ID_BYTE_MASK) >> 8) >= 0x3) { 845 eeprom->type = MLX5E_ETH_MODULE_SFF_8636; 846 eeprom->len = MLX5E_ETH_MODULE_SFF_8636_LEN; 847 } else { 848 eeprom->type = MLX5E_ETH_MODULE_SFF_8436; 849 eeprom->len = MLX5E_ETH_MODULE_SFF_8436_LEN; 850 } 851 if ((data & MLX5_EEPROM_PAGE_3_VALID_BIT_MASK) == 0) 852 eeprom->page_valid = 1; 853 break; 854 case SFF_8024_ID_SFP: 855 eeprom->type = MLX5E_ETH_MODULE_SFF_8472; 856 eeprom->len = MLX5E_ETH_MODULE_SFF_8472_LEN; 857 break; 858 default: 859 if_printf(priv->ifp, "%s:%d: Not recognized cable type = 0x%x(%s)\n", 860 __func__, __LINE__, data & MLX5_EEPROM_IDENTIFIER_BYTE_MASK, 861 sff_8024_id[data & MLX5_EEPROM_IDENTIFIER_BYTE_MASK]); 862 return (EINVAL); 863 } 864 return (0); 865 } 866 867 /* Read both low and high pages of the eeprom */ 868 static int 869 mlx5e_get_eeprom(struct mlx5e_priv *priv, struct mlx5e_eeprom *ee) 870 { 871 struct mlx5_core_dev *dev = priv->mdev; 872 int size_read = 0; 873 int ret; 874 875 if (ee->len == 0) 876 return (EINVAL); 877 878 /* Read low page of the eeprom */ 879 while (ee->device_addr < ee->len) { 880 ret = mlx5_query_eeprom(dev, ee->i2c_addr, ee->page_num, ee->device_addr, 881 ee->len - ee->device_addr, ee->module_num, 882 ee->data + (ee->device_addr / 4), &size_read); 883 if (ret) { 884 if_printf(priv->ifp, "%s:%d: Failed reading eeprom, " 885 "error = 0x%02x\n", __func__, __LINE__, ret); 886 return (ret); 887 } 888 ee->device_addr += size_read; 889 } 890 891 /* Read high page of the eeprom */ 892 if (ee->page_valid) { 893 ee->device_addr = MLX5E_EEPROM_HIGH_PAGE_OFFSET; 894 ee->page_num = MLX5E_EEPROM_HIGH_PAGE; 895 size_read = 0; 896 while (ee->device_addr < MLX5E_EEPROM_PAGE_LENGTH) { 897 ret = mlx5_query_eeprom(dev, ee->i2c_addr, ee->page_num, 898 ee->device_addr, MLX5E_EEPROM_PAGE_LENGTH - ee->device_addr, 899 ee->module_num, ee->data + (ee->len / 4) + 900 ((ee->device_addr - MLX5E_EEPROM_HIGH_PAGE_OFFSET) / 4), 901 &size_read); 902 if (ret) { 903 if_printf(priv->ifp, "%s:%d: Failed reading eeprom, " 904 "error = 0x%02x\n", __func__, __LINE__, ret); 905 return (ret); 906 } 907 ee->device_addr += size_read; 908 } 909 } 910 return (0); 911 } 912 913 static void 914 mlx5e_print_eeprom(struct mlx5e_eeprom *eeprom) 915 { 916 int row; 917 int index_in_row; 918 int byte_to_write = 0; 919 int line_length = 16; 920 921 printf("\nOffset\t\tValues\n"); 922 printf("------\t\t------"); 923 while (byte_to_write < eeprom->len) { 924 printf("\n0x%04X\t\t", byte_to_write); 925 for (index_in_row = 0; index_in_row < line_length; index_in_row++) { 926 printf("%02X ", ((u8 *)eeprom->data)[byte_to_write]); 927 byte_to_write++; 928 } 929 } 930 931 if (eeprom->page_valid) { 932 row = MLX5E_EEPROM_HIGH_PAGE_OFFSET; 933 printf("\n\nUpper Page 0x03\n"); 934 printf("\nOffset\t\tValues\n"); 935 printf("------\t\t------"); 936 while (row < MLX5E_EEPROM_PAGE_LENGTH) { 937 printf("\n0x%04X\t\t", row); 938 for (index_in_row = 0; index_in_row < line_length; index_in_row++) { 939 printf("%02X ", ((u8 *)eeprom->data)[byte_to_write]); 940 byte_to_write++; 941 row++; 942 } 943 } 944 } 945 } 946 947 /* 948 * Read cable EEPROM module information by first inspecting the first 949 * three bytes to get the initial information for a whole reading. 950 * Information will be printed to dmesg. 951 */ 952 static int 953 mlx5e_read_eeprom(SYSCTL_HANDLER_ARGS) 954 { 955 struct mlx5e_priv *priv = arg1; 956 struct mlx5e_eeprom eeprom; 957 int error; 958 int result = 0; 959 960 PRIV_LOCK(priv); 961 error = sysctl_handle_int(oidp, &result, 0, req); 962 if (error || !req->newptr) 963 goto done; 964 965 /* Check if device is gone */ 966 if (priv->gone) { 967 error = ENXIO; 968 goto done; 969 } 970 971 if (result == 1) { 972 eeprom.i2c_addr = MLX5E_I2C_ADDR_LOW; 973 eeprom.device_addr = 0; 974 eeprom.page_num = MLX5E_EEPROM_LOW_PAGE; 975 eeprom.page_valid = 0; 976 977 /* Read three first bytes to get important info */ 978 error = mlx5e_get_eeprom_info(priv, &eeprom); 979 if (error) { 980 if_printf(priv->ifp, "%s:%d: Failed reading eeprom's " 981 "initial information\n", __func__, __LINE__); 982 error = 0; 983 goto done; 984 } 985 /* 986 * Allocate needed length buffer and additional space for 987 * page 0x03 988 */ 989 eeprom.data = malloc(eeprom.len + MLX5E_EEPROM_PAGE_LENGTH, 990 M_MLX5EN, M_WAITOK | M_ZERO); 991 992 /* Read the whole eeprom information */ 993 error = mlx5e_get_eeprom(priv, &eeprom); 994 if (error) { 995 if_printf(priv->ifp, "%s:%d: Failed reading eeprom\n", 996 __func__, __LINE__); 997 error = 0; 998 /* 999 * Continue printing partial information in case of 1000 * an error 1001 */ 1002 } 1003 mlx5e_print_eeprom(&eeprom); 1004 free(eeprom.data, M_MLX5EN); 1005 } 1006 done: 1007 PRIV_UNLOCK(priv); 1008 return (error); 1009 } 1010 1011 static const char *mlx5e_params_desc[] = { 1012 MLX5E_PARAMS(MLX5E_STATS_DESC) 1013 }; 1014 1015 static const char *mlx5e_port_stats_debug_desc[] = { 1016 MLX5E_PORT_STATS_DEBUG(MLX5E_STATS_DESC) 1017 }; 1018 1019 static int 1020 mlx5e_ethtool_debug_channel_info(SYSCTL_HANDLER_ARGS) 1021 { 1022 struct mlx5e_priv *priv; 1023 struct sbuf sb; 1024 struct mlx5e_channel *c; 1025 struct mlx5e_sq *sq; 1026 struct mlx5e_rq *rq; 1027 int error, i, tc; 1028 1029 priv = arg1; 1030 error = sysctl_wire_old_buffer(req, 0); 1031 if (error != 0) 1032 return (error); 1033 if (sbuf_new_for_sysctl(&sb, NULL, 128, req) == NULL) 1034 return (ENOMEM); 1035 sbuf_clear_flags(&sb, SBUF_INCLUDENUL); 1036 1037 PRIV_LOCK(priv); 1038 if (test_bit(MLX5E_STATE_OPENED, &priv->state) == 0) 1039 goto out; 1040 for (i = 0; i < priv->params.num_channels; i++) { 1041 c = &priv->channel[i]; 1042 rq = &c->rq; 1043 sbuf_printf(&sb, "channel %d rq %d cq %d\n", 1044 c->ix, rq->rqn, rq->cq.mcq.cqn); 1045 for (tc = 0; tc < c->num_tc; tc++) { 1046 sq = &c->sq[tc]; 1047 sbuf_printf(&sb, "channel %d tc %d sq %d cq %d\n", 1048 c->ix, tc, sq->sqn, sq->cq.mcq.cqn); 1049 } 1050 } 1051 out: 1052 PRIV_UNLOCK(priv); 1053 error = sbuf_finish(&sb); 1054 sbuf_delete(&sb); 1055 return (error); 1056 } 1057 1058 static int 1059 mlx5e_ethtool_debug_stats(SYSCTL_HANDLER_ARGS) 1060 { 1061 struct mlx5e_priv *priv = arg1; 1062 int sys_debug; 1063 int error; 1064 1065 PRIV_LOCK(priv); 1066 sys_debug = priv->sysctl_debug; 1067 error = sysctl_handle_int(oidp, &sys_debug, 0, req); 1068 if (error != 0 || !req->newptr) 1069 goto done; 1070 sys_debug = sys_debug ? 1 : 0; 1071 if (sys_debug == priv->sysctl_debug) 1072 goto done; 1073 1074 if ((priv->sysctl_debug = sys_debug)) { 1075 mlx5e_create_stats(&priv->stats.port_stats_debug.ctx, 1076 SYSCTL_CHILDREN(priv->sysctl_ifnet), "debug_stats", 1077 mlx5e_port_stats_debug_desc, MLX5E_PORT_STATS_DEBUG_NUM, 1078 priv->stats.port_stats_debug.arg); 1079 SYSCTL_ADD_PROC(&priv->stats.port_stats_debug.ctx, 1080 SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO, 1081 "hw_ctx_debug", 1082 CTLFLAG_RD | CTLFLAG_MPSAFE | CTLTYPE_STRING, priv, 0, 1083 mlx5e_ethtool_debug_channel_info, "S", ""); 1084 } else { 1085 sysctl_ctx_free(&priv->stats.port_stats_debug.ctx); 1086 } 1087 done: 1088 PRIV_UNLOCK(priv); 1089 return (error); 1090 } 1091 1092 static void 1093 mlx5e_create_diagnostics(struct mlx5e_priv *priv) 1094 { 1095 struct mlx5_core_diagnostics_entry entry; 1096 struct sysctl_ctx_list *ctx; 1097 struct sysctl_oid *node; 1098 int x; 1099 1100 /* sysctl context we are using */ 1101 ctx = &priv->sysctl_ctx; 1102 1103 /* create root node */ 1104 node = SYSCTL_ADD_NODE(ctx, 1105 SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO, 1106 "diagnostics", CTLFLAG_RD, NULL, "Diagnostics"); 1107 if (node == NULL) 1108 return; 1109 1110 /* create PCI diagnostics */ 1111 for (x = 0; x != MLX5_CORE_PCI_DIAGNOSTICS_NUM; x++) { 1112 entry = mlx5_core_pci_diagnostics_table[x]; 1113 if (mlx5_core_supports_diagnostics(priv->mdev, entry.counter_id) == 0) 1114 continue; 1115 SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO, 1116 entry.desc, CTLFLAG_RD, priv->params_pci.array + x, 1117 "PCI diagnostics counter"); 1118 } 1119 1120 /* create general diagnostics */ 1121 for (x = 0; x != MLX5_CORE_GENERAL_DIAGNOSTICS_NUM; x++) { 1122 entry = mlx5_core_general_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_general.array + x, 1127 "General diagnostics counter"); 1128 } 1129 } 1130 1131 void 1132 mlx5e_create_ethtool(struct mlx5e_priv *priv) 1133 { 1134 struct mlx5_core_dev *mdev = priv->mdev; 1135 struct sysctl_oid *node, *qos_node; 1136 const char *pnameunit; 1137 unsigned x; 1138 int i; 1139 1140 /* set some defaults */ 1141 priv->params_ethtool.tx_queue_size_max = 1 << MLX5E_PARAMS_MAXIMUM_LOG_SQ_SIZE; 1142 priv->params_ethtool.rx_queue_size_max = 1 << MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE; 1143 priv->params_ethtool.tx_queue_size = 1 << priv->params.log_sq_size; 1144 priv->params_ethtool.rx_queue_size = 1 << priv->params.log_rq_size; 1145 priv->params_ethtool.channels = priv->params.num_channels; 1146 priv->params_ethtool.channels_rsss = priv->params.channels_rsss; 1147 priv->params_ethtool.coalesce_pkts_max = MLX5E_FLD_MAX(cqc, cq_max_count); 1148 priv->params_ethtool.coalesce_usecs_max = MLX5E_FLD_MAX(cqc, cq_period); 1149 priv->params_ethtool.rx_coalesce_mode = priv->params.rx_cq_moderation_mode; 1150 priv->params_ethtool.rx_coalesce_usecs = priv->params.rx_cq_moderation_usec; 1151 priv->params_ethtool.rx_coalesce_pkts = priv->params.rx_cq_moderation_pkts; 1152 priv->params_ethtool.tx_coalesce_mode = priv->params.tx_cq_moderation_mode; 1153 priv->params_ethtool.tx_coalesce_usecs = priv->params.tx_cq_moderation_usec; 1154 priv->params_ethtool.tx_coalesce_pkts = priv->params.tx_cq_moderation_pkts; 1155 priv->params_ethtool.hw_lro = priv->params.hw_lro_en; 1156 priv->params_ethtool.cqe_zipping = priv->params.cqe_zipping_en; 1157 mlx5e_ethtool_sync_tx_completion_fact(priv); 1158 1159 /* get default values for local loopback, if any */ 1160 if (MLX5_CAP_GEN(priv->mdev, disable_local_lb)) { 1161 int err; 1162 u8 val; 1163 1164 err = mlx5_nic_vport_query_local_lb(priv->mdev, MLX5_LOCAL_MC_LB, &val); 1165 if (err == 0) 1166 priv->params_ethtool.mc_local_lb = val; 1167 1168 err = mlx5_nic_vport_query_local_lb(priv->mdev, MLX5_LOCAL_UC_LB, &val); 1169 if (err == 0) 1170 priv->params_ethtool.uc_local_lb = val; 1171 } 1172 1173 /* create root node */ 1174 node = SYSCTL_ADD_NODE(&priv->sysctl_ctx, 1175 SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO, 1176 "conf", CTLFLAG_RW, NULL, "Configuration"); 1177 if (node == NULL) 1178 return; 1179 for (x = 0; x != MLX5E_PARAMS_NUM; x++) { 1180 /* check for read-only parameter */ 1181 if (strstr(mlx5e_params_desc[2 * x], "_max") != NULL || 1182 strstr(mlx5e_params_desc[2 * x], "_mtu") != NULL) { 1183 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO, 1184 mlx5e_params_desc[2 * x], CTLTYPE_U64 | CTLFLAG_RD | 1185 CTLFLAG_MPSAFE, priv, x, &mlx5e_ethtool_handler, "QU", 1186 mlx5e_params_desc[2 * x + 1]); 1187 } else { 1188 #if (__FreeBSD_version < 1100000) 1189 char path[64]; 1190 #endif 1191 /* 1192 * NOTE: In FreeBSD-11 and newer the 1193 * CTLFLAG_RWTUN flag will take care of 1194 * loading default sysctl value from the 1195 * kernel environment, if any: 1196 */ 1197 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO, 1198 mlx5e_params_desc[2 * x], CTLTYPE_U64 | CTLFLAG_RWTUN | 1199 CTLFLAG_MPSAFE, priv, x, &mlx5e_ethtool_handler, "QU", 1200 mlx5e_params_desc[2 * x + 1]); 1201 1202 #if (__FreeBSD_version < 1100000) 1203 /* compute path for sysctl */ 1204 snprintf(path, sizeof(path), "dev.mce.%d.conf.%s", 1205 device_get_unit(priv->mdev->pdev->dev.bsddev), 1206 mlx5e_params_desc[2 * x]); 1207 1208 /* try to fetch tunable, if any */ 1209 if (TUNABLE_QUAD_FETCH(path, &priv->params_ethtool.arg[x])) 1210 mlx5e_ethtool_handler(NULL, priv, x, NULL); 1211 #endif 1212 } 1213 } 1214 1215 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO, 1216 "debug_stats", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 1217 0, &mlx5e_ethtool_debug_stats, "I", "Extended debug statistics"); 1218 1219 pnameunit = device_get_nameunit(priv->mdev->pdev->dev.bsddev); 1220 1221 SYSCTL_ADD_STRING(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), 1222 OID_AUTO, "device_name", CTLFLAG_RD, 1223 __DECONST(void *, pnameunit), 0, 1224 "PCI device name"); 1225 1226 /* EEPROM support */ 1227 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO, "eeprom_info", 1228 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 0, 1229 mlx5e_read_eeprom, "I", "EEPROM information"); 1230 1231 /* Diagnostics support */ 1232 mlx5e_create_diagnostics(priv); 1233 1234 /* create qos node */ 1235 qos_node = SYSCTL_ADD_NODE(&priv->sysctl_ctx, 1236 SYSCTL_CHILDREN(node), OID_AUTO, 1237 "qos", CTLFLAG_RW, NULL, "Quality Of Service configuration"); 1238 if (qos_node == NULL) 1239 return; 1240 1241 /* Priority rate limit support */ 1242 if (mlx5e_getmaxrate(priv) == 0) { 1243 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1244 OID_AUTO, "tc_max_rate", CTLTYPE_U64 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1245 priv, 0, mlx5e_tc_maxrate_handler, "QU", 1246 "Max rate for priority, specified in kilobits, where kilo=1000, " 1247 "max_rate must be divisible by 100000"); 1248 } 1249 1250 /* Bandwidth limiting by ratio */ 1251 if (mlx5e_get_max_alloc(priv) == 0) { 1252 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1253 OID_AUTO, "tc_rate_share", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1254 priv, 0, mlx5e_tc_rate_share_handler, "QU", 1255 "Specify bandwidth ratio from 1 to 100 " 1256 "for the available traffic classes"); 1257 } 1258 1259 /* Priority to traffic class mapping */ 1260 if (mlx5e_get_prio_tc(priv) == 0) { 1261 for (i = 0; i <= mlx5_max_tc(mdev); i++) { 1262 char name[32]; 1263 snprintf(name, sizeof(name), "prio_%d_to_tc", i); 1264 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1265 OID_AUTO, name, CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1266 priv, i, mlx5e_prio_to_tc_handler, "CU", 1267 "Set priority to traffic class"); 1268 } 1269 } 1270 1271 /* DSCP support */ 1272 if (mlx5e_get_dscp(priv) == 0) { 1273 for (i = 0; i != MLX5_MAX_SUPPORTED_DSCP; i += 8) { 1274 char name[32]; 1275 snprintf(name, sizeof(name), "dscp_%d_%d_prio", i, i + 7); 1276 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1277 OID_AUTO, name, CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1278 priv, i, mlx5e_dscp_prio_handler, "CU", 1279 "Set DSCP to priority mapping, 0..7"); 1280 } 1281 #define A "Set trust state, 1:PCP 2:DSCP" 1282 #define B " 3:BOTH" 1283 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1284 OID_AUTO, "trust_state", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1285 priv, 0, mlx5e_trust_state_handler, "CU", 1286 MLX5_CAP_QCAM_FEATURE(mdev, qpts_trust_both) ? 1287 A B : A); 1288 #undef B 1289 #undef A 1290 } 1291 } 1292