efx_port.c revision 299517
1131087Smarcel/*- 2131087Smarcel * Copyright (c) 2009-2015 Solarflare Communications Inc. 3131087Smarcel * All rights reserved. 4131087Smarcel * 5131087Smarcel * Redistribution and use in source and binary forms, with or without 6131087Smarcel * modification, are permitted provided that the following conditions are met: 7131087Smarcel * 8131087Smarcel * 1. Redistributions of source code must retain the above copyright notice, 9131087Smarcel * this list of conditions and the following disclaimer. 10131087Smarcel * 2. Redistributions in binary form must reproduce the above copyright notice, 11131087Smarcel * this list of conditions and the following disclaimer in the documentation 12131087Smarcel * and/or other materials provided with the distribution. 13131087Smarcel * 14131087Smarcel * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15131087Smarcel * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 16131087Smarcel * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17131087Smarcel * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 18131087Smarcel * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19131087Smarcel * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20131087Smarcel * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21131087Smarcel * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22131087Smarcel * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23131087Smarcel * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 24131087Smarcel * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25131087Smarcel * 26131087Smarcel * The views and conclusions contained in the software and documentation are 27131087Smarcel * those of the authors and should not be interpreted as representing official 28131087Smarcel * policies, either expressed or implied, of the FreeBSD Project. 29131087Smarcel */ 30131087Smarcel 31131087Smarcel#include <sys/cdefs.h> 32131087Smarcel__FBSDID("$FreeBSD: head/sys/dev/sfxge/common/efx_port.c 299517 2016-05-12 06:19:06Z arybchik $"); 33131087Smarcel 34131087Smarcel#include "efx.h" 35131087Smarcel#include "efx_impl.h" 36131087Smarcel 37131087Smarcel __checkReturn efx_rc_t 38131087Smarcelefx_port_init( 39131087Smarcel __in efx_nic_t *enp) 40134154Sdavidxu{ 41131087Smarcel efx_port_t *epp = &(enp->en_port); 42131087Smarcel const efx_phy_ops_t *epop = epp->ep_epop; 43131087Smarcel efx_rc_t rc; 44134154Sdavidxu 45134154Sdavidxu EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 46134154Sdavidxu EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 47134154Sdavidxu EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC); 48131087Smarcel 49131087Smarcel if (enp->en_mod_flags & EFX_MOD_PORT) { 50131087Smarcel rc = EINVAL; 51131087Smarcel goto fail1; 52131087Smarcel } 53131087Smarcel 54131087Smarcel enp->en_mod_flags |= EFX_MOD_PORT; 55131087Smarcel 56131087Smarcel epp->ep_mac_type = EFX_MAC_INVALID; 57 epp->ep_link_mode = EFX_LINK_UNKNOWN; 58 epp->ep_mac_drain = B_TRUE; 59 60 /* Configure the MAC */ 61 if ((rc = efx_mac_select(enp)) != 0) 62 goto fail1; 63 64 epp->ep_emop->emo_reconfigure(enp); 65 66 /* Pick up current phy capababilities */ 67 efx_port_poll(enp, NULL); 68 69 /* 70 * Turn on the PHY if available, otherwise reset it, and 71 * reconfigure it with the current configuration. 72 */ 73 if (epop->epo_power != NULL) { 74 if ((rc = epop->epo_power(enp, B_TRUE)) != 0) 75 goto fail2; 76 } else { 77 if ((rc = epop->epo_reset(enp)) != 0) 78 goto fail2; 79 } 80 81 EFSYS_ASSERT(enp->en_reset_flags & EFX_RESET_PHY); 82 enp->en_reset_flags &= ~EFX_RESET_PHY; 83 84 if ((rc = epop->epo_reconfigure(enp)) != 0) 85 goto fail3; 86 87 return (0); 88 89fail3: 90 EFSYS_PROBE(fail3); 91fail2: 92 EFSYS_PROBE(fail2); 93fail1: 94 EFSYS_PROBE1(fail1, efx_rc_t, rc); 95 96 enp->en_mod_flags &= ~EFX_MOD_PORT; 97 98 return (rc); 99} 100 101 __checkReturn efx_rc_t 102efx_port_poll( 103 __in efx_nic_t *enp, 104 __out_opt efx_link_mode_t *link_modep) 105{ 106 efx_port_t *epp = &(enp->en_port); 107 const efx_mac_ops_t *emop = epp->ep_emop; 108 efx_link_mode_t ignore_link_mode; 109 efx_rc_t rc; 110 111 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 112 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 113 114 EFSYS_ASSERT(emop != NULL); 115 EFSYS_ASSERT(!epp->ep_mac_stats_pending); 116 117 if (link_modep == NULL) 118 link_modep = &ignore_link_mode; 119 120 if ((rc = emop->emo_poll(enp, link_modep)) != 0) 121 goto fail1; 122 123 return (0); 124 125fail1: 126 EFSYS_PROBE1(fail1, efx_rc_t, rc); 127 128 return (rc); 129} 130 131#if EFSYS_OPT_LOOPBACK 132 133 __checkReturn efx_rc_t 134efx_port_loopback_set( 135 __in efx_nic_t *enp, 136 __in efx_link_mode_t link_mode, 137 __in efx_loopback_type_t loopback_type) 138{ 139 efx_port_t *epp = &(enp->en_port); 140 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 141 const efx_mac_ops_t *emop = epp->ep_emop; 142 efx_rc_t rc; 143 144 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 145 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 146 EFSYS_ASSERT(emop != NULL); 147 148 EFSYS_ASSERT(link_mode < EFX_LINK_NMODES); 149 150 if (EFX_TEST_QWORD_BIT(encp->enc_loopback_types[link_mode], 151 loopback_type) == 0) { 152 rc = ENOTSUP; 153 goto fail1; 154 } 155 156 if (epp->ep_loopback_type == loopback_type && 157 epp->ep_loopback_link_mode == link_mode) 158 return (0); 159 160 if ((rc = emop->emo_loopback_set(enp, link_mode, loopback_type)) != 0) 161 goto fail2; 162 163 return (0); 164 165fail2: 166 EFSYS_PROBE(fail2); 167fail1: 168 EFSYS_PROBE1(fail1, efx_rc_t, rc); 169 170 return (rc); 171} 172 173#if EFSYS_OPT_NAMES 174 175static const char *__efx_loopback_type_name[] = { 176 "OFF", 177 "DATA", 178 "GMAC", 179 "XGMII", 180 "XGXS", 181 "XAUI", 182 "GMII", 183 "SGMII", 184 "XGBR", 185 "XFI", 186 "XAUI_FAR", 187 "GMII_FAR", 188 "SGMII_FAR", 189 "XFI_FAR", 190 "GPHY", 191 "PHY_XS", 192 "PCS", 193 "PMA_PMD", 194 "XPORT", 195 "XGMII_WS", 196 "XAUI_WS", 197 "XAUI_WS_FAR", 198 "XAUI_WS_NEAR", 199 "GMII_WS", 200 "XFI_WS", 201 "XFI_WS_FAR", 202 "PHYXS_WS", 203 "PMA_INT", 204 "SD_NEAR", 205 "SD_FAR", 206 "PMA_INT_WS", 207 "SD_FEP2_WS", 208 "SD_FEP1_5_WS", 209 "SD_FEP_WS", 210 "SD_FES_WS", 211}; 212 213 __checkReturn const char * 214efx_loopback_type_name( 215 __in efx_nic_t *enp, 216 __in efx_loopback_type_t type) 217{ 218 EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__efx_loopback_type_name) == 219 EFX_LOOPBACK_NTYPES); 220 221 _NOTE(ARGUNUSED(enp)) 222 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 223 EFSYS_ASSERT3U(type, <, EFX_LOOPBACK_NTYPES); 224 225 return (__efx_loopback_type_name[type]); 226} 227 228#endif /* EFSYS_OPT_NAMES */ 229 230#endif /* EFSYS_OPT_LOOPBACK */ 231 232 void 233efx_port_fini( 234 __in efx_nic_t *enp) 235{ 236 efx_port_t *epp = &(enp->en_port); 237 const efx_phy_ops_t *epop = epp->ep_epop; 238 239 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 240 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 241 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC); 242 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 243 244 EFSYS_ASSERT(epp->ep_mac_drain); 245 246 epp->ep_emop = NULL; 247 epp->ep_mac_type = EFX_MAC_INVALID; 248 epp->ep_mac_drain = B_FALSE; 249 250 /* Turn off the PHY */ 251 if (epop->epo_power != NULL) 252 (void) epop->epo_power(enp, B_FALSE); 253 254 enp->en_mod_flags &= ~EFX_MOD_PORT; 255} 256