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 #define MLX5_PARAM_OFFSET(n) \ 88 __offsetof(struct mlx5e_priv, params_ethtool.n) 89 90 static int 91 mlx5e_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): 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 < 1) 256 priv->params_ethtool.channels = 1; 257 else if (priv->params_ethtool.channels > 258 (u64) priv->mdev->priv.eq_table.num_comp_vectors) { 259 priv->params_ethtool.channels = 260 (u64) priv->mdev->priv.eq_table.num_comp_vectors; 261 } 262 priv->params.num_channels = priv->params_ethtool.channels; 263 264 /* restart network interface, if any */ 265 if (was_opened) 266 mlx5e_open_locked(priv->ifp); 267 break; 268 269 case MLX5_PARAM_OFFSET(rx_coalesce_mode): 270 /* network interface must be down */ 271 if (was_opened != 0 && mode_modify == 0) 272 mlx5e_close_locked(priv->ifp); 273 274 /* import RX coalesce mode */ 275 if (priv->params_ethtool.rx_coalesce_mode != 0) 276 priv->params_ethtool.rx_coalesce_mode = 1; 277 priv->params.rx_cq_moderation_mode = 278 priv->params_ethtool.rx_coalesce_mode; 279 280 /* restart network interface, if any */ 281 if (was_opened != 0) { 282 if (mode_modify == 0) 283 mlx5e_open_locked(priv->ifp); 284 else 285 error = mlx5e_refresh_channel_params(priv); 286 } 287 break; 288 289 case MLX5_PARAM_OFFSET(tx_coalesce_mode): 290 /* network interface must be down */ 291 if (was_opened != 0 && mode_modify == 0) 292 mlx5e_close_locked(priv->ifp); 293 294 /* import TX coalesce mode */ 295 if (priv->params_ethtool.tx_coalesce_mode != 0) 296 priv->params_ethtool.tx_coalesce_mode = 1; 297 priv->params.tx_cq_moderation_mode = 298 priv->params_ethtool.tx_coalesce_mode; 299 300 /* restart network interface, if any */ 301 if (was_opened != 0) { 302 if (mode_modify == 0) 303 mlx5e_open_locked(priv->ifp); 304 else 305 error = mlx5e_refresh_channel_params(priv); 306 } 307 break; 308 309 case MLX5_PARAM_OFFSET(hw_lro): 310 /* network interface must be down */ 311 if (was_opened) 312 mlx5e_close_locked(priv->ifp); 313 314 /* import HW LRO mode */ 315 if (priv->params_ethtool.hw_lro != 0) { 316 if ((priv->ifp->if_capenable & IFCAP_LRO) && 317 MLX5_CAP_ETH(priv->mdev, lro_cap)) { 318 priv->params.hw_lro_en = 1; 319 priv->params_ethtool.hw_lro = 1; 320 } else { 321 priv->params.hw_lro_en = 0; 322 priv->params_ethtool.hw_lro = 0; 323 error = EINVAL; 324 325 if_printf(priv->ifp, "Can't enable HW LRO: " 326 "The HW or SW LRO feature is disabled\n"); 327 } 328 } else { 329 priv->params.hw_lro_en = 0; 330 } 331 /* restart network interface, if any */ 332 if (was_opened) 333 mlx5e_open_locked(priv->ifp); 334 break; 335 336 case MLX5_PARAM_OFFSET(cqe_zipping): 337 /* network interface must be down */ 338 if (was_opened) 339 mlx5e_close_locked(priv->ifp); 340 341 /* import CQE zipping mode */ 342 if (priv->params_ethtool.cqe_zipping && 343 MLX5_CAP_GEN(priv->mdev, cqe_compression)) { 344 priv->params.cqe_zipping_en = true; 345 priv->params_ethtool.cqe_zipping = 1; 346 } else { 347 priv->params.cqe_zipping_en = false; 348 priv->params_ethtool.cqe_zipping = 0; 349 } 350 /* restart network interface, if any */ 351 if (was_opened) 352 mlx5e_open_locked(priv->ifp); 353 break; 354 355 case MLX5_PARAM_OFFSET(tx_bufring_disable): 356 /* rangecheck input value */ 357 priv->params_ethtool.tx_bufring_disable = 358 priv->params_ethtool.tx_bufring_disable ? 1 : 0; 359 360 /* reconfigure the sendqueues, if any */ 361 if (was_opened) { 362 mlx5e_close_locked(priv->ifp); 363 mlx5e_open_locked(priv->ifp); 364 } 365 break; 366 367 case MLX5_PARAM_OFFSET(tx_completion_fact): 368 /* network interface must be down */ 369 if (was_opened) 370 mlx5e_close_locked(priv->ifp); 371 372 /* verify parameter */ 373 mlx5e_ethtool_sync_tx_completion_fact(priv); 374 375 /* restart network interface, if any */ 376 if (was_opened) 377 mlx5e_open_locked(priv->ifp); 378 break; 379 380 case MLX5_PARAM_OFFSET(modify_tx_dma): 381 /* check if network interface is opened */ 382 if (was_opened) { 383 priv->params_ethtool.modify_tx_dma = 384 priv->params_ethtool.modify_tx_dma ? 1 : 0; 385 /* modify tx according to value */ 386 mlx5e_modify_tx_dma(priv, value != 0); 387 } else { 388 /* if closed force enable tx */ 389 priv->params_ethtool.modify_tx_dma = 0; 390 } 391 break; 392 393 case MLX5_PARAM_OFFSET(modify_rx_dma): 394 /* check if network interface is opened */ 395 if (was_opened) { 396 priv->params_ethtool.modify_rx_dma = 397 priv->params_ethtool.modify_rx_dma ? 1 : 0; 398 /* modify rx according to value */ 399 mlx5e_modify_rx_dma(priv, value != 0); 400 } else { 401 /* if closed force enable rx */ 402 priv->params_ethtool.modify_rx_dma = 0; 403 } 404 break; 405 406 case MLX5_PARAM_OFFSET(diag_pci_enable): 407 priv->params_ethtool.diag_pci_enable = 408 priv->params_ethtool.diag_pci_enable ? 1 : 0; 409 410 error = -mlx5_core_set_diagnostics_full(priv->mdev, 411 priv->params_ethtool.diag_pci_enable, 412 priv->params_ethtool.diag_general_enable); 413 break; 414 415 case MLX5_PARAM_OFFSET(diag_general_enable): 416 priv->params_ethtool.diag_general_enable = 417 priv->params_ethtool.diag_general_enable ? 1 : 0; 418 419 error = -mlx5_core_set_diagnostics_full(priv->mdev, 420 priv->params_ethtool.diag_pci_enable, 421 priv->params_ethtool.diag_general_enable); 422 break; 423 424 case MLX5_PARAM_OFFSET(mc_local_lb): 425 priv->params_ethtool.mc_local_lb = 426 priv->params_ethtool.mc_local_lb ? 1 : 0; 427 428 if (MLX5_CAP_GEN(priv->mdev, disable_local_lb)) { 429 error = mlx5_nic_vport_modify_local_lb(priv->mdev, 430 MLX5_LOCAL_MC_LB, priv->params_ethtool.mc_local_lb); 431 } else { 432 error = EOPNOTSUPP; 433 } 434 break; 435 436 case MLX5_PARAM_OFFSET(uc_local_lb): 437 priv->params_ethtool.uc_local_lb = 438 priv->params_ethtool.uc_local_lb ? 1 : 0; 439 440 if (MLX5_CAP_GEN(priv->mdev, disable_local_lb)) { 441 error = mlx5_nic_vport_modify_local_lb(priv->mdev, 442 MLX5_LOCAL_UC_LB, priv->params_ethtool.uc_local_lb); 443 } else { 444 error = EOPNOTSUPP; 445 } 446 break; 447 448 default: 449 break; 450 } 451 done: 452 PRIV_UNLOCK(priv); 453 return (error); 454 } 455 456 /* 457 * Read the first three bytes of the eeprom in order to get the needed info 458 * for the whole reading. 459 * Byte 0 - Identifier byte 460 * Byte 1 - Revision byte 461 * Byte 2 - Status byte 462 */ 463 static int 464 mlx5e_get_eeprom_info(struct mlx5e_priv *priv, struct mlx5e_eeprom *eeprom) 465 { 466 struct mlx5_core_dev *dev = priv->mdev; 467 u32 data = 0; 468 int size_read = 0; 469 int ret; 470 471 ret = mlx5_query_module_num(dev, &eeprom->module_num); 472 if (ret) { 473 if_printf(priv->ifp, "%s:%d: Failed query module error=%d\n", 474 __func__, __LINE__, ret); 475 return (ret); 476 } 477 478 /* Read the first three bytes to get Identifier, Revision and Status */ 479 ret = mlx5_query_eeprom(dev, eeprom->i2c_addr, eeprom->page_num, 480 eeprom->device_addr, MLX5E_EEPROM_INFO_BYTES, eeprom->module_num, &data, 481 &size_read); 482 if (ret) { 483 if_printf(priv->ifp, "%s:%d: Failed query eeprom module error=0x%x\n", 484 __func__, __LINE__, ret); 485 return (ret); 486 } 487 488 switch (data & MLX5_EEPROM_IDENTIFIER_BYTE_MASK) { 489 case SFF_8024_ID_QSFP: 490 eeprom->type = MLX5E_ETH_MODULE_SFF_8436; 491 eeprom->len = MLX5E_ETH_MODULE_SFF_8436_LEN; 492 break; 493 case SFF_8024_ID_QSFPPLUS: 494 case SFF_8024_ID_QSFP28: 495 if ((data & MLX5_EEPROM_IDENTIFIER_BYTE_MASK) == SFF_8024_ID_QSFP28 || 496 ((data & MLX5_EEPROM_REVISION_ID_BYTE_MASK) >> 8) >= 0x3) { 497 eeprom->type = MLX5E_ETH_MODULE_SFF_8636; 498 eeprom->len = MLX5E_ETH_MODULE_SFF_8636_LEN; 499 } else { 500 eeprom->type = MLX5E_ETH_MODULE_SFF_8436; 501 eeprom->len = MLX5E_ETH_MODULE_SFF_8436_LEN; 502 } 503 if ((data & MLX5_EEPROM_PAGE_3_VALID_BIT_MASK) == 0) 504 eeprom->page_valid = 1; 505 break; 506 case SFF_8024_ID_SFP: 507 eeprom->type = MLX5E_ETH_MODULE_SFF_8472; 508 eeprom->len = MLX5E_ETH_MODULE_SFF_8472_LEN; 509 break; 510 default: 511 if_printf(priv->ifp, "%s:%d: Not recognized cable type = 0x%x(%s)\n", 512 __func__, __LINE__, data & MLX5_EEPROM_IDENTIFIER_BYTE_MASK, 513 sff_8024_id[data & MLX5_EEPROM_IDENTIFIER_BYTE_MASK]); 514 return (EINVAL); 515 } 516 return (0); 517 } 518 519 /* Read both low and high pages of the eeprom */ 520 static int 521 mlx5e_get_eeprom(struct mlx5e_priv *priv, struct mlx5e_eeprom *ee) 522 { 523 struct mlx5_core_dev *dev = priv->mdev; 524 int size_read = 0; 525 int ret; 526 527 if (ee->len == 0) 528 return (EINVAL); 529 530 /* Read low page of the eeprom */ 531 while (ee->device_addr < ee->len) { 532 ret = mlx5_query_eeprom(dev, ee->i2c_addr, ee->page_num, ee->device_addr, 533 ee->len - ee->device_addr, ee->module_num, 534 ee->data + (ee->device_addr / 4), &size_read); 535 if (ret) { 536 if_printf(priv->ifp, "%s:%d: Failed reading eeprom, " 537 "error = 0x%02x\n", __func__, __LINE__, ret); 538 return (ret); 539 } 540 ee->device_addr += size_read; 541 } 542 543 /* Read high page of the eeprom */ 544 if (ee->page_valid) { 545 ee->device_addr = MLX5E_EEPROM_HIGH_PAGE_OFFSET; 546 ee->page_num = MLX5E_EEPROM_HIGH_PAGE; 547 size_read = 0; 548 while (ee->device_addr < MLX5E_EEPROM_PAGE_LENGTH) { 549 ret = mlx5_query_eeprom(dev, ee->i2c_addr, ee->page_num, 550 ee->device_addr, MLX5E_EEPROM_PAGE_LENGTH - ee->device_addr, 551 ee->module_num, ee->data + (ee->len / 4) + 552 ((ee->device_addr - MLX5E_EEPROM_HIGH_PAGE_OFFSET) / 4), 553 &size_read); 554 if (ret) { 555 if_printf(priv->ifp, "%s:%d: Failed reading eeprom, " 556 "error = 0x%02x\n", __func__, __LINE__, ret); 557 return (ret); 558 } 559 ee->device_addr += size_read; 560 } 561 } 562 return (0); 563 } 564 565 static void 566 mlx5e_print_eeprom(struct mlx5e_eeprom *eeprom) 567 { 568 int row; 569 int index_in_row; 570 int byte_to_write = 0; 571 int line_length = 16; 572 573 printf("\nOffset\t\tValues\n"); 574 printf("------\t\t------"); 575 while (byte_to_write < eeprom->len) { 576 printf("\n0x%04X\t\t", byte_to_write); 577 for (index_in_row = 0; index_in_row < line_length; index_in_row++) { 578 printf("%02X ", ((u8 *)eeprom->data)[byte_to_write]); 579 byte_to_write++; 580 } 581 } 582 583 if (eeprom->page_valid) { 584 row = MLX5E_EEPROM_HIGH_PAGE_OFFSET; 585 printf("\n\nUpper Page 0x03\n"); 586 printf("\nOffset\t\tValues\n"); 587 printf("------\t\t------"); 588 while (row < MLX5E_EEPROM_PAGE_LENGTH) { 589 printf("\n0x%04X\t\t", row); 590 for (index_in_row = 0; index_in_row < line_length; index_in_row++) { 591 printf("%02X ", ((u8 *)eeprom->data)[byte_to_write]); 592 byte_to_write++; 593 row++; 594 } 595 } 596 } 597 } 598 599 /* 600 * Read cable EEPROM module information by first inspecting the first 601 * three bytes to get the initial information for a whole reading. 602 * Information will be printed to dmesg. 603 */ 604 static int 605 mlx5e_read_eeprom(SYSCTL_HANDLER_ARGS) 606 { 607 struct mlx5e_priv *priv = arg1; 608 struct mlx5e_eeprom eeprom; 609 int error; 610 int result = 0; 611 612 PRIV_LOCK(priv); 613 error = sysctl_handle_int(oidp, &result, 0, req); 614 if (error || !req->newptr) 615 goto done; 616 617 /* Check if device is gone */ 618 if (priv->gone) { 619 error = ENXIO; 620 goto done; 621 } 622 623 if (result == 1) { 624 eeprom.i2c_addr = MLX5E_I2C_ADDR_LOW; 625 eeprom.device_addr = 0; 626 eeprom.page_num = MLX5E_EEPROM_LOW_PAGE; 627 eeprom.page_valid = 0; 628 629 /* Read three first bytes to get important info */ 630 error = mlx5e_get_eeprom_info(priv, &eeprom); 631 if (error) { 632 if_printf(priv->ifp, "%s:%d: Failed reading eeprom's " 633 "initial information\n", __func__, __LINE__); 634 error = 0; 635 goto done; 636 } 637 /* 638 * Allocate needed length buffer and additional space for 639 * page 0x03 640 */ 641 eeprom.data = malloc(eeprom.len + MLX5E_EEPROM_PAGE_LENGTH, 642 M_MLX5EN, M_WAITOK | M_ZERO); 643 644 /* Read the whole eeprom information */ 645 error = mlx5e_get_eeprom(priv, &eeprom); 646 if (error) { 647 if_printf(priv->ifp, "%s:%d: Failed reading eeprom\n", 648 __func__, __LINE__); 649 error = 0; 650 /* 651 * Continue printing partial information in case of 652 * an error 653 */ 654 } 655 mlx5e_print_eeprom(&eeprom); 656 free(eeprom.data, M_MLX5EN); 657 } 658 done: 659 PRIV_UNLOCK(priv); 660 return (error); 661 } 662 663 static const char *mlx5e_params_desc[] = { 664 MLX5E_PARAMS(MLX5E_STATS_DESC) 665 }; 666 667 static const char *mlx5e_port_stats_debug_desc[] = { 668 MLX5E_PORT_STATS_DEBUG(MLX5E_STATS_DESC) 669 }; 670 671 static int 672 mlx5e_ethtool_debug_stats(SYSCTL_HANDLER_ARGS) 673 { 674 struct mlx5e_priv *priv = arg1; 675 int error; 676 int sys_debug; 677 678 sys_debug = priv->sysctl_debug; 679 error = sysctl_handle_int(oidp, &priv->sysctl_debug, 0, req); 680 if (error || !req->newptr) 681 return (error); 682 priv->sysctl_debug = !!priv->sysctl_debug; 683 if (sys_debug == priv->sysctl_debug) 684 return (error); 685 if (priv->sysctl_debug) 686 mlx5e_create_stats(&priv->stats.port_stats_debug.ctx, 687 SYSCTL_CHILDREN(priv->sysctl_ifnet), "debug_stats", 688 mlx5e_port_stats_debug_desc, MLX5E_PORT_STATS_DEBUG_NUM, 689 priv->stats.port_stats_debug.arg); 690 else 691 sysctl_ctx_free(&priv->stats.port_stats_debug.ctx); 692 return (error); 693 } 694 695 static void 696 mlx5e_create_diagnostics(struct mlx5e_priv *priv) 697 { 698 struct mlx5_core_diagnostics_entry entry; 699 struct sysctl_ctx_list *ctx; 700 struct sysctl_oid *node; 701 int x; 702 703 /* sysctl context we are using */ 704 ctx = &priv->sysctl_ctx; 705 706 /* create root node */ 707 node = SYSCTL_ADD_NODE(ctx, 708 SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO, 709 "diagnostics", CTLFLAG_RD, NULL, "Diagnostics"); 710 if (node == NULL) 711 return; 712 713 /* create PCI diagnostics */ 714 for (x = 0; x != MLX5_CORE_PCI_DIAGNOSTICS_NUM; x++) { 715 entry = mlx5_core_pci_diagnostics_table[x]; 716 if (mlx5_core_supports_diagnostics(priv->mdev, entry.counter_id) == 0) 717 continue; 718 SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO, 719 entry.desc, CTLFLAG_RD, priv->params_pci.array + x, 720 "PCI diagnostics counter"); 721 } 722 723 /* create general diagnostics */ 724 for (x = 0; x != MLX5_CORE_GENERAL_DIAGNOSTICS_NUM; x++) { 725 entry = mlx5_core_general_diagnostics_table[x]; 726 if (mlx5_core_supports_diagnostics(priv->mdev, entry.counter_id) == 0) 727 continue; 728 SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO, 729 entry.desc, CTLFLAG_RD, priv->params_general.array + x, 730 "General diagnostics counter"); 731 } 732 } 733 734 void 735 mlx5e_create_ethtool(struct mlx5e_priv *priv) 736 { 737 struct sysctl_oid *node; 738 const char *pnameunit; 739 unsigned x; 740 741 /* set some defaults */ 742 priv->params_ethtool.tx_queue_size_max = 1 << MLX5E_PARAMS_MAXIMUM_LOG_SQ_SIZE; 743 priv->params_ethtool.rx_queue_size_max = 1 << MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE; 744 priv->params_ethtool.tx_queue_size = 1 << priv->params.log_sq_size; 745 priv->params_ethtool.rx_queue_size = 1 << priv->params.log_rq_size; 746 priv->params_ethtool.channels = priv->params.num_channels; 747 priv->params_ethtool.coalesce_pkts_max = MLX5E_FLD_MAX(cqc, cq_max_count); 748 priv->params_ethtool.coalesce_usecs_max = MLX5E_FLD_MAX(cqc, cq_period); 749 priv->params_ethtool.rx_coalesce_mode = priv->params.rx_cq_moderation_mode; 750 priv->params_ethtool.rx_coalesce_usecs = priv->params.rx_cq_moderation_usec; 751 priv->params_ethtool.rx_coalesce_pkts = priv->params.rx_cq_moderation_pkts; 752 priv->params_ethtool.tx_coalesce_mode = priv->params.tx_cq_moderation_mode; 753 priv->params_ethtool.tx_coalesce_usecs = priv->params.tx_cq_moderation_usec; 754 priv->params_ethtool.tx_coalesce_pkts = priv->params.tx_cq_moderation_pkts; 755 priv->params_ethtool.hw_lro = priv->params.hw_lro_en; 756 priv->params_ethtool.cqe_zipping = priv->params.cqe_zipping_en; 757 mlx5e_ethtool_sync_tx_completion_fact(priv); 758 759 /* get default values for local loopback, if any */ 760 if (MLX5_CAP_GEN(priv->mdev, disable_local_lb)) { 761 int err; 762 u8 val; 763 764 err = mlx5_nic_vport_query_local_lb(priv->mdev, MLX5_LOCAL_MC_LB, &val); 765 if (err == 0) 766 priv->params_ethtool.mc_local_lb = val; 767 768 err = mlx5_nic_vport_query_local_lb(priv->mdev, MLX5_LOCAL_UC_LB, &val); 769 if (err == 0) 770 priv->params_ethtool.uc_local_lb = val; 771 } 772 773 /* create root node */ 774 node = SYSCTL_ADD_NODE(&priv->sysctl_ctx, 775 SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO, 776 "conf", CTLFLAG_RW, NULL, "Configuration"); 777 if (node == NULL) 778 return; 779 for (x = 0; x != MLX5E_PARAMS_NUM; x++) { 780 /* check for read-only parameter */ 781 if (strstr(mlx5e_params_desc[2 * x], "_max") != NULL || 782 strstr(mlx5e_params_desc[2 * x], "_mtu") != NULL) { 783 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO, 784 mlx5e_params_desc[2 * x], CTLTYPE_U64 | CTLFLAG_RD | 785 CTLFLAG_MPSAFE, priv, x, &mlx5e_ethtool_handler, "QU", 786 mlx5e_params_desc[2 * x + 1]); 787 } else { 788 #if (__FreeBSD_version < 1100000) 789 char path[64]; 790 #endif 791 /* 792 * NOTE: In FreeBSD-11 and newer the 793 * CTLFLAG_RWTUN flag will take care of 794 * loading default sysctl value from the 795 * kernel environment, if any: 796 */ 797 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO, 798 mlx5e_params_desc[2 * x], CTLTYPE_U64 | CTLFLAG_RWTUN | 799 CTLFLAG_MPSAFE, priv, x, &mlx5e_ethtool_handler, "QU", 800 mlx5e_params_desc[2 * x + 1]); 801 802 #if (__FreeBSD_version < 1100000) 803 /* compute path for sysctl */ 804 snprintf(path, sizeof(path), "dev.mce.%d.conf.%s", 805 device_get_unit(priv->mdev->pdev->dev.bsddev), 806 mlx5e_params_desc[2 * x]); 807 808 /* try to fetch tunable, if any */ 809 if (TUNABLE_QUAD_FETCH(path, &priv->params_ethtool.arg[x])) 810 mlx5e_ethtool_handler(NULL, priv, x, NULL); 811 #endif 812 } 813 } 814 815 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO, 816 "debug_stats", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 817 0, &mlx5e_ethtool_debug_stats, "I", "Extended debug statistics"); 818 819 pnameunit = device_get_nameunit(priv->mdev->pdev->dev.bsddev); 820 821 SYSCTL_ADD_STRING(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), 822 OID_AUTO, "device_name", CTLFLAG_RD, 823 __DECONST(void *, pnameunit), 0, 824 "PCI device name"); 825 826 /* EEPROM support */ 827 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO, "eeprom_info", 828 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 0, 829 mlx5e_read_eeprom, "I", "EEPROM information"); 830 831 /* Diagnostics support */ 832 mlx5e_create_diagnostics(priv); 833 } 834