1227569Sphilip/*- 2300607Sarybchik * Copyright (c) 2009-2016 Solarflare Communications Inc. 3283514Sarybchik * All rights reserved. 4227569Sphilip * 5227569Sphilip * Redistribution and use in source and binary forms, with or without 6283514Sarybchik * modification, are permitted provided that the following conditions are met: 7227569Sphilip * 8283514Sarybchik * 1. Redistributions of source code must retain the above copyright notice, 9283514Sarybchik * this list of conditions and the following disclaimer. 10283514Sarybchik * 2. Redistributions in binary form must reproduce the above copyright notice, 11283514Sarybchik * this list of conditions and the following disclaimer in the documentation 12283514Sarybchik * and/or other materials provided with the distribution. 13283514Sarybchik * 14283514Sarybchik * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15283514Sarybchik * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 16283514Sarybchik * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17283514Sarybchik * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 18283514Sarybchik * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19283514Sarybchik * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20283514Sarybchik * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21283514Sarybchik * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22283514Sarybchik * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23283514Sarybchik * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 24283514Sarybchik * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25283514Sarybchik * 26283514Sarybchik * The views and conclusions contained in the software and documentation are 27283514Sarybchik * those of the authors and should not be interpreted as representing official 28283514Sarybchik * policies, either expressed or implied, of the FreeBSD Project. 29227569Sphilip */ 30228078Sphilip 31228078Sphilip#include <sys/cdefs.h> 32228078Sphilip__FBSDID("$FreeBSD: releng/11.0/sys/dev/sfxge/common/siena_phy.c 300607 2016-05-24 12:16:57Z arybchik $"); 33228078Sphilip 34227569Sphilip#include "efx.h" 35227569Sphilip#include "efx_impl.h" 36227569Sphilip 37227569Sphilip#if EFSYS_OPT_SIENA 38227569Sphilip 39227569Sphilipstatic void 40227569Sphilipsiena_phy_decode_cap( 41227569Sphilip __in uint32_t mcdi_cap, 42227569Sphilip __out uint32_t *maskp) 43227569Sphilip{ 44227569Sphilip uint32_t mask; 45227569Sphilip 46227569Sphilip mask = 0; 47227569Sphilip if (mcdi_cap & (1 << MC_CMD_PHY_CAP_10HDX_LBN)) 48227569Sphilip mask |= (1 << EFX_PHY_CAP_10HDX); 49227569Sphilip if (mcdi_cap & (1 << MC_CMD_PHY_CAP_10FDX_LBN)) 50227569Sphilip mask |= (1 << EFX_PHY_CAP_10FDX); 51227569Sphilip if (mcdi_cap & (1 << MC_CMD_PHY_CAP_100HDX_LBN)) 52227569Sphilip mask |= (1 << EFX_PHY_CAP_100HDX); 53227569Sphilip if (mcdi_cap & (1 << MC_CMD_PHY_CAP_100FDX_LBN)) 54227569Sphilip mask |= (1 << EFX_PHY_CAP_100FDX); 55227569Sphilip if (mcdi_cap & (1 << MC_CMD_PHY_CAP_1000HDX_LBN)) 56227569Sphilip mask |= (1 << EFX_PHY_CAP_1000HDX); 57227569Sphilip if (mcdi_cap & (1 << MC_CMD_PHY_CAP_1000FDX_LBN)) 58227569Sphilip mask |= (1 << EFX_PHY_CAP_1000FDX); 59227569Sphilip if (mcdi_cap & (1 << MC_CMD_PHY_CAP_10000FDX_LBN)) 60227569Sphilip mask |= (1 << EFX_PHY_CAP_10000FDX); 61227569Sphilip if (mcdi_cap & (1 << MC_CMD_PHY_CAP_PAUSE_LBN)) 62227569Sphilip mask |= (1 << EFX_PHY_CAP_PAUSE); 63227569Sphilip if (mcdi_cap & (1 << MC_CMD_PHY_CAP_ASYM_LBN)) 64227569Sphilip mask |= (1 << EFX_PHY_CAP_ASYM); 65227569Sphilip if (mcdi_cap & (1 << MC_CMD_PHY_CAP_AN_LBN)) 66227569Sphilip mask |= (1 << EFX_PHY_CAP_AN); 67227569Sphilip 68227569Sphilip *maskp = mask; 69227569Sphilip} 70227569Sphilip 71227569Sphilipstatic void 72227569Sphilipsiena_phy_decode_link_mode( 73227569Sphilip __in efx_nic_t *enp, 74227569Sphilip __in uint32_t link_flags, 75227569Sphilip __in unsigned int speed, 76227569Sphilip __in unsigned int fcntl, 77227569Sphilip __out efx_link_mode_t *link_modep, 78227569Sphilip __out unsigned int *fcntlp) 79227569Sphilip{ 80227569Sphilip boolean_t fd = !!(link_flags & 81227569Sphilip (1 << MC_CMD_GET_LINK_OUT_FULL_DUPLEX_LBN)); 82227569Sphilip boolean_t up = !!(link_flags & 83227569Sphilip (1 << MC_CMD_GET_LINK_OUT_LINK_UP_LBN)); 84227569Sphilip 85227569Sphilip _NOTE(ARGUNUSED(enp)) 86227569Sphilip 87227569Sphilip if (!up) 88227569Sphilip *link_modep = EFX_LINK_DOWN; 89227569Sphilip else if (speed == 10000 && fd) 90227569Sphilip *link_modep = EFX_LINK_10000FDX; 91227569Sphilip else if (speed == 1000) 92227569Sphilip *link_modep = fd ? EFX_LINK_1000FDX : EFX_LINK_1000HDX; 93227569Sphilip else if (speed == 100) 94227569Sphilip *link_modep = fd ? EFX_LINK_100FDX : EFX_LINK_100HDX; 95227569Sphilip else if (speed == 10) 96227569Sphilip *link_modep = fd ? EFX_LINK_10FDX : EFX_LINK_10HDX; 97227569Sphilip else 98227569Sphilip *link_modep = EFX_LINK_UNKNOWN; 99227569Sphilip 100227569Sphilip if (fcntl == MC_CMD_FCNTL_OFF) 101227569Sphilip *fcntlp = 0; 102227569Sphilip else if (fcntl == MC_CMD_FCNTL_RESPOND) 103227569Sphilip *fcntlp = EFX_FCNTL_RESPOND; 104227569Sphilip else if (fcntl == MC_CMD_FCNTL_BIDIR) 105227569Sphilip *fcntlp = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE; 106227569Sphilip else { 107227569Sphilip EFSYS_PROBE1(mc_pcol_error, int, fcntl); 108227569Sphilip *fcntlp = 0; 109227569Sphilip } 110227569Sphilip} 111227569Sphilip 112227569Sphilip void 113227569Sphilipsiena_phy_link_ev( 114227569Sphilip __in efx_nic_t *enp, 115227569Sphilip __in efx_qword_t *eqp, 116227569Sphilip __out efx_link_mode_t *link_modep) 117227569Sphilip{ 118227569Sphilip efx_port_t *epp = &(enp->en_port); 119227569Sphilip unsigned int link_flags; 120227569Sphilip unsigned int speed; 121227569Sphilip unsigned int fcntl; 122227569Sphilip efx_link_mode_t link_mode; 123227569Sphilip uint32_t lp_cap_mask; 124227569Sphilip 125227569Sphilip /* 126227569Sphilip * Convert the LINKCHANGE speed enumeration into mbit/s, in the 127227569Sphilip * same way as GET_LINK encodes the speed 128227569Sphilip */ 129278942Sarybchik switch (MCDI_EV_FIELD(eqp, LINKCHANGE_SPEED)) { 130227569Sphilip case MCDI_EVENT_LINKCHANGE_SPEED_100M: 131227569Sphilip speed = 100; 132227569Sphilip break; 133227569Sphilip case MCDI_EVENT_LINKCHANGE_SPEED_1G: 134227569Sphilip speed = 1000; 135227569Sphilip break; 136227569Sphilip case MCDI_EVENT_LINKCHANGE_SPEED_10G: 137227569Sphilip speed = 10000; 138227569Sphilip break; 139227569Sphilip default: 140227569Sphilip speed = 0; 141227569Sphilip break; 142227569Sphilip } 143227569Sphilip 144278942Sarybchik link_flags = MCDI_EV_FIELD(eqp, LINKCHANGE_LINK_FLAGS); 145227569Sphilip siena_phy_decode_link_mode(enp, link_flags, speed, 146278942Sarybchik MCDI_EV_FIELD(eqp, LINKCHANGE_FCNTL), 147227569Sphilip &link_mode, &fcntl); 148278942Sarybchik siena_phy_decode_cap(MCDI_EV_FIELD(eqp, LINKCHANGE_LP_CAP), 149227569Sphilip &lp_cap_mask); 150227569Sphilip 151227569Sphilip /* 152227569Sphilip * It's safe to update ep_lp_cap_mask without the driver's port lock 153227569Sphilip * because presumably any concurrently running efx_port_poll() is 154227569Sphilip * only going to arrive at the same value. 155227569Sphilip * 156227569Sphilip * ep_fcntl has two meanings. It's either the link common fcntl 157227569Sphilip * (if the PHY supports AN), or it's the forced link state. If 158227569Sphilip * the former, it's safe to update the value for the same reason as 159227569Sphilip * for ep_lp_cap_mask. If the latter, then just ignore the value, 160227569Sphilip * because we can race with efx_mac_fcntl_set(). 161227569Sphilip */ 162227569Sphilip epp->ep_lp_cap_mask = lp_cap_mask; 163227569Sphilip if (epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_AN)) 164227569Sphilip epp->ep_fcntl = fcntl; 165227569Sphilip 166227569Sphilip *link_modep = link_mode; 167227569Sphilip} 168227569Sphilip 169291436Sarybchik __checkReturn efx_rc_t 170227569Sphilipsiena_phy_power( 171227569Sphilip __in efx_nic_t *enp, 172227569Sphilip __in boolean_t power) 173227569Sphilip{ 174291436Sarybchik efx_rc_t rc; 175227569Sphilip 176227569Sphilip if (!power) 177227569Sphilip return (0); 178227569Sphilip 179227569Sphilip /* Check if the PHY is a zombie */ 180227569Sphilip if ((rc = siena_phy_verify(enp)) != 0) 181227569Sphilip goto fail1; 182227569Sphilip 183227569Sphilip enp->en_reset_flags |= EFX_RESET_PHY; 184227569Sphilip 185227569Sphilip return (0); 186227569Sphilip 187227569Sphilipfail1: 188291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 189227569Sphilip 190227569Sphilip return (rc); 191227569Sphilip} 192227569Sphilip 193291436Sarybchik __checkReturn efx_rc_t 194227569Sphilipsiena_phy_get_link( 195227569Sphilip __in efx_nic_t *enp, 196227569Sphilip __out siena_link_state_t *slsp) 197227569Sphilip{ 198227569Sphilip efx_mcdi_req_t req; 199283514Sarybchik uint8_t payload[MAX(MC_CMD_GET_LINK_IN_LEN, 200283514Sarybchik MC_CMD_GET_LINK_OUT_LEN)]; 201291436Sarybchik efx_rc_t rc; 202227569Sphilip 203283514Sarybchik (void) memset(payload, 0, sizeof (payload)); 204227569Sphilip req.emr_cmd = MC_CMD_GET_LINK; 205283514Sarybchik req.emr_in_buf = payload; 206283514Sarybchik req.emr_in_length = MC_CMD_GET_LINK_IN_LEN; 207283514Sarybchik req.emr_out_buf = payload; 208283514Sarybchik req.emr_out_length = MC_CMD_GET_LINK_OUT_LEN; 209227569Sphilip 210227569Sphilip efx_mcdi_execute(enp, &req); 211227569Sphilip 212227569Sphilip if (req.emr_rc != 0) { 213227569Sphilip rc = req.emr_rc; 214227569Sphilip goto fail1; 215227569Sphilip } 216227569Sphilip 217227569Sphilip if (req.emr_out_length_used < MC_CMD_GET_LINK_OUT_LEN) { 218227569Sphilip rc = EMSGSIZE; 219227569Sphilip goto fail2; 220227569Sphilip } 221227569Sphilip 222227569Sphilip siena_phy_decode_cap(MCDI_OUT_DWORD(req, GET_LINK_OUT_CAP), 223227569Sphilip &slsp->sls_adv_cap_mask); 224227569Sphilip siena_phy_decode_cap(MCDI_OUT_DWORD(req, GET_LINK_OUT_LP_CAP), 225227569Sphilip &slsp->sls_lp_cap_mask); 226227569Sphilip 227227569Sphilip siena_phy_decode_link_mode(enp, MCDI_OUT_DWORD(req, GET_LINK_OUT_FLAGS), 228227569Sphilip MCDI_OUT_DWORD(req, GET_LINK_OUT_LINK_SPEED), 229227569Sphilip MCDI_OUT_DWORD(req, GET_LINK_OUT_FCNTL), 230227569Sphilip &slsp->sls_link_mode, &slsp->sls_fcntl); 231227569Sphilip 232227569Sphilip#if EFSYS_OPT_LOOPBACK 233227569Sphilip /* Assert the MC_CMD_LOOPBACK and EFX_LOOPBACK namespace agree */ 234227569Sphilip EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_NONE == EFX_LOOPBACK_OFF); 235227569Sphilip EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_DATA == EFX_LOOPBACK_DATA); 236227569Sphilip EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GMAC == EFX_LOOPBACK_GMAC); 237227569Sphilip EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XGMII == EFX_LOOPBACK_XGMII); 238227569Sphilip EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XGXS == EFX_LOOPBACK_XGXS); 239227569Sphilip EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XAUI == EFX_LOOPBACK_XAUI); 240227569Sphilip EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GMII == EFX_LOOPBACK_GMII); 241227569Sphilip EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SGMII == EFX_LOOPBACK_SGMII); 242227569Sphilip EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XGBR == EFX_LOOPBACK_XGBR); 243227569Sphilip EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XFI == EFX_LOOPBACK_XFI); 244227569Sphilip EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XAUI_FAR == EFX_LOOPBACK_XAUI_FAR); 245227569Sphilip EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GMII_FAR == EFX_LOOPBACK_GMII_FAR); 246227569Sphilip EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SGMII_FAR == EFX_LOOPBACK_SGMII_FAR); 247227569Sphilip EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XFI_FAR == EFX_LOOPBACK_XFI_FAR); 248227569Sphilip EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GPHY == EFX_LOOPBACK_GPHY); 249227569Sphilip EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PHYXS == EFX_LOOPBACK_PHY_XS); 250227569Sphilip EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PCS == EFX_LOOPBACK_PCS); 251227569Sphilip EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PMAPMD == EFX_LOOPBACK_PMA_PMD); 252227569Sphilip 253227569Sphilip slsp->sls_loopback = MCDI_OUT_DWORD(req, GET_LINK_OUT_LOOPBACK_MODE); 254227569Sphilip#endif /* EFSYS_OPT_LOOPBACK */ 255227569Sphilip 256227569Sphilip slsp->sls_mac_up = MCDI_OUT_DWORD(req, GET_LINK_OUT_MAC_FAULT) == 0; 257227569Sphilip 258227569Sphilip return (0); 259227569Sphilip 260227569Sphilipfail2: 261227569Sphilip EFSYS_PROBE(fail2); 262227569Sphilipfail1: 263291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 264227569Sphilip 265227569Sphilip return (rc); 266227569Sphilip} 267227569Sphilip 268291436Sarybchik __checkReturn efx_rc_t 269227569Sphilipsiena_phy_reconfigure( 270227569Sphilip __in efx_nic_t *enp) 271227569Sphilip{ 272227569Sphilip efx_port_t *epp = &(enp->en_port); 273227569Sphilip efx_mcdi_req_t req; 274283514Sarybchik uint8_t payload[MAX(MAX(MC_CMD_SET_ID_LED_IN_LEN, 275283514Sarybchik MC_CMD_SET_ID_LED_OUT_LEN), 276283514Sarybchik MAX(MC_CMD_SET_LINK_IN_LEN, 277283514Sarybchik MC_CMD_SET_LINK_OUT_LEN))]; 278227569Sphilip uint32_t cap_mask; 279227569Sphilip unsigned int led_mode; 280227569Sphilip unsigned int speed; 281291436Sarybchik efx_rc_t rc; 282227569Sphilip 283283514Sarybchik (void) memset(payload, 0, sizeof (payload)); 284227569Sphilip req.emr_cmd = MC_CMD_SET_LINK; 285227569Sphilip req.emr_in_buf = payload; 286227569Sphilip req.emr_in_length = MC_CMD_SET_LINK_IN_LEN; 287283514Sarybchik req.emr_out_buf = payload; 288283514Sarybchik req.emr_out_length = MC_CMD_SET_LINK_OUT_LEN; 289227569Sphilip 290227569Sphilip cap_mask = epp->ep_adv_cap_mask; 291227569Sphilip MCDI_IN_POPULATE_DWORD_10(req, SET_LINK_IN_CAP, 292227569Sphilip PHY_CAP_10HDX, (cap_mask >> EFX_PHY_CAP_10HDX) & 0x1, 293227569Sphilip PHY_CAP_10FDX, (cap_mask >> EFX_PHY_CAP_10FDX) & 0x1, 294227569Sphilip PHY_CAP_100HDX, (cap_mask >> EFX_PHY_CAP_100HDX) & 0x1, 295227569Sphilip PHY_CAP_100FDX, (cap_mask >> EFX_PHY_CAP_100FDX) & 0x1, 296227569Sphilip PHY_CAP_1000HDX, (cap_mask >> EFX_PHY_CAP_1000HDX) & 0x1, 297227569Sphilip PHY_CAP_1000FDX, (cap_mask >> EFX_PHY_CAP_1000FDX) & 0x1, 298227569Sphilip PHY_CAP_10000FDX, (cap_mask >> EFX_PHY_CAP_10000FDX) & 0x1, 299227569Sphilip PHY_CAP_PAUSE, (cap_mask >> EFX_PHY_CAP_PAUSE) & 0x1, 300227569Sphilip PHY_CAP_ASYM, (cap_mask >> EFX_PHY_CAP_ASYM) & 0x1, 301227569Sphilip PHY_CAP_AN, (cap_mask >> EFX_PHY_CAP_AN) & 0x1); 302227569Sphilip 303227569Sphilip#if EFSYS_OPT_LOOPBACK 304227569Sphilip MCDI_IN_SET_DWORD(req, SET_LINK_IN_LOOPBACK_MODE, 305227569Sphilip epp->ep_loopback_type); 306227569Sphilip switch (epp->ep_loopback_link_mode) { 307227569Sphilip case EFX_LINK_100FDX: 308227569Sphilip speed = 100; 309227569Sphilip break; 310227569Sphilip case EFX_LINK_1000FDX: 311227569Sphilip speed = 1000; 312227569Sphilip break; 313227569Sphilip case EFX_LINK_10000FDX: 314227569Sphilip speed = 10000; 315227569Sphilip break; 316227569Sphilip default: 317227569Sphilip speed = 0; 318227569Sphilip } 319227569Sphilip#else 320227569Sphilip MCDI_IN_SET_DWORD(req, SET_LINK_IN_LOOPBACK_MODE, MC_CMD_LOOPBACK_NONE); 321227569Sphilip speed = 0; 322227569Sphilip#endif /* EFSYS_OPT_LOOPBACK */ 323227569Sphilip MCDI_IN_SET_DWORD(req, SET_LINK_IN_LOOPBACK_SPEED, speed); 324227569Sphilip 325227569Sphilip#if EFSYS_OPT_PHY_FLAGS 326227569Sphilip MCDI_IN_SET_DWORD(req, SET_LINK_IN_FLAGS, epp->ep_phy_flags); 327227569Sphilip#else 328227569Sphilip MCDI_IN_SET_DWORD(req, SET_LINK_IN_FLAGS, 0); 329227569Sphilip#endif /* EFSYS_OPT_PHY_FLAGS */ 330227569Sphilip 331227569Sphilip efx_mcdi_execute(enp, &req); 332227569Sphilip 333227569Sphilip if (req.emr_rc != 0) { 334227569Sphilip rc = req.emr_rc; 335227569Sphilip goto fail1; 336227569Sphilip } 337227569Sphilip 338227569Sphilip /* And set the blink mode */ 339283514Sarybchik (void) memset(payload, 0, sizeof (payload)); 340227569Sphilip req.emr_cmd = MC_CMD_SET_ID_LED; 341227569Sphilip req.emr_in_buf = payload; 342227569Sphilip req.emr_in_length = MC_CMD_SET_ID_LED_IN_LEN; 343283514Sarybchik req.emr_out_buf = payload; 344283514Sarybchik req.emr_out_length = MC_CMD_SET_ID_LED_OUT_LEN; 345227569Sphilip 346227569Sphilip#if EFSYS_OPT_PHY_LED_CONTROL 347227569Sphilip switch (epp->ep_phy_led_mode) { 348227569Sphilip case EFX_PHY_LED_DEFAULT: 349227569Sphilip led_mode = MC_CMD_LED_DEFAULT; 350227569Sphilip break; 351227569Sphilip case EFX_PHY_LED_OFF: 352227569Sphilip led_mode = MC_CMD_LED_OFF; 353227569Sphilip break; 354227569Sphilip case EFX_PHY_LED_ON: 355227569Sphilip led_mode = MC_CMD_LED_ON; 356227569Sphilip break; 357227569Sphilip default: 358227569Sphilip EFSYS_ASSERT(0); 359227569Sphilip led_mode = MC_CMD_LED_DEFAULT; 360227569Sphilip } 361227569Sphilip 362227569Sphilip MCDI_IN_SET_DWORD(req, SET_ID_LED_IN_STATE, led_mode); 363227569Sphilip#else 364227569Sphilip MCDI_IN_SET_DWORD(req, SET_ID_LED_IN_STATE, MC_CMD_LED_DEFAULT); 365227569Sphilip#endif /* EFSYS_OPT_PHY_LED_CONTROL */ 366227569Sphilip 367227569Sphilip efx_mcdi_execute(enp, &req); 368227569Sphilip 369227569Sphilip if (req.emr_rc != 0) { 370227569Sphilip rc = req.emr_rc; 371227569Sphilip goto fail2; 372227569Sphilip } 373227569Sphilip 374227569Sphilip return (0); 375227569Sphilip 376227569Sphilipfail2: 377227569Sphilip EFSYS_PROBE(fail2); 378227569Sphilipfail1: 379291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 380227569Sphilip 381227569Sphilip return (rc); 382227569Sphilip} 383227569Sphilip 384291436Sarybchik __checkReturn efx_rc_t 385227569Sphilipsiena_phy_verify( 386227569Sphilip __in efx_nic_t *enp) 387227569Sphilip{ 388227569Sphilip efx_mcdi_req_t req; 389283514Sarybchik uint8_t payload[MAX(MC_CMD_GET_PHY_STATE_IN_LEN, 390283514Sarybchik MC_CMD_GET_PHY_STATE_OUT_LEN)]; 391227569Sphilip uint32_t state; 392291436Sarybchik efx_rc_t rc; 393227569Sphilip 394283514Sarybchik (void) memset(payload, 0, sizeof (payload)); 395227569Sphilip req.emr_cmd = MC_CMD_GET_PHY_STATE; 396283514Sarybchik req.emr_in_buf = payload; 397283514Sarybchik req.emr_in_length = MC_CMD_GET_PHY_STATE_IN_LEN; 398283514Sarybchik req.emr_out_buf = payload; 399283514Sarybchik req.emr_out_length = MC_CMD_GET_PHY_STATE_OUT_LEN; 400227569Sphilip 401227569Sphilip efx_mcdi_execute(enp, &req); 402227569Sphilip 403227569Sphilip if (req.emr_rc != 0) { 404227569Sphilip rc = req.emr_rc; 405227569Sphilip goto fail1; 406227569Sphilip } 407227569Sphilip 408227569Sphilip if (req.emr_out_length_used < MC_CMD_GET_PHY_STATE_OUT_LEN) { 409227569Sphilip rc = EMSGSIZE; 410227569Sphilip goto fail2; 411227569Sphilip } 412227569Sphilip 413227569Sphilip state = MCDI_OUT_DWORD(req, GET_PHY_STATE_OUT_STATE); 414227569Sphilip if (state != MC_CMD_PHY_STATE_OK) { 415227569Sphilip if (state != MC_CMD_PHY_STATE_ZOMBIE) 416227569Sphilip EFSYS_PROBE1(mc_pcol_error, int, state); 417227569Sphilip rc = ENOTACTIVE; 418227569Sphilip goto fail3; 419227569Sphilip } 420227569Sphilip 421227569Sphilip return (0); 422227569Sphilip 423227569Sphilipfail3: 424227569Sphilip EFSYS_PROBE(fail3); 425227569Sphilipfail2: 426227569Sphilip EFSYS_PROBE(fail2); 427227569Sphilipfail1: 428291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 429227569Sphilip 430227569Sphilip return (rc); 431227569Sphilip} 432227569Sphilip 433291436Sarybchik __checkReturn efx_rc_t 434227569Sphilipsiena_phy_oui_get( 435227569Sphilip __in efx_nic_t *enp, 436227569Sphilip __out uint32_t *ouip) 437227569Sphilip{ 438227569Sphilip _NOTE(ARGUNUSED(enp, ouip)) 439227569Sphilip 440227569Sphilip return (ENOTSUP); 441227569Sphilip} 442227569Sphilip 443227569Sphilip#if EFSYS_OPT_PHY_STATS 444227569Sphilip 445227569Sphilip#define SIENA_SIMPLE_STAT_SET(_vmask, _esmp, _smask, _stat, \ 446227569Sphilip _mc_record, _efx_record) \ 447227569Sphilip if ((_vmask) & (1ULL << (_mc_record))) { \ 448227569Sphilip (_smask) |= (1ULL << (_efx_record)); \ 449227569Sphilip if ((_stat) != NULL && !EFSYS_MEM_IS_NULL(_esmp)) { \ 450227569Sphilip efx_dword_t dword; \ 451227569Sphilip EFSYS_MEM_READD(_esmp, (_mc_record) * 4, &dword);\ 452227569Sphilip (_stat)[_efx_record] = \ 453227569Sphilip EFX_DWORD_FIELD(dword, EFX_DWORD_0); \ 454227569Sphilip } \ 455227569Sphilip } 456227569Sphilip 457227569Sphilip#define SIENA_SIMPLE_STAT_SET2(_vmask, _esmp, _smask, _stat, _record) \ 458227569Sphilip SIENA_SIMPLE_STAT_SET(_vmask, _esmp, _smask, _stat, \ 459227569Sphilip MC_CMD_ ## _record, \ 460227569Sphilip EFX_PHY_STAT_ ## _record) 461227569Sphilip 462227569Sphilip void 463227569Sphilipsiena_phy_decode_stats( 464227569Sphilip __in efx_nic_t *enp, 465227569Sphilip __in uint32_t vmask, 466227569Sphilip __in_opt efsys_mem_t *esmp, 467227569Sphilip __out_opt uint64_t *smaskp, 468291395Sarybchik __inout_ecount_opt(EFX_PHY_NSTATS) uint32_t *stat) 469227569Sphilip{ 470227569Sphilip uint64_t smask = 0; 471227569Sphilip 472227569Sphilip _NOTE(ARGUNUSED(enp)) 473227569Sphilip 474227569Sphilip SIENA_SIMPLE_STAT_SET2(vmask, esmp, smask, stat, OUI); 475227569Sphilip SIENA_SIMPLE_STAT_SET2(vmask, esmp, smask, stat, PMA_PMD_LINK_UP); 476227569Sphilip SIENA_SIMPLE_STAT_SET2(vmask, esmp, smask, stat, PMA_PMD_RX_FAULT); 477227569Sphilip SIENA_SIMPLE_STAT_SET2(vmask, esmp, smask, stat, PMA_PMD_TX_FAULT); 478227569Sphilip 479227569Sphilip if (vmask & (1 << MC_CMD_PMA_PMD_SIGNAL)) { 480227569Sphilip smask |= ((1ULL << EFX_PHY_STAT_PMA_PMD_SIGNAL_A) | 481227569Sphilip (1ULL << EFX_PHY_STAT_PMA_PMD_SIGNAL_B) | 482227569Sphilip (1ULL << EFX_PHY_STAT_PMA_PMD_SIGNAL_C) | 483227569Sphilip (1ULL << EFX_PHY_STAT_PMA_PMD_SIGNAL_D)); 484227569Sphilip if (stat != NULL && esmp != NULL && !EFSYS_MEM_IS_NULL(esmp)) { 485227569Sphilip efx_dword_t dword; 486227569Sphilip uint32_t sig; 487227569Sphilip EFSYS_MEM_READD(esmp, 4 * MC_CMD_PMA_PMD_SIGNAL, 488227569Sphilip &dword); 489227569Sphilip sig = EFX_DWORD_FIELD(dword, EFX_DWORD_0); 490227569Sphilip stat[EFX_PHY_STAT_PMA_PMD_SIGNAL_A] = (sig >> 1) & 1; 491227569Sphilip stat[EFX_PHY_STAT_PMA_PMD_SIGNAL_B] = (sig >> 2) & 1; 492227569Sphilip stat[EFX_PHY_STAT_PMA_PMD_SIGNAL_C] = (sig >> 3) & 1; 493227569Sphilip stat[EFX_PHY_STAT_PMA_PMD_SIGNAL_D] = (sig >> 4) & 1; 494227569Sphilip } 495227569Sphilip } 496227569Sphilip 497227569Sphilip SIENA_SIMPLE_STAT_SET(vmask, esmp, smask, stat, MC_CMD_PMA_PMD_SNR_A, 498227569Sphilip EFX_PHY_STAT_SNR_A); 499227569Sphilip SIENA_SIMPLE_STAT_SET(vmask, esmp, smask, stat, MC_CMD_PMA_PMD_SNR_B, 500227569Sphilip EFX_PHY_STAT_SNR_B); 501227569Sphilip SIENA_SIMPLE_STAT_SET(vmask, esmp, smask, stat, MC_CMD_PMA_PMD_SNR_C, 502227569Sphilip EFX_PHY_STAT_SNR_C); 503227569Sphilip SIENA_SIMPLE_STAT_SET(vmask, esmp, smask, stat, MC_CMD_PMA_PMD_SNR_D, 504227569Sphilip EFX_PHY_STAT_SNR_D); 505227569Sphilip 506227569Sphilip SIENA_SIMPLE_STAT_SET2(vmask, esmp, smask, stat, PCS_LINK_UP); 507227569Sphilip SIENA_SIMPLE_STAT_SET2(vmask, esmp, smask, stat, PCS_RX_FAULT); 508227569Sphilip SIENA_SIMPLE_STAT_SET2(vmask, esmp, smask, stat, PCS_TX_FAULT); 509227569Sphilip SIENA_SIMPLE_STAT_SET2(vmask, esmp, smask, stat, PCS_BER); 510227569Sphilip SIENA_SIMPLE_STAT_SET2(vmask, esmp, smask, stat, PCS_BLOCK_ERRORS); 511227569Sphilip 512227569Sphilip SIENA_SIMPLE_STAT_SET(vmask, esmp, smask, stat, MC_CMD_PHYXS_LINK_UP, 513227569Sphilip EFX_PHY_STAT_PHY_XS_LINK_UP); 514227569Sphilip SIENA_SIMPLE_STAT_SET(vmask, esmp, smask, stat, MC_CMD_PHYXS_RX_FAULT, 515227569Sphilip EFX_PHY_STAT_PHY_XS_RX_FAULT); 516227569Sphilip SIENA_SIMPLE_STAT_SET(vmask, esmp, smask, stat, MC_CMD_PHYXS_TX_FAULT, 517227569Sphilip EFX_PHY_STAT_PHY_XS_TX_FAULT); 518227569Sphilip SIENA_SIMPLE_STAT_SET(vmask, esmp, smask, stat, MC_CMD_PHYXS_ALIGN, 519227569Sphilip EFX_PHY_STAT_PHY_XS_ALIGN); 520227569Sphilip 521227569Sphilip if (vmask & (1 << MC_CMD_PHYXS_SYNC)) { 522227569Sphilip smask |= ((1 << EFX_PHY_STAT_PHY_XS_SYNC_A) | 523227569Sphilip (1 << EFX_PHY_STAT_PHY_XS_SYNC_B) | 524227569Sphilip (1 << EFX_PHY_STAT_PHY_XS_SYNC_C) | 525227569Sphilip (1 << EFX_PHY_STAT_PHY_XS_SYNC_D)); 526227569Sphilip if (stat != NULL && !EFSYS_MEM_IS_NULL(esmp)) { 527227569Sphilip efx_dword_t dword; 528227569Sphilip uint32_t sync; 529227569Sphilip EFSYS_MEM_READD(esmp, 4 * MC_CMD_PHYXS_SYNC, &dword); 530227569Sphilip sync = EFX_DWORD_FIELD(dword, EFX_DWORD_0); 531227569Sphilip stat[EFX_PHY_STAT_PHY_XS_SYNC_A] = (sync >> 0) & 1; 532227569Sphilip stat[EFX_PHY_STAT_PHY_XS_SYNC_B] = (sync >> 1) & 1; 533227569Sphilip stat[EFX_PHY_STAT_PHY_XS_SYNC_C] = (sync >> 2) & 1; 534227569Sphilip stat[EFX_PHY_STAT_PHY_XS_SYNC_D] = (sync >> 3) & 1; 535227569Sphilip } 536227569Sphilip } 537227569Sphilip 538227569Sphilip SIENA_SIMPLE_STAT_SET2(vmask, esmp, smask, stat, AN_LINK_UP); 539227569Sphilip SIENA_SIMPLE_STAT_SET2(vmask, esmp, smask, stat, AN_COMPLETE); 540227569Sphilip 541227569Sphilip SIENA_SIMPLE_STAT_SET(vmask, esmp, smask, stat, MC_CMD_CL22_LINK_UP, 542227569Sphilip EFX_PHY_STAT_CL22EXT_LINK_UP); 543227569Sphilip 544227569Sphilip if (smaskp != NULL) 545227569Sphilip *smaskp = smask; 546227569Sphilip} 547227569Sphilip 548291436Sarybchik __checkReturn efx_rc_t 549227569Sphilipsiena_phy_stats_update( 550227569Sphilip __in efx_nic_t *enp, 551227569Sphilip __in efsys_mem_t *esmp, 552291395Sarybchik __inout_ecount(EFX_PHY_NSTATS) uint32_t *stat) 553227569Sphilip{ 554227569Sphilip efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 555283514Sarybchik uint32_t vmask = encp->enc_mcdi_phy_stat_mask; 556227569Sphilip uint64_t smask; 557227569Sphilip efx_mcdi_req_t req; 558283514Sarybchik uint8_t payload[MAX(MC_CMD_PHY_STATS_IN_LEN, 559283514Sarybchik MC_CMD_PHY_STATS_OUT_DMA_LEN)]; 560291436Sarybchik efx_rc_t rc; 561227569Sphilip 562283514Sarybchik (void) memset(payload, 0, sizeof (payload)); 563227569Sphilip req.emr_cmd = MC_CMD_PHY_STATS; 564227569Sphilip req.emr_in_buf = payload; 565283514Sarybchik req.emr_in_length = MC_CMD_PHY_STATS_IN_LEN; 566283514Sarybchik req.emr_out_buf = payload; 567283514Sarybchik req.emr_out_length = MC_CMD_PHY_STATS_OUT_DMA_LEN; 568227569Sphilip 569227569Sphilip MCDI_IN_SET_DWORD(req, PHY_STATS_IN_DMA_ADDR_LO, 570227569Sphilip EFSYS_MEM_ADDR(esmp) & 0xffffffff); 571227569Sphilip MCDI_IN_SET_DWORD(req, PHY_STATS_IN_DMA_ADDR_HI, 572227569Sphilip EFSYS_MEM_ADDR(esmp) >> 32); 573227569Sphilip 574227569Sphilip efx_mcdi_execute(enp, &req); 575227569Sphilip 576227569Sphilip if (req.emr_rc != 0) { 577227569Sphilip rc = req.emr_rc; 578227569Sphilip goto fail1; 579227569Sphilip } 580227569Sphilip EFSYS_ASSERT3U(req.emr_out_length, ==, MC_CMD_PHY_STATS_OUT_DMA_LEN); 581227569Sphilip 582227569Sphilip siena_phy_decode_stats(enp, vmask, esmp, &smask, stat); 583227569Sphilip EFSYS_ASSERT(smask == encp->enc_phy_stat_mask); 584227569Sphilip 585227569Sphilip return (0); 586227569Sphilip 587227569Sphilipfail1: 588291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 589227569Sphilip 590227569Sphilip return (0); 591227569Sphilip} 592227569Sphilip 593227569Sphilip#endif /* EFSYS_OPT_PHY_STATS */ 594227569Sphilip 595283514Sarybchik#if EFSYS_OPT_BIST 596227569Sphilip 597291436Sarybchik __checkReturn efx_rc_t 598227569Sphilipsiena_phy_bist_start( 599227569Sphilip __in efx_nic_t *enp, 600283514Sarybchik __in efx_bist_type_t type) 601227569Sphilip{ 602291436Sarybchik efx_rc_t rc; 603227569Sphilip 604283514Sarybchik if ((rc = efx_mcdi_bist_start(enp, type)) != 0) 605227569Sphilip goto fail1; 606227569Sphilip 607227569Sphilip return (0); 608227569Sphilip 609227569Sphilipfail1: 610291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 611227569Sphilip 612227569Sphilip return (rc); 613227569Sphilip} 614227569Sphilip 615227569Sphilipstatic __checkReturn unsigned long 616227569Sphilipsiena_phy_sft9001_bist_status( 617227569Sphilip __in uint16_t code) 618227569Sphilip{ 619227569Sphilip switch (code) { 620227569Sphilip case MC_CMD_POLL_BIST_SFT9001_PAIR_BUSY: 621227569Sphilip return (EFX_PHY_CABLE_STATUS_BUSY); 622227569Sphilip case MC_CMD_POLL_BIST_SFT9001_INTER_PAIR_SHORT: 623227569Sphilip return (EFX_PHY_CABLE_STATUS_INTERPAIRSHORT); 624227569Sphilip case MC_CMD_POLL_BIST_SFT9001_INTRA_PAIR_SHORT: 625227569Sphilip return (EFX_PHY_CABLE_STATUS_INTRAPAIRSHORT); 626227569Sphilip case MC_CMD_POLL_BIST_SFT9001_PAIR_OPEN: 627227569Sphilip return (EFX_PHY_CABLE_STATUS_OPEN); 628227569Sphilip case MC_CMD_POLL_BIST_SFT9001_PAIR_OK: 629227569Sphilip return (EFX_PHY_CABLE_STATUS_OK); 630227569Sphilip default: 631227569Sphilip return (EFX_PHY_CABLE_STATUS_INVALID); 632227569Sphilip } 633227569Sphilip} 634227569Sphilip 635291436Sarybchik __checkReturn efx_rc_t 636227569Sphilipsiena_phy_bist_poll( 637227569Sphilip __in efx_nic_t *enp, 638283514Sarybchik __in efx_bist_type_t type, 639283514Sarybchik __out efx_bist_result_t *resultp, 640227569Sphilip __out_opt __drv_when(count > 0, __notnull) 641227569Sphilip uint32_t *value_maskp, 642227569Sphilip __out_ecount_opt(count) __drv_when(count > 0, __notnull) 643227569Sphilip unsigned long *valuesp, 644227569Sphilip __in size_t count) 645227569Sphilip{ 646227569Sphilip efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 647283514Sarybchik uint8_t payload[MAX(MC_CMD_POLL_BIST_IN_LEN, 648283514Sarybchik MCDI_CTL_SDU_LEN_MAX)]; 649227569Sphilip uint32_t value_mask = 0; 650227569Sphilip efx_mcdi_req_t req; 651227569Sphilip uint32_t result; 652291436Sarybchik efx_rc_t rc; 653227569Sphilip 654283514Sarybchik (void) memset(payload, 0, sizeof (payload)); 655227569Sphilip req.emr_cmd = MC_CMD_POLL_BIST; 656283514Sarybchik req.emr_in_buf = payload; 657283514Sarybchik req.emr_in_length = MC_CMD_POLL_BIST_IN_LEN; 658227569Sphilip req.emr_out_buf = payload; 659283514Sarybchik req.emr_out_length = MCDI_CTL_SDU_LEN_MAX; 660227569Sphilip 661227569Sphilip efx_mcdi_execute(enp, &req); 662227569Sphilip 663227569Sphilip if (req.emr_rc != 0) { 664227569Sphilip rc = req.emr_rc; 665227569Sphilip goto fail1; 666227569Sphilip } 667227569Sphilip 668227569Sphilip if (req.emr_out_length_used < MC_CMD_POLL_BIST_OUT_RESULT_OFST + 4) { 669227569Sphilip rc = EMSGSIZE; 670227569Sphilip goto fail2; 671227569Sphilip } 672227569Sphilip 673227569Sphilip if (count > 0) 674227569Sphilip (void) memset(valuesp, '\0', count * sizeof (unsigned long)); 675227569Sphilip 676227569Sphilip result = MCDI_OUT_DWORD(req, POLL_BIST_OUT_RESULT); 677227569Sphilip 678227569Sphilip /* Extract PHY specific results */ 679227569Sphilip if (result == MC_CMD_POLL_BIST_PASSED && 680227569Sphilip encp->enc_phy_type == EFX_PHY_SFT9001B && 681227569Sphilip req.emr_out_length_used >= MC_CMD_POLL_BIST_OUT_SFT9001_LEN && 682283514Sarybchik (type == EFX_BIST_TYPE_PHY_CABLE_SHORT || 683283514Sarybchik type == EFX_BIST_TYPE_PHY_CABLE_LONG)) { 684227569Sphilip uint16_t word; 685227569Sphilip 686283514Sarybchik if (count > EFX_BIST_PHY_CABLE_LENGTH_A) { 687227569Sphilip if (valuesp != NULL) 688283514Sarybchik valuesp[EFX_BIST_PHY_CABLE_LENGTH_A] = 689227569Sphilip MCDI_OUT_DWORD(req, 690227569Sphilip POLL_BIST_OUT_SFT9001_CABLE_LENGTH_A); 691283514Sarybchik value_mask |= (1 << EFX_BIST_PHY_CABLE_LENGTH_A); 692227569Sphilip } 693227569Sphilip 694283514Sarybchik if (count > EFX_BIST_PHY_CABLE_LENGTH_B) { 695227569Sphilip if (valuesp != NULL) 696283514Sarybchik valuesp[EFX_BIST_PHY_CABLE_LENGTH_B] = 697227569Sphilip MCDI_OUT_DWORD(req, 698227569Sphilip POLL_BIST_OUT_SFT9001_CABLE_LENGTH_B); 699283514Sarybchik value_mask |= (1 << EFX_BIST_PHY_CABLE_LENGTH_B); 700227569Sphilip } 701227569Sphilip 702283514Sarybchik if (count > EFX_BIST_PHY_CABLE_LENGTH_C) { 703227569Sphilip if (valuesp != NULL) 704283514Sarybchik valuesp[EFX_BIST_PHY_CABLE_LENGTH_C] = 705227569Sphilip MCDI_OUT_DWORD(req, 706227569Sphilip POLL_BIST_OUT_SFT9001_CABLE_LENGTH_C); 707283514Sarybchik value_mask |= (1 << EFX_BIST_PHY_CABLE_LENGTH_C); 708227569Sphilip } 709227569Sphilip 710283514Sarybchik if (count > EFX_BIST_PHY_CABLE_LENGTH_D) { 711227569Sphilip if (valuesp != NULL) 712283514Sarybchik valuesp[EFX_BIST_PHY_CABLE_LENGTH_D] = 713227569Sphilip MCDI_OUT_DWORD(req, 714227569Sphilip POLL_BIST_OUT_SFT9001_CABLE_LENGTH_D); 715283514Sarybchik value_mask |= (1 << EFX_BIST_PHY_CABLE_LENGTH_D); 716227569Sphilip } 717227569Sphilip 718283514Sarybchik if (count > EFX_BIST_PHY_CABLE_STATUS_A) { 719227569Sphilip if (valuesp != NULL) { 720227569Sphilip word = MCDI_OUT_WORD(req, 721227569Sphilip POLL_BIST_OUT_SFT9001_CABLE_STATUS_A); 722283514Sarybchik valuesp[EFX_BIST_PHY_CABLE_STATUS_A] = 723227569Sphilip siena_phy_sft9001_bist_status(word); 724227569Sphilip } 725283514Sarybchik value_mask |= (1 << EFX_BIST_PHY_CABLE_STATUS_A); 726227569Sphilip } 727227569Sphilip 728283514Sarybchik if (count > EFX_BIST_PHY_CABLE_STATUS_B) { 729227569Sphilip if (valuesp != NULL) { 730227569Sphilip word = MCDI_OUT_WORD(req, 731227569Sphilip POLL_BIST_OUT_SFT9001_CABLE_STATUS_B); 732283514Sarybchik valuesp[EFX_BIST_PHY_CABLE_STATUS_B] = 733227569Sphilip siena_phy_sft9001_bist_status(word); 734227569Sphilip } 735283514Sarybchik value_mask |= (1 << EFX_BIST_PHY_CABLE_STATUS_B); 736227569Sphilip } 737227569Sphilip 738283514Sarybchik if (count > EFX_BIST_PHY_CABLE_STATUS_C) { 739227569Sphilip if (valuesp != NULL) { 740227569Sphilip word = MCDI_OUT_WORD(req, 741227569Sphilip POLL_BIST_OUT_SFT9001_CABLE_STATUS_C); 742283514Sarybchik valuesp[EFX_BIST_PHY_CABLE_STATUS_C] = 743227569Sphilip siena_phy_sft9001_bist_status(word); 744227569Sphilip } 745283514Sarybchik value_mask |= (1 << EFX_BIST_PHY_CABLE_STATUS_C); 746227569Sphilip } 747227569Sphilip 748283514Sarybchik if (count > EFX_BIST_PHY_CABLE_STATUS_D) { 749227569Sphilip if (valuesp != NULL) { 750227569Sphilip word = MCDI_OUT_WORD(req, 751227569Sphilip POLL_BIST_OUT_SFT9001_CABLE_STATUS_D); 752283514Sarybchik valuesp[EFX_BIST_PHY_CABLE_STATUS_D] = 753227569Sphilip siena_phy_sft9001_bist_status(word); 754227569Sphilip } 755283514Sarybchik value_mask |= (1 << EFX_BIST_PHY_CABLE_STATUS_D); 756227569Sphilip } 757227569Sphilip 758227569Sphilip } else if (result == MC_CMD_POLL_BIST_FAILED && 759227569Sphilip encp->enc_phy_type == EFX_PHY_QLX111V && 760227569Sphilip req.emr_out_length >= MC_CMD_POLL_BIST_OUT_MRSFP_LEN && 761283514Sarybchik count > EFX_BIST_FAULT_CODE) { 762227569Sphilip if (valuesp != NULL) 763283514Sarybchik valuesp[EFX_BIST_FAULT_CODE] = 764227569Sphilip MCDI_OUT_DWORD(req, POLL_BIST_OUT_MRSFP_TEST); 765283514Sarybchik value_mask |= 1 << EFX_BIST_FAULT_CODE; 766227569Sphilip } 767227569Sphilip 768227569Sphilip if (value_maskp != NULL) 769227569Sphilip *value_maskp = value_mask; 770227569Sphilip 771227569Sphilip EFSYS_ASSERT(resultp != NULL); 772227569Sphilip if (result == MC_CMD_POLL_BIST_RUNNING) 773283514Sarybchik *resultp = EFX_BIST_RESULT_RUNNING; 774227569Sphilip else if (result == MC_CMD_POLL_BIST_PASSED) 775283514Sarybchik *resultp = EFX_BIST_RESULT_PASSED; 776227569Sphilip else 777283514Sarybchik *resultp = EFX_BIST_RESULT_FAILED; 778227569Sphilip 779227569Sphilip return (0); 780227569Sphilip 781227569Sphilipfail2: 782227569Sphilip EFSYS_PROBE(fail2); 783227569Sphilipfail1: 784291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 785227569Sphilip 786227569Sphilip return (rc); 787227569Sphilip} 788227569Sphilip 789227569Sphilip void 790227569Sphilipsiena_phy_bist_stop( 791227569Sphilip __in efx_nic_t *enp, 792283514Sarybchik __in efx_bist_type_t type) 793227569Sphilip{ 794227569Sphilip /* There is no way to stop BIST on Siena */ 795227569Sphilip _NOTE(ARGUNUSED(enp, type)) 796227569Sphilip} 797227569Sphilip 798283514Sarybchik#endif /* EFSYS_OPT_BIST */ 799227569Sphilip 800227569Sphilip#endif /* EFSYS_OPT_SIENA */ 801