efx_port.c revision 283514
1202878Srdivacky/*- 2202878Srdivacky * Copyright (c) 2009-2015 Solarflare Communications Inc. 3202878Srdivacky * All rights reserved. 4202878Srdivacky * 5202878Srdivacky * Redistribution and use in source and binary forms, with or without 6202878Srdivacky * modification, are permitted provided that the following conditions are met: 7202878Srdivacky * 8202878Srdivacky * 1. Redistributions of source code must retain the above copyright notice, 9202878Srdivacky * this list of conditions and the following disclaimer. 10202878Srdivacky * 2. Redistributions in binary form must reproduce the above copyright notice, 11202878Srdivacky * this list of conditions and the following disclaimer in the documentation 12202878Srdivacky * and/or other materials provided with the distribution. 13202878Srdivacky * 14202878Srdivacky * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15202878Srdivacky * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 16202878Srdivacky * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17202878Srdivacky * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 18202878Srdivacky * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19202878Srdivacky * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20202878Srdivacky * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21202878Srdivacky * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22202878Srdivacky * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23202878Srdivacky * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 24202878Srdivacky * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25202878Srdivacky * 26202878Srdivacky * The views and conclusions contained in the software and documentation are 27202878Srdivacky * those of the authors and should not be interpreted as representing official 28202878Srdivacky * policies, either expressed or implied, of the FreeBSD Project. 29202878Srdivacky */ 30202878Srdivacky 31202878Srdivacky#include <sys/cdefs.h> 32202878Srdivacky__FBSDID("$FreeBSD: head/sys/dev/sfxge/common/efx_port.c 283514 2015-05-25 08:34:55Z arybchik $"); 33202878Srdivacky 34202878Srdivacky#include "efsys.h" 35202878Srdivacky#include "efx.h" 36202878Srdivacky#include "efx_types.h" 37202878Srdivacky#include "efx_impl.h" 38202878Srdivacky 39202878Srdivacky __checkReturn int 40202878Srdivackyefx_port_init( 41202878Srdivacky __in efx_nic_t *enp) 42202878Srdivacky{ 43202878Srdivacky efx_port_t *epp = &(enp->en_port); 44202878Srdivacky efx_phy_ops_t *epop = epp->ep_epop; 45202878Srdivacky int rc; 46202878Srdivacky 47202878Srdivacky EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 48202878Srdivacky EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 49202878Srdivacky EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC); 50202878Srdivacky 51202878Srdivacky if (enp->en_mod_flags & EFX_MOD_PORT) { 52202878Srdivacky rc = EINVAL; 53202878Srdivacky goto fail1; 54202878Srdivacky } 55202878Srdivacky 56202878Srdivacky enp->en_mod_flags |= EFX_MOD_PORT; 57202878Srdivacky 58202878Srdivacky epp->ep_mac_type = EFX_MAC_INVALID; 59202878Srdivacky epp->ep_link_mode = EFX_LINK_UNKNOWN; 60202878Srdivacky epp->ep_mac_poll_needed = B_TRUE; 61202878Srdivacky epp->ep_mac_drain = B_TRUE; 62202878Srdivacky 63202878Srdivacky /* Configure the MAC */ 64202878Srdivacky if ((rc = efx_mac_select(enp)) != 0) 65202878Srdivacky goto fail1; 66202878Srdivacky 67202878Srdivacky epp->ep_emop->emo_reconfigure(enp); 68202878Srdivacky 69202878Srdivacky /* Pick up current phy capababilities */ 70202878Srdivacky efx_port_poll(enp, NULL); 71202878Srdivacky 72202878Srdivacky /* 73202878Srdivacky * Turn on the PHY if available, otherwise reset it, and 74202878Srdivacky * reconfigure it with the current configuration. 75202878Srdivacky */ 76202878Srdivacky if (epop->epo_power != NULL) { 77207618Srdivacky if ((rc = epop->epo_power(enp, B_TRUE)) != 0) 78207618Srdivacky goto fail2; 79207618Srdivacky } else { 80207618Srdivacky if ((rc = epop->epo_reset(enp)) != 0) 81207618Srdivacky goto fail2; 82202878Srdivacky } 83202878Srdivacky 84202878Srdivacky EFSYS_ASSERT(enp->en_reset_flags & EFX_RESET_PHY); 85202878Srdivacky enp->en_reset_flags &= ~EFX_RESET_PHY; 86202878Srdivacky 87202878Srdivacky if ((rc = epop->epo_reconfigure(enp)) != 0) 88202878Srdivacky goto fail3; 89202878Srdivacky 90202878Srdivacky return (0); 91202878Srdivacky 92202878Srdivackyfail3: 93202878Srdivacky EFSYS_PROBE(fail3); 94202878Srdivackyfail2: 95202878Srdivacky EFSYS_PROBE(fail2); 96202878Srdivackyfail1: 97202878Srdivacky EFSYS_PROBE1(fail1, int, rc); 98202878Srdivacky 99202878Srdivacky enp->en_mod_flags &= ~EFX_MOD_PORT; 100202878Srdivacky 101202878Srdivacky return (rc); 102202878Srdivacky} 103202878Srdivacky 104202878Srdivacky __checkReturn int 105202878Srdivackyefx_port_poll( 106202878Srdivacky __in efx_nic_t *enp, 107202878Srdivacky __out_opt efx_link_mode_t *link_modep) 108202878Srdivacky{ 109202878Srdivacky efx_port_t *epp = &(enp->en_port); 110202878Srdivacky efx_mac_ops_t *emop = epp->ep_emop; 111202878Srdivacky efx_link_mode_t ignore_link_mode; 112202878Srdivacky int rc; 113202878Srdivacky 114202878Srdivacky EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 115202878Srdivacky EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 116202878Srdivacky 117202878Srdivacky EFSYS_ASSERT(emop != NULL); 118202878Srdivacky EFSYS_ASSERT(!epp->ep_mac_stats_pending); 119202878Srdivacky 120202878Srdivacky if (link_modep == NULL) 121202878Srdivacky link_modep = &ignore_link_mode; 122202878Srdivacky 123202878Srdivacky if ((rc = emop->emo_poll(enp, link_modep)) != 0) 124202878Srdivacky goto fail1; 125202878Srdivacky 126202878Srdivacky return (0); 127202878Srdivacky 128202878Srdivackyfail1: 129202878Srdivacky EFSYS_PROBE1(fail1, int, rc); 130202878Srdivacky 131202878Srdivacky return (rc); 132202878Srdivacky} 133202878Srdivacky 134202878Srdivacky#if EFSYS_OPT_LOOPBACK 135202878Srdivacky 136202878Srdivacky __checkReturn int 137202878Srdivackyefx_port_loopback_set( 138202878Srdivacky __in efx_nic_t *enp, 139202878Srdivacky __in efx_link_mode_t link_mode, 140202878Srdivacky __in efx_loopback_type_t loopback_type) 141202878Srdivacky{ 142202878Srdivacky efx_port_t *epp = &(enp->en_port); 143205218Srdivacky efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 144205218Srdivacky efx_mac_ops_t *emop = epp->ep_emop; 145205218Srdivacky int rc; 146205218Srdivacky 147205218Srdivacky EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 148205218Srdivacky EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 149205218Srdivacky EFSYS_ASSERT(emop != NULL); 150205218Srdivacky 151202878Srdivacky EFSYS_ASSERT(link_mode < EFX_LINK_NMODES); 152202878Srdivacky 153202878Srdivacky if (EFX_TEST_QWORD_BIT(encp->enc_loopback_types[link_mode], 154202878Srdivacky loopback_type) == 0) { 155202878Srdivacky rc = ENOTSUP; 156208599Srdivacky goto fail1; 157208599Srdivacky } 158208599Srdivacky 159208599Srdivacky if (epp->ep_loopback_type == loopback_type && 160208599Srdivacky epp->ep_loopback_link_mode == link_mode) 161208599Srdivacky return (0); 162202878Srdivacky 163202878Srdivacky if ((rc = emop->emo_loopback_set(enp, link_mode, loopback_type)) != 0) 164202878Srdivacky goto fail2; 165202878Srdivacky 166202878Srdivacky return (0); 167202878Srdivacky 168202878Srdivackyfail2: 169202878Srdivacky EFSYS_PROBE(fail2); 170202878Srdivackyfail1: 171202878Srdivacky EFSYS_PROBE1(fail1, int, rc); 172202878Srdivacky 173202878Srdivacky return (rc); 174202878Srdivacky} 175202878Srdivacky 176202878Srdivacky#if EFSYS_OPT_NAMES 177202878Srdivacky 178202878Srdivackystatic const char *__efx_loopback_type_name[] = { 179202878Srdivacky "OFF", 180202878Srdivacky "DATA", 181202878Srdivacky "GMAC", 182202878Srdivacky "XGMII", 183202878Srdivacky "XGXS", 184202878Srdivacky "XAUI", 185202878Srdivacky "GMII", 186202878Srdivacky "SGMII", 187202878Srdivacky "XGBR", 188202878Srdivacky "XFI", 189202878Srdivacky "XAUI_FAR", 190202878Srdivacky "GMII_FAR", 191202878Srdivacky "SGMII_FAR", 192202878Srdivacky "XFI_FAR", 193202878Srdivacky "GPHY", 194202878Srdivacky "PHY_XS", 195202878Srdivacky "PCS", 196202878Srdivacky "PMA_PMD", 197202878Srdivacky "XPORT", 198202878Srdivacky "XGMII_WS", 199202878Srdivacky "XAUI_WS", 200202878Srdivacky "XAUI_WS_FAR", 201202878Srdivacky "XAUI_WS_NEAR", 202202878Srdivacky "GMII_WS", 203202878Srdivacky "XFI_WS", 204202878Srdivacky "XFI_WS_FAR", 205202878Srdivacky "PHYXS_WS", 206202878Srdivacky "PMA_INT", 207202878Srdivacky "SD_NEAR", 208202878Srdivacky "SD_FAR", 209202878Srdivacky "PMA_INT_WS", 210202878Srdivacky "SD_FEP2_WS", 211202878Srdivacky "SD_FEP1_5_WS", 212202878Srdivacky "SD_FEP_WS", 213202878Srdivacky "SD_FES_WS", 214202878Srdivacky}; 215202878Srdivacky 216202878Srdivacky __checkReturn const char * 217202878Srdivackyefx_loopback_type_name( 218202878Srdivacky __in efx_nic_t *enp, 219202878Srdivacky __in efx_loopback_type_t type) 220202878Srdivacky{ 221202878Srdivacky EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__efx_loopback_type_name) == 222202878Srdivacky EFX_LOOPBACK_NTYPES); 223202878Srdivacky 224202878Srdivacky _NOTE(ARGUNUSED(enp)) 225202878Srdivacky EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 226202878Srdivacky EFSYS_ASSERT3U(type, <, EFX_LOOPBACK_NTYPES); 227202878Srdivacky 228202878Srdivacky return (__efx_loopback_type_name[type]); 229202878Srdivacky} 230202878Srdivacky 231202878Srdivacky#endif /* EFSYS_OPT_NAMES */ 232202878Srdivacky 233202878Srdivacky#endif /* EFSYS_OPT_LOOPBACK */ 234202878Srdivacky 235202878Srdivacky void 236202878Srdivackyefx_port_fini( 237202878Srdivacky __in efx_nic_t *enp) 238202878Srdivacky{ 239202878Srdivacky efx_port_t *epp = &(enp->en_port); 240202878Srdivacky efx_phy_ops_t *epop = epp->ep_epop; 241202878Srdivacky 242202878Srdivacky EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 243202878Srdivacky EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 244202878Srdivacky EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC); 245202878Srdivacky EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 246202878Srdivacky 247202878Srdivacky EFSYS_ASSERT(epp->ep_mac_drain); 248202878Srdivacky 249202878Srdivacky epp->ep_emop = NULL; 250202878Srdivacky epp->ep_mac_type = EFX_MAC_INVALID; 251202878Srdivacky epp->ep_mac_drain = B_FALSE; 252202878Srdivacky epp->ep_mac_poll_needed = B_FALSE; 253202878Srdivacky 254202878Srdivacky /* Turn off the PHY */ 255202878Srdivacky if (epop->epo_power != NULL) 256202878Srdivacky (void) epop->epo_power(enp, B_FALSE); 257202878Srdivacky 258202878Srdivacky enp->en_mod_flags &= ~EFX_MOD_PORT; 259202878Srdivacky} 260202878Srdivacky