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_fec_type_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_fec_type_get, /* epo_fec_type_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_port_t *epp = &(enp->en_port); 355 const efx_phy_ops_t *epop = epp->ep_epop; 356 efx_rc_t rc; 357 358 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 359 360 if (epop->epo_fec_type_get == NULL) { 361 rc = ENOTSUP; 362 goto fail1; 363 } 364 365 if ((rc = epop->epo_fec_type_get(enp, typep)) != 0) 366 goto fail2; 367 368 return (0); 369 370 fail2: 371 EFSYS_PROBE(fail2); 372 fail1: 373 EFSYS_PROBE1(fail1, efx_rc_t, rc); 374 375 return (rc); 376 } 377 378 #if EFSYS_OPT_PHY_STATS 379 380 #if EFSYS_OPT_NAMES 381 382 /* START MKCONFIG GENERATED PhyStatNamesBlock af9ffa24da3bc100 */ 383 static const char * const __efx_phy_stat_name[] = { 384 "oui", 385 "pma_pmd_link_up", 386 "pma_pmd_rx_fault", 387 "pma_pmd_tx_fault", 388 "pma_pmd_rev_a", 389 "pma_pmd_rev_b", 390 "pma_pmd_rev_c", 391 "pma_pmd_rev_d", 392 "pcs_link_up", 393 "pcs_rx_fault", 394 "pcs_tx_fault", 395 "pcs_ber", 396 "pcs_block_errors", 397 "phy_xs_link_up", 398 "phy_xs_rx_fault", 399 "phy_xs_tx_fault", 400 "phy_xs_align", 401 "phy_xs_sync_a", 402 "phy_xs_sync_b", 403 "phy_xs_sync_c", 404 "phy_xs_sync_d", 405 "an_link_up", 406 "an_master", 407 "an_local_rx_ok", 408 "an_remote_rx_ok", 409 "cl22ext_link_up", 410 "snr_a", 411 "snr_b", 412 "snr_c", 413 "snr_d", 414 "pma_pmd_signal_a", 415 "pma_pmd_signal_b", 416 "pma_pmd_signal_c", 417 "pma_pmd_signal_d", 418 "an_complete", 419 "pma_pmd_rev_major", 420 "pma_pmd_rev_minor", 421 "pma_pmd_rev_micro", 422 "pcs_fw_version_0", 423 "pcs_fw_version_1", 424 "pcs_fw_version_2", 425 "pcs_fw_version_3", 426 "pcs_fw_build_yy", 427 "pcs_fw_build_mm", 428 "pcs_fw_build_dd", 429 "pcs_op_mode", 430 }; 431 432 /* END MKCONFIG GENERATED PhyStatNamesBlock */ 433 434 const char * 435 efx_phy_stat_name( 436 __in efx_nic_t *enp, 437 __in efx_phy_stat_t type) 438 { 439 _NOTE(ARGUNUSED(enp)) 440 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 441 EFSYS_ASSERT3U(type, <, EFX_PHY_NSTATS); 442 443 return (__efx_phy_stat_name[type]); 444 } 445 446 #endif /* EFSYS_OPT_NAMES */ 447 448 __checkReturn efx_rc_t 449 efx_phy_stats_update( 450 __in efx_nic_t *enp, 451 __in efsys_mem_t *esmp, 452 __inout_ecount(EFX_PHY_NSTATS) uint32_t *stat) 453 { 454 efx_port_t *epp = &(enp->en_port); 455 const efx_phy_ops_t *epop = epp->ep_epop; 456 457 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 458 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 459 460 return (epop->epo_stats_update(enp, esmp, stat)); 461 } 462 463 #endif /* EFSYS_OPT_PHY_STATS */ 464 465 466 #if EFSYS_OPT_BIST 467 468 __checkReturn efx_rc_t 469 efx_bist_enable_offline( 470 __in efx_nic_t *enp) 471 { 472 efx_port_t *epp = &(enp->en_port); 473 const efx_phy_ops_t *epop = epp->ep_epop; 474 efx_rc_t rc; 475 476 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 477 478 if (epop->epo_bist_enable_offline == NULL) { 479 rc = ENOTSUP; 480 goto fail1; 481 } 482 483 if ((rc = epop->epo_bist_enable_offline(enp)) != 0) 484 goto fail2; 485 486 return (0); 487 488 fail2: 489 EFSYS_PROBE(fail2); 490 fail1: 491 EFSYS_PROBE1(fail1, efx_rc_t, rc); 492 493 return (rc); 494 495 } 496 497 __checkReturn efx_rc_t 498 efx_bist_start( 499 __in efx_nic_t *enp, 500 __in efx_bist_type_t type) 501 { 502 efx_port_t *epp = &(enp->en_port); 503 const efx_phy_ops_t *epop = epp->ep_epop; 504 efx_rc_t rc; 505 506 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 507 508 EFSYS_ASSERT3U(type, !=, EFX_BIST_TYPE_UNKNOWN); 509 EFSYS_ASSERT3U(type, <, EFX_BIST_TYPE_NTYPES); 510 EFSYS_ASSERT3U(epp->ep_current_bist, ==, EFX_BIST_TYPE_UNKNOWN); 511 512 if (epop->epo_bist_start == NULL) { 513 rc = ENOTSUP; 514 goto fail1; 515 } 516 517 if ((rc = epop->epo_bist_start(enp, type)) != 0) 518 goto fail2; 519 520 epp->ep_current_bist = type; 521 522 return (0); 523 524 fail2: 525 EFSYS_PROBE(fail2); 526 fail1: 527 EFSYS_PROBE1(fail1, efx_rc_t, rc); 528 529 return (rc); 530 } 531 532 __checkReturn efx_rc_t 533 efx_bist_poll( 534 __in efx_nic_t *enp, 535 __in efx_bist_type_t type, 536 __out efx_bist_result_t *resultp, 537 __out_opt uint32_t *value_maskp, 538 __out_ecount_opt(count) unsigned long *valuesp, 539 __in size_t count) 540 { 541 efx_port_t *epp = &(enp->en_port); 542 const efx_phy_ops_t *epop = epp->ep_epop; 543 efx_rc_t rc; 544 545 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 546 547 EFSYS_ASSERT3U(type, !=, EFX_BIST_TYPE_UNKNOWN); 548 EFSYS_ASSERT3U(type, <, EFX_BIST_TYPE_NTYPES); 549 EFSYS_ASSERT3U(epp->ep_current_bist, ==, type); 550 551 EFSYS_ASSERT(epop->epo_bist_poll != NULL); 552 if (epop->epo_bist_poll == NULL) { 553 rc = ENOTSUP; 554 goto fail1; 555 } 556 557 if ((rc = epop->epo_bist_poll(enp, type, resultp, value_maskp, 558 valuesp, count)) != 0) 559 goto fail2; 560 561 return (0); 562 563 fail2: 564 EFSYS_PROBE(fail2); 565 fail1: 566 EFSYS_PROBE1(fail1, efx_rc_t, rc); 567 568 return (rc); 569 } 570 571 void 572 efx_bist_stop( 573 __in efx_nic_t *enp, 574 __in efx_bist_type_t type) 575 { 576 efx_port_t *epp = &(enp->en_port); 577 const efx_phy_ops_t *epop = epp->ep_epop; 578 579 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 580 581 EFSYS_ASSERT3U(type, !=, EFX_BIST_TYPE_UNKNOWN); 582 EFSYS_ASSERT3U(type, <, EFX_BIST_TYPE_NTYPES); 583 EFSYS_ASSERT3U(epp->ep_current_bist, ==, type); 584 585 EFSYS_ASSERT(epop->epo_bist_stop != NULL); 586 587 if (epop->epo_bist_stop != NULL) 588 epop->epo_bist_stop(enp, type); 589 590 epp->ep_current_bist = EFX_BIST_TYPE_UNKNOWN; 591 } 592 593 #endif /* EFSYS_OPT_BIST */ 594 void 595 efx_phy_unprobe( 596 __in efx_nic_t *enp) 597 { 598 efx_port_t *epp = &(enp->en_port); 599 600 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 601 602 epp->ep_epop = NULL; 603 604 epp->ep_adv_cap_mask = 0; 605 606 epp->ep_port = 0; 607 epp->ep_phy_type = 0; 608 } 609