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