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/cxgbe/t4_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) 2018 Chelsio 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
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  */
   28 #include <sys/cdefs.h>
   29 __FBSDID("$FreeBSD$");
   30 
   31 #include "opt_inet.h"
   32 #include "opt_inet6.h"
   33 
   34 #include <sys/param.h>
   35 #include <sys/eventhandler.h>
   36 #include <sys/fnv_hash.h>
   37 #include <sys/systm.h>
   38 #include <sys/kernel.h>
   39 #include <sys/module.h>
   40 #include <sys/bus.h>
   41 #include <sys/lock.h>
   42 #include <sys/mutex.h>
   43 #include <sys/rwlock.h>
   44 #include <sys/socket.h>
   45 #include <sys/sbuf.h>
   46 #include <netinet/in.h>
   47 
   48 #include "common/common.h"
   49 #include "common/t4_msg.h"
   50 #include "common/t4_regs.h"
   51 #include "common/t4_regs_values.h"
   52 #include "common/t4_tcb.h"
   53 #include "t4_l2t.h"
   54 #include "t4_smt.h"
   55 
   56 struct filter_entry {
   57         LIST_ENTRY(filter_entry) link_4t;
   58         LIST_ENTRY(filter_entry) link_tid;
   59 
   60         uint32_t valid:1;       /* filter allocated and valid */
   61         uint32_t locked:1;      /* filter is administratively locked or busy */
   62         uint32_t pending:1;     /* filter action is pending firmware reply */
   63         int tid;                /* tid of the filter TCB */
   64         struct l2t_entry *l2te; /* L2 table entry for DMAC rewrite */
   65         struct smt_entry *smt;  /* SMT entry for SMAC rewrite */
   66 
   67         struct t4_filter_specification fs;
   68 };
   69 
   70 static void free_filter_resources(struct filter_entry *);
   71 static int get_tcamfilter(struct adapter *, struct t4_filter *);
   72 static int get_hashfilter(struct adapter *, struct t4_filter *);
   73 static int set_hashfilter(struct adapter *, struct t4_filter *, uint64_t,
   74     struct l2t_entry *, struct smt_entry *);
   75 static int del_hashfilter(struct adapter *, struct t4_filter *);
   76 static int configure_hashfilter_tcb(struct adapter *, struct filter_entry *);
   77 
   78 static inline bool
   79 separate_hpfilter_region(struct adapter *sc)
   80 {
   81 
   82         return (chip_id(sc) >= CHELSIO_T6);
   83 }
   84 
   85 static inline uint32_t
   86 hf_hashfn_4t(struct t4_filter_specification *fs)
   87 {
   88         struct t4_filter_tuple *ft = &fs->val;
   89         uint32_t hash;
   90 
   91         if (fs->type) {
   92                 /* IPv6 */
   93                 hash = fnv_32_buf(&ft->sip[0], 16, FNV1_32_INIT);
   94                 hash = fnv_32_buf(&ft->dip[0], 16, hash);
   95         } else {
   96                 hash = fnv_32_buf(&ft->sip[0], 4, FNV1_32_INIT);
   97                 hash = fnv_32_buf(&ft->dip[0], 4, hash);
   98         }
   99         hash = fnv_32_buf(&ft->sport, sizeof(ft->sport), hash);
  100         hash = fnv_32_buf(&ft->dport, sizeof(ft->dport), hash);
  101 
  102         return (hash);
  103 }
  104 
  105 static inline uint32_t
  106 hf_hashfn_tid(int tid)
  107 {
  108 
  109         return (fnv_32_buf(&tid, sizeof(tid), FNV1_32_INIT));
  110 }
  111 
  112 static int
  113 alloc_hftid_hash(struct tid_info *t, int flags)
  114 {
  115         int n;
  116 
  117         MPASS(t->ntids > 0);
  118         MPASS(t->hftid_hash_4t == NULL);
  119         MPASS(t->hftid_hash_tid == NULL);
  120 
  121         n = max(t->ntids / 1024, 16);
  122         t->hftid_hash_4t = hashinit_flags(n, M_CXGBE, &t->hftid_4t_mask, flags);
  123         if (t->hftid_hash_4t == NULL)
  124                 return (ENOMEM);
  125         t->hftid_hash_tid = hashinit_flags(n, M_CXGBE, &t->hftid_tid_mask,
  126             flags);
  127         if (t->hftid_hash_tid == NULL) {
  128                 hashdestroy(t->hftid_hash_4t, M_CXGBE, t->hftid_4t_mask);
  129                 t->hftid_hash_4t = NULL;
  130                 return (ENOMEM);
  131         }
  132 
  133         mtx_init(&t->hftid_lock, "T4 hashfilters", 0, MTX_DEF);
  134         cv_init(&t->hftid_cv, "t4hfcv");
  135 
  136         return (0);
  137 }
  138 
  139 void
  140 free_hftid_hash(struct tid_info *t)
  141 {
  142         struct filter_entry *f, *ftmp;
  143         LIST_HEAD(, filter_entry) *head;
  144         int i;
  145 #ifdef INVARIANTS
  146         int n = 0;
  147 #endif
  148 
  149         if (t->tids_in_use > 0) {
  150                 /* Remove everything from the tid hash. */
  151                 head = t->hftid_hash_tid;
  152                 for (i = 0; i <= t->hftid_tid_mask; i++) {
  153                         LIST_FOREACH_SAFE(f, &head[i], link_tid, ftmp) {
  154                                 LIST_REMOVE(f, link_tid);
  155                         }
  156                 }
  157 
  158                 /* Remove and then free each filter in the 4t hash. */
  159                 head = t->hftid_hash_4t;
  160                 for (i = 0; i <= t->hftid_4t_mask; i++) {
  161                         LIST_FOREACH_SAFE(f, &head[i], link_4t, ftmp) {
  162 #ifdef INVARIANTS
  163                                 n += f->fs.type ? 2 : 1;
  164 #endif
  165                                 LIST_REMOVE(f, link_4t);
  166                                 free(f, M_CXGBE);
  167                         }
  168                 }
  169                 MPASS(t->tids_in_use == n);
  170                 t->tids_in_use = 0;
  171         }
  172 
  173         if (t->hftid_hash_4t) {
  174                 hashdestroy(t->hftid_hash_4t, M_CXGBE, t->hftid_4t_mask);
  175                 t->hftid_hash_4t = NULL;
  176         }
  177         if (t->hftid_hash_tid) {
  178                 hashdestroy(t->hftid_hash_tid, M_CXGBE, t->hftid_tid_mask);
  179                 t->hftid_hash_tid = NULL;
  180         }
  181         if (mtx_initialized(&t->hftid_lock)) {
  182                 mtx_destroy(&t->hftid_lock);
  183                 cv_destroy(&t->hftid_cv);
  184         }
  185 }
  186 
  187 static void
  188 insert_hf(struct adapter *sc, struct filter_entry *f, uint32_t hash)
  189 {
  190         struct tid_info *t = &sc->tids;
  191         LIST_HEAD(, filter_entry) *head = t->hftid_hash_4t;
  192 
  193         MPASS(head != NULL);
  194         if (hash == 0)
  195                 hash = hf_hashfn_4t(&f->fs);
  196         LIST_INSERT_HEAD(&head[hash & t->hftid_4t_mask], f, link_4t);
  197         atomic_add_int(&t->tids_in_use, f->fs.type ? 2 : 1);
  198 }
  199 
  200 static void
  201 insert_hftid(struct adapter *sc, struct filter_entry *f)
  202 {
  203         struct tid_info *t = &sc->tids;
  204         LIST_HEAD(, filter_entry) *head = t->hftid_hash_tid;
  205         uint32_t hash;
  206 
  207         MPASS(f->tid >= t->tid_base);
  208         MPASS(f->tid - t->tid_base < t->ntids);
  209         mtx_assert(&t->hftid_lock, MA_OWNED);
  210 
  211         hash = hf_hashfn_tid(f->tid);
  212         LIST_INSERT_HEAD(&head[hash & t->hftid_tid_mask], f, link_tid);
  213 }
  214 
  215 static bool
  216 filter_eq(struct t4_filter_specification *fs1,
  217     struct t4_filter_specification *fs2)
  218 {
  219         int n;
  220 
  221         MPASS(fs1->hash && fs2->hash);
  222 
  223         if (fs1->type != fs2->type)
  224                 return (false);
  225 
  226         n = fs1->type ? 16 : 4;
  227         if (bcmp(&fs1->val.sip[0], &fs2->val.sip[0], n) ||
  228             bcmp(&fs1->val.dip[0], &fs2->val.dip[0], n) ||
  229             fs1->val.sport != fs2->val.sport ||
  230             fs1->val.dport != fs2->val.dport)
  231                 return (false);
  232 
  233         /*
  234          * We know the masks are the same because all hashfilters conform to the
  235          * global tp->filter_mask and the driver has verified that already.
  236          */
  237 
  238         if ((fs1->mask.pfvf_vld || fs1->mask.ovlan_vld) &&
  239             fs1->val.vnic != fs2->val.vnic)
  240                 return (false);
  241         if (fs1->mask.vlan_vld && fs1->val.vlan != fs2->val.vlan)
  242                 return (false);
  243         if (fs1->mask.macidx && fs1->val.macidx != fs2->val.macidx)
  244                 return (false);
  245         if (fs1->mask.frag && fs1->val.frag != fs2->val.frag)
  246                 return (false);
  247         if (fs1->mask.matchtype && fs1->val.matchtype != fs2->val.matchtype)
  248                 return (false);
  249         if (fs1->mask.iport && fs1->val.iport != fs2->val.iport)
  250                 return (false);
  251         if (fs1->mask.fcoe && fs1->val.fcoe != fs2->val.fcoe)
  252                 return (false);
  253         if (fs1->mask.proto && fs1->val.proto != fs2->val.proto)
  254                 return (false);
  255         if (fs1->mask.tos && fs1->val.tos != fs2->val.tos)
  256                 return (false);
  257         if (fs1->mask.ethtype && fs1->val.ethtype != fs2->val.ethtype)
  258                 return (false);
  259 
  260         return (true);
  261 }
  262 
  263 static struct filter_entry *
  264 lookup_hf(struct adapter *sc, struct t4_filter_specification *fs, uint32_t hash)
  265 {
  266         struct tid_info *t = &sc->tids;
  267         LIST_HEAD(, filter_entry) *head = t->hftid_hash_4t;
  268         struct filter_entry *f;
  269 
  270         mtx_assert(&t->hftid_lock, MA_OWNED);
  271         MPASS(head != NULL);
  272 
  273         if (hash == 0)
  274                 hash = hf_hashfn_4t(fs);
  275 
  276         LIST_FOREACH(f, &head[hash & t->hftid_4t_mask], link_4t) {
  277                 if (filter_eq(&f->fs, fs))
  278                         return (f);
  279         }
  280 
  281         return (NULL);
  282 }
  283 
  284 static struct filter_entry *
  285 lookup_hftid(struct adapter *sc, int tid)
  286 {
  287         struct tid_info *t = &sc->tids;
  288         LIST_HEAD(, filter_entry) *head = t->hftid_hash_tid;
  289         struct filter_entry *f;
  290         uint32_t hash;
  291 
  292         mtx_assert(&t->hftid_lock, MA_OWNED);
  293         MPASS(head != NULL);
  294 
  295         hash = hf_hashfn_tid(tid);
  296         LIST_FOREACH(f, &head[hash & t->hftid_tid_mask], link_tid) {
  297                 if (f->tid == tid)
  298                         return (f);
  299         }
  300 
  301         return (NULL);
  302 }
  303 
  304 static void
  305 remove_hf(struct adapter *sc, struct filter_entry *f)
  306 {
  307         struct tid_info *t = &sc->tids;
  308 
  309         mtx_assert(&t->hftid_lock, MA_OWNED);
  310 
  311         LIST_REMOVE(f, link_4t);
  312         atomic_subtract_int(&t->tids_in_use, f->fs.type ? 2 : 1);
  313 }
  314 
  315 static void
  316 remove_hftid(struct adapter *sc, struct filter_entry *f)
  317 {
  318 #ifdef INVARIANTS
  319         struct tid_info *t = &sc->tids;
  320 
  321         mtx_assert(&t->hftid_lock, MA_OWNED);
  322 #endif
  323 
  324         LIST_REMOVE(f, link_tid);
  325 }
  326 
  327 /*
  328  * Input: driver's 32b filter mode.
  329  * Returns: hardware filter mode (bits to set in vlan_pri_map) for the input.
  330  */
  331 static uint16_t
  332 mode_to_fconf(uint32_t mode)
  333 {
  334         uint32_t fconf = 0;
  335 
  336         if (mode & T4_FILTER_IP_FRAGMENT)
  337                 fconf |= F_FRAGMENTATION;
  338 
  339         if (mode & T4_FILTER_MPS_HIT_TYPE)
  340                 fconf |= F_MPSHITTYPE;
  341 
  342         if (mode & T4_FILTER_MAC_IDX)
  343                 fconf |= F_MACMATCH;
  344 
  345         if (mode & T4_FILTER_ETH_TYPE)
  346                 fconf |= F_ETHERTYPE;
  347 
  348         if (mode & T4_FILTER_IP_PROTO)
  349                 fconf |= F_PROTOCOL;
  350 
  351         if (mode & T4_FILTER_IP_TOS)
  352                 fconf |= F_TOS;
  353 
  354         if (mode & T4_FILTER_VLAN)
  355                 fconf |= F_VLAN;
  356 
  357         if (mode & T4_FILTER_VNIC)
  358                 fconf |= F_VNIC_ID;
  359 
  360         if (mode & T4_FILTER_PORT)
  361                 fconf |= F_PORT;
  362 
  363         if (mode & T4_FILTER_FCoE)
  364                 fconf |= F_FCOE;
  365 
  366         return (fconf);
  367 }
  368 
  369 /*
  370  * Input: driver's 32b filter mode.
  371  * Returns: hardware vnic mode (ingress config) matching the input.
  372  */
  373 static int
  374 mode_to_iconf(uint32_t mode)
  375 {
  376         if ((mode & T4_FILTER_VNIC) == 0)
  377                 return (-1);    /* ingress config doesn't matter. */
  378 
  379         if (mode & T4_FILTER_IC_VNIC)
  380                 return (FW_VNIC_MODE_PF_VF);
  381         else if (mode & T4_FILTER_IC_ENCAP)
  382                 return (FW_VNIC_MODE_ENCAP_EN);
  383         else
  384                 return (FW_VNIC_MODE_OUTER_VLAN);
  385 }
  386 
  387 static int
  388 check_fspec_against_fconf_iconf(struct adapter *sc,
  389     struct t4_filter_specification *fs)
  390 {
  391         struct tp_params *tpp = &sc->params.tp;
  392         uint32_t fconf = 0;
  393 
  394         if (fs->val.frag || fs->mask.frag)
  395                 fconf |= F_FRAGMENTATION;
  396 
  397         if (fs->val.matchtype || fs->mask.matchtype)
  398                 fconf |= F_MPSHITTYPE;
  399 
  400         if (fs->val.macidx || fs->mask.macidx)
  401                 fconf |= F_MACMATCH;
  402 
  403         if (fs->val.ethtype || fs->mask.ethtype)
  404                 fconf |= F_ETHERTYPE;
  405 
  406         if (fs->val.proto || fs->mask.proto)
  407                 fconf |= F_PROTOCOL;
  408 
  409         if (fs->val.tos || fs->mask.tos)
  410                 fconf |= F_TOS;
  411 
  412         if (fs->val.vlan_vld || fs->mask.vlan_vld)
  413                 fconf |= F_VLAN;
  414 
  415         if (fs->val.ovlan_vld || fs->mask.ovlan_vld) {
  416                 if (tpp->vnic_mode != FW_VNIC_MODE_OUTER_VLAN)
  417                         return (EINVAL);
  418                 fconf |= F_VNIC_ID;
  419         }
  420 
  421         if (fs->val.pfvf_vld || fs->mask.pfvf_vld) {
  422                 if (tpp->vnic_mode != FW_VNIC_MODE_PF_VF)
  423                         return (EINVAL);
  424                 fconf |= F_VNIC_ID;
  425         }
  426 
  427 #ifdef notyet
  428         if (fs->val.encap_vld || fs->mask.encap_vld) {
  429                 if (tpp->vnic_mode != FW_VNIC_MODE_ENCAP_EN);
  430                         return (EINVAL);
  431                 fconf |= F_VNIC_ID;
  432         }
  433 #endif
  434 
  435         if (fs->val.iport || fs->mask.iport)
  436                 fconf |= F_PORT;
  437 
  438         if (fs->val.fcoe || fs->mask.fcoe)
  439                 fconf |= F_FCOE;
  440 
  441         if ((tpp->filter_mode | fconf) != tpp->filter_mode)
  442                 return (E2BIG);
  443 
  444         return (0);
  445 }
  446 
  447 /*
  448  * Input: hardware filter configuration (filter mode/mask, ingress config).
  449  * Input: driver's 32b filter mode matching the input.
  450  */
  451 static uint32_t
  452 fconf_to_mode(uint16_t hwmode, int vnic_mode)
  453 {
  454         uint32_t mode = T4_FILTER_IPv4 | T4_FILTER_IPv6 | T4_FILTER_IP_SADDR |
  455             T4_FILTER_IP_DADDR | T4_FILTER_IP_SPORT | T4_FILTER_IP_DPORT;
  456 
  457         if (hwmode & F_FRAGMENTATION)
  458                 mode |= T4_FILTER_IP_FRAGMENT;
  459         if (hwmode & F_MPSHITTYPE)
  460                 mode |= T4_FILTER_MPS_HIT_TYPE;
  461         if (hwmode & F_MACMATCH)
  462                 mode |= T4_FILTER_MAC_IDX;
  463         if (hwmode & F_ETHERTYPE)
  464                 mode |= T4_FILTER_ETH_TYPE;
  465         if (hwmode & F_PROTOCOL)
  466                 mode |= T4_FILTER_IP_PROTO;
  467         if (hwmode & F_TOS)
  468                 mode |= T4_FILTER_IP_TOS;
  469         if (hwmode & F_VLAN)
  470                 mode |= T4_FILTER_VLAN;
  471         if (hwmode & F_VNIC_ID)
  472                 mode |= T4_FILTER_VNIC; /* real meaning depends on vnic_mode. */
  473         if (hwmode & F_PORT)
  474                 mode |= T4_FILTER_PORT;
  475         if (hwmode & F_FCOE)
  476                 mode |= T4_FILTER_FCoE;
  477 
  478         switch (vnic_mode) {
  479         case FW_VNIC_MODE_PF_VF:
  480                 mode |= T4_FILTER_IC_VNIC;
  481                 break;
  482         case FW_VNIC_MODE_ENCAP_EN:
  483                 mode |= T4_FILTER_IC_ENCAP;
  484                 break;
  485         case FW_VNIC_MODE_OUTER_VLAN:
  486         default:
  487                 break;
  488         }
  489 
  490         return (mode);
  491 }
  492 
  493 int
  494 get_filter_mode(struct adapter *sc, uint32_t *mode)
  495 {
  496         struct tp_params *tp = &sc->params.tp;
  497         uint16_t filter_mode;
  498 
  499         /* Filter mask must comply with the global filter mode. */
  500         MPASS((tp->filter_mode | tp->filter_mask) == tp->filter_mode);
  501 
  502         /* Non-zero incoming value in mode means "hashfilter mode". */
  503         filter_mode = *mode ? tp->filter_mask : tp->filter_mode;
  504         *mode = fconf_to_mode(filter_mode, tp->vnic_mode);
  505 
  506         return (0);
  507 }
  508 
  509 int
  510 set_filter_mode(struct adapter *sc, uint32_t mode)
  511 {
  512         struct tp_params *tp = &sc->params.tp;
  513         int rc, iconf;
  514         uint16_t fconf;
  515 
  516         iconf = mode_to_iconf(mode);
  517         fconf = mode_to_fconf(mode);
  518         if ((iconf == -1 || iconf == tp->vnic_mode) && fconf == tp->filter_mode)
  519                 return (0);     /* Nothing to do */
  520 
  521         rc = begin_synchronized_op(sc, NULL, SLEEP_OK | INTR_OK, "t4setfm");
  522         if (rc)
  523                 return (rc);
  524 
  525         if (hw_off_limits(sc)) {
  526                 rc = ENXIO;
  527                 goto done;
  528         }
  529 
  530         if (sc->tids.ftids_in_use > 0 ||        /* TCAM filters active */
  531             sc->tids.hpftids_in_use > 0 ||      /* hi-pri TCAM filters active */
  532             sc->tids.tids_in_use > 0) {         /* TOE or hashfilters active */
  533                 rc = EBUSY;
  534                 goto done;
  535         }
  536 
  537 #ifdef TCP_OFFLOAD
  538         if (uld_active(sc, ULD_TOM)) {
  539                 rc = EBUSY;
  540                 goto done;
  541         }
  542 #endif
  543 
  544         /* Note that filter mask will get clipped to the new filter mode. */
  545         rc = -t4_set_filter_cfg(sc, fconf, -1, iconf);
  546 done:
  547         end_synchronized_op(sc, 0);
  548         return (rc);
  549 }
  550 
  551 int
  552 set_filter_mask(struct adapter *sc, uint32_t mode)
  553 {
  554         struct tp_params *tp = &sc->params.tp;
  555         int rc, iconf;
  556         uint16_t fmask;
  557 
  558         iconf = mode_to_iconf(mode);
  559         fmask = mode_to_fconf(mode);
  560         if ((iconf == -1 || iconf == tp->vnic_mode) && fmask == tp->filter_mask)
  561                 return (0);     /* Nothing to do */
  562 
  563         /*
  564          * We aren't going to change the global filter mode or VNIC mode here.
  565          * The given filter mask must conform to them.
  566          */
  567         if ((fmask | tp->filter_mode) != tp->filter_mode)
  568                 return (EINVAL);
  569         if (iconf != -1 && iconf != tp->vnic_mode)
  570                 return (EINVAL);
  571 
  572         rc = begin_synchronized_op(sc, NULL, SLEEP_OK | INTR_OK, "t4sethfm");
  573         if (rc)
  574                 return (rc);
  575 
  576         if (hw_off_limits(sc)) {
  577                 rc = ENXIO;
  578                 goto done;
  579         }
  580 
  581         if (sc->tids.tids_in_use > 0) {         /* TOE or hashfilters active */
  582                 rc = EBUSY;
  583                 goto done;
  584         }
  585 
  586 #ifdef TCP_OFFLOAD
  587         if (uld_active(sc, ULD_TOM)) {
  588                 rc = EBUSY;
  589                 goto done;
  590         }
  591 #endif
  592         rc = -t4_set_filter_cfg(sc, -1, fmask, -1);
  593 done:
  594         end_synchronized_op(sc, 0);
  595         return (rc);
  596 }
  597 
  598 static inline uint64_t
  599 get_filter_hits(struct adapter *sc, uint32_t tid)
  600 {
  601         uint32_t tcb_addr;
  602         uint64_t hits;
  603 
  604         tcb_addr = t4_read_reg(sc, A_TP_CMM_TCB_BASE) + tid * TCB_SIZE;
  605 
  606         mtx_lock(&sc->reg_lock);
  607         if (hw_off_limits(sc))
  608                 hits = 0;
  609         else if (is_t4(sc)) {
  610                 uint64_t t;
  611 
  612                 read_via_memwin(sc, 0, tcb_addr + 16, (uint32_t *)&t, 8);
  613                 hits = be64toh(t);
  614         } else {
  615                 uint32_t t;
  616 
  617                 read_via_memwin(sc, 0, tcb_addr + 24, &t, 4);
  618                 hits = be32toh(t);
  619         }
  620         mtx_unlock(&sc->reg_lock);
  621 
  622         return (hits);
  623 }
  624 
  625 int
  626 get_filter(struct adapter *sc, struct t4_filter *t)
  627 {
  628         if (t->fs.hash)
  629                 return (get_hashfilter(sc, t));
  630         else
  631                 return (get_tcamfilter(sc, t));
  632 }
  633 
  634 static int
  635 set_tcamfilter(struct adapter *sc, struct t4_filter *t, struct l2t_entry *l2te,
  636     struct smt_entry *smt)
  637 {
  638         struct filter_entry *f;
  639         struct fw_filter2_wr *fwr;
  640         u_int vnic_vld, vnic_vld_mask;
  641         struct wrq_cookie cookie;
  642         int i, rc, busy, locked;
  643         u_int tid;
  644         const int ntids = t->fs.type ? 4 : 1;
  645 
  646         MPASS(!t->fs.hash);
  647         /* Already validated against fconf, iconf */
  648         MPASS((t->fs.val.pfvf_vld & t->fs.val.ovlan_vld) == 0);
  649         MPASS((t->fs.mask.pfvf_vld & t->fs.mask.ovlan_vld) == 0);
  650 
  651         if (separate_hpfilter_region(sc) && t->fs.prio) {
  652                 MPASS(t->idx < sc->tids.nhpftids);
  653                 f = &sc->tids.hpftid_tab[t->idx];
  654                 tid = sc->tids.hpftid_base + t->idx;
  655         } else {
  656                 MPASS(t->idx < sc->tids.nftids);
  657                 f = &sc->tids.ftid_tab[t->idx];
  658                 tid = sc->tids.ftid_base + t->idx;
  659         }
  660         rc = busy = locked = 0;
  661         mtx_lock(&sc->tids.ftid_lock);
  662         for (i = 0; i < ntids; i++) {
  663                 busy += f[i].pending + f[i].valid;
  664                 locked += f[i].locked;
  665         }
  666         if (locked > 0)
  667                 rc = EPERM;
  668         else if (busy > 0)
  669                 rc = EBUSY;
  670         else {
  671                 int len16;
  672 
  673                 if (sc->params.filter2_wr_support)
  674                         len16 = howmany(sizeof(struct fw_filter2_wr), 16);
  675                 else
  676                         len16 = howmany(sizeof(struct fw_filter_wr), 16);
  677                 fwr = start_wrq_wr(&sc->sge.ctrlq[0], len16, &cookie);
  678                 if (__predict_false(fwr == NULL))
  679                         rc = ENOMEM;
  680                 else {
  681                         f->pending = 1;
  682                         if (separate_hpfilter_region(sc) && t->fs.prio)
  683                                 sc->tids.hpftids_in_use++;
  684                         else
  685                                 sc->tids.ftids_in_use++;
  686                 }
  687         }
  688         mtx_unlock(&sc->tids.ftid_lock);
  689         if (rc != 0)
  690                 return (rc);
  691 
  692         /*
  693          * Can't fail now.  A set-filter WR will definitely be sent.
  694          */
  695 
  696         f->tid = tid;
  697         f->fs = t->fs;
  698         f->l2te = l2te;
  699         f->smt = smt;
  700 
  701         if (t->fs.val.pfvf_vld || t->fs.val.ovlan_vld)
  702                 vnic_vld = 1;
  703         else
  704                 vnic_vld = 0;
  705         if (t->fs.mask.pfvf_vld || t->fs.mask.ovlan_vld)
  706                 vnic_vld_mask = 1;
  707         else
  708                 vnic_vld_mask = 0;
  709 
  710         bzero(fwr, sizeof(*fwr));
  711         if (sc->params.filter2_wr_support)
  712                 fwr->op_pkd = htobe32(V_FW_WR_OP(FW_FILTER2_WR));
  713         else
  714                 fwr->op_pkd = htobe32(V_FW_WR_OP(FW_FILTER_WR));
  715         fwr->len16_pkd = htobe32(FW_LEN16(*fwr));
  716         fwr->tid_to_iq =
  717             htobe32(V_FW_FILTER_WR_TID(f->tid) |
  718                 V_FW_FILTER_WR_RQTYPE(f->fs.type) |
  719                 V_FW_FILTER_WR_NOREPLY(0) |
  720                 V_FW_FILTER_WR_IQ(f->fs.iq));
  721         fwr->del_filter_to_l2tix =
  722             htobe32(V_FW_FILTER_WR_RPTTID(f->fs.rpttid) |
  723                 V_FW_FILTER_WR_DROP(f->fs.action == FILTER_DROP) |
  724                 V_FW_FILTER_WR_DIRSTEER(f->fs.dirsteer) |
  725                 V_FW_FILTER_WR_MASKHASH(f->fs.maskhash) |
  726                 V_FW_FILTER_WR_DIRSTEERHASH(f->fs.dirsteerhash) |
  727                 V_FW_FILTER_WR_LPBK(f->fs.action == FILTER_SWITCH) |
  728                 V_FW_FILTER_WR_DMAC(f->fs.newdmac) |
  729                 V_FW_FILTER_WR_SMAC(f->fs.newsmac) |
  730                 V_FW_FILTER_WR_INSVLAN(f->fs.newvlan == VLAN_INSERT ||
  731                     f->fs.newvlan == VLAN_REWRITE) |
  732                 V_FW_FILTER_WR_RMVLAN(f->fs.newvlan == VLAN_REMOVE ||
  733                     f->fs.newvlan == VLAN_REWRITE) |
  734                 V_FW_FILTER_WR_HITCNTS(f->fs.hitcnts) |
  735                 V_FW_FILTER_WR_TXCHAN(f->fs.eport) |
  736                 V_FW_FILTER_WR_PRIO(f->fs.prio) |
  737                 V_FW_FILTER_WR_L2TIX(f->l2te ? f->l2te->idx : 0));
  738         fwr->ethtype = htobe16(f->fs.val.ethtype);
  739         fwr->ethtypem = htobe16(f->fs.mask.ethtype);
  740         fwr->frag_to_ovlan_vldm =
  741             (V_FW_FILTER_WR_FRAG(f->fs.val.frag) |
  742                 V_FW_FILTER_WR_FRAGM(f->fs.mask.frag) |
  743                 V_FW_FILTER_WR_IVLAN_VLD(f->fs.val.vlan_vld) |
  744                 V_FW_FILTER_WR_OVLAN_VLD(vnic_vld) |
  745                 V_FW_FILTER_WR_IVLAN_VLDM(f->fs.mask.vlan_vld) |
  746                 V_FW_FILTER_WR_OVLAN_VLDM(vnic_vld_mask));
  747         fwr->smac_sel = 0;
  748         fwr->rx_chan_rx_rpl_iq = htobe16(V_FW_FILTER_WR_RX_CHAN(0) |
  749             V_FW_FILTER_WR_RX_RPL_IQ(sc->sge.fwq.abs_id));
  750         fwr->maci_to_matchtypem =
  751             htobe32(V_FW_FILTER_WR_MACI(f->fs.val.macidx) |
  752                 V_FW_FILTER_WR_MACIM(f->fs.mask.macidx) |
  753                 V_FW_FILTER_WR_FCOE(f->fs.val.fcoe) |
  754                 V_FW_FILTER_WR_FCOEM(f->fs.mask.fcoe) |
  755                 V_FW_FILTER_WR_PORT(f->fs.val.iport) |
  756                 V_FW_FILTER_WR_PORTM(f->fs.mask.iport) |
  757                 V_FW_FILTER_WR_MATCHTYPE(f->fs.val.matchtype) |
  758                 V_FW_FILTER_WR_MATCHTYPEM(f->fs.mask.matchtype));
  759         fwr->ptcl = f->fs.val.proto;
  760         fwr->ptclm = f->fs.mask.proto;
  761         fwr->ttyp = f->fs.val.tos;
  762         fwr->ttypm = f->fs.mask.tos;
  763         fwr->ivlan = htobe16(f->fs.val.vlan);
  764         fwr->ivlanm = htobe16(f->fs.mask.vlan);
  765         fwr->ovlan = htobe16(f->fs.val.vnic);
  766         fwr->ovlanm = htobe16(f->fs.mask.vnic);
  767         bcopy(f->fs.val.dip, fwr->lip, sizeof (fwr->lip));
  768         bcopy(f->fs.mask.dip, fwr->lipm, sizeof (fwr->lipm));
  769         bcopy(f->fs.val.sip, fwr->fip, sizeof (fwr->fip));
  770         bcopy(f->fs.mask.sip, fwr->fipm, sizeof (fwr->fipm));
  771         fwr->lp = htobe16(f->fs.val.dport);
  772         fwr->lpm = htobe16(f->fs.mask.dport);
  773         fwr->fp = htobe16(f->fs.val.sport);
  774         fwr->fpm = htobe16(f->fs.mask.sport);
  775         /* sma = 0 tells the fw to use SMAC_SEL for source MAC address */
  776         bzero(fwr->sma, sizeof (fwr->sma));
  777         if (sc->params.filter2_wr_support) {
  778                 fwr->filter_type_swapmac =
  779                     V_FW_FILTER2_WR_SWAPMAC(f->fs.swapmac);
  780                 fwr->natmode_to_ulp_type =
  781                     V_FW_FILTER2_WR_ULP_TYPE(f->fs.nat_mode ?
  782                         ULP_MODE_TCPDDP : ULP_MODE_NONE) |
  783                     V_FW_FILTER2_WR_NATFLAGCHECK(f->fs.nat_flag_chk) |
  784                     V_FW_FILTER2_WR_NATMODE(f->fs.nat_mode);
  785                 memcpy(fwr->newlip, f->fs.nat_dip, sizeof(fwr->newlip));
  786                 memcpy(fwr->newfip, f->fs.nat_sip, sizeof(fwr->newfip));
  787                 fwr->newlport = htobe16(f->fs.nat_dport);
  788                 fwr->newfport = htobe16(f->fs.nat_sport);
  789                 fwr->natseqcheck = htobe32(f->fs.nat_seq_chk);
  790         }
  791         commit_wrq_wr(&sc->sge.ctrlq[0], fwr, &cookie);
  792 
  793         /* Wait for response. */
  794         mtx_lock(&sc->tids.ftid_lock);
  795         for (;;) {
  796                 if (f->pending == 0) {
  797                         rc = f->valid ? 0 : EIO;
  798                         break;
  799                 }
  800                 if (cv_wait_sig(&sc->tids.ftid_cv, &sc->tids.ftid_lock) != 0) {
  801                         rc = EINPROGRESS;
  802                         break;
  803                 }
  804         }
  805         mtx_unlock(&sc->tids.ftid_lock);
  806         return (rc);
  807 }
  808 
  809 static int
  810 hashfilter_ntuple(struct adapter *sc, const struct t4_filter_specification *fs,
  811     uint64_t *ftuple)
  812 {
  813         struct tp_params *tp = &sc->params.tp;
  814         uint16_t fmask;
  815 
  816         *ftuple = fmask = 0;
  817 
  818         /*
  819          * Initialize each of the fields which we care about which are present
  820          * in the Compressed Filter Tuple.
  821          */
  822         if (tp->vlan_shift >= 0 && fs->mask.vlan) {
  823                 *ftuple |= (uint64_t)(F_FT_VLAN_VLD | fs->val.vlan) <<
  824                     tp->vlan_shift;
  825                 fmask |= F_VLAN;
  826         }
  827 
  828         if (tp->port_shift >= 0 && fs->mask.iport) {
  829                 *ftuple |= (uint64_t)fs->val.iport << tp->port_shift;
  830                 fmask |= F_PORT;
  831         }
  832 
  833         if (tp->protocol_shift >= 0 && fs->mask.proto) {
  834                 *ftuple |= (uint64_t)fs->val.proto << tp->protocol_shift;
  835                 fmask |= F_PROTOCOL;
  836         }
  837 
  838         if (tp->tos_shift >= 0 && fs->mask.tos) {
  839                 *ftuple |= (uint64_t)(fs->val.tos) << tp->tos_shift;
  840                 fmask |= F_TOS;
  841         }
  842 
  843         if (tp->vnic_shift >= 0 && fs->mask.vnic) {
  844                 /* vnic_mode was already validated. */
  845                 if (tp->vnic_mode == FW_VNIC_MODE_PF_VF)
  846                         MPASS(fs->mask.pfvf_vld);
  847                 else if (tp->vnic_mode == FW_VNIC_MODE_OUTER_VLAN)
  848                         MPASS(fs->mask.ovlan_vld);
  849 #ifdef notyet
  850                 else if (tp->vnic_mode == FW_VNIC_MODE_ENCAP_EN)
  851                         MPASS(fs->mask.encap_vld);
  852 #endif
  853                 *ftuple |= ((1ULL << 16) | fs->val.vnic) << tp->vnic_shift;
  854                 fmask |= F_VNIC_ID;
  855         }
  856 
  857         if (tp->macmatch_shift >= 0 && fs->mask.macidx) {
  858                 *ftuple |= (uint64_t)(fs->val.macidx) << tp->macmatch_shift;
  859                 fmask |= F_MACMATCH;
  860         }
  861 
  862         if (tp->ethertype_shift >= 0 && fs->mask.ethtype) {
  863                 *ftuple |= (uint64_t)(fs->val.ethtype) << tp->ethertype_shift;
  864                 fmask |= F_ETHERTYPE;
  865         }
  866 
  867         if (tp->matchtype_shift >= 0 && fs->mask.matchtype) {
  868                 *ftuple |= (uint64_t)(fs->val.matchtype) << tp->matchtype_shift;
  869                 fmask |= F_MPSHITTYPE;
  870         }
  871 
  872         if (tp->frag_shift >= 0 && fs->mask.frag) {
  873                 *ftuple |= (uint64_t)(fs->val.frag) << tp->frag_shift;
  874                 fmask |= F_FRAGMENTATION;
  875         }
  876 
  877         if (tp->fcoe_shift >= 0 && fs->mask.fcoe) {
  878                 *ftuple |= (uint64_t)(fs->val.fcoe) << tp->fcoe_shift;
  879                 fmask |= F_FCOE;
  880         }
  881 
  882         /* A hashfilter must conform to the hardware filter mask. */
  883         if (fmask != tp->filter_mask)
  884                 return (EINVAL);
  885 
  886         return (0);
  887 }
  888 
  889 static bool
  890 is_4tuple_specified(struct t4_filter_specification *fs)
  891 {
  892         int i;
  893         const int n = fs->type ? 16 : 4;
  894 
  895         if (fs->mask.sport != 0xffff || fs->mask.dport != 0xffff)
  896                 return (false);
  897 
  898         for (i = 0; i < n; i++) {
  899                 if (fs->mask.sip[i] != 0xff)
  900                         return (false);
  901                 if (fs->mask.dip[i] != 0xff)
  902                         return (false);
  903         }
  904 
  905         return (true);
  906 }
  907 
  908 int
  909 set_filter(struct adapter *sc, struct t4_filter *t)
  910 {
  911         struct tid_info *ti = &sc->tids;
  912         struct l2t_entry *l2te = NULL;
  913         struct smt_entry *smt = NULL;
  914         uint64_t ftuple;
  915         int rc;
  916 
  917         /*
  918          * Basic filter checks first.
  919          */
  920 
  921         if (t->fs.hash) {
  922                 if (!is_hashfilter(sc) || ti->ntids == 0)
  923                         return (ENOTSUP);
  924                 /* Hardware, not user, selects a tid for hashfilters. */
  925                 if (t->idx != (uint32_t)-1)
  926                         return (EINVAL);
  927                 /* T5 can't count hashfilter hits. */
  928                 if (is_t5(sc) && t->fs.hitcnts)
  929                         return (EINVAL);
  930                 if (!is_4tuple_specified(&t->fs))
  931                         return (EINVAL);
  932                 rc = hashfilter_ntuple(sc, &t->fs, &ftuple);
  933                 if (rc != 0)
  934                         return (rc);
  935         } else {
  936                 if (separate_hpfilter_region(sc) && t->fs.prio) {
  937                         if (ti->nhpftids == 0)
  938                                 return (ENOTSUP);
  939                         if (t->idx >= ti->nhpftids)
  940                                 return (EINVAL);
  941                 } else {
  942                         if (ti->nftids == 0)
  943                                 return (ENOTSUP);
  944                         if (t->idx >= ti->nftids)
  945                                 return (EINVAL);
  946                 }
  947                 /* IPv6 filter idx must be 4 aligned */
  948                 if (t->fs.type == 1 &&
  949                     ((t->idx & 0x3) || t->idx + 4 >= ti->nftids))
  950                         return (EINVAL);
  951         }
  952 
  953         /* T4 doesn't support VLAN tag removal or rewrite, swapmac, and NAT. */
  954         if (is_t4(sc) && t->fs.action == FILTER_SWITCH &&
  955             (t->fs.newvlan == VLAN_REMOVE || t->fs.newvlan == VLAN_REWRITE ||
  956             t->fs.swapmac || t->fs.nat_mode))
  957                 return (ENOTSUP);
  958 
  959         if (t->fs.action == FILTER_SWITCH && t->fs.eport >= sc->params.nports)
  960                 return (EINVAL);
  961         if (t->fs.val.iport >= sc->params.nports)
  962                 return (EINVAL);
  963 
  964         /* Can't specify an iqid/rss_info if not steering. */
  965         if (!t->fs.dirsteer && !t->fs.dirsteerhash && !t->fs.maskhash && t->fs.iq)
  966                 return (EINVAL);
  967 
  968         /* Validate against the global filter mode and ingress config */
  969         rc = check_fspec_against_fconf_iconf(sc, &t->fs);
  970         if (rc != 0)
  971                 return (rc);
  972 
  973         /*
  974          * Basic checks passed.  Make sure the queues and tid tables are setup.
  975          */
  976 
  977         rc = begin_synchronized_op(sc, NULL, SLEEP_OK | INTR_OK, "t4setf");
  978         if (rc)
  979                 return (rc);
  980 
  981         if (hw_off_limits(sc)) {
  982                 rc = ENXIO;
  983                 goto done;
  984         }
  985 
  986         if (!(sc->flags & FULL_INIT_DONE) && ((rc = adapter_init(sc)) != 0))
  987                 goto done;
  988 
  989         if (t->fs.hash) {
  990                 if (__predict_false(ti->hftid_hash_4t == NULL)) {
  991                         rc = alloc_hftid_hash(&sc->tids, HASH_NOWAIT);
  992                         if (rc != 0)
  993                                 goto done;
  994                 }
  995         } else if (separate_hpfilter_region(sc) && t->fs.prio &&
  996             __predict_false(ti->hpftid_tab == NULL)) {
  997                 MPASS(ti->nhpftids != 0);
  998                 KASSERT(ti->hpftids_in_use == 0,
  999                     ("%s: no memory allocated but hpftids_in_use is %u",
 1000                     __func__, ti->hpftids_in_use));
 1001                 ti->hpftid_tab = malloc(sizeof(struct filter_entry) *
 1002                     ti->nhpftids, M_CXGBE, M_NOWAIT | M_ZERO);
 1003                 if (ti->hpftid_tab == NULL) {
 1004                         rc = ENOMEM;
 1005                         goto done;
 1006                 }
 1007                 if (!mtx_initialized(&sc->tids.ftid_lock)) {
 1008                         mtx_init(&ti->ftid_lock, "T4 filters", 0, MTX_DEF);
 1009                         cv_init(&ti->ftid_cv, "t4fcv");
 1010                 }
 1011         } else if (__predict_false(ti->ftid_tab == NULL)) {
 1012                 MPASS(ti->nftids != 0);
 1013                 KASSERT(ti->ftids_in_use == 0,
 1014                     ("%s: no memory allocated but ftids_in_use is %u",
 1015                     __func__, ti->ftids_in_use));
 1016                 ti->ftid_tab = malloc(sizeof(struct filter_entry) * ti->nftids,
 1017                     M_CXGBE, M_NOWAIT | M_ZERO);
 1018                 if (ti->ftid_tab == NULL) {
 1019                         rc = ENOMEM;
 1020                         goto done;
 1021                 }
 1022                 if (!mtx_initialized(&sc->tids.ftid_lock)) {
 1023                         mtx_init(&ti->ftid_lock, "T4 filters", 0, MTX_DEF);
 1024                         cv_init(&ti->ftid_cv, "t4fcv");
 1025                 }
 1026         }
 1027 done:
 1028         end_synchronized_op(sc, 0);
 1029         if (rc != 0)
 1030                 return (rc);
 1031 
 1032         /*
 1033          * Allocate L2T entry, SMT entry, etc.
 1034          */
 1035 
 1036         if (t->fs.newdmac || t->fs.newvlan) {
 1037                 /* This filter needs an L2T entry; allocate one. */
 1038                 l2te = t4_l2t_alloc_switching(sc, t->fs.vlan, t->fs.eport,
 1039                     t->fs.dmac);
 1040                 if (__predict_false(l2te == NULL)) {
 1041                         rc = EAGAIN;
 1042                         goto error;
 1043                 }
 1044         }
 1045 
 1046         if (t->fs.newsmac) {
 1047                 /* This filter needs an SMT entry; allocate one. */
 1048                 smt = t4_smt_alloc_switching(sc->smt, t->fs.smac);
 1049                 if (__predict_false(smt == NULL)) {
 1050                         rc = EAGAIN;
 1051                         goto error;
 1052                 }
 1053                 rc = t4_smt_set_switching(sc, smt, 0x0, t->fs.smac);
 1054                 if (rc)
 1055                         goto error;
 1056         }
 1057 
 1058         if (t->fs.hash)
 1059                 rc = set_hashfilter(sc, t, ftuple, l2te, smt);
 1060         else
 1061                 rc = set_tcamfilter(sc, t, l2te, smt);
 1062 
 1063         if (rc != 0 && rc != EINPROGRESS) {
 1064 error:
 1065                 if (l2te)
 1066                         t4_l2t_release(l2te);
 1067                 if (smt)
 1068                         t4_smt_release(smt);
 1069         }
 1070         return (rc);
 1071 }
 1072 
 1073 static int
 1074 del_tcamfilter(struct adapter *sc, struct t4_filter *t)
 1075 {
 1076         struct filter_entry *f;
 1077         struct fw_filter_wr *fwr;
 1078         struct wrq_cookie cookie;
 1079         int rc, nfilters;
 1080 #ifdef INVARIANTS
 1081         u_int tid_base;
 1082 #endif
 1083 
 1084         mtx_lock(&sc->tids.ftid_lock);
 1085         if (separate_hpfilter_region(sc) && t->fs.prio) {
 1086                 nfilters = sc->tids.nhpftids;
 1087                 f = sc->tids.hpftid_tab;
 1088 #ifdef INVARIANTS
 1089                 tid_base = sc->tids.hpftid_base;
 1090 #endif
 1091         } else {
 1092                 nfilters = sc->tids.nftids;
 1093                 f = sc->tids.ftid_tab;
 1094 #ifdef INVARIANTS
 1095                 tid_base = sc->tids.ftid_base;
 1096 #endif
 1097         }
 1098         MPASS(f != NULL);       /* Caller checked this. */
 1099         if (t->idx >= nfilters) {
 1100                 rc = EINVAL;
 1101                 goto done;
 1102         }
 1103         f += t->idx;
 1104 
 1105         if (f->locked) {
 1106                 rc = EPERM;
 1107                 goto done;
 1108         }
 1109         if (f->pending) {
 1110                 rc = EBUSY;
 1111                 goto done;
 1112         }
 1113         if (f->valid == 0) {
 1114                 rc = EINVAL;
 1115                 goto done;
 1116         }
 1117         MPASS(f->tid == tid_base + t->idx);
 1118         fwr = start_wrq_wr(&sc->sge.ctrlq[0], howmany(sizeof(*fwr), 16), &cookie);
 1119         if (fwr == NULL) {
 1120                 rc = ENOMEM;
 1121                 goto done;
 1122         }
 1123 
 1124         bzero(fwr, sizeof (*fwr));
 1125         t4_mk_filtdelwr(f->tid, fwr, sc->sge.fwq.abs_id);
 1126         f->pending = 1;
 1127         commit_wrq_wr(&sc->sge.ctrlq[0], fwr, &cookie);
 1128         t->fs = f->fs;  /* extra info for the caller */
 1129 
 1130         for (;;) {
 1131                 if (f->pending == 0) {
 1132                         rc = f->valid ? EIO : 0;
 1133                         break;
 1134                 }
 1135                 if (cv_wait_sig(&sc->tids.ftid_cv, &sc->tids.ftid_lock) != 0) {
 1136                         rc = EINPROGRESS;
 1137                         break;
 1138                 }
 1139         }
 1140 done:
 1141         mtx_unlock(&sc->tids.ftid_lock);
 1142         return (rc);
 1143 }
 1144 
 1145 int
 1146 del_filter(struct adapter *sc, struct t4_filter *t)
 1147 {
 1148 
 1149         /* No filters possible if not initialized yet. */
 1150         if (!(sc->flags & FULL_INIT_DONE))
 1151                 return (EINVAL);
 1152 
 1153         /*
 1154          * The checks for tid tables ensure that the locks that del_* will reach
 1155          * for are initialized.
 1156          */
 1157         if (t->fs.hash) {
 1158                 if (sc->tids.hftid_hash_4t != NULL)
 1159                         return (del_hashfilter(sc, t));
 1160         } else if (separate_hpfilter_region(sc) && t->fs.prio) {
 1161                 if (sc->tids.hpftid_tab != NULL)
 1162                         return (del_tcamfilter(sc, t));
 1163         } else {
 1164                 if (sc->tids.ftid_tab != NULL)
 1165                         return (del_tcamfilter(sc, t));
 1166         }
 1167 
 1168         return (EINVAL);
 1169 }
 1170 
 1171 /*
 1172  * Release secondary resources associated with the filter.
 1173  */
 1174 static void
 1175 free_filter_resources(struct filter_entry *f)
 1176 {
 1177 
 1178         if (f->l2te) {
 1179                 t4_l2t_release(f->l2te);
 1180                 f->l2te = NULL;
 1181         }
 1182         if (f->smt) {
 1183                 t4_smt_release(f->smt);
 1184                 f->smt = NULL;
 1185         }
 1186 }
 1187 
 1188 static int
 1189 set_tcb_field(struct adapter *sc, u_int tid, uint16_t word, uint64_t mask,
 1190     uint64_t val, int no_reply)
 1191 {
 1192         struct wrq_cookie cookie;
 1193         struct cpl_set_tcb_field *req;
 1194 
 1195         req = start_wrq_wr(&sc->sge.ctrlq[0], howmany(sizeof(*req), 16), &cookie);
 1196         if (req == NULL)
 1197                 return (ENOMEM);
 1198         bzero(req, sizeof(*req));
 1199         INIT_TP_WR_MIT_CPL(req, CPL_SET_TCB_FIELD, tid);
 1200         if (no_reply == 0) {
 1201                 req->reply_ctrl = htobe16(V_QUEUENO(sc->sge.fwq.abs_id) |
 1202                     V_NO_REPLY(0));
 1203         } else
 1204                 req->reply_ctrl = htobe16(V_NO_REPLY(1));
 1205         req->word_cookie = htobe16(V_WORD(word) | V_COOKIE(CPL_COOKIE_HASHFILTER));
 1206         req->mask = htobe64(mask);
 1207         req->val = htobe64(val);
 1208         commit_wrq_wr(&sc->sge.ctrlq[0], req, &cookie);
 1209 
 1210         return (0);
 1211 }
 1212 
 1213 /* Set one of the t_flags bits in the TCB. */
 1214 static inline int
 1215 set_tcb_tflag(struct adapter *sc, int tid, u_int bit_pos, u_int val,
 1216     u_int no_reply)
 1217 {
 1218 
 1219         return (set_tcb_field(sc, tid,  W_TCB_T_FLAGS, 1ULL << bit_pos,
 1220             (uint64_t)val << bit_pos, no_reply));
 1221 }
 1222 
 1223 int
 1224 t4_filter_rpl(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
 1225 {
 1226         struct adapter *sc = iq->adapter;
 1227         const struct cpl_set_tcb_rpl *rpl = (const void *)(rss + 1);
 1228         u_int tid = GET_TID(rpl);
 1229         u_int rc, idx;
 1230         struct filter_entry *f;
 1231 
 1232         KASSERT(m == NULL, ("%s: payload with opcode %02x", __func__,
 1233             rss->opcode));
 1234 
 1235 
 1236         if (is_hpftid(sc, tid)) {
 1237                 idx = tid - sc->tids.hpftid_base;
 1238                 f = &sc->tids.hpftid_tab[idx];
 1239         } else if (is_ftid(sc, tid)) {
 1240                 idx = tid - sc->tids.ftid_base;
 1241                 f = &sc->tids.ftid_tab[idx];
 1242         } else
 1243                 panic("%s: FW reply for invalid TID %d.", __func__, tid);
 1244 
 1245         MPASS(f->tid == tid);
 1246         rc = G_COOKIE(rpl->cookie);
 1247 
 1248         mtx_lock(&sc->tids.ftid_lock);
 1249         KASSERT(f->pending, ("%s: reply %d for filter[%u] that isn't pending.",
 1250             __func__, rc, tid));
 1251         switch(rc) {
 1252         case FW_FILTER_WR_FLT_ADDED:
 1253                 /* set-filter succeeded */
 1254                 f->valid = 1;
 1255                 if (f->fs.newsmac) {
 1256                         MPASS(f->smt != NULL);
 1257                         set_tcb_tflag(sc, f->tid, S_TF_CCTRL_CWR, 1, 1);
 1258                         set_tcb_field(sc, f->tid, W_TCB_SMAC_SEL,
 1259                             V_TCB_SMAC_SEL(M_TCB_SMAC_SEL),
 1260                             V_TCB_SMAC_SEL(f->smt->idx), 1);
 1261                         /* XXX: wait for reply to TCB update before !pending */
 1262                 }
 1263                 break;
 1264         case FW_FILTER_WR_FLT_DELETED:
 1265                 /* del-filter succeeded */
 1266                 MPASS(f->valid == 1);
 1267                 f->valid = 0;
 1268                 /* Fall through */
 1269         case FW_FILTER_WR_SMT_TBL_FULL:
 1270                 /* set-filter failed due to lack of SMT space. */
 1271                 MPASS(f->valid == 0);
 1272                 free_filter_resources(f);
 1273                 if (separate_hpfilter_region(sc) && f->fs.prio)
 1274                         sc->tids.hpftids_in_use--;
 1275                 else
 1276                         sc->tids.ftids_in_use--;
 1277                 break;
 1278         case FW_FILTER_WR_SUCCESS:
 1279         case FW_FILTER_WR_EINVAL:
 1280         default:
 1281                 panic("%s: unexpected reply %d for filter[%d].", __func__, rc,
 1282                     idx);
 1283         }
 1284         f->pending = 0;
 1285         cv_broadcast(&sc->tids.ftid_cv);
 1286         mtx_unlock(&sc->tids.ftid_lock);
 1287 
 1288         return (0);
 1289 }
 1290 
 1291 /*
 1292  * This is the reply to the Active Open that created the filter.  Additional TCB
 1293  * updates may be required to complete the filter configuration.
 1294  */
 1295 int
 1296 t4_hashfilter_ao_rpl(struct sge_iq *iq, const struct rss_header *rss,
 1297     struct mbuf *m)
 1298 {
 1299         struct adapter *sc = iq->adapter;
 1300         const struct cpl_act_open_rpl *cpl = (const void *)(rss + 1);
 1301         u_int atid = G_TID_TID(G_AOPEN_ATID(be32toh(cpl->atid_status)));
 1302         u_int status = G_AOPEN_STATUS(be32toh(cpl->atid_status));
 1303         struct filter_entry *f = lookup_atid(sc, atid);
 1304 
 1305         KASSERT(m == NULL, ("%s: wasn't expecting payload", __func__));
 1306 
 1307         mtx_lock(&sc->tids.hftid_lock);
 1308         KASSERT(f->pending, ("%s: hashfilter[%p] isn't pending.", __func__, f));
 1309         KASSERT(f->tid == -1, ("%s: hashfilter[%p] has tid %d already.",
 1310             __func__, f, f->tid));
 1311         if (status == CPL_ERR_NONE) {
 1312                 f->tid = GET_TID(cpl);
 1313                 MPASS(lookup_hftid(sc, f->tid) == NULL);
 1314                 insert_hftid(sc, f);
 1315                 /*
 1316                  * Leave the filter pending until it is fully set up, which will
 1317                  * be indicated by the reply to the last TCB update.  No need to
 1318                  * unblock the ioctl thread either.
 1319                  */
 1320                 if (configure_hashfilter_tcb(sc, f) == EINPROGRESS)
 1321                         goto done;
 1322                 f->valid = 1;
 1323                 f->pending = 0;
 1324         } else {
 1325                 /* provide errno instead of tid to ioctl */
 1326                 f->tid = act_open_rpl_status_to_errno(status);
 1327                 f->valid = 0;
 1328                 f->pending = 0;
 1329                 if (act_open_has_tid(status))
 1330                         release_tid(sc, GET_TID(cpl), &sc->sge.ctrlq[0]);
 1331                 free_filter_resources(f);
 1332                 remove_hf(sc, f);
 1333                 if (f->locked == 0)
 1334                         free(f, M_CXGBE);
 1335         }
 1336         cv_broadcast(&sc->tids.hftid_cv);
 1337 done:
 1338         mtx_unlock(&sc->tids.hftid_lock);
 1339 
 1340         free_atid(sc, atid);
 1341         return (0);
 1342 }
 1343 
 1344 int
 1345 t4_hashfilter_tcb_rpl(struct sge_iq *iq, const struct rss_header *rss,
 1346     struct mbuf *m)
 1347 {
 1348         struct adapter *sc = iq->adapter;
 1349         const struct cpl_set_tcb_rpl *rpl = (const void *)(rss + 1);
 1350         u_int tid = GET_TID(rpl);
 1351         struct filter_entry *f;
 1352 
 1353         mtx_lock(&sc->tids.hftid_lock);
 1354         f = lookup_hftid(sc, tid);
 1355         KASSERT(f->tid == tid, ("%s: filter tid mismatch", __func__));
 1356         KASSERT(f->pending, ("%s: hashfilter %p [%u] isn't pending.", __func__,
 1357             f, tid));
 1358         KASSERT(f->valid == 0, ("%s: hashfilter %p [%u] is valid already.",
 1359             __func__, f, tid));
 1360         f->pending = 0;
 1361         if (rpl->status == 0) {
 1362                 f->valid = 1;
 1363         } else {
 1364                 f->tid = EIO;
 1365                 f->valid = 0;
 1366                 free_filter_resources(f);
 1367                 remove_hftid(sc, f);
 1368                 remove_hf(sc, f);
 1369                 release_tid(sc, tid, &sc->sge.ctrlq[0]);
 1370                 if (f->locked == 0)
 1371                         free(f, M_CXGBE);
 1372         }
 1373         cv_broadcast(&sc->tids.hftid_cv);
 1374         mtx_unlock(&sc->tids.hftid_lock);
 1375 
 1376         return (0);
 1377 }
 1378 
 1379 int
 1380 t4_del_hashfilter_rpl(struct sge_iq *iq, const struct rss_header *rss,
 1381     struct mbuf *m)
 1382 {
 1383         struct adapter *sc = iq->adapter;
 1384         const struct cpl_abort_rpl_rss *cpl = (const void *)(rss + 1);
 1385         unsigned int tid = GET_TID(cpl);
 1386         struct filter_entry *f;
 1387 
 1388         mtx_lock(&sc->tids.hftid_lock);
 1389         f = lookup_hftid(sc, tid);
 1390         KASSERT(f->tid == tid, ("%s: filter tid mismatch", __func__));
 1391         KASSERT(f->pending, ("%s: hashfilter %p [%u] isn't pending.", __func__,
 1392             f, tid));
 1393         KASSERT(f->valid, ("%s: hashfilter %p [%u] isn't valid.", __func__, f,
 1394             tid));
 1395         f->pending = 0;
 1396         if (cpl->status == 0) {
 1397                 f->valid = 0;
 1398                 free_filter_resources(f);
 1399                 remove_hftid(sc, f);
 1400                 remove_hf(sc, f);
 1401                 release_tid(sc, tid, &sc->sge.ctrlq[0]);
 1402                 if (f->locked == 0)
 1403                         free(f, M_CXGBE);
 1404         }
 1405         cv_broadcast(&sc->tids.hftid_cv);
 1406         mtx_unlock(&sc->tids.hftid_lock);
 1407 
 1408         return (0);
 1409 }
 1410 
 1411 static int
 1412 get_tcamfilter(struct adapter *sc, struct t4_filter *t)
 1413 {
 1414         int i, nfilters;
 1415         struct filter_entry *f;
 1416         u_int in_use;
 1417 #ifdef INVARIANTS
 1418         u_int tid_base;
 1419 #endif
 1420 
 1421         MPASS(!t->fs.hash);
 1422 
 1423         if (separate_hpfilter_region(sc) && t->fs.prio) {
 1424                 nfilters = sc->tids.nhpftids;
 1425                 f = sc->tids.hpftid_tab;
 1426                 in_use = sc->tids.hpftids_in_use;
 1427 #ifdef INVARIANTS
 1428                 tid_base = sc->tids.hpftid_base;
 1429 #endif
 1430         } else {
 1431                 nfilters = sc->tids.nftids;
 1432                 f = sc->tids.ftid_tab;
 1433                 in_use = sc->tids.ftids_in_use;
 1434 #ifdef INVARIANTS
 1435                 tid_base = sc->tids.ftid_base;
 1436 #endif
 1437         }
 1438 
 1439         if (in_use == 0 || f == NULL || t->idx >= nfilters) {
 1440                 t->idx = 0xffffffff;
 1441                 return (0);
 1442         }
 1443 
 1444         f += t->idx;
 1445         mtx_lock(&sc->tids.ftid_lock);
 1446         for (i = t->idx; i < nfilters; i++, f++) {
 1447                 if (f->valid) {
 1448                         MPASS(f->tid == tid_base + i);
 1449                         t->idx = i;
 1450                         t->l2tidx = f->l2te ? f->l2te->idx : 0;
 1451                         t->smtidx = f->smt ? f->smt->idx : 0;
 1452                         if (f->fs.hitcnts)
 1453                                 t->hits = get_filter_hits(sc, f->tid);
 1454                         else
 1455                                 t->hits = UINT64_MAX;
 1456                         t->fs = f->fs;
 1457 
 1458                         goto done;
 1459                 }
 1460         }
 1461         t->idx = 0xffffffff;
 1462 done:
 1463         mtx_unlock(&sc->tids.ftid_lock);
 1464         return (0);
 1465 }
 1466 
 1467 static int
 1468 get_hashfilter(struct adapter *sc, struct t4_filter *t)
 1469 {
 1470         struct tid_info *ti = &sc->tids;
 1471         int tid;
 1472         struct filter_entry *f;
 1473         const int inv_tid = ti->ntids + ti->tid_base;
 1474 
 1475         MPASS(t->fs.hash);
 1476 
 1477         if (ti->tids_in_use == 0 || ti->hftid_hash_tid == NULL ||
 1478             t->idx >= inv_tid) {
 1479                 t->idx = 0xffffffff;
 1480                 return (0);
 1481         }
 1482         if (t->idx < ti->tid_base)
 1483                 t->idx = ti->tid_base;
 1484 
 1485         mtx_lock(&ti->hftid_lock);
 1486         for (tid = t->idx; tid < inv_tid; tid++) {
 1487                 f = lookup_hftid(sc, tid);
 1488                 if (f != NULL && f->valid) {
 1489                         t->idx = tid;
 1490                         t->l2tidx = f->l2te ? f->l2te->idx : 0;
 1491                         t->smtidx = f->smt ? f->smt->idx : 0;
 1492                         if (f->fs.hitcnts)
 1493                                 t->hits = get_filter_hits(sc, tid);
 1494                         else
 1495                                 t->hits = UINT64_MAX;
 1496                         t->fs = f->fs;
 1497 
 1498                         goto done;
 1499                 }
 1500         }
 1501         t->idx = 0xffffffff;
 1502 done:
 1503         mtx_unlock(&ti->hftid_lock);
 1504         return (0);
 1505 }
 1506 
 1507 static void
 1508 mk_act_open_req6(struct adapter *sc, struct filter_entry *f, int atid,
 1509     uint64_t ftuple, struct cpl_act_open_req6 *cpl)
 1510 {
 1511         struct cpl_t5_act_open_req6 *cpl5 = (void *)cpl;
 1512         struct cpl_t6_act_open_req6 *cpl6 = (void *)cpl;
 1513 
 1514         /* Review changes to CPL after cpl_t6_act_open_req if this goes off. */
 1515         MPASS(chip_id(sc) >= CHELSIO_T5 && chip_id(sc) <= CHELSIO_T6);
 1516         MPASS(atid >= 0);
 1517 
 1518         if (chip_id(sc) == CHELSIO_T5) {
 1519                 INIT_TP_WR(cpl5, 0);
 1520         } else {
 1521                 INIT_TP_WR(cpl6, 0);
 1522                 cpl6->rsvd2 = 0;
 1523                 cpl6->opt3 = 0;
 1524         }
 1525 
 1526         OPCODE_TID(cpl) = htobe32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ6,
 1527             V_TID_QID(sc->sge.fwq.abs_id) | V_TID_TID(atid) |
 1528             V_TID_COOKIE(CPL_COOKIE_HASHFILTER)));
 1529         cpl->local_port = htobe16(f->fs.val.dport);
 1530         cpl->peer_port = htobe16(f->fs.val.sport);
 1531         cpl->local_ip_hi = *(uint64_t *)(&f->fs.val.dip);
 1532         cpl->local_ip_lo = *(((uint64_t *)&f->fs.val.dip) + 1);
 1533         cpl->peer_ip_hi = *(uint64_t *)(&f->fs.val.sip);
 1534         cpl->peer_ip_lo = *(((uint64_t *)&f->fs.val.sip) + 1);
 1535         cpl->opt0 = htobe64(V_NAGLE(f->fs.newvlan == VLAN_REMOVE ||
 1536             f->fs.newvlan == VLAN_REWRITE) | V_DELACK(f->fs.hitcnts) |
 1537             V_L2T_IDX(f->l2te ? f->l2te->idx : 0) | V_TX_CHAN(f->fs.eport) |
 1538             V_NO_CONG(f->fs.rpttid) |
 1539             V_ULP_MODE(f->fs.nat_mode ? ULP_MODE_TCPDDP : ULP_MODE_NONE) |
 1540             F_TCAM_BYPASS | F_NON_OFFLOAD);
 1541 
 1542         cpl6->params = htobe64(V_FILTER_TUPLE(ftuple));
 1543         cpl6->opt2 = htobe32(F_RSS_QUEUE_VALID | V_RSS_QUEUE(f->fs.iq) |
 1544             V_TX_QUEUE(f->fs.nat_mode) | V_WND_SCALE_EN(f->fs.nat_flag_chk) |
 1545             V_RX_FC_DISABLE(f->fs.nat_seq_chk ? 1 : 0) | F_T5_OPT_2_VALID |
 1546             F_RX_CHANNEL | V_SACK_EN(f->fs.swapmac) |
 1547             V_CONG_CNTRL((f->fs.action == FILTER_DROP) | (f->fs.dirsteer << 1)) |
 1548             V_PACE(f->fs.maskhash | (f->fs.dirsteerhash << 1)));
 1549 }
 1550 
 1551 static void
 1552 mk_act_open_req(struct adapter *sc, struct filter_entry *f, int atid,
 1553     uint64_t ftuple, struct cpl_act_open_req *cpl)
 1554 {
 1555         struct cpl_t5_act_open_req *cpl5 = (void *)cpl;
 1556         struct cpl_t6_act_open_req *cpl6 = (void *)cpl;
 1557 
 1558         /* Review changes to CPL after cpl_t6_act_open_req if this goes off. */
 1559         MPASS(chip_id(sc) >= CHELSIO_T5 && chip_id(sc) <= CHELSIO_T6);
 1560         MPASS(atid >= 0);
 1561 
 1562         if (chip_id(sc) == CHELSIO_T5) {
 1563                 INIT_TP_WR(cpl5, 0);
 1564         } else {
 1565                 INIT_TP_WR(cpl6, 0);
 1566                 cpl6->rsvd2 = 0;
 1567                 cpl6->opt3 = 0;
 1568         }
 1569 
 1570         OPCODE_TID(cpl) = htobe32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ,
 1571             V_TID_QID(sc->sge.fwq.abs_id) | V_TID_TID(atid) |
 1572             V_TID_COOKIE(CPL_COOKIE_HASHFILTER)));
 1573         cpl->local_port = htobe16(f->fs.val.dport);
 1574         cpl->peer_port = htobe16(f->fs.val.sport);
 1575         cpl->local_ip = f->fs.val.dip[0] | f->fs.val.dip[1] << 8 |
 1576             f->fs.val.dip[2] << 16 | f->fs.val.dip[3] << 24;
 1577         cpl->peer_ip = f->fs.val.sip[0] | f->fs.val.sip[1] << 8 |
 1578                 f->fs.val.sip[2] << 16 | f->fs.val.sip[3] << 24;
 1579         cpl->opt0 = htobe64(V_NAGLE(f->fs.newvlan == VLAN_REMOVE ||
 1580             f->fs.newvlan == VLAN_REWRITE) | V_DELACK(f->fs.hitcnts) |
 1581             V_L2T_IDX(f->l2te ? f->l2te->idx : 0) | V_TX_CHAN(f->fs.eport) |
 1582             V_NO_CONG(f->fs.rpttid) |
 1583             V_ULP_MODE(f->fs.nat_mode ? ULP_MODE_TCPDDP : ULP_MODE_NONE) |
 1584             F_TCAM_BYPASS | F_NON_OFFLOAD);
 1585 
 1586         cpl6->params = htobe64(V_FILTER_TUPLE(ftuple));
 1587         cpl6->opt2 = htobe32(F_RSS_QUEUE_VALID | V_RSS_QUEUE(f->fs.iq) |
 1588             V_TX_QUEUE(f->fs.nat_mode) | V_WND_SCALE_EN(f->fs.nat_flag_chk) |
 1589             V_RX_FC_DISABLE(f->fs.nat_seq_chk ? 1 : 0) | F_T5_OPT_2_VALID |
 1590             F_RX_CHANNEL | V_SACK_EN(f->fs.swapmac) |
 1591             V_CONG_CNTRL((f->fs.action == FILTER_DROP) | (f->fs.dirsteer << 1)) |
 1592             V_PACE(f->fs.maskhash | (f->fs.dirsteerhash << 1)));
 1593 }
 1594 
 1595 static int
 1596 act_open_cpl_len16(struct adapter *sc, int isipv6)
 1597 {
 1598         int idx;
 1599         static const int sz_table[3][2] = {
 1600                 {
 1601                         howmany(sizeof (struct cpl_act_open_req), 16),
 1602                         howmany(sizeof (struct cpl_act_open_req6), 16)
 1603                 },
 1604                 {
 1605                         howmany(sizeof (struct cpl_t5_act_open_req), 16),
 1606                         howmany(sizeof (struct cpl_t5_act_open_req6), 16)
 1607                 },
 1608                 {
 1609                         howmany(sizeof (struct cpl_t6_act_open_req), 16),
 1610                         howmany(sizeof (struct cpl_t6_act_open_req6), 16)
 1611                 },
 1612         };
 1613 
 1614         MPASS(chip_id(sc) >= CHELSIO_T4);
 1615         idx = min(chip_id(sc) - CHELSIO_T4, 2);
 1616 
 1617         return (sz_table[idx][!!isipv6]);
 1618 }
 1619 
 1620 static int
 1621 set_hashfilter(struct adapter *sc, struct t4_filter *t, uint64_t ftuple,
 1622     struct l2t_entry *l2te, struct smt_entry *smt)
 1623 {
 1624         void *wr;
 1625         struct wrq_cookie cookie;
 1626         struct filter_entry *f;
 1627         int rc, atid = -1;
 1628         uint32_t hash;
 1629 
 1630         MPASS(t->fs.hash);
 1631         /* Already validated against fconf, iconf */
 1632         MPASS((t->fs.val.pfvf_vld & t->fs.val.ovlan_vld) == 0);
 1633         MPASS((t->fs.mask.pfvf_vld & t->fs.mask.ovlan_vld) == 0);
 1634 
 1635         hash = hf_hashfn_4t(&t->fs);
 1636 
 1637         mtx_lock(&sc->tids.hftid_lock);
 1638         if (lookup_hf(sc, &t->fs, hash) != NULL) {
 1639                 rc = EEXIST;
 1640                 goto done;
 1641         }
 1642 
 1643         f = malloc(sizeof(*f), M_CXGBE, M_ZERO | M_NOWAIT);
 1644         if (__predict_false(f == NULL)) {
 1645                 rc = ENOMEM;
 1646                 goto done;
 1647         }
 1648         f->fs = t->fs;
 1649         f->l2te = l2te;
 1650         f->smt = smt;
 1651 
 1652         atid = alloc_atid(sc, f);
 1653         if (__predict_false(atid) == -1) {
 1654                 free(f, M_CXGBE);
 1655                 rc = EAGAIN;
 1656                 goto done;
 1657         }
 1658         MPASS(atid >= 0);
 1659 
 1660         wr = start_wrq_wr(&sc->sge.ctrlq[0], act_open_cpl_len16(sc, f->fs.type),
 1661             &cookie);
 1662         if (wr == NULL) {
 1663                 free_atid(sc, atid);
 1664                 free(f, M_CXGBE);
 1665                 rc = ENOMEM;
 1666                 goto done;
 1667         }
 1668         if (f->fs.type)
 1669                 mk_act_open_req6(sc, f, atid, ftuple, wr);
 1670         else
 1671                 mk_act_open_req(sc, f, atid, ftuple, wr);
 1672 
 1673         f->locked = 1; /* ithread mustn't free f if ioctl is still around. */
 1674         f->pending = 1;
 1675         f->tid = -1;
 1676         insert_hf(sc, f, hash);
 1677         commit_wrq_wr(&sc->sge.ctrlq[0], wr, &cookie);
 1678 
 1679         for (;;) {
 1680                 MPASS(f->locked);
 1681                 if (f->pending == 0) {
 1682                         if (f->valid) {
 1683                                 rc = 0;
 1684                                 f->locked = 0;
 1685                                 t->idx = f->tid;
 1686                         } else {
 1687                                 rc = f->tid;
 1688                                 free(f, M_CXGBE);
 1689                         }
 1690                         break;
 1691                 }
 1692                 if (cv_wait_sig(&sc->tids.hftid_cv, &sc->tids.hftid_lock) != 0) {
 1693                         f->locked = 0;
 1694                         rc = EINPROGRESS;
 1695                         break;
 1696                 }
 1697         }
 1698 done:
 1699         mtx_unlock(&sc->tids.hftid_lock);
 1700         return (rc);
 1701 }
 1702 
 1703 /* SET_TCB_FIELD sent as a ULP command looks like this */
 1704 #define LEN__SET_TCB_FIELD_ULP (sizeof(struct ulp_txpkt) + \
 1705     sizeof(struct ulptx_idata) + sizeof(struct cpl_set_tcb_field_core))
 1706 
 1707 static void *
 1708 mk_set_tcb_field_ulp(struct ulp_txpkt *ulpmc, uint64_t word, uint64_t mask,
 1709                 uint64_t val, uint32_t tid, uint32_t qid)
 1710 {
 1711         struct ulptx_idata *ulpsc;
 1712         struct cpl_set_tcb_field_core *req;
 1713 
 1714         ulpmc->cmd_dest = htonl(V_ULPTX_CMD(ULP_TX_PKT) | V_ULP_TXPKT_DEST(0));
 1715         ulpmc->len = htobe32(howmany(LEN__SET_TCB_FIELD_ULP, 16));
 1716 
 1717         ulpsc = (struct ulptx_idata *)(ulpmc + 1);
 1718         ulpsc->cmd_more = htobe32(V_ULPTX_CMD(ULP_TX_SC_IMM));
 1719         ulpsc->len = htobe32(sizeof(*req));
 1720 
 1721         req = (struct cpl_set_tcb_field_core *)(ulpsc + 1);
 1722         OPCODE_TID(req) = htobe32(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid));
 1723         req->reply_ctrl = htobe16(V_NO_REPLY(1) | V_QUEUENO(qid));
 1724         req->word_cookie = htobe16(V_WORD(word) | V_COOKIE(0));
 1725         req->mask = htobe64(mask);
 1726         req->val = htobe64(val);
 1727 
 1728         ulpsc = (struct ulptx_idata *)(req + 1);
 1729         if (LEN__SET_TCB_FIELD_ULP % 16) {
 1730                 ulpsc->cmd_more = htobe32(V_ULPTX_CMD(ULP_TX_SC_NOOP));
 1731                 ulpsc->len = htobe32(0);
 1732                 return (ulpsc + 1);
 1733         }
 1734         return (ulpsc);
 1735 }
 1736 
 1737 /* ABORT_REQ sent as a ULP command looks like this */
 1738 #define LEN__ABORT_REQ_ULP (sizeof(struct ulp_txpkt) + \
 1739         sizeof(struct ulptx_idata) + sizeof(struct cpl_abort_req_core))
 1740 
 1741 static void *
 1742 mk_abort_req_ulp(struct ulp_txpkt *ulpmc, uint32_t tid)
 1743 {
 1744         struct ulptx_idata *ulpsc;
 1745         struct cpl_abort_req_core *req;
 1746 
 1747         ulpmc->cmd_dest = htonl(V_ULPTX_CMD(ULP_TX_PKT) | V_ULP_TXPKT_DEST(0));
 1748         ulpmc->len = htobe32(howmany(LEN__ABORT_REQ_ULP, 16));
 1749 
 1750         ulpsc = (struct ulptx_idata *)(ulpmc + 1);
 1751         ulpsc->cmd_more = htobe32(V_ULPTX_CMD(ULP_TX_SC_IMM));
 1752         ulpsc->len = htobe32(sizeof(*req));
 1753 
 1754         req = (struct cpl_abort_req_core *)(ulpsc + 1);
 1755         OPCODE_TID(req) = htobe32(MK_OPCODE_TID(CPL_ABORT_REQ, tid));
 1756         req->rsvd0 = htonl(0);
 1757         req->rsvd1 = 0;
 1758         req->cmd = CPL_ABORT_NO_RST;
 1759 
 1760         ulpsc = (struct ulptx_idata *)(req + 1);
 1761         if (LEN__ABORT_REQ_ULP % 16) {
 1762                 ulpsc->cmd_more = htobe32(V_ULPTX_CMD(ULP_TX_SC_NOOP));
 1763                 ulpsc->len = htobe32(0);
 1764                 return (ulpsc + 1);
 1765         }
 1766         return (ulpsc);
 1767 }
 1768 
 1769 /* ABORT_RPL sent as a ULP command looks like this */
 1770 #define LEN__ABORT_RPL_ULP (sizeof(struct ulp_txpkt) + \
 1771         sizeof(struct ulptx_idata) + sizeof(struct cpl_abort_rpl_core))
 1772 
 1773 static void *
 1774 mk_abort_rpl_ulp(struct ulp_txpkt *ulpmc, uint32_t tid)
 1775 {
 1776         struct ulptx_idata *ulpsc;
 1777         struct cpl_abort_rpl_core *rpl;
 1778 
 1779         ulpmc->cmd_dest = htonl(V_ULPTX_CMD(ULP_TX_PKT) | V_ULP_TXPKT_DEST(0));
 1780         ulpmc->len = htobe32(howmany(LEN__ABORT_RPL_ULP, 16));
 1781 
 1782         ulpsc = (struct ulptx_idata *)(ulpmc + 1);
 1783         ulpsc->cmd_more = htobe32(V_ULPTX_CMD(ULP_TX_SC_IMM));
 1784         ulpsc->len = htobe32(sizeof(*rpl));
 1785 
 1786         rpl = (struct cpl_abort_rpl_core *)(ulpsc + 1);
 1787         OPCODE_TID(rpl) = htobe32(MK_OPCODE_TID(CPL_ABORT_RPL, tid));
 1788         rpl->rsvd0 = htonl(0);
 1789         rpl->rsvd1 = 0;
 1790         rpl->cmd = CPL_ABORT_NO_RST;
 1791 
 1792         ulpsc = (struct ulptx_idata *)(rpl + 1);
 1793         if (LEN__ABORT_RPL_ULP % 16) {
 1794                 ulpsc->cmd_more = htobe32(V_ULPTX_CMD(ULP_TX_SC_NOOP));
 1795                 ulpsc->len = htobe32(0);
 1796                 return (ulpsc + 1);
 1797         }
 1798         return (ulpsc);
 1799 }
 1800 
 1801 static inline int
 1802 del_hashfilter_wrlen(void)
 1803 {
 1804 
 1805         return (sizeof(struct work_request_hdr) +
 1806             roundup2(LEN__SET_TCB_FIELD_ULP, 16) +
 1807             roundup2(LEN__ABORT_REQ_ULP, 16) +
 1808             roundup2(LEN__ABORT_RPL_ULP, 16));
 1809 }
 1810 
 1811 static void
 1812 mk_del_hashfilter_wr(int tid, struct work_request_hdr *wrh, int wrlen, int qid)
 1813 {
 1814         struct ulp_txpkt *ulpmc;
 1815 
 1816         INIT_ULPTX_WRH(wrh, wrlen, 0, 0);
 1817         ulpmc = (struct ulp_txpkt *)(wrh + 1);
 1818         ulpmc = mk_set_tcb_field_ulp(ulpmc, W_TCB_RSS_INFO,
 1819             V_TCB_RSS_INFO(M_TCB_RSS_INFO), V_TCB_RSS_INFO(qid), tid, 0);
 1820         ulpmc = mk_abort_req_ulp(ulpmc, tid);
 1821         ulpmc = mk_abort_rpl_ulp(ulpmc, tid);
 1822 }
 1823 
 1824 static int
 1825 del_hashfilter(struct adapter *sc, struct t4_filter *t)
 1826 {
 1827         struct tid_info *ti = &sc->tids;
 1828         void *wr;
 1829         struct filter_entry *f;
 1830         struct wrq_cookie cookie;
 1831         int rc;
 1832         const int wrlen = del_hashfilter_wrlen();
 1833         const int inv_tid = ti->ntids + ti->tid_base;
 1834 
 1835         MPASS(sc->tids.hftid_hash_4t != NULL);
 1836         MPASS(sc->tids.ntids > 0);
 1837 
 1838         if (t->idx < sc->tids.tid_base || t->idx >= inv_tid)
 1839                 return (EINVAL);
 1840 
 1841         mtx_lock(&ti->hftid_lock);
 1842         f = lookup_hftid(sc, t->idx);
 1843         if (f == NULL || f->valid == 0) {
 1844                 rc = EINVAL;
 1845                 goto done;
 1846         }
 1847         MPASS(f->tid == t->idx);
 1848         if (f->locked) {
 1849                 rc = EPERM;
 1850                 goto done;
 1851         }
 1852         if (f->pending) {
 1853                 rc = EBUSY;
 1854                 goto done;
 1855         }
 1856         wr = start_wrq_wr(&sc->sge.ctrlq[0], howmany(wrlen, 16), &cookie);
 1857         if (wr == NULL) {
 1858                 rc = ENOMEM;
 1859                 goto done;
 1860         }
 1861 
 1862         mk_del_hashfilter_wr(t->idx, wr, wrlen, sc->sge.fwq.abs_id);
 1863         f->locked = 1;
 1864         f->pending = 1;
 1865         commit_wrq_wr(&sc->sge.ctrlq[0], wr, &cookie);
 1866         t->fs = f->fs;  /* extra info for the caller */
 1867 
 1868         for (;;) {
 1869                 MPASS(f->locked);
 1870                 if (f->pending == 0) {
 1871                         if (f->valid) {
 1872                                 f->locked = 0;
 1873                                 rc = EIO;
 1874                         } else {
 1875                                 rc = 0;
 1876                                 free(f, M_CXGBE);
 1877                         }
 1878                         break;
 1879                 }
 1880                 if (cv_wait_sig(&ti->hftid_cv, &ti->hftid_lock) != 0) {
 1881                         f->locked = 0;
 1882                         rc = EINPROGRESS;
 1883                         break;
 1884                 }
 1885         }
 1886 done:
 1887         mtx_unlock(&ti->hftid_lock);
 1888         return (rc);
 1889 }
 1890 
 1891 #define WORD_MASK       0xffffffff
 1892 static void
 1893 set_nat_params(struct adapter *sc, struct filter_entry *f, const bool dip,
 1894     const bool sip, const bool dp, const bool sp)
 1895 {
 1896 
 1897         if (dip) {
 1898                 if (f->fs.type) {
 1899                         set_tcb_field(sc, f->tid, W_TCB_SND_UNA_RAW, WORD_MASK,
 1900                             f->fs.nat_dip[15] | f->fs.nat_dip[14] << 8 |
 1901                             f->fs.nat_dip[13] << 16 | f->fs.nat_dip[12] << 24, 1);
 1902 
 1903                         set_tcb_field(sc, f->tid,
 1904                             W_TCB_SND_UNA_RAW + 1, WORD_MASK,
 1905                             f->fs.nat_dip[11] | f->fs.nat_dip[10] << 8 |
 1906                             f->fs.nat_dip[9] << 16 | f->fs.nat_dip[8] << 24, 1);
 1907 
 1908                         set_tcb_field(sc, f->tid,
 1909                             W_TCB_SND_UNA_RAW + 2, WORD_MASK,
 1910                             f->fs.nat_dip[7] | f->fs.nat_dip[6] << 8 |
 1911                             f->fs.nat_dip[5] << 16 | f->fs.nat_dip[4] << 24, 1);
 1912 
 1913                         set_tcb_field(sc, f->tid,
 1914                             W_TCB_SND_UNA_RAW + 3, WORD_MASK,
 1915                             f->fs.nat_dip[3] | f->fs.nat_dip[2] << 8 |
 1916                             f->fs.nat_dip[1] << 16 | f->fs.nat_dip[0] << 24, 1);
 1917                 } else {
 1918                         set_tcb_field(sc, f->tid,
 1919                             W_TCB_RX_FRAG3_LEN_RAW, WORD_MASK,
 1920                             f->fs.nat_dip[3] | f->fs.nat_dip[2] << 8 |
 1921                             f->fs.nat_dip[1] << 16 | f->fs.nat_dip[0] << 24, 1);
 1922                 }
 1923         }
 1924 
 1925         if (sip) {
 1926                 if (f->fs.type) {
 1927                         set_tcb_field(sc, f->tid,
 1928                             W_TCB_RX_FRAG2_PTR_RAW, WORD_MASK,
 1929                             f->fs.nat_sip[15] | f->fs.nat_sip[14] << 8 |
 1930                             f->fs.nat_sip[13] << 16 | f->fs.nat_sip[12] << 24, 1);
 1931 
 1932                         set_tcb_field(sc, f->tid,
 1933                             W_TCB_RX_FRAG2_PTR_RAW + 1, WORD_MASK,
 1934                             f->fs.nat_sip[11] | f->fs.nat_sip[10] << 8 |
 1935                             f->fs.nat_sip[9] << 16 | f->fs.nat_sip[8] << 24, 1);
 1936 
 1937                         set_tcb_field(sc, f->tid,
 1938                             W_TCB_RX_FRAG2_PTR_RAW + 2, WORD_MASK,
 1939                             f->fs.nat_sip[7] | f->fs.nat_sip[6] << 8 |
 1940                             f->fs.nat_sip[5] << 16 | f->fs.nat_sip[4] << 24, 1);
 1941 
 1942                         set_tcb_field(sc, f->tid,
 1943                             W_TCB_RX_FRAG2_PTR_RAW + 3, WORD_MASK,
 1944                             f->fs.nat_sip[3] | f->fs.nat_sip[2] << 8 |
 1945                             f->fs.nat_sip[1] << 16 | f->fs.nat_sip[0] << 24, 1);
 1946 
 1947                 } else {
 1948                         set_tcb_field(sc, f->tid,
 1949                             W_TCB_RX_FRAG3_START_IDX_OFFSET_RAW, WORD_MASK,
 1950                             f->fs.nat_sip[3] | f->fs.nat_sip[2] << 8 |
 1951                             f->fs.nat_sip[1] << 16 | f->fs.nat_sip[0] << 24, 1);
 1952                 }
 1953         }
 1954 
 1955         set_tcb_field(sc, f->tid, W_TCB_PDU_HDR_LEN, WORD_MASK,
 1956             (dp ? f->fs.nat_dport : 0) | (sp ? f->fs.nat_sport << 16 : 0), 1);
 1957 }
 1958 
 1959 /*
 1960  * Returns EINPROGRESS to indicate that at least one TCB update was sent and the
 1961  * last of the series of updates requested a reply.  The reply informs the
 1962  * driver that the filter is fully setup.
 1963  */
 1964 static int
 1965 configure_hashfilter_tcb(struct adapter *sc, struct filter_entry *f)
 1966 {
 1967         int updated = 0;
 1968 
 1969         MPASS(f->tid < sc->tids.ntids);
 1970         MPASS(f->fs.hash);
 1971         MPASS(f->pending);
 1972         MPASS(f->valid == 0);
 1973 
 1974         if (f->fs.newdmac) {
 1975                 set_tcb_tflag(sc, f->tid, S_TF_CCTRL_ECE, 1, 1);
 1976                 updated++;
 1977         }
 1978 
 1979         if (f->fs.newvlan == VLAN_INSERT || f->fs.newvlan == VLAN_REWRITE) {
 1980                 set_tcb_tflag(sc, f->tid, S_TF_CCTRL_RFR, 1, 1);
 1981                 updated++;
 1982         }
 1983 
 1984         if (f->fs.newsmac) {
 1985                 MPASS(f->smt != NULL);
 1986                 set_tcb_tflag(sc, f->tid, S_TF_CCTRL_CWR, 1, 1);
 1987                 set_tcb_field(sc, f->tid, W_TCB_SMAC_SEL,
 1988                     V_TCB_SMAC_SEL(M_TCB_SMAC_SEL), V_TCB_SMAC_SEL(f->smt->idx),
 1989                     1);
 1990                 updated++;
 1991         }
 1992 
 1993         switch(f->fs.nat_mode) {
 1994         case NAT_MODE_NONE:
 1995                 break;
 1996         case NAT_MODE_DIP:
 1997                 set_nat_params(sc, f, true, false, false, false);
 1998                 updated++;
 1999                 break;
 2000         case NAT_MODE_DIP_DP:
 2001                 set_nat_params(sc, f, true, false, true, false);
 2002                 updated++;
 2003                 break;
 2004         case NAT_MODE_DIP_DP_SIP:
 2005                 set_nat_params(sc, f, true, true, true, false);
 2006                 updated++;
 2007                 break;
 2008         case NAT_MODE_DIP_DP_SP:
 2009                 set_nat_params(sc, f, true, false, true, true);
 2010                 updated++;
 2011                 break;
 2012         case NAT_MODE_SIP_SP:
 2013                 set_nat_params(sc, f, false, true, false, true);
 2014                 updated++;
 2015                 break;
 2016         case NAT_MODE_DIP_SIP_SP:
 2017                 set_nat_params(sc, f, true, true, false, true);
 2018                 updated++;
 2019                 break;
 2020         case NAT_MODE_ALL:
 2021                 set_nat_params(sc, f, true, true, true, true);
 2022                 updated++;
 2023                 break;
 2024         default:
 2025                 MPASS(0);       /* should have been validated earlier */
 2026                 break;
 2027 
 2028         }
 2029 
 2030         if (f->fs.nat_seq_chk) {
 2031                 set_tcb_field(sc, f->tid, W_TCB_RCV_NXT,
 2032                     V_TCB_RCV_NXT(M_TCB_RCV_NXT),
 2033                     V_TCB_RCV_NXT(f->fs.nat_seq_chk), 1);
 2034                 updated++;
 2035         }
 2036 
 2037         if (is_t5(sc) && f->fs.action == FILTER_DROP) {
 2038                 /*
 2039                  * Migrating = 1, Non-offload = 0 to get a T5 hashfilter to drop.
 2040                  */
 2041                 set_tcb_field(sc, f->tid, W_TCB_T_FLAGS, V_TF_NON_OFFLOAD(1) |
 2042                     V_TF_MIGRATING(1), V_TF_MIGRATING(1), 1);
 2043                 updated++;
 2044         }
 2045 
 2046         /*
 2047          * Enable switching after all secondary resources (L2T entry, SMT entry,
 2048          * etc.) are setup so that any switched packet will use correct
 2049          * values.
 2050          */
 2051         if (f->fs.action == FILTER_SWITCH) {
 2052                 set_tcb_tflag(sc, f->tid, S_TF_CCTRL_ECN, 1, 1);
 2053                 updated++;
 2054         }
 2055 
 2056         if (f->fs.hitcnts || updated > 0) {
 2057                 set_tcb_field(sc, f->tid, W_TCB_TIMESTAMP,
 2058                     V_TCB_TIMESTAMP(M_TCB_TIMESTAMP) |
 2059                     V_TCB_T_RTT_TS_RECENT_AGE(M_TCB_T_RTT_TS_RECENT_AGE),
 2060                     V_TCB_TIMESTAMP(0ULL) | V_TCB_T_RTT_TS_RECENT_AGE(0ULL), 0);
 2061                 return (EINPROGRESS);
 2062         }
 2063 
 2064         return (0);
 2065 }

Cache object: a0cd6b34934ca15c92f80712d20cee4b


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