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_dscp(struct mlx5e_priv *priv) 125 { 126 struct mlx5_core_dev *mdev = priv->mdev; 127 int err; 128 129 if (MLX5_CAP_GEN(mdev, qcam_reg) == 0 || 130 MLX5_CAP_QCAM_REG(mdev, qpts) == 0 || 131 MLX5_CAP_QCAM_REG(mdev, qpdpm) == 0) 132 return (EOPNOTSUPP); 133 134 PRIV_LOCK(priv); 135 err = -mlx5_query_dscp2prio(mdev, priv->params_ethtool.dscp2prio); 136 if (err) 137 goto done; 138 139 err = -mlx5_query_trust_state(mdev, &priv->params_ethtool.trust_state); 140 if (err) 141 goto done; 142 done: 143 PRIV_UNLOCK(priv); 144 return (err); 145 } 146 147 static int 148 mlx5e_tc_maxrate_handler(SYSCTL_HANDLER_ARGS) 149 { 150 struct mlx5e_priv *priv = arg1; 151 int prio_index = arg2; 152 struct mlx5_core_dev *mdev = priv->mdev; 153 u8 max_bw_unit[IEEE_8021QAZ_MAX_TCS]; 154 u8 max_bw_value[IEEE_8021QAZ_MAX_TCS]; 155 int i, err; 156 u64 bw_val; 157 u64 result = priv->params_ethtool.max_bw_value[prio_index]; 158 const u64 upper_limit_mbps = 255 * MLX5E_100MB; 159 const u64 upper_limit_gbps = 255 * MLX5E_1GB; 160 161 PRIV_LOCK(priv); 162 err = sysctl_handle_64(oidp, &result, 0, req); 163 if (err || !req->newptr || 164 result == priv->params_ethtool.max_bw_value[prio_index]) 165 goto done; 166 167 if (result % MLX5E_100MB) { 168 err = ERANGE; 169 goto done; 170 } 171 172 memset(max_bw_value, 0, sizeof(max_bw_value)); 173 memset(max_bw_unit, 0, sizeof(max_bw_unit)); 174 175 for (i = 0; i <= mlx5_max_tc(mdev); i++) { 176 bw_val = (i == prio_index) ? result : priv->params_ethtool.max_bw_value[i]; 177 178 if (!bw_val) { 179 max_bw_unit[i] = MLX5_BW_NO_LIMIT; 180 } else if (bw_val > upper_limit_gbps) { 181 result = 0; 182 max_bw_unit[i] = MLX5_BW_NO_LIMIT; 183 } else if (bw_val <= upper_limit_mbps) { 184 max_bw_value[i] = howmany(bw_val, MLX5E_100MB); 185 max_bw_unit[i] = MLX5_100_MBPS_UNIT; 186 } else { 187 max_bw_value[i] = howmany(bw_val, MLX5E_1GB); 188 max_bw_unit[i] = MLX5_GBPS_UNIT; 189 } 190 } 191 192 err = -mlx5_modify_port_tc_rate_limit(mdev, max_bw_value, max_bw_unit); 193 if (err) 194 goto done; 195 196 priv->params_ethtool.max_bw_value[prio_index] = result; 197 done: 198 PRIV_UNLOCK(priv); 199 return (err); 200 } 201 202 static int 203 mlx5e_get_prio_tc(struct mlx5e_priv *priv) 204 { 205 struct mlx5_core_dev *mdev = priv->mdev; 206 int err = 0; 207 int i; 208 209 PRIV_LOCK(priv); 210 if (!MLX5_CAP_GEN(priv->mdev, ets)) { 211 PRIV_UNLOCK(priv); 212 return (EOPNOTSUPP); 213 } 214 215 for (i = 0; i <= mlx5_max_tc(priv->mdev); i++) { 216 err = -mlx5_query_port_prio_tc(mdev, i, &(priv->params_ethtool.prio_tc[i])); 217 if (err) 218 break; 219 } 220 221 PRIV_UNLOCK(priv); 222 return (err); 223 } 224 225 static int 226 mlx5e_prio_to_tc_handler(SYSCTL_HANDLER_ARGS) 227 { 228 struct mlx5e_priv *priv = arg1; 229 int prio_index = arg2; 230 struct mlx5_core_dev *mdev = priv->mdev; 231 int err; 232 uint8_t result = priv->params_ethtool.prio_tc[prio_index]; 233 234 PRIV_LOCK(priv); 235 err = sysctl_handle_8(oidp, &result, 0, req); 236 if (err || !req->newptr || 237 result == priv->params_ethtool.prio_tc[prio_index]) 238 goto done; 239 240 if (result > mlx5_max_tc(mdev)) { 241 err = ERANGE; 242 goto done; 243 } 244 245 err = -mlx5_set_port_prio_tc(mdev, prio_index, result); 246 if (err) 247 goto done; 248 249 priv->params_ethtool.prio_tc[prio_index] = result; 250 251 done: 252 PRIV_UNLOCK(priv); 253 return (err); 254 } 255 256 static int 257 mlx5e_trust_state_handler(SYSCTL_HANDLER_ARGS) 258 { 259 struct mlx5e_priv *priv = arg1; 260 struct mlx5_core_dev *mdev = priv->mdev; 261 int err; 262 u8 result; 263 264 PRIV_LOCK(priv); 265 result = priv->params_ethtool.trust_state; 266 err = sysctl_handle_8(oidp, &result, 0, req); 267 if (err || !req->newptr || 268 result == priv->params_ethtool.trust_state) 269 goto done; 270 271 switch (result) { 272 case MLX5_QPTS_TRUST_PCP: 273 case MLX5_QPTS_TRUST_DSCP: 274 break; 275 case MLX5_QPTS_TRUST_BOTH: 276 if (!MLX5_CAP_QCAM_FEATURE(mdev, qpts_trust_both)) { 277 err = EOPNOTSUPP; 278 goto done; 279 } 280 break; 281 default: 282 err = ERANGE; 283 goto done; 284 } 285 286 err = -mlx5_set_trust_state(mdev, result); 287 if (err) 288 goto done; 289 290 priv->params_ethtool.trust_state = result; 291 done: 292 PRIV_UNLOCK(priv); 293 return (err); 294 } 295 296 static int 297 mlx5e_dscp_prio_handler(SYSCTL_HANDLER_ARGS) 298 { 299 struct mlx5e_priv *priv = arg1; 300 int prio_index = arg2; 301 struct mlx5_core_dev *mdev = priv->mdev; 302 uint8_t dscp2prio[MLX5_MAX_SUPPORTED_DSCP]; 303 uint8_t x; 304 int err; 305 306 PRIV_LOCK(priv); 307 err = SYSCTL_OUT(req, priv->params_ethtool.dscp2prio + prio_index, 308 sizeof(priv->params_ethtool.dscp2prio) / 8); 309 if (err || !req->newptr) 310 goto done; 311 312 memcpy(dscp2prio, priv->params_ethtool.dscp2prio, sizeof(dscp2prio)); 313 err = SYSCTL_IN(req, dscp2prio + prio_index, sizeof(dscp2prio) / 8); 314 if (err) 315 goto done; 316 for (x = 0; x != MLX5_MAX_SUPPORTED_DSCP; x++) { 317 if (dscp2prio[x] > 7) { 318 err = ERANGE; 319 goto done; 320 } 321 } 322 err = -mlx5_set_dscp2prio(mdev, dscp2prio); 323 if (err) 324 goto done; 325 326 /* update local array */ 327 memcpy(priv->params_ethtool.dscp2prio, dscp2prio, 328 sizeof(priv->params_ethtool.dscp2prio)); 329 done: 330 PRIV_UNLOCK(priv); 331 return (err); 332 } 333 334 #define MLX5_PARAM_OFFSET(n) \ 335 __offsetof(struct mlx5e_priv, params_ethtool.n) 336 337 static int 338 mlx5e_ethtool_handler(SYSCTL_HANDLER_ARGS) 339 { 340 struct mlx5e_priv *priv = arg1; 341 uint64_t value; 342 int mode_modify; 343 int was_opened; 344 int error; 345 346 PRIV_LOCK(priv); 347 value = priv->params_ethtool.arg[arg2]; 348 if (req != NULL) { 349 error = sysctl_handle_64(oidp, &value, 0, req); 350 if (error || req->newptr == NULL || 351 value == priv->params_ethtool.arg[arg2]) 352 goto done; 353 354 /* assign new value */ 355 priv->params_ethtool.arg[arg2] = value; 356 } else { 357 error = 0; 358 } 359 /* check if device is gone */ 360 if (priv->gone) { 361 error = ENXIO; 362 goto done; 363 } 364 was_opened = test_bit(MLX5E_STATE_OPENED, &priv->state); 365 mode_modify = MLX5_CAP_GEN(priv->mdev, cq_period_mode_modify); 366 367 switch (MLX5_PARAM_OFFSET(arg[arg2])) { 368 case MLX5_PARAM_OFFSET(rx_coalesce_usecs): 369 /* import RX coal time */ 370 if (priv->params_ethtool.rx_coalesce_usecs < 1) 371 priv->params_ethtool.rx_coalesce_usecs = 0; 372 else if (priv->params_ethtool.rx_coalesce_usecs > 373 MLX5E_FLD_MAX(cqc, cq_period)) { 374 priv->params_ethtool.rx_coalesce_usecs = 375 MLX5E_FLD_MAX(cqc, cq_period); 376 } 377 priv->params.rx_cq_moderation_usec = 378 priv->params_ethtool.rx_coalesce_usecs; 379 380 /* check to avoid down and up the network interface */ 381 if (was_opened) 382 error = mlx5e_refresh_channel_params(priv); 383 break; 384 385 case MLX5_PARAM_OFFSET(rx_coalesce_pkts): 386 /* import RX coal pkts */ 387 if (priv->params_ethtool.rx_coalesce_pkts < 1) 388 priv->params_ethtool.rx_coalesce_pkts = 0; 389 else if (priv->params_ethtool.rx_coalesce_pkts > 390 MLX5E_FLD_MAX(cqc, cq_max_count)) { 391 priv->params_ethtool.rx_coalesce_pkts = 392 MLX5E_FLD_MAX(cqc, cq_max_count); 393 } 394 priv->params.rx_cq_moderation_pkts = 395 priv->params_ethtool.rx_coalesce_pkts; 396 397 /* check to avoid down and up the network interface */ 398 if (was_opened) 399 error = mlx5e_refresh_channel_params(priv); 400 break; 401 402 case MLX5_PARAM_OFFSET(tx_coalesce_usecs): 403 /* import TX coal time */ 404 if (priv->params_ethtool.tx_coalesce_usecs < 1) 405 priv->params_ethtool.tx_coalesce_usecs = 0; 406 else if (priv->params_ethtool.tx_coalesce_usecs > 407 MLX5E_FLD_MAX(cqc, cq_period)) { 408 priv->params_ethtool.tx_coalesce_usecs = 409 MLX5E_FLD_MAX(cqc, cq_period); 410 } 411 priv->params.tx_cq_moderation_usec = 412 priv->params_ethtool.tx_coalesce_usecs; 413 414 /* check to avoid down and up the network interface */ 415 if (was_opened) 416 error = mlx5e_refresh_channel_params(priv); 417 break; 418 419 case MLX5_PARAM_OFFSET(tx_coalesce_pkts): 420 /* import TX coal pkts */ 421 if (priv->params_ethtool.tx_coalesce_pkts < 1) 422 priv->params_ethtool.tx_coalesce_pkts = 0; 423 else if (priv->params_ethtool.tx_coalesce_pkts > 424 MLX5E_FLD_MAX(cqc, cq_max_count)) { 425 priv->params_ethtool.tx_coalesce_pkts = 426 MLX5E_FLD_MAX(cqc, cq_max_count); 427 } 428 priv->params.tx_cq_moderation_pkts = 429 priv->params_ethtool.tx_coalesce_pkts; 430 431 /* check to avoid down and up the network interface */ 432 if (was_opened) 433 error = mlx5e_refresh_channel_params(priv); 434 break; 435 436 case MLX5_PARAM_OFFSET(tx_queue_size): 437 /* network interface must be down */ 438 if (was_opened) 439 mlx5e_close_locked(priv->ifp); 440 441 /* import TX queue size */ 442 if (priv->params_ethtool.tx_queue_size < 443 (1 << MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE)) { 444 priv->params_ethtool.tx_queue_size = 445 (1 << MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE); 446 } else if (priv->params_ethtool.tx_queue_size > 447 priv->params_ethtool.tx_queue_size_max) { 448 priv->params_ethtool.tx_queue_size = 449 priv->params_ethtool.tx_queue_size_max; 450 } 451 /* store actual TX queue size */ 452 priv->params.log_sq_size = 453 order_base_2(priv->params_ethtool.tx_queue_size); 454 priv->params_ethtool.tx_queue_size = 455 1 << priv->params.log_sq_size; 456 457 /* verify TX completion factor */ 458 mlx5e_ethtool_sync_tx_completion_fact(priv); 459 460 /* restart network interface, if any */ 461 if (was_opened) 462 mlx5e_open_locked(priv->ifp); 463 break; 464 465 case MLX5_PARAM_OFFSET(rx_queue_size): 466 /* network interface must be down */ 467 if (was_opened) 468 mlx5e_close_locked(priv->ifp); 469 470 /* import RX queue size */ 471 if (priv->params_ethtool.rx_queue_size < 472 (1 << MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE)) { 473 priv->params_ethtool.rx_queue_size = 474 (1 << MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE); 475 } else if (priv->params_ethtool.rx_queue_size > 476 priv->params_ethtool.rx_queue_size_max) { 477 priv->params_ethtool.rx_queue_size = 478 priv->params_ethtool.rx_queue_size_max; 479 } 480 /* store actual RX queue size */ 481 priv->params.log_rq_size = 482 order_base_2(priv->params_ethtool.rx_queue_size); 483 priv->params_ethtool.rx_queue_size = 484 1 << priv->params.log_rq_size; 485 486 /* update least number of RX WQEs */ 487 priv->params.min_rx_wqes = min( 488 priv->params_ethtool.rx_queue_size - 1, 489 MLX5E_PARAMS_DEFAULT_MIN_RX_WQES); 490 491 /* restart network interface, if any */ 492 if (was_opened) 493 mlx5e_open_locked(priv->ifp); 494 break; 495 496 case MLX5_PARAM_OFFSET(channels): 497 /* network interface must be down */ 498 if (was_opened) 499 mlx5e_close_locked(priv->ifp); 500 501 /* import number of channels */ 502 if (priv->params_ethtool.channels < 1) 503 priv->params_ethtool.channels = 1; 504 else if (priv->params_ethtool.channels > 505 (u64) priv->mdev->priv.eq_table.num_comp_vectors) { 506 priv->params_ethtool.channels = 507 (u64) priv->mdev->priv.eq_table.num_comp_vectors; 508 } 509 priv->params.num_channels = priv->params_ethtool.channels; 510 511 /* restart network interface, if any */ 512 if (was_opened) 513 mlx5e_open_locked(priv->ifp); 514 break; 515 516 case MLX5_PARAM_OFFSET(rx_coalesce_mode): 517 /* network interface must be down */ 518 if (was_opened != 0 && mode_modify == 0) 519 mlx5e_close_locked(priv->ifp); 520 521 /* import RX coalesce mode */ 522 if (priv->params_ethtool.rx_coalesce_mode != 0) 523 priv->params_ethtool.rx_coalesce_mode = 1; 524 priv->params.rx_cq_moderation_mode = 525 priv->params_ethtool.rx_coalesce_mode; 526 527 /* restart network interface, if any */ 528 if (was_opened != 0) { 529 if (mode_modify == 0) 530 mlx5e_open_locked(priv->ifp); 531 else 532 error = mlx5e_refresh_channel_params(priv); 533 } 534 break; 535 536 case MLX5_PARAM_OFFSET(tx_coalesce_mode): 537 /* network interface must be down */ 538 if (was_opened != 0 && mode_modify == 0) 539 mlx5e_close_locked(priv->ifp); 540 541 /* import TX coalesce mode */ 542 if (priv->params_ethtool.tx_coalesce_mode != 0) 543 priv->params_ethtool.tx_coalesce_mode = 1; 544 priv->params.tx_cq_moderation_mode = 545 priv->params_ethtool.tx_coalesce_mode; 546 547 /* restart network interface, if any */ 548 if (was_opened != 0) { 549 if (mode_modify == 0) 550 mlx5e_open_locked(priv->ifp); 551 else 552 error = mlx5e_refresh_channel_params(priv); 553 } 554 break; 555 556 case MLX5_PARAM_OFFSET(hw_lro): 557 /* network interface must be down */ 558 if (was_opened) 559 mlx5e_close_locked(priv->ifp); 560 561 /* import HW LRO mode */ 562 if (priv->params_ethtool.hw_lro != 0) { 563 if ((priv->ifp->if_capenable & IFCAP_LRO) && 564 MLX5_CAP_ETH(priv->mdev, lro_cap)) { 565 priv->params.hw_lro_en = 1; 566 priv->params_ethtool.hw_lro = 1; 567 } else { 568 priv->params.hw_lro_en = 0; 569 priv->params_ethtool.hw_lro = 0; 570 error = EINVAL; 571 572 if_printf(priv->ifp, "Can't enable HW LRO: " 573 "The HW or SW LRO feature is disabled\n"); 574 } 575 } else { 576 priv->params.hw_lro_en = 0; 577 } 578 /* restart network interface, if any */ 579 if (was_opened) 580 mlx5e_open_locked(priv->ifp); 581 break; 582 583 case MLX5_PARAM_OFFSET(cqe_zipping): 584 /* network interface must be down */ 585 if (was_opened) 586 mlx5e_close_locked(priv->ifp); 587 588 /* import CQE zipping mode */ 589 if (priv->params_ethtool.cqe_zipping && 590 MLX5_CAP_GEN(priv->mdev, cqe_compression)) { 591 priv->params.cqe_zipping_en = true; 592 priv->params_ethtool.cqe_zipping = 1; 593 } else { 594 priv->params.cqe_zipping_en = false; 595 priv->params_ethtool.cqe_zipping = 0; 596 } 597 /* restart network interface, if any */ 598 if (was_opened) 599 mlx5e_open_locked(priv->ifp); 600 break; 601 602 case MLX5_PARAM_OFFSET(tx_bufring_disable): 603 /* rangecheck input value */ 604 priv->params_ethtool.tx_bufring_disable = 605 priv->params_ethtool.tx_bufring_disable ? 1 : 0; 606 607 /* reconfigure the sendqueues, if any */ 608 if (was_opened) { 609 mlx5e_close_locked(priv->ifp); 610 mlx5e_open_locked(priv->ifp); 611 } 612 break; 613 614 case MLX5_PARAM_OFFSET(tx_completion_fact): 615 /* network interface must be down */ 616 if (was_opened) 617 mlx5e_close_locked(priv->ifp); 618 619 /* verify parameter */ 620 mlx5e_ethtool_sync_tx_completion_fact(priv); 621 622 /* restart network interface, if any */ 623 if (was_opened) 624 mlx5e_open_locked(priv->ifp); 625 break; 626 627 case MLX5_PARAM_OFFSET(modify_tx_dma): 628 /* check if network interface is opened */ 629 if (was_opened) { 630 priv->params_ethtool.modify_tx_dma = 631 priv->params_ethtool.modify_tx_dma ? 1 : 0; 632 /* modify tx according to value */ 633 mlx5e_modify_tx_dma(priv, value != 0); 634 } else { 635 /* if closed force enable tx */ 636 priv->params_ethtool.modify_tx_dma = 0; 637 } 638 break; 639 640 case MLX5_PARAM_OFFSET(modify_rx_dma): 641 /* check if network interface is opened */ 642 if (was_opened) { 643 priv->params_ethtool.modify_rx_dma = 644 priv->params_ethtool.modify_rx_dma ? 1 : 0; 645 /* modify rx according to value */ 646 mlx5e_modify_rx_dma(priv, value != 0); 647 } else { 648 /* if closed force enable rx */ 649 priv->params_ethtool.modify_rx_dma = 0; 650 } 651 break; 652 653 case MLX5_PARAM_OFFSET(diag_pci_enable): 654 priv->params_ethtool.diag_pci_enable = 655 priv->params_ethtool.diag_pci_enable ? 1 : 0; 656 657 error = -mlx5_core_set_diagnostics_full(priv->mdev, 658 priv->params_ethtool.diag_pci_enable, 659 priv->params_ethtool.diag_general_enable); 660 break; 661 662 case MLX5_PARAM_OFFSET(diag_general_enable): 663 priv->params_ethtool.diag_general_enable = 664 priv->params_ethtool.diag_general_enable ? 1 : 0; 665 666 error = -mlx5_core_set_diagnostics_full(priv->mdev, 667 priv->params_ethtool.diag_pci_enable, 668 priv->params_ethtool.diag_general_enable); 669 break; 670 671 case MLX5_PARAM_OFFSET(mc_local_lb): 672 priv->params_ethtool.mc_local_lb = 673 priv->params_ethtool.mc_local_lb ? 1 : 0; 674 675 if (MLX5_CAP_GEN(priv->mdev, disable_local_lb)) { 676 error = mlx5_nic_vport_modify_local_lb(priv->mdev, 677 MLX5_LOCAL_MC_LB, priv->params_ethtool.mc_local_lb); 678 } else { 679 error = EOPNOTSUPP; 680 } 681 break; 682 683 case MLX5_PARAM_OFFSET(uc_local_lb): 684 priv->params_ethtool.uc_local_lb = 685 priv->params_ethtool.uc_local_lb ? 1 : 0; 686 687 if (MLX5_CAP_GEN(priv->mdev, disable_local_lb)) { 688 error = mlx5_nic_vport_modify_local_lb(priv->mdev, 689 MLX5_LOCAL_UC_LB, priv->params_ethtool.uc_local_lb); 690 } else { 691 error = EOPNOTSUPP; 692 } 693 break; 694 695 default: 696 break; 697 } 698 done: 699 PRIV_UNLOCK(priv); 700 return (error); 701 } 702 703 /* 704 * Read the first three bytes of the eeprom in order to get the needed info 705 * for the whole reading. 706 * Byte 0 - Identifier byte 707 * Byte 1 - Revision byte 708 * Byte 2 - Status byte 709 */ 710 static int 711 mlx5e_get_eeprom_info(struct mlx5e_priv *priv, struct mlx5e_eeprom *eeprom) 712 { 713 struct mlx5_core_dev *dev = priv->mdev; 714 u32 data = 0; 715 int size_read = 0; 716 int ret; 717 718 ret = mlx5_query_module_num(dev, &eeprom->module_num); 719 if (ret) { 720 if_printf(priv->ifp, "%s:%d: Failed query module error=%d\n", 721 __func__, __LINE__, ret); 722 return (ret); 723 } 724 725 /* Read the first three bytes to get Identifier, Revision and Status */ 726 ret = mlx5_query_eeprom(dev, eeprom->i2c_addr, eeprom->page_num, 727 eeprom->device_addr, MLX5E_EEPROM_INFO_BYTES, eeprom->module_num, &data, 728 &size_read); 729 if (ret) { 730 if_printf(priv->ifp, "%s:%d: Failed query eeprom module error=0x%x\n", 731 __func__, __LINE__, ret); 732 return (ret); 733 } 734 735 switch (data & MLX5_EEPROM_IDENTIFIER_BYTE_MASK) { 736 case SFF_8024_ID_QSFP: 737 eeprom->type = MLX5E_ETH_MODULE_SFF_8436; 738 eeprom->len = MLX5E_ETH_MODULE_SFF_8436_LEN; 739 break; 740 case SFF_8024_ID_QSFPPLUS: 741 case SFF_8024_ID_QSFP28: 742 if ((data & MLX5_EEPROM_IDENTIFIER_BYTE_MASK) == SFF_8024_ID_QSFP28 || 743 ((data & MLX5_EEPROM_REVISION_ID_BYTE_MASK) >> 8) >= 0x3) { 744 eeprom->type = MLX5E_ETH_MODULE_SFF_8636; 745 eeprom->len = MLX5E_ETH_MODULE_SFF_8636_LEN; 746 } else { 747 eeprom->type = MLX5E_ETH_MODULE_SFF_8436; 748 eeprom->len = MLX5E_ETH_MODULE_SFF_8436_LEN; 749 } 750 if ((data & MLX5_EEPROM_PAGE_3_VALID_BIT_MASK) == 0) 751 eeprom->page_valid = 1; 752 break; 753 case SFF_8024_ID_SFP: 754 eeprom->type = MLX5E_ETH_MODULE_SFF_8472; 755 eeprom->len = MLX5E_ETH_MODULE_SFF_8472_LEN; 756 break; 757 default: 758 if_printf(priv->ifp, "%s:%d: Not recognized cable type = 0x%x(%s)\n", 759 __func__, __LINE__, data & MLX5_EEPROM_IDENTIFIER_BYTE_MASK, 760 sff_8024_id[data & MLX5_EEPROM_IDENTIFIER_BYTE_MASK]); 761 return (EINVAL); 762 } 763 return (0); 764 } 765 766 /* Read both low and high pages of the eeprom */ 767 static int 768 mlx5e_get_eeprom(struct mlx5e_priv *priv, struct mlx5e_eeprom *ee) 769 { 770 struct mlx5_core_dev *dev = priv->mdev; 771 int size_read = 0; 772 int ret; 773 774 if (ee->len == 0) 775 return (EINVAL); 776 777 /* Read low page of the eeprom */ 778 while (ee->device_addr < ee->len) { 779 ret = mlx5_query_eeprom(dev, ee->i2c_addr, ee->page_num, ee->device_addr, 780 ee->len - ee->device_addr, ee->module_num, 781 ee->data + (ee->device_addr / 4), &size_read); 782 if (ret) { 783 if_printf(priv->ifp, "%s:%d: Failed reading eeprom, " 784 "error = 0x%02x\n", __func__, __LINE__, ret); 785 return (ret); 786 } 787 ee->device_addr += size_read; 788 } 789 790 /* Read high page of the eeprom */ 791 if (ee->page_valid) { 792 ee->device_addr = MLX5E_EEPROM_HIGH_PAGE_OFFSET; 793 ee->page_num = MLX5E_EEPROM_HIGH_PAGE; 794 size_read = 0; 795 while (ee->device_addr < MLX5E_EEPROM_PAGE_LENGTH) { 796 ret = mlx5_query_eeprom(dev, ee->i2c_addr, ee->page_num, 797 ee->device_addr, MLX5E_EEPROM_PAGE_LENGTH - ee->device_addr, 798 ee->module_num, ee->data + (ee->len / 4) + 799 ((ee->device_addr - MLX5E_EEPROM_HIGH_PAGE_OFFSET) / 4), 800 &size_read); 801 if (ret) { 802 if_printf(priv->ifp, "%s:%d: Failed reading eeprom, " 803 "error = 0x%02x\n", __func__, __LINE__, ret); 804 return (ret); 805 } 806 ee->device_addr += size_read; 807 } 808 } 809 return (0); 810 } 811 812 static void 813 mlx5e_print_eeprom(struct mlx5e_eeprom *eeprom) 814 { 815 int row; 816 int index_in_row; 817 int byte_to_write = 0; 818 int line_length = 16; 819 820 printf("\nOffset\t\tValues\n"); 821 printf("------\t\t------"); 822 while (byte_to_write < eeprom->len) { 823 printf("\n0x%04X\t\t", byte_to_write); 824 for (index_in_row = 0; index_in_row < line_length; index_in_row++) { 825 printf("%02X ", ((u8 *)eeprom->data)[byte_to_write]); 826 byte_to_write++; 827 } 828 } 829 830 if (eeprom->page_valid) { 831 row = MLX5E_EEPROM_HIGH_PAGE_OFFSET; 832 printf("\n\nUpper Page 0x03\n"); 833 printf("\nOffset\t\tValues\n"); 834 printf("------\t\t------"); 835 while (row < MLX5E_EEPROM_PAGE_LENGTH) { 836 printf("\n0x%04X\t\t", row); 837 for (index_in_row = 0; index_in_row < line_length; index_in_row++) { 838 printf("%02X ", ((u8 *)eeprom->data)[byte_to_write]); 839 byte_to_write++; 840 row++; 841 } 842 } 843 } 844 } 845 846 /* 847 * Read cable EEPROM module information by first inspecting the first 848 * three bytes to get the initial information for a whole reading. 849 * Information will be printed to dmesg. 850 */ 851 static int 852 mlx5e_read_eeprom(SYSCTL_HANDLER_ARGS) 853 { 854 struct mlx5e_priv *priv = arg1; 855 struct mlx5e_eeprom eeprom; 856 int error; 857 int result = 0; 858 859 PRIV_LOCK(priv); 860 error = sysctl_handle_int(oidp, &result, 0, req); 861 if (error || !req->newptr) 862 goto done; 863 864 /* Check if device is gone */ 865 if (priv->gone) { 866 error = ENXIO; 867 goto done; 868 } 869 870 if (result == 1) { 871 eeprom.i2c_addr = MLX5E_I2C_ADDR_LOW; 872 eeprom.device_addr = 0; 873 eeprom.page_num = MLX5E_EEPROM_LOW_PAGE; 874 eeprom.page_valid = 0; 875 876 /* Read three first bytes to get important info */ 877 error = mlx5e_get_eeprom_info(priv, &eeprom); 878 if (error) { 879 if_printf(priv->ifp, "%s:%d: Failed reading eeprom's " 880 "initial information\n", __func__, __LINE__); 881 error = 0; 882 goto done; 883 } 884 /* 885 * Allocate needed length buffer and additional space for 886 * page 0x03 887 */ 888 eeprom.data = malloc(eeprom.len + MLX5E_EEPROM_PAGE_LENGTH, 889 M_MLX5EN, M_WAITOK | M_ZERO); 890 891 /* Read the whole eeprom information */ 892 error = mlx5e_get_eeprom(priv, &eeprom); 893 if (error) { 894 if_printf(priv->ifp, "%s:%d: Failed reading eeprom\n", 895 __func__, __LINE__); 896 error = 0; 897 /* 898 * Continue printing partial information in case of 899 * an error 900 */ 901 } 902 mlx5e_print_eeprom(&eeprom); 903 free(eeprom.data, M_MLX5EN); 904 } 905 done: 906 PRIV_UNLOCK(priv); 907 return (error); 908 } 909 910 static const char *mlx5e_params_desc[] = { 911 MLX5E_PARAMS(MLX5E_STATS_DESC) 912 }; 913 914 static const char *mlx5e_port_stats_debug_desc[] = { 915 MLX5E_PORT_STATS_DEBUG(MLX5E_STATS_DESC) 916 }; 917 918 static int 919 mlx5e_ethtool_debug_channel_info(SYSCTL_HANDLER_ARGS) 920 { 921 struct mlx5e_priv *priv; 922 struct sbuf sb; 923 struct mlx5e_channel *c; 924 struct mlx5e_sq *sq; 925 struct mlx5e_rq *rq; 926 int error, i, tc; 927 928 priv = arg1; 929 error = sysctl_wire_old_buffer(req, 0); 930 if (error != 0) 931 return (error); 932 if (sbuf_new_for_sysctl(&sb, NULL, 128, req) == NULL) 933 return (ENOMEM); 934 sbuf_clear_flags(&sb, SBUF_INCLUDENUL); 935 936 PRIV_LOCK(priv); 937 if (test_bit(MLX5E_STATE_OPENED, &priv->state) == 0) 938 goto out; 939 for (i = 0; i < priv->params.num_channels; i++) { 940 c = priv->channel[i]; 941 rq = &c->rq; 942 sbuf_printf(&sb, "channel %d rq %d cq %d\n", 943 c->ix, rq->rqn, rq->cq.mcq.cqn); 944 for (tc = 0; tc < c->num_tc; tc++) { 945 sq = &c->sq[tc]; 946 sbuf_printf(&sb, "channel %d tc %d sq %d cq %d\n", 947 c->ix, tc, sq->sqn, sq->cq.mcq.cqn); 948 } 949 } 950 out: 951 PRIV_UNLOCK(priv); 952 error = sbuf_finish(&sb); 953 sbuf_delete(&sb); 954 return (error); 955 } 956 957 static int 958 mlx5e_ethtool_debug_stats(SYSCTL_HANDLER_ARGS) 959 { 960 struct mlx5e_priv *priv = arg1; 961 int error, sys_debug; 962 963 sys_debug = priv->sysctl_debug; 964 error = sysctl_handle_int(oidp, &priv->sysctl_debug, 0, req); 965 if (error != 0 || !req->newptr) 966 return (error); 967 priv->sysctl_debug = priv->sysctl_debug != 0; 968 if (sys_debug == priv->sysctl_debug) 969 return (0); 970 971 PRIV_LOCK(priv); 972 if (priv->sysctl_debug) { 973 mlx5e_create_stats(&priv->stats.port_stats_debug.ctx, 974 SYSCTL_CHILDREN(priv->sysctl_ifnet), "debug_stats", 975 mlx5e_port_stats_debug_desc, MLX5E_PORT_STATS_DEBUG_NUM, 976 priv->stats.port_stats_debug.arg); 977 SYSCTL_ADD_PROC(&priv->sysctl_ctx_channel_debug, 978 SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO, 979 "hw_ctx_debug", 980 CTLFLAG_RD | CTLFLAG_MPSAFE | CTLTYPE_STRING, priv, 0, 981 mlx5e_ethtool_debug_channel_info, "S", ""); 982 } else { 983 sysctl_ctx_free(&priv->stats.port_stats_debug.ctx); 984 sysctl_ctx_free(&priv->sysctl_ctx_channel_debug); 985 } 986 PRIV_UNLOCK(priv); 987 return (0); 988 } 989 990 static void 991 mlx5e_create_diagnostics(struct mlx5e_priv *priv) 992 { 993 struct mlx5_core_diagnostics_entry entry; 994 struct sysctl_ctx_list *ctx; 995 struct sysctl_oid *node; 996 int x; 997 998 /* sysctl context we are using */ 999 ctx = &priv->sysctl_ctx; 1000 1001 /* create root node */ 1002 node = SYSCTL_ADD_NODE(ctx, 1003 SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO, 1004 "diagnostics", CTLFLAG_RD, NULL, "Diagnostics"); 1005 if (node == NULL) 1006 return; 1007 1008 /* create PCI diagnostics */ 1009 for (x = 0; x != MLX5_CORE_PCI_DIAGNOSTICS_NUM; x++) { 1010 entry = mlx5_core_pci_diagnostics_table[x]; 1011 if (mlx5_core_supports_diagnostics(priv->mdev, entry.counter_id) == 0) 1012 continue; 1013 SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO, 1014 entry.desc, CTLFLAG_RD, priv->params_pci.array + x, 1015 "PCI diagnostics counter"); 1016 } 1017 1018 /* create general diagnostics */ 1019 for (x = 0; x != MLX5_CORE_GENERAL_DIAGNOSTICS_NUM; x++) { 1020 entry = mlx5_core_general_diagnostics_table[x]; 1021 if (mlx5_core_supports_diagnostics(priv->mdev, entry.counter_id) == 0) 1022 continue; 1023 SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO, 1024 entry.desc, CTLFLAG_RD, priv->params_general.array + x, 1025 "General diagnostics counter"); 1026 } 1027 } 1028 1029 void 1030 mlx5e_create_ethtool(struct mlx5e_priv *priv) 1031 { 1032 struct mlx5_core_dev *mdev = priv->mdev; 1033 struct sysctl_oid *node, *qos_node; 1034 const char *pnameunit; 1035 unsigned x; 1036 int i; 1037 1038 /* set some defaults */ 1039 priv->params_ethtool.tx_queue_size_max = 1 << MLX5E_PARAMS_MAXIMUM_LOG_SQ_SIZE; 1040 priv->params_ethtool.rx_queue_size_max = 1 << MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE; 1041 priv->params_ethtool.tx_queue_size = 1 << priv->params.log_sq_size; 1042 priv->params_ethtool.rx_queue_size = 1 << priv->params.log_rq_size; 1043 priv->params_ethtool.channels = priv->params.num_channels; 1044 priv->params_ethtool.coalesce_pkts_max = MLX5E_FLD_MAX(cqc, cq_max_count); 1045 priv->params_ethtool.coalesce_usecs_max = MLX5E_FLD_MAX(cqc, cq_period); 1046 priv->params_ethtool.rx_coalesce_mode = priv->params.rx_cq_moderation_mode; 1047 priv->params_ethtool.rx_coalesce_usecs = priv->params.rx_cq_moderation_usec; 1048 priv->params_ethtool.rx_coalesce_pkts = priv->params.rx_cq_moderation_pkts; 1049 priv->params_ethtool.tx_coalesce_mode = priv->params.tx_cq_moderation_mode; 1050 priv->params_ethtool.tx_coalesce_usecs = priv->params.tx_cq_moderation_usec; 1051 priv->params_ethtool.tx_coalesce_pkts = priv->params.tx_cq_moderation_pkts; 1052 priv->params_ethtool.hw_lro = priv->params.hw_lro_en; 1053 priv->params_ethtool.cqe_zipping = priv->params.cqe_zipping_en; 1054 mlx5e_ethtool_sync_tx_completion_fact(priv); 1055 1056 /* get default values for local loopback, if any */ 1057 if (MLX5_CAP_GEN(priv->mdev, disable_local_lb)) { 1058 int err; 1059 u8 val; 1060 1061 err = mlx5_nic_vport_query_local_lb(priv->mdev, MLX5_LOCAL_MC_LB, &val); 1062 if (err == 0) 1063 priv->params_ethtool.mc_local_lb = val; 1064 1065 err = mlx5_nic_vport_query_local_lb(priv->mdev, MLX5_LOCAL_UC_LB, &val); 1066 if (err == 0) 1067 priv->params_ethtool.uc_local_lb = val; 1068 } 1069 1070 /* create root node */ 1071 node = SYSCTL_ADD_NODE(&priv->sysctl_ctx, 1072 SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO, 1073 "conf", CTLFLAG_RW, NULL, "Configuration"); 1074 if (node == NULL) 1075 return; 1076 for (x = 0; x != MLX5E_PARAMS_NUM; x++) { 1077 /* check for read-only parameter */ 1078 if (strstr(mlx5e_params_desc[2 * x], "_max") != NULL || 1079 strstr(mlx5e_params_desc[2 * x], "_mtu") != NULL) { 1080 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO, 1081 mlx5e_params_desc[2 * x], CTLTYPE_U64 | CTLFLAG_RD | 1082 CTLFLAG_MPSAFE, priv, x, &mlx5e_ethtool_handler, "QU", 1083 mlx5e_params_desc[2 * x + 1]); 1084 } else { 1085 #if (__FreeBSD_version < 1100000) 1086 char path[64]; 1087 #endif 1088 /* 1089 * NOTE: In FreeBSD-11 and newer the 1090 * CTLFLAG_RWTUN flag will take care of 1091 * loading default sysctl value from the 1092 * kernel environment, if any: 1093 */ 1094 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO, 1095 mlx5e_params_desc[2 * x], CTLTYPE_U64 | CTLFLAG_RWTUN | 1096 CTLFLAG_MPSAFE, priv, x, &mlx5e_ethtool_handler, "QU", 1097 mlx5e_params_desc[2 * x + 1]); 1098 1099 #if (__FreeBSD_version < 1100000) 1100 /* compute path for sysctl */ 1101 snprintf(path, sizeof(path), "dev.mce.%d.conf.%s", 1102 device_get_unit(priv->mdev->pdev->dev.bsddev), 1103 mlx5e_params_desc[2 * x]); 1104 1105 /* try to fetch tunable, if any */ 1106 if (TUNABLE_QUAD_FETCH(path, &priv->params_ethtool.arg[x])) 1107 mlx5e_ethtool_handler(NULL, priv, x, NULL); 1108 #endif 1109 } 1110 } 1111 1112 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO, 1113 "debug_stats", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 1114 0, &mlx5e_ethtool_debug_stats, "I", "Extended debug statistics"); 1115 1116 pnameunit = device_get_nameunit(priv->mdev->pdev->dev.bsddev); 1117 1118 SYSCTL_ADD_STRING(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), 1119 OID_AUTO, "device_name", CTLFLAG_RD, 1120 __DECONST(void *, pnameunit), 0, 1121 "PCI device name"); 1122 1123 /* EEPROM support */ 1124 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO, "eeprom_info", 1125 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 0, 1126 mlx5e_read_eeprom, "I", "EEPROM information"); 1127 1128 /* Diagnostics support */ 1129 mlx5e_create_diagnostics(priv); 1130 1131 /* create qos node */ 1132 qos_node = SYSCTL_ADD_NODE(&priv->sysctl_ctx, 1133 SYSCTL_CHILDREN(node), OID_AUTO, 1134 "qos", CTLFLAG_RW, NULL, "Quality Of Service configuration"); 1135 if (node == NULL) 1136 return; 1137 1138 /* Prioriry rate limit support */ 1139 if (mlx5e_getmaxrate(priv)) 1140 return; 1141 1142 for (i = 0; i <= mlx5_max_tc(mdev); i++) { 1143 char name[32]; 1144 snprintf(name, sizeof(name), "tc_%d_max_rate", i); 1145 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1146 OID_AUTO, name, CTLTYPE_U64 | CTLFLAG_RW | CTLFLAG_MPSAFE, 1147 priv, i, mlx5e_tc_maxrate_handler, "QU", 1148 "Max rate for priority, specified in kilobits, where kilo=1000, \ 1149 max_rate must be divisible by 100000"); 1150 } 1151 1152 if (mlx5e_get_prio_tc(priv)) 1153 return; 1154 1155 for (i = 0; i <= mlx5_max_tc(mdev); i++) { 1156 char name[32]; 1157 snprintf(name, sizeof(name), "prio_%d_to_tc", i); 1158 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1159 OID_AUTO, name, CTLTYPE_U8 | CTLFLAG_RW | CTLFLAG_MPSAFE, 1160 priv, i, mlx5e_prio_to_tc_handler, "CU", 1161 "Set priority to traffic class"); 1162 } 1163 1164 /* DSCP support */ 1165 if (mlx5e_get_dscp(priv) == 0) { 1166 for (i = 0; i != MLX5_MAX_SUPPORTED_DSCP; i += 8) { 1167 char name[32]; 1168 snprintf(name, sizeof(name), "dscp_%d_%d_prio", i, i + 7); 1169 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1170 OID_AUTO, name, CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1171 priv, i, mlx5e_dscp_prio_handler, "CU", 1172 "Set DSCP to priority mapping, 0..7"); 1173 } 1174 #define A "Set trust state, 1:PCP 2:DSCP" 1175 #define B " 3:BOTH" 1176 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1177 OID_AUTO, "trust_state", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1178 priv, 0, mlx5e_trust_state_handler, "CU", 1179 MLX5_CAP_QCAM_FEATURE(mdev, qpts_trust_both) ? 1180 A B : A); 1181 #undef B 1182 #undef A 1183 } 1184 } 1185