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: stable/10/sys/dev/mlx5/mlx5_en/mlx5_en_ethtool.c 341984 2018-12-12 13:14:41Z hselasky $ 26 */ 27 28#include "en.h" 29#include <net/sff8472.h> 30 31void 32mlx5e_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 51static void 52mlx5e_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#define MLX5_PARAM_OFFSET(n) \ 88 __offsetof(struct mlx5e_priv, params_ethtool.n) 89 90static int 91mlx5e_ethtool_handler(SYSCTL_HANDLER_ARGS) 92{ 93 struct mlx5e_priv *priv = arg1; 94 uint64_t value; 95 int mode_modify; 96 int was_opened; 97 int error; 98 99 PRIV_LOCK(priv); 100 value = priv->params_ethtool.arg[arg2]; 101 if (req != NULL) { 102 error = sysctl_handle_64(oidp, &value, 0, req); 103 if (error || req->newptr == NULL || 104 value == priv->params_ethtool.arg[arg2]) 105 goto done; 106 107 /* assign new value */ 108 priv->params_ethtool.arg[arg2] = value; 109 } else { 110 error = 0; 111 } 112 /* check if device is gone */ 113 if (priv->gone) { 114 error = ENXIO; 115 goto done; 116 } 117 was_opened = test_bit(MLX5E_STATE_OPENED, &priv->state); 118 mode_modify = MLX5_CAP_GEN(priv->mdev, cq_period_mode_modify); 119 120 switch (MLX5_PARAM_OFFSET(arg[arg2])) { 121 case MLX5_PARAM_OFFSET(rx_coalesce_usecs): 122 /* import RX coal time */ 123 if (priv->params_ethtool.rx_coalesce_usecs < 1) 124 priv->params_ethtool.rx_coalesce_usecs = 0; 125 else if (priv->params_ethtool.rx_coalesce_usecs > 126 MLX5E_FLD_MAX(cqc, cq_period)) { 127 priv->params_ethtool.rx_coalesce_usecs = 128 MLX5E_FLD_MAX(cqc, cq_period); 129 } 130 priv->params.rx_cq_moderation_usec = 131 priv->params_ethtool.rx_coalesce_usecs; 132 133 /* check to avoid down and up the network interface */ 134 if (was_opened) 135 error = mlx5e_refresh_channel_params(priv); 136 break; 137 138 case MLX5_PARAM_OFFSET(rx_coalesce_pkts): 139 /* import RX coal pkts */ 140 if (priv->params_ethtool.rx_coalesce_pkts < 1) 141 priv->params_ethtool.rx_coalesce_pkts = 0; 142 else if (priv->params_ethtool.rx_coalesce_pkts > 143 MLX5E_FLD_MAX(cqc, cq_max_count)) { 144 priv->params_ethtool.rx_coalesce_pkts = 145 MLX5E_FLD_MAX(cqc, cq_max_count); 146 } 147 priv->params.rx_cq_moderation_pkts = 148 priv->params_ethtool.rx_coalesce_pkts; 149 150 /* check to avoid down and up the network interface */ 151 if (was_opened) 152 error = mlx5e_refresh_channel_params(priv); 153 break; 154 155 case MLX5_PARAM_OFFSET(tx_coalesce_usecs): 156 /* import TX coal time */ 157 if (priv->params_ethtool.tx_coalesce_usecs < 1) 158 priv->params_ethtool.tx_coalesce_usecs = 0; 159 else if (priv->params_ethtool.tx_coalesce_usecs > 160 MLX5E_FLD_MAX(cqc, cq_period)) { 161 priv->params_ethtool.tx_coalesce_usecs = 162 MLX5E_FLD_MAX(cqc, cq_period); 163 } 164 priv->params.tx_cq_moderation_usec = 165 priv->params_ethtool.tx_coalesce_usecs; 166 167 /* check to avoid down and up the network interface */ 168 if (was_opened) 169 error = mlx5e_refresh_channel_params(priv); 170 break; 171 172 case MLX5_PARAM_OFFSET(tx_coalesce_pkts): 173 /* import TX coal pkts */ 174 if (priv->params_ethtool.tx_coalesce_pkts < 1) 175 priv->params_ethtool.tx_coalesce_pkts = 0; 176 else if (priv->params_ethtool.tx_coalesce_pkts > 177 MLX5E_FLD_MAX(cqc, cq_max_count)) { 178 priv->params_ethtool.tx_coalesce_pkts = 179 MLX5E_FLD_MAX(cqc, cq_max_count); 180 } 181 priv->params.tx_cq_moderation_pkts = 182 priv->params_ethtool.tx_coalesce_pkts; 183 184 /* check to avoid down and up the network interface */ 185 if (was_opened) 186 error = mlx5e_refresh_channel_params(priv); 187 break; 188 189 case MLX5_PARAM_OFFSET(tx_queue_size): 190 /* network interface must be down */ 191 if (was_opened) 192 mlx5e_close_locked(priv->ifp); 193 194 /* import TX queue size */ 195 if (priv->params_ethtool.tx_queue_size < 196 (1 << MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE)) { 197 priv->params_ethtool.tx_queue_size = 198 (1 << MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE); 199 } else if (priv->params_ethtool.tx_queue_size > 200 priv->params_ethtool.tx_queue_size_max) { 201 priv->params_ethtool.tx_queue_size = 202 priv->params_ethtool.tx_queue_size_max; 203 } 204 /* store actual TX queue size */ 205 priv->params.log_sq_size = 206 order_base_2(priv->params_ethtool.tx_queue_size); 207 priv->params_ethtool.tx_queue_size = 208 1 << priv->params.log_sq_size; 209 210 /* verify TX completion factor */ 211 mlx5e_ethtool_sync_tx_completion_fact(priv); 212 213 /* restart network interface, if any */ 214 if (was_opened) 215 mlx5e_open_locked(priv->ifp); 216 break; 217 218 case MLX5_PARAM_OFFSET(rx_queue_size): 219 /* network interface must be down */ 220 if (was_opened) 221 mlx5e_close_locked(priv->ifp); 222 223 /* import RX queue size */ 224 if (priv->params_ethtool.rx_queue_size < 225 (1 << MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE)) { 226 priv->params_ethtool.rx_queue_size = 227 (1 << MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE); 228 } else if (priv->params_ethtool.rx_queue_size > 229 priv->params_ethtool.rx_queue_size_max) { 230 priv->params_ethtool.rx_queue_size = 231 priv->params_ethtool.rx_queue_size_max; 232 } 233 /* store actual RX queue size */ 234 priv->params.log_rq_size = 235 order_base_2(priv->params_ethtool.rx_queue_size); 236 priv->params_ethtool.rx_queue_size = 237 1 << priv->params.log_rq_size; 238 239 /* update least number of RX WQEs */ 240 priv->params.min_rx_wqes = min( 241 priv->params_ethtool.rx_queue_size - 1, 242 MLX5E_PARAMS_DEFAULT_MIN_RX_WQES); 243 244 /* restart network interface, if any */ 245 if (was_opened) 246 mlx5e_open_locked(priv->ifp); 247 break; 248 249 case MLX5_PARAM_OFFSET(channels_rsss): 250 /* network interface must be down */ 251 if (was_opened) 252 mlx5e_close_locked(priv->ifp); 253 254 /* import number of channels */ 255 if (priv->params_ethtool.channels_rsss < 1) 256 priv->params_ethtool.channels_rsss = 1; 257 else if (priv->params_ethtool.channels_rsss > 128) 258 priv->params_ethtool.channels_rsss = 128; 259 260 priv->params.channels_rsss = priv->params_ethtool.channels_rsss; 261 262 /* restart network interface, if any */ 263 if (was_opened) 264 mlx5e_open_locked(priv->ifp); 265 break; 266 267 case MLX5_PARAM_OFFSET(channels): 268 /* network interface must be down */ 269 if (was_opened) 270 mlx5e_close_locked(priv->ifp); 271 272 /* import number of channels */ 273 if (priv->params_ethtool.channels < 1) 274 priv->params_ethtool.channels = 1; 275 else if (priv->params_ethtool.channels > 276 (u64) priv->mdev->priv.eq_table.num_comp_vectors) { 277 priv->params_ethtool.channels = 278 (u64) priv->mdev->priv.eq_table.num_comp_vectors; 279 } 280 priv->params.num_channels = priv->params_ethtool.channels; 281 282 /* restart network interface, if any */ 283 if (was_opened) 284 mlx5e_open_locked(priv->ifp); 285 break; 286 287 case MLX5_PARAM_OFFSET(rx_coalesce_mode): 288 /* network interface must be down */ 289 if (was_opened != 0 && mode_modify == 0) 290 mlx5e_close_locked(priv->ifp); 291 292 /* import RX coalesce mode */ 293 if (priv->params_ethtool.rx_coalesce_mode != 0) 294 priv->params_ethtool.rx_coalesce_mode = 1; 295 priv->params.rx_cq_moderation_mode = 296 priv->params_ethtool.rx_coalesce_mode; 297 298 /* restart network interface, if any */ 299 if (was_opened != 0) { 300 if (mode_modify == 0) 301 mlx5e_open_locked(priv->ifp); 302 else 303 error = mlx5e_refresh_channel_params(priv); 304 } 305 break; 306 307 case MLX5_PARAM_OFFSET(tx_coalesce_mode): 308 /* network interface must be down */ 309 if (was_opened != 0 && mode_modify == 0) 310 mlx5e_close_locked(priv->ifp); 311 312 /* import TX coalesce mode */ 313 if (priv->params_ethtool.tx_coalesce_mode != 0) 314 priv->params_ethtool.tx_coalesce_mode = 1; 315 priv->params.tx_cq_moderation_mode = 316 priv->params_ethtool.tx_coalesce_mode; 317 318 /* restart network interface, if any */ 319 if (was_opened != 0) { 320 if (mode_modify == 0) 321 mlx5e_open_locked(priv->ifp); 322 else 323 error = mlx5e_refresh_channel_params(priv); 324 } 325 break; 326 327 case MLX5_PARAM_OFFSET(hw_lro): 328 /* network interface must be down */ 329 if (was_opened) 330 mlx5e_close_locked(priv->ifp); 331 332 /* import HW LRO mode */ 333 if (priv->params_ethtool.hw_lro != 0 && 334 MLX5_CAP_ETH(priv->mdev, lro_cap)) { 335 priv->params_ethtool.hw_lro = 1; 336 /* check if feature should actually be enabled */ 337 if (priv->ifp->if_capenable & IFCAP_LRO) { 338 priv->params.hw_lro_en = true; 339 } else { 340 priv->params.hw_lro_en = false; 341 342 if_printf(priv->ifp, "To enable HW LRO " 343 "please also enable LRO via ifconfig(8).\n"); 344 } 345 } else { 346 /* return an error if HW does not support this feature */ 347 if (priv->params_ethtool.hw_lro != 0) 348 error = EINVAL; 349 priv->params.hw_lro_en = false; 350 priv->params_ethtool.hw_lro = 0; 351 } 352 /* restart network interface, if any */ 353 if (was_opened) 354 mlx5e_open_locked(priv->ifp); 355 break; 356 357 case MLX5_PARAM_OFFSET(cqe_zipping): 358 /* network interface must be down */ 359 if (was_opened) 360 mlx5e_close_locked(priv->ifp); 361 362 /* import CQE zipping mode */ 363 if (priv->params_ethtool.cqe_zipping && 364 MLX5_CAP_GEN(priv->mdev, cqe_compression)) { 365 priv->params.cqe_zipping_en = true; 366 priv->params_ethtool.cqe_zipping = 1; 367 } else { 368 priv->params.cqe_zipping_en = false; 369 priv->params_ethtool.cqe_zipping = 0; 370 } 371 /* restart network interface, if any */ 372 if (was_opened) 373 mlx5e_open_locked(priv->ifp); 374 break; 375 376 case MLX5_PARAM_OFFSET(tx_bufring_disable): 377 /* rangecheck input value */ 378 priv->params_ethtool.tx_bufring_disable = 379 priv->params_ethtool.tx_bufring_disable ? 1 : 0; 380 381 /* reconfigure the sendqueues, if any */ 382 if (was_opened) { 383 mlx5e_close_locked(priv->ifp); 384 mlx5e_open_locked(priv->ifp); 385 } 386 break; 387 388 case MLX5_PARAM_OFFSET(tx_completion_fact): 389 /* network interface must be down */ 390 if (was_opened) 391 mlx5e_close_locked(priv->ifp); 392 393 /* verify parameter */ 394 mlx5e_ethtool_sync_tx_completion_fact(priv); 395 396 /* restart network interface, if any */ 397 if (was_opened) 398 mlx5e_open_locked(priv->ifp); 399 break; 400 401 case MLX5_PARAM_OFFSET(diag_pci_enable): 402 priv->params_ethtool.diag_pci_enable = 403 priv->params_ethtool.diag_pci_enable ? 1 : 0; 404 405 error = -mlx5_core_set_diagnostics_full(priv->mdev, 406 priv->params_ethtool.diag_pci_enable, 407 priv->params_ethtool.diag_general_enable); 408 break; 409 410 case MLX5_PARAM_OFFSET(diag_general_enable): 411 priv->params_ethtool.diag_general_enable = 412 priv->params_ethtool.diag_general_enable ? 1 : 0; 413 414 error = -mlx5_core_set_diagnostics_full(priv->mdev, 415 priv->params_ethtool.diag_pci_enable, 416 priv->params_ethtool.diag_general_enable); 417 break; 418 419 default: 420 break; 421 } 422done: 423 PRIV_UNLOCK(priv); 424 return (error); 425} 426 427/* 428 * Read the first three bytes of the eeprom in order to get the needed info 429 * for the whole reading. 430 * Byte 0 - Identifier byte 431 * Byte 1 - Revision byte 432 * Byte 2 - Status byte 433 */ 434static int 435mlx5e_get_eeprom_info(struct mlx5e_priv *priv, struct mlx5e_eeprom *eeprom) 436{ 437 struct mlx5_core_dev *dev = priv->mdev; 438 u32 data = 0; 439 int size_read = 0; 440 int ret; 441 442 ret = mlx5_query_module_num(dev, &eeprom->module_num); 443 if (ret) { 444 if_printf(priv->ifp, "%s:%d: Failed query module error=%d\n", 445 __func__, __LINE__, ret); 446 return (ret); 447 } 448 449 /* Read the first three bytes to get Identifier, Revision and Status */ 450 ret = mlx5_query_eeprom(dev, eeprom->i2c_addr, eeprom->page_num, 451 eeprom->device_addr, MLX5E_EEPROM_INFO_BYTES, eeprom->module_num, &data, 452 &size_read); 453 if (ret) { 454 if_printf(priv->ifp, "%s:%d: Failed query eeprom module error=0x%x\n", 455 __func__, __LINE__, ret); 456 return (ret); 457 } 458 459 switch (data & MLX5_EEPROM_IDENTIFIER_BYTE_MASK) { 460 case SFF_8024_ID_QSFP: 461 eeprom->type = MLX5E_ETH_MODULE_SFF_8436; 462 eeprom->len = MLX5E_ETH_MODULE_SFF_8436_LEN; 463 break; 464 case SFF_8024_ID_QSFPPLUS: 465 case SFF_8024_ID_QSFP28: 466 if ((data & MLX5_EEPROM_IDENTIFIER_BYTE_MASK) == SFF_8024_ID_QSFP28 || 467 ((data & MLX5_EEPROM_REVISION_ID_BYTE_MASK) >> 8) >= 0x3) { 468 eeprom->type = MLX5E_ETH_MODULE_SFF_8636; 469 eeprom->len = MLX5E_ETH_MODULE_SFF_8636_LEN; 470 } else { 471 eeprom->type = MLX5E_ETH_MODULE_SFF_8436; 472 eeprom->len = MLX5E_ETH_MODULE_SFF_8436_LEN; 473 } 474 if ((data & MLX5_EEPROM_PAGE_3_VALID_BIT_MASK) == 0) 475 eeprom->page_valid = 1; 476 break; 477 case SFF_8024_ID_SFP: 478 eeprom->type = MLX5E_ETH_MODULE_SFF_8472; 479 eeprom->len = MLX5E_ETH_MODULE_SFF_8472_LEN; 480 break; 481 default: 482 if_printf(priv->ifp, "%s:%d: Not recognized cable type = 0x%x(%s)\n", 483 __func__, __LINE__, data & MLX5_EEPROM_IDENTIFIER_BYTE_MASK, 484 sff_8024_id[data & MLX5_EEPROM_IDENTIFIER_BYTE_MASK]); 485 return (EINVAL); 486 } 487 return (0); 488} 489 490/* Read both low and high pages of the eeprom */ 491static int 492mlx5e_get_eeprom(struct mlx5e_priv *priv, struct mlx5e_eeprom *ee) 493{ 494 struct mlx5_core_dev *dev = priv->mdev; 495 int size_read = 0; 496 int ret; 497 498 if (ee->len == 0) 499 return (EINVAL); 500 501 /* Read low page of the eeprom */ 502 while (ee->device_addr < ee->len) { 503 ret = mlx5_query_eeprom(dev, ee->i2c_addr, ee->page_num, ee->device_addr, 504 ee->len - ee->device_addr, ee->module_num, 505 ee->data + (ee->device_addr / 4), &size_read); 506 if (ret) { 507 if_printf(priv->ifp, "%s:%d: Failed reading eeprom, " 508 "error = 0x%02x\n", __func__, __LINE__, ret); 509 return (ret); 510 } 511 ee->device_addr += size_read; 512 } 513 514 /* Read high page of the eeprom */ 515 if (ee->page_valid) { 516 ee->device_addr = MLX5E_EEPROM_HIGH_PAGE_OFFSET; 517 ee->page_num = MLX5E_EEPROM_HIGH_PAGE; 518 size_read = 0; 519 while (ee->device_addr < MLX5E_EEPROM_PAGE_LENGTH) { 520 ret = mlx5_query_eeprom(dev, ee->i2c_addr, ee->page_num, 521 ee->device_addr, MLX5E_EEPROM_PAGE_LENGTH - ee->device_addr, 522 ee->module_num, ee->data + (ee->len / 4) + 523 ((ee->device_addr - MLX5E_EEPROM_HIGH_PAGE_OFFSET) / 4), 524 &size_read); 525 if (ret) { 526 if_printf(priv->ifp, "%s:%d: Failed reading eeprom, " 527 "error = 0x%02x\n", __func__, __LINE__, ret); 528 return (ret); 529 } 530 ee->device_addr += size_read; 531 } 532 } 533 return (0); 534} 535 536static void 537mlx5e_print_eeprom(struct mlx5e_eeprom *eeprom) 538{ 539 int row; 540 int index_in_row; 541 int byte_to_write = 0; 542 int line_length = 16; 543 544 printf("\nOffset\t\tValues\n"); 545 printf("------\t\t------"); 546 while (byte_to_write < eeprom->len) { 547 printf("\n0x%04X\t\t", byte_to_write); 548 for (index_in_row = 0; index_in_row < line_length; index_in_row++) { 549 printf("%02X ", ((u8 *)eeprom->data)[byte_to_write]); 550 byte_to_write++; 551 } 552 } 553 554 if (eeprom->page_valid) { 555 row = MLX5E_EEPROM_HIGH_PAGE_OFFSET; 556 printf("\n\nUpper Page 0x03\n"); 557 printf("\nOffset\t\tValues\n"); 558 printf("------\t\t------"); 559 while (row < MLX5E_EEPROM_PAGE_LENGTH) { 560 printf("\n0x%04X\t\t", row); 561 for (index_in_row = 0; index_in_row < line_length; index_in_row++) { 562 printf("%02X ", ((u8 *)eeprom->data)[byte_to_write]); 563 byte_to_write++; 564 row++; 565 } 566 } 567 } 568} 569 570/* 571 * Read cable EEPROM module information by first inspecting the first 572 * three bytes to get the initial information for a whole reading. 573 * Information will be printed to dmesg. 574 */ 575static int 576mlx5e_read_eeprom(SYSCTL_HANDLER_ARGS) 577{ 578 struct mlx5e_priv *priv = arg1; 579 struct mlx5e_eeprom eeprom; 580 int error; 581 int result = 0; 582 583 PRIV_LOCK(priv); 584 error = sysctl_handle_int(oidp, &result, 0, req); 585 if (error || !req->newptr) 586 goto done; 587 588 /* Check if device is gone */ 589 if (priv->gone) { 590 error = ENXIO; 591 goto done; 592 } 593 594 if (result == 1) { 595 eeprom.i2c_addr = MLX5E_I2C_ADDR_LOW; 596 eeprom.device_addr = 0; 597 eeprom.page_num = MLX5E_EEPROM_LOW_PAGE; 598 eeprom.page_valid = 0; 599 600 /* Read three first bytes to get important info */ 601 error = mlx5e_get_eeprom_info(priv, &eeprom); 602 if (error) { 603 if_printf(priv->ifp, "%s:%d: Failed reading eeprom's " 604 "initial information\n", __func__, __LINE__); 605 error = 0; 606 goto done; 607 } 608 /* 609 * Allocate needed length buffer and additional space for 610 * page 0x03 611 */ 612 eeprom.data = malloc(eeprom.len + MLX5E_EEPROM_PAGE_LENGTH, 613 M_MLX5EN, M_WAITOK | M_ZERO); 614 615 /* Read the whole eeprom information */ 616 error = mlx5e_get_eeprom(priv, &eeprom); 617 if (error) { 618 if_printf(priv->ifp, "%s:%d: Failed reading eeprom\n", 619 __func__, __LINE__); 620 error = 0; 621 /* 622 * Continue printing partial information in case of 623 * an error 624 */ 625 } 626 mlx5e_print_eeprom(&eeprom); 627 free(eeprom.data, M_MLX5EN); 628 } 629done: 630 PRIV_UNLOCK(priv); 631 return (error); 632} 633 634static const char *mlx5e_params_desc[] = { 635 MLX5E_PARAMS(MLX5E_STATS_DESC) 636}; 637 638static const char *mlx5e_port_stats_debug_desc[] = { 639 MLX5E_PORT_STATS_DEBUG(MLX5E_STATS_DESC) 640}; 641 642static int 643mlx5e_ethtool_debug_stats(SYSCTL_HANDLER_ARGS) 644{ 645 struct mlx5e_priv *priv = arg1; 646 int error; 647 int sys_debug; 648 649 sys_debug = priv->sysctl_debug; 650 error = sysctl_handle_int(oidp, &priv->sysctl_debug, 0, req); 651 if (error || !req->newptr) 652 return (error); 653 priv->sysctl_debug = !!priv->sysctl_debug; 654 if (sys_debug == priv->sysctl_debug) 655 return (error); 656 if (priv->sysctl_debug) 657 mlx5e_create_stats(&priv->stats.port_stats_debug.ctx, 658 SYSCTL_CHILDREN(priv->sysctl_ifnet), "debug_stats", 659 mlx5e_port_stats_debug_desc, MLX5E_PORT_STATS_DEBUG_NUM, 660 priv->stats.port_stats_debug.arg); 661 else 662 sysctl_ctx_free(&priv->stats.port_stats_debug.ctx); 663 return (error); 664} 665 666static void 667mlx5e_create_diagnostics(struct mlx5e_priv *priv) 668{ 669 struct mlx5_core_diagnostics_entry entry; 670 struct sysctl_ctx_list *ctx; 671 struct sysctl_oid *node; 672 int x; 673 674 /* sysctl context we are using */ 675 ctx = &priv->sysctl_ctx; 676 677 /* create root node */ 678 node = SYSCTL_ADD_NODE(ctx, 679 SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO, 680 "diagnostics", CTLFLAG_RD, NULL, "Diagnostics"); 681 if (node == NULL) 682 return; 683 684 /* create PCI diagnostics */ 685 for (x = 0; x != MLX5_CORE_PCI_DIAGNOSTICS_NUM; x++) { 686 entry = mlx5_core_pci_diagnostics_table[x]; 687 if (mlx5_core_supports_diagnostics(priv->mdev, entry.counter_id) == 0) 688 continue; 689 SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO, 690 entry.desc, CTLFLAG_RD, priv->params_pci.array + x, 691 "PCI diagnostics counter"); 692 } 693 694 /* create general diagnostics */ 695 for (x = 0; x != MLX5_CORE_GENERAL_DIAGNOSTICS_NUM; x++) { 696 entry = mlx5_core_general_diagnostics_table[x]; 697 if (mlx5_core_supports_diagnostics(priv->mdev, entry.counter_id) == 0) 698 continue; 699 SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO, 700 entry.desc, CTLFLAG_RD, priv->params_general.array + x, 701 "General diagnostics counter"); 702 } 703} 704 705void 706mlx5e_create_ethtool(struct mlx5e_priv *priv) 707{ 708 struct sysctl_oid *node; 709 const char *pnameunit; 710 unsigned x; 711 712 /* set some defaults */ 713 priv->params_ethtool.tx_queue_size_max = 1 << MLX5E_PARAMS_MAXIMUM_LOG_SQ_SIZE; 714 priv->params_ethtool.rx_queue_size_max = 1 << MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE; 715 priv->params_ethtool.tx_queue_size = 1 << priv->params.log_sq_size; 716 priv->params_ethtool.rx_queue_size = 1 << priv->params.log_rq_size; 717 priv->params_ethtool.channels = priv->params.num_channels; 718 priv->params_ethtool.channels_rsss = priv->params.channels_rsss; 719 priv->params_ethtool.coalesce_pkts_max = MLX5E_FLD_MAX(cqc, cq_max_count); 720 priv->params_ethtool.coalesce_usecs_max = MLX5E_FLD_MAX(cqc, cq_period); 721 priv->params_ethtool.rx_coalesce_mode = priv->params.rx_cq_moderation_mode; 722 priv->params_ethtool.rx_coalesce_usecs = priv->params.rx_cq_moderation_usec; 723 priv->params_ethtool.rx_coalesce_pkts = priv->params.rx_cq_moderation_pkts; 724 priv->params_ethtool.tx_coalesce_mode = priv->params.tx_cq_moderation_mode; 725 priv->params_ethtool.tx_coalesce_usecs = priv->params.tx_cq_moderation_usec; 726 priv->params_ethtool.tx_coalesce_pkts = priv->params.tx_cq_moderation_pkts; 727 priv->params_ethtool.hw_lro = priv->params.hw_lro_en; 728 priv->params_ethtool.cqe_zipping = priv->params.cqe_zipping_en; 729 mlx5e_ethtool_sync_tx_completion_fact(priv); 730 731 /* create root node */ 732 node = SYSCTL_ADD_NODE(&priv->sysctl_ctx, 733 SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO, 734 "conf", CTLFLAG_RW, NULL, "Configuration"); 735 if (node == NULL) 736 return; 737 for (x = 0; x != MLX5E_PARAMS_NUM; x++) { 738 /* check for read-only parameter */ 739 if (strstr(mlx5e_params_desc[2 * x], "_max") != NULL || 740 strstr(mlx5e_params_desc[2 * x], "_mtu") != NULL) { 741 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO, 742 mlx5e_params_desc[2 * x], CTLTYPE_U64 | CTLFLAG_RD | 743 CTLFLAG_MPSAFE, priv, x, &mlx5e_ethtool_handler, "QU", 744 mlx5e_params_desc[2 * x + 1]); 745 } else { 746#if (__FreeBSD_version < 1100000) 747 char path[64]; 748#endif 749 /* 750 * NOTE: In FreeBSD-11 and newer the 751 * CTLFLAG_RWTUN flag will take care of 752 * loading default sysctl value from the 753 * kernel environment, if any: 754 */ 755 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO, 756 mlx5e_params_desc[2 * x], CTLTYPE_U64 | CTLFLAG_RWTUN | 757 CTLFLAG_MPSAFE, priv, x, &mlx5e_ethtool_handler, "QU", 758 mlx5e_params_desc[2 * x + 1]); 759 760#if (__FreeBSD_version < 1100000) 761 /* compute path for sysctl */ 762 snprintf(path, sizeof(path), "dev.mce.%d.conf.%s", 763 device_get_unit(priv->mdev->pdev->dev.bsddev), 764 mlx5e_params_desc[2 * x]); 765 766 /* try to fetch tunable, if any */ 767 if (TUNABLE_QUAD_FETCH(path, &priv->params_ethtool.arg[x])) 768 mlx5e_ethtool_handler(NULL, priv, x, NULL); 769#endif 770 } 771 } 772 773 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO, 774 "debug_stats", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 775 0, &mlx5e_ethtool_debug_stats, "I", "Extended debug statistics"); 776 777 pnameunit = device_get_nameunit(priv->mdev->pdev->dev.bsddev); 778 779 SYSCTL_ADD_STRING(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), 780 OID_AUTO, "device_name", CTLFLAG_RD, 781 __DECONST(void *, pnameunit), 0, 782 "PCI device name"); 783 784 /* EEPROM support */ 785 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO, "eeprom_info", 786 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 0, 787 mlx5e_read_eeprom, "I", "EEPROM information"); 788 789 /* Diagnostics support */ 790 mlx5e_create_diagnostics(priv); 791} 792