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_filter.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 #if EFSYS_OPT_FILTER
   40 
   41 #if EFSYS_OPT_SIENA
   42 
   43 static  __checkReturn   efx_rc_t
   44 siena_filter_init(
   45         __in            efx_nic_t *enp);
   46 
   47 static                  void
   48 siena_filter_fini(
   49         __in            efx_nic_t *enp);
   50 
   51 static  __checkReturn   efx_rc_t
   52 siena_filter_restore(
   53         __in            efx_nic_t *enp);
   54 
   55 static  __checkReturn   efx_rc_t
   56 siena_filter_add(
   57         __in            efx_nic_t *enp,
   58         __inout         efx_filter_spec_t *spec,
   59         __in            boolean_t may_replace);
   60 
   61 static  __checkReturn   efx_rc_t
   62 siena_filter_delete(
   63         __in            efx_nic_t *enp,
   64         __inout         efx_filter_spec_t *spec);
   65 
   66 static  __checkReturn   efx_rc_t
   67 siena_filter_supported_filters(
   68         __in                            efx_nic_t *enp,
   69         __out_ecount(buffer_length)     uint32_t *buffer,
   70         __in                            size_t buffer_length,
   71         __out                           size_t *list_lengthp);
   72 
   73 #endif /* EFSYS_OPT_SIENA */
   74 
   75 #if EFSYS_OPT_SIENA
   76 static const efx_filter_ops_t   __efx_filter_siena_ops = {
   77         siena_filter_init,              /* efo_init */
   78         siena_filter_fini,              /* efo_fini */
   79         siena_filter_restore,           /* efo_restore */
   80         siena_filter_add,               /* efo_add */
   81         siena_filter_delete,            /* efo_delete */
   82         siena_filter_supported_filters, /* efo_supported_filters */
   83         NULL,                           /* efo_reconfigure */
   84 };
   85 #endif /* EFSYS_OPT_SIENA */
   86 
   87 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
   88 static const efx_filter_ops_t   __efx_filter_ef10_ops = {
   89         ef10_filter_init,               /* efo_init */
   90         ef10_filter_fini,               /* efo_fini */
   91         ef10_filter_restore,            /* efo_restore */
   92         ef10_filter_add,                /* efo_add */
   93         ef10_filter_delete,             /* efo_delete */
   94         ef10_filter_supported_filters,  /* efo_supported_filters */
   95         ef10_filter_reconfigure,        /* efo_reconfigure */
   96 };
   97 #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
   98 
   99         __checkReturn   efx_rc_t
  100 efx_filter_insert(
  101         __in            efx_nic_t *enp,
  102         __inout         efx_filter_spec_t *spec)
  103 {
  104         const efx_filter_ops_t *efop = enp->en_efop;
  105         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
  106         efx_rc_t rc;
  107 
  108         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
  109         EFSYS_ASSERT3P(spec, !=, NULL);
  110         EFSYS_ASSERT3U(spec->efs_flags, &, EFX_FILTER_FLAG_RX);
  111 
  112         if ((spec->efs_flags & EFX_FILTER_FLAG_ACTION_MARK) &&
  113             !encp->enc_filter_action_mark_supported) {
  114                 rc = ENOTSUP;
  115                 goto fail1;
  116         }
  117 
  118         if ((spec->efs_flags & EFX_FILTER_FLAG_ACTION_FLAG) &&
  119             !encp->enc_filter_action_flag_supported) {
  120                 rc = ENOTSUP;
  121                 goto fail2;
  122         }
  123 
  124         return (efop->efo_add(enp, spec, B_FALSE));
  125 
  126 fail2:
  127         EFSYS_PROBE(fail2);
  128 fail1:
  129         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  130 
  131         return (rc);
  132 }
  133 
  134         __checkReturn   efx_rc_t
  135 efx_filter_remove(
  136         __in            efx_nic_t *enp,
  137         __inout         efx_filter_spec_t *spec)
  138 {
  139         const efx_filter_ops_t *efop = enp->en_efop;
  140 
  141         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
  142         EFSYS_ASSERT3P(spec, !=, NULL);
  143         EFSYS_ASSERT3U(spec->efs_flags, &, EFX_FILTER_FLAG_RX);
  144 
  145         return (efop->efo_delete(enp, spec));
  146 }
  147 
  148         __checkReturn   efx_rc_t
  149 efx_filter_restore(
  150         __in            efx_nic_t *enp)
  151 {
  152         efx_rc_t rc;
  153 
  154         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
  155 
  156         if ((rc = enp->en_efop->efo_restore(enp)) != 0)
  157                 goto fail1;
  158 
  159         return (0);
  160 
  161 fail1:
  162         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  163 
  164         return (rc);
  165 }
  166 
  167         __checkReturn   efx_rc_t
  168 efx_filter_init(
  169         __in            efx_nic_t *enp)
  170 {
  171         const efx_filter_ops_t *efop;
  172         efx_rc_t rc;
  173 
  174         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
  175         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
  176         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_FILTER));
  177 
  178         switch (enp->en_family) {
  179 #if EFSYS_OPT_SIENA
  180         case EFX_FAMILY_SIENA:
  181                 efop = &__efx_filter_siena_ops;
  182                 break;
  183 #endif /* EFSYS_OPT_SIENA */
  184 
  185 #if EFSYS_OPT_HUNTINGTON
  186         case EFX_FAMILY_HUNTINGTON:
  187                 efop = &__efx_filter_ef10_ops;
  188                 break;
  189 #endif /* EFSYS_OPT_HUNTINGTON */
  190 
  191 #if EFSYS_OPT_MEDFORD
  192         case EFX_FAMILY_MEDFORD:
  193                 efop = &__efx_filter_ef10_ops;
  194                 break;
  195 #endif /* EFSYS_OPT_MEDFORD */
  196 
  197 #if EFSYS_OPT_MEDFORD2
  198         case EFX_FAMILY_MEDFORD2:
  199                 efop = &__efx_filter_ef10_ops;
  200                 break;
  201 #endif /* EFSYS_OPT_MEDFORD2 */
  202 
  203         default:
  204                 EFSYS_ASSERT(0);
  205                 rc = ENOTSUP;
  206                 goto fail1;
  207         }
  208 
  209         if ((rc = efop->efo_init(enp)) != 0)
  210                 goto fail2;
  211 
  212         enp->en_efop = efop;
  213         enp->en_mod_flags |= EFX_MOD_FILTER;
  214         return (0);
  215 
  216 fail2:
  217         EFSYS_PROBE(fail2);
  218 fail1:
  219         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  220 
  221         enp->en_efop = NULL;
  222         enp->en_mod_flags &= ~EFX_MOD_FILTER;
  223         return (rc);
  224 }
  225 
  226                         void
  227 efx_filter_fini(
  228         __in            efx_nic_t *enp)
  229 {
  230         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
  231         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
  232         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
  233 
  234         enp->en_efop->efo_fini(enp);
  235 
  236         enp->en_efop = NULL;
  237         enp->en_mod_flags &= ~EFX_MOD_FILTER;
  238 }
  239 
  240 /*
  241  * Query the possible combinations of match flags which can be filtered on.
  242  * These are returned as a list, of which each 32 bit element is a bitmask
  243  * formed of EFX_FILTER_MATCH flags.
  244  *
  245  * The combinations are ordered in priority from highest to lowest.
  246  *
  247  * If the provided buffer is too short to hold the list, the call with fail with
  248  * ENOSPC and *list_lengthp will be set to the buffer length required.
  249  */
  250         __checkReturn   efx_rc_t
  251 efx_filter_supported_filters(
  252         __in                            efx_nic_t *enp,
  253         __out_ecount(buffer_length)     uint32_t *buffer,
  254         __in                            size_t buffer_length,
  255         __out                           size_t *list_lengthp)
  256 {
  257         efx_rc_t rc;
  258 
  259         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
  260         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
  261         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
  262         EFSYS_ASSERT(enp->en_efop->efo_supported_filters != NULL);
  263 
  264         if (buffer == NULL) {
  265                 rc = EINVAL;
  266                 goto fail1;
  267         }
  268 
  269         rc = enp->en_efop->efo_supported_filters(enp, buffer, buffer_length,
  270                                                     list_lengthp);
  271         if (rc != 0)
  272                 goto fail2;
  273 
  274         return (0);
  275 
  276 fail2:
  277         EFSYS_PROBE(fail2);
  278 fail1:
  279         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  280 
  281         return (rc);
  282 }
  283 
  284         __checkReturn   efx_rc_t
  285 efx_filter_reconfigure(
  286         __in                            efx_nic_t *enp,
  287         __in_ecount(6)                  uint8_t const *mac_addr,
  288         __in                            boolean_t all_unicst,
  289         __in                            boolean_t mulcst,
  290         __in                            boolean_t all_mulcst,
  291         __in                            boolean_t brdcst,
  292         __in_ecount(6*count)            uint8_t const *addrs,
  293         __in                            uint32_t count)
  294 {
  295         efx_rc_t rc;
  296 
  297         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
  298         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
  299         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
  300 
  301         if (enp->en_efop->efo_reconfigure != NULL) {
  302                 if ((rc = enp->en_efop->efo_reconfigure(enp, mac_addr,
  303                                                         all_unicst, mulcst,
  304                                                         all_mulcst, brdcst,
  305                                                         addrs, count)) != 0)
  306                         goto fail1;
  307         }
  308 
  309         return (0);
  310 
  311 fail1:
  312         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  313 
  314         return (rc);
  315 }
  316 
  317                 void
  318 efx_filter_spec_init_rx(
  319         __out           efx_filter_spec_t *spec,
  320         __in            efx_filter_priority_t priority,
  321         __in            efx_filter_flags_t flags,
  322         __in            efx_rxq_t *erp)
  323 {
  324         EFSYS_ASSERT3P(spec, !=, NULL);
  325         EFSYS_ASSERT3P(erp, !=, NULL);
  326         EFSYS_ASSERT((flags & ~(EFX_FILTER_FLAG_RX_RSS |
  327                                 EFX_FILTER_FLAG_RX_SCATTER)) == 0);
  328 
  329         memset(spec, 0, sizeof (*spec));
  330         spec->efs_priority = priority;
  331         spec->efs_flags = EFX_FILTER_FLAG_RX | flags;
  332         spec->efs_rss_context = EFX_RSS_CONTEXT_DEFAULT;
  333         spec->efs_dmaq_id = (uint16_t)erp->er_index;
  334 }
  335 
  336                 void
  337 efx_filter_spec_init_tx(
  338         __out           efx_filter_spec_t *spec,
  339         __in            efx_txq_t *etp)
  340 {
  341         EFSYS_ASSERT3P(spec, !=, NULL);
  342         EFSYS_ASSERT3P(etp, !=, NULL);
  343 
  344         memset(spec, 0, sizeof (*spec));
  345         spec->efs_priority = EFX_FILTER_PRI_REQUIRED;
  346         spec->efs_flags = EFX_FILTER_FLAG_TX;
  347         spec->efs_dmaq_id = (uint16_t)etp->et_index;
  348 }
  349 
  350 /*
  351  *  Specify IPv4 host, transport protocol and port in a filter specification
  352  */
  353 __checkReturn           efx_rc_t
  354 efx_filter_spec_set_ipv4_local(
  355         __inout         efx_filter_spec_t *spec,
  356         __in            uint8_t proto,
  357         __in            uint32_t host,
  358         __in            uint16_t port)
  359 {
  360         EFSYS_ASSERT3P(spec, !=, NULL);
  361 
  362         spec->efs_match_flags |=
  363                 EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
  364                 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT;
  365         spec->efs_ether_type = EFX_ETHER_TYPE_IPV4;
  366         spec->efs_ip_proto = proto;
  367         spec->efs_loc_host.eo_u32[0] = host;
  368         spec->efs_loc_port = port;
  369         return (0);
  370 }
  371 
  372 /*
  373  * Specify IPv4 hosts, transport protocol and ports in a filter specification
  374  */
  375 __checkReturn           efx_rc_t
  376 efx_filter_spec_set_ipv4_full(
  377         __inout         efx_filter_spec_t *spec,
  378         __in            uint8_t proto,
  379         __in            uint32_t lhost,
  380         __in            uint16_t lport,
  381         __in            uint32_t rhost,
  382         __in            uint16_t rport)
  383 {
  384         EFSYS_ASSERT3P(spec, !=, NULL);
  385 
  386         spec->efs_match_flags |=
  387                 EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
  388                 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT |
  389                 EFX_FILTER_MATCH_REM_HOST | EFX_FILTER_MATCH_REM_PORT;
  390         spec->efs_ether_type = EFX_ETHER_TYPE_IPV4;
  391         spec->efs_ip_proto = proto;
  392         spec->efs_loc_host.eo_u32[0] = lhost;
  393         spec->efs_loc_port = lport;
  394         spec->efs_rem_host.eo_u32[0] = rhost;
  395         spec->efs_rem_port = rport;
  396         return (0);
  397 }
  398 
  399 /*
  400  * Specify local Ethernet address and/or VID in filter specification
  401  */
  402 __checkReturn           efx_rc_t
  403 efx_filter_spec_set_eth_local(
  404         __inout         efx_filter_spec_t *spec,
  405         __in            uint16_t vid,
  406         __in            const uint8_t *addr)
  407 {
  408         EFSYS_ASSERT3P(spec, !=, NULL);
  409         EFSYS_ASSERT3P(addr, !=, NULL);
  410 
  411         if (vid == EFX_FILTER_SPEC_VID_UNSPEC && addr == NULL)
  412                 return (EINVAL);
  413 
  414         if (vid != EFX_FILTER_SPEC_VID_UNSPEC) {
  415                 spec->efs_match_flags |= EFX_FILTER_MATCH_OUTER_VID;
  416                 spec->efs_outer_vid = vid;
  417         }
  418         if (addr != NULL) {
  419                 spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_MAC;
  420                 memcpy(spec->efs_loc_mac, addr, EFX_MAC_ADDR_LEN);
  421         }
  422         return (0);
  423 }
  424 
  425                         void
  426 efx_filter_spec_set_ether_type(
  427         __inout         efx_filter_spec_t *spec,
  428         __in            uint16_t ether_type)
  429 {
  430         EFSYS_ASSERT3P(spec, !=, NULL);
  431 
  432         spec->efs_ether_type = ether_type;
  433         spec->efs_match_flags |= EFX_FILTER_MATCH_ETHER_TYPE;
  434 }
  435 
  436 /*
  437  * Specify matching otherwise-unmatched unicast in a filter specification
  438  */
  439 __checkReturn           efx_rc_t
  440 efx_filter_spec_set_uc_def(
  441         __inout         efx_filter_spec_t *spec)
  442 {
  443         EFSYS_ASSERT3P(spec, !=, NULL);
  444 
  445         spec->efs_match_flags |= EFX_FILTER_MATCH_UNKNOWN_UCAST_DST;
  446         return (0);
  447 }
  448 
  449 /*
  450  * Specify matching otherwise-unmatched multicast in a filter specification
  451  */
  452 __checkReturn           efx_rc_t
  453 efx_filter_spec_set_mc_def(
  454         __inout         efx_filter_spec_t *spec)
  455 {
  456         EFSYS_ASSERT3P(spec, !=, NULL);
  457 
  458         spec->efs_match_flags |= EFX_FILTER_MATCH_UNKNOWN_MCAST_DST;
  459         return (0);
  460 }
  461 
  462 __checkReturn           efx_rc_t
  463 efx_filter_spec_set_encap_type(
  464         __inout         efx_filter_spec_t *spec,
  465         __in            efx_tunnel_protocol_t encap_type,
  466         __in            efx_filter_inner_frame_match_t inner_frame_match)
  467 {
  468         uint32_t match_flags = EFX_FILTER_MATCH_ENCAP_TYPE;
  469         uint8_t ip_proto;
  470         efx_rc_t rc;
  471 
  472         EFSYS_ASSERT3P(spec, !=, NULL);
  473 
  474         switch (encap_type) {
  475         case EFX_TUNNEL_PROTOCOL_VXLAN:
  476         case EFX_TUNNEL_PROTOCOL_GENEVE:
  477                 ip_proto = EFX_IPPROTO_UDP;
  478                 break;
  479         case EFX_TUNNEL_PROTOCOL_NVGRE:
  480                 ip_proto = EFX_IPPROTO_GRE;
  481                 break;
  482         default:
  483                 EFSYS_ASSERT(0);
  484                 rc = EINVAL;
  485                 goto fail1;
  486         }
  487 
  488         switch (inner_frame_match) {
  489         case EFX_FILTER_INNER_FRAME_MATCH_UNKNOWN_MCAST_DST:
  490                 match_flags |= EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST;
  491                 break;
  492         case EFX_FILTER_INNER_FRAME_MATCH_UNKNOWN_UCAST_DST:
  493                 match_flags |= EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST;
  494                 break;
  495         case EFX_FILTER_INNER_FRAME_MATCH_OTHER:
  496                 /* This is for when specific inner frames are to be matched. */
  497                 break;
  498         default:
  499                 EFSYS_ASSERT(0);
  500                 rc = EINVAL;
  501                 goto fail2;
  502         }
  503 
  504         spec->efs_encap_type = encap_type;
  505         spec->efs_ip_proto = ip_proto;
  506         spec->efs_match_flags |= (match_flags | EFX_FILTER_MATCH_IP_PROTO);
  507 
  508         return (0);
  509 
  510 fail2:
  511         EFSYS_PROBE(fail2);
  512 fail1:
  513         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  514 
  515         return (rc);
  516 }
  517 
  518 /*
  519  * Specify inner and outer Ethernet address and VNI or VSID in tunnel filter
  520  * specification.
  521  */
  522 static  __checkReturn   efx_rc_t
  523 efx_filter_spec_set_tunnel(
  524         __inout efx_filter_spec_t *spec,
  525         __in            efx_tunnel_protocol_t encap_type,
  526         __in            const uint8_t *vni_or_vsid,
  527         __in            const uint8_t *inner_addr,
  528         __in            const uint8_t *outer_addr)
  529 {
  530         efx_rc_t rc;
  531 
  532         EFSYS_ASSERT3P(spec, !=, NULL);
  533         EFSYS_ASSERT3P(vni_or_vsid, !=, NULL);
  534         EFSYS_ASSERT3P(inner_addr, !=, NULL);
  535         EFSYS_ASSERT3P(outer_addr, !=, NULL);
  536 
  537         switch (encap_type) {
  538         case EFX_TUNNEL_PROTOCOL_VXLAN:
  539         case EFX_TUNNEL_PROTOCOL_GENEVE:
  540         case EFX_TUNNEL_PROTOCOL_NVGRE:
  541                 break;
  542         default:
  543                 rc = EINVAL;
  544                 goto fail1;
  545         }
  546 
  547         if ((inner_addr == NULL) && (outer_addr == NULL)) {
  548                 rc = EINVAL;
  549                 goto fail2;
  550         }
  551 
  552         if (vni_or_vsid != NULL) {
  553                 spec->efs_match_flags |= EFX_FILTER_MATCH_VNI_OR_VSID;
  554                 memcpy(spec->efs_vni_or_vsid, vni_or_vsid, EFX_VNI_OR_VSID_LEN);
  555         }
  556         if (outer_addr != NULL) {
  557                 spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_MAC;
  558                 memcpy(spec->efs_loc_mac, outer_addr, EFX_MAC_ADDR_LEN);
  559         }
  560         if (inner_addr != NULL) {
  561                 spec->efs_match_flags |= EFX_FILTER_MATCH_IFRM_LOC_MAC;
  562                 memcpy(spec->efs_ifrm_loc_mac, inner_addr, EFX_MAC_ADDR_LEN);
  563         }
  564 
  565         spec->efs_match_flags |= EFX_FILTER_MATCH_ENCAP_TYPE;
  566         spec->efs_encap_type = encap_type;
  567 
  568         return (0);
  569 
  570 fail2:
  571         EFSYS_PROBE(fail2);
  572 fail1:
  573         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  574 
  575         return (rc);
  576 }
  577 
  578 /*
  579  * Specify inner and outer Ethernet address and VNI in VXLAN filter
  580  * specification.
  581  */
  582 __checkReturn           efx_rc_t
  583 efx_filter_spec_set_vxlan(
  584         __inout         efx_filter_spec_t *spec,
  585         __in            const uint8_t *vni,
  586         __in            const uint8_t *inner_addr,
  587         __in            const uint8_t *outer_addr)
  588 {
  589         return efx_filter_spec_set_tunnel(spec, EFX_TUNNEL_PROTOCOL_VXLAN,
  590             vni, inner_addr, outer_addr);
  591 }
  592 
  593 /*
  594  * Specify inner and outer Ethernet address and VNI in Geneve filter
  595  * specification.
  596  */
  597 __checkReturn           efx_rc_t
  598 efx_filter_spec_set_geneve(
  599         __inout         efx_filter_spec_t *spec,
  600         __in            const uint8_t *vni,
  601         __in            const uint8_t *inner_addr,
  602         __in            const uint8_t *outer_addr)
  603 {
  604         return efx_filter_spec_set_tunnel(spec, EFX_TUNNEL_PROTOCOL_GENEVE,
  605             vni, inner_addr, outer_addr);
  606 }
  607 
  608 /*
  609  * Specify inner and outer Ethernet address and vsid in NVGRE filter
  610  * specification.
  611  */
  612 __checkReturn           efx_rc_t
  613 efx_filter_spec_set_nvgre(
  614         __inout         efx_filter_spec_t *spec,
  615         __in            const uint8_t *vsid,
  616         __in            const uint8_t *inner_addr,
  617         __in            const uint8_t *outer_addr)
  618 {
  619         return efx_filter_spec_set_tunnel(spec, EFX_TUNNEL_PROTOCOL_NVGRE,
  620             vsid, inner_addr, outer_addr);
  621 }
  622 
  623 #if EFSYS_OPT_RX_SCALE
  624         __checkReturn   efx_rc_t
  625 efx_filter_spec_set_rss_context(
  626         __inout         efx_filter_spec_t *spec,
  627         __in            uint32_t rss_context)
  628 {
  629         efx_rc_t rc;
  630 
  631         EFSYS_ASSERT3P(spec, !=, NULL);
  632 
  633         /* The filter must have been created with EFX_FILTER_FLAG_RX_RSS. */
  634         if ((spec->efs_flags & EFX_FILTER_FLAG_RX_RSS) == 0) {
  635                 rc = EINVAL;
  636                 goto fail1;
  637         }
  638 
  639         spec->efs_rss_context = rss_context;
  640 
  641         return (0);
  642 
  643 fail1:
  644         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  645 
  646         return (rc);
  647 }
  648 #endif
  649 
  650 #if EFSYS_OPT_SIENA
  651 
  652 /*
  653  * "Fudge factors" - difference between programmed value and actual depth.
  654  * Due to pipelined implementation we need to program H/W with a value that
  655  * is larger than the hop limit we want.
  656  */
  657 #define FILTER_CTL_SRCH_FUDGE_WILD 3
  658 #define FILTER_CTL_SRCH_FUDGE_FULL 1
  659 
  660 /*
  661  * Hard maximum hop limit.  Hardware will time-out beyond 200-something.
  662  * We also need to avoid infinite loops in efx_filter_search() when the
  663  * table is full.
  664  */
  665 #define FILTER_CTL_SRCH_MAX 200
  666 
  667 static  __checkReturn   efx_rc_t
  668 siena_filter_spec_from_gen_spec(
  669         __out           siena_filter_spec_t *sf_spec,
  670         __in            efx_filter_spec_t *gen_spec)
  671 {
  672         efx_rc_t rc;
  673         boolean_t is_full = B_FALSE;
  674 
  675         if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX)
  676                 EFSYS_ASSERT3U(gen_spec->efs_flags, ==, EFX_FILTER_FLAG_TX);
  677         else
  678                 EFSYS_ASSERT3U(gen_spec->efs_flags, &, EFX_FILTER_FLAG_RX);
  679 
  680         /* Siena only has one RSS context */
  681         if ((gen_spec->efs_flags & EFX_FILTER_FLAG_RX_RSS) &&
  682             gen_spec->efs_rss_context != EFX_RSS_CONTEXT_DEFAULT) {
  683                 rc = EINVAL;
  684                 goto fail1;
  685         }
  686 
  687         sf_spec->sfs_flags = gen_spec->efs_flags;
  688         sf_spec->sfs_dmaq_id = gen_spec->efs_dmaq_id;
  689 
  690         switch (gen_spec->efs_match_flags) {
  691         case EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
  692             EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT |
  693             EFX_FILTER_MATCH_REM_HOST | EFX_FILTER_MATCH_REM_PORT:
  694                 is_full = B_TRUE;
  695                 /* Fall through */
  696         case EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
  697             EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT: {
  698                 uint32_t rhost, host1, host2;
  699                 uint16_t rport, port1, port2;
  700 
  701                 if (gen_spec->efs_ether_type != EFX_ETHER_TYPE_IPV4) {
  702                         rc = ENOTSUP;
  703                         goto fail2;
  704                 }
  705                 if (gen_spec->efs_loc_port == 0 ||
  706                     (is_full && gen_spec->efs_rem_port == 0)) {
  707                         rc = EINVAL;
  708                         goto fail3;
  709                 }
  710                 switch (gen_spec->efs_ip_proto) {
  711                 case EFX_IPPROTO_TCP:
  712                         if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX) {
  713                                 sf_spec->sfs_type = (is_full ?
  714                                     EFX_SIENA_FILTER_TX_TCP_FULL :
  715                                     EFX_SIENA_FILTER_TX_TCP_WILD);
  716                         } else {
  717                                 sf_spec->sfs_type = (is_full ?
  718                                     EFX_SIENA_FILTER_RX_TCP_FULL :
  719                                     EFX_SIENA_FILTER_RX_TCP_WILD);
  720                         }
  721                         break;
  722                 case EFX_IPPROTO_UDP:
  723                         if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX) {
  724                                 sf_spec->sfs_type = (is_full ?
  725                                     EFX_SIENA_FILTER_TX_UDP_FULL :
  726                                     EFX_SIENA_FILTER_TX_UDP_WILD);
  727                         } else {
  728                                 sf_spec->sfs_type = (is_full ?
  729                                     EFX_SIENA_FILTER_RX_UDP_FULL :
  730                                     EFX_SIENA_FILTER_RX_UDP_WILD);
  731                         }
  732                         break;
  733                 default:
  734                         rc = ENOTSUP;
  735                         goto fail4;
  736                 }
  737                 /*
  738                  * The filter is constructed in terms of source and destination,
  739                  * with the odd wrinkle that the ports are swapped in a UDP
  740                  * wildcard filter. We need to convert from local and remote
  741                  * addresses (zero for a wildcard).
  742                  */
  743                 rhost = is_full ? gen_spec->efs_rem_host.eo_u32[0] : 0;
  744                 rport = is_full ? gen_spec->efs_rem_port : 0;
  745                 if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX) {
  746                         host1 = gen_spec->efs_loc_host.eo_u32[0];
  747                         host2 = rhost;
  748                 } else {
  749                         host1 = rhost;
  750                         host2 = gen_spec->efs_loc_host.eo_u32[0];
  751                 }
  752                 if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX) {
  753                         if (sf_spec->sfs_type ==
  754                             EFX_SIENA_FILTER_TX_UDP_WILD) {
  755                                 port1 = rport;
  756                                 port2 = gen_spec->efs_loc_port;
  757                         } else {
  758                                 port1 = gen_spec->efs_loc_port;
  759                                 port2 = rport;
  760                         }
  761                 } else {
  762                         if (sf_spec->sfs_type ==
  763                             EFX_SIENA_FILTER_RX_UDP_WILD) {
  764                                 port1 = gen_spec->efs_loc_port;
  765                                 port2 = rport;
  766                         } else {
  767                                 port1 = rport;
  768                                 port2 = gen_spec->efs_loc_port;
  769                         }
  770                 }
  771                 sf_spec->sfs_dword[0] = (host1 << 16) | port1;
  772                 sf_spec->sfs_dword[1] = (port2 << 16) | (host1 >> 16);
  773                 sf_spec->sfs_dword[2] = host2;
  774                 break;
  775         }
  776 
  777         case EFX_FILTER_MATCH_LOC_MAC | EFX_FILTER_MATCH_OUTER_VID:
  778                 is_full = B_TRUE;
  779                 /* Fall through */
  780         case EFX_FILTER_MATCH_LOC_MAC:
  781                 if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX) {
  782                         sf_spec->sfs_type = (is_full ?
  783                             EFX_SIENA_FILTER_TX_MAC_FULL :
  784                             EFX_SIENA_FILTER_TX_MAC_WILD);
  785                 } else {
  786                         sf_spec->sfs_type = (is_full ?
  787                             EFX_SIENA_FILTER_RX_MAC_FULL :
  788                             EFX_SIENA_FILTER_RX_MAC_WILD);
  789                 }
  790                 sf_spec->sfs_dword[0] = is_full ? gen_spec->efs_outer_vid : 0;
  791                 sf_spec->sfs_dword[1] =
  792                     gen_spec->efs_loc_mac[2] << 24 |
  793                     gen_spec->efs_loc_mac[3] << 16 |
  794                     gen_spec->efs_loc_mac[4] <<  8 |
  795                     gen_spec->efs_loc_mac[5];
  796                 sf_spec->sfs_dword[2] =
  797                     gen_spec->efs_loc_mac[0] << 8 |
  798                     gen_spec->efs_loc_mac[1];
  799                 break;
  800 
  801         default:
  802                 EFSYS_ASSERT(B_FALSE);
  803                 rc = ENOTSUP;
  804                 goto fail5;
  805         }
  806 
  807         return (0);
  808 
  809 fail5:
  810         EFSYS_PROBE(fail5);
  811 fail4:
  812         EFSYS_PROBE(fail4);
  813 fail3:
  814         EFSYS_PROBE(fail3);
  815 fail2:
  816         EFSYS_PROBE(fail2);
  817 fail1:
  818         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  819 
  820         return (rc);
  821 }
  822 
  823 /*
  824  * The filter hash function is LFSR polynomial x^16 + x^3 + 1 of a 32-bit
  825  * key derived from the n-tuple.
  826  */
  827 static                  uint16_t
  828 siena_filter_tbl_hash(
  829         __in            uint32_t key)
  830 {
  831         uint16_t tmp;
  832 
  833         /* First 16 rounds */
  834         tmp = 0x1fff ^ (uint16_t)(key >> 16);
  835         tmp = tmp ^ tmp >> 3 ^ tmp >> 6;
  836         tmp = tmp ^ tmp >> 9;
  837 
  838         /* Last 16 rounds */
  839         tmp = tmp ^ tmp << 13 ^ (uint16_t)(key & 0xffff);
  840         tmp = tmp ^ tmp >> 3 ^ tmp >> 6;
  841         tmp = tmp ^ tmp >> 9;
  842 
  843         return (tmp);
  844 }
  845 
  846 /*
  847  * To allow for hash collisions, filter search continues at these
  848  * increments from the first possible entry selected by the hash.
  849  */
  850 static                  uint16_t
  851 siena_filter_tbl_increment(
  852         __in            uint32_t key)
  853 {
  854         return ((uint16_t)(key * 2 - 1));
  855 }
  856 
  857 static  __checkReturn   boolean_t
  858 siena_filter_test_used(
  859         __in            siena_filter_tbl_t *sftp,
  860         __in            unsigned int index)
  861 {
  862         EFSYS_ASSERT3P(sftp->sft_bitmap, !=, NULL);
  863         return ((sftp->sft_bitmap[index / 32] & (1 << (index % 32))) != 0);
  864 }
  865 
  866 static                  void
  867 siena_filter_set_used(
  868         __in            siena_filter_tbl_t *sftp,
  869         __in            unsigned int index)
  870 {
  871         EFSYS_ASSERT3P(sftp->sft_bitmap, !=, NULL);
  872         sftp->sft_bitmap[index / 32] |= (1 << (index % 32));
  873         ++sftp->sft_used;
  874 }
  875 
  876 static                  void
  877 siena_filter_clear_used(
  878         __in            siena_filter_tbl_t *sftp,
  879         __in            unsigned int index)
  880 {
  881         EFSYS_ASSERT3P(sftp->sft_bitmap, !=, NULL);
  882         sftp->sft_bitmap[index / 32] &= ~(1 << (index % 32));
  883 
  884         --sftp->sft_used;
  885         EFSYS_ASSERT3U(sftp->sft_used, >=, 0);
  886 }
  887 
  888 static                  siena_filter_tbl_id_t
  889 siena_filter_tbl_id(
  890         __in            siena_filter_type_t type)
  891 {
  892         siena_filter_tbl_id_t tbl_id;
  893 
  894         switch (type) {
  895         case EFX_SIENA_FILTER_RX_TCP_FULL:
  896         case EFX_SIENA_FILTER_RX_TCP_WILD:
  897         case EFX_SIENA_FILTER_RX_UDP_FULL:
  898         case EFX_SIENA_FILTER_RX_UDP_WILD:
  899                 tbl_id = EFX_SIENA_FILTER_TBL_RX_IP;
  900                 break;
  901 
  902         case EFX_SIENA_FILTER_RX_MAC_FULL:
  903         case EFX_SIENA_FILTER_RX_MAC_WILD:
  904                 tbl_id = EFX_SIENA_FILTER_TBL_RX_MAC;
  905                 break;
  906 
  907         case EFX_SIENA_FILTER_TX_TCP_FULL:
  908         case EFX_SIENA_FILTER_TX_TCP_WILD:
  909         case EFX_SIENA_FILTER_TX_UDP_FULL:
  910         case EFX_SIENA_FILTER_TX_UDP_WILD:
  911                 tbl_id = EFX_SIENA_FILTER_TBL_TX_IP;
  912                 break;
  913 
  914         case EFX_SIENA_FILTER_TX_MAC_FULL:
  915         case EFX_SIENA_FILTER_TX_MAC_WILD:
  916                 tbl_id = EFX_SIENA_FILTER_TBL_TX_MAC;
  917                 break;
  918 
  919         default:
  920                 EFSYS_ASSERT(B_FALSE);
  921                 tbl_id = EFX_SIENA_FILTER_NTBLS;
  922                 break;
  923         }
  924         return (tbl_id);
  925 }
  926 
  927 static                  void
  928 siena_filter_reset_search_depth(
  929         __inout         siena_filter_t *sfp,
  930         __in            siena_filter_tbl_id_t tbl_id)
  931 {
  932         switch (tbl_id) {
  933         case EFX_SIENA_FILTER_TBL_RX_IP:
  934                 sfp->sf_depth[EFX_SIENA_FILTER_RX_TCP_FULL] = 0;
  935                 sfp->sf_depth[EFX_SIENA_FILTER_RX_TCP_WILD] = 0;
  936                 sfp->sf_depth[EFX_SIENA_FILTER_RX_UDP_FULL] = 0;
  937                 sfp->sf_depth[EFX_SIENA_FILTER_RX_UDP_WILD] = 0;
  938                 break;
  939 
  940         case EFX_SIENA_FILTER_TBL_RX_MAC:
  941                 sfp->sf_depth[EFX_SIENA_FILTER_RX_MAC_FULL] = 0;
  942                 sfp->sf_depth[EFX_SIENA_FILTER_RX_MAC_WILD] = 0;
  943                 break;
  944 
  945         case EFX_SIENA_FILTER_TBL_TX_IP:
  946                 sfp->sf_depth[EFX_SIENA_FILTER_TX_TCP_FULL] = 0;
  947                 sfp->sf_depth[EFX_SIENA_FILTER_TX_TCP_WILD] = 0;
  948                 sfp->sf_depth[EFX_SIENA_FILTER_TX_UDP_FULL] = 0;
  949                 sfp->sf_depth[EFX_SIENA_FILTER_TX_UDP_WILD] = 0;
  950                 break;
  951 
  952         case EFX_SIENA_FILTER_TBL_TX_MAC:
  953                 sfp->sf_depth[EFX_SIENA_FILTER_TX_MAC_FULL] = 0;
  954                 sfp->sf_depth[EFX_SIENA_FILTER_TX_MAC_WILD] = 0;
  955                 break;
  956 
  957         default:
  958                 EFSYS_ASSERT(B_FALSE);
  959                 break;
  960         }
  961 }
  962 
  963 static                  void
  964 siena_filter_push_rx_limits(
  965         __in            efx_nic_t *enp)
  966 {
  967         siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
  968         efx_oword_t oword;
  969 
  970         EFX_BAR_READO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
  971 
  972         EFX_SET_OWORD_FIELD(oword, FRF_AZ_TCP_FULL_SRCH_LIMIT,
  973             sfp->sf_depth[EFX_SIENA_FILTER_RX_TCP_FULL] +
  974             FILTER_CTL_SRCH_FUDGE_FULL);
  975         EFX_SET_OWORD_FIELD(oword, FRF_AZ_TCP_WILD_SRCH_LIMIT,
  976             sfp->sf_depth[EFX_SIENA_FILTER_RX_TCP_WILD] +
  977             FILTER_CTL_SRCH_FUDGE_WILD);
  978         EFX_SET_OWORD_FIELD(oword, FRF_AZ_UDP_FULL_SRCH_LIMIT,
  979             sfp->sf_depth[EFX_SIENA_FILTER_RX_UDP_FULL] +
  980             FILTER_CTL_SRCH_FUDGE_FULL);
  981         EFX_SET_OWORD_FIELD(oword, FRF_AZ_UDP_WILD_SRCH_LIMIT,
  982             sfp->sf_depth[EFX_SIENA_FILTER_RX_UDP_WILD] +
  983             FILTER_CTL_SRCH_FUDGE_WILD);
  984 
  985         if (sfp->sf_tbl[EFX_SIENA_FILTER_TBL_RX_MAC].sft_size) {
  986                 EFX_SET_OWORD_FIELD(oword,
  987                     FRF_CZ_ETHERNET_FULL_SEARCH_LIMIT,
  988                     sfp->sf_depth[EFX_SIENA_FILTER_RX_MAC_FULL] +
  989                     FILTER_CTL_SRCH_FUDGE_FULL);
  990                 EFX_SET_OWORD_FIELD(oword,
  991                     FRF_CZ_ETHERNET_WILDCARD_SEARCH_LIMIT,
  992                     sfp->sf_depth[EFX_SIENA_FILTER_RX_MAC_WILD] +
  993                     FILTER_CTL_SRCH_FUDGE_WILD);
  994         }
  995 
  996         EFX_BAR_WRITEO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
  997 }
  998 
  999 static                  void
 1000 siena_filter_push_tx_limits(
 1001         __in            efx_nic_t *enp)
 1002 {
 1003         siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
 1004         efx_oword_t oword;
 1005 
 1006         EFX_BAR_READO(enp, FR_AZ_TX_CFG_REG, &oword);
 1007 
 1008         if (sfp->sf_tbl[EFX_SIENA_FILTER_TBL_TX_IP].sft_size != 0) {
 1009                 EFX_SET_OWORD_FIELD(oword,
 1010                     FRF_CZ_TX_TCPIP_FILTER_FULL_SEARCH_RANGE,
 1011                     sfp->sf_depth[EFX_SIENA_FILTER_TX_TCP_FULL] +
 1012                     FILTER_CTL_SRCH_FUDGE_FULL);
 1013                 EFX_SET_OWORD_FIELD(oword,
 1014                     FRF_CZ_TX_TCPIP_FILTER_WILD_SEARCH_RANGE,
 1015                     sfp->sf_depth[EFX_SIENA_FILTER_TX_TCP_WILD] +
 1016                     FILTER_CTL_SRCH_FUDGE_WILD);
 1017                 EFX_SET_OWORD_FIELD(oword,
 1018                     FRF_CZ_TX_UDPIP_FILTER_FULL_SEARCH_RANGE,
 1019                     sfp->sf_depth[EFX_SIENA_FILTER_TX_UDP_FULL] +
 1020                     FILTER_CTL_SRCH_FUDGE_FULL);
 1021                 EFX_SET_OWORD_FIELD(oword,
 1022                     FRF_CZ_TX_UDPIP_FILTER_WILD_SEARCH_RANGE,
 1023                     sfp->sf_depth[EFX_SIENA_FILTER_TX_UDP_WILD] +
 1024                     FILTER_CTL_SRCH_FUDGE_WILD);
 1025         }
 1026 
 1027         if (sfp->sf_tbl[EFX_SIENA_FILTER_TBL_TX_MAC].sft_size != 0) {
 1028                 EFX_SET_OWORD_FIELD(
 1029                         oword, FRF_CZ_TX_ETH_FILTER_FULL_SEARCH_RANGE,
 1030                         sfp->sf_depth[EFX_SIENA_FILTER_TX_MAC_FULL] +
 1031                         FILTER_CTL_SRCH_FUDGE_FULL);
 1032                 EFX_SET_OWORD_FIELD(
 1033                         oword, FRF_CZ_TX_ETH_FILTER_WILD_SEARCH_RANGE,
 1034                         sfp->sf_depth[EFX_SIENA_FILTER_TX_MAC_WILD] +
 1035                         FILTER_CTL_SRCH_FUDGE_WILD);
 1036         }
 1037 
 1038         EFX_BAR_WRITEO(enp, FR_AZ_TX_CFG_REG, &oword);
 1039 }
 1040 
 1041 /* Build a filter entry and return its n-tuple key. */
 1042 static  __checkReturn   uint32_t
 1043 siena_filter_build(
 1044         __out           efx_oword_t *filter,
 1045         __in            siena_filter_spec_t *spec)
 1046 {
 1047         uint32_t dword3;
 1048         uint32_t key;
 1049         uint8_t  type  = spec->sfs_type;
 1050         uint32_t flags = spec->sfs_flags;
 1051 
 1052         switch (siena_filter_tbl_id(type)) {
 1053         case EFX_SIENA_FILTER_TBL_RX_IP: {
 1054                 boolean_t is_udp = (type == EFX_SIENA_FILTER_RX_UDP_FULL ||
 1055                     type == EFX_SIENA_FILTER_RX_UDP_WILD);
 1056                 EFX_POPULATE_OWORD_7(*filter,
 1057                     FRF_BZ_RSS_EN,
 1058                     (flags & EFX_FILTER_FLAG_RX_RSS) ? 1 : 0,
 1059                     FRF_BZ_SCATTER_EN,
 1060                     (flags & EFX_FILTER_FLAG_RX_SCATTER) ? 1 : 0,
 1061                     FRF_AZ_TCP_UDP, is_udp,
 1062                     FRF_AZ_RXQ_ID, spec->sfs_dmaq_id,
 1063                     EFX_DWORD_2, spec->sfs_dword[2],
 1064                     EFX_DWORD_1, spec->sfs_dword[1],
 1065                     EFX_DWORD_0, spec->sfs_dword[0]);
 1066                 dword3 = is_udp;
 1067                 break;
 1068         }
 1069 
 1070         case EFX_SIENA_FILTER_TBL_RX_MAC: {
 1071                 boolean_t is_wild = (type == EFX_SIENA_FILTER_RX_MAC_WILD);
 1072                 EFX_POPULATE_OWORD_7(*filter,
 1073                     FRF_CZ_RMFT_RSS_EN,
 1074                     (flags & EFX_FILTER_FLAG_RX_RSS) ? 1 : 0,
 1075                     FRF_CZ_RMFT_SCATTER_EN,
 1076                     (flags & EFX_FILTER_FLAG_RX_SCATTER) ? 1 : 0,
 1077                     FRF_CZ_RMFT_RXQ_ID, spec->sfs_dmaq_id,
 1078                     FRF_CZ_RMFT_WILDCARD_MATCH, is_wild,
 1079                     FRF_CZ_RMFT_DEST_MAC_DW1, spec->sfs_dword[2],
 1080                     FRF_CZ_RMFT_DEST_MAC_DW0, spec->sfs_dword[1],
 1081                     FRF_CZ_RMFT_VLAN_ID, spec->sfs_dword[0]);
 1082                 dword3 = is_wild;
 1083                 break;
 1084         }
 1085 
 1086         case EFX_SIENA_FILTER_TBL_TX_IP: {
 1087                 boolean_t is_udp = (type == EFX_SIENA_FILTER_TX_UDP_FULL ||
 1088                     type == EFX_SIENA_FILTER_TX_UDP_WILD);
 1089                 EFX_POPULATE_OWORD_5(*filter,
 1090                     FRF_CZ_TIFT_TCP_UDP, is_udp,
 1091                     FRF_CZ_TIFT_TXQ_ID, spec->sfs_dmaq_id,
 1092                     EFX_DWORD_2, spec->sfs_dword[2],
 1093                     EFX_DWORD_1, spec->sfs_dword[1],
 1094                     EFX_DWORD_0, spec->sfs_dword[0]);
 1095                 dword3 = is_udp | spec->sfs_dmaq_id << 1;
 1096                 break;
 1097         }
 1098 
 1099         case EFX_SIENA_FILTER_TBL_TX_MAC: {
 1100                 boolean_t is_wild = (type == EFX_SIENA_FILTER_TX_MAC_WILD);
 1101                 EFX_POPULATE_OWORD_5(*filter,
 1102                     FRF_CZ_TMFT_TXQ_ID, spec->sfs_dmaq_id,
 1103                     FRF_CZ_TMFT_WILDCARD_MATCH, is_wild,
 1104                     FRF_CZ_TMFT_SRC_MAC_DW1, spec->sfs_dword[2],
 1105                     FRF_CZ_TMFT_SRC_MAC_DW0, spec->sfs_dword[1],
 1106                     FRF_CZ_TMFT_VLAN_ID, spec->sfs_dword[0]);
 1107                 dword3 = is_wild | spec->sfs_dmaq_id << 1;
 1108                 break;
 1109         }
 1110 
 1111         default:
 1112                 EFSYS_ASSERT(B_FALSE);
 1113                 EFX_ZERO_OWORD(*filter);
 1114                 return (0);
 1115         }
 1116 
 1117         key =
 1118             spec->sfs_dword[0] ^
 1119             spec->sfs_dword[1] ^
 1120             spec->sfs_dword[2] ^
 1121             dword3;
 1122 
 1123         return (key);
 1124 }
 1125 
 1126 static  __checkReturn           efx_rc_t
 1127 siena_filter_push_entry(
 1128         __inout                 efx_nic_t *enp,
 1129         __in                    siena_filter_type_t type,
 1130         __in                    int index,
 1131         __in                    efx_oword_t *eop)
 1132 {
 1133         efx_rc_t rc;
 1134 
 1135         switch (type) {
 1136         case EFX_SIENA_FILTER_RX_TCP_FULL:
 1137         case EFX_SIENA_FILTER_RX_TCP_WILD:
 1138         case EFX_SIENA_FILTER_RX_UDP_FULL:
 1139         case EFX_SIENA_FILTER_RX_UDP_WILD:
 1140                 EFX_BAR_TBL_WRITEO(enp, FR_AZ_RX_FILTER_TBL0, index,
 1141                     eop, B_TRUE);
 1142                 break;
 1143 
 1144         case EFX_SIENA_FILTER_RX_MAC_FULL:
 1145         case EFX_SIENA_FILTER_RX_MAC_WILD:
 1146                 EFX_BAR_TBL_WRITEO(enp, FR_CZ_RX_MAC_FILTER_TBL0, index,
 1147                     eop, B_TRUE);
 1148                 break;
 1149 
 1150         case EFX_SIENA_FILTER_TX_TCP_FULL:
 1151         case EFX_SIENA_FILTER_TX_TCP_WILD:
 1152         case EFX_SIENA_FILTER_TX_UDP_FULL:
 1153         case EFX_SIENA_FILTER_TX_UDP_WILD:
 1154                 EFX_BAR_TBL_WRITEO(enp, FR_CZ_TX_FILTER_TBL0, index,
 1155                     eop, B_TRUE);
 1156                 break;
 1157 
 1158         case EFX_SIENA_FILTER_TX_MAC_FULL:
 1159         case EFX_SIENA_FILTER_TX_MAC_WILD:
 1160                 EFX_BAR_TBL_WRITEO(enp, FR_CZ_TX_MAC_FILTER_TBL0, index,
 1161                     eop, B_TRUE);
 1162                 break;
 1163 
 1164         default:
 1165                 EFSYS_ASSERT(B_FALSE);
 1166                 rc = ENOTSUP;
 1167                 goto fail1;
 1168         }
 1169         return (0);
 1170 
 1171 fail1:
 1172         return (rc);
 1173 }
 1174 
 1175 static  __checkReturn   boolean_t
 1176 siena_filter_equal(
 1177         __in            const siena_filter_spec_t *left,
 1178         __in            const siena_filter_spec_t *right)
 1179 {
 1180         siena_filter_tbl_id_t tbl_id;
 1181 
 1182         tbl_id = siena_filter_tbl_id(left->sfs_type);
 1183 
 1184         if (left->sfs_type != right->sfs_type)
 1185                 return (B_FALSE);
 1186 
 1187         if (memcmp(left->sfs_dword, right->sfs_dword,
 1188                 sizeof (left->sfs_dword)))
 1189                 return (B_FALSE);
 1190 
 1191         if ((tbl_id == EFX_SIENA_FILTER_TBL_TX_IP ||
 1192                 tbl_id == EFX_SIENA_FILTER_TBL_TX_MAC) &&
 1193             left->sfs_dmaq_id != right->sfs_dmaq_id)
 1194                 return (B_FALSE);
 1195 
 1196         return (B_TRUE);
 1197 }
 1198 
 1199 static  __checkReturn   efx_rc_t
 1200 siena_filter_search(
 1201         __in            siena_filter_tbl_t *sftp,
 1202         __in            siena_filter_spec_t *spec,
 1203         __in            uint32_t key,
 1204         __in            boolean_t for_insert,
 1205         __out           int *filter_index,
 1206         __out           unsigned int *depth_required)
 1207 {
 1208         unsigned int hash, incr, filter_idx, depth;
 1209 
 1210         hash = siena_filter_tbl_hash(key);
 1211         incr = siena_filter_tbl_increment(key);
 1212 
 1213         filter_idx = hash & (sftp->sft_size - 1);
 1214         depth = 1;
 1215 
 1216         for (;;) {
 1217                 /*
 1218                  * Return success if entry is used and matches this spec
 1219                  * or entry is unused and we are trying to insert.
 1220                  */
 1221                 if (siena_filter_test_used(sftp, filter_idx) ?
 1222                     siena_filter_equal(spec,
 1223                     &sftp->sft_spec[filter_idx]) :
 1224                     for_insert) {
 1225                         *filter_index = filter_idx;
 1226                         *depth_required = depth;
 1227                         return (0);
 1228                 }
 1229 
 1230                 /* Return failure if we reached the maximum search depth */
 1231                 if (depth == FILTER_CTL_SRCH_MAX)
 1232                         return (for_insert ? EBUSY : ENOENT);
 1233 
 1234                 filter_idx = (filter_idx + incr) & (sftp->sft_size - 1);
 1235                 ++depth;
 1236         }
 1237 }
 1238 
 1239 static                  void
 1240 siena_filter_clear_entry(
 1241         __in            efx_nic_t *enp,
 1242         __in            siena_filter_tbl_t *sftp,
 1243         __in            int index)
 1244 {
 1245         efx_oword_t filter;
 1246 
 1247         if (siena_filter_test_used(sftp, index)) {
 1248                 siena_filter_clear_used(sftp, index);
 1249 
 1250                 EFX_ZERO_OWORD(filter);
 1251                 siena_filter_push_entry(enp,
 1252                     sftp->sft_spec[index].sfs_type,
 1253                     index, &filter);
 1254 
 1255                 memset(&sftp->sft_spec[index],
 1256                     0, sizeof (sftp->sft_spec[0]));
 1257         }
 1258 }
 1259 
 1260                         void
 1261 siena_filter_tbl_clear(
 1262         __in            efx_nic_t *enp,
 1263         __in            siena_filter_tbl_id_t tbl_id)
 1264 {
 1265         siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
 1266         siena_filter_tbl_t *sftp = &sfp->sf_tbl[tbl_id];
 1267         int index;
 1268         efsys_lock_state_t state;
 1269 
 1270         EFSYS_LOCK(enp->en_eslp, state);
 1271 
 1272         for (index = 0; index < sftp->sft_size; ++index) {
 1273                 siena_filter_clear_entry(enp, sftp, index);
 1274         }
 1275 
 1276         if (sftp->sft_used == 0)
 1277                 siena_filter_reset_search_depth(sfp, tbl_id);
 1278 
 1279         EFSYS_UNLOCK(enp->en_eslp, state);
 1280 }
 1281 
 1282 static  __checkReturn   efx_rc_t
 1283 siena_filter_init(
 1284         __in            efx_nic_t *enp)
 1285 {
 1286         siena_filter_t *sfp;
 1287         siena_filter_tbl_t *sftp;
 1288         int tbl_id;
 1289         efx_rc_t rc;
 1290 
 1291         EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (siena_filter_t), sfp);
 1292 
 1293         if (!sfp) {
 1294                 rc = ENOMEM;
 1295                 goto fail1;
 1296         }
 1297 
 1298         enp->en_filter.ef_siena_filter = sfp;
 1299 
 1300         switch (enp->en_family) {
 1301         case EFX_FAMILY_SIENA:
 1302                 sftp = &sfp->sf_tbl[EFX_SIENA_FILTER_TBL_RX_IP];
 1303                 sftp->sft_size = FR_AZ_RX_FILTER_TBL0_ROWS;
 1304 
 1305                 sftp = &sfp->sf_tbl[EFX_SIENA_FILTER_TBL_RX_MAC];
 1306                 sftp->sft_size = FR_CZ_RX_MAC_FILTER_TBL0_ROWS;
 1307 
 1308                 sftp = &sfp->sf_tbl[EFX_SIENA_FILTER_TBL_TX_IP];
 1309                 sftp->sft_size = FR_CZ_TX_FILTER_TBL0_ROWS;
 1310 
 1311                 sftp = &sfp->sf_tbl[EFX_SIENA_FILTER_TBL_TX_MAC];
 1312                 sftp->sft_size = FR_CZ_TX_MAC_FILTER_TBL0_ROWS;
 1313                 break;
 1314 
 1315         default:
 1316                 rc = ENOTSUP;
 1317                 goto fail2;
 1318         }
 1319 
 1320         for (tbl_id = 0; tbl_id < EFX_SIENA_FILTER_NTBLS; tbl_id++) {
 1321                 unsigned int bitmap_size;
 1322 
 1323                 sftp = &sfp->sf_tbl[tbl_id];
 1324                 if (sftp->sft_size == 0)
 1325                         continue;
 1326 
 1327                 EFX_STATIC_ASSERT(sizeof (sftp->sft_bitmap[0]) ==
 1328                     sizeof (uint32_t));
 1329                 bitmap_size =
 1330                     (sftp->sft_size + (sizeof (uint32_t) * 8) - 1) / 8;
 1331 
 1332                 EFSYS_KMEM_ALLOC(enp->en_esip, bitmap_size, sftp->sft_bitmap);
 1333                 if (!sftp->sft_bitmap) {
 1334                         rc = ENOMEM;
 1335                         goto fail3;
 1336                 }
 1337 
 1338                 EFSYS_KMEM_ALLOC(enp->en_esip,
 1339                     sftp->sft_size * sizeof (*sftp->sft_spec),
 1340                     sftp->sft_spec);
 1341                 if (!sftp->sft_spec) {
 1342                         rc = ENOMEM;
 1343                         goto fail4;
 1344                 }
 1345                 memset(sftp->sft_spec, 0,
 1346                     sftp->sft_size * sizeof (*sftp->sft_spec));
 1347         }
 1348 
 1349         return (0);
 1350 
 1351 fail4:
 1352         EFSYS_PROBE(fail4);
 1353 
 1354 fail3:
 1355         EFSYS_PROBE(fail3);
 1356 
 1357 fail2:
 1358         EFSYS_PROBE(fail2);
 1359         siena_filter_fini(enp);
 1360 
 1361 fail1:
 1362         EFSYS_PROBE1(fail1, efx_rc_t, rc);
 1363         return (rc);
 1364 }
 1365 
 1366 static                  void
 1367 siena_filter_fini(
 1368         __in            efx_nic_t *enp)
 1369 {
 1370         siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
 1371         siena_filter_tbl_id_t tbl_id;
 1372 
 1373         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
 1374         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
 1375 
 1376         if (sfp == NULL)
 1377                 return;
 1378 
 1379         for (tbl_id = 0; tbl_id < EFX_SIENA_FILTER_NTBLS; tbl_id++) {
 1380                 siena_filter_tbl_t *sftp = &sfp->sf_tbl[tbl_id];
 1381                 unsigned int bitmap_size;
 1382 
 1383                 EFX_STATIC_ASSERT(sizeof (sftp->sft_bitmap[0]) ==
 1384                     sizeof (uint32_t));
 1385                 bitmap_size =
 1386                     (sftp->sft_size + (sizeof (uint32_t) * 8) - 1) / 8;
 1387 
 1388                 if (sftp->sft_bitmap != NULL) {
 1389                         EFSYS_KMEM_FREE(enp->en_esip, bitmap_size,
 1390                             sftp->sft_bitmap);
 1391                         sftp->sft_bitmap = NULL;
 1392                 }
 1393 
 1394                 if (sftp->sft_spec != NULL) {
 1395                         EFSYS_KMEM_FREE(enp->en_esip, sftp->sft_size *
 1396                             sizeof (*sftp->sft_spec), sftp->sft_spec);
 1397                         sftp->sft_spec = NULL;
 1398                 }
 1399         }
 1400 
 1401         EFSYS_KMEM_FREE(enp->en_esip, sizeof (siena_filter_t),
 1402             enp->en_filter.ef_siena_filter);
 1403 }
 1404 
 1405 /* Restore filter state after a reset */
 1406 static  __checkReturn   efx_rc_t
 1407 siena_filter_restore(
 1408         __in            efx_nic_t *enp)
 1409 {
 1410         siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
 1411         siena_filter_tbl_id_t tbl_id;
 1412         siena_filter_tbl_t *sftp;
 1413         siena_filter_spec_t *spec;
 1414         efx_oword_t filter;
 1415         int filter_idx;
 1416         efsys_lock_state_t state;
 1417         uint32_t key;
 1418         efx_rc_t rc;
 1419 
 1420         EFSYS_LOCK(enp->en_eslp, state);
 1421 
 1422         for (tbl_id = 0; tbl_id < EFX_SIENA_FILTER_NTBLS; tbl_id++) {
 1423                 sftp = &sfp->sf_tbl[tbl_id];
 1424                 for (filter_idx = 0;
 1425                         filter_idx < sftp->sft_size;
 1426                         filter_idx++) {
 1427                         if (!siena_filter_test_used(sftp, filter_idx))
 1428                                 continue;
 1429 
 1430                         spec = &sftp->sft_spec[filter_idx];
 1431                         if ((key = siena_filter_build(&filter, spec)) == 0) {
 1432                                 rc = EINVAL;
 1433                                 goto fail1;
 1434                         }
 1435                         if ((rc = siena_filter_push_entry(enp,
 1436                                     spec->sfs_type, filter_idx, &filter)) != 0)
 1437                                 goto fail2;
 1438                 }
 1439         }
 1440 
 1441         siena_filter_push_rx_limits(enp);
 1442         siena_filter_push_tx_limits(enp);
 1443 
 1444         EFSYS_UNLOCK(enp->en_eslp, state);
 1445 
 1446         return (0);
 1447 
 1448 fail2:
 1449         EFSYS_PROBE(fail2);
 1450 
 1451 fail1:
 1452         EFSYS_PROBE1(fail1, efx_rc_t, rc);
 1453 
 1454         EFSYS_UNLOCK(enp->en_eslp, state);
 1455 
 1456         return (rc);
 1457 }
 1458 
 1459 static   __checkReturn  efx_rc_t
 1460 siena_filter_add(
 1461         __in            efx_nic_t *enp,
 1462         __inout         efx_filter_spec_t *spec,
 1463         __in            boolean_t may_replace)
 1464 {
 1465         efx_rc_t rc;
 1466         siena_filter_spec_t sf_spec;
 1467         siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
 1468         siena_filter_tbl_id_t tbl_id;
 1469         siena_filter_tbl_t *sftp;
 1470         siena_filter_spec_t *saved_sf_spec;
 1471         efx_oword_t filter;
 1472         int filter_idx;
 1473         unsigned int depth;
 1474         efsys_lock_state_t state;
 1475         uint32_t key;
 1476 
 1477         EFSYS_ASSERT3P(spec, !=, NULL);
 1478 
 1479         if ((rc = siena_filter_spec_from_gen_spec(&sf_spec, spec)) != 0)
 1480                 goto fail1;
 1481 
 1482         tbl_id = siena_filter_tbl_id(sf_spec.sfs_type);
 1483         sftp = &sfp->sf_tbl[tbl_id];
 1484 
 1485         if (sftp->sft_size == 0) {
 1486                 rc = EINVAL;
 1487                 goto fail2;
 1488         }
 1489 
 1490         key = siena_filter_build(&filter, &sf_spec);
 1491 
 1492         EFSYS_LOCK(enp->en_eslp, state);
 1493 
 1494         rc = siena_filter_search(sftp, &sf_spec, key, B_TRUE,
 1495             &filter_idx, &depth);
 1496         if (rc != 0)
 1497                 goto fail3;
 1498 
 1499         EFSYS_ASSERT3U(filter_idx, <, sftp->sft_size);
 1500         saved_sf_spec = &sftp->sft_spec[filter_idx];
 1501 
 1502         if (siena_filter_test_used(sftp, filter_idx)) {
 1503                 if (may_replace == B_FALSE) {
 1504                         rc = EEXIST;
 1505                         goto fail4;
 1506                 }
 1507         }
 1508         siena_filter_set_used(sftp, filter_idx);
 1509         *saved_sf_spec = sf_spec;
 1510 
 1511         if (sfp->sf_depth[sf_spec.sfs_type] < depth) {
 1512                 sfp->sf_depth[sf_spec.sfs_type] = depth;
 1513                 if (tbl_id == EFX_SIENA_FILTER_TBL_TX_IP ||
 1514                     tbl_id == EFX_SIENA_FILTER_TBL_TX_MAC)
 1515                         siena_filter_push_tx_limits(enp);
 1516                 else
 1517                         siena_filter_push_rx_limits(enp);
 1518         }
 1519 
 1520         siena_filter_push_entry(enp, sf_spec.sfs_type,
 1521             filter_idx, &filter);
 1522 
 1523         EFSYS_UNLOCK(enp->en_eslp, state);
 1524         return (0);
 1525 
 1526 fail4:
 1527         EFSYS_PROBE(fail4);
 1528 
 1529 fail3:
 1530         EFSYS_UNLOCK(enp->en_eslp, state);
 1531         EFSYS_PROBE(fail3);
 1532 
 1533 fail2:
 1534         EFSYS_PROBE(fail2);
 1535 
 1536 fail1:
 1537         EFSYS_PROBE1(fail1, efx_rc_t, rc);
 1538         return (rc);
 1539 }
 1540 
 1541 static   __checkReturn  efx_rc_t
 1542 siena_filter_delete(
 1543         __in            efx_nic_t *enp,
 1544         __inout         efx_filter_spec_t *spec)
 1545 {
 1546         efx_rc_t rc;
 1547         siena_filter_spec_t sf_spec;
 1548         siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
 1549         siena_filter_tbl_id_t tbl_id;
 1550         siena_filter_tbl_t *sftp;
 1551         efx_oword_t filter;
 1552         int filter_idx;
 1553         unsigned int depth;
 1554         efsys_lock_state_t state;
 1555         uint32_t key;
 1556 
 1557         EFSYS_ASSERT3P(spec, !=, NULL);
 1558 
 1559         if ((rc = siena_filter_spec_from_gen_spec(&sf_spec, spec)) != 0)
 1560                 goto fail1;
 1561 
 1562         tbl_id = siena_filter_tbl_id(sf_spec.sfs_type);
 1563         sftp = &sfp->sf_tbl[tbl_id];
 1564 
 1565         key = siena_filter_build(&filter, &sf_spec);
 1566 
 1567         EFSYS_LOCK(enp->en_eslp, state);
 1568 
 1569         rc = siena_filter_search(sftp, &sf_spec, key, B_FALSE,
 1570             &filter_idx, &depth);
 1571         if (rc != 0)
 1572                 goto fail2;
 1573 
 1574         siena_filter_clear_entry(enp, sftp, filter_idx);
 1575         if (sftp->sft_used == 0)
 1576                 siena_filter_reset_search_depth(sfp, tbl_id);
 1577 
 1578         EFSYS_UNLOCK(enp->en_eslp, state);
 1579         return (0);
 1580 
 1581 fail2:
 1582         EFSYS_UNLOCK(enp->en_eslp, state);
 1583         EFSYS_PROBE(fail2);
 1584 
 1585 fail1:
 1586         EFSYS_PROBE1(fail1, efx_rc_t, rc);
 1587         return (rc);
 1588 }
 1589 
 1590 #define SIENA_MAX_SUPPORTED_MATCHES 4
 1591 
 1592 static  __checkReturn   efx_rc_t
 1593 siena_filter_supported_filters(
 1594         __in                            efx_nic_t *enp,
 1595         __out_ecount(buffer_length)     uint32_t *buffer,
 1596         __in                            size_t buffer_length,
 1597         __out                           size_t *list_lengthp)
 1598 {
 1599         uint32_t index = 0;
 1600         uint32_t rx_matches[SIENA_MAX_SUPPORTED_MATCHES];
 1601         size_t list_length;
 1602         efx_rc_t rc;
 1603 
 1604         rx_matches[index++] =
 1605             EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
 1606             EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT |
 1607             EFX_FILTER_MATCH_REM_HOST | EFX_FILTER_MATCH_REM_PORT;
 1608 
 1609         rx_matches[index++] =
 1610             EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
 1611             EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT;
 1612 
 1613         if (enp->en_features & EFX_FEATURE_MAC_HEADER_FILTERS) {
 1614                 rx_matches[index++] =
 1615                     EFX_FILTER_MATCH_OUTER_VID | EFX_FILTER_MATCH_LOC_MAC;
 1616 
 1617                 rx_matches[index++] = EFX_FILTER_MATCH_LOC_MAC;
 1618         }
 1619 
 1620         EFSYS_ASSERT3U(index, <=, SIENA_MAX_SUPPORTED_MATCHES);
 1621         list_length = index;
 1622 
 1623         *list_lengthp = list_length;
 1624 
 1625         if (buffer_length < list_length) {
 1626                 rc = ENOSPC;
 1627                 goto fail1;
 1628         }
 1629 
 1630         memcpy(buffer, rx_matches, list_length * sizeof (rx_matches[0]));
 1631 
 1632         return (0);
 1633 
 1634 fail1:
 1635         EFSYS_PROBE1(fail1, efx_rc_t, rc);
 1636 
 1637         return (rc);
 1638 }
 1639 
 1640 #undef MAX_SUPPORTED
 1641 
 1642 #endif /* EFSYS_OPT_SIENA */
 1643 
 1644 #endif /* EFSYS_OPT_FILTER */

Cache object: 3f74bd0eef1cfcf4ae35198165f00c41


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