1 /* SPDX-License-Identifier: BSD-3-Clause 2 * 3 * Copyright(c) 2019-2021 Xilinx, Inc. 4 * Copyright(c) 2009-2019 Solarflare Communications Inc. 5 */ 6 7 #include "efx.h" 8 #include "efx_impl.h" 9 10 __checkReturn efx_rc_t 11 efx_port_init( 12 __in efx_nic_t *enp) 13 { 14 efx_port_t *epp = &(enp->en_port); 15 const efx_phy_ops_t *epop = epp->ep_epop; 16 efx_rc_t rc; 17 18 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 19 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 20 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC); 21 22 if (enp->en_mod_flags & EFX_MOD_PORT) { 23 rc = EINVAL; 24 goto fail1; 25 } 26 27 enp->en_mod_flags |= EFX_MOD_PORT; 28 29 epp->ep_mac_type = EFX_MAC_INVALID; 30 epp->ep_link_mode = EFX_LINK_UNKNOWN; 31 epp->ep_mac_drain = B_TRUE; 32 33 /* Configure the MAC */ 34 if ((rc = efx_mac_select(enp)) != 0) 35 goto fail1; 36 37 epp->ep_emop->emo_reconfigure(enp); 38 39 /* Pick up current phy capababilities */ 40 (void) efx_port_poll(enp, NULL); 41 42 /* 43 * Turn on the PHY if available, otherwise reset it, and 44 * reconfigure it with the current configuration. 45 */ 46 if (epop->epo_power != NULL) { 47 if ((rc = epop->epo_power(enp, B_TRUE)) != 0) 48 goto fail2; 49 } else { 50 if ((rc = epop->epo_reset(enp)) != 0) 51 goto fail2; 52 } 53 54 EFSYS_ASSERT(enp->en_reset_flags & EFX_RESET_PHY); 55 enp->en_reset_flags &= ~EFX_RESET_PHY; 56 57 if ((rc = epop->epo_reconfigure(enp)) != 0) 58 goto fail3; 59 60 return (0); 61 62 fail3: 63 EFSYS_PROBE(fail3); 64 fail2: 65 EFSYS_PROBE(fail2); 66 fail1: 67 EFSYS_PROBE1(fail1, efx_rc_t, rc); 68 69 enp->en_mod_flags &= ~EFX_MOD_PORT; 70 71 return (rc); 72 } 73 74 __checkReturn efx_rc_t 75 efx_port_poll( 76 __in efx_nic_t *enp, 77 __out_opt efx_link_mode_t *link_modep) 78 { 79 efx_port_t *epp = &(enp->en_port); 80 const efx_mac_ops_t *emop = epp->ep_emop; 81 efx_link_mode_t ignore_link_mode; 82 efx_rc_t rc; 83 84 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 85 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 86 87 EFSYS_ASSERT(emop != NULL); 88 89 if (link_modep == NULL) 90 link_modep = &ignore_link_mode; 91 92 if ((rc = emop->emo_poll(enp, link_modep)) != 0) 93 goto fail1; 94 95 return (0); 96 97 fail1: 98 EFSYS_PROBE1(fail1, efx_rc_t, rc); 99 100 return (rc); 101 } 102 103 #if EFSYS_OPT_LOOPBACK 104 105 __checkReturn efx_rc_t 106 efx_port_loopback_set( 107 __in efx_nic_t *enp, 108 __in efx_link_mode_t link_mode, 109 __in efx_loopback_type_t loopback_type) 110 { 111 efx_port_t *epp = &(enp->en_port); 112 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 113 const efx_mac_ops_t *emop = epp->ep_emop; 114 efx_rc_t rc; 115 116 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 117 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 118 EFSYS_ASSERT(emop != NULL); 119 120 EFSYS_ASSERT(link_mode < EFX_LINK_NMODES); 121 122 if (EFX_TEST_QWORD_BIT(encp->enc_loopback_types[link_mode], 123 (int)loopback_type) == 0) { 124 rc = ENOTSUP; 125 goto fail1; 126 } 127 128 if (epp->ep_loopback_type == loopback_type && 129 epp->ep_loopback_link_mode == link_mode) 130 return (0); 131 132 if ((rc = emop->emo_loopback_set(enp, link_mode, loopback_type)) != 0) 133 goto fail2; 134 135 return (0); 136 137 fail2: 138 EFSYS_PROBE(fail2); 139 fail1: 140 EFSYS_PROBE1(fail1, efx_rc_t, rc); 141 142 return (rc); 143 } 144 145 #if EFSYS_OPT_NAMES 146 147 static const char * const __efx_loopback_type_name[] = { 148 "OFF", 149 "DATA", 150 "GMAC", 151 "XGMII", 152 "XGXS", 153 "XAUI", 154 "GMII", 155 "SGMII", 156 "XGBR", 157 "XFI", 158 "XAUI_FAR", 159 "GMII_FAR", 160 "SGMII_FAR", 161 "XFI_FAR", 162 "GPHY", 163 "PHY_XS", 164 "PCS", 165 "PMA_PMD", 166 "XPORT", 167 "XGMII_WS", 168 "XAUI_WS", 169 "XAUI_WS_FAR", 170 "XAUI_WS_NEAR", 171 "GMII_WS", 172 "XFI_WS", 173 "XFI_WS_FAR", 174 "PHYXS_WS", 175 "PMA_INT", 176 "SD_NEAR", 177 "SD_FAR", 178 "PMA_INT_WS", 179 "SD_FEP2_WS", 180 "SD_FEP1_5_WS", 181 "SD_FEP_WS", 182 "SD_FES_WS", 183 "AOE_INT_NEAR", 184 "DATA_WS", 185 "FORCE_EXT_LINK", 186 }; 187 188 __checkReturn const char * 189 efx_loopback_type_name( 190 __in efx_nic_t *enp, 191 __in efx_loopback_type_t type) 192 { 193 EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__efx_loopback_type_name) == 194 EFX_LOOPBACK_NTYPES); 195 196 _NOTE(ARGUNUSED(enp)) 197 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 198 EFSYS_ASSERT3U(type, <, EFX_LOOPBACK_NTYPES); 199 200 return (__efx_loopback_type_name[type]); 201 } 202 203 #endif /* EFSYS_OPT_NAMES */ 204 205 #endif /* EFSYS_OPT_LOOPBACK */ 206 207 void 208 efx_port_fini( 209 __in efx_nic_t *enp) 210 { 211 efx_port_t *epp = &(enp->en_port); 212 const efx_phy_ops_t *epop = epp->ep_epop; 213 214 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 215 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 216 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC); 217 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 218 219 EFSYS_ASSERT(epp->ep_mac_drain); 220 221 epp->ep_emop = NULL; 222 epp->ep_mac_type = EFX_MAC_INVALID; 223 epp->ep_mac_drain = B_FALSE; 224 225 /* Turn off the PHY */ 226 if (epop->epo_power != NULL) 227 (void) epop->epo_power(enp, B_FALSE); 228 229 enp->en_mod_flags &= ~EFX_MOD_PORT; 230 } 231