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