15e111ed8SAndrew Rybchenko /* SPDX-License-Identifier: BSD-3-Clause
25e111ed8SAndrew Rybchenko *
3*672386c1SAndrew Rybchenko * Copyright(c) 2019-2021 Xilinx, Inc.
45e111ed8SAndrew Rybchenko * Copyright(c) 2007-2019 Solarflare Communications Inc.
55e111ed8SAndrew Rybchenko */
65e111ed8SAndrew Rybchenko
75e111ed8SAndrew Rybchenko #include "efx.h"
85e111ed8SAndrew Rybchenko #include "efx_impl.h"
95e111ed8SAndrew Rybchenko
105e111ed8SAndrew Rybchenko
115e111ed8SAndrew Rybchenko #if EFSYS_OPT_SIENA
125e111ed8SAndrew Rybchenko static const efx_phy_ops_t __efx_phy_siena_ops = {
135e111ed8SAndrew Rybchenko siena_phy_power, /* epo_power */
145e111ed8SAndrew Rybchenko NULL, /* epo_reset */
155e111ed8SAndrew Rybchenko siena_phy_reconfigure, /* epo_reconfigure */
165e111ed8SAndrew Rybchenko siena_phy_verify, /* epo_verify */
175e111ed8SAndrew Rybchenko siena_phy_oui_get, /* epo_oui_get */
185e111ed8SAndrew Rybchenko NULL, /* epo_link_state_get */
195e111ed8SAndrew Rybchenko #if EFSYS_OPT_PHY_STATS
205e111ed8SAndrew Rybchenko siena_phy_stats_update, /* epo_stats_update */
215e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_PHY_STATS */
225e111ed8SAndrew Rybchenko #if EFSYS_OPT_BIST
235e111ed8SAndrew Rybchenko NULL, /* epo_bist_enable_offline */
245e111ed8SAndrew Rybchenko siena_phy_bist_start, /* epo_bist_start */
255e111ed8SAndrew Rybchenko siena_phy_bist_poll, /* epo_bist_poll */
265e111ed8SAndrew Rybchenko siena_phy_bist_stop, /* epo_bist_stop */
275e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_BIST */
285e111ed8SAndrew Rybchenko };
295e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_SIENA */
305e111ed8SAndrew Rybchenko
315e111ed8SAndrew Rybchenko #if EFX_OPTS_EF10()
325e111ed8SAndrew Rybchenko static const efx_phy_ops_t __efx_phy_ef10_ops = {
335e111ed8SAndrew Rybchenko ef10_phy_power, /* epo_power */
345e111ed8SAndrew Rybchenko NULL, /* epo_reset */
355e111ed8SAndrew Rybchenko ef10_phy_reconfigure, /* epo_reconfigure */
365e111ed8SAndrew Rybchenko ef10_phy_verify, /* epo_verify */
375e111ed8SAndrew Rybchenko ef10_phy_oui_get, /* epo_oui_get */
385e111ed8SAndrew Rybchenko ef10_phy_link_state_get, /* epo_link_state_get */
395e111ed8SAndrew Rybchenko #if EFSYS_OPT_PHY_STATS
405e111ed8SAndrew Rybchenko ef10_phy_stats_update, /* epo_stats_update */
415e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_PHY_STATS */
425e111ed8SAndrew Rybchenko #if EFSYS_OPT_BIST
435e111ed8SAndrew Rybchenko ef10_bist_enable_offline, /* epo_bist_enable_offline */
445e111ed8SAndrew Rybchenko ef10_bist_start, /* epo_bist_start */
455e111ed8SAndrew Rybchenko ef10_bist_poll, /* epo_bist_poll */
465e111ed8SAndrew Rybchenko ef10_bist_stop, /* epo_bist_stop */
475e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_BIST */
485e111ed8SAndrew Rybchenko };
495e111ed8SAndrew Rybchenko #endif /* EFX_OPTS_EF10() */
505e111ed8SAndrew Rybchenko
513ac211cfSAndrew Rybchenko #if EFSYS_OPT_RIVERHEAD
523ac211cfSAndrew Rybchenko static const efx_phy_ops_t __efx_phy_rhead_ops = {
533ac211cfSAndrew Rybchenko ef10_phy_power, /* epo_power */
543ac211cfSAndrew Rybchenko NULL, /* epo_reset */
553ac211cfSAndrew Rybchenko ef10_phy_reconfigure, /* epo_reconfigure */
563ac211cfSAndrew Rybchenko ef10_phy_verify, /* epo_verify */
573ac211cfSAndrew Rybchenko ef10_phy_oui_get, /* epo_oui_get */
583ac211cfSAndrew Rybchenko ef10_phy_link_state_get, /* epo_link_state_get */
593ac211cfSAndrew Rybchenko #if EFSYS_OPT_PHY_STATS
603ac211cfSAndrew Rybchenko ef10_phy_stats_update, /* epo_stats_update */
613ac211cfSAndrew Rybchenko #endif /* EFSYS_OPT_PHY_STATS */
623ac211cfSAndrew Rybchenko #if EFSYS_OPT_BIST
633ac211cfSAndrew Rybchenko ef10_bist_enable_offline, /* epo_bist_enable_offline */
643ac211cfSAndrew Rybchenko ef10_bist_start, /* epo_bist_start */
653ac211cfSAndrew Rybchenko ef10_bist_poll, /* epo_bist_poll */
663ac211cfSAndrew Rybchenko ef10_bist_stop, /* epo_bist_stop */
673ac211cfSAndrew Rybchenko #endif /* EFSYS_OPT_BIST */
683ac211cfSAndrew Rybchenko };
693ac211cfSAndrew Rybchenko #endif /* EFSYS_OPT_RIVERHEAD */
703ac211cfSAndrew Rybchenko
715e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
efx_phy_probe(__in efx_nic_t * enp)725e111ed8SAndrew Rybchenko efx_phy_probe(
735e111ed8SAndrew Rybchenko __in efx_nic_t *enp)
745e111ed8SAndrew Rybchenko {
755e111ed8SAndrew Rybchenko efx_port_t *epp = &(enp->en_port);
765e111ed8SAndrew Rybchenko efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
775e111ed8SAndrew Rybchenko const efx_phy_ops_t *epop;
785e111ed8SAndrew Rybchenko efx_rc_t rc;
795e111ed8SAndrew Rybchenko
805e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
815e111ed8SAndrew Rybchenko
825e111ed8SAndrew Rybchenko epp->ep_port = encp->enc_port;
835e111ed8SAndrew Rybchenko epp->ep_phy_type = encp->enc_phy_type;
845e111ed8SAndrew Rybchenko
855e111ed8SAndrew Rybchenko /* Hook in operations structure */
865e111ed8SAndrew Rybchenko switch (enp->en_family) {
875e111ed8SAndrew Rybchenko #if EFSYS_OPT_SIENA
885e111ed8SAndrew Rybchenko case EFX_FAMILY_SIENA:
895e111ed8SAndrew Rybchenko epop = &__efx_phy_siena_ops;
905e111ed8SAndrew Rybchenko break;
915e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_SIENA */
925e111ed8SAndrew Rybchenko
935e111ed8SAndrew Rybchenko #if EFSYS_OPT_HUNTINGTON
945e111ed8SAndrew Rybchenko case EFX_FAMILY_HUNTINGTON:
955e111ed8SAndrew Rybchenko epop = &__efx_phy_ef10_ops;
965e111ed8SAndrew Rybchenko break;
975e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_HUNTINGTON */
985e111ed8SAndrew Rybchenko
995e111ed8SAndrew Rybchenko #if EFSYS_OPT_MEDFORD
1005e111ed8SAndrew Rybchenko case EFX_FAMILY_MEDFORD:
1015e111ed8SAndrew Rybchenko epop = &__efx_phy_ef10_ops;
1025e111ed8SAndrew Rybchenko break;
1035e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_MEDFORD */
1045e111ed8SAndrew Rybchenko
1055e111ed8SAndrew Rybchenko #if EFSYS_OPT_MEDFORD2
1065e111ed8SAndrew Rybchenko case EFX_FAMILY_MEDFORD2:
1075e111ed8SAndrew Rybchenko epop = &__efx_phy_ef10_ops;
1085e111ed8SAndrew Rybchenko break;
1095e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_MEDFORD2 */
1105e111ed8SAndrew Rybchenko
1113ac211cfSAndrew Rybchenko #if EFSYS_OPT_RIVERHEAD
1123ac211cfSAndrew Rybchenko case EFX_FAMILY_RIVERHEAD:
1133ac211cfSAndrew Rybchenko epop = &__efx_phy_rhead_ops;
1143ac211cfSAndrew Rybchenko break;
1153ac211cfSAndrew Rybchenko #endif /* EFSYS_OPT_MEDFORD2 */
1163ac211cfSAndrew Rybchenko
1175e111ed8SAndrew Rybchenko default:
1185e111ed8SAndrew Rybchenko rc = ENOTSUP;
1195e111ed8SAndrew Rybchenko goto fail1;
1205e111ed8SAndrew Rybchenko }
1215e111ed8SAndrew Rybchenko
1225e111ed8SAndrew Rybchenko epp->ep_epop = epop;
1235e111ed8SAndrew Rybchenko
1245e111ed8SAndrew Rybchenko return (0);
1255e111ed8SAndrew Rybchenko
1265e111ed8SAndrew Rybchenko fail1:
1275e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
1285e111ed8SAndrew Rybchenko
1295e111ed8SAndrew Rybchenko epp->ep_port = 0;
1305e111ed8SAndrew Rybchenko epp->ep_phy_type = 0;
1315e111ed8SAndrew Rybchenko
1325e111ed8SAndrew Rybchenko return (rc);
1335e111ed8SAndrew Rybchenko }
1345e111ed8SAndrew Rybchenko
1355e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
efx_phy_verify(__in efx_nic_t * enp)1365e111ed8SAndrew Rybchenko efx_phy_verify(
1375e111ed8SAndrew Rybchenko __in efx_nic_t *enp)
1385e111ed8SAndrew Rybchenko {
1395e111ed8SAndrew Rybchenko efx_port_t *epp = &(enp->en_port);
1405e111ed8SAndrew Rybchenko const efx_phy_ops_t *epop = epp->ep_epop;
1415e111ed8SAndrew Rybchenko
1425e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1435e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
1445e111ed8SAndrew Rybchenko
1455e111ed8SAndrew Rybchenko return (epop->epo_verify(enp));
1465e111ed8SAndrew Rybchenko }
1475e111ed8SAndrew Rybchenko
1485e111ed8SAndrew Rybchenko #if EFSYS_OPT_PHY_LED_CONTROL
1495e111ed8SAndrew Rybchenko
1505e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
efx_phy_led_set(__in efx_nic_t * enp,__in efx_phy_led_mode_t mode)1515e111ed8SAndrew Rybchenko efx_phy_led_set(
1525e111ed8SAndrew Rybchenko __in efx_nic_t *enp,
1535e111ed8SAndrew Rybchenko __in efx_phy_led_mode_t mode)
1545e111ed8SAndrew Rybchenko {
1555e111ed8SAndrew Rybchenko efx_nic_cfg_t *encp = (&enp->en_nic_cfg);
1565e111ed8SAndrew Rybchenko efx_port_t *epp = &(enp->en_port);
1575e111ed8SAndrew Rybchenko const efx_phy_ops_t *epop = epp->ep_epop;
1585e111ed8SAndrew Rybchenko uint32_t mask;
1595e111ed8SAndrew Rybchenko efx_rc_t rc;
1605e111ed8SAndrew Rybchenko
1615e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1625e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
1635e111ed8SAndrew Rybchenko
1645e111ed8SAndrew Rybchenko if (epp->ep_phy_led_mode == mode)
1655e111ed8SAndrew Rybchenko goto done;
1665e111ed8SAndrew Rybchenko
1675e111ed8SAndrew Rybchenko mask = (1 << EFX_PHY_LED_DEFAULT);
1685e111ed8SAndrew Rybchenko mask |= encp->enc_led_mask;
1695e111ed8SAndrew Rybchenko
1705e111ed8SAndrew Rybchenko if (!((1 << mode) & mask)) {
1715e111ed8SAndrew Rybchenko rc = ENOTSUP;
1725e111ed8SAndrew Rybchenko goto fail1;
1735e111ed8SAndrew Rybchenko }
1745e111ed8SAndrew Rybchenko
1755e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(mode, <, EFX_PHY_LED_NMODES);
1765e111ed8SAndrew Rybchenko epp->ep_phy_led_mode = mode;
1775e111ed8SAndrew Rybchenko
1785e111ed8SAndrew Rybchenko if ((rc = epop->epo_reconfigure(enp)) != 0)
1795e111ed8SAndrew Rybchenko goto fail2;
1805e111ed8SAndrew Rybchenko
1815e111ed8SAndrew Rybchenko done:
1825e111ed8SAndrew Rybchenko return (0);
1835e111ed8SAndrew Rybchenko
1845e111ed8SAndrew Rybchenko fail2:
1855e111ed8SAndrew Rybchenko EFSYS_PROBE(fail2);
1865e111ed8SAndrew Rybchenko fail1:
1875e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
1885e111ed8SAndrew Rybchenko
1895e111ed8SAndrew Rybchenko return (rc);
1905e111ed8SAndrew Rybchenko }
1915e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_PHY_LED_CONTROL */
1925e111ed8SAndrew Rybchenko
1935e111ed8SAndrew Rybchenko void
efx_phy_adv_cap_get(__in efx_nic_t * enp,__in uint32_t flag,__out uint32_t * maskp)1945e111ed8SAndrew Rybchenko efx_phy_adv_cap_get(
1955e111ed8SAndrew Rybchenko __in efx_nic_t *enp,
1965e111ed8SAndrew Rybchenko __in uint32_t flag,
1975e111ed8SAndrew Rybchenko __out uint32_t *maskp)
1985e111ed8SAndrew Rybchenko {
1995e111ed8SAndrew Rybchenko efx_port_t *epp = &(enp->en_port);
2005e111ed8SAndrew Rybchenko
2015e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
2025e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
2035e111ed8SAndrew Rybchenko
2045e111ed8SAndrew Rybchenko switch (flag) {
2055e111ed8SAndrew Rybchenko case EFX_PHY_CAP_CURRENT:
2065e111ed8SAndrew Rybchenko *maskp = epp->ep_adv_cap_mask;
2075e111ed8SAndrew Rybchenko break;
2085e111ed8SAndrew Rybchenko case EFX_PHY_CAP_DEFAULT:
2095e111ed8SAndrew Rybchenko *maskp = epp->ep_default_adv_cap_mask;
2105e111ed8SAndrew Rybchenko break;
2115e111ed8SAndrew Rybchenko case EFX_PHY_CAP_PERM:
2125e111ed8SAndrew Rybchenko *maskp = epp->ep_phy_cap_mask;
2135e111ed8SAndrew Rybchenko break;
2145e111ed8SAndrew Rybchenko default:
2155e111ed8SAndrew Rybchenko EFSYS_ASSERT(B_FALSE);
2165e111ed8SAndrew Rybchenko *maskp = 0;
2175e111ed8SAndrew Rybchenko break;
2185e111ed8SAndrew Rybchenko }
2195e111ed8SAndrew Rybchenko }
2205e111ed8SAndrew Rybchenko
2215e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
efx_phy_adv_cap_set(__in efx_nic_t * enp,__in uint32_t mask)2225e111ed8SAndrew Rybchenko efx_phy_adv_cap_set(
2235e111ed8SAndrew Rybchenko __in efx_nic_t *enp,
2245e111ed8SAndrew Rybchenko __in uint32_t mask)
2255e111ed8SAndrew Rybchenko {
2265e111ed8SAndrew Rybchenko efx_port_t *epp = &(enp->en_port);
2275e111ed8SAndrew Rybchenko const efx_phy_ops_t *epop = epp->ep_epop;
2285e111ed8SAndrew Rybchenko uint32_t old_mask;
2295e111ed8SAndrew Rybchenko efx_rc_t rc;
2305e111ed8SAndrew Rybchenko
2315e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
2325e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
2335e111ed8SAndrew Rybchenko
2345e111ed8SAndrew Rybchenko if ((mask & ~epp->ep_phy_cap_mask) != 0) {
2355e111ed8SAndrew Rybchenko rc = ENOTSUP;
2365e111ed8SAndrew Rybchenko goto fail1;
2375e111ed8SAndrew Rybchenko }
2385e111ed8SAndrew Rybchenko
2395e111ed8SAndrew Rybchenko if (epp->ep_adv_cap_mask == mask)
2405e111ed8SAndrew Rybchenko goto done;
2415e111ed8SAndrew Rybchenko
2425e111ed8SAndrew Rybchenko old_mask = epp->ep_adv_cap_mask;
2435e111ed8SAndrew Rybchenko epp->ep_adv_cap_mask = mask;
2445e111ed8SAndrew Rybchenko
2455e111ed8SAndrew Rybchenko if ((rc = epop->epo_reconfigure(enp)) != 0)
2465e111ed8SAndrew Rybchenko goto fail2;
2475e111ed8SAndrew Rybchenko
2485e111ed8SAndrew Rybchenko done:
2495e111ed8SAndrew Rybchenko return (0);
2505e111ed8SAndrew Rybchenko
2515e111ed8SAndrew Rybchenko fail2:
2525e111ed8SAndrew Rybchenko EFSYS_PROBE(fail2);
2535e111ed8SAndrew Rybchenko
2545e111ed8SAndrew Rybchenko epp->ep_adv_cap_mask = old_mask;
2555e111ed8SAndrew Rybchenko /* Reconfigure for robustness */
2565e111ed8SAndrew Rybchenko if (epop->epo_reconfigure(enp) != 0) {
2575e111ed8SAndrew Rybchenko /*
2585e111ed8SAndrew Rybchenko * We may have an inconsistent view of our advertised speed
2595e111ed8SAndrew Rybchenko * capabilities.
2605e111ed8SAndrew Rybchenko */
2615e111ed8SAndrew Rybchenko EFSYS_ASSERT(0);
2625e111ed8SAndrew Rybchenko }
2635e111ed8SAndrew Rybchenko
2645e111ed8SAndrew Rybchenko fail1:
2655e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
2665e111ed8SAndrew Rybchenko
2675e111ed8SAndrew Rybchenko return (rc);
2685e111ed8SAndrew Rybchenko }
2695e111ed8SAndrew Rybchenko
2705e111ed8SAndrew Rybchenko void
efx_phy_lp_cap_get(__in efx_nic_t * enp,__out uint32_t * maskp)2715e111ed8SAndrew Rybchenko efx_phy_lp_cap_get(
2725e111ed8SAndrew Rybchenko __in efx_nic_t *enp,
2735e111ed8SAndrew Rybchenko __out uint32_t *maskp)
2745e111ed8SAndrew Rybchenko {
2755e111ed8SAndrew Rybchenko efx_port_t *epp = &(enp->en_port);
2765e111ed8SAndrew Rybchenko
2775e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
2785e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
2795e111ed8SAndrew Rybchenko
2805e111ed8SAndrew Rybchenko *maskp = epp->ep_lp_cap_mask;
2815e111ed8SAndrew Rybchenko }
2825e111ed8SAndrew Rybchenko
2835e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
efx_phy_oui_get(__in efx_nic_t * enp,__out uint32_t * ouip)2845e111ed8SAndrew Rybchenko efx_phy_oui_get(
2855e111ed8SAndrew Rybchenko __in efx_nic_t *enp,
2865e111ed8SAndrew Rybchenko __out uint32_t *ouip)
2875e111ed8SAndrew Rybchenko {
2885e111ed8SAndrew Rybchenko efx_port_t *epp = &(enp->en_port);
2895e111ed8SAndrew Rybchenko const efx_phy_ops_t *epop = epp->ep_epop;
2905e111ed8SAndrew Rybchenko
2915e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
2925e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
2935e111ed8SAndrew Rybchenko
2945e111ed8SAndrew Rybchenko return (epop->epo_oui_get(enp, ouip));
2955e111ed8SAndrew Rybchenko }
2965e111ed8SAndrew Rybchenko
2975e111ed8SAndrew Rybchenko void
efx_phy_media_type_get(__in efx_nic_t * enp,__out efx_phy_media_type_t * typep)2985e111ed8SAndrew Rybchenko efx_phy_media_type_get(
2995e111ed8SAndrew Rybchenko __in efx_nic_t *enp,
3005e111ed8SAndrew Rybchenko __out efx_phy_media_type_t *typep)
3015e111ed8SAndrew Rybchenko {
3025e111ed8SAndrew Rybchenko efx_port_t *epp = &(enp->en_port);
3035e111ed8SAndrew Rybchenko
3045e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
3055e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
3065e111ed8SAndrew Rybchenko
3075e111ed8SAndrew Rybchenko if (epp->ep_module_type != EFX_PHY_MEDIA_INVALID)
3085e111ed8SAndrew Rybchenko *typep = epp->ep_module_type;
3095e111ed8SAndrew Rybchenko else
3105e111ed8SAndrew Rybchenko *typep = epp->ep_fixed_port_type;
3115e111ed8SAndrew Rybchenko }
3125e111ed8SAndrew Rybchenko
3135e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
efx_phy_module_get_info(__in efx_nic_t * enp,__in uint8_t dev_addr,__in size_t offset,__in size_t len,__out_bcount (len)uint8_t * data)3145e111ed8SAndrew Rybchenko efx_phy_module_get_info(
3155e111ed8SAndrew Rybchenko __in efx_nic_t *enp,
3165e111ed8SAndrew Rybchenko __in uint8_t dev_addr,
3175e111ed8SAndrew Rybchenko __in size_t offset,
3185e111ed8SAndrew Rybchenko __in size_t len,
3195e111ed8SAndrew Rybchenko __out_bcount(len) uint8_t *data)
3205e111ed8SAndrew Rybchenko {
3215e111ed8SAndrew Rybchenko efx_rc_t rc;
3225e111ed8SAndrew Rybchenko
3235e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
3245e111ed8SAndrew Rybchenko EFSYS_ASSERT(data != NULL);
3255e111ed8SAndrew Rybchenko
3265e111ed8SAndrew Rybchenko if ((offset > EFX_PHY_MEDIA_INFO_MAX_OFFSET) ||
3275e111ed8SAndrew Rybchenko ((offset + len) > EFX_PHY_MEDIA_INFO_MAX_OFFSET)) {
3285e111ed8SAndrew Rybchenko rc = EINVAL;
3295e111ed8SAndrew Rybchenko goto fail1;
3305e111ed8SAndrew Rybchenko }
3315e111ed8SAndrew Rybchenko
3325e111ed8SAndrew Rybchenko if ((rc = efx_mcdi_phy_module_get_info(enp, dev_addr,
3335e111ed8SAndrew Rybchenko offset, len, data)) != 0)
3345e111ed8SAndrew Rybchenko goto fail2;
3355e111ed8SAndrew Rybchenko
3365e111ed8SAndrew Rybchenko return (0);
3375e111ed8SAndrew Rybchenko
3385e111ed8SAndrew Rybchenko fail2:
3395e111ed8SAndrew Rybchenko EFSYS_PROBE(fail2);
3405e111ed8SAndrew Rybchenko fail1:
3415e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
3425e111ed8SAndrew Rybchenko
3435e111ed8SAndrew Rybchenko return (rc);
3445e111ed8SAndrew Rybchenko }
3455e111ed8SAndrew Rybchenko
3465e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
efx_phy_fec_type_get(__in efx_nic_t * enp,__out efx_phy_fec_type_t * typep)3475e111ed8SAndrew Rybchenko efx_phy_fec_type_get(
3485e111ed8SAndrew Rybchenko __in efx_nic_t *enp,
3495e111ed8SAndrew Rybchenko __out efx_phy_fec_type_t *typep)
3505e111ed8SAndrew Rybchenko {
3515e111ed8SAndrew Rybchenko efx_rc_t rc;
3525e111ed8SAndrew Rybchenko efx_phy_link_state_t epls;
3535e111ed8SAndrew Rybchenko
3545e111ed8SAndrew Rybchenko if ((rc = efx_phy_link_state_get(enp, &epls)) != 0)
3555e111ed8SAndrew Rybchenko goto fail1;
3565e111ed8SAndrew Rybchenko
3575e111ed8SAndrew Rybchenko *typep = epls.epls_fec;
3585e111ed8SAndrew Rybchenko
3595e111ed8SAndrew Rybchenko return (0);
3605e111ed8SAndrew Rybchenko
3615e111ed8SAndrew Rybchenko fail1:
3625e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
3635e111ed8SAndrew Rybchenko
3645e111ed8SAndrew Rybchenko return (rc);
3655e111ed8SAndrew Rybchenko }
3665e111ed8SAndrew Rybchenko
3675e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
efx_phy_link_state_get(__in efx_nic_t * enp,__out efx_phy_link_state_t * eplsp)3685e111ed8SAndrew Rybchenko efx_phy_link_state_get(
3695e111ed8SAndrew Rybchenko __in efx_nic_t *enp,
3705e111ed8SAndrew Rybchenko __out efx_phy_link_state_t *eplsp)
3715e111ed8SAndrew Rybchenko {
3725e111ed8SAndrew Rybchenko efx_port_t *epp = &(enp->en_port);
3735e111ed8SAndrew Rybchenko const efx_phy_ops_t *epop = epp->ep_epop;
3745e111ed8SAndrew Rybchenko efx_rc_t rc;
3755e111ed8SAndrew Rybchenko
3765e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
3775e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
3785e111ed8SAndrew Rybchenko
3795e111ed8SAndrew Rybchenko if (epop->epo_link_state_get == NULL) {
3805e111ed8SAndrew Rybchenko rc = ENOTSUP;
3815e111ed8SAndrew Rybchenko goto fail1;
3825e111ed8SAndrew Rybchenko }
3835e111ed8SAndrew Rybchenko
3845e111ed8SAndrew Rybchenko if ((rc = epop->epo_link_state_get(enp, eplsp)) != 0)
3855e111ed8SAndrew Rybchenko goto fail2;
3865e111ed8SAndrew Rybchenko
3875e111ed8SAndrew Rybchenko return (0);
3885e111ed8SAndrew Rybchenko
3895e111ed8SAndrew Rybchenko fail2:
3905e111ed8SAndrew Rybchenko EFSYS_PROBE(fail2);
3915e111ed8SAndrew Rybchenko fail1:
3925e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
3935e111ed8SAndrew Rybchenko
3945e111ed8SAndrew Rybchenko return (rc);
3955e111ed8SAndrew Rybchenko }
3965e111ed8SAndrew Rybchenko
3975e111ed8SAndrew Rybchenko #if EFSYS_OPT_PHY_STATS
3985e111ed8SAndrew Rybchenko
3995e111ed8SAndrew Rybchenko #if EFSYS_OPT_NAMES
4005e111ed8SAndrew Rybchenko
4015e111ed8SAndrew Rybchenko /* START MKCONFIG GENERATED PhyStatNamesBlock af9ffa24da3bc100 */
4025e111ed8SAndrew Rybchenko static const char * const __efx_phy_stat_name[] = {
4035e111ed8SAndrew Rybchenko "oui",
4045e111ed8SAndrew Rybchenko "pma_pmd_link_up",
4055e111ed8SAndrew Rybchenko "pma_pmd_rx_fault",
4065e111ed8SAndrew Rybchenko "pma_pmd_tx_fault",
4075e111ed8SAndrew Rybchenko "pma_pmd_rev_a",
4085e111ed8SAndrew Rybchenko "pma_pmd_rev_b",
4095e111ed8SAndrew Rybchenko "pma_pmd_rev_c",
4105e111ed8SAndrew Rybchenko "pma_pmd_rev_d",
4115e111ed8SAndrew Rybchenko "pcs_link_up",
4125e111ed8SAndrew Rybchenko "pcs_rx_fault",
4135e111ed8SAndrew Rybchenko "pcs_tx_fault",
4145e111ed8SAndrew Rybchenko "pcs_ber",
4155e111ed8SAndrew Rybchenko "pcs_block_errors",
4165e111ed8SAndrew Rybchenko "phy_xs_link_up",
4175e111ed8SAndrew Rybchenko "phy_xs_rx_fault",
4185e111ed8SAndrew Rybchenko "phy_xs_tx_fault",
4195e111ed8SAndrew Rybchenko "phy_xs_align",
4205e111ed8SAndrew Rybchenko "phy_xs_sync_a",
4215e111ed8SAndrew Rybchenko "phy_xs_sync_b",
4225e111ed8SAndrew Rybchenko "phy_xs_sync_c",
4235e111ed8SAndrew Rybchenko "phy_xs_sync_d",
4245e111ed8SAndrew Rybchenko "an_link_up",
4255e111ed8SAndrew Rybchenko "an_master",
4265e111ed8SAndrew Rybchenko "an_local_rx_ok",
4275e111ed8SAndrew Rybchenko "an_remote_rx_ok",
4285e111ed8SAndrew Rybchenko "cl22ext_link_up",
4295e111ed8SAndrew Rybchenko "snr_a",
4305e111ed8SAndrew Rybchenko "snr_b",
4315e111ed8SAndrew Rybchenko "snr_c",
4325e111ed8SAndrew Rybchenko "snr_d",
4335e111ed8SAndrew Rybchenko "pma_pmd_signal_a",
4345e111ed8SAndrew Rybchenko "pma_pmd_signal_b",
4355e111ed8SAndrew Rybchenko "pma_pmd_signal_c",
4365e111ed8SAndrew Rybchenko "pma_pmd_signal_d",
4375e111ed8SAndrew Rybchenko "an_complete",
4385e111ed8SAndrew Rybchenko "pma_pmd_rev_major",
4395e111ed8SAndrew Rybchenko "pma_pmd_rev_minor",
4405e111ed8SAndrew Rybchenko "pma_pmd_rev_micro",
4415e111ed8SAndrew Rybchenko "pcs_fw_version_0",
4425e111ed8SAndrew Rybchenko "pcs_fw_version_1",
4435e111ed8SAndrew Rybchenko "pcs_fw_version_2",
4445e111ed8SAndrew Rybchenko "pcs_fw_version_3",
4455e111ed8SAndrew Rybchenko "pcs_fw_build_yy",
4465e111ed8SAndrew Rybchenko "pcs_fw_build_mm",
4475e111ed8SAndrew Rybchenko "pcs_fw_build_dd",
4485e111ed8SAndrew Rybchenko "pcs_op_mode",
4495e111ed8SAndrew Rybchenko };
4505e111ed8SAndrew Rybchenko
4515e111ed8SAndrew Rybchenko /* END MKCONFIG GENERATED PhyStatNamesBlock */
4525e111ed8SAndrew Rybchenko
4535e111ed8SAndrew Rybchenko const char *
efx_phy_stat_name(__in efx_nic_t * enp,__in efx_phy_stat_t type)4545e111ed8SAndrew Rybchenko efx_phy_stat_name(
4555e111ed8SAndrew Rybchenko __in efx_nic_t *enp,
4565e111ed8SAndrew Rybchenko __in efx_phy_stat_t type)
4575e111ed8SAndrew Rybchenko {
4585e111ed8SAndrew Rybchenko _NOTE(ARGUNUSED(enp))
4595e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
4605e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(type, <, EFX_PHY_NSTATS);
4615e111ed8SAndrew Rybchenko
4625e111ed8SAndrew Rybchenko return (__efx_phy_stat_name[type]);
4635e111ed8SAndrew Rybchenko }
4645e111ed8SAndrew Rybchenko
4655e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_NAMES */
4665e111ed8SAndrew Rybchenko
4675e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
efx_phy_stats_update(__in efx_nic_t * enp,__in efsys_mem_t * esmp,__inout_ecount (EFX_PHY_NSTATS)uint32_t * stat)4685e111ed8SAndrew Rybchenko efx_phy_stats_update(
4695e111ed8SAndrew Rybchenko __in efx_nic_t *enp,
4705e111ed8SAndrew Rybchenko __in efsys_mem_t *esmp,
4715e111ed8SAndrew Rybchenko __inout_ecount(EFX_PHY_NSTATS) uint32_t *stat)
4725e111ed8SAndrew Rybchenko {
4735e111ed8SAndrew Rybchenko efx_port_t *epp = &(enp->en_port);
4745e111ed8SAndrew Rybchenko const efx_phy_ops_t *epop = epp->ep_epop;
4755e111ed8SAndrew Rybchenko
4765e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
4775e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
4785e111ed8SAndrew Rybchenko
4795e111ed8SAndrew Rybchenko return (epop->epo_stats_update(enp, esmp, stat));
4805e111ed8SAndrew Rybchenko }
4815e111ed8SAndrew Rybchenko
4825e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_PHY_STATS */
4835e111ed8SAndrew Rybchenko
4845e111ed8SAndrew Rybchenko
4855e111ed8SAndrew Rybchenko #if EFSYS_OPT_BIST
4865e111ed8SAndrew Rybchenko
4875e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
efx_bist_enable_offline(__in efx_nic_t * enp)4885e111ed8SAndrew Rybchenko efx_bist_enable_offline(
4895e111ed8SAndrew Rybchenko __in efx_nic_t *enp)
4905e111ed8SAndrew Rybchenko {
4915e111ed8SAndrew Rybchenko efx_port_t *epp = &(enp->en_port);
4925e111ed8SAndrew Rybchenko const efx_phy_ops_t *epop = epp->ep_epop;
4935e111ed8SAndrew Rybchenko efx_rc_t rc;
4945e111ed8SAndrew Rybchenko
4955e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
4965e111ed8SAndrew Rybchenko
4975e111ed8SAndrew Rybchenko if (epop->epo_bist_enable_offline == NULL) {
4985e111ed8SAndrew Rybchenko rc = ENOTSUP;
4995e111ed8SAndrew Rybchenko goto fail1;
5005e111ed8SAndrew Rybchenko }
5015e111ed8SAndrew Rybchenko
5025e111ed8SAndrew Rybchenko if ((rc = epop->epo_bist_enable_offline(enp)) != 0)
5035e111ed8SAndrew Rybchenko goto fail2;
5045e111ed8SAndrew Rybchenko
5055e111ed8SAndrew Rybchenko return (0);
5065e111ed8SAndrew Rybchenko
5075e111ed8SAndrew Rybchenko fail2:
5085e111ed8SAndrew Rybchenko EFSYS_PROBE(fail2);
5095e111ed8SAndrew Rybchenko fail1:
5105e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
5115e111ed8SAndrew Rybchenko
5125e111ed8SAndrew Rybchenko return (rc);
5135e111ed8SAndrew Rybchenko
5145e111ed8SAndrew Rybchenko }
5155e111ed8SAndrew Rybchenko
5165e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
efx_bist_start(__in efx_nic_t * enp,__in efx_bist_type_t type)5175e111ed8SAndrew Rybchenko efx_bist_start(
5185e111ed8SAndrew Rybchenko __in efx_nic_t *enp,
5195e111ed8SAndrew Rybchenko __in efx_bist_type_t type)
5205e111ed8SAndrew Rybchenko {
5215e111ed8SAndrew Rybchenko efx_port_t *epp = &(enp->en_port);
5225e111ed8SAndrew Rybchenko const efx_phy_ops_t *epop = epp->ep_epop;
5235e111ed8SAndrew Rybchenko efx_rc_t rc;
5245e111ed8SAndrew Rybchenko
5255e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
5265e111ed8SAndrew Rybchenko
5275e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(type, !=, EFX_BIST_TYPE_UNKNOWN);
5285e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(type, <, EFX_BIST_TYPE_NTYPES);
5295e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(epp->ep_current_bist, ==, EFX_BIST_TYPE_UNKNOWN);
5305e111ed8SAndrew Rybchenko
5315e111ed8SAndrew Rybchenko if (epop->epo_bist_start == NULL) {
5325e111ed8SAndrew Rybchenko rc = ENOTSUP;
5335e111ed8SAndrew Rybchenko goto fail1;
5345e111ed8SAndrew Rybchenko }
5355e111ed8SAndrew Rybchenko
5365e111ed8SAndrew Rybchenko if ((rc = epop->epo_bist_start(enp, type)) != 0)
5375e111ed8SAndrew Rybchenko goto fail2;
5385e111ed8SAndrew Rybchenko
5395e111ed8SAndrew Rybchenko epp->ep_current_bist = type;
5405e111ed8SAndrew Rybchenko
5415e111ed8SAndrew Rybchenko return (0);
5425e111ed8SAndrew Rybchenko
5435e111ed8SAndrew Rybchenko fail2:
5445e111ed8SAndrew Rybchenko EFSYS_PROBE(fail2);
5455e111ed8SAndrew Rybchenko fail1:
5465e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
5475e111ed8SAndrew Rybchenko
5485e111ed8SAndrew Rybchenko return (rc);
5495e111ed8SAndrew Rybchenko }
5505e111ed8SAndrew Rybchenko
5515e111ed8SAndrew Rybchenko __checkReturn efx_rc_t
efx_bist_poll(__in efx_nic_t * enp,__in efx_bist_type_t type,__out efx_bist_result_t * resultp,__out_opt uint32_t * value_maskp,__out_ecount_opt (count)unsigned long * valuesp,__in size_t count)5525e111ed8SAndrew Rybchenko efx_bist_poll(
5535e111ed8SAndrew Rybchenko __in efx_nic_t *enp,
5545e111ed8SAndrew Rybchenko __in efx_bist_type_t type,
5555e111ed8SAndrew Rybchenko __out efx_bist_result_t *resultp,
5565e111ed8SAndrew Rybchenko __out_opt uint32_t *value_maskp,
5575e111ed8SAndrew Rybchenko __out_ecount_opt(count) unsigned long *valuesp,
5585e111ed8SAndrew Rybchenko __in size_t count)
5595e111ed8SAndrew Rybchenko {
5605e111ed8SAndrew Rybchenko efx_port_t *epp = &(enp->en_port);
5615e111ed8SAndrew Rybchenko const efx_phy_ops_t *epop = epp->ep_epop;
5625e111ed8SAndrew Rybchenko efx_rc_t rc;
5635e111ed8SAndrew Rybchenko
5645e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
5655e111ed8SAndrew Rybchenko
5665e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(type, !=, EFX_BIST_TYPE_UNKNOWN);
5675e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(type, <, EFX_BIST_TYPE_NTYPES);
5685e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(epp->ep_current_bist, ==, type);
5695e111ed8SAndrew Rybchenko
5705e111ed8SAndrew Rybchenko EFSYS_ASSERT(epop->epo_bist_poll != NULL);
5715e111ed8SAndrew Rybchenko if (epop->epo_bist_poll == NULL) {
5725e111ed8SAndrew Rybchenko rc = ENOTSUP;
5735e111ed8SAndrew Rybchenko goto fail1;
5745e111ed8SAndrew Rybchenko }
5755e111ed8SAndrew Rybchenko
5765e111ed8SAndrew Rybchenko if ((rc = epop->epo_bist_poll(enp, type, resultp, value_maskp,
5775e111ed8SAndrew Rybchenko valuesp, count)) != 0)
5785e111ed8SAndrew Rybchenko goto fail2;
5795e111ed8SAndrew Rybchenko
5805e111ed8SAndrew Rybchenko return (0);
5815e111ed8SAndrew Rybchenko
5825e111ed8SAndrew Rybchenko fail2:
5835e111ed8SAndrew Rybchenko EFSYS_PROBE(fail2);
5845e111ed8SAndrew Rybchenko fail1:
5855e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
5865e111ed8SAndrew Rybchenko
5875e111ed8SAndrew Rybchenko return (rc);
5885e111ed8SAndrew Rybchenko }
5895e111ed8SAndrew Rybchenko
5905e111ed8SAndrew Rybchenko void
efx_bist_stop(__in efx_nic_t * enp,__in efx_bist_type_t type)5915e111ed8SAndrew Rybchenko efx_bist_stop(
5925e111ed8SAndrew Rybchenko __in efx_nic_t *enp,
5935e111ed8SAndrew Rybchenko __in efx_bist_type_t type)
5945e111ed8SAndrew Rybchenko {
5955e111ed8SAndrew Rybchenko efx_port_t *epp = &(enp->en_port);
5965e111ed8SAndrew Rybchenko const efx_phy_ops_t *epop = epp->ep_epop;
5975e111ed8SAndrew Rybchenko
5985e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
5995e111ed8SAndrew Rybchenko
6005e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(type, !=, EFX_BIST_TYPE_UNKNOWN);
6015e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(type, <, EFX_BIST_TYPE_NTYPES);
6025e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(epp->ep_current_bist, ==, type);
6035e111ed8SAndrew Rybchenko
6045e111ed8SAndrew Rybchenko EFSYS_ASSERT(epop->epo_bist_stop != NULL);
6055e111ed8SAndrew Rybchenko
6065e111ed8SAndrew Rybchenko if (epop->epo_bist_stop != NULL)
6075e111ed8SAndrew Rybchenko epop->epo_bist_stop(enp, type);
6085e111ed8SAndrew Rybchenko
6095e111ed8SAndrew Rybchenko epp->ep_current_bist = EFX_BIST_TYPE_UNKNOWN;
6105e111ed8SAndrew Rybchenko }
6115e111ed8SAndrew Rybchenko
6125e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_BIST */
6135e111ed8SAndrew Rybchenko void
efx_phy_unprobe(__in efx_nic_t * enp)6145e111ed8SAndrew Rybchenko efx_phy_unprobe(
6155e111ed8SAndrew Rybchenko __in efx_nic_t *enp)
6165e111ed8SAndrew Rybchenko {
6175e111ed8SAndrew Rybchenko efx_port_t *epp = &(enp->en_port);
6185e111ed8SAndrew Rybchenko
6195e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
6205e111ed8SAndrew Rybchenko
6215e111ed8SAndrew Rybchenko epp->ep_epop = NULL;
6225e111ed8SAndrew Rybchenko
6235e111ed8SAndrew Rybchenko epp->ep_adv_cap_mask = 0;
6245e111ed8SAndrew Rybchenko
6255e111ed8SAndrew Rybchenko epp->ep_port = 0;
6265e111ed8SAndrew Rybchenko epp->ep_phy_type = 0;
6275e111ed8SAndrew Rybchenko }
628