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_rx.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  __checkReturn   efx_rc_t
   40 efx_mcdi_init_rxq(
   41         __in            efx_nic_t *enp,
   42         __in            uint32_t ndescs,
   43         __in            uint32_t target_evq,
   44         __in            uint32_t label,
   45         __in            uint32_t instance,
   46         __in            efsys_mem_t *esmp,
   47         __in            boolean_t disable_scatter,
   48         __in            boolean_t want_inner_classes,
   49         __in            uint32_t ps_bufsize,
   50         __in            uint32_t es_bufs_per_desc,
   51         __in            uint32_t es_max_dma_len,
   52         __in            uint32_t es_buf_stride,
   53         __in            uint32_t hol_block_timeout)
   54 {
   55         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
   56         efx_mcdi_req_t req;
   57         EFX_MCDI_DECLARE_BUF(payload, MC_CMD_INIT_RXQ_V3_IN_LEN,
   58                 MC_CMD_INIT_RXQ_V3_OUT_LEN);
   59         int npages = EFX_RXQ_NBUFS(ndescs);
   60         int i;
   61         efx_qword_t *dma_addr;
   62         uint64_t addr;
   63         efx_rc_t rc;
   64         uint32_t dma_mode;
   65         boolean_t want_outer_classes;
   66 
   67         EFSYS_ASSERT3U(ndescs, <=, EFX_RXQ_MAXNDESCS);
   68 
   69         if ((esmp == NULL) || (EFSYS_MEM_SIZE(esmp) < EFX_RXQ_SIZE(ndescs))) {
   70                 rc = EINVAL;
   71                 goto fail1;
   72         }
   73 
   74         if (ps_bufsize > 0)
   75                 dma_mode = MC_CMD_INIT_RXQ_EXT_IN_PACKED_STREAM;
   76         else if (es_bufs_per_desc > 0)
   77                 dma_mode = MC_CMD_INIT_RXQ_V3_IN_EQUAL_STRIDE_SUPER_BUFFER;
   78         else
   79                 dma_mode = MC_CMD_INIT_RXQ_EXT_IN_SINGLE_PACKET;
   80 
   81         if (encp->enc_tunnel_encapsulations_supported != 0 &&
   82             !want_inner_classes) {
   83                 /*
   84                  * WANT_OUTER_CLASSES can only be specified on hardware which
   85                  * supports tunnel encapsulation offloads, even though it is
   86                  * effectively the behaviour the hardware gives.
   87                  *
   88                  * Also, on hardware which does support such offloads, older
   89                  * firmware rejects the flag if the offloads are not supported
   90                  * by the current firmware variant, which means this may fail if
   91                  * the capabilities are not updated when the firmware variant
   92                  * changes. This is not an issue on newer firmware, as it was
   93                  * changed in bug 69842 (v6.4.2.1007) to permit this flag to be
   94                  * specified on all firmware variants.
   95                  */
   96                 want_outer_classes = B_TRUE;
   97         } else {
   98                 want_outer_classes = B_FALSE;
   99         }
  100 
  101         req.emr_cmd = MC_CMD_INIT_RXQ;
  102         req.emr_in_buf = payload;
  103         req.emr_in_length = MC_CMD_INIT_RXQ_V3_IN_LEN;
  104         req.emr_out_buf = payload;
  105         req.emr_out_length = MC_CMD_INIT_RXQ_V3_OUT_LEN;
  106 
  107         MCDI_IN_SET_DWORD(req, INIT_RXQ_EXT_IN_SIZE, ndescs);
  108         MCDI_IN_SET_DWORD(req, INIT_RXQ_EXT_IN_TARGET_EVQ, target_evq);
  109         MCDI_IN_SET_DWORD(req, INIT_RXQ_EXT_IN_LABEL, label);
  110         MCDI_IN_SET_DWORD(req, INIT_RXQ_EXT_IN_INSTANCE, instance);
  111         MCDI_IN_POPULATE_DWORD_9(req, INIT_RXQ_EXT_IN_FLAGS,
  112             INIT_RXQ_EXT_IN_FLAG_BUFF_MODE, 0,
  113             INIT_RXQ_EXT_IN_FLAG_HDR_SPLIT, 0,
  114             INIT_RXQ_EXT_IN_FLAG_TIMESTAMP, 0,
  115             INIT_RXQ_EXT_IN_CRC_MODE, 0,
  116             INIT_RXQ_EXT_IN_FLAG_PREFIX, 1,
  117             INIT_RXQ_EXT_IN_FLAG_DISABLE_SCATTER, disable_scatter,
  118             INIT_RXQ_EXT_IN_DMA_MODE,
  119             dma_mode,
  120             INIT_RXQ_EXT_IN_PACKED_STREAM_BUFF_SIZE, ps_bufsize,
  121             INIT_RXQ_EXT_IN_FLAG_WANT_OUTER_CLASSES, want_outer_classes);
  122         MCDI_IN_SET_DWORD(req, INIT_RXQ_EXT_IN_OWNER_ID, 0);
  123         MCDI_IN_SET_DWORD(req, INIT_RXQ_EXT_IN_PORT_ID, EVB_PORT_ID_ASSIGNED);
  124 
  125         if (es_bufs_per_desc > 0) {
  126                 MCDI_IN_SET_DWORD(req,
  127                     INIT_RXQ_V3_IN_ES_PACKET_BUFFERS_PER_BUCKET,
  128                     es_bufs_per_desc);
  129                 MCDI_IN_SET_DWORD(req,
  130                     INIT_RXQ_V3_IN_ES_MAX_DMA_LEN, es_max_dma_len);
  131                 MCDI_IN_SET_DWORD(req,
  132                     INIT_RXQ_V3_IN_ES_PACKET_STRIDE, es_buf_stride);
  133                 MCDI_IN_SET_DWORD(req,
  134                     INIT_RXQ_V3_IN_ES_HEAD_OF_LINE_BLOCK_TIMEOUT,
  135                     hol_block_timeout);
  136         }
  137 
  138         dma_addr = MCDI_IN2(req, efx_qword_t, INIT_RXQ_IN_DMA_ADDR);
  139         addr = EFSYS_MEM_ADDR(esmp);
  140 
  141         for (i = 0; i < npages; i++) {
  142                 EFX_POPULATE_QWORD_2(*dma_addr,
  143                     EFX_DWORD_1, (uint32_t)(addr >> 32),
  144                     EFX_DWORD_0, (uint32_t)(addr & 0xffffffff));
  145 
  146                 dma_addr++;
  147                 addr += EFX_BUF_SIZE;
  148         }
  149 
  150         efx_mcdi_execute(enp, &req);
  151 
  152         if (req.emr_rc != 0) {
  153                 rc = req.emr_rc;
  154                 goto fail2;
  155         }
  156 
  157         return (0);
  158 
  159 fail2:
  160         EFSYS_PROBE(fail2);
  161 fail1:
  162         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  163 
  164         return (rc);
  165 }
  166 
  167 static  __checkReturn   efx_rc_t
  168 efx_mcdi_fini_rxq(
  169         __in            efx_nic_t *enp,
  170         __in            uint32_t instance)
  171 {
  172         efx_mcdi_req_t req;
  173         EFX_MCDI_DECLARE_BUF(payload, MC_CMD_FINI_RXQ_IN_LEN,
  174                 MC_CMD_FINI_RXQ_OUT_LEN);
  175         efx_rc_t rc;
  176 
  177         req.emr_cmd = MC_CMD_FINI_RXQ;
  178         req.emr_in_buf = payload;
  179         req.emr_in_length = MC_CMD_FINI_RXQ_IN_LEN;
  180         req.emr_out_buf = payload;
  181         req.emr_out_length = MC_CMD_FINI_RXQ_OUT_LEN;
  182 
  183         MCDI_IN_SET_DWORD(req, FINI_RXQ_IN_INSTANCE, instance);
  184 
  185         efx_mcdi_execute_quiet(enp, &req);
  186 
  187         if (req.emr_rc != 0) {
  188                 rc = req.emr_rc;
  189                 goto fail1;
  190         }
  191 
  192         return (0);
  193 
  194 fail1:
  195         /*
  196          * EALREADY is not an error, but indicates that the MC has rebooted and
  197          * that the RXQ has already been destroyed.
  198          */
  199         if (rc != EALREADY)
  200                 EFSYS_PROBE1(fail1, efx_rc_t, rc);
  201 
  202         return (rc);
  203 }
  204 
  205 #if EFSYS_OPT_RX_SCALE
  206 static  __checkReturn   efx_rc_t
  207 efx_mcdi_rss_context_alloc(
  208         __in            efx_nic_t *enp,
  209         __in            efx_rx_scale_context_type_t type,
  210         __in            uint32_t num_queues,
  211         __out           uint32_t *rss_contextp)
  212 {
  213         efx_mcdi_req_t req;
  214         EFX_MCDI_DECLARE_BUF(payload, MC_CMD_RSS_CONTEXT_ALLOC_IN_LEN,
  215                 MC_CMD_RSS_CONTEXT_ALLOC_OUT_LEN);
  216         uint32_t rss_context;
  217         uint32_t context_type;
  218         efx_rc_t rc;
  219 
  220         if (num_queues > EFX_MAXRSS) {
  221                 rc = EINVAL;
  222                 goto fail1;
  223         }
  224 
  225         switch (type) {
  226         case EFX_RX_SCALE_EXCLUSIVE:
  227                 context_type = MC_CMD_RSS_CONTEXT_ALLOC_IN_TYPE_EXCLUSIVE;
  228                 break;
  229         case EFX_RX_SCALE_SHARED:
  230                 context_type = MC_CMD_RSS_CONTEXT_ALLOC_IN_TYPE_SHARED;
  231                 break;
  232         default:
  233                 rc = EINVAL;
  234                 goto fail2;
  235         }
  236 
  237         req.emr_cmd = MC_CMD_RSS_CONTEXT_ALLOC;
  238         req.emr_in_buf = payload;
  239         req.emr_in_length = MC_CMD_RSS_CONTEXT_ALLOC_IN_LEN;
  240         req.emr_out_buf = payload;
  241         req.emr_out_length = MC_CMD_RSS_CONTEXT_ALLOC_OUT_LEN;
  242 
  243         MCDI_IN_SET_DWORD(req, RSS_CONTEXT_ALLOC_IN_UPSTREAM_PORT_ID,
  244             EVB_PORT_ID_ASSIGNED);
  245         MCDI_IN_SET_DWORD(req, RSS_CONTEXT_ALLOC_IN_TYPE, context_type);
  246 
  247         /*
  248          * For exclusive contexts, NUM_QUEUES is only used to validate
  249          * indirection table offsets.
  250          * For shared contexts, the provided context will spread traffic over
  251          * NUM_QUEUES many queues.
  252          */
  253         MCDI_IN_SET_DWORD(req, RSS_CONTEXT_ALLOC_IN_NUM_QUEUES, num_queues);
  254 
  255         efx_mcdi_execute(enp, &req);
  256 
  257         if (req.emr_rc != 0) {
  258                 rc = req.emr_rc;
  259                 goto fail3;
  260         }
  261 
  262         if (req.emr_out_length_used < MC_CMD_RSS_CONTEXT_ALLOC_OUT_LEN) {
  263                 rc = EMSGSIZE;
  264                 goto fail4;
  265         }
  266 
  267         rss_context = MCDI_OUT_DWORD(req, RSS_CONTEXT_ALLOC_OUT_RSS_CONTEXT_ID);
  268         if (rss_context == EF10_RSS_CONTEXT_INVALID) {
  269                 rc = ENOENT;
  270                 goto fail5;
  271         }
  272 
  273         *rss_contextp = rss_context;
  274 
  275         return (0);
  276 
  277 fail5:
  278         EFSYS_PROBE(fail5);
  279 fail4:
  280         EFSYS_PROBE(fail4);
  281 fail3:
  282         EFSYS_PROBE(fail3);
  283 fail2:
  284         EFSYS_PROBE(fail2);
  285 fail1:
  286         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  287 
  288         return (rc);
  289 }
  290 #endif /* EFSYS_OPT_RX_SCALE */
  291 
  292 #if EFSYS_OPT_RX_SCALE
  293 static                  efx_rc_t
  294 efx_mcdi_rss_context_free(
  295         __in            efx_nic_t *enp,
  296         __in            uint32_t rss_context)
  297 {
  298         efx_mcdi_req_t req;
  299         EFX_MCDI_DECLARE_BUF(payload, MC_CMD_RSS_CONTEXT_FREE_IN_LEN,
  300                 MC_CMD_RSS_CONTEXT_FREE_OUT_LEN);
  301         efx_rc_t rc;
  302 
  303         if (rss_context == EF10_RSS_CONTEXT_INVALID) {
  304                 rc = EINVAL;
  305                 goto fail1;
  306         }
  307 
  308         req.emr_cmd = MC_CMD_RSS_CONTEXT_FREE;
  309         req.emr_in_buf = payload;
  310         req.emr_in_length = MC_CMD_RSS_CONTEXT_FREE_IN_LEN;
  311         req.emr_out_buf = payload;
  312         req.emr_out_length = MC_CMD_RSS_CONTEXT_FREE_OUT_LEN;
  313 
  314         MCDI_IN_SET_DWORD(req, RSS_CONTEXT_FREE_IN_RSS_CONTEXT_ID, rss_context);
  315 
  316         efx_mcdi_execute_quiet(enp, &req);
  317 
  318         if (req.emr_rc != 0) {
  319                 rc = req.emr_rc;
  320                 goto fail2;
  321         }
  322 
  323         return (0);
  324 
  325 fail2:
  326         EFSYS_PROBE(fail2);
  327 fail1:
  328         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  329 
  330         return (rc);
  331 }
  332 #endif /* EFSYS_OPT_RX_SCALE */
  333 
  334 #if EFSYS_OPT_RX_SCALE
  335 static                  efx_rc_t
  336 efx_mcdi_rss_context_set_flags(
  337         __in            efx_nic_t *enp,
  338         __in            uint32_t rss_context,
  339         __in            efx_rx_hash_type_t type)
  340 {
  341         efx_nic_cfg_t *encp = &enp->en_nic_cfg;
  342         efx_mcdi_req_t req;
  343         EFX_MCDI_DECLARE_BUF(payload, MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_LEN,
  344                 MC_CMD_RSS_CONTEXT_SET_FLAGS_OUT_LEN);
  345         efx_rc_t rc;
  346 
  347         EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV4_TCP_LBN ==
  348                     MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_TCP_IPV4_RSS_MODE_LBN);
  349         EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV4_TCP_WIDTH ==
  350                     MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_TCP_IPV4_RSS_MODE_WIDTH);
  351         EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV4_LBN ==
  352                     MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_OTHER_IPV4_RSS_MODE_LBN);
  353         EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV4_WIDTH ==
  354                     MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_OTHER_IPV4_RSS_MODE_WIDTH);
  355         EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV6_TCP_LBN ==
  356                     MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_TCP_IPV6_RSS_MODE_LBN);
  357         EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV6_TCP_WIDTH ==
  358                     MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_TCP_IPV6_RSS_MODE_WIDTH);
  359         EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV6_LBN ==
  360                     MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_OTHER_IPV6_RSS_MODE_LBN);
  361         EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV6_WIDTH ==
  362                     MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_OTHER_IPV6_RSS_MODE_WIDTH);
  363 
  364         if (rss_context == EF10_RSS_CONTEXT_INVALID) {
  365                 rc = EINVAL;
  366                 goto fail1;
  367         }
  368 
  369         req.emr_cmd = MC_CMD_RSS_CONTEXT_SET_FLAGS;
  370         req.emr_in_buf = payload;
  371         req.emr_in_length = MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_LEN;
  372         req.emr_out_buf = payload;
  373         req.emr_out_length = MC_CMD_RSS_CONTEXT_SET_FLAGS_OUT_LEN;
  374 
  375         MCDI_IN_SET_DWORD(req, RSS_CONTEXT_SET_FLAGS_IN_RSS_CONTEXT_ID,
  376             rss_context);
  377 
  378         /*
  379          * If the firmware lacks support for additional modes, RSS_MODE
  380          * fields must contain zeros, otherwise the operation will fail.
  381          */
  382         if (encp->enc_rx_scale_additional_modes_supported == B_FALSE)
  383                 type &= EFX_RX_HASH_LEGACY_MASK;
  384 
  385         MCDI_IN_POPULATE_DWORD_10(req, RSS_CONTEXT_SET_FLAGS_IN_FLAGS,
  386             RSS_CONTEXT_SET_FLAGS_IN_TOEPLITZ_IPV4_EN,
  387             (type & EFX_RX_HASH_IPV4) ? 1 : 0,
  388             RSS_CONTEXT_SET_FLAGS_IN_TOEPLITZ_TCPV4_EN,
  389             (type & EFX_RX_HASH_TCPIPV4) ? 1 : 0,
  390             RSS_CONTEXT_SET_FLAGS_IN_TOEPLITZ_IPV6_EN,
  391             (type & EFX_RX_HASH_IPV6) ? 1 : 0,
  392             RSS_CONTEXT_SET_FLAGS_IN_TOEPLITZ_TCPV6_EN,
  393             (type & EFX_RX_HASH_TCPIPV6) ? 1 : 0,
  394             RSS_CONTEXT_SET_FLAGS_IN_TCP_IPV4_RSS_MODE,
  395             (type >> EFX_RX_CLASS_IPV4_TCP_LBN) &
  396             EFX_MASK32(EFX_RX_CLASS_IPV4_TCP),
  397             RSS_CONTEXT_SET_FLAGS_IN_UDP_IPV4_RSS_MODE,
  398             (type >> EFX_RX_CLASS_IPV4_UDP_LBN) &
  399             EFX_MASK32(EFX_RX_CLASS_IPV4_UDP),
  400             RSS_CONTEXT_SET_FLAGS_IN_OTHER_IPV4_RSS_MODE,
  401             (type >> EFX_RX_CLASS_IPV4_LBN) & EFX_MASK32(EFX_RX_CLASS_IPV4),
  402             RSS_CONTEXT_SET_FLAGS_IN_TCP_IPV6_RSS_MODE,
  403             (type >> EFX_RX_CLASS_IPV6_TCP_LBN) &
  404             EFX_MASK32(EFX_RX_CLASS_IPV6_TCP),
  405             RSS_CONTEXT_SET_FLAGS_IN_UDP_IPV6_RSS_MODE,
  406             (type >> EFX_RX_CLASS_IPV6_UDP_LBN) &
  407             EFX_MASK32(EFX_RX_CLASS_IPV6_UDP),
  408             RSS_CONTEXT_SET_FLAGS_IN_OTHER_IPV6_RSS_MODE,
  409             (type >> EFX_RX_CLASS_IPV6_LBN) & EFX_MASK32(EFX_RX_CLASS_IPV6));
  410 
  411         efx_mcdi_execute(enp, &req);
  412 
  413         if (req.emr_rc != 0) {
  414                 rc = req.emr_rc;
  415                 goto fail2;
  416         }
  417 
  418         return (0);
  419 
  420 fail2:
  421         EFSYS_PROBE(fail2);
  422 fail1:
  423         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  424 
  425         return (rc);
  426 }
  427 #endif /* EFSYS_OPT_RX_SCALE */
  428 
  429 #if EFSYS_OPT_RX_SCALE
  430 static                  efx_rc_t
  431 efx_mcdi_rss_context_set_key(
  432         __in            efx_nic_t *enp,
  433         __in            uint32_t rss_context,
  434         __in_ecount(n)  uint8_t *key,
  435         __in            size_t n)
  436 {
  437         efx_mcdi_req_t req;
  438         EFX_MCDI_DECLARE_BUF(payload, MC_CMD_RSS_CONTEXT_SET_KEY_IN_LEN,
  439                 MC_CMD_RSS_CONTEXT_SET_KEY_OUT_LEN);
  440         efx_rc_t rc;
  441 
  442         if (rss_context == EF10_RSS_CONTEXT_INVALID) {
  443                 rc = EINVAL;
  444                 goto fail1;
  445         }
  446 
  447         req.emr_cmd = MC_CMD_RSS_CONTEXT_SET_KEY;
  448         req.emr_in_buf = payload;
  449         req.emr_in_length = MC_CMD_RSS_CONTEXT_SET_KEY_IN_LEN;
  450         req.emr_out_buf = payload;
  451         req.emr_out_length = MC_CMD_RSS_CONTEXT_SET_KEY_OUT_LEN;
  452 
  453         MCDI_IN_SET_DWORD(req, RSS_CONTEXT_SET_KEY_IN_RSS_CONTEXT_ID,
  454             rss_context);
  455 
  456         EFSYS_ASSERT3U(n, ==, MC_CMD_RSS_CONTEXT_SET_KEY_IN_TOEPLITZ_KEY_LEN);
  457         if (n != MC_CMD_RSS_CONTEXT_SET_KEY_IN_TOEPLITZ_KEY_LEN) {
  458                 rc = EINVAL;
  459                 goto fail2;
  460         }
  461 
  462         memcpy(MCDI_IN2(req, uint8_t, RSS_CONTEXT_SET_KEY_IN_TOEPLITZ_KEY),
  463             key, n);
  464 
  465         efx_mcdi_execute(enp, &req);
  466 
  467         if (req.emr_rc != 0) {
  468                 rc = req.emr_rc;
  469                 goto fail3;
  470         }
  471 
  472         return (0);
  473 
  474 fail3:
  475         EFSYS_PROBE(fail3);
  476 fail2:
  477         EFSYS_PROBE(fail2);
  478 fail1:
  479         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  480 
  481         return (rc);
  482 }
  483 #endif /* EFSYS_OPT_RX_SCALE */
  484 
  485 #if EFSYS_OPT_RX_SCALE
  486 static                  efx_rc_t
  487 efx_mcdi_rss_context_set_table(
  488         __in            efx_nic_t *enp,
  489         __in            uint32_t rss_context,
  490         __in_ecount(n)  unsigned int *table,
  491         __in            size_t n)
  492 {
  493         efx_mcdi_req_t req;
  494         EFX_MCDI_DECLARE_BUF(payload, MC_CMD_RSS_CONTEXT_SET_TABLE_IN_LEN,
  495                 MC_CMD_RSS_CONTEXT_SET_TABLE_OUT_LEN);
  496         uint8_t *req_table;
  497         int i, rc;
  498 
  499         if (rss_context == EF10_RSS_CONTEXT_INVALID) {
  500                 rc = EINVAL;
  501                 goto fail1;
  502         }
  503 
  504         req.emr_cmd = MC_CMD_RSS_CONTEXT_SET_TABLE;
  505         req.emr_in_buf = payload;
  506         req.emr_in_length = MC_CMD_RSS_CONTEXT_SET_TABLE_IN_LEN;
  507         req.emr_out_buf = payload;
  508         req.emr_out_length = MC_CMD_RSS_CONTEXT_SET_TABLE_OUT_LEN;
  509 
  510         MCDI_IN_SET_DWORD(req, RSS_CONTEXT_SET_TABLE_IN_RSS_CONTEXT_ID,
  511             rss_context);
  512 
  513         req_table =
  514             MCDI_IN2(req, uint8_t, RSS_CONTEXT_SET_TABLE_IN_INDIRECTION_TABLE);
  515 
  516         for (i = 0;
  517             i < MC_CMD_RSS_CONTEXT_SET_TABLE_IN_INDIRECTION_TABLE_LEN;
  518             i++) {
  519                 req_table[i] = (n > 0) ? (uint8_t)table[i % n] : 0;
  520         }
  521 
  522         efx_mcdi_execute(enp, &req);
  523 
  524         if (req.emr_rc != 0) {
  525                 rc = req.emr_rc;
  526                 goto fail2;
  527         }
  528 
  529         return (0);
  530 
  531 fail2:
  532         EFSYS_PROBE(fail2);
  533 fail1:
  534         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  535 
  536         return (rc);
  537 }
  538 #endif /* EFSYS_OPT_RX_SCALE */
  539 
  540         __checkReturn   efx_rc_t
  541 ef10_rx_init(
  542         __in            efx_nic_t *enp)
  543 {
  544 #if EFSYS_OPT_RX_SCALE
  545 
  546         if (efx_mcdi_rss_context_alloc(enp, EFX_RX_SCALE_EXCLUSIVE, EFX_MAXRSS,
  547                 &enp->en_rss_context) == 0) {
  548                 /*
  549                  * Allocated an exclusive RSS context, which allows both the
  550                  * indirection table and key to be modified.
  551                  */
  552                 enp->en_rss_context_type = EFX_RX_SCALE_EXCLUSIVE;
  553                 enp->en_hash_support = EFX_RX_HASH_AVAILABLE;
  554         } else {
  555                 /*
  556                  * Failed to allocate an exclusive RSS context. Continue
  557                  * operation without support for RSS. The pseudo-header in
  558                  * received packets will not contain a Toeplitz hash value.
  559                  */
  560                 enp->en_rss_context_type = EFX_RX_SCALE_UNAVAILABLE;
  561                 enp->en_hash_support = EFX_RX_HASH_UNAVAILABLE;
  562         }
  563 
  564 #endif /* EFSYS_OPT_RX_SCALE */
  565 
  566         return (0);
  567 }
  568 
  569 #if EFSYS_OPT_RX_SCATTER
  570         __checkReturn   efx_rc_t
  571 ef10_rx_scatter_enable(
  572         __in            efx_nic_t *enp,
  573         __in            unsigned int buf_size)
  574 {
  575         _NOTE(ARGUNUSED(enp, buf_size))
  576         return (0);
  577 }
  578 #endif  /* EFSYS_OPT_RX_SCATTER */
  579 
  580 #if EFSYS_OPT_RX_SCALE
  581         __checkReturn   efx_rc_t
  582 ef10_rx_scale_context_alloc(
  583         __in            efx_nic_t *enp,
  584         __in            efx_rx_scale_context_type_t type,
  585         __in            uint32_t num_queues,
  586         __out           uint32_t *rss_contextp)
  587 {
  588         efx_rc_t rc;
  589 
  590         rc = efx_mcdi_rss_context_alloc(enp, type, num_queues, rss_contextp);
  591         if (rc != 0)
  592                 goto fail1;
  593 
  594         return (0);
  595 
  596 fail1:
  597         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  598         return (rc);
  599 }
  600 #endif /* EFSYS_OPT_RX_SCALE */
  601 
  602 #if EFSYS_OPT_RX_SCALE
  603         __checkReturn   efx_rc_t
  604 ef10_rx_scale_context_free(
  605         __in            efx_nic_t *enp,
  606         __in            uint32_t rss_context)
  607 {
  608         efx_rc_t rc;
  609 
  610         rc = efx_mcdi_rss_context_free(enp, rss_context);
  611         if (rc != 0)
  612                 goto fail1;
  613 
  614         return (0);
  615 
  616 fail1:
  617         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  618         return (rc);
  619 }
  620 #endif /* EFSYS_OPT_RX_SCALE */
  621 
  622 #if EFSYS_OPT_RX_SCALE
  623         __checkReturn   efx_rc_t
  624 ef10_rx_scale_mode_set(
  625         __in            efx_nic_t *enp,
  626         __in            uint32_t rss_context,
  627         __in            efx_rx_hash_alg_t alg,
  628         __in            efx_rx_hash_type_t type,
  629         __in            boolean_t insert)
  630 {
  631         efx_nic_cfg_t *encp = &enp->en_nic_cfg;
  632         efx_rc_t rc;
  633 
  634         EFSYS_ASSERT3U(insert, ==, B_TRUE);
  635 
  636         if ((encp->enc_rx_scale_hash_alg_mask & (1U << alg)) == 0 ||
  637             insert == B_FALSE) {
  638                 rc = EINVAL;
  639                 goto fail1;
  640         }
  641 
  642         if (rss_context == EFX_RSS_CONTEXT_DEFAULT) {
  643                 if (enp->en_rss_context_type == EFX_RX_SCALE_UNAVAILABLE) {
  644                         rc = ENOTSUP;
  645                         goto fail2;
  646                 }
  647                 rss_context = enp->en_rss_context;
  648         }
  649 
  650         if ((rc = efx_mcdi_rss_context_set_flags(enp,
  651                     rss_context, type)) != 0)
  652                 goto fail3;
  653 
  654         return (0);
  655 
  656 fail3:
  657         EFSYS_PROBE(fail3);
  658 fail2:
  659         EFSYS_PROBE(fail2);
  660 fail1:
  661         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  662 
  663         return (rc);
  664 }
  665 #endif /* EFSYS_OPT_RX_SCALE */
  666 
  667 #if EFSYS_OPT_RX_SCALE
  668         __checkReturn   efx_rc_t
  669 ef10_rx_scale_key_set(
  670         __in            efx_nic_t *enp,
  671         __in            uint32_t rss_context,
  672         __in_ecount(n)  uint8_t *key,
  673         __in            size_t n)
  674 {
  675         efx_rc_t rc;
  676 
  677         EFX_STATIC_ASSERT(EFX_RSS_KEY_SIZE ==
  678             MC_CMD_RSS_CONTEXT_SET_KEY_IN_TOEPLITZ_KEY_LEN);
  679 
  680         if (rss_context == EFX_RSS_CONTEXT_DEFAULT) {
  681                 if (enp->en_rss_context_type == EFX_RX_SCALE_UNAVAILABLE) {
  682                         rc = ENOTSUP;
  683                         goto fail1;
  684                 }
  685                 rss_context = enp->en_rss_context;
  686         }
  687 
  688         if ((rc = efx_mcdi_rss_context_set_key(enp, rss_context, key, n)) != 0)
  689                 goto fail2;
  690 
  691         return (0);
  692 
  693 fail2:
  694         EFSYS_PROBE(fail2);
  695 fail1:
  696         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  697 
  698         return (rc);
  699 }
  700 #endif /* EFSYS_OPT_RX_SCALE */
  701 
  702 #if EFSYS_OPT_RX_SCALE
  703         __checkReturn   efx_rc_t
  704 ef10_rx_scale_tbl_set(
  705         __in            efx_nic_t *enp,
  706         __in            uint32_t rss_context,
  707         __in_ecount(n)  unsigned int *table,
  708         __in            size_t n)
  709 {
  710         efx_rc_t rc;
  711 
  712         if (rss_context == EFX_RSS_CONTEXT_DEFAULT) {
  713                 if (enp->en_rss_context_type == EFX_RX_SCALE_UNAVAILABLE) {
  714                         rc = ENOTSUP;
  715                         goto fail1;
  716                 }
  717                 rss_context = enp->en_rss_context;
  718         }
  719 
  720         if ((rc = efx_mcdi_rss_context_set_table(enp,
  721                     rss_context, table, n)) != 0)
  722                 goto fail2;
  723 
  724         return (0);
  725 
  726 fail2:
  727         EFSYS_PROBE(fail2);
  728 fail1:
  729         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  730 
  731         return (rc);
  732 }
  733 #endif /* EFSYS_OPT_RX_SCALE */
  734 
  735 /*
  736  * EF10 RX pseudo-header
  737  * ---------------------
  738  *
  739  * Receive packets are prefixed by an (optional) 14 byte pseudo-header:
  740  *
  741  *  +00: Toeplitz hash value.
  742  *       (32bit little-endian)
  743  *  +04: Outer VLAN tag. Zero if the packet did not have an outer VLAN tag.
  744  *       (16bit big-endian)
  745  *  +06: Inner VLAN tag. Zero if the packet did not have an inner VLAN tag.
  746  *       (16bit big-endian)
  747  *  +08: Packet Length. Zero if the RX datapath was in cut-through mode.
  748  *       (16bit little-endian)
  749  *  +10: MAC timestamp. Zero if timestamping is not enabled.
  750  *       (32bit little-endian)
  751  *
  752  * See "The RX Pseudo-header" in SF-109306-TC.
  753  */
  754 
  755         __checkReturn   efx_rc_t
  756 ef10_rx_prefix_pktlen(
  757         __in            efx_nic_t *enp,
  758         __in            uint8_t *buffer,
  759         __out           uint16_t *lengthp)
  760 {
  761         _NOTE(ARGUNUSED(enp))
  762 
  763         /*
  764          * The RX pseudo-header contains the packet length, excluding the
  765          * pseudo-header. If the hardware receive datapath was operating in
  766          * cut-through mode then the length in the RX pseudo-header will be
  767          * zero, and the packet length must be obtained from the DMA length
  768          * reported in the RX event.
  769          */
  770         *lengthp = buffer[8] | (buffer[9] << 8);
  771         return (0);
  772 }
  773 
  774 #if EFSYS_OPT_RX_SCALE
  775         __checkReturn   uint32_t
  776 ef10_rx_prefix_hash(
  777         __in            efx_nic_t *enp,
  778         __in            efx_rx_hash_alg_t func,
  779         __in            uint8_t *buffer)
  780 {
  781         _NOTE(ARGUNUSED(enp))
  782 
  783         switch (func) {
  784         case EFX_RX_HASHALG_PACKED_STREAM:
  785         case EFX_RX_HASHALG_TOEPLITZ:
  786                 return (buffer[0] |
  787                     (buffer[1] << 8) |
  788                     (buffer[2] << 16) |
  789                     (buffer[3] << 24));
  790 
  791         default:
  792                 EFSYS_ASSERT(0);
  793                 return (0);
  794         }
  795 }
  796 #endif /* EFSYS_OPT_RX_SCALE */
  797 
  798 #if EFSYS_OPT_RX_PACKED_STREAM
  799 /*
  800  * Fake length for RXQ descriptors in packed stream mode
  801  * to make hardware happy
  802  */
  803 #define EFX_RXQ_PACKED_STREAM_FAKE_BUF_SIZE 32
  804 #endif
  805 
  806                                 void
  807 ef10_rx_qpost(
  808         __in                    efx_rxq_t *erp,
  809         __in_ecount(ndescs)     efsys_dma_addr_t *addrp,
  810         __in                    size_t size,
  811         __in                    unsigned int ndescs,
  812         __in                    unsigned int completed,
  813         __in                    unsigned int added)
  814 {
  815         efx_qword_t qword;
  816         unsigned int i;
  817         unsigned int offset;
  818         unsigned int id;
  819 
  820         _NOTE(ARGUNUSED(completed))
  821 
  822 #if EFSYS_OPT_RX_PACKED_STREAM
  823         /*
  824          * Real size of the buffer does not fit into ESF_DZ_RX_KER_BYTE_CNT
  825          * and equal to 0 after applying mask. Hardware does not like it.
  826          */
  827         if (erp->er_ev_qstate->eers_rx_packed_stream)
  828                 size = EFX_RXQ_PACKED_STREAM_FAKE_BUF_SIZE;
  829 #endif
  830 
  831         /* The client driver must not overfill the queue */
  832         EFSYS_ASSERT3U(added - completed + ndescs, <=,
  833             EFX_RXQ_LIMIT(erp->er_mask + 1));
  834 
  835         id = added & (erp->er_mask);
  836         for (i = 0; i < ndescs; i++) {
  837                 EFSYS_PROBE4(rx_post, unsigned int, erp->er_index,
  838                     unsigned int, id, efsys_dma_addr_t, addrp[i],
  839                     size_t, size);
  840 
  841                 EFX_POPULATE_QWORD_3(qword,
  842                     ESF_DZ_RX_KER_BYTE_CNT, (uint32_t)(size),
  843                     ESF_DZ_RX_KER_BUF_ADDR_DW0,
  844                     (uint32_t)(addrp[i] & 0xffffffff),
  845                     ESF_DZ_RX_KER_BUF_ADDR_DW1,
  846                     (uint32_t)(addrp[i] >> 32));
  847 
  848                 offset = id * sizeof (efx_qword_t);
  849                 EFSYS_MEM_WRITEQ(erp->er_esmp, offset, &qword);
  850 
  851                 id = (id + 1) & (erp->er_mask);
  852         }
  853 }
  854 
  855                         void
  856 ef10_rx_qpush(
  857         __in    efx_rxq_t *erp,
  858         __in    unsigned int added,
  859         __inout unsigned int *pushedp)
  860 {
  861         efx_nic_t *enp = erp->er_enp;
  862         unsigned int pushed = *pushedp;
  863         uint32_t wptr;
  864         efx_dword_t dword;
  865 
  866         /* Hardware has alignment restriction for WPTR */
  867         wptr = EFX_P2ALIGN(unsigned int, added, EF10_RX_WPTR_ALIGN);
  868         if (pushed == wptr)
  869                 return;
  870 
  871         *pushedp = wptr;
  872 
  873         /* Push the populated descriptors out */
  874         wptr &= erp->er_mask;
  875 
  876         EFX_POPULATE_DWORD_1(dword, ERF_DZ_RX_DESC_WPTR, wptr);
  877 
  878         /* Guarantee ordering of memory (descriptors) and PIO (doorbell) */
  879         EFX_DMA_SYNC_QUEUE_FOR_DEVICE(erp->er_esmp, erp->er_mask + 1,
  880             wptr, pushed & erp->er_mask);
  881         EFSYS_PIO_WRITE_BARRIER();
  882         EFX_BAR_VI_WRITED(enp, ER_DZ_RX_DESC_UPD_REG,
  883             erp->er_index, &dword, B_FALSE);
  884 }
  885 
  886 #if EFSYS_OPT_RX_PACKED_STREAM
  887 
  888                         void
  889 ef10_rx_qpush_ps_credits(
  890         __in            efx_rxq_t *erp)
  891 {
  892         efx_nic_t *enp = erp->er_enp;
  893         efx_dword_t dword;
  894         efx_evq_rxq_state_t *rxq_state = erp->er_ev_qstate;
  895         uint32_t credits;
  896 
  897         EFSYS_ASSERT(rxq_state->eers_rx_packed_stream);
  898 
  899         if (rxq_state->eers_rx_packed_stream_credits == 0)
  900                 return;
  901 
  902         /*
  903          * It is a bug if we think that FW has utilized more
  904          * credits than it is allowed to have (maximum). However,
  905          * make sure that we do not credit more than maximum anyway.
  906          */
  907         credits = MIN(rxq_state->eers_rx_packed_stream_credits,
  908             EFX_RX_PACKED_STREAM_MAX_CREDITS);
  909         EFX_POPULATE_DWORD_3(dword,
  910             ERF_DZ_RX_DESC_MAGIC_DOORBELL, 1,
  911             ERF_DZ_RX_DESC_MAGIC_CMD,
  912             ERE_DZ_RX_DESC_MAGIC_CMD_PS_CREDITS,
  913             ERF_DZ_RX_DESC_MAGIC_DATA, credits);
  914         EFX_BAR_VI_WRITED(enp, ER_DZ_RX_DESC_UPD_REG,
  915             erp->er_index, &dword, B_FALSE);
  916 
  917         rxq_state->eers_rx_packed_stream_credits = 0;
  918 }
  919 
  920 /*
  921  * In accordance with SF-112241-TC the received data has the following layout:
  922  *  - 8 byte pseudo-header which consist of:
  923  *    - 4 byte little-endian timestamp
  924  *    - 2 byte little-endian captured length in bytes
  925  *    - 2 byte little-endian original packet length in bytes
  926  *  - captured packet bytes
  927  *  - optional padding to align to 64 bytes boundary
  928  *  - 64 bytes scratch space for the host software
  929  */
  930         __checkReturn   uint8_t *
  931 ef10_rx_qps_packet_info(
  932         __in            efx_rxq_t *erp,
  933         __in            uint8_t *buffer,
  934         __in            uint32_t buffer_length,
  935         __in            uint32_t current_offset,
  936         __out           uint16_t *lengthp,
  937         __out           uint32_t *next_offsetp,
  938         __out           uint32_t *timestamp)
  939 {
  940         uint16_t buf_len;
  941         uint8_t *pkt_start;
  942         efx_qword_t *qwordp;
  943         efx_evq_rxq_state_t *rxq_state = erp->er_ev_qstate;
  944 
  945         EFSYS_ASSERT(rxq_state->eers_rx_packed_stream);
  946 
  947         buffer += current_offset;
  948         pkt_start = buffer + EFX_RX_PACKED_STREAM_RX_PREFIX_SIZE;
  949 
  950         qwordp = (efx_qword_t *)buffer;
  951         *timestamp = EFX_QWORD_FIELD(*qwordp, ES_DZ_PS_RX_PREFIX_TSTAMP);
  952         *lengthp   = EFX_QWORD_FIELD(*qwordp, ES_DZ_PS_RX_PREFIX_ORIG_LEN);
  953         buf_len    = EFX_QWORD_FIELD(*qwordp, ES_DZ_PS_RX_PREFIX_CAP_LEN);
  954 
  955         buf_len = EFX_P2ROUNDUP(uint16_t,
  956             buf_len + EFX_RX_PACKED_STREAM_RX_PREFIX_SIZE,
  957             EFX_RX_PACKED_STREAM_ALIGNMENT);
  958         *next_offsetp =
  959             current_offset + buf_len + EFX_RX_PACKED_STREAM_ALIGNMENT;
  960 
  961         EFSYS_ASSERT3U(*next_offsetp, <=, buffer_length);
  962         EFSYS_ASSERT3U(current_offset + *lengthp, <, *next_offsetp);
  963 
  964         if ((*next_offsetp ^ current_offset) &
  965             EFX_RX_PACKED_STREAM_MEM_PER_CREDIT)
  966                 rxq_state->eers_rx_packed_stream_credits++;
  967 
  968         return (pkt_start);
  969 }
  970 
  971 #endif
  972 
  973         __checkReturn   efx_rc_t
  974 ef10_rx_qflush(
  975         __in    efx_rxq_t *erp)
  976 {
  977         efx_nic_t *enp = erp->er_enp;
  978         efx_rc_t rc;
  979 
  980         if ((rc = efx_mcdi_fini_rxq(enp, erp->er_index)) != 0)
  981                 goto fail1;
  982 
  983         return (0);
  984 
  985 fail1:
  986         /*
  987          * EALREADY is not an error, but indicates that the MC has rebooted and
  988          * that the RXQ has already been destroyed. Callers need to know that
  989          * the RXQ flush has completed to avoid waiting until timeout for a
  990          * flush done event that will not be delivered.
  991          */
  992         if (rc != EALREADY)
  993                 EFSYS_PROBE1(fail1, efx_rc_t, rc);
  994 
  995         return (rc);
  996 }
  997 
  998                 void
  999 ef10_rx_qenable(
 1000         __in    efx_rxq_t *erp)
 1001 {
 1002         /* FIXME */
 1003         _NOTE(ARGUNUSED(erp))
 1004         /* FIXME */
 1005 }
 1006 
 1007         __checkReturn   efx_rc_t
 1008 ef10_rx_qcreate(
 1009         __in            efx_nic_t *enp,
 1010         __in            unsigned int index,
 1011         __in            unsigned int label,
 1012         __in            efx_rxq_type_t type,
 1013         __in_opt        const efx_rxq_type_data_t *type_data,
 1014         __in            efsys_mem_t *esmp,
 1015         __in            size_t ndescs,
 1016         __in            uint32_t id,
 1017         __in            unsigned int flags,
 1018         __in            efx_evq_t *eep,
 1019         __in            efx_rxq_t *erp)
 1020 {
 1021         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
 1022         efx_rc_t rc;
 1023         boolean_t disable_scatter;
 1024         boolean_t want_inner_classes;
 1025         unsigned int ps_buf_size;
 1026         uint32_t es_bufs_per_desc = 0;
 1027         uint32_t es_max_dma_len = 0;
 1028         uint32_t es_buf_stride = 0;
 1029         uint32_t hol_block_timeout = 0;
 1030 
 1031         _NOTE(ARGUNUSED(id, erp, type_data))
 1032 
 1033         EFX_STATIC_ASSERT(EFX_EV_RX_NLABELS == (1 << ESF_DZ_RX_QLABEL_WIDTH));
 1034         EFSYS_ASSERT3U(label, <, EFX_EV_RX_NLABELS);
 1035         EFSYS_ASSERT3U(enp->en_rx_qcount + 1, <, encp->enc_rxq_limit);
 1036 
 1037         EFX_STATIC_ASSERT(ISP2(EFX_RXQ_MAXNDESCS));
 1038         EFX_STATIC_ASSERT(ISP2(EFX_RXQ_MINNDESCS));
 1039 
 1040         if (!ISP2(ndescs) ||
 1041             (ndescs < EFX_RXQ_MINNDESCS) || (ndescs > EFX_RXQ_MAXNDESCS)) {
 1042                 rc = EINVAL;
 1043                 goto fail1;
 1044         }
 1045         if (index >= encp->enc_rxq_limit) {
 1046                 rc = EINVAL;
 1047                 goto fail2;
 1048         }
 1049 
 1050         switch (type) {
 1051         case EFX_RXQ_TYPE_DEFAULT:
 1052                 ps_buf_size = 0;
 1053                 break;
 1054 #if EFSYS_OPT_RX_PACKED_STREAM
 1055         case EFX_RXQ_TYPE_PACKED_STREAM:
 1056                 if (type_data == NULL) {
 1057                         rc = EINVAL;
 1058                         goto fail3;
 1059                 }
 1060                 switch (type_data->ertd_packed_stream.eps_buf_size) {
 1061                 case EFX_RXQ_PACKED_STREAM_BUF_SIZE_1M:
 1062                         ps_buf_size = MC_CMD_INIT_RXQ_EXT_IN_PS_BUFF_1M;
 1063                         break;
 1064                 case EFX_RXQ_PACKED_STREAM_BUF_SIZE_512K:
 1065                         ps_buf_size = MC_CMD_INIT_RXQ_EXT_IN_PS_BUFF_512K;
 1066                         break;
 1067                 case EFX_RXQ_PACKED_STREAM_BUF_SIZE_256K:
 1068                         ps_buf_size = MC_CMD_INIT_RXQ_EXT_IN_PS_BUFF_256K;
 1069                         break;
 1070                 case EFX_RXQ_PACKED_STREAM_BUF_SIZE_128K:
 1071                         ps_buf_size = MC_CMD_INIT_RXQ_EXT_IN_PS_BUFF_128K;
 1072                         break;
 1073                 case EFX_RXQ_PACKED_STREAM_BUF_SIZE_64K:
 1074                         ps_buf_size = MC_CMD_INIT_RXQ_EXT_IN_PS_BUFF_64K;
 1075                         break;
 1076                 default:
 1077                         rc = ENOTSUP;
 1078                         goto fail4;
 1079                 }
 1080                 break;
 1081 #endif /* EFSYS_OPT_RX_PACKED_STREAM */
 1082 #if EFSYS_OPT_RX_ES_SUPER_BUFFER
 1083         case EFX_RXQ_TYPE_ES_SUPER_BUFFER:
 1084                 if (type_data == NULL) {
 1085                         rc = EINVAL;
 1086                         goto fail5;
 1087                 }
 1088                 ps_buf_size = 0;
 1089                 es_bufs_per_desc =
 1090                     type_data->ertd_es_super_buffer.eessb_bufs_per_desc;
 1091                 es_max_dma_len =
 1092                     type_data->ertd_es_super_buffer.eessb_max_dma_len;
 1093                 es_buf_stride =
 1094                     type_data->ertd_es_super_buffer.eessb_buf_stride;
 1095                 hol_block_timeout =
 1096                     type_data->ertd_es_super_buffer.eessb_hol_block_timeout;
 1097                 break;
 1098 #endif /* EFSYS_OPT_RX_ES_SUPER_BUFFER */
 1099         default:
 1100                 rc = ENOTSUP;
 1101                 goto fail6;
 1102         }
 1103 
 1104 #if EFSYS_OPT_RX_PACKED_STREAM
 1105         if (ps_buf_size != 0) {
 1106                 /* Check if datapath firmware supports packed stream mode */
 1107                 if (encp->enc_rx_packed_stream_supported == B_FALSE) {
 1108                         rc = ENOTSUP;
 1109                         goto fail7;
 1110                 }
 1111                 /* Check if packed stream allows configurable buffer sizes */
 1112                 if ((ps_buf_size != MC_CMD_INIT_RXQ_EXT_IN_PS_BUFF_1M) &&
 1113                     (encp->enc_rx_var_packed_stream_supported == B_FALSE)) {
 1114                         rc = ENOTSUP;
 1115                         goto fail8;
 1116                 }
 1117         }
 1118 #else /* EFSYS_OPT_RX_PACKED_STREAM */
 1119         EFSYS_ASSERT(ps_buf_size == 0);
 1120 #endif /* EFSYS_OPT_RX_PACKED_STREAM */
 1121 
 1122 #if EFSYS_OPT_RX_ES_SUPER_BUFFER
 1123         if (es_bufs_per_desc > 0) {
 1124                 if (encp->enc_rx_es_super_buffer_supported == B_FALSE) {
 1125                         rc = ENOTSUP;
 1126                         goto fail9;
 1127                 }
 1128                 if (!EFX_IS_P2ALIGNED(uint32_t, es_max_dma_len,
 1129                             EFX_RX_ES_SUPER_BUFFER_BUF_ALIGNMENT)) {
 1130                         rc = EINVAL;
 1131                         goto fail10;
 1132                 }
 1133                 if (!EFX_IS_P2ALIGNED(uint32_t, es_buf_stride,
 1134                             EFX_RX_ES_SUPER_BUFFER_BUF_ALIGNMENT)) {
 1135                         rc = EINVAL;
 1136                         goto fail11;
 1137                 }
 1138         }
 1139 #else /* EFSYS_OPT_RX_ES_SUPER_BUFFER */
 1140         EFSYS_ASSERT(es_bufs_per_desc == 0);
 1141 #endif /* EFSYS_OPT_RX_ES_SUPER_BUFFER */
 1142 
 1143         /* Scatter can only be disabled if the firmware supports doing so */
 1144         if (flags & EFX_RXQ_FLAG_SCATTER)
 1145                 disable_scatter = B_FALSE;
 1146         else
 1147                 disable_scatter = encp->enc_rx_disable_scatter_supported;
 1148 
 1149         if (flags & EFX_RXQ_FLAG_INNER_CLASSES)
 1150                 want_inner_classes = B_TRUE;
 1151         else
 1152                 want_inner_classes = B_FALSE;
 1153 
 1154         if ((rc = efx_mcdi_init_rxq(enp, ndescs, eep->ee_index, label, index,
 1155                     esmp, disable_scatter, want_inner_classes,
 1156                     ps_buf_size, es_bufs_per_desc, es_max_dma_len,
 1157                     es_buf_stride, hol_block_timeout)) != 0)
 1158                 goto fail12;
 1159 
 1160         erp->er_eep = eep;
 1161         erp->er_label = label;
 1162 
 1163         ef10_ev_rxlabel_init(eep, erp, label, type);
 1164 
 1165         erp->er_ev_qstate = &erp->er_eep->ee_rxq_state[label];
 1166 
 1167         return (0);
 1168 
 1169 fail12:
 1170         EFSYS_PROBE(fail12);
 1171 #if EFSYS_OPT_RX_ES_SUPER_BUFFER
 1172 fail11:
 1173         EFSYS_PROBE(fail11);
 1174 fail10:
 1175         EFSYS_PROBE(fail10);
 1176 fail9:
 1177         EFSYS_PROBE(fail9);
 1178 #endif /* EFSYS_OPT_RX_ES_SUPER_BUFFER */
 1179 #if EFSYS_OPT_RX_PACKED_STREAM
 1180 fail8:
 1181         EFSYS_PROBE(fail8);
 1182 fail7:
 1183         EFSYS_PROBE(fail7);
 1184 #endif /* EFSYS_OPT_RX_PACKED_STREAM */
 1185 fail6:
 1186         EFSYS_PROBE(fail6);
 1187 #if EFSYS_OPT_RX_ES_SUPER_BUFFER
 1188 fail5:
 1189         EFSYS_PROBE(fail5);
 1190 #endif /* EFSYS_OPT_RX_ES_SUPER_BUFFER */
 1191 #if EFSYS_OPT_RX_PACKED_STREAM
 1192 fail4:
 1193         EFSYS_PROBE(fail4);
 1194 fail3:
 1195         EFSYS_PROBE(fail3);
 1196 #endif /* EFSYS_OPT_RX_PACKED_STREAM */
 1197 fail2:
 1198         EFSYS_PROBE(fail2);
 1199 fail1:
 1200         EFSYS_PROBE1(fail1, efx_rc_t, rc);
 1201 
 1202         return (rc);
 1203 }
 1204 
 1205                 void
 1206 ef10_rx_qdestroy(
 1207         __in    efx_rxq_t *erp)
 1208 {
 1209         efx_nic_t *enp = erp->er_enp;
 1210         efx_evq_t *eep = erp->er_eep;
 1211         unsigned int label = erp->er_label;
 1212 
 1213         ef10_ev_rxlabel_fini(eep, label);
 1214 
 1215         EFSYS_ASSERT(enp->en_rx_qcount != 0);
 1216         --enp->en_rx_qcount;
 1217 
 1218         EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_rxq_t), erp);
 1219 }
 1220 
 1221                 void
 1222 ef10_rx_fini(
 1223         __in    efx_nic_t *enp)
 1224 {
 1225 #if EFSYS_OPT_RX_SCALE
 1226         if (enp->en_rss_context_type != EFX_RX_SCALE_UNAVAILABLE)
 1227                 (void) efx_mcdi_rss_context_free(enp, enp->en_rss_context);
 1228         enp->en_rss_context = 0;
 1229         enp->en_rss_context_type = EFX_RX_SCALE_UNAVAILABLE;
 1230 #else
 1231         _NOTE(ARGUNUSED(enp))
 1232 #endif /* EFSYS_OPT_RX_SCALE */
 1233 }
 1234 
 1235 #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */

Cache object: 2566a7975915731d4831bea2c99ee215


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