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/efx_nic.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  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2007-2016 Solarflare Communications Inc.
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions are met:
    9  *
   10  * 1. Redistributions of source code must retain the above copyright notice,
   11  *    this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright notice,
   13  *    this list of conditions and the following disclaimer in the documentation
   14  *    and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
   18  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   19  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
   20  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   21  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   22  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
   23  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   24  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
   25  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
   26  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   27  *
   28  * The views and conclusions contained in the software and documentation are
   29  * those of the authors and should not be interpreted as representing official
   30  * policies, either expressed or implied, of the FreeBSD Project.
   31  */
   32 
   33 #include <sys/cdefs.h>
   34 __FBSDID("$FreeBSD$");
   35 
   36 #include "efx.h"
   37 #include "efx_impl.h"
   38 
   39         __checkReturn   efx_rc_t
   40 efx_family(
   41         __in            uint16_t venid,
   42         __in            uint16_t devid,
   43         __out           efx_family_t *efp,
   44         __out           unsigned int *membarp)
   45 {
   46         if (venid == EFX_PCI_VENID_SFC) {
   47                 switch (devid) {
   48 #if EFSYS_OPT_SIENA
   49                 case EFX_PCI_DEVID_SIENA_F1_UNINIT:
   50                         /*
   51                          * Hardware default for PF0 of uninitialised Siena.
   52                          * manftest must be able to cope with this device id.
   53                          */
   54                 case EFX_PCI_DEVID_BETHPAGE:
   55                 case EFX_PCI_DEVID_SIENA:
   56                         *efp = EFX_FAMILY_SIENA;
   57                         *membarp = EFX_MEM_BAR_SIENA;
   58                         return (0);
   59 #endif /* EFSYS_OPT_SIENA */
   60 
   61 #if EFSYS_OPT_HUNTINGTON
   62                 case EFX_PCI_DEVID_HUNTINGTON_PF_UNINIT:
   63                         /*
   64                          * Hardware default for PF0 of uninitialised Huntington.
   65                          * manftest must be able to cope with this device id.
   66                          */
   67                 case EFX_PCI_DEVID_FARMINGDALE:
   68                 case EFX_PCI_DEVID_GREENPORT:
   69                         *efp = EFX_FAMILY_HUNTINGTON;
   70                         *membarp = EFX_MEM_BAR_HUNTINGTON_PF;
   71                         return (0);
   72 
   73                 case EFX_PCI_DEVID_FARMINGDALE_VF:
   74                 case EFX_PCI_DEVID_GREENPORT_VF:
   75                         *efp = EFX_FAMILY_HUNTINGTON;
   76                         *membarp = EFX_MEM_BAR_HUNTINGTON_VF;
   77                         return (0);
   78 #endif /* EFSYS_OPT_HUNTINGTON */
   79 
   80 #if EFSYS_OPT_MEDFORD
   81                 case EFX_PCI_DEVID_MEDFORD_PF_UNINIT:
   82                         /*
   83                          * Hardware default for PF0 of uninitialised Medford.
   84                          * manftest must be able to cope with this device id.
   85                          */
   86                 case EFX_PCI_DEVID_MEDFORD:
   87                         *efp = EFX_FAMILY_MEDFORD;
   88                         *membarp = EFX_MEM_BAR_MEDFORD_PF;
   89                         return (0);
   90 
   91                 case EFX_PCI_DEVID_MEDFORD_VF:
   92                         *efp = EFX_FAMILY_MEDFORD;
   93                         *membarp = EFX_MEM_BAR_MEDFORD_VF;
   94                         return (0);
   95 #endif /* EFSYS_OPT_MEDFORD */
   96 
   97 #if EFSYS_OPT_MEDFORD2
   98                 case EFX_PCI_DEVID_MEDFORD2_PF_UNINIT:
   99                         /*
  100                          * Hardware default for PF0 of uninitialised Medford2.
  101                          * manftest must be able to cope with this device id.
  102                          */
  103                 case EFX_PCI_DEVID_MEDFORD2:
  104                 case EFX_PCI_DEVID_MEDFORD2_VF:
  105                         *efp = EFX_FAMILY_MEDFORD2;
  106                         *membarp = EFX_MEM_BAR_MEDFORD2;
  107                         return (0);
  108 #endif /* EFSYS_OPT_MEDFORD2 */
  109 
  110                 case EFX_PCI_DEVID_FALCON:      /* Obsolete, not supported */
  111                 default:
  112                         break;
  113                 }
  114         }
  115 
  116         *efp = EFX_FAMILY_INVALID;
  117         return (ENOTSUP);
  118 }
  119 
  120 #if EFSYS_OPT_SIENA
  121 
  122 static const efx_nic_ops_t      __efx_nic_siena_ops = {
  123         siena_nic_probe,                /* eno_probe */
  124         NULL,                           /* eno_board_cfg */
  125         NULL,                           /* eno_set_drv_limits */
  126         siena_nic_reset,                /* eno_reset */
  127         siena_nic_init,                 /* eno_init */
  128         NULL,                           /* eno_get_vi_pool */
  129         NULL,                           /* eno_get_bar_region */
  130         NULL,                           /* eno_hw_unavailable */
  131         NULL,                           /* eno_set_hw_unavailable */
  132 #if EFSYS_OPT_DIAG
  133         siena_nic_register_test,        /* eno_register_test */
  134 #endif  /* EFSYS_OPT_DIAG */
  135         siena_nic_fini,                 /* eno_fini */
  136         siena_nic_unprobe,              /* eno_unprobe */
  137 };
  138 
  139 #endif  /* EFSYS_OPT_SIENA */
  140 
  141 #if EFSYS_OPT_HUNTINGTON
  142 
  143 static const efx_nic_ops_t      __efx_nic_hunt_ops = {
  144         ef10_nic_probe,                 /* eno_probe */
  145         hunt_board_cfg,                 /* eno_board_cfg */
  146         ef10_nic_set_drv_limits,        /* eno_set_drv_limits */
  147         ef10_nic_reset,                 /* eno_reset */
  148         ef10_nic_init,                  /* eno_init */
  149         ef10_nic_get_vi_pool,           /* eno_get_vi_pool */
  150         ef10_nic_get_bar_region,        /* eno_get_bar_region */
  151         ef10_nic_hw_unavailable,        /* eno_hw_unavailable */
  152         ef10_nic_set_hw_unavailable,    /* eno_set_hw_unavailable */
  153 #if EFSYS_OPT_DIAG
  154         ef10_nic_register_test,         /* eno_register_test */
  155 #endif  /* EFSYS_OPT_DIAG */
  156         ef10_nic_fini,                  /* eno_fini */
  157         ef10_nic_unprobe,               /* eno_unprobe */
  158 };
  159 
  160 #endif  /* EFSYS_OPT_HUNTINGTON */
  161 
  162 #if EFSYS_OPT_MEDFORD
  163 
  164 static const efx_nic_ops_t      __efx_nic_medford_ops = {
  165         ef10_nic_probe,                 /* eno_probe */
  166         medford_board_cfg,              /* eno_board_cfg */
  167         ef10_nic_set_drv_limits,        /* eno_set_drv_limits */
  168         ef10_nic_reset,                 /* eno_reset */
  169         ef10_nic_init,                  /* eno_init */
  170         ef10_nic_get_vi_pool,           /* eno_get_vi_pool */
  171         ef10_nic_get_bar_region,        /* eno_get_bar_region */
  172         ef10_nic_hw_unavailable,        /* eno_hw_unavailable */
  173         ef10_nic_set_hw_unavailable,    /* eno_set_hw_unavailable */
  174 #if EFSYS_OPT_DIAG
  175         ef10_nic_register_test,         /* eno_register_test */
  176 #endif  /* EFSYS_OPT_DIAG */
  177         ef10_nic_fini,                  /* eno_fini */
  178         ef10_nic_unprobe,               /* eno_unprobe */
  179 };
  180 
  181 #endif  /* EFSYS_OPT_MEDFORD */
  182 
  183 #if EFSYS_OPT_MEDFORD2
  184 
  185 static const efx_nic_ops_t      __efx_nic_medford2_ops = {
  186         ef10_nic_probe,                 /* eno_probe */
  187         medford2_board_cfg,             /* eno_board_cfg */
  188         ef10_nic_set_drv_limits,        /* eno_set_drv_limits */
  189         ef10_nic_reset,                 /* eno_reset */
  190         ef10_nic_init,                  /* eno_init */
  191         ef10_nic_get_vi_pool,           /* eno_get_vi_pool */
  192         ef10_nic_get_bar_region,        /* eno_get_bar_region */
  193         ef10_nic_hw_unavailable,        /* eno_hw_unavailable */
  194         ef10_nic_set_hw_unavailable,    /* eno_set_hw_unavailable */
  195 #if EFSYS_OPT_DIAG
  196         ef10_nic_register_test,         /* eno_register_test */
  197 #endif  /* EFSYS_OPT_DIAG */
  198         ef10_nic_fini,                  /* eno_fini */
  199         ef10_nic_unprobe,               /* eno_unprobe */
  200 };
  201 
  202 #endif  /* EFSYS_OPT_MEDFORD2 */
  203 
  204         __checkReturn   efx_rc_t
  205 efx_nic_create(
  206         __in            efx_family_t family,
  207         __in            efsys_identifier_t *esip,
  208         __in            efsys_bar_t *esbp,
  209         __in            efsys_lock_t *eslp,
  210         __deref_out     efx_nic_t **enpp)
  211 {
  212         efx_nic_t *enp;
  213         efx_rc_t rc;
  214 
  215         EFSYS_ASSERT3U(family, >, EFX_FAMILY_INVALID);
  216         EFSYS_ASSERT3U(family, <, EFX_FAMILY_NTYPES);
  217 
  218         /* Allocate a NIC object */
  219         EFSYS_KMEM_ALLOC(esip, sizeof (efx_nic_t), enp);
  220 
  221         if (enp == NULL) {
  222                 rc = ENOMEM;
  223                 goto fail1;
  224         }
  225 
  226         enp->en_magic = EFX_NIC_MAGIC;
  227 
  228         switch (family) {
  229 #if EFSYS_OPT_SIENA
  230         case EFX_FAMILY_SIENA:
  231                 enp->en_enop = &__efx_nic_siena_ops;
  232                 enp->en_features =
  233                     EFX_FEATURE_IPV6 |
  234                     EFX_FEATURE_LFSR_HASH_INSERT |
  235                     EFX_FEATURE_LINK_EVENTS |
  236                     EFX_FEATURE_PERIODIC_MAC_STATS |
  237                     EFX_FEATURE_MCDI |
  238                     EFX_FEATURE_LOOKAHEAD_SPLIT |
  239                     EFX_FEATURE_MAC_HEADER_FILTERS |
  240                     EFX_FEATURE_TX_SRC_FILTERS;
  241                 break;
  242 #endif  /* EFSYS_OPT_SIENA */
  243 
  244 #if EFSYS_OPT_HUNTINGTON
  245         case EFX_FAMILY_HUNTINGTON:
  246                 enp->en_enop = &__efx_nic_hunt_ops;
  247                 enp->en_features =
  248                     EFX_FEATURE_IPV6 |
  249                     EFX_FEATURE_LINK_EVENTS |
  250                     EFX_FEATURE_PERIODIC_MAC_STATS |
  251                     EFX_FEATURE_MCDI |
  252                     EFX_FEATURE_MAC_HEADER_FILTERS |
  253                     EFX_FEATURE_MCDI_DMA |
  254                     EFX_FEATURE_PIO_BUFFERS |
  255                     EFX_FEATURE_FW_ASSISTED_TSO |
  256                     EFX_FEATURE_FW_ASSISTED_TSO_V2 |
  257                     EFX_FEATURE_PACKED_STREAM |
  258                     EFX_FEATURE_TXQ_CKSUM_OP_DESC;
  259                 break;
  260 #endif  /* EFSYS_OPT_HUNTINGTON */
  261 
  262 #if EFSYS_OPT_MEDFORD
  263         case EFX_FAMILY_MEDFORD:
  264                 enp->en_enop = &__efx_nic_medford_ops;
  265                 /*
  266                  * FW_ASSISTED_TSO omitted as Medford only supports firmware
  267                  * assisted TSO version 2, not the v1 scheme used on Huntington.
  268                  */
  269                 enp->en_features =
  270                     EFX_FEATURE_IPV6 |
  271                     EFX_FEATURE_LINK_EVENTS |
  272                     EFX_FEATURE_PERIODIC_MAC_STATS |
  273                     EFX_FEATURE_MCDI |
  274                     EFX_FEATURE_MAC_HEADER_FILTERS |
  275                     EFX_FEATURE_MCDI_DMA |
  276                     EFX_FEATURE_PIO_BUFFERS |
  277                     EFX_FEATURE_FW_ASSISTED_TSO_V2 |
  278                     EFX_FEATURE_PACKED_STREAM |
  279                     EFX_FEATURE_TXQ_CKSUM_OP_DESC;
  280                 break;
  281 #endif  /* EFSYS_OPT_MEDFORD */
  282 
  283 #if EFSYS_OPT_MEDFORD2
  284         case EFX_FAMILY_MEDFORD2:
  285                 enp->en_enop = &__efx_nic_medford2_ops;
  286                 enp->en_features =
  287                     EFX_FEATURE_IPV6 |
  288                     EFX_FEATURE_LINK_EVENTS |
  289                     EFX_FEATURE_PERIODIC_MAC_STATS |
  290                     EFX_FEATURE_MCDI |
  291                     EFX_FEATURE_MAC_HEADER_FILTERS |
  292                     EFX_FEATURE_MCDI_DMA |
  293                     EFX_FEATURE_PIO_BUFFERS |
  294                     EFX_FEATURE_FW_ASSISTED_TSO_V2 |
  295                     EFX_FEATURE_PACKED_STREAM |
  296                     EFX_FEATURE_TXQ_CKSUM_OP_DESC;
  297                 break;
  298 #endif  /* EFSYS_OPT_MEDFORD2 */
  299 
  300         default:
  301                 rc = ENOTSUP;
  302                 goto fail2;
  303         }
  304 
  305         enp->en_family = family;
  306         enp->en_esip = esip;
  307         enp->en_esbp = esbp;
  308         enp->en_eslp = eslp;
  309 
  310         *enpp = enp;
  311 
  312         return (0);
  313 
  314 fail2:
  315         EFSYS_PROBE(fail2);
  316 
  317         enp->en_magic = 0;
  318 
  319         /* Free the NIC object */
  320         EFSYS_KMEM_FREE(esip, sizeof (efx_nic_t), enp);
  321 
  322 fail1:
  323         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  324 
  325         return (rc);
  326 }
  327 
  328         __checkReturn   efx_rc_t
  329 efx_nic_probe(
  330         __in            efx_nic_t *enp,
  331         __in            efx_fw_variant_t efv)
  332 {
  333         const efx_nic_ops_t *enop;
  334         efx_rc_t rc;
  335 
  336         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
  337 #if EFSYS_OPT_MCDI
  338         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI);
  339 #endif  /* EFSYS_OPT_MCDI */
  340         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_PROBE));
  341 
  342         /* Ensure FW variant codes match with MC_CMD_FW codes */
  343         EFX_STATIC_ASSERT(EFX_FW_VARIANT_FULL_FEATURED ==
  344             MC_CMD_FW_FULL_FEATURED);
  345         EFX_STATIC_ASSERT(EFX_FW_VARIANT_LOW_LATENCY ==
  346             MC_CMD_FW_LOW_LATENCY);
  347         EFX_STATIC_ASSERT(EFX_FW_VARIANT_PACKED_STREAM ==
  348             MC_CMD_FW_PACKED_STREAM);
  349         EFX_STATIC_ASSERT(EFX_FW_VARIANT_HIGH_TX_RATE ==
  350             MC_CMD_FW_HIGH_TX_RATE);
  351         EFX_STATIC_ASSERT(EFX_FW_VARIANT_PACKED_STREAM_HASH_MODE_1 ==
  352             MC_CMD_FW_PACKED_STREAM_HASH_MODE_1);
  353         EFX_STATIC_ASSERT(EFX_FW_VARIANT_RULES_ENGINE ==
  354             MC_CMD_FW_RULES_ENGINE);
  355         EFX_STATIC_ASSERT(EFX_FW_VARIANT_DPDK ==
  356             MC_CMD_FW_DPDK);
  357         EFX_STATIC_ASSERT(EFX_FW_VARIANT_DONT_CARE ==
  358             (int)MC_CMD_FW_DONT_CARE);
  359 
  360         enop = enp->en_enop;
  361         enp->efv = efv;
  362 
  363         if ((rc = enop->eno_probe(enp)) != 0)
  364                 goto fail1;
  365 
  366         if ((rc = efx_phy_probe(enp)) != 0)
  367                 goto fail2;
  368 
  369         enp->en_mod_flags |= EFX_MOD_PROBE;
  370 
  371         return (0);
  372 
  373 fail2:
  374         EFSYS_PROBE(fail2);
  375 
  376         enop->eno_unprobe(enp);
  377 
  378 fail1:
  379         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  380 
  381         return (rc);
  382 }
  383 
  384         __checkReturn   efx_rc_t
  385 efx_nic_set_drv_limits(
  386         __inout         efx_nic_t *enp,
  387         __in            efx_drv_limits_t *edlp)
  388 {
  389         const efx_nic_ops_t *enop = enp->en_enop;
  390         efx_rc_t rc;
  391 
  392         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
  393         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
  394 
  395         if (enop->eno_set_drv_limits != NULL) {
  396                 if ((rc = enop->eno_set_drv_limits(enp, edlp)) != 0)
  397                         goto fail1;
  398         }
  399 
  400         return (0);
  401 
  402 fail1:
  403         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  404 
  405         return (rc);
  406 }
  407 
  408         __checkReturn   efx_rc_t
  409 efx_nic_get_bar_region(
  410         __in            efx_nic_t *enp,
  411         __in            efx_nic_region_t region,
  412         __out           uint32_t *offsetp,
  413         __out           size_t *sizep)
  414 {
  415         const efx_nic_ops_t *enop = enp->en_enop;
  416         efx_rc_t rc;
  417 
  418         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
  419         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
  420         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
  421 
  422         if (enop->eno_get_bar_region == NULL) {
  423                 rc = ENOTSUP;
  424                 goto fail1;
  425         }
  426         if ((rc = (enop->eno_get_bar_region)(enp,
  427                     region, offsetp, sizep)) != 0) {
  428                 goto fail2;
  429         }
  430 
  431         return (0);
  432 
  433 fail2:
  434         EFSYS_PROBE(fail2);
  435 
  436 fail1:
  437         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  438 
  439         return (rc);
  440 }
  441 
  442         __checkReturn   efx_rc_t
  443 efx_nic_get_vi_pool(
  444         __in            efx_nic_t *enp,
  445         __out           uint32_t *evq_countp,
  446         __out           uint32_t *rxq_countp,
  447         __out           uint32_t *txq_countp)
  448 {
  449         const efx_nic_ops_t *enop = enp->en_enop;
  450         efx_nic_cfg_t *encp = &enp->en_nic_cfg;
  451         efx_rc_t rc;
  452 
  453         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
  454         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
  455         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
  456 
  457         if (enop->eno_get_vi_pool != NULL) {
  458                 uint32_t vi_count = 0;
  459 
  460                 if ((rc = (enop->eno_get_vi_pool)(enp, &vi_count)) != 0)
  461                         goto fail1;
  462 
  463                 *evq_countp = vi_count;
  464                 *rxq_countp = vi_count;
  465                 *txq_countp = vi_count;
  466         } else {
  467                 /* Use NIC limits as default value */
  468                 *evq_countp = encp->enc_evq_limit;
  469                 *rxq_countp = encp->enc_rxq_limit;
  470                 *txq_countp = encp->enc_txq_limit;
  471         }
  472 
  473         return (0);
  474 
  475 fail1:
  476         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  477 
  478         return (rc);
  479 }
  480 
  481         __checkReturn   efx_rc_t
  482 efx_nic_init(
  483         __in            efx_nic_t *enp)
  484 {
  485         const efx_nic_ops_t *enop = enp->en_enop;
  486         efx_rc_t rc;
  487 
  488         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
  489         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
  490 
  491         if (enp->en_mod_flags & EFX_MOD_NIC) {
  492                 rc = EINVAL;
  493                 goto fail1;
  494         }
  495 
  496         if ((rc = enop->eno_init(enp)) != 0)
  497                 goto fail2;
  498 
  499         enp->en_mod_flags |= EFX_MOD_NIC;
  500 
  501         return (0);
  502 
  503 fail2:
  504         EFSYS_PROBE(fail2);
  505 fail1:
  506         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  507 
  508         return (rc);
  509 }
  510 
  511                         void
  512 efx_nic_fini(
  513         __in            efx_nic_t *enp)
  514 {
  515         const efx_nic_ops_t *enop = enp->en_enop;
  516 
  517         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
  518         EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_PROBE);
  519         EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_NIC);
  520         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_INTR));
  521         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV));
  522         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_RX));
  523         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TX));
  524 
  525         enop->eno_fini(enp);
  526 
  527         enp->en_mod_flags &= ~EFX_MOD_NIC;
  528 }
  529 
  530                         void
  531 efx_nic_unprobe(
  532         __in            efx_nic_t *enp)
  533 {
  534         const efx_nic_ops_t *enop = enp->en_enop;
  535 
  536         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
  537 #if EFSYS_OPT_MCDI
  538         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI);
  539 #endif  /* EFSYS_OPT_MCDI */
  540         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
  541         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NIC));
  542         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_INTR));
  543         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV));
  544         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_RX));
  545         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TX));
  546 
  547         efx_phy_unprobe(enp);
  548 
  549         enop->eno_unprobe(enp);
  550 
  551         enp->en_mod_flags &= ~EFX_MOD_PROBE;
  552 }
  553 
  554                         void
  555 efx_nic_destroy(
  556         __in    efx_nic_t *enp)
  557 {
  558         efsys_identifier_t *esip = enp->en_esip;
  559 
  560         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
  561         EFSYS_ASSERT3U(enp->en_mod_flags, ==, 0);
  562 
  563         enp->en_family = EFX_FAMILY_INVALID;
  564         enp->en_esip = NULL;
  565         enp->en_esbp = NULL;
  566         enp->en_eslp = NULL;
  567 
  568         enp->en_enop = NULL;
  569 
  570         enp->en_magic = 0;
  571 
  572         /* Free the NIC object */
  573         EFSYS_KMEM_FREE(esip, sizeof (efx_nic_t), enp);
  574 }
  575 
  576         __checkReturn   efx_rc_t
  577 efx_nic_reset(
  578         __in            efx_nic_t *enp)
  579 {
  580         const efx_nic_ops_t *enop = enp->en_enop;
  581         unsigned int mod_flags;
  582         efx_rc_t rc;
  583 
  584         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
  585         EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_PROBE);
  586         /*
  587          * All modules except the MCDI, PROBE, NVRAM, VPD, MON, TUNNEL
  588          * (which we do not reset here) must have been shut down or never
  589          * initialized.
  590          *
  591          * A rule of thumb here is: If the controller or MC reboots, is *any*
  592          * state lost. If it's lost and needs reapplying, then the module
  593          * *must* not be initialised during the reset.
  594          */
  595         mod_flags = enp->en_mod_flags;
  596         mod_flags &= ~(EFX_MOD_MCDI | EFX_MOD_PROBE | EFX_MOD_NVRAM |
  597             EFX_MOD_VPD | EFX_MOD_MON);
  598 #if EFSYS_OPT_TUNNEL
  599         mod_flags &= ~EFX_MOD_TUNNEL;
  600 #endif /* EFSYS_OPT_TUNNEL */
  601         EFSYS_ASSERT3U(mod_flags, ==, 0);
  602         if (mod_flags != 0) {
  603                 rc = EINVAL;
  604                 goto fail1;
  605         }
  606 
  607         if ((rc = enop->eno_reset(enp)) != 0)
  608                 goto fail2;
  609 
  610         return (0);
  611 
  612 fail2:
  613         EFSYS_PROBE(fail2);
  614 fail1:
  615         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  616 
  617         return (rc);
  618 }
  619 
  620                         const efx_nic_cfg_t *
  621 efx_nic_cfg_get(
  622         __in            efx_nic_t *enp)
  623 {
  624         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
  625         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
  626 
  627         return (&(enp->en_nic_cfg));
  628 }
  629 
  630         __checkReturn           efx_rc_t
  631 efx_nic_get_fw_version(
  632         __in                    efx_nic_t *enp,
  633         __out                   efx_nic_fw_info_t *enfip)
  634 {
  635         uint16_t mc_fw_version[4];
  636         efx_rc_t rc;
  637 
  638         if (enfip == NULL) {
  639                 rc = EINVAL;
  640                 goto fail1;
  641         }
  642 
  643         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI);
  644         EFSYS_ASSERT3U(enp->en_features, &, EFX_FEATURE_MCDI);
  645 
  646         /* Ensure RXDP_FW_ID codes match with MC_CMD_GET_CAPABILITIES codes */
  647         EFX_STATIC_ASSERT(EFX_RXDP_FULL_FEATURED_FW_ID ==
  648             MC_CMD_GET_CAPABILITIES_OUT_RXDP);
  649         EFX_STATIC_ASSERT(EFX_RXDP_LOW_LATENCY_FW_ID ==
  650             MC_CMD_GET_CAPABILITIES_OUT_RXDP_LOW_LATENCY);
  651         EFX_STATIC_ASSERT(EFX_RXDP_PACKED_STREAM_FW_ID ==
  652             MC_CMD_GET_CAPABILITIES_OUT_RXDP_PACKED_STREAM);
  653         EFX_STATIC_ASSERT(EFX_RXDP_RULES_ENGINE_FW_ID ==
  654             MC_CMD_GET_CAPABILITIES_OUT_RXDP_RULES_ENGINE);
  655         EFX_STATIC_ASSERT(EFX_RXDP_DPDK_FW_ID ==
  656             MC_CMD_GET_CAPABILITIES_OUT_RXDP_DPDK);
  657 
  658         rc = efx_mcdi_version(enp, mc_fw_version, NULL, NULL);
  659         if (rc != 0)
  660                 goto fail2;
  661 
  662         rc = efx_mcdi_get_capabilities(enp, NULL,
  663             &enfip->enfi_rx_dpcpu_fw_id,
  664             &enfip->enfi_tx_dpcpu_fw_id,
  665             NULL, NULL);
  666         if (rc == 0) {
  667                 enfip->enfi_dpcpu_fw_ids_valid = B_TRUE;
  668         } else if (rc == ENOTSUP) {
  669                 enfip->enfi_dpcpu_fw_ids_valid = B_FALSE;
  670                 enfip->enfi_rx_dpcpu_fw_id = 0;
  671                 enfip->enfi_tx_dpcpu_fw_id = 0;
  672         } else {
  673                 goto fail3;
  674         }
  675 
  676         memcpy(enfip->enfi_mc_fw_version, mc_fw_version,
  677             sizeof (mc_fw_version));
  678 
  679         return (0);
  680 
  681 fail3:
  682         EFSYS_PROBE(fail3);
  683 fail2:
  684         EFSYS_PROBE(fail2);
  685 fail1:
  686         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  687 
  688         return (rc);
  689 }
  690 
  691         __checkReturn   boolean_t
  692 efx_nic_hw_unavailable(
  693         __in            efx_nic_t *enp)
  694 {
  695         const efx_nic_ops_t *enop = enp->en_enop;
  696 
  697         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
  698         /* NOTE: can be used by MCDI before NIC probe */
  699 
  700         if (enop->eno_hw_unavailable != NULL) {
  701                 if ((enop->eno_hw_unavailable)(enp) != B_FALSE)
  702                         goto unavail;
  703         }
  704 
  705         return (B_FALSE);
  706 
  707 unavail:
  708         return (B_TRUE);
  709 }
  710 
  711                         void
  712 efx_nic_set_hw_unavailable(
  713         __in            efx_nic_t *enp)
  714 {
  715         const efx_nic_ops_t *enop = enp->en_enop;
  716 
  717         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
  718 
  719         if (enop->eno_set_hw_unavailable != NULL)
  720                 enop->eno_set_hw_unavailable(enp);
  721 }
  722 
  723 #if EFSYS_OPT_DIAG
  724 
  725         __checkReturn   efx_rc_t
  726 efx_nic_register_test(
  727         __in            efx_nic_t *enp)
  728 {
  729         const efx_nic_ops_t *enop = enp->en_enop;
  730         efx_rc_t rc;
  731 
  732         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
  733         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
  734         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NIC));
  735 
  736         if ((rc = enop->eno_register_test(enp)) != 0)
  737                 goto fail1;
  738 
  739         return (0);
  740 
  741 fail1:
  742         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  743 
  744         return (rc);
  745 }
  746 
  747 #endif  /* EFSYS_OPT_DIAG */
  748 
  749 #if EFSYS_OPT_LOOPBACK
  750 
  751 extern                  void
  752 efx_loopback_mask(
  753         __in    efx_loopback_kind_t loopback_kind,
  754         __out   efx_qword_t *maskp)
  755 {
  756         efx_qword_t mask;
  757 
  758         EFSYS_ASSERT3U(loopback_kind, <, EFX_LOOPBACK_NKINDS);
  759         EFSYS_ASSERT(maskp != NULL);
  760 
  761         /* Assert the MC_CMD_LOOPBACK and EFX_LOOPBACK namespaces agree */
  762 #define LOOPBACK_CHECK(_mcdi, _efx) \
  763         EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_##_mcdi == EFX_LOOPBACK_##_efx)
  764 
  765         LOOPBACK_CHECK(NONE, OFF);
  766         LOOPBACK_CHECK(DATA, DATA);
  767         LOOPBACK_CHECK(GMAC, GMAC);
  768         LOOPBACK_CHECK(XGMII, XGMII);
  769         LOOPBACK_CHECK(XGXS, XGXS);
  770         LOOPBACK_CHECK(XAUI, XAUI);
  771         LOOPBACK_CHECK(GMII, GMII);
  772         LOOPBACK_CHECK(SGMII, SGMII);
  773         LOOPBACK_CHECK(XGBR, XGBR);
  774         LOOPBACK_CHECK(XFI, XFI);
  775         LOOPBACK_CHECK(XAUI_FAR, XAUI_FAR);
  776         LOOPBACK_CHECK(GMII_FAR, GMII_FAR);
  777         LOOPBACK_CHECK(SGMII_FAR, SGMII_FAR);
  778         LOOPBACK_CHECK(XFI_FAR, XFI_FAR);
  779         LOOPBACK_CHECK(GPHY, GPHY);
  780         LOOPBACK_CHECK(PHYXS, PHY_XS);
  781         LOOPBACK_CHECK(PCS, PCS);
  782         LOOPBACK_CHECK(PMAPMD, PMA_PMD);
  783         LOOPBACK_CHECK(XPORT, XPORT);
  784         LOOPBACK_CHECK(XGMII_WS, XGMII_WS);
  785         LOOPBACK_CHECK(XAUI_WS, XAUI_WS);
  786         LOOPBACK_CHECK(XAUI_WS_FAR, XAUI_WS_FAR);
  787         LOOPBACK_CHECK(XAUI_WS_NEAR, XAUI_WS_NEAR);
  788         LOOPBACK_CHECK(GMII_WS, GMII_WS);
  789         LOOPBACK_CHECK(XFI_WS, XFI_WS);
  790         LOOPBACK_CHECK(XFI_WS_FAR, XFI_WS_FAR);
  791         LOOPBACK_CHECK(PHYXS_WS, PHYXS_WS);
  792         LOOPBACK_CHECK(PMA_INT, PMA_INT);
  793         LOOPBACK_CHECK(SD_NEAR, SD_NEAR);
  794         LOOPBACK_CHECK(SD_FAR, SD_FAR);
  795         LOOPBACK_CHECK(PMA_INT_WS, PMA_INT_WS);
  796         LOOPBACK_CHECK(SD_FEP2_WS, SD_FEP2_WS);
  797         LOOPBACK_CHECK(SD_FEP1_5_WS, SD_FEP1_5_WS);
  798         LOOPBACK_CHECK(SD_FEP_WS, SD_FEP_WS);
  799         LOOPBACK_CHECK(SD_FES_WS, SD_FES_WS);
  800         LOOPBACK_CHECK(AOE_INT_NEAR, AOE_INT_NEAR);
  801         LOOPBACK_CHECK(DATA_WS, DATA_WS);
  802         LOOPBACK_CHECK(FORCE_EXT_LINK, FORCE_EXT_LINK);
  803 #undef LOOPBACK_CHECK
  804 
  805         /* Build bitmask of possible loopback types */
  806         EFX_ZERO_QWORD(mask);
  807 
  808         if ((loopback_kind == EFX_LOOPBACK_KIND_OFF) ||
  809             (loopback_kind == EFX_LOOPBACK_KIND_ALL)) {
  810                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_OFF);
  811         }
  812 
  813         if ((loopback_kind == EFX_LOOPBACK_KIND_MAC) ||
  814             (loopback_kind == EFX_LOOPBACK_KIND_ALL)) {
  815                 /*
  816                  * The "MAC" grouping has historically been used by drivers to
  817                  * mean loopbacks supported by on-chip hardware. Keep that
  818                  * meaning here, and include on-chip PHY layer loopbacks.
  819                  */
  820                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_DATA);
  821                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_GMAC);
  822                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XGMII);
  823                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XGXS);
  824                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XAUI);
  825                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_GMII);
  826                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_SGMII);
  827                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XGBR);
  828                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XFI);
  829                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XAUI_FAR);
  830                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_GMII_FAR);
  831                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_SGMII_FAR);
  832                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XFI_FAR);
  833                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_PMA_INT);
  834                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_SD_NEAR);
  835                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_SD_FAR);
  836         }
  837 
  838         if ((loopback_kind == EFX_LOOPBACK_KIND_PHY) ||
  839             (loopback_kind == EFX_LOOPBACK_KIND_ALL)) {
  840                 /*
  841                  * The "PHY" grouping has historically been used by drivers to
  842                  * mean loopbacks supported by off-chip hardware. Keep that
  843                  * meaning here.
  844                  */
  845                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_GPHY);
  846                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_PHY_XS);
  847                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_PCS);
  848                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_PMA_PMD);
  849         }
  850 
  851         *maskp = mask;
  852 }
  853 
  854         __checkReturn   efx_rc_t
  855 efx_mcdi_get_loopback_modes(
  856         __in            efx_nic_t *enp)
  857 {
  858         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
  859         efx_mcdi_req_t req;
  860         EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_LOOPBACK_MODES_IN_LEN,
  861                 MC_CMD_GET_LOOPBACK_MODES_OUT_V2_LEN);
  862         efx_qword_t mask;
  863         efx_qword_t modes;
  864         efx_rc_t rc;
  865 
  866         req.emr_cmd = MC_CMD_GET_LOOPBACK_MODES;
  867         req.emr_in_buf = payload;
  868         req.emr_in_length = MC_CMD_GET_LOOPBACK_MODES_IN_LEN;
  869         req.emr_out_buf = payload;
  870         req.emr_out_length = MC_CMD_GET_LOOPBACK_MODES_OUT_V2_LEN;
  871 
  872         efx_mcdi_execute(enp, &req);
  873 
  874         if (req.emr_rc != 0) {
  875                 rc = req.emr_rc;
  876                 goto fail1;
  877         }
  878 
  879         if (req.emr_out_length_used <
  880             MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_OFST +
  881             MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_LEN) {
  882                 rc = EMSGSIZE;
  883                 goto fail2;
  884         }
  885 
  886         /*
  887          * We assert the MC_CMD_LOOPBACK and EFX_LOOPBACK namespaces agree
  888          * in efx_loopback_mask() and in siena_phy.c:siena_phy_get_link().
  889          */
  890         efx_loopback_mask(EFX_LOOPBACK_KIND_ALL, &mask);
  891 
  892         EFX_AND_QWORD(mask,
  893             *MCDI_OUT2(req, efx_qword_t, GET_LOOPBACK_MODES_OUT_SUGGESTED));
  894 
  895         modes = *MCDI_OUT2(req, efx_qword_t, GET_LOOPBACK_MODES_OUT_100M);
  896         EFX_AND_QWORD(modes, mask);
  897         encp->enc_loopback_types[EFX_LINK_100FDX] = modes;
  898 
  899         modes = *MCDI_OUT2(req, efx_qword_t, GET_LOOPBACK_MODES_OUT_1G);
  900         EFX_AND_QWORD(modes, mask);
  901         encp->enc_loopback_types[EFX_LINK_1000FDX] = modes;
  902 
  903         modes = *MCDI_OUT2(req, efx_qword_t, GET_LOOPBACK_MODES_OUT_10G);
  904         EFX_AND_QWORD(modes, mask);
  905         encp->enc_loopback_types[EFX_LINK_10000FDX] = modes;
  906 
  907         if (req.emr_out_length_used >=
  908             MC_CMD_GET_LOOPBACK_MODES_OUT_40G_OFST +
  909             MC_CMD_GET_LOOPBACK_MODES_OUT_40G_LEN) {
  910                 /* Response includes 40G loopback modes */
  911                 modes = *MCDI_OUT2(req, efx_qword_t,
  912                     GET_LOOPBACK_MODES_OUT_40G);
  913                 EFX_AND_QWORD(modes, mask);
  914                 encp->enc_loopback_types[EFX_LINK_40000FDX] = modes;
  915         }
  916 
  917         if (req.emr_out_length_used >=
  918             MC_CMD_GET_LOOPBACK_MODES_OUT_V2_25G_OFST +
  919             MC_CMD_GET_LOOPBACK_MODES_OUT_V2_25G_LEN) {
  920                 /* Response includes 25G loopback modes */
  921                 modes = *MCDI_OUT2(req, efx_qword_t,
  922                     GET_LOOPBACK_MODES_OUT_V2_25G);
  923                 EFX_AND_QWORD(modes, mask);
  924                 encp->enc_loopback_types[EFX_LINK_25000FDX] = modes;
  925         }
  926 
  927         if (req.emr_out_length_used >=
  928             MC_CMD_GET_LOOPBACK_MODES_OUT_V2_50G_OFST +
  929             MC_CMD_GET_LOOPBACK_MODES_OUT_V2_50G_LEN) {
  930                 /* Response includes 50G loopback modes */
  931                 modes = *MCDI_OUT2(req, efx_qword_t,
  932                     GET_LOOPBACK_MODES_OUT_V2_50G);
  933                 EFX_AND_QWORD(modes, mask);
  934                 encp->enc_loopback_types[EFX_LINK_50000FDX] = modes;
  935         }
  936 
  937         if (req.emr_out_length_used >=
  938             MC_CMD_GET_LOOPBACK_MODES_OUT_V2_100G_OFST +
  939             MC_CMD_GET_LOOPBACK_MODES_OUT_V2_100G_LEN) {
  940                 /* Response includes 100G loopback modes */
  941                 modes = *MCDI_OUT2(req, efx_qword_t,
  942                     GET_LOOPBACK_MODES_OUT_V2_100G);
  943                 EFX_AND_QWORD(modes, mask);
  944                 encp->enc_loopback_types[EFX_LINK_100000FDX] = modes;
  945         }
  946 
  947         EFX_ZERO_QWORD(modes);
  948         EFX_SET_QWORD_BIT(modes, EFX_LOOPBACK_OFF);
  949         EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_100FDX]);
  950         EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_1000FDX]);
  951         EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_10000FDX]);
  952         EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_40000FDX]);
  953         EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_25000FDX]);
  954         EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_50000FDX]);
  955         EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_100000FDX]);
  956         encp->enc_loopback_types[EFX_LINK_UNKNOWN] = modes;
  957 
  958         return (0);
  959 
  960 fail2:
  961         EFSYS_PROBE(fail2);
  962 fail1:
  963         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  964 
  965         return (rc);
  966 }
  967 
  968 #endif /* EFSYS_OPT_LOOPBACK */
  969 
  970         __checkReturn   efx_rc_t
  971 efx_nic_calculate_pcie_link_bandwidth(
  972         __in            uint32_t pcie_link_width,
  973         __in            uint32_t pcie_link_gen,
  974         __out           uint32_t *bandwidth_mbpsp)
  975 {
  976         uint32_t lane_bandwidth;
  977         uint32_t total_bandwidth;
  978         efx_rc_t rc;
  979 
  980         if ((pcie_link_width == 0) || (pcie_link_width > 16) ||
  981             !ISP2(pcie_link_width)) {
  982                 rc = EINVAL;
  983                 goto fail1;
  984         }
  985 
  986         switch (pcie_link_gen) {
  987         case EFX_PCIE_LINK_SPEED_GEN1:
  988                 /* 2.5 Gb/s raw bandwidth with 8b/10b encoding */
  989                 lane_bandwidth = 2000;
  990                 break;
  991         case EFX_PCIE_LINK_SPEED_GEN2:
  992                 /* 5.0 Gb/s raw bandwidth with 8b/10b encoding */
  993                 lane_bandwidth = 4000;
  994                 break;
  995         case EFX_PCIE_LINK_SPEED_GEN3:
  996                 /* 8.0 Gb/s raw bandwidth with 128b/130b encoding */
  997                 lane_bandwidth = 7877;
  998                 break;
  999         default:
 1000                 rc = EINVAL;
 1001                 goto fail2;
 1002         }
 1003 
 1004         total_bandwidth = lane_bandwidth * pcie_link_width;
 1005         *bandwidth_mbpsp = total_bandwidth;
 1006 
 1007         return (0);
 1008 
 1009 fail2:
 1010         EFSYS_PROBE(fail2);
 1011 fail1:
 1012         EFSYS_PROBE1(fail1, efx_rc_t, rc);
 1013 
 1014         return (rc);
 1015 }
 1016 
 1017 #if EFSYS_OPT_FW_SUBVARIANT_AWARE
 1018 
 1019         __checkReturn   efx_rc_t
 1020 efx_nic_get_fw_subvariant(
 1021         __in            efx_nic_t *enp,
 1022         __out           efx_nic_fw_subvariant_t *subvariantp)
 1023 {
 1024         efx_rc_t rc;
 1025         uint32_t value;
 1026 
 1027         rc = efx_mcdi_get_nic_global(enp,
 1028             MC_CMD_SET_NIC_GLOBAL_IN_FIRMWARE_SUBVARIANT, &value);
 1029         if (rc != 0)
 1030                 goto fail1;
 1031 
 1032         /* Mapping is not required since values match MCDI */
 1033         EFX_STATIC_ASSERT(EFX_NIC_FW_SUBVARIANT_DEFAULT ==
 1034             MC_CMD_SET_NIC_GLOBAL_IN_FW_SUBVARIANT_DEFAULT);
 1035         EFX_STATIC_ASSERT(EFX_NIC_FW_SUBVARIANT_NO_TX_CSUM ==
 1036             MC_CMD_SET_NIC_GLOBAL_IN_FW_SUBVARIANT_NO_TX_CSUM);
 1037 
 1038         switch (value) {
 1039         case MC_CMD_SET_NIC_GLOBAL_IN_FW_SUBVARIANT_DEFAULT:
 1040         case MC_CMD_SET_NIC_GLOBAL_IN_FW_SUBVARIANT_NO_TX_CSUM:
 1041                 *subvariantp = value;
 1042                 break;
 1043         default:
 1044                 rc = EINVAL;
 1045                 goto fail2;
 1046         }
 1047 
 1048         return (0);
 1049 
 1050 fail2:
 1051         EFSYS_PROBE(fail2);
 1052 
 1053 fail1:
 1054         EFSYS_PROBE1(fail1, efx_rc_t, rc);
 1055 
 1056         return (rc);
 1057 }
 1058 
 1059         __checkReturn   efx_rc_t
 1060 efx_nic_set_fw_subvariant(
 1061         __in            efx_nic_t *enp,
 1062         __in            efx_nic_fw_subvariant_t subvariant)
 1063 {
 1064         efx_rc_t rc;
 1065 
 1066         switch (subvariant) {
 1067         case EFX_NIC_FW_SUBVARIANT_DEFAULT:
 1068         case EFX_NIC_FW_SUBVARIANT_NO_TX_CSUM:
 1069                 /* Mapping is not required since values match MCDI */
 1070                 break;
 1071         default:
 1072                 rc = EINVAL;
 1073                 goto fail1;
 1074         }
 1075 
 1076         rc = efx_mcdi_set_nic_global(enp,
 1077             MC_CMD_SET_NIC_GLOBAL_IN_FIRMWARE_SUBVARIANT, subvariant);
 1078         if (rc != 0)
 1079                 goto fail2;
 1080 
 1081         return (0);
 1082 
 1083 fail2:
 1084         EFSYS_PROBE(fail2);
 1085 
 1086 fail1:
 1087         EFSYS_PROBE1(fail1, efx_rc_t, rc);
 1088 
 1089         return (rc);
 1090 }
 1091 
 1092 #endif  /* EFSYS_OPT_FW_SUBVARIANT_AWARE */
 1093 
 1094         __checkReturn   efx_rc_t
 1095 efx_nic_check_pcie_link_speed(
 1096         __in            efx_nic_t *enp,
 1097         __in            uint32_t pcie_link_width,
 1098         __in            uint32_t pcie_link_gen,
 1099         __out           efx_pcie_link_performance_t *resultp)
 1100 {
 1101         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
 1102         uint32_t bandwidth;
 1103         efx_pcie_link_performance_t result;
 1104         efx_rc_t rc;
 1105 
 1106         if ((encp->enc_required_pcie_bandwidth_mbps == 0) ||
 1107             (pcie_link_width == 0) || (pcie_link_width == 32) ||
 1108             (pcie_link_gen == 0)) {
 1109                 /*
 1110                  * No usable info on what is required and/or in use. In virtual
 1111                  * machines, sometimes the PCIe link width is reported as 0 or
 1112                  * 32, or the speed as 0.
 1113                  */
 1114                 result = EFX_PCIE_LINK_PERFORMANCE_UNKNOWN_BANDWIDTH;
 1115                 goto out;
 1116         }
 1117 
 1118         /* Calculate the available bandwidth in megabits per second */
 1119         rc = efx_nic_calculate_pcie_link_bandwidth(pcie_link_width,
 1120                                             pcie_link_gen, &bandwidth);
 1121         if (rc != 0)
 1122                 goto fail1;
 1123 
 1124         if (bandwidth < encp->enc_required_pcie_bandwidth_mbps) {
 1125                 result = EFX_PCIE_LINK_PERFORMANCE_SUBOPTIMAL_BANDWIDTH;
 1126         } else if (pcie_link_gen < encp->enc_max_pcie_link_gen) {
 1127                 /* The link provides enough bandwidth but not optimal latency */
 1128                 result = EFX_PCIE_LINK_PERFORMANCE_SUBOPTIMAL_LATENCY;
 1129         } else {
 1130                 result = EFX_PCIE_LINK_PERFORMANCE_OPTIMAL;
 1131         }
 1132 
 1133 out:
 1134         *resultp = result;
 1135 
 1136         return (0);
 1137 
 1138 fail1:
 1139         EFSYS_PROBE1(fail1, efx_rc_t, rc);
 1140 
 1141         return (rc);
 1142 }

Cache object: 1b89acfba1ee7bdb35c5765e36d4fdef


[ 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.