1 /* 2 * Copyright (c) 2009-2015 Solarflare Communications Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 24 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * 26 * The views and conclusions contained in the software and documentation are 27 * those of the authors and should not be interpreted as representing official 28 * policies, either expressed or implied, of the FreeBSD Project. 29 */ 30 31 #include "efx.h" 32 #include "efx_impl.h" 33 34 __checkReturn efx_rc_t 35 efx_port_init( 36 __in efx_nic_t *enp) 37 { 38 efx_port_t *epp = &(enp->en_port); 39 const efx_phy_ops_t *epop = epp->ep_epop; 40 efx_rc_t rc; 41 42 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 43 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 44 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC); 45 46 if (enp->en_mod_flags & EFX_MOD_PORT) { 47 rc = EINVAL; 48 goto fail1; 49 } 50 51 enp->en_mod_flags |= EFX_MOD_PORT; 52 53 epp->ep_mac_type = EFX_MAC_INVALID; 54 epp->ep_link_mode = EFX_LINK_UNKNOWN; 55 epp->ep_mac_drain = B_TRUE; 56 57 /* Configure the MAC */ 58 if ((rc = efx_mac_select(enp)) != 0) 59 goto fail1; 60 61 epp->ep_emop->emo_reconfigure(enp); 62 63 /* Pick up current phy capababilities */ 64 (void) efx_port_poll(enp, NULL); 65 66 /* 67 * Turn on the PHY if available, otherwise reset it, and 68 * reconfigure it with the current configuration. 69 */ 70 if (epop->epo_power != NULL) { 71 if ((rc = epop->epo_power(enp, B_TRUE)) != 0) 72 goto fail2; 73 } else { 74 if ((rc = epop->epo_reset(enp)) != 0) 75 goto fail2; 76 } 77 78 EFSYS_ASSERT(enp->en_reset_flags & EFX_RESET_PHY); 79 enp->en_reset_flags &= ~EFX_RESET_PHY; 80 81 if ((rc = epop->epo_reconfigure(enp)) != 0) 82 goto fail3; 83 84 return (0); 85 86 fail3: 87 EFSYS_PROBE(fail3); 88 fail2: 89 EFSYS_PROBE(fail2); 90 fail1: 91 EFSYS_PROBE1(fail1, efx_rc_t, rc); 92 93 enp->en_mod_flags &= ~EFX_MOD_PORT; 94 95 return (rc); 96 } 97 98 __checkReturn efx_rc_t 99 efx_port_poll( 100 __in efx_nic_t *enp, 101 __out_opt efx_link_mode_t *link_modep) 102 { 103 efx_port_t *epp = &(enp->en_port); 104 const efx_mac_ops_t *emop = epp->ep_emop; 105 efx_link_mode_t ignore_link_mode; 106 efx_rc_t rc; 107 108 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 109 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 110 111 EFSYS_ASSERT(emop != NULL); 112 EFSYS_ASSERT(!epp->ep_mac_stats_pending); 113 114 if (link_modep == NULL) 115 link_modep = &ignore_link_mode; 116 117 if ((rc = emop->emo_poll(enp, link_modep)) != 0) 118 goto fail1; 119 120 return (0); 121 122 fail1: 123 EFSYS_PROBE1(fail1, efx_rc_t, rc); 124 125 return (rc); 126 } 127 128 #if EFSYS_OPT_LOOPBACK 129 130 __checkReturn efx_rc_t 131 efx_port_loopback_set( 132 __in efx_nic_t *enp, 133 __in efx_link_mode_t link_mode, 134 __in efx_loopback_type_t loopback_type) 135 { 136 efx_port_t *epp = &(enp->en_port); 137 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 138 const efx_mac_ops_t *emop = epp->ep_emop; 139 efx_rc_t rc; 140 141 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 142 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 143 EFSYS_ASSERT(emop != NULL); 144 145 EFSYS_ASSERT(link_mode < EFX_LINK_NMODES); 146 147 if (EFX_TEST_QWORD_BIT(encp->enc_loopback_types[link_mode], 148 loopback_type) == 0) { 149 rc = ENOTSUP; 150 goto fail1; 151 } 152 153 if (epp->ep_loopback_type == loopback_type && 154 epp->ep_loopback_link_mode == link_mode) 155 return (0); 156 157 if ((rc = emop->emo_loopback_set(enp, link_mode, loopback_type)) != 0) 158 goto fail2; 159 160 return (0); 161 162 fail2: 163 EFSYS_PROBE(fail2); 164 fail1: 165 EFSYS_PROBE1(fail1, efx_rc_t, rc); 166 167 return (rc); 168 } 169 170 #if EFSYS_OPT_NAMES 171 172 static const char *__efx_loopback_type_name[] = { 173 "OFF", 174 "DATA", 175 "GMAC", 176 "XGMII", 177 "XGXS", 178 "XAUI", 179 "GMII", 180 "SGMII", 181 "XGBR", 182 "XFI", 183 "XAUI_FAR", 184 "GMII_FAR", 185 "SGMII_FAR", 186 "XFI_FAR", 187 "GPHY", 188 "PHY_XS", 189 "PCS", 190 "PMA_PMD", 191 "XPORT", 192 "XGMII_WS", 193 "XAUI_WS", 194 "XAUI_WS_FAR", 195 "XAUI_WS_NEAR", 196 "GMII_WS", 197 "XFI_WS", 198 "XFI_WS_FAR", 199 "PHYXS_WS", 200 "PMA_INT", 201 "SD_NEAR", 202 "SD_FAR", 203 "PMA_INT_WS", 204 "SD_FEP2_WS", 205 "SD_FEP1_5_WS", 206 "SD_FEP_WS", 207 "SD_FES_WS", 208 }; 209 210 __checkReturn const char * 211 efx_loopback_type_name( 212 __in efx_nic_t *enp, 213 __in efx_loopback_type_t type) 214 { 215 EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__efx_loopback_type_name) == 216 EFX_LOOPBACK_NTYPES); 217 218 _NOTE(ARGUNUSED(enp)) 219 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 220 EFSYS_ASSERT3U(type, <, EFX_LOOPBACK_NTYPES); 221 222 return (__efx_loopback_type_name[type]); 223 } 224 225 #endif /* EFSYS_OPT_NAMES */ 226 227 #endif /* EFSYS_OPT_LOOPBACK */ 228 229 void 230 efx_port_fini( 231 __in efx_nic_t *enp) 232 { 233 efx_port_t *epp = &(enp->en_port); 234 const efx_phy_ops_t *epop = epp->ep_epop; 235 236 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 237 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 238 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC); 239 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 240 241 EFSYS_ASSERT(epp->ep_mac_drain); 242 243 epp->ep_emop = NULL; 244 epp->ep_mac_type = EFX_MAC_INVALID; 245 epp->ep_mac_drain = B_FALSE; 246 247 /* Turn off the PHY */ 248 if (epop->epo_power != NULL) 249 (void) epop->epo_power(enp, B_FALSE); 250 251 enp->en_mod_flags &= ~EFX_MOD_PORT; 252 } 253