The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/sfxge/common/ef10_phy.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2012-2016 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 <sys/cdefs.h>
   32 __FBSDID("$FreeBSD$");
   33 
   34 #include "efx.h"
   35 #include "efx_impl.h"
   36 
   37 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
   38 
   39 static                  void
   40 mcdi_phy_decode_cap(
   41         __in            uint32_t mcdi_cap,
   42         __out           uint32_t *maskp)
   43 {
   44         uint32_t mask;
   45 
   46 #define CHECK_CAP(_cap) \
   47         EFX_STATIC_ASSERT(EFX_PHY_CAP_##_cap == MC_CMD_PHY_CAP_##_cap##_LBN)
   48 
   49         CHECK_CAP(10HDX);
   50         CHECK_CAP(10FDX);
   51         CHECK_CAP(100HDX);
   52         CHECK_CAP(100FDX);
   53         CHECK_CAP(1000HDX);
   54         CHECK_CAP(1000FDX);
   55         CHECK_CAP(10000FDX);
   56         CHECK_CAP(25000FDX);
   57         CHECK_CAP(40000FDX);
   58         CHECK_CAP(50000FDX);
   59         CHECK_CAP(100000FDX);
   60         CHECK_CAP(PAUSE);
   61         CHECK_CAP(ASYM);
   62         CHECK_CAP(AN);
   63         CHECK_CAP(DDM);
   64         CHECK_CAP(BASER_FEC);
   65         CHECK_CAP(BASER_FEC_REQUESTED);
   66         CHECK_CAP(RS_FEC);
   67         CHECK_CAP(RS_FEC_REQUESTED);
   68         CHECK_CAP(25G_BASER_FEC);
   69         CHECK_CAP(25G_BASER_FEC_REQUESTED);
   70 #undef CHECK_CAP
   71 
   72         mask = 0;
   73         if (mcdi_cap & (1 << MC_CMD_PHY_CAP_10HDX_LBN))
   74                 mask |= (1 << EFX_PHY_CAP_10HDX);
   75         if (mcdi_cap & (1 << MC_CMD_PHY_CAP_10FDX_LBN))
   76                 mask |= (1 << EFX_PHY_CAP_10FDX);
   77         if (mcdi_cap & (1 << MC_CMD_PHY_CAP_100HDX_LBN))
   78                 mask |= (1 << EFX_PHY_CAP_100HDX);
   79         if (mcdi_cap & (1 << MC_CMD_PHY_CAP_100FDX_LBN))
   80                 mask |= (1 << EFX_PHY_CAP_100FDX);
   81         if (mcdi_cap & (1 << MC_CMD_PHY_CAP_1000HDX_LBN))
   82                 mask |= (1 << EFX_PHY_CAP_1000HDX);
   83         if (mcdi_cap & (1 << MC_CMD_PHY_CAP_1000FDX_LBN))
   84                 mask |= (1 << EFX_PHY_CAP_1000FDX);
   85         if (mcdi_cap & (1 << MC_CMD_PHY_CAP_10000FDX_LBN))
   86                 mask |= (1 << EFX_PHY_CAP_10000FDX);
   87         if (mcdi_cap & (1 << MC_CMD_PHY_CAP_25000FDX_LBN))
   88                 mask |= (1 << EFX_PHY_CAP_25000FDX);
   89         if (mcdi_cap & (1 << MC_CMD_PHY_CAP_40000FDX_LBN))
   90                 mask |= (1 << EFX_PHY_CAP_40000FDX);
   91         if (mcdi_cap & (1 << MC_CMD_PHY_CAP_50000FDX_LBN))
   92                 mask |= (1 << EFX_PHY_CAP_50000FDX);
   93         if (mcdi_cap & (1 << MC_CMD_PHY_CAP_100000FDX_LBN))
   94                 mask |= (1 << EFX_PHY_CAP_100000FDX);
   95 
   96         if (mcdi_cap & (1 << MC_CMD_PHY_CAP_PAUSE_LBN))
   97                 mask |= (1 << EFX_PHY_CAP_PAUSE);
   98         if (mcdi_cap & (1 << MC_CMD_PHY_CAP_ASYM_LBN))
   99                 mask |= (1 << EFX_PHY_CAP_ASYM);
  100         if (mcdi_cap & (1 << MC_CMD_PHY_CAP_AN_LBN))
  101                 mask |= (1 << EFX_PHY_CAP_AN);
  102 
  103         /* FEC caps (supported on Medford2 and later) */
  104         if (mcdi_cap & (1 << MC_CMD_PHY_CAP_BASER_FEC_LBN))
  105                 mask |= (1 << EFX_PHY_CAP_BASER_FEC);
  106         if (mcdi_cap & (1 << MC_CMD_PHY_CAP_BASER_FEC_REQUESTED_LBN))
  107                 mask |= (1 << EFX_PHY_CAP_BASER_FEC_REQUESTED);
  108 
  109         if (mcdi_cap & (1 << MC_CMD_PHY_CAP_RS_FEC_LBN))
  110                 mask |= (1 << EFX_PHY_CAP_RS_FEC);
  111         if (mcdi_cap & (1 << MC_CMD_PHY_CAP_RS_FEC_REQUESTED_LBN))
  112                 mask |= (1 << EFX_PHY_CAP_RS_FEC_REQUESTED);
  113 
  114         if (mcdi_cap & (1 << MC_CMD_PHY_CAP_25G_BASER_FEC_LBN))
  115                 mask |= (1 << EFX_PHY_CAP_25G_BASER_FEC);
  116         if (mcdi_cap & (1 << MC_CMD_PHY_CAP_25G_BASER_FEC_REQUESTED_LBN))
  117                 mask |= (1 << EFX_PHY_CAP_25G_BASER_FEC_REQUESTED);
  118 
  119         *maskp = mask;
  120 }
  121 
  122 static                  void
  123 mcdi_phy_decode_link_mode(
  124         __in            efx_nic_t *enp,
  125         __in            uint32_t link_flags,
  126         __in            unsigned int speed,
  127         __in            unsigned int fcntl,
  128         __in            uint32_t fec,
  129         __out           efx_link_mode_t *link_modep,
  130         __out           unsigned int *fcntlp,
  131         __out           efx_phy_fec_type_t *fecp)
  132 {
  133         boolean_t fd = !!(link_flags &
  134                     (1 << MC_CMD_GET_LINK_OUT_FULL_DUPLEX_LBN));
  135         boolean_t up = !!(link_flags &
  136                     (1 << MC_CMD_GET_LINK_OUT_LINK_UP_LBN));
  137 
  138         _NOTE(ARGUNUSED(enp))
  139 
  140         if (!up)
  141                 *link_modep = EFX_LINK_DOWN;
  142         else if (speed == 100000 && fd)
  143                 *link_modep = EFX_LINK_100000FDX;
  144         else if (speed == 50000 && fd)
  145                 *link_modep = EFX_LINK_50000FDX;
  146         else if (speed == 40000 && fd)
  147                 *link_modep = EFX_LINK_40000FDX;
  148         else if (speed == 25000 && fd)
  149                 *link_modep = EFX_LINK_25000FDX;
  150         else if (speed == 10000 && fd)
  151                 *link_modep = EFX_LINK_10000FDX;
  152         else if (speed == 1000)
  153                 *link_modep = fd ? EFX_LINK_1000FDX : EFX_LINK_1000HDX;
  154         else if (speed == 100)
  155                 *link_modep = fd ? EFX_LINK_100FDX : EFX_LINK_100HDX;
  156         else if (speed == 10)
  157                 *link_modep = fd ? EFX_LINK_10FDX : EFX_LINK_10HDX;
  158         else
  159                 *link_modep = EFX_LINK_UNKNOWN;
  160 
  161         if (fcntl == MC_CMD_FCNTL_OFF)
  162                 *fcntlp = 0;
  163         else if (fcntl == MC_CMD_FCNTL_RESPOND)
  164                 *fcntlp = EFX_FCNTL_RESPOND;
  165         else if (fcntl == MC_CMD_FCNTL_GENERATE)
  166                 *fcntlp = EFX_FCNTL_GENERATE;
  167         else if (fcntl == MC_CMD_FCNTL_BIDIR)
  168                 *fcntlp = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE;
  169         else {
  170                 EFSYS_PROBE1(mc_pcol_error, int, fcntl);
  171                 *fcntlp = 0;
  172         }
  173 
  174         switch (fec) {
  175         case MC_CMD_FEC_NONE:
  176                 *fecp = EFX_PHY_FEC_NONE;
  177                 break;
  178         case MC_CMD_FEC_BASER:
  179                 *fecp = EFX_PHY_FEC_BASER;
  180                 break;
  181         case MC_CMD_FEC_RS:
  182                 *fecp = EFX_PHY_FEC_RS;
  183                 break;
  184         default:
  185                 EFSYS_PROBE1(mc_pcol_error, int, fec);
  186                 *fecp = EFX_PHY_FEC_NONE;
  187                 break;
  188         }
  189 }
  190 
  191                         void
  192 ef10_phy_link_ev(
  193         __in            efx_nic_t *enp,
  194         __in            efx_qword_t *eqp,
  195         __out           efx_link_mode_t *link_modep)
  196 {
  197         efx_port_t *epp = &(enp->en_port);
  198         unsigned int link_flags;
  199         unsigned int speed;
  200         unsigned int fcntl;
  201         efx_phy_fec_type_t fec = MC_CMD_FEC_NONE;
  202         efx_link_mode_t link_mode;
  203         uint32_t lp_cap_mask;
  204 
  205         /*
  206          * Convert the LINKCHANGE speed enumeration into mbit/s, in the
  207          * same way as GET_LINK encodes the speed
  208          */
  209         switch (MCDI_EV_FIELD(eqp, LINKCHANGE_SPEED)) {
  210         case MCDI_EVENT_LINKCHANGE_SPEED_100M:
  211                 speed = 100;
  212                 break;
  213         case MCDI_EVENT_LINKCHANGE_SPEED_1G:
  214                 speed = 1000;
  215                 break;
  216         case MCDI_EVENT_LINKCHANGE_SPEED_10G:
  217                 speed = 10000;
  218                 break;
  219         case MCDI_EVENT_LINKCHANGE_SPEED_25G:
  220                 speed = 25000;
  221                 break;
  222         case MCDI_EVENT_LINKCHANGE_SPEED_40G:
  223                 speed = 40000;
  224                 break;
  225         case MCDI_EVENT_LINKCHANGE_SPEED_50G:
  226                 speed = 50000;
  227                 break;
  228         case MCDI_EVENT_LINKCHANGE_SPEED_100G:
  229                 speed = 100000;
  230                 break;
  231         default:
  232                 speed = 0;
  233                 break;
  234         }
  235 
  236         link_flags = MCDI_EV_FIELD(eqp, LINKCHANGE_LINK_FLAGS);
  237         mcdi_phy_decode_link_mode(enp, link_flags, speed,
  238                                     MCDI_EV_FIELD(eqp, LINKCHANGE_FCNTL),
  239                                     MC_CMD_FEC_NONE, &link_mode,
  240                                     &fcntl, &fec);
  241         mcdi_phy_decode_cap(MCDI_EV_FIELD(eqp, LINKCHANGE_LP_CAP),
  242                             &lp_cap_mask);
  243 
  244         /*
  245          * It's safe to update ep_lp_cap_mask without the driver's port lock
  246          * because presumably any concurrently running efx_port_poll() is
  247          * only going to arrive at the same value.
  248          *
  249          * ep_fcntl has two meanings. It's either the link common fcntl
  250          * (if the PHY supports AN), or it's the forced link state. If
  251          * the former, it's safe to update the value for the same reason as
  252          * for ep_lp_cap_mask. If the latter, then just ignore the value,
  253          * because we can race with efx_mac_fcntl_set().
  254          */
  255         epp->ep_lp_cap_mask = lp_cap_mask;
  256         epp->ep_fcntl = fcntl;
  257 
  258         *link_modep = link_mode;
  259 }
  260 
  261         __checkReturn   efx_rc_t
  262 ef10_phy_power(
  263         __in            efx_nic_t *enp,
  264         __in            boolean_t power)
  265 {
  266         efx_rc_t rc;
  267 
  268         if (!power)
  269                 return (0);
  270 
  271         /* Check if the PHY is a zombie */
  272         if ((rc = ef10_phy_verify(enp)) != 0)
  273                 goto fail1;
  274 
  275         enp->en_reset_flags |= EFX_RESET_PHY;
  276 
  277         return (0);
  278 
  279 fail1:
  280         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  281 
  282         return (rc);
  283 }
  284 
  285         __checkReturn   efx_rc_t
  286 ef10_phy_get_link(
  287         __in            efx_nic_t *enp,
  288         __out           ef10_link_state_t *elsp)
  289 {
  290         efx_mcdi_req_t req;
  291         uint32_t fec;
  292         EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_LINK_IN_LEN,
  293                 MC_CMD_GET_LINK_OUT_V2_LEN);
  294         efx_rc_t rc;
  295 
  296         req.emr_cmd = MC_CMD_GET_LINK;
  297         req.emr_in_buf = payload;
  298         req.emr_in_length = MC_CMD_GET_LINK_IN_LEN;
  299         req.emr_out_buf = payload;
  300         req.emr_out_length = MC_CMD_GET_LINK_OUT_V2_LEN;
  301 
  302         efx_mcdi_execute(enp, &req);
  303 
  304         if (req.emr_rc != 0) {
  305                 rc = req.emr_rc;
  306                 goto fail1;
  307         }
  308 
  309         if (req.emr_out_length_used < MC_CMD_GET_LINK_OUT_LEN) {
  310                 rc = EMSGSIZE;
  311                 goto fail2;
  312         }
  313 
  314         mcdi_phy_decode_cap(MCDI_OUT_DWORD(req, GET_LINK_OUT_CAP),
  315                             &elsp->epls.epls_adv_cap_mask);
  316         mcdi_phy_decode_cap(MCDI_OUT_DWORD(req, GET_LINK_OUT_LP_CAP),
  317                             &elsp->epls.epls_lp_cap_mask);
  318 
  319         if (req.emr_out_length_used < MC_CMD_GET_LINK_OUT_V2_LEN)
  320                 fec = MC_CMD_FEC_NONE;
  321         else
  322                 fec = MCDI_OUT_DWORD(req, GET_LINK_OUT_V2_FEC_TYPE);
  323 
  324         mcdi_phy_decode_link_mode(enp, MCDI_OUT_DWORD(req, GET_LINK_OUT_FLAGS),
  325                             MCDI_OUT_DWORD(req, GET_LINK_OUT_LINK_SPEED),
  326                             MCDI_OUT_DWORD(req, GET_LINK_OUT_FCNTL),
  327                             fec, &elsp->epls.epls_link_mode,
  328                             &elsp->epls.epls_fcntl, &elsp->epls.epls_fec);
  329 
  330         if (req.emr_out_length_used < MC_CMD_GET_LINK_OUT_V2_LEN) {
  331                 elsp->epls.epls_ld_cap_mask = 0;
  332         } else {
  333                 mcdi_phy_decode_cap(MCDI_OUT_DWORD(req, GET_LINK_OUT_V2_LD_CAP),
  334                                     &elsp->epls.epls_ld_cap_mask);
  335         }
  336 
  337 #if EFSYS_OPT_LOOPBACK
  338         /*
  339          * MC_CMD_LOOPBACK and EFX_LOOPBACK names are equivalent, so use the
  340          * MCDI value directly. Agreement is checked in efx_loopback_mask().
  341          */
  342         elsp->els_loopback = MCDI_OUT_DWORD(req, GET_LINK_OUT_LOOPBACK_MODE);
  343 #endif  /* EFSYS_OPT_LOOPBACK */
  344 
  345         elsp->els_mac_up = MCDI_OUT_DWORD(req, GET_LINK_OUT_MAC_FAULT) == 0;
  346 
  347         return (0);
  348 
  349 fail2:
  350         EFSYS_PROBE(fail2);
  351 fail1:
  352         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  353 
  354         return (rc);
  355 }
  356 
  357         __checkReturn   efx_rc_t
  358 ef10_phy_reconfigure(
  359         __in            efx_nic_t *enp)
  360 {
  361         efx_port_t *epp = &(enp->en_port);
  362         efx_mcdi_req_t req;
  363         EFX_MCDI_DECLARE_BUF(payload, MC_CMD_SET_LINK_IN_LEN,
  364                 MC_CMD_SET_LINK_OUT_LEN);
  365         uint32_t cap_mask;
  366 #if EFSYS_OPT_PHY_LED_CONTROL
  367         unsigned int led_mode;
  368 #endif
  369         unsigned int speed;
  370         boolean_t supported;
  371         efx_rc_t rc;
  372 
  373         if ((rc = efx_mcdi_link_control_supported(enp, &supported)) != 0)
  374                 goto fail1;
  375         if (supported == B_FALSE)
  376                 goto out;
  377 
  378         req.emr_cmd = MC_CMD_SET_LINK;
  379         req.emr_in_buf = payload;
  380         req.emr_in_length = MC_CMD_SET_LINK_IN_LEN;
  381         req.emr_out_buf = payload;
  382         req.emr_out_length = MC_CMD_SET_LINK_OUT_LEN;
  383 
  384         cap_mask = epp->ep_adv_cap_mask;
  385         MCDI_IN_POPULATE_DWORD_10(req, SET_LINK_IN_CAP,
  386                 PHY_CAP_10HDX, (cap_mask >> EFX_PHY_CAP_10HDX) & 0x1,
  387                 PHY_CAP_10FDX, (cap_mask >> EFX_PHY_CAP_10FDX) & 0x1,
  388                 PHY_CAP_100HDX, (cap_mask >> EFX_PHY_CAP_100HDX) & 0x1,
  389                 PHY_CAP_100FDX, (cap_mask >> EFX_PHY_CAP_100FDX) & 0x1,
  390                 PHY_CAP_1000HDX, (cap_mask >> EFX_PHY_CAP_1000HDX) & 0x1,
  391                 PHY_CAP_1000FDX, (cap_mask >> EFX_PHY_CAP_1000FDX) & 0x1,
  392                 PHY_CAP_10000FDX, (cap_mask >> EFX_PHY_CAP_10000FDX) & 0x1,
  393                 PHY_CAP_PAUSE, (cap_mask >> EFX_PHY_CAP_PAUSE) & 0x1,
  394                 PHY_CAP_ASYM, (cap_mask >> EFX_PHY_CAP_ASYM) & 0x1,
  395                 PHY_CAP_AN, (cap_mask >> EFX_PHY_CAP_AN) & 0x1);
  396         /* Too many fields for POPULATE macros, so insert this afterwards */
  397         MCDI_IN_SET_DWORD_FIELD(req, SET_LINK_IN_CAP,
  398             PHY_CAP_25000FDX, (cap_mask >> EFX_PHY_CAP_25000FDX) & 0x1);
  399         MCDI_IN_SET_DWORD_FIELD(req, SET_LINK_IN_CAP,
  400             PHY_CAP_40000FDX, (cap_mask >> EFX_PHY_CAP_40000FDX) & 0x1);
  401         MCDI_IN_SET_DWORD_FIELD(req, SET_LINK_IN_CAP,
  402             PHY_CAP_50000FDX, (cap_mask >> EFX_PHY_CAP_50000FDX) & 0x1);
  403         MCDI_IN_SET_DWORD_FIELD(req, SET_LINK_IN_CAP,
  404             PHY_CAP_100000FDX, (cap_mask >> EFX_PHY_CAP_100000FDX) & 0x1);
  405 
  406         MCDI_IN_SET_DWORD_FIELD(req, SET_LINK_IN_CAP,
  407             PHY_CAP_BASER_FEC, (cap_mask >> EFX_PHY_CAP_BASER_FEC) & 0x1);
  408         MCDI_IN_SET_DWORD_FIELD(req, SET_LINK_IN_CAP,
  409             PHY_CAP_BASER_FEC_REQUESTED,
  410             (cap_mask >> EFX_PHY_CAP_BASER_FEC_REQUESTED) & 0x1);
  411 
  412         MCDI_IN_SET_DWORD_FIELD(req, SET_LINK_IN_CAP,
  413             PHY_CAP_RS_FEC, (cap_mask >> EFX_PHY_CAP_RS_FEC) & 0x1);
  414         MCDI_IN_SET_DWORD_FIELD(req, SET_LINK_IN_CAP,
  415             PHY_CAP_RS_FEC_REQUESTED,
  416             (cap_mask >> EFX_PHY_CAP_RS_FEC_REQUESTED) & 0x1);
  417 
  418         MCDI_IN_SET_DWORD_FIELD(req, SET_LINK_IN_CAP,
  419             PHY_CAP_25G_BASER_FEC,
  420             (cap_mask >> EFX_PHY_CAP_25G_BASER_FEC) & 0x1);
  421         MCDI_IN_SET_DWORD_FIELD(req, SET_LINK_IN_CAP,
  422             PHY_CAP_25G_BASER_FEC_REQUESTED,
  423             (cap_mask >> EFX_PHY_CAP_25G_BASER_FEC_REQUESTED) & 0x1);
  424 
  425 #if EFSYS_OPT_LOOPBACK
  426         MCDI_IN_SET_DWORD(req, SET_LINK_IN_LOOPBACK_MODE,
  427                     epp->ep_loopback_type);
  428         switch (epp->ep_loopback_link_mode) {
  429         case EFX_LINK_100FDX:
  430                 speed = 100;
  431                 break;
  432         case EFX_LINK_1000FDX:
  433                 speed = 1000;
  434                 break;
  435         case EFX_LINK_10000FDX:
  436                 speed = 10000;
  437                 break;
  438         case EFX_LINK_25000FDX:
  439                 speed = 25000;
  440                 break;
  441         case EFX_LINK_40000FDX:
  442                 speed = 40000;
  443                 break;
  444         case EFX_LINK_50000FDX:
  445                 speed = 50000;
  446                 break;
  447         case EFX_LINK_100000FDX:
  448                 speed = 100000;
  449                 break;
  450         default:
  451                 speed = 0;
  452         }
  453 #else
  454         MCDI_IN_SET_DWORD(req, SET_LINK_IN_LOOPBACK_MODE, MC_CMD_LOOPBACK_NONE);
  455         speed = 0;
  456 #endif  /* EFSYS_OPT_LOOPBACK */
  457         MCDI_IN_SET_DWORD(req, SET_LINK_IN_LOOPBACK_SPEED, speed);
  458 
  459 #if EFSYS_OPT_PHY_FLAGS
  460         MCDI_IN_SET_DWORD(req, SET_LINK_IN_FLAGS, epp->ep_phy_flags);
  461 #else
  462         MCDI_IN_SET_DWORD(req, SET_LINK_IN_FLAGS, 0);
  463 #endif  /* EFSYS_OPT_PHY_FLAGS */
  464 
  465         efx_mcdi_execute(enp, &req);
  466 
  467         if (req.emr_rc != 0) {
  468                 rc = req.emr_rc;
  469                 goto fail2;
  470         }
  471 
  472         /* And set the blink mode */
  473         (void) memset(payload, 0, sizeof (payload));
  474         req.emr_cmd = MC_CMD_SET_ID_LED;
  475         req.emr_in_buf = payload;
  476         req.emr_in_length = MC_CMD_SET_ID_LED_IN_LEN;
  477         req.emr_out_buf = payload;
  478         req.emr_out_length = MC_CMD_SET_ID_LED_OUT_LEN;
  479 
  480 #if EFSYS_OPT_PHY_LED_CONTROL
  481         switch (epp->ep_phy_led_mode) {
  482         case EFX_PHY_LED_DEFAULT:
  483                 led_mode = MC_CMD_LED_DEFAULT;
  484                 break;
  485         case EFX_PHY_LED_OFF:
  486                 led_mode = MC_CMD_LED_OFF;
  487                 break;
  488         case EFX_PHY_LED_ON:
  489                 led_mode = MC_CMD_LED_ON;
  490                 break;
  491         default:
  492                 EFSYS_ASSERT(0);
  493                 led_mode = MC_CMD_LED_DEFAULT;
  494         }
  495 
  496         MCDI_IN_SET_DWORD(req, SET_ID_LED_IN_STATE, led_mode);
  497 #else
  498         MCDI_IN_SET_DWORD(req, SET_ID_LED_IN_STATE, MC_CMD_LED_DEFAULT);
  499 #endif  /* EFSYS_OPT_PHY_LED_CONTROL */
  500 
  501         efx_mcdi_execute(enp, &req);
  502 
  503         if (req.emr_rc != 0) {
  504                 rc = req.emr_rc;
  505                 goto fail3;
  506         }
  507 out:
  508         return (0);
  509 
  510 fail3:
  511         EFSYS_PROBE(fail3);
  512 fail2:
  513         EFSYS_PROBE(fail2);
  514 fail1:
  515         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  516 
  517         return (rc);
  518 }
  519 
  520         __checkReturn   efx_rc_t
  521 ef10_phy_verify(
  522         __in            efx_nic_t *enp)
  523 {
  524         efx_mcdi_req_t req;
  525         EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_PHY_STATE_IN_LEN,
  526                 MC_CMD_GET_PHY_STATE_OUT_LEN);
  527         uint32_t state;
  528         efx_rc_t rc;
  529 
  530         req.emr_cmd = MC_CMD_GET_PHY_STATE;
  531         req.emr_in_buf = payload;
  532         req.emr_in_length = MC_CMD_GET_PHY_STATE_IN_LEN;
  533         req.emr_out_buf = payload;
  534         req.emr_out_length = MC_CMD_GET_PHY_STATE_OUT_LEN;
  535 
  536         efx_mcdi_execute(enp, &req);
  537 
  538         if (req.emr_rc != 0) {
  539                 rc = req.emr_rc;
  540                 goto fail1;
  541         }
  542 
  543         if (req.emr_out_length_used < MC_CMD_GET_PHY_STATE_OUT_LEN) {
  544                 rc = EMSGSIZE;
  545                 goto fail2;
  546         }
  547 
  548         state = MCDI_OUT_DWORD(req, GET_PHY_STATE_OUT_STATE);
  549         if (state != MC_CMD_PHY_STATE_OK) {
  550                 if (state != MC_CMD_PHY_STATE_ZOMBIE)
  551                         EFSYS_PROBE1(mc_pcol_error, int, state);
  552                 rc = ENOTACTIVE;
  553                 goto fail3;
  554         }
  555 
  556         return (0);
  557 
  558 fail3:
  559         EFSYS_PROBE(fail3);
  560 fail2:
  561         EFSYS_PROBE(fail2);
  562 fail1:
  563         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  564 
  565         return (rc);
  566 }
  567 
  568         __checkReturn   efx_rc_t
  569 ef10_phy_oui_get(
  570         __in            efx_nic_t *enp,
  571         __out           uint32_t *ouip)
  572 {
  573         _NOTE(ARGUNUSED(enp, ouip))
  574 
  575         return (ENOTSUP);
  576 }
  577 
  578         __checkReturn   efx_rc_t
  579 ef10_phy_link_state_get(
  580         __in            efx_nic_t *enp,
  581         __out           efx_phy_link_state_t  *eplsp)
  582 {
  583         efx_rc_t rc;
  584         ef10_link_state_t els;
  585 
  586         /* Obtain the active link state */
  587         if ((rc = ef10_phy_get_link(enp, &els)) != 0)
  588                 goto fail1;
  589 
  590         *eplsp = els.epls;
  591 
  592         return (0);
  593 
  594 fail1:
  595         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  596 
  597         return (rc);
  598 }
  599 
  600 #if EFSYS_OPT_PHY_STATS
  601 
  602         __checkReturn                           efx_rc_t
  603 ef10_phy_stats_update(
  604         __in                                    efx_nic_t *enp,
  605         __in                                    efsys_mem_t *esmp,
  606         __inout_ecount(EFX_PHY_NSTATS)          uint32_t *stat)
  607 {
  608         /* TBD: no stats support in firmware yet */
  609         _NOTE(ARGUNUSED(enp, esmp))
  610         memset(stat, 0, EFX_PHY_NSTATS * sizeof (*stat));
  611 
  612         return (0);
  613 }
  614 
  615 #endif  /* EFSYS_OPT_PHY_STATS */
  616 
  617 #if EFSYS_OPT_BIST
  618 
  619         __checkReturn           efx_rc_t
  620 ef10_bist_enable_offline(
  621         __in                    efx_nic_t *enp)
  622 {
  623         efx_rc_t rc;
  624 
  625         if ((rc = efx_mcdi_bist_enable_offline(enp)) != 0)
  626                 goto fail1;
  627 
  628         return (0);
  629 
  630 fail1:
  631         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  632 
  633         return (rc);
  634 }
  635 
  636         __checkReturn           efx_rc_t
  637 ef10_bist_start(
  638         __in                    efx_nic_t *enp,
  639         __in                    efx_bist_type_t type)
  640 {
  641         efx_rc_t rc;
  642 
  643         if ((rc = efx_mcdi_bist_start(enp, type)) != 0)
  644                 goto fail1;
  645 
  646         return (0);
  647 
  648 fail1:
  649         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  650 
  651         return (rc);
  652 }
  653 
  654         __checkReturn           efx_rc_t
  655 ef10_bist_poll(
  656         __in                    efx_nic_t *enp,
  657         __in                    efx_bist_type_t type,
  658         __out                   efx_bist_result_t *resultp,
  659         __out_opt __drv_when(count > 0, __notnull)
  660         uint32_t *value_maskp,
  661         __out_ecount_opt(count) __drv_when(count > 0, __notnull)
  662         unsigned long *valuesp,
  663         __in                    size_t count)
  664 {
  665         /*
  666          * MCDI_CTL_SDU_LEN_MAX_V1 is large enough cover all BIST results,
  667          * whilst not wasting stack.
  668          */
  669         EFX_MCDI_DECLARE_BUF(payload, MC_CMD_POLL_BIST_IN_LEN,
  670                 MCDI_CTL_SDU_LEN_MAX_V1);
  671         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
  672         efx_mcdi_req_t req;
  673         uint32_t value_mask = 0;
  674         uint32_t result;
  675         efx_rc_t rc;
  676 
  677         EFX_STATIC_ASSERT(MC_CMD_POLL_BIST_OUT_LEN <=
  678             MCDI_CTL_SDU_LEN_MAX_V1);
  679         EFX_STATIC_ASSERT(MC_CMD_POLL_BIST_OUT_SFT9001_LEN <=
  680             MCDI_CTL_SDU_LEN_MAX_V1);
  681         EFX_STATIC_ASSERT(MC_CMD_POLL_BIST_OUT_MRSFP_LEN <=
  682             MCDI_CTL_SDU_LEN_MAX_V1);
  683         EFX_STATIC_ASSERT(MC_CMD_POLL_BIST_OUT_MEM_LEN <=
  684             MCDI_CTL_SDU_LEN_MAX_V1);
  685 
  686         _NOTE(ARGUNUSED(type))
  687 
  688         req.emr_cmd = MC_CMD_POLL_BIST;
  689         req.emr_in_buf = payload;
  690         req.emr_in_length = MC_CMD_POLL_BIST_IN_LEN;
  691         req.emr_out_buf = payload;
  692         req.emr_out_length = MCDI_CTL_SDU_LEN_MAX_V1;
  693 
  694         efx_mcdi_execute(enp, &req);
  695 
  696         if (req.emr_rc != 0) {
  697                 rc = req.emr_rc;
  698                 goto fail1;
  699         }
  700 
  701         if (req.emr_out_length_used < MC_CMD_POLL_BIST_OUT_RESULT_OFST + 4) {
  702                 rc = EMSGSIZE;
  703                 goto fail2;
  704         }
  705 
  706         if (count > 0)
  707                 (void) memset(valuesp, '\0', count * sizeof (unsigned long));
  708 
  709         result = MCDI_OUT_DWORD(req, POLL_BIST_OUT_RESULT);
  710 
  711         if (result == MC_CMD_POLL_BIST_FAILED &&
  712             req.emr_out_length >= MC_CMD_POLL_BIST_OUT_MEM_LEN &&
  713             count > EFX_BIST_MEM_ECC_FATAL) {
  714                 if (valuesp != NULL) {
  715                         valuesp[EFX_BIST_MEM_TEST] =
  716                             MCDI_OUT_DWORD(req, POLL_BIST_OUT_MEM_TEST);
  717                         valuesp[EFX_BIST_MEM_ADDR] =
  718                             MCDI_OUT_DWORD(req, POLL_BIST_OUT_MEM_ADDR);
  719                         valuesp[EFX_BIST_MEM_BUS] =
  720                             MCDI_OUT_DWORD(req, POLL_BIST_OUT_MEM_BUS);
  721                         valuesp[EFX_BIST_MEM_EXPECT] =
  722                             MCDI_OUT_DWORD(req, POLL_BIST_OUT_MEM_EXPECT);
  723                         valuesp[EFX_BIST_MEM_ACTUAL] =
  724                             MCDI_OUT_DWORD(req, POLL_BIST_OUT_MEM_ACTUAL);
  725                         valuesp[EFX_BIST_MEM_ECC] =
  726                             MCDI_OUT_DWORD(req, POLL_BIST_OUT_MEM_ECC);
  727                         valuesp[EFX_BIST_MEM_ECC_PARITY] =
  728                             MCDI_OUT_DWORD(req, POLL_BIST_OUT_MEM_ECC_PARITY);
  729                         valuesp[EFX_BIST_MEM_ECC_FATAL] =
  730                             MCDI_OUT_DWORD(req, POLL_BIST_OUT_MEM_ECC_FATAL);
  731                 }
  732                 value_mask |= (1 << EFX_BIST_MEM_TEST) |
  733                     (1 << EFX_BIST_MEM_ADDR) |
  734                     (1 << EFX_BIST_MEM_BUS) |
  735                     (1 << EFX_BIST_MEM_EXPECT) |
  736                     (1 << EFX_BIST_MEM_ACTUAL) |
  737                     (1 << EFX_BIST_MEM_ECC) |
  738                     (1 << EFX_BIST_MEM_ECC_PARITY) |
  739                     (1 << EFX_BIST_MEM_ECC_FATAL);
  740         } else if (result == MC_CMD_POLL_BIST_FAILED &&
  741             encp->enc_phy_type == EFX_PHY_XFI_FARMI &&
  742             req.emr_out_length >= MC_CMD_POLL_BIST_OUT_MRSFP_LEN &&
  743             count > EFX_BIST_FAULT_CODE) {
  744                 if (valuesp != NULL)
  745                         valuesp[EFX_BIST_FAULT_CODE] =
  746                             MCDI_OUT_DWORD(req, POLL_BIST_OUT_MRSFP_TEST);
  747                 value_mask |= 1 << EFX_BIST_FAULT_CODE;
  748         }
  749 
  750         if (value_maskp != NULL)
  751                 *value_maskp = value_mask;
  752 
  753         EFSYS_ASSERT(resultp != NULL);
  754         if (result == MC_CMD_POLL_BIST_RUNNING)
  755                 *resultp = EFX_BIST_RESULT_RUNNING;
  756         else if (result == MC_CMD_POLL_BIST_PASSED)
  757                 *resultp = EFX_BIST_RESULT_PASSED;
  758         else
  759                 *resultp = EFX_BIST_RESULT_FAILED;
  760 
  761         return (0);
  762 
  763 fail2:
  764         EFSYS_PROBE(fail2);
  765 fail1:
  766         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  767 
  768         return (rc);
  769 }
  770 
  771                         void
  772 ef10_bist_stop(
  773         __in            efx_nic_t *enp,
  774         __in            efx_bist_type_t type)
  775 {
  776         /* There is no way to stop BIST on EF10. */
  777         _NOTE(ARGUNUSED(enp, type))
  778 }
  779 
  780 #endif  /* EFSYS_OPT_BIST */
  781 
  782 #endif  /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */

Cache object: ddc7defe9272cae1cd3f57ac77811382


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.