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