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