1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2007-2016 Solarflare Communications Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright notice, 11 * this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright notice, 13 * this list of conditions and the following disclaimer in the documentation 14 * and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 18 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 23 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 26 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * The views and conclusions contained in the software and documentation are 29 * those of the authors and should not be interpreted as representing official 30 * policies, either expressed or implied, of the FreeBSD Project. 31 */ 32 33 #include <sys/cdefs.h> 34 #include "efx.h" 35 #include "efx_impl.h" 36 37 __checkReturn efx_rc_t 38 efx_family( 39 __in uint16_t venid, 40 __in uint16_t devid, 41 __out efx_family_t *efp, 42 __out unsigned int *membarp) 43 { 44 if (venid == EFX_PCI_VENID_SFC) { 45 switch (devid) { 46 #if EFSYS_OPT_SIENA 47 case EFX_PCI_DEVID_SIENA_F1_UNINIT: 48 /* 49 * Hardware default for PF0 of uninitialised Siena. 50 * manftest must be able to cope with this device id. 51 */ 52 case EFX_PCI_DEVID_BETHPAGE: 53 case EFX_PCI_DEVID_SIENA: 54 *efp = EFX_FAMILY_SIENA; 55 *membarp = EFX_MEM_BAR_SIENA; 56 return (0); 57 #endif /* EFSYS_OPT_SIENA */ 58 59 #if EFSYS_OPT_HUNTINGTON 60 case EFX_PCI_DEVID_HUNTINGTON_PF_UNINIT: 61 /* 62 * Hardware default for PF0 of uninitialised Huntington. 63 * manftest must be able to cope with this device id. 64 */ 65 case EFX_PCI_DEVID_FARMINGDALE: 66 case EFX_PCI_DEVID_GREENPORT: 67 *efp = EFX_FAMILY_HUNTINGTON; 68 *membarp = EFX_MEM_BAR_HUNTINGTON_PF; 69 return (0); 70 71 case EFX_PCI_DEVID_FARMINGDALE_VF: 72 case EFX_PCI_DEVID_GREENPORT_VF: 73 *efp = EFX_FAMILY_HUNTINGTON; 74 *membarp = EFX_MEM_BAR_HUNTINGTON_VF; 75 return (0); 76 #endif /* EFSYS_OPT_HUNTINGTON */ 77 78 #if EFSYS_OPT_MEDFORD 79 case EFX_PCI_DEVID_MEDFORD_PF_UNINIT: 80 /* 81 * Hardware default for PF0 of uninitialised Medford. 82 * manftest must be able to cope with this device id. 83 */ 84 case EFX_PCI_DEVID_MEDFORD: 85 *efp = EFX_FAMILY_MEDFORD; 86 *membarp = EFX_MEM_BAR_MEDFORD_PF; 87 return (0); 88 89 case EFX_PCI_DEVID_MEDFORD_VF: 90 *efp = EFX_FAMILY_MEDFORD; 91 *membarp = EFX_MEM_BAR_MEDFORD_VF; 92 return (0); 93 #endif /* EFSYS_OPT_MEDFORD */ 94 95 #if EFSYS_OPT_MEDFORD2 96 case EFX_PCI_DEVID_MEDFORD2_PF_UNINIT: 97 /* 98 * Hardware default for PF0 of uninitialised Medford2. 99 * manftest must be able to cope with this device id. 100 */ 101 case EFX_PCI_DEVID_MEDFORD2: 102 case EFX_PCI_DEVID_MEDFORD2_VF: 103 *efp = EFX_FAMILY_MEDFORD2; 104 *membarp = EFX_MEM_BAR_MEDFORD2; 105 return (0); 106 #endif /* EFSYS_OPT_MEDFORD2 */ 107 108 case EFX_PCI_DEVID_FALCON: /* Obsolete, not supported */ 109 default: 110 break; 111 } 112 } 113 114 *efp = EFX_FAMILY_INVALID; 115 return (ENOTSUP); 116 } 117 118 #if EFSYS_OPT_SIENA 119 120 static const efx_nic_ops_t __efx_nic_siena_ops = { 121 siena_nic_probe, /* eno_probe */ 122 NULL, /* eno_board_cfg */ 123 NULL, /* eno_set_drv_limits */ 124 siena_nic_reset, /* eno_reset */ 125 siena_nic_init, /* eno_init */ 126 NULL, /* eno_get_vi_pool */ 127 NULL, /* eno_get_bar_region */ 128 NULL, /* eno_hw_unavailable */ 129 NULL, /* eno_set_hw_unavailable */ 130 #if EFSYS_OPT_DIAG 131 siena_nic_register_test, /* eno_register_test */ 132 #endif /* EFSYS_OPT_DIAG */ 133 siena_nic_fini, /* eno_fini */ 134 siena_nic_unprobe, /* eno_unprobe */ 135 }; 136 137 #endif /* EFSYS_OPT_SIENA */ 138 139 #if EFSYS_OPT_HUNTINGTON 140 141 static const efx_nic_ops_t __efx_nic_hunt_ops = { 142 ef10_nic_probe, /* eno_probe */ 143 hunt_board_cfg, /* eno_board_cfg */ 144 ef10_nic_set_drv_limits, /* eno_set_drv_limits */ 145 ef10_nic_reset, /* eno_reset */ 146 ef10_nic_init, /* eno_init */ 147 ef10_nic_get_vi_pool, /* eno_get_vi_pool */ 148 ef10_nic_get_bar_region, /* eno_get_bar_region */ 149 ef10_nic_hw_unavailable, /* eno_hw_unavailable */ 150 ef10_nic_set_hw_unavailable, /* eno_set_hw_unavailable */ 151 #if EFSYS_OPT_DIAG 152 ef10_nic_register_test, /* eno_register_test */ 153 #endif /* EFSYS_OPT_DIAG */ 154 ef10_nic_fini, /* eno_fini */ 155 ef10_nic_unprobe, /* eno_unprobe */ 156 }; 157 158 #endif /* EFSYS_OPT_HUNTINGTON */ 159 160 #if EFSYS_OPT_MEDFORD 161 162 static const efx_nic_ops_t __efx_nic_medford_ops = { 163 ef10_nic_probe, /* eno_probe */ 164 medford_board_cfg, /* eno_board_cfg */ 165 ef10_nic_set_drv_limits, /* eno_set_drv_limits */ 166 ef10_nic_reset, /* eno_reset */ 167 ef10_nic_init, /* eno_init */ 168 ef10_nic_get_vi_pool, /* eno_get_vi_pool */ 169 ef10_nic_get_bar_region, /* eno_get_bar_region */ 170 ef10_nic_hw_unavailable, /* eno_hw_unavailable */ 171 ef10_nic_set_hw_unavailable, /* eno_set_hw_unavailable */ 172 #if EFSYS_OPT_DIAG 173 ef10_nic_register_test, /* eno_register_test */ 174 #endif /* EFSYS_OPT_DIAG */ 175 ef10_nic_fini, /* eno_fini */ 176 ef10_nic_unprobe, /* eno_unprobe */ 177 }; 178 179 #endif /* EFSYS_OPT_MEDFORD */ 180 181 #if EFSYS_OPT_MEDFORD2 182 183 static const efx_nic_ops_t __efx_nic_medford2_ops = { 184 ef10_nic_probe, /* eno_probe */ 185 medford2_board_cfg, /* eno_board_cfg */ 186 ef10_nic_set_drv_limits, /* eno_set_drv_limits */ 187 ef10_nic_reset, /* eno_reset */ 188 ef10_nic_init, /* eno_init */ 189 ef10_nic_get_vi_pool, /* eno_get_vi_pool */ 190 ef10_nic_get_bar_region, /* eno_get_bar_region */ 191 ef10_nic_hw_unavailable, /* eno_hw_unavailable */ 192 ef10_nic_set_hw_unavailable, /* eno_set_hw_unavailable */ 193 #if EFSYS_OPT_DIAG 194 ef10_nic_register_test, /* eno_register_test */ 195 #endif /* EFSYS_OPT_DIAG */ 196 ef10_nic_fini, /* eno_fini */ 197 ef10_nic_unprobe, /* eno_unprobe */ 198 }; 199 200 #endif /* EFSYS_OPT_MEDFORD2 */ 201 202 __checkReturn efx_rc_t 203 efx_nic_create( 204 __in efx_family_t family, 205 __in efsys_identifier_t *esip, 206 __in efsys_bar_t *esbp, 207 __in efsys_lock_t *eslp, 208 __deref_out efx_nic_t **enpp) 209 { 210 efx_nic_t *enp; 211 efx_rc_t rc; 212 213 EFSYS_ASSERT3U(family, >, EFX_FAMILY_INVALID); 214 EFSYS_ASSERT3U(family, <, EFX_FAMILY_NTYPES); 215 216 /* Allocate a NIC object */ 217 EFSYS_KMEM_ALLOC(esip, sizeof (efx_nic_t), enp); 218 219 if (enp == NULL) { 220 rc = ENOMEM; 221 goto fail1; 222 } 223 224 enp->en_magic = EFX_NIC_MAGIC; 225 226 switch (family) { 227 #if EFSYS_OPT_SIENA 228 case EFX_FAMILY_SIENA: 229 enp->en_enop = &__efx_nic_siena_ops; 230 enp->en_features = 231 EFX_FEATURE_IPV6 | 232 EFX_FEATURE_LFSR_HASH_INSERT | 233 EFX_FEATURE_LINK_EVENTS | 234 EFX_FEATURE_PERIODIC_MAC_STATS | 235 EFX_FEATURE_MCDI | 236 EFX_FEATURE_LOOKAHEAD_SPLIT | 237 EFX_FEATURE_MAC_HEADER_FILTERS | 238 EFX_FEATURE_TX_SRC_FILTERS; 239 break; 240 #endif /* EFSYS_OPT_SIENA */ 241 242 #if EFSYS_OPT_HUNTINGTON 243 case EFX_FAMILY_HUNTINGTON: 244 enp->en_enop = &__efx_nic_hunt_ops; 245 enp->en_features = 246 EFX_FEATURE_IPV6 | 247 EFX_FEATURE_LINK_EVENTS | 248 EFX_FEATURE_PERIODIC_MAC_STATS | 249 EFX_FEATURE_MCDI | 250 EFX_FEATURE_MAC_HEADER_FILTERS | 251 EFX_FEATURE_MCDI_DMA | 252 EFX_FEATURE_PIO_BUFFERS | 253 EFX_FEATURE_FW_ASSISTED_TSO | 254 EFX_FEATURE_FW_ASSISTED_TSO_V2 | 255 EFX_FEATURE_PACKED_STREAM | 256 EFX_FEATURE_TXQ_CKSUM_OP_DESC; 257 break; 258 #endif /* EFSYS_OPT_HUNTINGTON */ 259 260 #if EFSYS_OPT_MEDFORD 261 case EFX_FAMILY_MEDFORD: 262 enp->en_enop = &__efx_nic_medford_ops; 263 /* 264 * FW_ASSISTED_TSO omitted as Medford only supports firmware 265 * assisted TSO version 2, not the v1 scheme used on Huntington. 266 */ 267 enp->en_features = 268 EFX_FEATURE_IPV6 | 269 EFX_FEATURE_LINK_EVENTS | 270 EFX_FEATURE_PERIODIC_MAC_STATS | 271 EFX_FEATURE_MCDI | 272 EFX_FEATURE_MAC_HEADER_FILTERS | 273 EFX_FEATURE_MCDI_DMA | 274 EFX_FEATURE_PIO_BUFFERS | 275 EFX_FEATURE_FW_ASSISTED_TSO_V2 | 276 EFX_FEATURE_PACKED_STREAM | 277 EFX_FEATURE_TXQ_CKSUM_OP_DESC; 278 break; 279 #endif /* EFSYS_OPT_MEDFORD */ 280 281 #if EFSYS_OPT_MEDFORD2 282 case EFX_FAMILY_MEDFORD2: 283 enp->en_enop = &__efx_nic_medford2_ops; 284 enp->en_features = 285 EFX_FEATURE_IPV6 | 286 EFX_FEATURE_LINK_EVENTS | 287 EFX_FEATURE_PERIODIC_MAC_STATS | 288 EFX_FEATURE_MCDI | 289 EFX_FEATURE_MAC_HEADER_FILTERS | 290 EFX_FEATURE_MCDI_DMA | 291 EFX_FEATURE_PIO_BUFFERS | 292 EFX_FEATURE_FW_ASSISTED_TSO_V2 | 293 EFX_FEATURE_PACKED_STREAM | 294 EFX_FEATURE_TXQ_CKSUM_OP_DESC; 295 break; 296 #endif /* EFSYS_OPT_MEDFORD2 */ 297 298 default: 299 rc = ENOTSUP; 300 goto fail2; 301 } 302 303 enp->en_family = family; 304 enp->en_esip = esip; 305 enp->en_esbp = esbp; 306 enp->en_eslp = eslp; 307 308 *enpp = enp; 309 310 return (0); 311 312 fail2: 313 EFSYS_PROBE(fail2); 314 315 enp->en_magic = 0; 316 317 /* Free the NIC object */ 318 EFSYS_KMEM_FREE(esip, sizeof (efx_nic_t), enp); 319 320 fail1: 321 EFSYS_PROBE1(fail1, efx_rc_t, rc); 322 323 return (rc); 324 } 325 326 __checkReturn efx_rc_t 327 efx_nic_probe( 328 __in efx_nic_t *enp, 329 __in efx_fw_variant_t efv) 330 { 331 const efx_nic_ops_t *enop; 332 efx_rc_t rc; 333 334 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 335 #if EFSYS_OPT_MCDI 336 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI); 337 #endif /* EFSYS_OPT_MCDI */ 338 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_PROBE)); 339 340 /* Ensure FW variant codes match with MC_CMD_FW codes */ 341 EFX_STATIC_ASSERT(EFX_FW_VARIANT_FULL_FEATURED == 342 MC_CMD_FW_FULL_FEATURED); 343 EFX_STATIC_ASSERT(EFX_FW_VARIANT_LOW_LATENCY == 344 MC_CMD_FW_LOW_LATENCY); 345 EFX_STATIC_ASSERT(EFX_FW_VARIANT_PACKED_STREAM == 346 MC_CMD_FW_PACKED_STREAM); 347 EFX_STATIC_ASSERT(EFX_FW_VARIANT_HIGH_TX_RATE == 348 MC_CMD_FW_HIGH_TX_RATE); 349 EFX_STATIC_ASSERT(EFX_FW_VARIANT_PACKED_STREAM_HASH_MODE_1 == 350 MC_CMD_FW_PACKED_STREAM_HASH_MODE_1); 351 EFX_STATIC_ASSERT(EFX_FW_VARIANT_RULES_ENGINE == 352 MC_CMD_FW_RULES_ENGINE); 353 EFX_STATIC_ASSERT(EFX_FW_VARIANT_DPDK == 354 MC_CMD_FW_DPDK); 355 EFX_STATIC_ASSERT(EFX_FW_VARIANT_DONT_CARE == 356 (int)MC_CMD_FW_DONT_CARE); 357 358 enop = enp->en_enop; 359 enp->efv = efv; 360 361 if ((rc = enop->eno_probe(enp)) != 0) 362 goto fail1; 363 364 if ((rc = efx_phy_probe(enp)) != 0) 365 goto fail2; 366 367 enp->en_mod_flags |= EFX_MOD_PROBE; 368 369 return (0); 370 371 fail2: 372 EFSYS_PROBE(fail2); 373 374 enop->eno_unprobe(enp); 375 376 fail1: 377 EFSYS_PROBE1(fail1, efx_rc_t, rc); 378 379 return (rc); 380 } 381 382 __checkReturn efx_rc_t 383 efx_nic_set_drv_limits( 384 __inout efx_nic_t *enp, 385 __in efx_drv_limits_t *edlp) 386 { 387 const efx_nic_ops_t *enop = enp->en_enop; 388 efx_rc_t rc; 389 390 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 391 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 392 393 if (enop->eno_set_drv_limits != NULL) { 394 if ((rc = enop->eno_set_drv_limits(enp, edlp)) != 0) 395 goto fail1; 396 } 397 398 return (0); 399 400 fail1: 401 EFSYS_PROBE1(fail1, efx_rc_t, rc); 402 403 return (rc); 404 } 405 406 __checkReturn efx_rc_t 407 efx_nic_get_bar_region( 408 __in efx_nic_t *enp, 409 __in efx_nic_region_t region, 410 __out uint32_t *offsetp, 411 __out size_t *sizep) 412 { 413 const efx_nic_ops_t *enop = enp->en_enop; 414 efx_rc_t rc; 415 416 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 417 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 418 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC); 419 420 if (enop->eno_get_bar_region == NULL) { 421 rc = ENOTSUP; 422 goto fail1; 423 } 424 if ((rc = (enop->eno_get_bar_region)(enp, 425 region, offsetp, sizep)) != 0) { 426 goto fail2; 427 } 428 429 return (0); 430 431 fail2: 432 EFSYS_PROBE(fail2); 433 434 fail1: 435 EFSYS_PROBE1(fail1, efx_rc_t, rc); 436 437 return (rc); 438 } 439 440 __checkReturn efx_rc_t 441 efx_nic_get_vi_pool( 442 __in efx_nic_t *enp, 443 __out uint32_t *evq_countp, 444 __out uint32_t *rxq_countp, 445 __out uint32_t *txq_countp) 446 { 447 const efx_nic_ops_t *enop = enp->en_enop; 448 efx_nic_cfg_t *encp = &enp->en_nic_cfg; 449 efx_rc_t rc; 450 451 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 452 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 453 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC); 454 455 if (enop->eno_get_vi_pool != NULL) { 456 uint32_t vi_count = 0; 457 458 if ((rc = (enop->eno_get_vi_pool)(enp, &vi_count)) != 0) 459 goto fail1; 460 461 *evq_countp = vi_count; 462 *rxq_countp = vi_count; 463 *txq_countp = vi_count; 464 } else { 465 /* Use NIC limits as default value */ 466 *evq_countp = encp->enc_evq_limit; 467 *rxq_countp = encp->enc_rxq_limit; 468 *txq_countp = encp->enc_txq_limit; 469 } 470 471 return (0); 472 473 fail1: 474 EFSYS_PROBE1(fail1, efx_rc_t, rc); 475 476 return (rc); 477 } 478 479 __checkReturn efx_rc_t 480 efx_nic_init( 481 __in efx_nic_t *enp) 482 { 483 const efx_nic_ops_t *enop = enp->en_enop; 484 efx_rc_t rc; 485 486 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 487 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 488 489 if (enp->en_mod_flags & EFX_MOD_NIC) { 490 rc = EINVAL; 491 goto fail1; 492 } 493 494 if ((rc = enop->eno_init(enp)) != 0) 495 goto fail2; 496 497 enp->en_mod_flags |= EFX_MOD_NIC; 498 499 return (0); 500 501 fail2: 502 EFSYS_PROBE(fail2); 503 fail1: 504 EFSYS_PROBE1(fail1, efx_rc_t, rc); 505 506 return (rc); 507 } 508 509 void 510 efx_nic_fini( 511 __in efx_nic_t *enp) 512 { 513 const efx_nic_ops_t *enop = enp->en_enop; 514 515 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 516 EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_PROBE); 517 EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_NIC); 518 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_INTR)); 519 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV)); 520 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_RX)); 521 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TX)); 522 523 enop->eno_fini(enp); 524 525 enp->en_mod_flags &= ~EFX_MOD_NIC; 526 } 527 528 void 529 efx_nic_unprobe( 530 __in efx_nic_t *enp) 531 { 532 const efx_nic_ops_t *enop = enp->en_enop; 533 534 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 535 #if EFSYS_OPT_MCDI 536 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI); 537 #endif /* EFSYS_OPT_MCDI */ 538 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 539 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NIC)); 540 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_INTR)); 541 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV)); 542 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_RX)); 543 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TX)); 544 545 efx_phy_unprobe(enp); 546 547 enop->eno_unprobe(enp); 548 549 enp->en_mod_flags &= ~EFX_MOD_PROBE; 550 } 551 552 void 553 efx_nic_destroy( 554 __in efx_nic_t *enp) 555 { 556 efsys_identifier_t *esip = enp->en_esip; 557 558 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 559 EFSYS_ASSERT3U(enp->en_mod_flags, ==, 0); 560 561 enp->en_family = EFX_FAMILY_INVALID; 562 enp->en_esip = NULL; 563 enp->en_esbp = NULL; 564 enp->en_eslp = NULL; 565 566 enp->en_enop = NULL; 567 568 enp->en_magic = 0; 569 570 /* Free the NIC object */ 571 EFSYS_KMEM_FREE(esip, sizeof (efx_nic_t), enp); 572 } 573 574 __checkReturn efx_rc_t 575 efx_nic_reset( 576 __in efx_nic_t *enp) 577 { 578 const efx_nic_ops_t *enop = enp->en_enop; 579 unsigned int mod_flags; 580 efx_rc_t rc; 581 582 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 583 EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_PROBE); 584 /* 585 * All modules except the MCDI, PROBE, NVRAM, VPD, MON, TUNNEL 586 * (which we do not reset here) must have been shut down or never 587 * initialized. 588 * 589 * A rule of thumb here is: If the controller or MC reboots, is *any* 590 * state lost. If it's lost and needs reapplying, then the module 591 * *must* not be initialised during the reset. 592 */ 593 mod_flags = enp->en_mod_flags; 594 mod_flags &= ~(EFX_MOD_MCDI | EFX_MOD_PROBE | EFX_MOD_NVRAM | 595 EFX_MOD_VPD | EFX_MOD_MON); 596 #if EFSYS_OPT_TUNNEL 597 mod_flags &= ~EFX_MOD_TUNNEL; 598 #endif /* EFSYS_OPT_TUNNEL */ 599 EFSYS_ASSERT3U(mod_flags, ==, 0); 600 if (mod_flags != 0) { 601 rc = EINVAL; 602 goto fail1; 603 } 604 605 if ((rc = enop->eno_reset(enp)) != 0) 606 goto fail2; 607 608 return (0); 609 610 fail2: 611 EFSYS_PROBE(fail2); 612 fail1: 613 EFSYS_PROBE1(fail1, efx_rc_t, rc); 614 615 return (rc); 616 } 617 618 const efx_nic_cfg_t * 619 efx_nic_cfg_get( 620 __in efx_nic_t *enp) 621 { 622 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 623 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 624 625 return (&(enp->en_nic_cfg)); 626 } 627 628 __checkReturn efx_rc_t 629 efx_nic_get_fw_version( 630 __in efx_nic_t *enp, 631 __out efx_nic_fw_info_t *enfip) 632 { 633 uint16_t mc_fw_version[4]; 634 efx_rc_t rc; 635 636 if (enfip == NULL) { 637 rc = EINVAL; 638 goto fail1; 639 } 640 641 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI); 642 EFSYS_ASSERT3U(enp->en_features, &, EFX_FEATURE_MCDI); 643 644 /* Ensure RXDP_FW_ID codes match with MC_CMD_GET_CAPABILITIES codes */ 645 EFX_STATIC_ASSERT(EFX_RXDP_FULL_FEATURED_FW_ID == 646 MC_CMD_GET_CAPABILITIES_OUT_RXDP); 647 EFX_STATIC_ASSERT(EFX_RXDP_LOW_LATENCY_FW_ID == 648 MC_CMD_GET_CAPABILITIES_OUT_RXDP_LOW_LATENCY); 649 EFX_STATIC_ASSERT(EFX_RXDP_PACKED_STREAM_FW_ID == 650 MC_CMD_GET_CAPABILITIES_OUT_RXDP_PACKED_STREAM); 651 EFX_STATIC_ASSERT(EFX_RXDP_RULES_ENGINE_FW_ID == 652 MC_CMD_GET_CAPABILITIES_OUT_RXDP_RULES_ENGINE); 653 EFX_STATIC_ASSERT(EFX_RXDP_DPDK_FW_ID == 654 MC_CMD_GET_CAPABILITIES_OUT_RXDP_DPDK); 655 656 rc = efx_mcdi_version(enp, mc_fw_version, NULL, NULL); 657 if (rc != 0) 658 goto fail2; 659 660 rc = efx_mcdi_get_capabilities(enp, NULL, 661 &enfip->enfi_rx_dpcpu_fw_id, 662 &enfip->enfi_tx_dpcpu_fw_id, 663 NULL, NULL); 664 if (rc == 0) { 665 enfip->enfi_dpcpu_fw_ids_valid = B_TRUE; 666 } else if (rc == ENOTSUP) { 667 enfip->enfi_dpcpu_fw_ids_valid = B_FALSE; 668 enfip->enfi_rx_dpcpu_fw_id = 0; 669 enfip->enfi_tx_dpcpu_fw_id = 0; 670 } else { 671 goto fail3; 672 } 673 674 memcpy(enfip->enfi_mc_fw_version, mc_fw_version, 675 sizeof (mc_fw_version)); 676 677 return (0); 678 679 fail3: 680 EFSYS_PROBE(fail3); 681 fail2: 682 EFSYS_PROBE(fail2); 683 fail1: 684 EFSYS_PROBE1(fail1, efx_rc_t, rc); 685 686 return (rc); 687 } 688 689 __checkReturn boolean_t 690 efx_nic_hw_unavailable( 691 __in efx_nic_t *enp) 692 { 693 const efx_nic_ops_t *enop = enp->en_enop; 694 695 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 696 /* NOTE: can be used by MCDI before NIC probe */ 697 698 if (enop->eno_hw_unavailable != NULL) { 699 if ((enop->eno_hw_unavailable)(enp) != B_FALSE) 700 goto unavail; 701 } 702 703 return (B_FALSE); 704 705 unavail: 706 return (B_TRUE); 707 } 708 709 void 710 efx_nic_set_hw_unavailable( 711 __in efx_nic_t *enp) 712 { 713 const efx_nic_ops_t *enop = enp->en_enop; 714 715 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 716 717 if (enop->eno_set_hw_unavailable != NULL) 718 enop->eno_set_hw_unavailable(enp); 719 } 720 721 #if EFSYS_OPT_DIAG 722 723 __checkReturn efx_rc_t 724 efx_nic_register_test( 725 __in efx_nic_t *enp) 726 { 727 const efx_nic_ops_t *enop = enp->en_enop; 728 efx_rc_t rc; 729 730 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 731 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 732 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NIC)); 733 734 if ((rc = enop->eno_register_test(enp)) != 0) 735 goto fail1; 736 737 return (0); 738 739 fail1: 740 EFSYS_PROBE1(fail1, efx_rc_t, rc); 741 742 return (rc); 743 } 744 745 #endif /* EFSYS_OPT_DIAG */ 746 747 #if EFSYS_OPT_LOOPBACK 748 749 extern void 750 efx_loopback_mask( 751 __in efx_loopback_kind_t loopback_kind, 752 __out efx_qword_t *maskp) 753 { 754 efx_qword_t mask; 755 756 EFSYS_ASSERT3U(loopback_kind, <, EFX_LOOPBACK_NKINDS); 757 EFSYS_ASSERT(maskp != NULL); 758 759 /* Assert the MC_CMD_LOOPBACK and EFX_LOOPBACK namespaces agree */ 760 #define LOOPBACK_CHECK(_mcdi, _efx) \ 761 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_##_mcdi == EFX_LOOPBACK_##_efx) 762 763 LOOPBACK_CHECK(NONE, OFF); 764 LOOPBACK_CHECK(DATA, DATA); 765 LOOPBACK_CHECK(GMAC, GMAC); 766 LOOPBACK_CHECK(XGMII, XGMII); 767 LOOPBACK_CHECK(XGXS, XGXS); 768 LOOPBACK_CHECK(XAUI, XAUI); 769 LOOPBACK_CHECK(GMII, GMII); 770 LOOPBACK_CHECK(SGMII, SGMII); 771 LOOPBACK_CHECK(XGBR, XGBR); 772 LOOPBACK_CHECK(XFI, XFI); 773 LOOPBACK_CHECK(XAUI_FAR, XAUI_FAR); 774 LOOPBACK_CHECK(GMII_FAR, GMII_FAR); 775 LOOPBACK_CHECK(SGMII_FAR, SGMII_FAR); 776 LOOPBACK_CHECK(XFI_FAR, XFI_FAR); 777 LOOPBACK_CHECK(GPHY, GPHY); 778 LOOPBACK_CHECK(PHYXS, PHY_XS); 779 LOOPBACK_CHECK(PCS, PCS); 780 LOOPBACK_CHECK(PMAPMD, PMA_PMD); 781 LOOPBACK_CHECK(XPORT, XPORT); 782 LOOPBACK_CHECK(XGMII_WS, XGMII_WS); 783 LOOPBACK_CHECK(XAUI_WS, XAUI_WS); 784 LOOPBACK_CHECK(XAUI_WS_FAR, XAUI_WS_FAR); 785 LOOPBACK_CHECK(XAUI_WS_NEAR, XAUI_WS_NEAR); 786 LOOPBACK_CHECK(GMII_WS, GMII_WS); 787 LOOPBACK_CHECK(XFI_WS, XFI_WS); 788 LOOPBACK_CHECK(XFI_WS_FAR, XFI_WS_FAR); 789 LOOPBACK_CHECK(PHYXS_WS, PHYXS_WS); 790 LOOPBACK_CHECK(PMA_INT, PMA_INT); 791 LOOPBACK_CHECK(SD_NEAR, SD_NEAR); 792 LOOPBACK_CHECK(SD_FAR, SD_FAR); 793 LOOPBACK_CHECK(PMA_INT_WS, PMA_INT_WS); 794 LOOPBACK_CHECK(SD_FEP2_WS, SD_FEP2_WS); 795 LOOPBACK_CHECK(SD_FEP1_5_WS, SD_FEP1_5_WS); 796 LOOPBACK_CHECK(SD_FEP_WS, SD_FEP_WS); 797 LOOPBACK_CHECK(SD_FES_WS, SD_FES_WS); 798 LOOPBACK_CHECK(AOE_INT_NEAR, AOE_INT_NEAR); 799 LOOPBACK_CHECK(DATA_WS, DATA_WS); 800 LOOPBACK_CHECK(FORCE_EXT_LINK, FORCE_EXT_LINK); 801 #undef LOOPBACK_CHECK 802 803 /* Build bitmask of possible loopback types */ 804 EFX_ZERO_QWORD(mask); 805 806 if ((loopback_kind == EFX_LOOPBACK_KIND_OFF) || 807 (loopback_kind == EFX_LOOPBACK_KIND_ALL)) { 808 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_OFF); 809 } 810 811 if ((loopback_kind == EFX_LOOPBACK_KIND_MAC) || 812 (loopback_kind == EFX_LOOPBACK_KIND_ALL)) { 813 /* 814 * The "MAC" grouping has historically been used by drivers to 815 * mean loopbacks supported by on-chip hardware. Keep that 816 * meaning here, and include on-chip PHY layer loopbacks. 817 */ 818 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_DATA); 819 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_GMAC); 820 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XGMII); 821 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XGXS); 822 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XAUI); 823 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_GMII); 824 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_SGMII); 825 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XGBR); 826 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XFI); 827 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XAUI_FAR); 828 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_GMII_FAR); 829 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_SGMII_FAR); 830 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XFI_FAR); 831 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_PMA_INT); 832 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_SD_NEAR); 833 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_SD_FAR); 834 } 835 836 if ((loopback_kind == EFX_LOOPBACK_KIND_PHY) || 837 (loopback_kind == EFX_LOOPBACK_KIND_ALL)) { 838 /* 839 * The "PHY" grouping has historically been used by drivers to 840 * mean loopbacks supported by off-chip hardware. Keep that 841 * meaning here. 842 */ 843 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_GPHY); 844 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_PHY_XS); 845 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_PCS); 846 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_PMA_PMD); 847 } 848 849 *maskp = mask; 850 } 851 852 __checkReturn efx_rc_t 853 efx_mcdi_get_loopback_modes( 854 __in efx_nic_t *enp) 855 { 856 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 857 efx_mcdi_req_t req; 858 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_LOOPBACK_MODES_IN_LEN, 859 MC_CMD_GET_LOOPBACK_MODES_OUT_V2_LEN); 860 efx_qword_t mask; 861 efx_qword_t modes; 862 efx_rc_t rc; 863 864 req.emr_cmd = MC_CMD_GET_LOOPBACK_MODES; 865 req.emr_in_buf = payload; 866 req.emr_in_length = MC_CMD_GET_LOOPBACK_MODES_IN_LEN; 867 req.emr_out_buf = payload; 868 req.emr_out_length = MC_CMD_GET_LOOPBACK_MODES_OUT_V2_LEN; 869 870 efx_mcdi_execute(enp, &req); 871 872 if (req.emr_rc != 0) { 873 rc = req.emr_rc; 874 goto fail1; 875 } 876 877 if (req.emr_out_length_used < 878 MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_OFST + 879 MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_LEN) { 880 rc = EMSGSIZE; 881 goto fail2; 882 } 883 884 /* 885 * We assert the MC_CMD_LOOPBACK and EFX_LOOPBACK namespaces agree 886 * in efx_loopback_mask() and in siena_phy.c:siena_phy_get_link(). 887 */ 888 efx_loopback_mask(EFX_LOOPBACK_KIND_ALL, &mask); 889 890 EFX_AND_QWORD(mask, 891 *MCDI_OUT2(req, efx_qword_t, GET_LOOPBACK_MODES_OUT_SUGGESTED)); 892 893 modes = *MCDI_OUT2(req, efx_qword_t, GET_LOOPBACK_MODES_OUT_100M); 894 EFX_AND_QWORD(modes, mask); 895 encp->enc_loopback_types[EFX_LINK_100FDX] = modes; 896 897 modes = *MCDI_OUT2(req, efx_qword_t, GET_LOOPBACK_MODES_OUT_1G); 898 EFX_AND_QWORD(modes, mask); 899 encp->enc_loopback_types[EFX_LINK_1000FDX] = modes; 900 901 modes = *MCDI_OUT2(req, efx_qword_t, GET_LOOPBACK_MODES_OUT_10G); 902 EFX_AND_QWORD(modes, mask); 903 encp->enc_loopback_types[EFX_LINK_10000FDX] = modes; 904 905 if (req.emr_out_length_used >= 906 MC_CMD_GET_LOOPBACK_MODES_OUT_40G_OFST + 907 MC_CMD_GET_LOOPBACK_MODES_OUT_40G_LEN) { 908 /* Response includes 40G loopback modes */ 909 modes = *MCDI_OUT2(req, efx_qword_t, 910 GET_LOOPBACK_MODES_OUT_40G); 911 EFX_AND_QWORD(modes, mask); 912 encp->enc_loopback_types[EFX_LINK_40000FDX] = modes; 913 } 914 915 if (req.emr_out_length_used >= 916 MC_CMD_GET_LOOPBACK_MODES_OUT_V2_25G_OFST + 917 MC_CMD_GET_LOOPBACK_MODES_OUT_V2_25G_LEN) { 918 /* Response includes 25G loopback modes */ 919 modes = *MCDI_OUT2(req, efx_qword_t, 920 GET_LOOPBACK_MODES_OUT_V2_25G); 921 EFX_AND_QWORD(modes, mask); 922 encp->enc_loopback_types[EFX_LINK_25000FDX] = modes; 923 } 924 925 if (req.emr_out_length_used >= 926 MC_CMD_GET_LOOPBACK_MODES_OUT_V2_50G_OFST + 927 MC_CMD_GET_LOOPBACK_MODES_OUT_V2_50G_LEN) { 928 /* Response includes 50G loopback modes */ 929 modes = *MCDI_OUT2(req, efx_qword_t, 930 GET_LOOPBACK_MODES_OUT_V2_50G); 931 EFX_AND_QWORD(modes, mask); 932 encp->enc_loopback_types[EFX_LINK_50000FDX] = modes; 933 } 934 935 if (req.emr_out_length_used >= 936 MC_CMD_GET_LOOPBACK_MODES_OUT_V2_100G_OFST + 937 MC_CMD_GET_LOOPBACK_MODES_OUT_V2_100G_LEN) { 938 /* Response includes 100G loopback modes */ 939 modes = *MCDI_OUT2(req, efx_qword_t, 940 GET_LOOPBACK_MODES_OUT_V2_100G); 941 EFX_AND_QWORD(modes, mask); 942 encp->enc_loopback_types[EFX_LINK_100000FDX] = modes; 943 } 944 945 EFX_ZERO_QWORD(modes); 946 EFX_SET_QWORD_BIT(modes, EFX_LOOPBACK_OFF); 947 EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_100FDX]); 948 EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_1000FDX]); 949 EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_10000FDX]); 950 EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_40000FDX]); 951 EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_25000FDX]); 952 EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_50000FDX]); 953 EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_100000FDX]); 954 encp->enc_loopback_types[EFX_LINK_UNKNOWN] = modes; 955 956 return (0); 957 958 fail2: 959 EFSYS_PROBE(fail2); 960 fail1: 961 EFSYS_PROBE1(fail1, efx_rc_t, rc); 962 963 return (rc); 964 } 965 966 #endif /* EFSYS_OPT_LOOPBACK */ 967 968 __checkReturn efx_rc_t 969 efx_nic_calculate_pcie_link_bandwidth( 970 __in uint32_t pcie_link_width, 971 __in uint32_t pcie_link_gen, 972 __out uint32_t *bandwidth_mbpsp) 973 { 974 uint32_t lane_bandwidth; 975 uint32_t total_bandwidth; 976 efx_rc_t rc; 977 978 if ((pcie_link_width == 0) || (pcie_link_width > 16) || 979 !ISP2(pcie_link_width)) { 980 rc = EINVAL; 981 goto fail1; 982 } 983 984 switch (pcie_link_gen) { 985 case EFX_PCIE_LINK_SPEED_GEN1: 986 /* 2.5 Gb/s raw bandwidth with 8b/10b encoding */ 987 lane_bandwidth = 2000; 988 break; 989 case EFX_PCIE_LINK_SPEED_GEN2: 990 /* 5.0 Gb/s raw bandwidth with 8b/10b encoding */ 991 lane_bandwidth = 4000; 992 break; 993 case EFX_PCIE_LINK_SPEED_GEN3: 994 /* 8.0 Gb/s raw bandwidth with 128b/130b encoding */ 995 lane_bandwidth = 7877; 996 break; 997 default: 998 rc = EINVAL; 999 goto fail2; 1000 } 1001 1002 total_bandwidth = lane_bandwidth * pcie_link_width; 1003 *bandwidth_mbpsp = total_bandwidth; 1004 1005 return (0); 1006 1007 fail2: 1008 EFSYS_PROBE(fail2); 1009 fail1: 1010 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1011 1012 return (rc); 1013 } 1014 1015 #if EFSYS_OPT_FW_SUBVARIANT_AWARE 1016 1017 __checkReturn efx_rc_t 1018 efx_nic_get_fw_subvariant( 1019 __in efx_nic_t *enp, 1020 __out efx_nic_fw_subvariant_t *subvariantp) 1021 { 1022 efx_rc_t rc; 1023 uint32_t value; 1024 1025 rc = efx_mcdi_get_nic_global(enp, 1026 MC_CMD_SET_NIC_GLOBAL_IN_FIRMWARE_SUBVARIANT, &value); 1027 if (rc != 0) 1028 goto fail1; 1029 1030 /* Mapping is not required since values match MCDI */ 1031 EFX_STATIC_ASSERT(EFX_NIC_FW_SUBVARIANT_DEFAULT == 1032 MC_CMD_SET_NIC_GLOBAL_IN_FW_SUBVARIANT_DEFAULT); 1033 EFX_STATIC_ASSERT(EFX_NIC_FW_SUBVARIANT_NO_TX_CSUM == 1034 MC_CMD_SET_NIC_GLOBAL_IN_FW_SUBVARIANT_NO_TX_CSUM); 1035 1036 switch (value) { 1037 case MC_CMD_SET_NIC_GLOBAL_IN_FW_SUBVARIANT_DEFAULT: 1038 case MC_CMD_SET_NIC_GLOBAL_IN_FW_SUBVARIANT_NO_TX_CSUM: 1039 *subvariantp = value; 1040 break; 1041 default: 1042 rc = EINVAL; 1043 goto fail2; 1044 } 1045 1046 return (0); 1047 1048 fail2: 1049 EFSYS_PROBE(fail2); 1050 1051 fail1: 1052 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1053 1054 return (rc); 1055 } 1056 1057 __checkReturn efx_rc_t 1058 efx_nic_set_fw_subvariant( 1059 __in efx_nic_t *enp, 1060 __in efx_nic_fw_subvariant_t subvariant) 1061 { 1062 efx_rc_t rc; 1063 1064 switch (subvariant) { 1065 case EFX_NIC_FW_SUBVARIANT_DEFAULT: 1066 case EFX_NIC_FW_SUBVARIANT_NO_TX_CSUM: 1067 /* Mapping is not required since values match MCDI */ 1068 break; 1069 default: 1070 rc = EINVAL; 1071 goto fail1; 1072 } 1073 1074 rc = efx_mcdi_set_nic_global(enp, 1075 MC_CMD_SET_NIC_GLOBAL_IN_FIRMWARE_SUBVARIANT, subvariant); 1076 if (rc != 0) 1077 goto fail2; 1078 1079 return (0); 1080 1081 fail2: 1082 EFSYS_PROBE(fail2); 1083 1084 fail1: 1085 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1086 1087 return (rc); 1088 } 1089 1090 #endif /* EFSYS_OPT_FW_SUBVARIANT_AWARE */ 1091 1092 __checkReturn efx_rc_t 1093 efx_nic_check_pcie_link_speed( 1094 __in efx_nic_t *enp, 1095 __in uint32_t pcie_link_width, 1096 __in uint32_t pcie_link_gen, 1097 __out efx_pcie_link_performance_t *resultp) 1098 { 1099 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 1100 uint32_t bandwidth; 1101 efx_pcie_link_performance_t result; 1102 efx_rc_t rc; 1103 1104 if ((encp->enc_required_pcie_bandwidth_mbps == 0) || 1105 (pcie_link_width == 0) || (pcie_link_width == 32) || 1106 (pcie_link_gen == 0)) { 1107 /* 1108 * No usable info on what is required and/or in use. In virtual 1109 * machines, sometimes the PCIe link width is reported as 0 or 1110 * 32, or the speed as 0. 1111 */ 1112 result = EFX_PCIE_LINK_PERFORMANCE_UNKNOWN_BANDWIDTH; 1113 goto out; 1114 } 1115 1116 /* Calculate the available bandwidth in megabits per second */ 1117 rc = efx_nic_calculate_pcie_link_bandwidth(pcie_link_width, 1118 pcie_link_gen, &bandwidth); 1119 if (rc != 0) 1120 goto fail1; 1121 1122 if (bandwidth < encp->enc_required_pcie_bandwidth_mbps) { 1123 result = EFX_PCIE_LINK_PERFORMANCE_SUBOPTIMAL_BANDWIDTH; 1124 } else if (pcie_link_gen < encp->enc_max_pcie_link_gen) { 1125 /* The link provides enough bandwidth but not optimal latency */ 1126 result = EFX_PCIE_LINK_PERFORMANCE_SUBOPTIMAL_LATENCY; 1127 } else { 1128 result = EFX_PCIE_LINK_PERFORMANCE_OPTIMAL; 1129 } 1130 1131 out: 1132 *resultp = result; 1133 1134 return (0); 1135 1136 fail1: 1137 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1138 1139 return (rc); 1140 } 1141