1 /*- 2 * Copyright (c) 2015-2019 Mellanox Technologies. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS' AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 * 25 * $FreeBSD$ 26 */ 27 28 #include "en.h" 29 #include "port_buffer.h" 30 #include <net/sff8472.h> 31 32 void 33 mlx5e_create_stats(struct sysctl_ctx_list *ctx, 34 struct sysctl_oid_list *parent, const char *buffer, 35 const char **desc, unsigned num, u64 * arg) 36 { 37 struct sysctl_oid *node; 38 unsigned x; 39 40 sysctl_ctx_init(ctx); 41 42 node = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, 43 buffer, CTLFLAG_RD, NULL, "Statistics"); 44 if (node == NULL) 45 return; 46 for (x = 0; x != num; x++) { 47 SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO, 48 desc[2 * x], CTLFLAG_RD, arg + x, desc[2 * x + 1]); 49 } 50 } 51 52 static void 53 mlx5e_ethtool_sync_tx_completion_fact(struct mlx5e_priv *priv) 54 { 55 /* 56 * Limit the maximum distance between completion events to 57 * half of the currently set TX queue size. 58 * 59 * The maximum number of queue entries a single IP packet can 60 * consume is given by MLX5_SEND_WQE_MAX_WQEBBS. 61 * 62 * The worst case max value is then given as below: 63 */ 64 uint64_t max = priv->params_ethtool.tx_queue_size / 65 (2 * MLX5_SEND_WQE_MAX_WQEBBS); 66 67 /* 68 * Update the maximum completion factor value in case the 69 * tx_queue_size field changed. Ensure we don't overflow 70 * 16-bits. 71 */ 72 if (max < 1) 73 max = 1; 74 else if (max > 65535) 75 max = 65535; 76 priv->params_ethtool.tx_completion_fact_max = max; 77 78 /* 79 * Verify that the current TX completion factor is within the 80 * given limits: 81 */ 82 if (priv->params_ethtool.tx_completion_fact < 1) 83 priv->params_ethtool.tx_completion_fact = 1; 84 else if (priv->params_ethtool.tx_completion_fact > max) 85 priv->params_ethtool.tx_completion_fact = max; 86 } 87 88 static int 89 mlx5e_getmaxrate(struct mlx5e_priv *priv) 90 { 91 struct mlx5_core_dev *mdev = priv->mdev; 92 u8 max_bw_unit[IEEE_8021QAZ_MAX_TCS]; 93 u8 max_bw_value[IEEE_8021QAZ_MAX_TCS]; 94 int err; 95 int i; 96 97 PRIV_LOCK(priv); 98 err = -mlx5_query_port_tc_rate_limit(mdev, max_bw_value, max_bw_unit); 99 if (err) 100 goto done; 101 102 for (i = 0; i <= mlx5_max_tc(mdev); i++) { 103 switch (max_bw_unit[i]) { 104 case MLX5_100_MBPS_UNIT: 105 priv->params_ethtool.max_bw_value[i] = max_bw_value[i] * MLX5E_100MB; 106 break; 107 case MLX5_GBPS_UNIT: 108 priv->params_ethtool.max_bw_value[i] = max_bw_value[i] * MLX5E_1GB; 109 break; 110 case MLX5_BW_NO_LIMIT: 111 priv->params_ethtool.max_bw_value[i] = 0; 112 break; 113 default: 114 priv->params_ethtool.max_bw_value[i] = -1; 115 WARN_ONCE(true, "non-supported BW unit"); 116 break; 117 } 118 } 119 done: 120 PRIV_UNLOCK(priv); 121 return (err); 122 } 123 124 static int 125 mlx5e_get_max_alloc(struct mlx5e_priv *priv) 126 { 127 struct mlx5_core_dev *mdev = priv->mdev; 128 int err; 129 int x; 130 131 PRIV_LOCK(priv); 132 err = -mlx5_query_port_tc_bw_alloc(mdev, priv->params_ethtool.max_bw_share); 133 if (err == 0) { 134 /* set default value */ 135 for (x = 0; x != IEEE_8021QAZ_MAX_TCS; x++) { 136 priv->params_ethtool.max_bw_share[x] = 137 100 / IEEE_8021QAZ_MAX_TCS; 138 } 139 err = -mlx5_set_port_tc_bw_alloc(mdev, 140 priv->params_ethtool.max_bw_share); 141 } 142 PRIV_UNLOCK(priv); 143 144 return (err); 145 } 146 147 static int 148 mlx5e_get_dscp(struct mlx5e_priv *priv) 149 { 150 struct mlx5_core_dev *mdev = priv->mdev; 151 int err; 152 153 if (MLX5_CAP_GEN(mdev, qcam_reg) == 0 || 154 MLX5_CAP_QCAM_REG(mdev, qpts) == 0 || 155 MLX5_CAP_QCAM_REG(mdev, qpdpm) == 0) 156 return (EOPNOTSUPP); 157 158 PRIV_LOCK(priv); 159 err = -mlx5_query_dscp2prio(mdev, priv->params_ethtool.dscp2prio); 160 if (err) 161 goto done; 162 163 err = -mlx5_query_trust_state(mdev, &priv->params_ethtool.trust_state); 164 if (err) 165 goto done; 166 done: 167 PRIV_UNLOCK(priv); 168 return (err); 169 } 170 171 static void 172 mlx5e_tc_get_parameters(struct mlx5e_priv *priv, 173 u64 *new_bw_value, u8 *max_bw_value, u8 *max_bw_unit) 174 { 175 const u64 upper_limit_mbps = 255 * MLX5E_100MB; 176 const u64 upper_limit_gbps = 255 * MLX5E_1GB; 177 u64 temp; 178 int i; 179 180 memset(max_bw_value, 0, IEEE_8021QAZ_MAX_TCS); 181 memset(max_bw_unit, 0, IEEE_8021QAZ_MAX_TCS); 182 183 for (i = 0; i <= mlx5_max_tc(priv->mdev); i++) { 184 temp = (new_bw_value != NULL) ? 185 new_bw_value[i] : priv->params_ethtool.max_bw_value[i]; 186 187 if (!temp) { 188 max_bw_unit[i] = MLX5_BW_NO_LIMIT; 189 } else if (temp > upper_limit_gbps) { 190 max_bw_unit[i] = MLX5_BW_NO_LIMIT; 191 } else if (temp <= upper_limit_mbps) { 192 max_bw_value[i] = howmany(temp, MLX5E_100MB); 193 max_bw_unit[i] = MLX5_100_MBPS_UNIT; 194 } else { 195 max_bw_value[i] = howmany(temp, MLX5E_1GB); 196 max_bw_unit[i] = MLX5_GBPS_UNIT; 197 } 198 } 199 } 200 201 static int 202 mlx5e_tc_maxrate_handler(SYSCTL_HANDLER_ARGS) 203 { 204 struct mlx5e_priv *priv = arg1; 205 struct mlx5_core_dev *mdev = priv->mdev; 206 u8 max_bw_unit[IEEE_8021QAZ_MAX_TCS]; 207 u8 max_bw_value[IEEE_8021QAZ_MAX_TCS]; 208 u64 new_bw_value[IEEE_8021QAZ_MAX_TCS]; 209 u8 max_rates = mlx5_max_tc(mdev) + 1; 210 u8 x; 211 int err; 212 213 PRIV_LOCK(priv); 214 err = SYSCTL_OUT(req, priv->params_ethtool.max_bw_value, 215 sizeof(priv->params_ethtool.max_bw_value[0]) * max_rates); 216 if (err || !req->newptr) 217 goto done; 218 err = SYSCTL_IN(req, new_bw_value, 219 sizeof(new_bw_value[0]) * max_rates); 220 if (err) 221 goto done; 222 223 /* range check input value */ 224 for (x = 0; x != max_rates; x++) { 225 if (new_bw_value[x] % MLX5E_100MB) { 226 err = ERANGE; 227 goto done; 228 } 229 } 230 231 mlx5e_tc_get_parameters(priv, new_bw_value, max_bw_value, max_bw_unit); 232 233 err = -mlx5_modify_port_tc_rate_limit(mdev, max_bw_value, max_bw_unit); 234 if (err) 235 goto done; 236 237 memcpy(priv->params_ethtool.max_bw_value, new_bw_value, 238 sizeof(priv->params_ethtool.max_bw_value)); 239 done: 240 PRIV_UNLOCK(priv); 241 return (err); 242 } 243 244 static int 245 mlx5e_tc_rate_share_handler(SYSCTL_HANDLER_ARGS) 246 { 247 struct mlx5e_priv *priv = arg1; 248 struct mlx5_core_dev *mdev = priv->mdev; 249 u8 max_bw_share[IEEE_8021QAZ_MAX_TCS]; 250 u8 max_rates = mlx5_max_tc(mdev) + 1; 251 int i; 252 int err; 253 int sum; 254 255 PRIV_LOCK(priv); 256 err = SYSCTL_OUT(req, priv->params_ethtool.max_bw_share, max_rates); 257 if (err || !req->newptr) 258 goto done; 259 err = SYSCTL_IN(req, max_bw_share, max_rates); 260 if (err) 261 goto done; 262 263 /* range check input value */ 264 for (sum = i = 0; i != max_rates; i++) { 265 if (max_bw_share[i] < 1 || max_bw_share[i] > 100) { 266 err = ERANGE; 267 goto done; 268 } 269 sum += max_bw_share[i]; 270 } 271 272 /* sum of values should be as close to 100 as possible */ 273 if (sum < (100 - max_rates + 1) || sum > 100) { 274 err = ERANGE; 275 goto done; 276 } 277 278 err = -mlx5_set_port_tc_bw_alloc(mdev, max_bw_share); 279 if (err) 280 goto done; 281 282 memcpy(priv->params_ethtool.max_bw_share, max_bw_share, 283 sizeof(priv->params_ethtool.max_bw_share)); 284 done: 285 PRIV_UNLOCK(priv); 286 return (err); 287 } 288 289 static int 290 mlx5e_get_prio_tc(struct mlx5e_priv *priv) 291 { 292 struct mlx5_core_dev *mdev = priv->mdev; 293 int err = 0; 294 int i; 295 296 PRIV_LOCK(priv); 297 if (!MLX5_CAP_GEN(priv->mdev, ets)) { 298 PRIV_UNLOCK(priv); 299 return (EOPNOTSUPP); 300 } 301 302 for (i = 0; i != MLX5E_MAX_PRIORITY; i++) { 303 err = -mlx5_query_port_prio_tc(mdev, i, priv->params_ethtool.prio_tc + i); 304 if (err) 305 break; 306 } 307 PRIV_UNLOCK(priv); 308 return (err); 309 } 310 311 static int 312 mlx5e_prio_to_tc_handler(SYSCTL_HANDLER_ARGS) 313 { 314 struct mlx5e_priv *priv = arg1; 315 struct mlx5_core_dev *mdev = priv->mdev; 316 uint8_t temp[MLX5E_MAX_PRIORITY]; 317 int err; 318 int i; 319 320 PRIV_LOCK(priv); 321 err = SYSCTL_OUT(req, priv->params_ethtool.prio_tc, MLX5E_MAX_PRIORITY); 322 if (err || !req->newptr) 323 goto done; 324 err = SYSCTL_IN(req, temp, MLX5E_MAX_PRIORITY); 325 if (err) 326 goto done; 327 328 for (i = 0; i != MLX5E_MAX_PRIORITY; i++) { 329 if (temp[i] > mlx5_max_tc(mdev)) { 330 err = ERANGE; 331 goto done; 332 } 333 } 334 335 for (i = 0; i != MLX5E_MAX_PRIORITY; i++) { 336 if (temp[i] == priv->params_ethtool.prio_tc[i]) 337 continue; 338 err = -mlx5_set_port_prio_tc(mdev, i, temp[i]); 339 if (err) 340 goto done; 341 /* update cached value */ 342 priv->params_ethtool.prio_tc[i] = temp[i]; 343 } 344 done: 345 PRIV_UNLOCK(priv); 346 return (err); 347 } 348 349 static int 350 mlx5e_trust_state_handler(SYSCTL_HANDLER_ARGS) 351 { 352 struct mlx5e_priv *priv = arg1; 353 struct mlx5_core_dev *mdev = priv->mdev; 354 int err; 355 u8 result; 356 357 PRIV_LOCK(priv); 358 result = priv->params_ethtool.trust_state; 359 err = sysctl_handle_8(oidp, &result, 0, req); 360 if (err || !req->newptr || 361 result == priv->params_ethtool.trust_state) 362 goto done; 363 364 switch (result) { 365 case MLX5_QPTS_TRUST_PCP: 366 case MLX5_QPTS_TRUST_DSCP: 367 break; 368 case MLX5_QPTS_TRUST_BOTH: 369 if (!MLX5_CAP_QCAM_FEATURE(mdev, qpts_trust_both)) { 370 err = EOPNOTSUPP; 371 goto done; 372 } 373 break; 374 default: 375 err = ERANGE; 376 goto done; 377 } 378 379 err = -mlx5_set_trust_state(mdev, result); 380 if (err) 381 goto done; 382 383 priv->params_ethtool.trust_state = result; 384 385 /* update inline mode */ 386 mlx5e_refresh_sq_inline(priv); 387 #ifdef RATELIMIT 388 mlx5e_rl_refresh_sq_inline(&priv->rl); 389 #endif 390 done: 391 PRIV_UNLOCK(priv); 392 return (err); 393 } 394 395 static int 396 mlx5e_dscp_prio_handler(SYSCTL_HANDLER_ARGS) 397 { 398 struct mlx5e_priv *priv = arg1; 399 int prio_index = arg2; 400 struct mlx5_core_dev *mdev = priv->mdev; 401 uint8_t dscp2prio[MLX5_MAX_SUPPORTED_DSCP]; 402 uint8_t x; 403 int err; 404 405 PRIV_LOCK(priv); 406 err = SYSCTL_OUT(req, priv->params_ethtool.dscp2prio + prio_index, 407 sizeof(priv->params_ethtool.dscp2prio) / 8); 408 if (err || !req->newptr) 409 goto done; 410 411 memcpy(dscp2prio, priv->params_ethtool.dscp2prio, sizeof(dscp2prio)); 412 err = SYSCTL_IN(req, dscp2prio + prio_index, sizeof(dscp2prio) / 8); 413 if (err) 414 goto done; 415 for (x = 0; x != MLX5_MAX_SUPPORTED_DSCP; x++) { 416 if (dscp2prio[x] > 7) { 417 err = ERANGE; 418 goto done; 419 } 420 } 421 err = -mlx5_set_dscp2prio(mdev, dscp2prio); 422 if (err) 423 goto done; 424 425 /* update local array */ 426 memcpy(priv->params_ethtool.dscp2prio, dscp2prio, 427 sizeof(priv->params_ethtool.dscp2prio)); 428 done: 429 PRIV_UNLOCK(priv); 430 return (err); 431 } 432 433 int 434 mlx5e_update_buf_lossy(struct mlx5e_priv *priv) 435 { 436 struct ieee_pfc pfc; 437 438 PRIV_ASSERT_LOCKED(priv); 439 bzero(&pfc, sizeof(pfc)); 440 pfc.pfc_en = priv->params.rx_priority_flow_control; 441 return (-mlx5e_port_manual_buffer_config(priv, MLX5E_PORT_BUFFER_PFC, 442 priv->params_ethtool.hw_mtu, &pfc, NULL, NULL)); 443 } 444 445 static int 446 mlx5e_buf_size_handler(SYSCTL_HANDLER_ARGS) 447 { 448 struct mlx5e_priv *priv; 449 u32 buf_size[MLX5E_MAX_BUFFER]; 450 struct mlx5e_port_buffer port_buffer; 451 int error, i; 452 453 priv = arg1; 454 PRIV_LOCK(priv); 455 error = -mlx5e_port_query_buffer(priv, &port_buffer); 456 if (error != 0) 457 goto done; 458 for (i = 0; i < nitems(buf_size); i++) 459 buf_size[i] = port_buffer.buffer[i].size; 460 error = SYSCTL_OUT(req, buf_size, sizeof(buf_size)); 461 if (error != 0 || req->newptr == NULL) 462 goto done; 463 error = SYSCTL_IN(req, buf_size, sizeof(buf_size)); 464 if (error != 0) 465 goto done; 466 error = -mlx5e_port_manual_buffer_config(priv, MLX5E_PORT_BUFFER_SIZE, 467 priv->params_ethtool.hw_mtu, NULL, buf_size, NULL); 468 done: 469 PRIV_UNLOCK(priv); 470 return (error); 471 } 472 473 static int 474 mlx5e_buf_prio_handler(SYSCTL_HANDLER_ARGS) 475 { 476 struct mlx5e_priv *priv; 477 struct mlx5_core_dev *mdev; 478 u8 buffer[MLX5E_MAX_BUFFER]; 479 int error; 480 481 priv = arg1; 482 mdev = priv->mdev; 483 PRIV_LOCK(priv); 484 error = -mlx5e_port_query_priority2buffer(mdev, buffer); 485 if (error != 0) 486 goto done; 487 error = SYSCTL_OUT(req, buffer, MLX5E_MAX_BUFFER); 488 if (error != 0 || req->newptr == NULL) 489 goto done; 490 error = SYSCTL_IN(req, buffer, MLX5E_MAX_BUFFER); 491 if (error != 0) 492 goto done; 493 error = -mlx5e_port_manual_buffer_config(priv, 494 MLX5E_PORT_BUFFER_PRIO2BUFFER, 495 priv->params_ethtool.hw_mtu, NULL, NULL, buffer); 496 if (error == 0) 497 error = mlx5e_update_buf_lossy(priv); 498 done: 499 PRIV_UNLOCK(priv); 500 return (error); 501 } 502 503 static int 504 mlx5e_cable_length_handler(SYSCTL_HANDLER_ARGS) 505 { 506 struct mlx5e_priv *priv; 507 u_int cable_len; 508 int error; 509 510 priv = arg1; 511 PRIV_LOCK(priv); 512 cable_len = priv->dcbx.cable_len; 513 error = sysctl_handle_int(oidp, &cable_len, 0, req); 514 if (error == 0 && req->newptr != NULL && 515 cable_len != priv->dcbx.cable_len) { 516 error = -mlx5e_port_manual_buffer_config(priv, 517 MLX5E_PORT_BUFFER_CABLE_LEN, priv->params_ethtool.hw_mtu, 518 NULL, NULL, NULL); 519 if (error == 0) 520 priv->dcbx.cable_len = cable_len; 521 } 522 PRIV_UNLOCK(priv); 523 return (error); 524 } 525 526 #define MLX5_PARAM_OFFSET(n) \ 527 __offsetof(struct mlx5e_priv, params_ethtool.n) 528 529 static int 530 mlx5e_ethtool_handler(SYSCTL_HANDLER_ARGS) 531 { 532 struct mlx5e_priv *priv = arg1; 533 uint64_t value; 534 int mode_modify; 535 int was_opened; 536 int error; 537 538 PRIV_LOCK(priv); 539 value = priv->params_ethtool.arg[arg2]; 540 if (req != NULL) { 541 error = sysctl_handle_64(oidp, &value, 0, req); 542 if (error || req->newptr == NULL || 543 value == priv->params_ethtool.arg[arg2]) 544 goto done; 545 546 /* assign new value */ 547 priv->params_ethtool.arg[arg2] = value; 548 } else { 549 error = 0; 550 } 551 /* check if device is gone */ 552 if (priv->gone) { 553 error = ENXIO; 554 goto done; 555 } 556 was_opened = test_bit(MLX5E_STATE_OPENED, &priv->state); 557 mode_modify = MLX5_CAP_GEN(priv->mdev, cq_period_mode_modify); 558 559 switch (MLX5_PARAM_OFFSET(arg[arg2])) { 560 case MLX5_PARAM_OFFSET(rx_coalesce_usecs): 561 /* import RX coal time */ 562 if (priv->params_ethtool.rx_coalesce_usecs < 1) 563 priv->params_ethtool.rx_coalesce_usecs = 0; 564 else if (priv->params_ethtool.rx_coalesce_usecs > 565 MLX5E_FLD_MAX(cqc, cq_period)) { 566 priv->params_ethtool.rx_coalesce_usecs = 567 MLX5E_FLD_MAX(cqc, cq_period); 568 } 569 priv->params.rx_cq_moderation_usec = 570 priv->params_ethtool.rx_coalesce_usecs; 571 572 /* check to avoid down and up the network interface */ 573 if (was_opened) 574 error = mlx5e_refresh_channel_params(priv); 575 break; 576 577 case MLX5_PARAM_OFFSET(rx_coalesce_pkts): 578 /* import RX coal pkts */ 579 if (priv->params_ethtool.rx_coalesce_pkts < 1) 580 priv->params_ethtool.rx_coalesce_pkts = 0; 581 else if (priv->params_ethtool.rx_coalesce_pkts > 582 MLX5E_FLD_MAX(cqc, cq_max_count)) { 583 priv->params_ethtool.rx_coalesce_pkts = 584 MLX5E_FLD_MAX(cqc, cq_max_count); 585 } 586 priv->params.rx_cq_moderation_pkts = 587 priv->params_ethtool.rx_coalesce_pkts; 588 589 /* check to avoid down and up the network interface */ 590 if (was_opened) 591 error = mlx5e_refresh_channel_params(priv); 592 break; 593 594 case MLX5_PARAM_OFFSET(tx_coalesce_usecs): 595 /* import TX coal time */ 596 if (priv->params_ethtool.tx_coalesce_usecs < 1) 597 priv->params_ethtool.tx_coalesce_usecs = 0; 598 else if (priv->params_ethtool.tx_coalesce_usecs > 599 MLX5E_FLD_MAX(cqc, cq_period)) { 600 priv->params_ethtool.tx_coalesce_usecs = 601 MLX5E_FLD_MAX(cqc, cq_period); 602 } 603 priv->params.tx_cq_moderation_usec = 604 priv->params_ethtool.tx_coalesce_usecs; 605 606 /* check to avoid down and up the network interface */ 607 if (was_opened) 608 error = mlx5e_refresh_channel_params(priv); 609 break; 610 611 case MLX5_PARAM_OFFSET(tx_coalesce_pkts): 612 /* import TX coal pkts */ 613 if (priv->params_ethtool.tx_coalesce_pkts < 1) 614 priv->params_ethtool.tx_coalesce_pkts = 0; 615 else if (priv->params_ethtool.tx_coalesce_pkts > 616 MLX5E_FLD_MAX(cqc, cq_max_count)) { 617 priv->params_ethtool.tx_coalesce_pkts = 618 MLX5E_FLD_MAX(cqc, cq_max_count); 619 } 620 priv->params.tx_cq_moderation_pkts = 621 priv->params_ethtool.tx_coalesce_pkts; 622 623 /* check to avoid down and up the network interface */ 624 if (was_opened) 625 error = mlx5e_refresh_channel_params(priv); 626 break; 627 628 case MLX5_PARAM_OFFSET(tx_queue_size): 629 /* network interface must be down */ 630 if (was_opened) 631 mlx5e_close_locked(priv->ifp); 632 633 /* import TX queue size */ 634 if (priv->params_ethtool.tx_queue_size < 635 (1 << MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE)) { 636 priv->params_ethtool.tx_queue_size = 637 (1 << MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE); 638 } else if (priv->params_ethtool.tx_queue_size > 639 priv->params_ethtool.tx_queue_size_max) { 640 priv->params_ethtool.tx_queue_size = 641 priv->params_ethtool.tx_queue_size_max; 642 } 643 /* store actual TX queue size */ 644 priv->params.log_sq_size = 645 order_base_2(priv->params_ethtool.tx_queue_size); 646 priv->params_ethtool.tx_queue_size = 647 1 << priv->params.log_sq_size; 648 649 /* verify TX completion factor */ 650 mlx5e_ethtool_sync_tx_completion_fact(priv); 651 652 /* restart network interface, if any */ 653 if (was_opened) 654 mlx5e_open_locked(priv->ifp); 655 break; 656 657 case MLX5_PARAM_OFFSET(rx_queue_size): 658 /* network interface must be down */ 659 if (was_opened) 660 mlx5e_close_locked(priv->ifp); 661 662 /* import RX queue size */ 663 if (priv->params_ethtool.rx_queue_size < 664 (1 << MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE)) { 665 priv->params_ethtool.rx_queue_size = 666 (1 << MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE); 667 } else if (priv->params_ethtool.rx_queue_size > 668 priv->params_ethtool.rx_queue_size_max) { 669 priv->params_ethtool.rx_queue_size = 670 priv->params_ethtool.rx_queue_size_max; 671 } 672 /* store actual RX queue size */ 673 priv->params.log_rq_size = 674 order_base_2(priv->params_ethtool.rx_queue_size); 675 priv->params_ethtool.rx_queue_size = 676 1 << priv->params.log_rq_size; 677 678 /* update least number of RX WQEs */ 679 priv->params.min_rx_wqes = min( 680 priv->params_ethtool.rx_queue_size - 1, 681 MLX5E_PARAMS_DEFAULT_MIN_RX_WQES); 682 683 /* restart network interface, if any */ 684 if (was_opened) 685 mlx5e_open_locked(priv->ifp); 686 break; 687 688 case MLX5_PARAM_OFFSET(channels_rsss): 689 /* network interface must be down */ 690 if (was_opened) 691 mlx5e_close_locked(priv->ifp); 692 693 /* import number of channels */ 694 if (priv->params_ethtool.channels_rsss < 1) 695 priv->params_ethtool.channels_rsss = 1; 696 else if (priv->params_ethtool.channels_rsss > 128) 697 priv->params_ethtool.channels_rsss = 128; 698 699 priv->params.channels_rsss = priv->params_ethtool.channels_rsss; 700 701 /* restart network interface, if any */ 702 if (was_opened) 703 mlx5e_open_locked(priv->ifp); 704 break; 705 706 case MLX5_PARAM_OFFSET(channels): 707 /* network interface must be down */ 708 if (was_opened) 709 mlx5e_close_locked(priv->ifp); 710 711 /* import number of channels */ 712 if (priv->params_ethtool.channels < 1) 713 priv->params_ethtool.channels = 1; 714 else if (priv->params_ethtool.channels > 715 (u64) priv->mdev->priv.eq_table.num_comp_vectors) { 716 priv->params_ethtool.channels = 717 (u64) priv->mdev->priv.eq_table.num_comp_vectors; 718 } 719 priv->params.num_channels = priv->params_ethtool.channels; 720 721 /* restart network interface, if any */ 722 if (was_opened) 723 mlx5e_open_locked(priv->ifp); 724 break; 725 726 case MLX5_PARAM_OFFSET(rx_coalesce_mode): 727 /* network interface must be down */ 728 if (was_opened != 0 && mode_modify == 0) 729 mlx5e_close_locked(priv->ifp); 730 731 /* import RX coalesce mode */ 732 if (priv->params_ethtool.rx_coalesce_mode > 3) 733 priv->params_ethtool.rx_coalesce_mode = 3; 734 priv->params.rx_cq_moderation_mode = 735 priv->params_ethtool.rx_coalesce_mode; 736 737 /* restart network interface, if any */ 738 if (was_opened != 0) { 739 if (mode_modify == 0) 740 mlx5e_open_locked(priv->ifp); 741 else 742 error = mlx5e_refresh_channel_params(priv); 743 } 744 break; 745 746 case MLX5_PARAM_OFFSET(tx_coalesce_mode): 747 /* network interface must be down */ 748 if (was_opened != 0 && mode_modify == 0) 749 mlx5e_close_locked(priv->ifp); 750 751 /* import TX coalesce mode */ 752 if (priv->params_ethtool.tx_coalesce_mode != 0) 753 priv->params_ethtool.tx_coalesce_mode = 1; 754 priv->params.tx_cq_moderation_mode = 755 priv->params_ethtool.tx_coalesce_mode; 756 757 /* restart network interface, if any */ 758 if (was_opened != 0) { 759 if (mode_modify == 0) 760 mlx5e_open_locked(priv->ifp); 761 else 762 error = mlx5e_refresh_channel_params(priv); 763 } 764 break; 765 766 case MLX5_PARAM_OFFSET(hw_lro): 767 /* network interface must be down */ 768 if (was_opened) 769 mlx5e_close_locked(priv->ifp); 770 771 /* import HW LRO mode */ 772 if (priv->params_ethtool.hw_lro != 0 && 773 MLX5_CAP_ETH(priv->mdev, lro_cap)) { 774 priv->params_ethtool.hw_lro = 1; 775 /* check if feature should actually be enabled */ 776 if (priv->ifp->if_capenable & IFCAP_LRO) { 777 priv->params.hw_lro_en = true; 778 } else { 779 priv->params.hw_lro_en = false; 780 781 mlx5_en_warn(priv->ifp, "To enable HW LRO " 782 "please also enable LRO via ifconfig(8).\n"); 783 } 784 } else { 785 /* return an error if HW does not support this feature */ 786 if (priv->params_ethtool.hw_lro != 0) 787 error = EINVAL; 788 priv->params.hw_lro_en = false; 789 priv->params_ethtool.hw_lro = 0; 790 } 791 /* restart network interface, if any */ 792 if (was_opened) 793 mlx5e_open_locked(priv->ifp); 794 break; 795 796 case MLX5_PARAM_OFFSET(cqe_zipping): 797 /* network interface must be down */ 798 if (was_opened) 799 mlx5e_close_locked(priv->ifp); 800 801 /* import CQE zipping mode */ 802 if (priv->params_ethtool.cqe_zipping && 803 MLX5_CAP_GEN(priv->mdev, cqe_compression)) { 804 priv->params.cqe_zipping_en = true; 805 priv->params_ethtool.cqe_zipping = 1; 806 } else { 807 priv->params.cqe_zipping_en = false; 808 priv->params_ethtool.cqe_zipping = 0; 809 } 810 /* restart network interface, if any */ 811 if (was_opened) 812 mlx5e_open_locked(priv->ifp); 813 break; 814 815 case MLX5_PARAM_OFFSET(tx_completion_fact): 816 /* network interface must be down */ 817 if (was_opened) 818 mlx5e_close_locked(priv->ifp); 819 820 /* verify parameter */ 821 mlx5e_ethtool_sync_tx_completion_fact(priv); 822 823 /* restart network interface, if any */ 824 if (was_opened) 825 mlx5e_open_locked(priv->ifp); 826 break; 827 828 case MLX5_PARAM_OFFSET(modify_tx_dma): 829 /* check if network interface is opened */ 830 if (was_opened) { 831 priv->params_ethtool.modify_tx_dma = 832 priv->params_ethtool.modify_tx_dma ? 1 : 0; 833 /* modify tx according to value */ 834 mlx5e_modify_tx_dma(priv, value != 0); 835 } else { 836 /* if closed force enable tx */ 837 priv->params_ethtool.modify_tx_dma = 0; 838 } 839 break; 840 841 case MLX5_PARAM_OFFSET(modify_rx_dma): 842 /* check if network interface is opened */ 843 if (was_opened) { 844 priv->params_ethtool.modify_rx_dma = 845 priv->params_ethtool.modify_rx_dma ? 1 : 0; 846 /* modify rx according to value */ 847 mlx5e_modify_rx_dma(priv, value != 0); 848 } else { 849 /* if closed force enable rx */ 850 priv->params_ethtool.modify_rx_dma = 0; 851 } 852 break; 853 854 case MLX5_PARAM_OFFSET(diag_pci_enable): 855 priv->params_ethtool.diag_pci_enable = 856 priv->params_ethtool.diag_pci_enable ? 1 : 0; 857 858 error = -mlx5_core_set_diagnostics_full(priv->mdev, 859 priv->params_ethtool.diag_pci_enable, 860 priv->params_ethtool.diag_general_enable); 861 break; 862 863 case MLX5_PARAM_OFFSET(diag_general_enable): 864 priv->params_ethtool.diag_general_enable = 865 priv->params_ethtool.diag_general_enable ? 1 : 0; 866 867 error = -mlx5_core_set_diagnostics_full(priv->mdev, 868 priv->params_ethtool.diag_pci_enable, 869 priv->params_ethtool.diag_general_enable); 870 break; 871 872 case MLX5_PARAM_OFFSET(mc_local_lb): 873 priv->params_ethtool.mc_local_lb = 874 priv->params_ethtool.mc_local_lb ? 1 : 0; 875 876 if (MLX5_CAP_GEN(priv->mdev, disable_local_lb)) { 877 error = mlx5_nic_vport_modify_local_lb(priv->mdev, 878 MLX5_LOCAL_MC_LB, priv->params_ethtool.mc_local_lb); 879 } else { 880 error = EOPNOTSUPP; 881 } 882 break; 883 884 case MLX5_PARAM_OFFSET(uc_local_lb): 885 priv->params_ethtool.uc_local_lb = 886 priv->params_ethtool.uc_local_lb ? 1 : 0; 887 888 if (MLX5_CAP_GEN(priv->mdev, disable_local_lb)) { 889 error = mlx5_nic_vport_modify_local_lb(priv->mdev, 890 MLX5_LOCAL_UC_LB, priv->params_ethtool.uc_local_lb); 891 } else { 892 error = EOPNOTSUPP; 893 } 894 break; 895 896 default: 897 break; 898 } 899 done: 900 PRIV_UNLOCK(priv); 901 return (error); 902 } 903 904 static const char *mlx5e_params_desc[] = { 905 MLX5E_PARAMS(MLX5E_STATS_DESC) 906 }; 907 908 static const char *mlx5e_port_stats_debug_desc[] = { 909 MLX5E_PORT_STATS_DEBUG(MLX5E_STATS_DESC) 910 }; 911 912 static int 913 mlx5e_ethtool_debug_channel_info(SYSCTL_HANDLER_ARGS) 914 { 915 struct mlx5e_priv *priv; 916 struct sbuf sb; 917 struct mlx5e_channel *c; 918 struct mlx5e_sq *sq; 919 struct mlx5e_rq *rq; 920 int error, i, tc; 921 bool opened; 922 923 priv = arg1; 924 error = sysctl_wire_old_buffer(req, 0); 925 if (error != 0) 926 return (error); 927 if (sbuf_new_for_sysctl(&sb, NULL, 1024, req) == NULL) 928 return (ENOMEM); 929 sbuf_clear_flags(&sb, SBUF_INCLUDENUL); 930 931 PRIV_LOCK(priv); 932 opened = test_bit(MLX5E_STATE_OPENED, &priv->state); 933 934 sbuf_printf(&sb, "pages irq %d\n", 935 priv->mdev->priv.msix_arr[MLX5_EQ_VEC_PAGES].vector); 936 sbuf_printf(&sb, "command irq %d\n", 937 priv->mdev->priv.msix_arr[MLX5_EQ_VEC_CMD].vector); 938 sbuf_printf(&sb, "async irq %d\n", 939 priv->mdev->priv.msix_arr[MLX5_EQ_VEC_ASYNC].vector); 940 941 for (i = 0; i != priv->params.num_channels; i++) { 942 int eqn_not_used = -1; 943 int irqn = MLX5_EQ_VEC_COMP_BASE; 944 945 if (mlx5_vector2eqn(priv->mdev, i, &eqn_not_used, &irqn) != 0) 946 continue; 947 948 c = opened ? &priv->channel[i] : NULL; 949 rq = opened ? &c->rq : NULL; 950 sbuf_printf(&sb, "channel %d rq %d cq %d irq %d\n", i, 951 opened ? rq->rqn : -1, 952 opened ? rq->cq.mcq.cqn : -1, 953 priv->mdev->priv.msix_arr[irqn].vector); 954 955 for (tc = 0; tc != priv->num_tc; tc++) { 956 sq = opened ? &c->sq[tc] : NULL; 957 sbuf_printf(&sb, "channel %d tc %d sq %d cq %d irq %d\n", 958 i, tc, 959 opened ? sq->sqn : -1, 960 opened ? sq->cq.mcq.cqn : -1, 961 priv->mdev->priv.msix_arr[irqn].vector); 962 } 963 } 964 PRIV_UNLOCK(priv); 965 error = sbuf_finish(&sb); 966 sbuf_delete(&sb); 967 return (error); 968 } 969 970 static int 971 mlx5e_ethtool_debug_stats(SYSCTL_HANDLER_ARGS) 972 { 973 struct mlx5e_priv *priv = arg1; 974 int sys_debug; 975 int error; 976 977 PRIV_LOCK(priv); 978 if (priv->gone != 0) { 979 error = ENODEV; 980 goto done; 981 } 982 sys_debug = priv->sysctl_debug; 983 error = sysctl_handle_int(oidp, &sys_debug, 0, req); 984 if (error != 0 || !req->newptr) 985 goto done; 986 sys_debug = sys_debug ? 1 : 0; 987 if (sys_debug == priv->sysctl_debug) 988 goto done; 989 990 if ((priv->sysctl_debug = sys_debug)) { 991 mlx5e_create_stats(&priv->stats.port_stats_debug.ctx, 992 SYSCTL_CHILDREN(priv->sysctl_ifnet), "debug_stats", 993 mlx5e_port_stats_debug_desc, MLX5E_PORT_STATS_DEBUG_NUM, 994 priv->stats.port_stats_debug.arg); 995 SYSCTL_ADD_PROC(&priv->stats.port_stats_debug.ctx, 996 SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO, 997 "hw_ctx_debug", 998 CTLFLAG_RD | CTLFLAG_MPSAFE | CTLTYPE_STRING, priv, 0, 999 mlx5e_ethtool_debug_channel_info, "S", ""); 1000 } else { 1001 sysctl_ctx_free(&priv->stats.port_stats_debug.ctx); 1002 } 1003 done: 1004 PRIV_UNLOCK(priv); 1005 return (error); 1006 } 1007 1008 static void 1009 mlx5e_create_diagnostics(struct mlx5e_priv *priv) 1010 { 1011 struct mlx5_core_diagnostics_entry entry; 1012 struct sysctl_ctx_list *ctx; 1013 struct sysctl_oid *node; 1014 int x; 1015 1016 /* sysctl context we are using */ 1017 ctx = &priv->sysctl_ctx; 1018 1019 /* create root node */ 1020 node = SYSCTL_ADD_NODE(ctx, 1021 SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO, 1022 "diagnostics", CTLFLAG_RD, NULL, "Diagnostics"); 1023 if (node == NULL) 1024 return; 1025 1026 /* create PCI diagnostics */ 1027 for (x = 0; x != MLX5_CORE_PCI_DIAGNOSTICS_NUM; x++) { 1028 entry = mlx5_core_pci_diagnostics_table[x]; 1029 if (mlx5_core_supports_diagnostics(priv->mdev, entry.counter_id) == 0) 1030 continue; 1031 SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO, 1032 entry.desc, CTLFLAG_RD, priv->params_pci.array + x, 1033 "PCI diagnostics counter"); 1034 } 1035 1036 /* create general diagnostics */ 1037 for (x = 0; x != MLX5_CORE_GENERAL_DIAGNOSTICS_NUM; x++) { 1038 entry = mlx5_core_general_diagnostics_table[x]; 1039 if (mlx5_core_supports_diagnostics(priv->mdev, entry.counter_id) == 0) 1040 continue; 1041 SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO, 1042 entry.desc, CTLFLAG_RD, priv->params_general.array + x, 1043 "General diagnostics counter"); 1044 } 1045 } 1046 1047 void 1048 mlx5e_create_ethtool(struct mlx5e_priv *priv) 1049 { 1050 struct sysctl_oid *node, *qos_node; 1051 const char *pnameunit; 1052 struct mlx5e_port_buffer port_buffer; 1053 unsigned x; 1054 int i; 1055 1056 /* set some defaults */ 1057 priv->params_ethtool.tx_queue_size_max = 1 << MLX5E_PARAMS_MAXIMUM_LOG_SQ_SIZE; 1058 priv->params_ethtool.rx_queue_size_max = 1 << MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE; 1059 priv->params_ethtool.tx_queue_size = 1 << priv->params.log_sq_size; 1060 priv->params_ethtool.rx_queue_size = 1 << priv->params.log_rq_size; 1061 priv->params_ethtool.channels = priv->params.num_channels; 1062 priv->params_ethtool.channels_rsss = priv->params.channels_rsss; 1063 priv->params_ethtool.coalesce_pkts_max = MLX5E_FLD_MAX(cqc, cq_max_count); 1064 priv->params_ethtool.coalesce_usecs_max = MLX5E_FLD_MAX(cqc, cq_period); 1065 priv->params_ethtool.rx_coalesce_mode = priv->params.rx_cq_moderation_mode; 1066 priv->params_ethtool.rx_coalesce_usecs = priv->params.rx_cq_moderation_usec; 1067 priv->params_ethtool.rx_coalesce_pkts = priv->params.rx_cq_moderation_pkts; 1068 priv->params_ethtool.tx_coalesce_mode = priv->params.tx_cq_moderation_mode; 1069 priv->params_ethtool.tx_coalesce_usecs = priv->params.tx_cq_moderation_usec; 1070 priv->params_ethtool.tx_coalesce_pkts = priv->params.tx_cq_moderation_pkts; 1071 priv->params_ethtool.hw_lro = priv->params.hw_lro_en; 1072 priv->params_ethtool.cqe_zipping = priv->params.cqe_zipping_en; 1073 mlx5e_ethtool_sync_tx_completion_fact(priv); 1074 1075 /* get default values for local loopback, if any */ 1076 if (MLX5_CAP_GEN(priv->mdev, disable_local_lb)) { 1077 int err; 1078 u8 val; 1079 1080 err = mlx5_nic_vport_query_local_lb(priv->mdev, MLX5_LOCAL_MC_LB, &val); 1081 if (err == 0) 1082 priv->params_ethtool.mc_local_lb = val; 1083 1084 err = mlx5_nic_vport_query_local_lb(priv->mdev, MLX5_LOCAL_UC_LB, &val); 1085 if (err == 0) 1086 priv->params_ethtool.uc_local_lb = val; 1087 } 1088 1089 /* create root node */ 1090 node = SYSCTL_ADD_NODE(&priv->sysctl_ctx, 1091 SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO, 1092 "conf", CTLFLAG_RW, NULL, "Configuration"); 1093 if (node == NULL) 1094 return; 1095 for (x = 0; x != MLX5E_PARAMS_NUM; x++) { 1096 /* check for read-only parameter */ 1097 if (strstr(mlx5e_params_desc[2 * x], "_max") != NULL || 1098 strstr(mlx5e_params_desc[2 * x], "_mtu") != NULL) { 1099 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO, 1100 mlx5e_params_desc[2 * x], CTLTYPE_U64 | CTLFLAG_RD | 1101 CTLFLAG_MPSAFE, priv, x, &mlx5e_ethtool_handler, "QU", 1102 mlx5e_params_desc[2 * x + 1]); 1103 } else { 1104 #if (__FreeBSD_version < 1100000) 1105 char path[64]; 1106 #endif 1107 /* 1108 * NOTE: In FreeBSD-11 and newer the 1109 * CTLFLAG_RWTUN flag will take care of 1110 * loading default sysctl value from the 1111 * kernel environment, if any: 1112 */ 1113 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO, 1114 mlx5e_params_desc[2 * x], CTLTYPE_U64 | CTLFLAG_RWTUN | 1115 CTLFLAG_MPSAFE, priv, x, &mlx5e_ethtool_handler, "QU", 1116 mlx5e_params_desc[2 * x + 1]); 1117 1118 #if (__FreeBSD_version < 1100000) 1119 /* compute path for sysctl */ 1120 snprintf(path, sizeof(path), "dev.mce.%d.conf.%s", 1121 device_get_unit(priv->mdev->pdev->dev.bsddev), 1122 mlx5e_params_desc[2 * x]); 1123 1124 /* try to fetch tunable, if any */ 1125 if (TUNABLE_QUAD_FETCH(path, &priv->params_ethtool.arg[x])) 1126 mlx5e_ethtool_handler(NULL, priv, x, NULL); 1127 #endif 1128 } 1129 } 1130 1131 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO, 1132 "debug_stats", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 1133 0, &mlx5e_ethtool_debug_stats, "I", "Extended debug statistics"); 1134 1135 pnameunit = device_get_nameunit(priv->mdev->pdev->dev.bsddev); 1136 1137 SYSCTL_ADD_STRING(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), 1138 OID_AUTO, "device_name", CTLFLAG_RD, 1139 __DECONST(void *, pnameunit), 0, 1140 "PCI device name"); 1141 1142 /* Diagnostics support */ 1143 mlx5e_create_diagnostics(priv); 1144 1145 /* create qos node */ 1146 qos_node = SYSCTL_ADD_NODE(&priv->sysctl_ctx, 1147 SYSCTL_CHILDREN(node), OID_AUTO, 1148 "qos", CTLFLAG_RW, NULL, "Quality Of Service configuration"); 1149 if (qos_node == NULL) 1150 return; 1151 1152 /* Priority rate limit support */ 1153 if (mlx5e_getmaxrate(priv) == 0) { 1154 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1155 OID_AUTO, "tc_max_rate", CTLTYPE_U64 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1156 priv, 0, mlx5e_tc_maxrate_handler, "QU", 1157 "Max rate for priority, specified in kilobits, where kilo=1000, " 1158 "max_rate must be divisible by 100000"); 1159 } 1160 1161 /* Bandwidth limiting by ratio */ 1162 if (mlx5e_get_max_alloc(priv) == 0) { 1163 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1164 OID_AUTO, "tc_rate_share", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1165 priv, 0, mlx5e_tc_rate_share_handler, "QU", 1166 "Specify bandwidth ratio from 1 to 100 " 1167 "for the available traffic classes"); 1168 } 1169 1170 /* Priority to traffic class mapping */ 1171 if (mlx5e_get_prio_tc(priv) == 0) { 1172 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1173 OID_AUTO, "prio_0_7_tc", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1174 priv, 0, mlx5e_prio_to_tc_handler, "CU", 1175 "Set traffic class 0 to 7 for priority 0 to 7 inclusivly"); 1176 } 1177 1178 /* DSCP support */ 1179 if (mlx5e_get_dscp(priv) == 0) { 1180 for (i = 0; i != MLX5_MAX_SUPPORTED_DSCP; i += 8) { 1181 char name[32]; 1182 snprintf(name, sizeof(name), "dscp_%d_%d_prio", i, i + 7); 1183 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1184 OID_AUTO, name, CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1185 priv, i, mlx5e_dscp_prio_handler, "CU", 1186 "Set DSCP to priority mapping, 0..7"); 1187 } 1188 #define A "Set trust state, 1:PCP 2:DSCP" 1189 #define B " 3:BOTH" 1190 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1191 OID_AUTO, "trust_state", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1192 priv, 0, mlx5e_trust_state_handler, "CU", 1193 MLX5_CAP_QCAM_FEATURE(priv->mdev, qpts_trust_both) ? 1194 A B : A); 1195 #undef B 1196 #undef A 1197 } 1198 1199 if (mlx5e_port_query_buffer(priv, &port_buffer) == 0) { 1200 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1201 OID_AUTO, "buffers_size", 1202 CTLTYPE_U32 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1203 priv, 0, mlx5e_buf_size_handler, "IU", 1204 "Set buffers sizes"); 1205 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1206 OID_AUTO, "buffers_prio", 1207 CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1208 priv, 0, mlx5e_buf_prio_handler, "CU", 1209 "Set prio to buffers mapping"); 1210 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1211 OID_AUTO, "cable_length", 1212 CTLTYPE_UINT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1213 priv, 0, mlx5e_cable_length_handler, "IU", 1214 "Set cable length in meters for xoff threshold calculation"); 1215 } 1216 } 1217