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 #if EFSYS_OPT_SIENA 41 static const efx_phy_ops_t __efx_phy_siena_ops = { 42 siena_phy_power, /* epo_power */ 43 NULL, /* epo_reset */ 44 siena_phy_reconfigure, /* epo_reconfigure */ 45 siena_phy_verify, /* epo_verify */ 46 siena_phy_oui_get, /* epo_oui_get */ 47 NULL, /* epo_link_state_get */ 48 #if EFSYS_OPT_PHY_STATS 49 siena_phy_stats_update, /* epo_stats_update */ 50 #endif /* EFSYS_OPT_PHY_STATS */ 51 #if EFSYS_OPT_BIST 52 NULL, /* epo_bist_enable_offline */ 53 siena_phy_bist_start, /* epo_bist_start */ 54 siena_phy_bist_poll, /* epo_bist_poll */ 55 siena_phy_bist_stop, /* epo_bist_stop */ 56 #endif /* EFSYS_OPT_BIST */ 57 }; 58 #endif /* EFSYS_OPT_SIENA */ 59 60 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 61 static const efx_phy_ops_t __efx_phy_ef10_ops = { 62 ef10_phy_power, /* epo_power */ 63 NULL, /* epo_reset */ 64 ef10_phy_reconfigure, /* epo_reconfigure */ 65 ef10_phy_verify, /* epo_verify */ 66 ef10_phy_oui_get, /* epo_oui_get */ 67 ef10_phy_link_state_get, /* epo_link_state_get */ 68 #if EFSYS_OPT_PHY_STATS 69 ef10_phy_stats_update, /* epo_stats_update */ 70 #endif /* EFSYS_OPT_PHY_STATS */ 71 #if EFSYS_OPT_BIST 72 ef10_bist_enable_offline, /* epo_bist_enable_offline */ 73 ef10_bist_start, /* epo_bist_start */ 74 ef10_bist_poll, /* epo_bist_poll */ 75 ef10_bist_stop, /* epo_bist_stop */ 76 #endif /* EFSYS_OPT_BIST */ 77 }; 78 #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */ 79 80 __checkReturn efx_rc_t 81 efx_phy_probe( 82 __in efx_nic_t *enp) 83 { 84 efx_port_t *epp = &(enp->en_port); 85 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 86 const efx_phy_ops_t *epop; 87 efx_rc_t rc; 88 89 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 90 91 epp->ep_port = encp->enc_port; 92 epp->ep_phy_type = encp->enc_phy_type; 93 94 /* Hook in operations structure */ 95 switch (enp->en_family) { 96 #if EFSYS_OPT_SIENA 97 case EFX_FAMILY_SIENA: 98 epop = &__efx_phy_siena_ops; 99 break; 100 #endif /* EFSYS_OPT_SIENA */ 101 102 #if EFSYS_OPT_HUNTINGTON 103 case EFX_FAMILY_HUNTINGTON: 104 epop = &__efx_phy_ef10_ops; 105 break; 106 #endif /* EFSYS_OPT_HUNTINGTON */ 107 108 #if EFSYS_OPT_MEDFORD 109 case EFX_FAMILY_MEDFORD: 110 epop = &__efx_phy_ef10_ops; 111 break; 112 #endif /* EFSYS_OPT_MEDFORD */ 113 114 #if EFSYS_OPT_MEDFORD2 115 case EFX_FAMILY_MEDFORD2: 116 epop = &__efx_phy_ef10_ops; 117 break; 118 #endif /* EFSYS_OPT_MEDFORD2 */ 119 120 default: 121 rc = ENOTSUP; 122 goto fail1; 123 } 124 125 epp->ep_epop = epop; 126 127 return (0); 128 129 fail1: 130 EFSYS_PROBE1(fail1, efx_rc_t, rc); 131 132 epp->ep_port = 0; 133 epp->ep_phy_type = 0; 134 135 return (rc); 136 } 137 138 __checkReturn efx_rc_t 139 efx_phy_verify( 140 __in efx_nic_t *enp) 141 { 142 efx_port_t *epp = &(enp->en_port); 143 const efx_phy_ops_t *epop = epp->ep_epop; 144 145 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 146 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 147 148 return (epop->epo_verify(enp)); 149 } 150 151 #if EFSYS_OPT_PHY_LED_CONTROL 152 153 __checkReturn efx_rc_t 154 efx_phy_led_set( 155 __in efx_nic_t *enp, 156 __in efx_phy_led_mode_t mode) 157 { 158 efx_nic_cfg_t *encp = (&enp->en_nic_cfg); 159 efx_port_t *epp = &(enp->en_port); 160 const efx_phy_ops_t *epop = epp->ep_epop; 161 uint32_t mask; 162 efx_rc_t rc; 163 164 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 165 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 166 167 if (epp->ep_phy_led_mode == mode) 168 goto done; 169 170 mask = (1 << EFX_PHY_LED_DEFAULT); 171 mask |= encp->enc_led_mask; 172 173 if (!((1 << mode) & mask)) { 174 rc = ENOTSUP; 175 goto fail1; 176 } 177 178 EFSYS_ASSERT3U(mode, <, EFX_PHY_LED_NMODES); 179 epp->ep_phy_led_mode = mode; 180 181 if ((rc = epop->epo_reconfigure(enp)) != 0) 182 goto fail2; 183 184 done: 185 return (0); 186 187 fail2: 188 EFSYS_PROBE(fail2); 189 fail1: 190 EFSYS_PROBE1(fail1, efx_rc_t, rc); 191 192 return (rc); 193 } 194 #endif /* EFSYS_OPT_PHY_LED_CONTROL */ 195 196 void 197 efx_phy_adv_cap_get( 198 __in efx_nic_t *enp, 199 __in uint32_t flag, 200 __out uint32_t *maskp) 201 { 202 efx_port_t *epp = &(enp->en_port); 203 204 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 205 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 206 207 switch (flag) { 208 case EFX_PHY_CAP_CURRENT: 209 *maskp = epp->ep_adv_cap_mask; 210 break; 211 case EFX_PHY_CAP_DEFAULT: 212 *maskp = epp->ep_default_adv_cap_mask; 213 break; 214 case EFX_PHY_CAP_PERM: 215 *maskp = epp->ep_phy_cap_mask; 216 break; 217 default: 218 EFSYS_ASSERT(B_FALSE); 219 *maskp = 0; 220 break; 221 } 222 } 223 224 __checkReturn efx_rc_t 225 efx_phy_adv_cap_set( 226 __in efx_nic_t *enp, 227 __in uint32_t mask) 228 { 229 efx_port_t *epp = &(enp->en_port); 230 const efx_phy_ops_t *epop = epp->ep_epop; 231 uint32_t old_mask; 232 efx_rc_t rc; 233 234 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 235 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 236 237 if ((mask & ~epp->ep_phy_cap_mask) != 0) { 238 rc = ENOTSUP; 239 goto fail1; 240 } 241 242 if (epp->ep_adv_cap_mask == mask) 243 goto done; 244 245 old_mask = epp->ep_adv_cap_mask; 246 epp->ep_adv_cap_mask = mask; 247 248 if ((rc = epop->epo_reconfigure(enp)) != 0) 249 goto fail2; 250 251 done: 252 return (0); 253 254 fail2: 255 EFSYS_PROBE(fail2); 256 257 epp->ep_adv_cap_mask = old_mask; 258 /* Reconfigure for robustness */ 259 if (epop->epo_reconfigure(enp) != 0) { 260 /* 261 * We may have an inconsistent view of our advertised speed 262 * capabilities. 263 */ 264 EFSYS_ASSERT(0); 265 } 266 267 fail1: 268 EFSYS_PROBE1(fail1, efx_rc_t, rc); 269 270 return (rc); 271 } 272 273 void 274 efx_phy_lp_cap_get( 275 __in efx_nic_t *enp, 276 __out uint32_t *maskp) 277 { 278 efx_port_t *epp = &(enp->en_port); 279 280 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 281 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 282 283 *maskp = epp->ep_lp_cap_mask; 284 } 285 286 __checkReturn efx_rc_t 287 efx_phy_oui_get( 288 __in efx_nic_t *enp, 289 __out uint32_t *ouip) 290 { 291 efx_port_t *epp = &(enp->en_port); 292 const efx_phy_ops_t *epop = epp->ep_epop; 293 294 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 295 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 296 297 return (epop->epo_oui_get(enp, ouip)); 298 } 299 300 void 301 efx_phy_media_type_get( 302 __in efx_nic_t *enp, 303 __out efx_phy_media_type_t *typep) 304 { 305 efx_port_t *epp = &(enp->en_port); 306 307 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 308 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 309 310 if (epp->ep_module_type != EFX_PHY_MEDIA_INVALID) 311 *typep = epp->ep_module_type; 312 else 313 *typep = epp->ep_fixed_port_type; 314 } 315 316 __checkReturn efx_rc_t 317 efx_phy_module_get_info( 318 __in efx_nic_t *enp, 319 __in uint8_t dev_addr, 320 __in size_t offset, 321 __in size_t len, 322 __out_bcount(len) uint8_t *data) 323 { 324 efx_rc_t rc; 325 326 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 327 EFSYS_ASSERT(data != NULL); 328 329 if ((offset > EFX_PHY_MEDIA_INFO_MAX_OFFSET) || 330 ((offset + len) > EFX_PHY_MEDIA_INFO_MAX_OFFSET)) { 331 rc = EINVAL; 332 goto fail1; 333 } 334 335 if ((rc = efx_mcdi_phy_module_get_info(enp, dev_addr, 336 offset, len, data)) != 0) 337 goto fail2; 338 339 return (0); 340 341 fail2: 342 EFSYS_PROBE(fail2); 343 fail1: 344 EFSYS_PROBE1(fail1, efx_rc_t, rc); 345 346 return (rc); 347 } 348 349 __checkReturn efx_rc_t 350 efx_phy_fec_type_get( 351 __in efx_nic_t *enp, 352 __out efx_phy_fec_type_t *typep) 353 { 354 efx_rc_t rc; 355 efx_phy_link_state_t epls; 356 357 if ((rc = efx_phy_link_state_get(enp, &epls)) != 0) 358 goto fail1; 359 360 *typep = epls.epls_fec; 361 362 return (0); 363 364 fail1: 365 EFSYS_PROBE1(fail1, efx_rc_t, rc); 366 367 return (rc); 368 } 369 370 __checkReturn efx_rc_t 371 efx_phy_link_state_get( 372 __in efx_nic_t *enp, 373 __out efx_phy_link_state_t *eplsp) 374 { 375 efx_port_t *epp = &(enp->en_port); 376 const efx_phy_ops_t *epop = epp->ep_epop; 377 efx_rc_t rc; 378 379 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 380 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 381 382 if (epop->epo_link_state_get == NULL) { 383 rc = ENOTSUP; 384 goto fail1; 385 } 386 387 if ((rc = epop->epo_link_state_get(enp, eplsp)) != 0) 388 goto fail2; 389 390 return (0); 391 392 fail2: 393 EFSYS_PROBE(fail2); 394 fail1: 395 EFSYS_PROBE1(fail1, efx_rc_t, rc); 396 397 return (rc); 398 } 399 400 #if EFSYS_OPT_PHY_STATS 401 402 #if EFSYS_OPT_NAMES 403 404 /* START MKCONFIG GENERATED PhyStatNamesBlock af9ffa24da3bc100 */ 405 static const char * const __efx_phy_stat_name[] = { 406 "oui", 407 "pma_pmd_link_up", 408 "pma_pmd_rx_fault", 409 "pma_pmd_tx_fault", 410 "pma_pmd_rev_a", 411 "pma_pmd_rev_b", 412 "pma_pmd_rev_c", 413 "pma_pmd_rev_d", 414 "pcs_link_up", 415 "pcs_rx_fault", 416 "pcs_tx_fault", 417 "pcs_ber", 418 "pcs_block_errors", 419 "phy_xs_link_up", 420 "phy_xs_rx_fault", 421 "phy_xs_tx_fault", 422 "phy_xs_align", 423 "phy_xs_sync_a", 424 "phy_xs_sync_b", 425 "phy_xs_sync_c", 426 "phy_xs_sync_d", 427 "an_link_up", 428 "an_master", 429 "an_local_rx_ok", 430 "an_remote_rx_ok", 431 "cl22ext_link_up", 432 "snr_a", 433 "snr_b", 434 "snr_c", 435 "snr_d", 436 "pma_pmd_signal_a", 437 "pma_pmd_signal_b", 438 "pma_pmd_signal_c", 439 "pma_pmd_signal_d", 440 "an_complete", 441 "pma_pmd_rev_major", 442 "pma_pmd_rev_minor", 443 "pma_pmd_rev_micro", 444 "pcs_fw_version_0", 445 "pcs_fw_version_1", 446 "pcs_fw_version_2", 447 "pcs_fw_version_3", 448 "pcs_fw_build_yy", 449 "pcs_fw_build_mm", 450 "pcs_fw_build_dd", 451 "pcs_op_mode", 452 }; 453 454 /* END MKCONFIG GENERATED PhyStatNamesBlock */ 455 456 const char * 457 efx_phy_stat_name( 458 __in efx_nic_t *enp, 459 __in efx_phy_stat_t type) 460 { 461 _NOTE(ARGUNUSED(enp)) 462 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 463 EFSYS_ASSERT3U(type, <, EFX_PHY_NSTATS); 464 465 return (__efx_phy_stat_name[type]); 466 } 467 468 #endif /* EFSYS_OPT_NAMES */ 469 470 __checkReturn efx_rc_t 471 efx_phy_stats_update( 472 __in efx_nic_t *enp, 473 __in efsys_mem_t *esmp, 474 __inout_ecount(EFX_PHY_NSTATS) uint32_t *stat) 475 { 476 efx_port_t *epp = &(enp->en_port); 477 const efx_phy_ops_t *epop = epp->ep_epop; 478 479 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 480 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 481 482 return (epop->epo_stats_update(enp, esmp, stat)); 483 } 484 485 #endif /* EFSYS_OPT_PHY_STATS */ 486 487 488 #if EFSYS_OPT_BIST 489 490 __checkReturn efx_rc_t 491 efx_bist_enable_offline( 492 __in efx_nic_t *enp) 493 { 494 efx_port_t *epp = &(enp->en_port); 495 const efx_phy_ops_t *epop = epp->ep_epop; 496 efx_rc_t rc; 497 498 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 499 500 if (epop->epo_bist_enable_offline == NULL) { 501 rc = ENOTSUP; 502 goto fail1; 503 } 504 505 if ((rc = epop->epo_bist_enable_offline(enp)) != 0) 506 goto fail2; 507 508 return (0); 509 510 fail2: 511 EFSYS_PROBE(fail2); 512 fail1: 513 EFSYS_PROBE1(fail1, efx_rc_t, rc); 514 515 return (rc); 516 517 } 518 519 __checkReturn efx_rc_t 520 efx_bist_start( 521 __in efx_nic_t *enp, 522 __in efx_bist_type_t type) 523 { 524 efx_port_t *epp = &(enp->en_port); 525 const efx_phy_ops_t *epop = epp->ep_epop; 526 efx_rc_t rc; 527 528 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 529 530 EFSYS_ASSERT3U(type, !=, EFX_BIST_TYPE_UNKNOWN); 531 EFSYS_ASSERT3U(type, <, EFX_BIST_TYPE_NTYPES); 532 EFSYS_ASSERT3U(epp->ep_current_bist, ==, EFX_BIST_TYPE_UNKNOWN); 533 534 if (epop->epo_bist_start == NULL) { 535 rc = ENOTSUP; 536 goto fail1; 537 } 538 539 if ((rc = epop->epo_bist_start(enp, type)) != 0) 540 goto fail2; 541 542 epp->ep_current_bist = type; 543 544 return (0); 545 546 fail2: 547 EFSYS_PROBE(fail2); 548 fail1: 549 EFSYS_PROBE1(fail1, efx_rc_t, rc); 550 551 return (rc); 552 } 553 554 __checkReturn efx_rc_t 555 efx_bist_poll( 556 __in efx_nic_t *enp, 557 __in efx_bist_type_t type, 558 __out efx_bist_result_t *resultp, 559 __out_opt uint32_t *value_maskp, 560 __out_ecount_opt(count) unsigned long *valuesp, 561 __in size_t count) 562 { 563 efx_port_t *epp = &(enp->en_port); 564 const efx_phy_ops_t *epop = epp->ep_epop; 565 efx_rc_t rc; 566 567 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 568 569 EFSYS_ASSERT3U(type, !=, EFX_BIST_TYPE_UNKNOWN); 570 EFSYS_ASSERT3U(type, <, EFX_BIST_TYPE_NTYPES); 571 EFSYS_ASSERT3U(epp->ep_current_bist, ==, type); 572 573 EFSYS_ASSERT(epop->epo_bist_poll != NULL); 574 if (epop->epo_bist_poll == NULL) { 575 rc = ENOTSUP; 576 goto fail1; 577 } 578 579 if ((rc = epop->epo_bist_poll(enp, type, resultp, value_maskp, 580 valuesp, count)) != 0) 581 goto fail2; 582 583 return (0); 584 585 fail2: 586 EFSYS_PROBE(fail2); 587 fail1: 588 EFSYS_PROBE1(fail1, efx_rc_t, rc); 589 590 return (rc); 591 } 592 593 void 594 efx_bist_stop( 595 __in efx_nic_t *enp, 596 __in efx_bist_type_t type) 597 { 598 efx_port_t *epp = &(enp->en_port); 599 const efx_phy_ops_t *epop = epp->ep_epop; 600 601 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 602 603 EFSYS_ASSERT3U(type, !=, EFX_BIST_TYPE_UNKNOWN); 604 EFSYS_ASSERT3U(type, <, EFX_BIST_TYPE_NTYPES); 605 EFSYS_ASSERT3U(epp->ep_current_bist, ==, type); 606 607 EFSYS_ASSERT(epop->epo_bist_stop != NULL); 608 609 if (epop->epo_bist_stop != NULL) 610 epop->epo_bist_stop(enp, type); 611 612 epp->ep_current_bist = EFX_BIST_TYPE_UNKNOWN; 613 } 614 615 #endif /* EFSYS_OPT_BIST */ 616 void 617 efx_phy_unprobe( 618 __in efx_nic_t *enp) 619 { 620 efx_port_t *epp = &(enp->en_port); 621 622 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 623 624 epp->ep_epop = NULL; 625 626 epp->ep_adv_cap_mask = 0; 627 628 epp->ep_port = 0; 629 epp->ep_phy_type = 0; 630 } 631