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