mlx5_en_ethtool.c revision 353238
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: stable/11/sys/dev/mlx5/mlx5_en/mlx5_en_ethtool.c 353238 2019-10-07 09:42:57Z hselasky $ 26 */ 27 28#include "en.h" 29#include "port_buffer.h" 30#include <net/sff8472.h> 31 32void 33mlx5e_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 52static void 53mlx5e_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 88static int 89mlx5e_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 } 119done: 120 PRIV_UNLOCK(priv); 121 return (err); 122} 123 124static int 125mlx5e_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 147static int 148mlx5e_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; 166done: 167 PRIV_UNLOCK(priv); 168 return (err); 169} 170 171static void 172mlx5e_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 201static int 202mlx5e_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)); 239done: 240 PRIV_UNLOCK(priv); 241 return (err); 242} 243 244static int 245mlx5e_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)); 284done: 285 PRIV_UNLOCK(priv); 286 return (err); 287} 288 289static int 290mlx5e_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 311static int 312mlx5e_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 } 344done: 345 PRIV_UNLOCK(priv); 346 return (err); 347} 348 349static int 350mlx5e_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 390done: 391 PRIV_UNLOCK(priv); 392 return (err); 393} 394 395static int 396mlx5e_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)); 428done: 429 PRIV_UNLOCK(priv); 430 return (err); 431} 432 433int 434mlx5e_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 445static int 446mlx5e_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); 468done: 469 PRIV_UNLOCK(priv); 470 return (error); 471} 472 473static int 474mlx5e_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); 498done: 499 PRIV_UNLOCK(priv); 500 return (error); 501} 502 503static int 504mlx5e_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 529static int 530mlx5e_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 } 899done: 900 PRIV_UNLOCK(priv); 901 return (error); 902} 903 904/* 905 * Read the first three bytes of the eeprom in order to get the needed info 906 * for the whole reading. 907 * Byte 0 - Identifier byte 908 * Byte 1 - Revision byte 909 * Byte 2 - Status byte 910 */ 911static int 912mlx5e_get_eeprom_info(struct mlx5e_priv *priv, struct mlx5e_eeprom *eeprom) 913{ 914 struct mlx5_core_dev *dev = priv->mdev; 915 u32 data = 0; 916 int size_read = 0; 917 int ret; 918 919 ret = mlx5_query_module_num(dev, &eeprom->module_num); 920 if (ret) { 921 mlx5_en_err(priv->ifp, "Failed query module error=%d\n", 922 ret); 923 return (ret); 924 } 925 926 /* Read the first three bytes to get Identifier, Revision and Status */ 927 ret = mlx5_query_eeprom(dev, eeprom->i2c_addr, eeprom->page_num, 928 eeprom->device_addr, MLX5E_EEPROM_INFO_BYTES, eeprom->module_num, &data, 929 &size_read); 930 if (ret) { 931 mlx5_en_err(priv->ifp, 932 "Failed query eeprom module error=0x%x\n", ret); 933 return (ret); 934 } 935 936 switch (data & MLX5_EEPROM_IDENTIFIER_BYTE_MASK) { 937 case SFF_8024_ID_QSFP: 938 eeprom->type = MLX5E_ETH_MODULE_SFF_8436; 939 eeprom->len = MLX5E_ETH_MODULE_SFF_8436_LEN; 940 break; 941 case SFF_8024_ID_QSFPPLUS: 942 case SFF_8024_ID_QSFP28: 943 if ((data & MLX5_EEPROM_IDENTIFIER_BYTE_MASK) == SFF_8024_ID_QSFP28 || 944 ((data & MLX5_EEPROM_REVISION_ID_BYTE_MASK) >> 8) >= 0x3) { 945 eeprom->type = MLX5E_ETH_MODULE_SFF_8636; 946 eeprom->len = MLX5E_ETH_MODULE_SFF_8636_LEN; 947 } else { 948 eeprom->type = MLX5E_ETH_MODULE_SFF_8436; 949 eeprom->len = MLX5E_ETH_MODULE_SFF_8436_LEN; 950 } 951 if ((data & MLX5_EEPROM_PAGE_3_VALID_BIT_MASK) == 0) 952 eeprom->page_valid = 1; 953 break; 954 case SFF_8024_ID_SFP: 955 eeprom->type = MLX5E_ETH_MODULE_SFF_8472; 956 eeprom->len = MLX5E_ETH_MODULE_SFF_8472_LEN; 957 break; 958 default: 959 mlx5_en_err(priv->ifp, 960 "Not recognized cable type = 0x%x(%s)\n", 961 data & MLX5_EEPROM_IDENTIFIER_BYTE_MASK, 962 sff_8024_id[data & MLX5_EEPROM_IDENTIFIER_BYTE_MASK]); 963 return (EINVAL); 964 } 965 return (0); 966} 967 968/* Read both low and high pages of the eeprom */ 969static int 970mlx5e_get_eeprom(struct mlx5e_priv *priv, struct mlx5e_eeprom *ee) 971{ 972 struct mlx5_core_dev *dev = priv->mdev; 973 int size_read = 0; 974 int ret; 975 976 if (ee->len == 0) 977 return (EINVAL); 978 979 /* Read low page of the eeprom */ 980 while (ee->device_addr < ee->len) { 981 ret = mlx5_query_eeprom(dev, ee->i2c_addr, ee->page_num, ee->device_addr, 982 ee->len - ee->device_addr, ee->module_num, 983 ee->data + (ee->device_addr / 4), &size_read); 984 if (ret) { 985 mlx5_en_err(priv->ifp, 986 "Failed reading eeprom, error = 0x%02x\n",ret); 987 return (ret); 988 } 989 ee->device_addr += size_read; 990 } 991 992 /* Read high page of the eeprom */ 993 if (ee->page_valid) { 994 ee->device_addr = MLX5E_EEPROM_HIGH_PAGE_OFFSET; 995 ee->page_num = MLX5E_EEPROM_HIGH_PAGE; 996 size_read = 0; 997 while (ee->device_addr < MLX5E_EEPROM_PAGE_LENGTH) { 998 ret = mlx5_query_eeprom(dev, ee->i2c_addr, ee->page_num, 999 ee->device_addr, MLX5E_EEPROM_PAGE_LENGTH - ee->device_addr, 1000 ee->module_num, ee->data + (ee->len / 4) + 1001 ((ee->device_addr - MLX5E_EEPROM_HIGH_PAGE_OFFSET) / 4), 1002 &size_read); 1003 if (ret) { 1004 mlx5_en_err(priv->ifp, 1005 "Failed reading eeprom, error = 0x%02x\n", 1006 ret); 1007 return (ret); 1008 } 1009 ee->device_addr += size_read; 1010 } 1011 } 1012 return (0); 1013} 1014 1015static void 1016mlx5e_print_eeprom(struct mlx5e_eeprom *eeprom) 1017{ 1018 int row; 1019 int index_in_row; 1020 int byte_to_write = 0; 1021 int line_length = 16; 1022 1023 printf("\nOffset\t\tValues\n"); 1024 printf("------\t\t------"); 1025 while (byte_to_write < eeprom->len) { 1026 printf("\n0x%04X\t\t", byte_to_write); 1027 for (index_in_row = 0; index_in_row < line_length; index_in_row++) { 1028 printf("%02X ", ((u8 *)eeprom->data)[byte_to_write]); 1029 byte_to_write++; 1030 } 1031 } 1032 1033 if (eeprom->page_valid) { 1034 row = MLX5E_EEPROM_HIGH_PAGE_OFFSET; 1035 printf("\n\nUpper Page 0x03\n"); 1036 printf("\nOffset\t\tValues\n"); 1037 printf("------\t\t------"); 1038 while (row < MLX5E_EEPROM_PAGE_LENGTH) { 1039 printf("\n0x%04X\t\t", row); 1040 for (index_in_row = 0; index_in_row < line_length; index_in_row++) { 1041 printf("%02X ", ((u8 *)eeprom->data)[byte_to_write]); 1042 byte_to_write++; 1043 row++; 1044 } 1045 } 1046 } 1047} 1048 1049/* 1050 * Read cable EEPROM module information by first inspecting the first 1051 * three bytes to get the initial information for a whole reading. 1052 * Information will be printed to dmesg. 1053 */ 1054static int 1055mlx5e_read_eeprom(SYSCTL_HANDLER_ARGS) 1056{ 1057 struct mlx5e_priv *priv = arg1; 1058 struct mlx5e_eeprom eeprom; 1059 int error; 1060 int result = 0; 1061 1062 PRIV_LOCK(priv); 1063 error = sysctl_handle_int(oidp, &result, 0, req); 1064 if (error || !req->newptr) 1065 goto done; 1066 1067 /* Check if device is gone */ 1068 if (priv->gone) { 1069 error = ENXIO; 1070 goto done; 1071 } 1072 1073 if (result == 1) { 1074 eeprom.i2c_addr = MLX5E_I2C_ADDR_LOW; 1075 eeprom.device_addr = 0; 1076 eeprom.page_num = MLX5E_EEPROM_LOW_PAGE; 1077 eeprom.page_valid = 0; 1078 1079 /* Read three first bytes to get important info */ 1080 error = mlx5e_get_eeprom_info(priv, &eeprom); 1081 if (error) { 1082 mlx5_en_err(priv->ifp, 1083 "Failed reading eeprom's initial information\n"); 1084 error = 0; 1085 goto done; 1086 } 1087 /* 1088 * Allocate needed length buffer and additional space for 1089 * page 0x03 1090 */ 1091 eeprom.data = malloc(eeprom.len + MLX5E_EEPROM_PAGE_LENGTH, 1092 M_MLX5EN, M_WAITOK | M_ZERO); 1093 1094 /* Read the whole eeprom information */ 1095 error = mlx5e_get_eeprom(priv, &eeprom); 1096 if (error) { 1097 mlx5_en_err(priv->ifp, "Failed reading eeprom\n"); 1098 error = 0; 1099 /* 1100 * Continue printing partial information in case of 1101 * an error 1102 */ 1103 } 1104 mlx5e_print_eeprom(&eeprom); 1105 free(eeprom.data, M_MLX5EN); 1106 } 1107done: 1108 PRIV_UNLOCK(priv); 1109 return (error); 1110} 1111 1112static const char *mlx5e_params_desc[] = { 1113 MLX5E_PARAMS(MLX5E_STATS_DESC) 1114}; 1115 1116static const char *mlx5e_port_stats_debug_desc[] = { 1117 MLX5E_PORT_STATS_DEBUG(MLX5E_STATS_DESC) 1118}; 1119 1120static int 1121mlx5e_ethtool_debug_channel_info(SYSCTL_HANDLER_ARGS) 1122{ 1123 struct mlx5e_priv *priv; 1124 struct sbuf sb; 1125 struct mlx5e_channel *c; 1126 struct mlx5e_sq *sq; 1127 struct mlx5e_rq *rq; 1128 int error, i, tc; 1129 bool opened; 1130 1131 priv = arg1; 1132 error = sysctl_wire_old_buffer(req, 0); 1133 if (error != 0) 1134 return (error); 1135 if (sbuf_new_for_sysctl(&sb, NULL, 1024, req) == NULL) 1136 return (ENOMEM); 1137 sbuf_clear_flags(&sb, SBUF_INCLUDENUL); 1138 1139 PRIV_LOCK(priv); 1140 opened = test_bit(MLX5E_STATE_OPENED, &priv->state); 1141 1142 sbuf_printf(&sb, "pages irq %d\n", 1143 priv->mdev->priv.msix_arr[MLX5_EQ_VEC_PAGES].vector); 1144 sbuf_printf(&sb, "command irq %d\n", 1145 priv->mdev->priv.msix_arr[MLX5_EQ_VEC_CMD].vector); 1146 sbuf_printf(&sb, "async irq %d\n", 1147 priv->mdev->priv.msix_arr[MLX5_EQ_VEC_ASYNC].vector); 1148 1149 for (i = 0; i != priv->params.num_channels; i++) { 1150 int eqn_not_used = -1; 1151 int irqn = MLX5_EQ_VEC_COMP_BASE; 1152 1153 if (mlx5_vector2eqn(priv->mdev, i, &eqn_not_used, &irqn) != 0) 1154 continue; 1155 1156 c = opened ? &priv->channel[i] : NULL; 1157 rq = opened ? &c->rq : NULL; 1158 sbuf_printf(&sb, "channel %d rq %d cq %d irq %d\n", i, 1159 opened ? rq->rqn : -1, 1160 opened ? rq->cq.mcq.cqn : -1, 1161 priv->mdev->priv.msix_arr[irqn].vector); 1162 1163 for (tc = 0; tc != priv->num_tc; tc++) { 1164 sq = opened ? &c->sq[tc] : NULL; 1165 sbuf_printf(&sb, "channel %d tc %d sq %d cq %d irq %d\n", 1166 i, tc, 1167 opened ? sq->sqn : -1, 1168 opened ? sq->cq.mcq.cqn : -1, 1169 priv->mdev->priv.msix_arr[irqn].vector); 1170 } 1171 } 1172 PRIV_UNLOCK(priv); 1173 error = sbuf_finish(&sb); 1174 sbuf_delete(&sb); 1175 return (error); 1176} 1177 1178static int 1179mlx5e_ethtool_debug_stats(SYSCTL_HANDLER_ARGS) 1180{ 1181 struct mlx5e_priv *priv = arg1; 1182 int sys_debug; 1183 int error; 1184 1185 PRIV_LOCK(priv); 1186 if (priv->gone != 0) { 1187 error = ENODEV; 1188 goto done; 1189 } 1190 sys_debug = priv->sysctl_debug; 1191 error = sysctl_handle_int(oidp, &sys_debug, 0, req); 1192 if (error != 0 || !req->newptr) 1193 goto done; 1194 sys_debug = sys_debug ? 1 : 0; 1195 if (sys_debug == priv->sysctl_debug) 1196 goto done; 1197 1198 if ((priv->sysctl_debug = sys_debug)) { 1199 mlx5e_create_stats(&priv->stats.port_stats_debug.ctx, 1200 SYSCTL_CHILDREN(priv->sysctl_ifnet), "debug_stats", 1201 mlx5e_port_stats_debug_desc, MLX5E_PORT_STATS_DEBUG_NUM, 1202 priv->stats.port_stats_debug.arg); 1203 SYSCTL_ADD_PROC(&priv->stats.port_stats_debug.ctx, 1204 SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO, 1205 "hw_ctx_debug", 1206 CTLFLAG_RD | CTLFLAG_MPSAFE | CTLTYPE_STRING, priv, 0, 1207 mlx5e_ethtool_debug_channel_info, "S", ""); 1208 } else { 1209 sysctl_ctx_free(&priv->stats.port_stats_debug.ctx); 1210 } 1211done: 1212 PRIV_UNLOCK(priv); 1213 return (error); 1214} 1215 1216static void 1217mlx5e_create_diagnostics(struct mlx5e_priv *priv) 1218{ 1219 struct mlx5_core_diagnostics_entry entry; 1220 struct sysctl_ctx_list *ctx; 1221 struct sysctl_oid *node; 1222 int x; 1223 1224 /* sysctl context we are using */ 1225 ctx = &priv->sysctl_ctx; 1226 1227 /* create root node */ 1228 node = SYSCTL_ADD_NODE(ctx, 1229 SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO, 1230 "diagnostics", CTLFLAG_RD, NULL, "Diagnostics"); 1231 if (node == NULL) 1232 return; 1233 1234 /* create PCI diagnostics */ 1235 for (x = 0; x != MLX5_CORE_PCI_DIAGNOSTICS_NUM; x++) { 1236 entry = mlx5_core_pci_diagnostics_table[x]; 1237 if (mlx5_core_supports_diagnostics(priv->mdev, entry.counter_id) == 0) 1238 continue; 1239 SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO, 1240 entry.desc, CTLFLAG_RD, priv->params_pci.array + x, 1241 "PCI diagnostics counter"); 1242 } 1243 1244 /* create general diagnostics */ 1245 for (x = 0; x != MLX5_CORE_GENERAL_DIAGNOSTICS_NUM; x++) { 1246 entry = mlx5_core_general_diagnostics_table[x]; 1247 if (mlx5_core_supports_diagnostics(priv->mdev, entry.counter_id) == 0) 1248 continue; 1249 SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO, 1250 entry.desc, CTLFLAG_RD, priv->params_general.array + x, 1251 "General diagnostics counter"); 1252 } 1253} 1254 1255void 1256mlx5e_create_ethtool(struct mlx5e_priv *priv) 1257{ 1258 struct sysctl_oid *node, *qos_node; 1259 const char *pnameunit; 1260 struct mlx5e_port_buffer port_buffer; 1261 unsigned x; 1262 int i; 1263 1264 /* set some defaults */ 1265 priv->params_ethtool.tx_queue_size_max = 1 << MLX5E_PARAMS_MAXIMUM_LOG_SQ_SIZE; 1266 priv->params_ethtool.rx_queue_size_max = 1 << MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE; 1267 priv->params_ethtool.tx_queue_size = 1 << priv->params.log_sq_size; 1268 priv->params_ethtool.rx_queue_size = 1 << priv->params.log_rq_size; 1269 priv->params_ethtool.channels = priv->params.num_channels; 1270 priv->params_ethtool.channels_rsss = priv->params.channels_rsss; 1271 priv->params_ethtool.coalesce_pkts_max = MLX5E_FLD_MAX(cqc, cq_max_count); 1272 priv->params_ethtool.coalesce_usecs_max = MLX5E_FLD_MAX(cqc, cq_period); 1273 priv->params_ethtool.rx_coalesce_mode = priv->params.rx_cq_moderation_mode; 1274 priv->params_ethtool.rx_coalesce_usecs = priv->params.rx_cq_moderation_usec; 1275 priv->params_ethtool.rx_coalesce_pkts = priv->params.rx_cq_moderation_pkts; 1276 priv->params_ethtool.tx_coalesce_mode = priv->params.tx_cq_moderation_mode; 1277 priv->params_ethtool.tx_coalesce_usecs = priv->params.tx_cq_moderation_usec; 1278 priv->params_ethtool.tx_coalesce_pkts = priv->params.tx_cq_moderation_pkts; 1279 priv->params_ethtool.hw_lro = priv->params.hw_lro_en; 1280 priv->params_ethtool.cqe_zipping = priv->params.cqe_zipping_en; 1281 mlx5e_ethtool_sync_tx_completion_fact(priv); 1282 1283 /* get default values for local loopback, if any */ 1284 if (MLX5_CAP_GEN(priv->mdev, disable_local_lb)) { 1285 int err; 1286 u8 val; 1287 1288 err = mlx5_nic_vport_query_local_lb(priv->mdev, MLX5_LOCAL_MC_LB, &val); 1289 if (err == 0) 1290 priv->params_ethtool.mc_local_lb = val; 1291 1292 err = mlx5_nic_vport_query_local_lb(priv->mdev, MLX5_LOCAL_UC_LB, &val); 1293 if (err == 0) 1294 priv->params_ethtool.uc_local_lb = val; 1295 } 1296 1297 /* create root node */ 1298 node = SYSCTL_ADD_NODE(&priv->sysctl_ctx, 1299 SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO, 1300 "conf", CTLFLAG_RW, NULL, "Configuration"); 1301 if (node == NULL) 1302 return; 1303 for (x = 0; x != MLX5E_PARAMS_NUM; x++) { 1304 /* check for read-only parameter */ 1305 if (strstr(mlx5e_params_desc[2 * x], "_max") != NULL || 1306 strstr(mlx5e_params_desc[2 * x], "_mtu") != NULL) { 1307 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO, 1308 mlx5e_params_desc[2 * x], CTLTYPE_U64 | CTLFLAG_RD | 1309 CTLFLAG_MPSAFE, priv, x, &mlx5e_ethtool_handler, "QU", 1310 mlx5e_params_desc[2 * x + 1]); 1311 } else { 1312#if (__FreeBSD_version < 1100000) 1313 char path[64]; 1314#endif 1315 /* 1316 * NOTE: In FreeBSD-11 and newer the 1317 * CTLFLAG_RWTUN flag will take care of 1318 * loading default sysctl value from the 1319 * kernel environment, if any: 1320 */ 1321 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO, 1322 mlx5e_params_desc[2 * x], CTLTYPE_U64 | CTLFLAG_RWTUN | 1323 CTLFLAG_MPSAFE, priv, x, &mlx5e_ethtool_handler, "QU", 1324 mlx5e_params_desc[2 * x + 1]); 1325 1326#if (__FreeBSD_version < 1100000) 1327 /* compute path for sysctl */ 1328 snprintf(path, sizeof(path), "dev.mce.%d.conf.%s", 1329 device_get_unit(priv->mdev->pdev->dev.bsddev), 1330 mlx5e_params_desc[2 * x]); 1331 1332 /* try to fetch tunable, if any */ 1333 if (TUNABLE_QUAD_FETCH(path, &priv->params_ethtool.arg[x])) 1334 mlx5e_ethtool_handler(NULL, priv, x, NULL); 1335#endif 1336 } 1337 } 1338 1339 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO, 1340 "debug_stats", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 1341 0, &mlx5e_ethtool_debug_stats, "I", "Extended debug statistics"); 1342 1343 pnameunit = device_get_nameunit(priv->mdev->pdev->dev.bsddev); 1344 1345 SYSCTL_ADD_STRING(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), 1346 OID_AUTO, "device_name", CTLFLAG_RD, 1347 __DECONST(void *, pnameunit), 0, 1348 "PCI device name"); 1349 1350 /* EEPROM support */ 1351 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO, "eeprom_info", 1352 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 0, 1353 mlx5e_read_eeprom, "I", "EEPROM information"); 1354 1355 /* Diagnostics support */ 1356 mlx5e_create_diagnostics(priv); 1357 1358 /* create qos node */ 1359 qos_node = SYSCTL_ADD_NODE(&priv->sysctl_ctx, 1360 SYSCTL_CHILDREN(node), OID_AUTO, 1361 "qos", CTLFLAG_RW, NULL, "Quality Of Service configuration"); 1362 if (qos_node == NULL) 1363 return; 1364 1365 /* Priority rate limit support */ 1366 if (mlx5e_getmaxrate(priv) == 0) { 1367 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1368 OID_AUTO, "tc_max_rate", CTLTYPE_U64 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1369 priv, 0, mlx5e_tc_maxrate_handler, "QU", 1370 "Max rate for priority, specified in kilobits, where kilo=1000, " 1371 "max_rate must be divisible by 100000"); 1372 } 1373 1374 /* Bandwidth limiting by ratio */ 1375 if (mlx5e_get_max_alloc(priv) == 0) { 1376 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1377 OID_AUTO, "tc_rate_share", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1378 priv, 0, mlx5e_tc_rate_share_handler, "QU", 1379 "Specify bandwidth ratio from 1 to 100 " 1380 "for the available traffic classes"); 1381 } 1382 1383 /* Priority to traffic class mapping */ 1384 if (mlx5e_get_prio_tc(priv) == 0) { 1385 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1386 OID_AUTO, "prio_0_7_tc", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1387 priv, 0, mlx5e_prio_to_tc_handler, "CU", 1388 "Set traffic class 0 to 7 for priority 0 to 7 inclusivly"); 1389 } 1390 1391 /* DSCP support */ 1392 if (mlx5e_get_dscp(priv) == 0) { 1393 for (i = 0; i != MLX5_MAX_SUPPORTED_DSCP; i += 8) { 1394 char name[32]; 1395 snprintf(name, sizeof(name), "dscp_%d_%d_prio", i, i + 7); 1396 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1397 OID_AUTO, name, CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1398 priv, i, mlx5e_dscp_prio_handler, "CU", 1399 "Set DSCP to priority mapping, 0..7"); 1400 } 1401#define A "Set trust state, 1:PCP 2:DSCP" 1402#define B " 3:BOTH" 1403 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1404 OID_AUTO, "trust_state", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1405 priv, 0, mlx5e_trust_state_handler, "CU", 1406 MLX5_CAP_QCAM_FEATURE(priv->mdev, qpts_trust_both) ? 1407 A B : A); 1408#undef B 1409#undef A 1410 } 1411 1412 if (mlx5e_port_query_buffer(priv, &port_buffer) == 0) { 1413 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1414 OID_AUTO, "buffers_size", 1415 CTLTYPE_U32 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1416 priv, 0, mlx5e_buf_size_handler, "IU", 1417 "Set buffers sizes"); 1418 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1419 OID_AUTO, "buffers_prio", 1420 CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1421 priv, 0, mlx5e_buf_prio_handler, "CU", 1422 "Set prio to buffers mapping"); 1423 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node), 1424 OID_AUTO, "cable_length", 1425 CTLTYPE_UINT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1426 priv, 0, mlx5e_cable_length_handler, "IU", 1427 "Set cable length in meters for xoff threshold calculation"); 1428 } 1429} 1430