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