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