2 * Copyright (c) 2007-2015 Solarflare Communications Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 * The views and conclusions contained in the software and documentation are
27 * those of the authors and should not be interpreted as representing official
28 * policies, either expressed or implied, of the FreeBSD Project.
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
40 #if EFSYS_OPT_FALCON || EFSYS_OPT_SIENA
42 static __checkReturn efx_rc_t
43 falconsiena_filter_init(
47 falconsiena_filter_fini(
50 static __checkReturn efx_rc_t
51 falconsiena_filter_restore(
54 static __checkReturn efx_rc_t
55 falconsiena_filter_add(
57 __inout efx_filter_spec_t *spec,
58 __in boolean_t may_replace);
60 static __checkReturn efx_rc_t
61 falconsiena_filter_delete(
63 __inout efx_filter_spec_t *spec);
65 static __checkReturn efx_rc_t
66 falconsiena_filter_supported_filters(
69 __out size_t *length);
71 #endif /* EFSYS_OPT_FALCON || EFSYS_OPT_SIENA */
74 static efx_filter_ops_t __efx_filter_falcon_ops = {
75 falconsiena_filter_init, /* efo_init */
76 falconsiena_filter_fini, /* efo_fini */
77 falconsiena_filter_restore, /* efo_restore */
78 falconsiena_filter_add, /* efo_add */
79 falconsiena_filter_delete, /* efo_delete */
80 falconsiena_filter_supported_filters, /* efo_supported_filters */
81 NULL, /* efo_reconfigure */
83 #endif /* EFSYS_OPT_FALCON */
86 static efx_filter_ops_t __efx_filter_siena_ops = {
87 falconsiena_filter_init, /* efo_init */
88 falconsiena_filter_fini, /* efo_fini */
89 falconsiena_filter_restore, /* efo_restore */
90 falconsiena_filter_add, /* efo_add */
91 falconsiena_filter_delete, /* efo_delete */
92 falconsiena_filter_supported_filters, /* efo_supported_filters */
93 NULL, /* efo_reconfigure */
95 #endif /* EFSYS_OPT_SIENA */
97 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
98 static efx_filter_ops_t __efx_filter_ef10_ops = {
99 ef10_filter_init, /* efo_init */
100 ef10_filter_fini, /* efo_fini */
101 ef10_filter_restore, /* efo_restore */
102 ef10_filter_add, /* efo_add */
103 ef10_filter_delete, /* efo_delete */
104 ef10_filter_supported_filters, /* efo_supported_filters */
105 ef10_filter_reconfigure, /* efo_reconfigure */
107 #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
109 __checkReturn efx_rc_t
112 __inout efx_filter_spec_t *spec)
114 efx_filter_ops_t *efop = enp->en_efop;
116 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
117 EFSYS_ASSERT3P(spec, !=, NULL);
118 EFSYS_ASSERT3U(spec->efs_flags, &, EFX_FILTER_FLAG_RX);
120 return (efop->efo_add(enp, spec, B_FALSE));
123 __checkReturn efx_rc_t
126 __inout efx_filter_spec_t *spec)
128 efx_filter_ops_t *efop = enp->en_efop;
130 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
131 EFSYS_ASSERT3P(spec, !=, NULL);
132 EFSYS_ASSERT3U(spec->efs_flags, &, EFX_FILTER_FLAG_RX);
134 #if EFSYS_OPT_RX_SCALE
135 spec->efs_rss_context = enp->en_rss_context;
138 return (efop->efo_delete(enp, spec));
141 __checkReturn efx_rc_t
147 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
149 if ((rc = enp->en_efop->efo_restore(enp)) != 0)
155 EFSYS_PROBE1(fail1, efx_rc_t, rc);
160 __checkReturn efx_rc_t
164 efx_filter_ops_t *efop;
167 /* Check that efx_filter_spec_t is 64 bytes. */
168 EFX_STATIC_ASSERT(sizeof (efx_filter_spec_t) == 64);
170 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
171 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
172 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_FILTER));
174 switch (enp->en_family) {
176 case EFX_FAMILY_FALCON:
177 efop = (efx_filter_ops_t *)&__efx_filter_falcon_ops;
179 #endif /* EFSYS_OPT_FALCON */
182 case EFX_FAMILY_SIENA:
183 efop = (efx_filter_ops_t *)&__efx_filter_siena_ops;
185 #endif /* EFSYS_OPT_SIENA */
187 #if EFSYS_OPT_HUNTINGTON
188 case EFX_FAMILY_HUNTINGTON:
189 efop = (efx_filter_ops_t *)&__efx_filter_ef10_ops;
191 #endif /* EFSYS_OPT_HUNTINGTON */
193 #if EFSYS_OPT_MEDFORD
194 case EFX_FAMILY_MEDFORD:
195 efop = (efx_filter_ops_t *)&__efx_filter_ef10_ops;
197 #endif /* EFSYS_OPT_MEDFORD */
205 if ((rc = efop->efo_init(enp)) != 0)
209 enp->en_mod_flags |= EFX_MOD_FILTER;
215 EFSYS_PROBE1(fail1, efx_rc_t, rc);
218 enp->en_mod_flags &= ~EFX_MOD_FILTER;
226 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
227 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
228 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
230 enp->en_efop->efo_fini(enp);
233 enp->en_mod_flags &= ~EFX_MOD_FILTER;
236 __checkReturn efx_rc_t
237 efx_filter_supported_filters(
239 __out uint32_t *list,
240 __out size_t *length)
244 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
245 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
246 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
247 EFSYS_ASSERT(enp->en_efop->efo_supported_filters != NULL);
249 if ((rc = enp->en_efop->efo_supported_filters(enp, list, length)) != 0)
255 EFSYS_PROBE1(fail1, efx_rc_t, rc);
260 __checkReturn efx_rc_t
261 efx_filter_reconfigure(
263 __in_ecount(6) uint8_t const *mac_addr,
264 __in boolean_t all_unicst,
265 __in boolean_t mulcst,
266 __in boolean_t all_mulcst,
267 __in boolean_t brdcst,
268 __in_ecount(6*count) uint8_t const *addrs,
273 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
274 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
275 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
277 if (enp->en_efop->efo_reconfigure != NULL) {
278 if ((rc = enp->en_efop->efo_reconfigure(enp, mac_addr,
288 EFSYS_PROBE1(fail1, efx_rc_t, rc);
294 efx_filter_spec_init_rx(
295 __out efx_filter_spec_t *spec,
296 __in efx_filter_priority_t priority,
297 __in efx_filter_flag_t flags,
300 EFSYS_ASSERT3P(spec, !=, NULL);
301 EFSYS_ASSERT3P(erp, !=, NULL);
302 EFSYS_ASSERT((flags & ~(EFX_FILTER_FLAG_RX_RSS |
303 EFX_FILTER_FLAG_RX_SCATTER)) == 0);
305 memset(spec, 0, sizeof (*spec));
306 spec->efs_priority = priority;
307 spec->efs_flags = EFX_FILTER_FLAG_RX | flags;
308 spec->efs_rss_context = EFX_FILTER_SPEC_RSS_CONTEXT_DEFAULT;
309 spec->efs_dmaq_id = (uint16_t)erp->er_index;
313 efx_filter_spec_init_tx(
314 __out efx_filter_spec_t *spec,
317 EFSYS_ASSERT3P(spec, !=, NULL);
318 EFSYS_ASSERT3P(etp, !=, NULL);
320 memset(spec, 0, sizeof (*spec));
321 spec->efs_priority = EFX_FILTER_PRI_REQUIRED;
322 spec->efs_flags = EFX_FILTER_FLAG_TX;
323 spec->efs_dmaq_id = (uint16_t)etp->et_index;
328 * Specify IPv4 host, transport protocol and port in a filter specification
330 __checkReturn efx_rc_t
331 efx_filter_spec_set_ipv4_local(
332 __inout efx_filter_spec_t *spec,
337 EFSYS_ASSERT3P(spec, !=, NULL);
339 spec->efs_match_flags |=
340 EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
341 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT;
342 spec->efs_ether_type = EFX_ETHER_TYPE_IPV4;
343 spec->efs_ip_proto = proto;
344 spec->efs_loc_host.eo_u32[0] = host;
345 spec->efs_loc_port = port;
350 * Specify IPv4 hosts, transport protocol and ports in a filter specification
352 __checkReturn efx_rc_t
353 efx_filter_spec_set_ipv4_full(
354 __inout efx_filter_spec_t *spec,
361 EFSYS_ASSERT3P(spec, !=, NULL);
363 spec->efs_match_flags |=
364 EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
365 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT |
366 EFX_FILTER_MATCH_REM_HOST | EFX_FILTER_MATCH_REM_PORT;
367 spec->efs_ether_type = EFX_ETHER_TYPE_IPV4;
368 spec->efs_ip_proto = proto;
369 spec->efs_loc_host.eo_u32[0] = lhost;
370 spec->efs_loc_port = lport;
371 spec->efs_rem_host.eo_u32[0] = rhost;
372 spec->efs_rem_port = rport;
377 * Specify local Ethernet address and/or VID in filter specification
379 __checkReturn efx_rc_t
380 efx_filter_spec_set_eth_local(
381 __inout efx_filter_spec_t *spec,
383 __in const uint8_t *addr)
385 EFSYS_ASSERT3P(spec, !=, NULL);
386 EFSYS_ASSERT3P(addr, !=, NULL);
388 if (vid == EFX_FILTER_SPEC_VID_UNSPEC && addr == NULL)
391 if (vid != EFX_FILTER_SPEC_VID_UNSPEC) {
392 spec->efs_match_flags |= EFX_FILTER_MATCH_OUTER_VID;
393 spec->efs_outer_vid = vid;
396 spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_MAC;
397 memcpy(spec->efs_loc_mac, addr, EFX_MAC_ADDR_LEN);
403 * Specify matching otherwise-unmatched unicast in a filter specification
405 __checkReturn efx_rc_t
406 efx_filter_spec_set_uc_def(
407 __inout efx_filter_spec_t *spec)
409 EFSYS_ASSERT3P(spec, !=, NULL);
411 spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_MAC_IG;
416 * Specify matching otherwise-unmatched multicast in a filter specification
418 __checkReturn efx_rc_t
419 efx_filter_spec_set_mc_def(
420 __inout efx_filter_spec_t *spec)
422 EFSYS_ASSERT3P(spec, !=, NULL);
424 spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_MAC_IG;
425 spec->efs_loc_mac[0] = 1;
431 #if EFSYS_OPT_FALCON || EFSYS_OPT_SIENA
434 * "Fudge factors" - difference between programmed value and actual depth.
435 * Due to pipelined implementation we need to program H/W with a value that
436 * is larger than the hop limit we want.
438 #define FILTER_CTL_SRCH_FUDGE_WILD 3
439 #define FILTER_CTL_SRCH_FUDGE_FULL 1
442 * Hard maximum hop limit. Hardware will time-out beyond 200-something.
443 * We also need to avoid infinite loops in efx_filter_search() when the
446 #define FILTER_CTL_SRCH_MAX 200
448 static __checkReturn efx_rc_t
449 falconsiena_filter_spec_from_gen_spec(
450 __out falconsiena_filter_spec_t *fs_spec,
451 __in efx_filter_spec_t *gen_spec)
454 boolean_t is_full = B_FALSE;
456 if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX)
457 EFSYS_ASSERT3U(gen_spec->efs_flags, ==, EFX_FILTER_FLAG_TX);
459 EFSYS_ASSERT3U(gen_spec->efs_flags, &, EFX_FILTER_FLAG_RX);
461 /* Falconsiena only has one RSS context */
462 if ((gen_spec->efs_flags & EFX_FILTER_FLAG_RX_RSS) &&
463 gen_spec->efs_rss_context != 0) {
468 fs_spec->fsfs_flags = gen_spec->efs_flags;
469 fs_spec->fsfs_dmaq_id = gen_spec->efs_dmaq_id;
471 switch (gen_spec->efs_match_flags) {
472 case EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
473 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT |
474 EFX_FILTER_MATCH_REM_HOST | EFX_FILTER_MATCH_REM_PORT:
477 case EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
478 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT: {
479 uint32_t rhost, host1, host2;
480 uint16_t rport, port1, port2;
482 if (gen_spec->efs_ether_type != EFX_ETHER_TYPE_IPV4) {
486 if (gen_spec->efs_loc_port == 0 ||
487 (is_full && gen_spec->efs_rem_port == 0)) {
491 switch (gen_spec->efs_ip_proto) {
492 case EFX_IPPROTO_TCP:
493 if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX) {
494 fs_spec->fsfs_type = (is_full ?
495 EFX_FS_FILTER_TX_TCP_FULL :
496 EFX_FS_FILTER_TX_TCP_WILD);
498 fs_spec->fsfs_type = (is_full ?
499 EFX_FS_FILTER_RX_TCP_FULL :
500 EFX_FS_FILTER_RX_TCP_WILD);
503 case EFX_IPPROTO_UDP:
504 if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX) {
505 fs_spec->fsfs_type = (is_full ?
506 EFX_FS_FILTER_TX_UDP_FULL :
507 EFX_FS_FILTER_TX_UDP_WILD);
509 fs_spec->fsfs_type = (is_full ?
510 EFX_FS_FILTER_RX_UDP_FULL :
511 EFX_FS_FILTER_RX_UDP_WILD);
519 * The filter is constructed in terms of source and destination,
520 * with the odd wrinkle that the ports are swapped in a UDP
521 * wildcard filter. We need to convert from local and remote
522 * addresses (zero for a wildcard).
524 rhost = is_full ? gen_spec->efs_rem_host.eo_u32[0] : 0;
525 rport = is_full ? gen_spec->efs_rem_port : 0;
526 if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX) {
527 host1 = gen_spec->efs_loc_host.eo_u32[0];
531 host2 = gen_spec->efs_loc_host.eo_u32[0];
533 if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX) {
534 if (fs_spec->fsfs_type == EFX_FS_FILTER_TX_UDP_WILD) {
536 port2 = gen_spec->efs_loc_port;
538 port1 = gen_spec->efs_loc_port;
542 if (fs_spec->fsfs_type == EFX_FS_FILTER_RX_UDP_WILD) {
543 port1 = gen_spec->efs_loc_port;
547 port2 = gen_spec->efs_loc_port;
550 fs_spec->fsfs_dword[0] = (host1 << 16) | port1;
551 fs_spec->fsfs_dword[1] = (port2 << 16) | (host1 >> 16);
552 fs_spec->fsfs_dword[2] = host2;
556 case EFX_FILTER_MATCH_LOC_MAC | EFX_FILTER_MATCH_OUTER_VID:
559 case EFX_FILTER_MATCH_LOC_MAC:
560 if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX) {
561 fs_spec->fsfs_type = (is_full ?
562 EFX_FS_FILTER_TX_MAC_FULL :
563 EFX_FS_FILTER_TX_MAC_WILD);
565 fs_spec->fsfs_type = (is_full ?
566 EFX_FS_FILTER_RX_MAC_FULL :
567 EFX_FS_FILTER_RX_MAC_WILD);
569 fs_spec->fsfs_dword[0] = is_full ? gen_spec->efs_outer_vid : 0;
570 fs_spec->fsfs_dword[1] =
571 gen_spec->efs_loc_mac[2] << 24 |
572 gen_spec->efs_loc_mac[3] << 16 |
573 gen_spec->efs_loc_mac[4] << 8 |
574 gen_spec->efs_loc_mac[5];
575 fs_spec->fsfs_dword[2] =
576 gen_spec->efs_loc_mac[0] << 8 |
577 gen_spec->efs_loc_mac[1];
581 EFSYS_ASSERT(B_FALSE);
597 EFSYS_PROBE1(fail1, efx_rc_t, rc);
603 * The filter hash function is LFSR polynomial x^16 + x^3 + 1 of a 32-bit
604 * key derived from the n-tuple.
607 falconsiena_filter_tbl_hash(
612 /* First 16 rounds */
613 tmp = 0x1fff ^ (uint16_t)(key >> 16);
614 tmp = tmp ^ tmp >> 3 ^ tmp >> 6;
615 tmp = tmp ^ tmp >> 9;
618 tmp = tmp ^ tmp << 13 ^ (uint16_t)(key & 0xffff);
619 tmp = tmp ^ tmp >> 3 ^ tmp >> 6;
620 tmp = tmp ^ tmp >> 9;
626 * To allow for hash collisions, filter search continues at these
627 * increments from the first possible entry selected by the hash.
630 falconsiena_filter_tbl_increment(
633 return ((uint16_t)(key * 2 - 1));
636 static __checkReturn boolean_t
637 falconsiena_filter_test_used(
638 __in falconsiena_filter_tbl_t *fsftp,
639 __in unsigned int index)
641 EFSYS_ASSERT3P(fsftp->fsft_bitmap, !=, NULL);
642 return ((fsftp->fsft_bitmap[index / 32] & (1 << (index % 32))) != 0);
646 falconsiena_filter_set_used(
647 __in falconsiena_filter_tbl_t *fsftp,
648 __in unsigned int index)
650 EFSYS_ASSERT3P(fsftp->fsft_bitmap, !=, NULL);
651 fsftp->fsft_bitmap[index / 32] |= (1 << (index % 32));
656 falconsiena_filter_clear_used(
657 __in falconsiena_filter_tbl_t *fsftp,
658 __in unsigned int index)
660 EFSYS_ASSERT3P(fsftp->fsft_bitmap, !=, NULL);
661 fsftp->fsft_bitmap[index / 32] &= ~(1 << (index % 32));
664 EFSYS_ASSERT3U(fsftp->fsft_used, >=, 0);
668 static falconsiena_filter_tbl_id_t
669 falconsiena_filter_tbl_id(
670 __in falconsiena_filter_type_t type)
672 falconsiena_filter_tbl_id_t tbl_id;
675 case EFX_FS_FILTER_RX_TCP_FULL:
676 case EFX_FS_FILTER_RX_TCP_WILD:
677 case EFX_FS_FILTER_RX_UDP_FULL:
678 case EFX_FS_FILTER_RX_UDP_WILD:
679 tbl_id = EFX_FS_FILTER_TBL_RX_IP;
683 case EFX_FS_FILTER_RX_MAC_FULL:
684 case EFX_FS_FILTER_RX_MAC_WILD:
685 tbl_id = EFX_FS_FILTER_TBL_RX_MAC;
688 case EFX_FS_FILTER_TX_TCP_FULL:
689 case EFX_FS_FILTER_TX_TCP_WILD:
690 case EFX_FS_FILTER_TX_UDP_FULL:
691 case EFX_FS_FILTER_TX_UDP_WILD:
692 tbl_id = EFX_FS_FILTER_TBL_TX_IP;
695 case EFX_FS_FILTER_TX_MAC_FULL:
696 case EFX_FS_FILTER_TX_MAC_WILD:
697 tbl_id = EFX_FS_FILTER_TBL_TX_MAC;
699 #endif /* EFSYS_OPT_SIENA */
702 EFSYS_ASSERT(B_FALSE);
703 tbl_id = EFX_FS_FILTER_NTBLS;
710 falconsiena_filter_reset_search_depth(
711 __inout falconsiena_filter_t *fsfp,
712 __in falconsiena_filter_tbl_id_t tbl_id)
715 case EFX_FS_FILTER_TBL_RX_IP:
716 fsfp->fsf_depth[EFX_FS_FILTER_RX_TCP_FULL] = 0;
717 fsfp->fsf_depth[EFX_FS_FILTER_RX_TCP_WILD] = 0;
718 fsfp->fsf_depth[EFX_FS_FILTER_RX_UDP_FULL] = 0;
719 fsfp->fsf_depth[EFX_FS_FILTER_RX_UDP_WILD] = 0;
723 case EFX_FS_FILTER_TBL_RX_MAC:
724 fsfp->fsf_depth[EFX_FS_FILTER_RX_MAC_FULL] = 0;
725 fsfp->fsf_depth[EFX_FS_FILTER_RX_MAC_WILD] = 0;
728 case EFX_FS_FILTER_TBL_TX_IP:
729 fsfp->fsf_depth[EFX_FS_FILTER_TX_TCP_FULL] = 0;
730 fsfp->fsf_depth[EFX_FS_FILTER_TX_TCP_WILD] = 0;
731 fsfp->fsf_depth[EFX_FS_FILTER_TX_UDP_FULL] = 0;
732 fsfp->fsf_depth[EFX_FS_FILTER_TX_UDP_WILD] = 0;
735 case EFX_FS_FILTER_TBL_TX_MAC:
736 fsfp->fsf_depth[EFX_FS_FILTER_TX_MAC_FULL] = 0;
737 fsfp->fsf_depth[EFX_FS_FILTER_TX_MAC_WILD] = 0;
739 #endif /* EFSYS_OPT_SIENA */
742 EFSYS_ASSERT(B_FALSE);
748 falconsiena_filter_push_rx_limits(
751 falconsiena_filter_t *fsfp = enp->en_filter.ef_falconsiena_filter;
754 EFX_BAR_READO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
756 EFX_SET_OWORD_FIELD(oword, FRF_AZ_TCP_FULL_SRCH_LIMIT,
757 fsfp->fsf_depth[EFX_FS_FILTER_RX_TCP_FULL] +
758 FILTER_CTL_SRCH_FUDGE_FULL);
759 EFX_SET_OWORD_FIELD(oword, FRF_AZ_TCP_WILD_SRCH_LIMIT,
760 fsfp->fsf_depth[EFX_FS_FILTER_RX_TCP_WILD] +
761 FILTER_CTL_SRCH_FUDGE_WILD);
762 EFX_SET_OWORD_FIELD(oword, FRF_AZ_UDP_FULL_SRCH_LIMIT,
763 fsfp->fsf_depth[EFX_FS_FILTER_RX_UDP_FULL] +
764 FILTER_CTL_SRCH_FUDGE_FULL);
765 EFX_SET_OWORD_FIELD(oword, FRF_AZ_UDP_WILD_SRCH_LIMIT,
766 fsfp->fsf_depth[EFX_FS_FILTER_RX_UDP_WILD] +
767 FILTER_CTL_SRCH_FUDGE_WILD);
770 if (fsfp->fsf_tbl[EFX_FS_FILTER_TBL_RX_MAC].fsft_size) {
771 EFX_SET_OWORD_FIELD(oword,
772 FRF_CZ_ETHERNET_FULL_SEARCH_LIMIT,
773 fsfp->fsf_depth[EFX_FS_FILTER_RX_MAC_FULL] +
774 FILTER_CTL_SRCH_FUDGE_FULL);
775 EFX_SET_OWORD_FIELD(oword,
776 FRF_CZ_ETHERNET_WILDCARD_SEARCH_LIMIT,
777 fsfp->fsf_depth[EFX_FS_FILTER_RX_MAC_WILD] +
778 FILTER_CTL_SRCH_FUDGE_WILD);
780 #endif /* EFSYS_OPT_SIENA */
782 EFX_BAR_WRITEO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
786 falconsiena_filter_push_tx_limits(
789 falconsiena_filter_t *fsfp = enp->en_filter.ef_falconsiena_filter;
792 EFX_BAR_READO(enp, FR_AZ_TX_CFG_REG, &oword);
794 if (fsfp->fsf_tbl[EFX_FS_FILTER_TBL_TX_IP].fsft_size != 0) {
795 EFX_SET_OWORD_FIELD(oword,
796 FRF_CZ_TX_TCPIP_FILTER_FULL_SEARCH_RANGE,
797 fsfp->fsf_depth[EFX_FS_FILTER_TX_TCP_FULL] +
798 FILTER_CTL_SRCH_FUDGE_FULL);
799 EFX_SET_OWORD_FIELD(oword,
800 FRF_CZ_TX_TCPIP_FILTER_WILD_SEARCH_RANGE,
801 fsfp->fsf_depth[EFX_FS_FILTER_TX_TCP_WILD] +
802 FILTER_CTL_SRCH_FUDGE_WILD);
803 EFX_SET_OWORD_FIELD(oword,
804 FRF_CZ_TX_UDPIP_FILTER_FULL_SEARCH_RANGE,
805 fsfp->fsf_depth[EFX_FS_FILTER_TX_UDP_FULL] +
806 FILTER_CTL_SRCH_FUDGE_FULL);
807 EFX_SET_OWORD_FIELD(oword,
808 FRF_CZ_TX_UDPIP_FILTER_WILD_SEARCH_RANGE,
809 fsfp->fsf_depth[EFX_FS_FILTER_TX_UDP_WILD] +
810 FILTER_CTL_SRCH_FUDGE_WILD);
813 if (fsfp->fsf_tbl[EFX_FS_FILTER_TBL_TX_MAC].fsft_size != 0) {
815 oword, FRF_CZ_TX_ETH_FILTER_FULL_SEARCH_RANGE,
816 fsfp->fsf_depth[EFX_FS_FILTER_TX_MAC_FULL] +
817 FILTER_CTL_SRCH_FUDGE_FULL);
819 oword, FRF_CZ_TX_ETH_FILTER_WILD_SEARCH_RANGE,
820 fsfp->fsf_depth[EFX_FS_FILTER_TX_MAC_WILD] +
821 FILTER_CTL_SRCH_FUDGE_WILD);
824 EFX_BAR_WRITEO(enp, FR_AZ_TX_CFG_REG, &oword);
827 /* Build a filter entry and return its n-tuple key. */
828 static __checkReturn uint32_t
829 falconsiena_filter_build(
830 __out efx_oword_t *filter,
831 __in falconsiena_filter_spec_t *spec)
835 uint8_t type = spec->fsfs_type;
836 uint32_t flags = spec->fsfs_flags;
838 switch (falconsiena_filter_tbl_id(type)) {
839 case EFX_FS_FILTER_TBL_RX_IP: {
840 boolean_t is_udp = (type == EFX_FS_FILTER_RX_UDP_FULL ||
841 type == EFX_FS_FILTER_RX_UDP_WILD);
842 EFX_POPULATE_OWORD_7(*filter,
844 (flags & EFX_FILTER_FLAG_RX_RSS) ? 1 : 0,
846 (flags & EFX_FILTER_FLAG_RX_SCATTER) ? 1 : 0,
847 FRF_AZ_TCP_UDP, is_udp,
848 FRF_AZ_RXQ_ID, spec->fsfs_dmaq_id,
849 EFX_DWORD_2, spec->fsfs_dword[2],
850 EFX_DWORD_1, spec->fsfs_dword[1],
851 EFX_DWORD_0, spec->fsfs_dword[0]);
857 case EFX_FS_FILTER_TBL_RX_MAC: {
858 boolean_t is_wild = (type == EFX_FS_FILTER_RX_MAC_WILD);
859 EFX_POPULATE_OWORD_7(*filter,
861 (flags & EFX_FILTER_FLAG_RX_RSS) ? 1 : 0,
862 FRF_CZ_RMFT_SCATTER_EN,
863 (flags & EFX_FILTER_FLAG_RX_SCATTER) ? 1 : 0,
864 FRF_CZ_RMFT_RXQ_ID, spec->fsfs_dmaq_id,
865 FRF_CZ_RMFT_WILDCARD_MATCH, is_wild,
866 FRF_CZ_RMFT_DEST_MAC_DW1, spec->fsfs_dword[2],
867 FRF_CZ_RMFT_DEST_MAC_DW0, spec->fsfs_dword[1],
868 FRF_CZ_RMFT_VLAN_ID, spec->fsfs_dword[0]);
872 #endif /* EFSYS_OPT_SIENA */
874 case EFX_FS_FILTER_TBL_TX_IP: {
875 boolean_t is_udp = (type == EFX_FS_FILTER_TX_UDP_FULL ||
876 type == EFX_FS_FILTER_TX_UDP_WILD);
877 EFX_POPULATE_OWORD_5(*filter,
878 FRF_CZ_TIFT_TCP_UDP, is_udp,
879 FRF_CZ_TIFT_TXQ_ID, spec->fsfs_dmaq_id,
880 EFX_DWORD_2, spec->fsfs_dword[2],
881 EFX_DWORD_1, spec->fsfs_dword[1],
882 EFX_DWORD_0, spec->fsfs_dword[0]);
883 dword3 = is_udp | spec->fsfs_dmaq_id << 1;
888 case EFX_FS_FILTER_TBL_TX_MAC: {
889 boolean_t is_wild = (type == EFX_FS_FILTER_TX_MAC_WILD);
890 EFX_POPULATE_OWORD_5(*filter,
891 FRF_CZ_TMFT_TXQ_ID, spec->fsfs_dmaq_id,
892 FRF_CZ_TMFT_WILDCARD_MATCH, is_wild,
893 FRF_CZ_TMFT_SRC_MAC_DW1, spec->fsfs_dword[2],
894 FRF_CZ_TMFT_SRC_MAC_DW0, spec->fsfs_dword[1],
895 FRF_CZ_TMFT_VLAN_ID, spec->fsfs_dword[0]);
896 dword3 = is_wild | spec->fsfs_dmaq_id << 1;
899 #endif /* EFSYS_OPT_SIENA */
902 EFSYS_ASSERT(B_FALSE);
907 spec->fsfs_dword[0] ^
908 spec->fsfs_dword[1] ^
909 spec->fsfs_dword[2] ^
915 static __checkReturn efx_rc_t
916 falconsiena_filter_push_entry(
917 __inout efx_nic_t *enp,
918 __in falconsiena_filter_type_t type,
920 __in efx_oword_t *eop)
925 case EFX_FS_FILTER_RX_TCP_FULL:
926 case EFX_FS_FILTER_RX_TCP_WILD:
927 case EFX_FS_FILTER_RX_UDP_FULL:
928 case EFX_FS_FILTER_RX_UDP_WILD:
929 EFX_BAR_TBL_WRITEO(enp, FR_AZ_RX_FILTER_TBL0, index,
934 case EFX_FS_FILTER_RX_MAC_FULL:
935 case EFX_FS_FILTER_RX_MAC_WILD:
936 EFX_BAR_TBL_WRITEO(enp, FR_CZ_RX_MAC_FILTER_TBL0, index,
940 case EFX_FS_FILTER_TX_TCP_FULL:
941 case EFX_FS_FILTER_TX_TCP_WILD:
942 case EFX_FS_FILTER_TX_UDP_FULL:
943 case EFX_FS_FILTER_TX_UDP_WILD:
944 EFX_BAR_TBL_WRITEO(enp, FR_CZ_TX_FILTER_TBL0, index,
948 case EFX_FS_FILTER_TX_MAC_FULL:
949 case EFX_FS_FILTER_TX_MAC_WILD:
950 EFX_BAR_TBL_WRITEO(enp, FR_CZ_TX_MAC_FILTER_TBL0, index,
953 #endif /* EFSYS_OPT_SIENA */
956 EFSYS_ASSERT(B_FALSE);
967 static __checkReturn boolean_t
968 falconsiena_filter_equal(
969 __in const falconsiena_filter_spec_t *left,
970 __in const falconsiena_filter_spec_t *right)
972 falconsiena_filter_tbl_id_t tbl_id;
974 tbl_id = falconsiena_filter_tbl_id(left->fsfs_type);
977 if (left->fsfs_type != right->fsfs_type)
980 if (memcmp(left->fsfs_dword, right->fsfs_dword,
981 sizeof (left->fsfs_dword)))
984 if ((tbl_id == EFX_FS_FILTER_TBL_TX_IP ||
985 tbl_id == EFX_FS_FILTER_TBL_TX_MAC) &&
986 left->fsfs_dmaq_id != right->fsfs_dmaq_id)
992 static __checkReturn efx_rc_t
993 falconsiena_filter_search(
994 __in falconsiena_filter_tbl_t *fsftp,
995 __in falconsiena_filter_spec_t *spec,
997 __in boolean_t for_insert,
998 __out int *filter_index,
999 __out unsigned int *depth_required)
1001 unsigned hash, incr, filter_idx, depth;
1003 hash = falconsiena_filter_tbl_hash(key);
1004 incr = falconsiena_filter_tbl_increment(key);
1006 filter_idx = hash & (fsftp->fsft_size - 1);
1011 * Return success if entry is used and matches this spec
1012 * or entry is unused and we are trying to insert.
1014 if (falconsiena_filter_test_used(fsftp, filter_idx) ?
1015 falconsiena_filter_equal(spec,
1016 &fsftp->fsft_spec[filter_idx]) :
1018 *filter_index = filter_idx;
1019 *depth_required = depth;
1023 /* Return failure if we reached the maximum search depth */
1024 if (depth == FILTER_CTL_SRCH_MAX)
1025 return (for_insert ? EBUSY : ENOENT);
1027 filter_idx = (filter_idx + incr) & (fsftp->fsft_size - 1);
1033 falconsiena_filter_clear_entry(
1034 __in efx_nic_t *enp,
1035 __in falconsiena_filter_tbl_t *fsftp,
1040 if (falconsiena_filter_test_used(fsftp, index)) {
1041 falconsiena_filter_clear_used(fsftp, index);
1043 EFX_ZERO_OWORD(filter);
1044 falconsiena_filter_push_entry(enp,
1045 fsftp->fsft_spec[index].fsfs_type,
1048 memset(&fsftp->fsft_spec[index],
1049 0, sizeof (fsftp->fsft_spec[0]));
1054 falconsiena_filter_tbl_clear(
1055 __in efx_nic_t *enp,
1056 __in falconsiena_filter_tbl_id_t tbl_id)
1058 falconsiena_filter_t *fsfp = enp->en_filter.ef_falconsiena_filter;
1059 falconsiena_filter_tbl_t *fsftp = &fsfp->fsf_tbl[tbl_id];
1063 EFSYS_LOCK(enp->en_eslp, state);
1065 for (index = 0; index < fsftp->fsft_size; ++index) {
1066 falconsiena_filter_clear_entry(enp, fsftp, index);
1069 if (fsftp->fsft_used == 0)
1070 falconsiena_filter_reset_search_depth(fsfp, tbl_id);
1072 EFSYS_UNLOCK(enp->en_eslp, state);
1075 static __checkReturn efx_rc_t
1076 falconsiena_filter_init(
1077 __in efx_nic_t *enp)
1079 falconsiena_filter_t *fsfp;
1080 falconsiena_filter_tbl_t *fsftp;
1084 EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (falconsiena_filter_t), fsfp);
1091 enp->en_filter.ef_falconsiena_filter = fsfp;
1093 switch (enp->en_family) {
1094 #if EFSYS_OPT_FALCON
1095 case EFX_FAMILY_FALCON:
1096 fsftp = &fsfp->fsf_tbl[EFX_FS_FILTER_TBL_RX_IP];
1097 fsftp->fsft_size = FR_AZ_RX_FILTER_TBL0_ROWS;
1099 #endif /* EFSYS_OPT_FALCON */
1102 case EFX_FAMILY_SIENA:
1103 fsftp = &fsfp->fsf_tbl[EFX_FS_FILTER_TBL_RX_IP];
1104 fsftp->fsft_size = FR_AZ_RX_FILTER_TBL0_ROWS;
1106 fsftp = &fsfp->fsf_tbl[EFX_FS_FILTER_TBL_RX_MAC];
1107 fsftp->fsft_size = FR_CZ_RX_MAC_FILTER_TBL0_ROWS;
1109 fsftp = &fsfp->fsf_tbl[EFX_FS_FILTER_TBL_TX_IP];
1110 fsftp->fsft_size = FR_CZ_TX_FILTER_TBL0_ROWS;
1112 fsftp = &fsfp->fsf_tbl[EFX_FS_FILTER_TBL_TX_MAC];
1113 fsftp->fsft_size = FR_CZ_TX_MAC_FILTER_TBL0_ROWS;
1115 #endif /* EFSYS_OPT_SIENA */
1122 for (tbl_id = 0; tbl_id < EFX_FS_FILTER_NTBLS; tbl_id++) {
1123 unsigned int bitmap_size;
1125 fsftp = &fsfp->fsf_tbl[tbl_id];
1126 if (fsftp->fsft_size == 0)
1129 EFX_STATIC_ASSERT(sizeof (fsftp->fsft_bitmap[0]) ==
1132 (fsftp->fsft_size + (sizeof (uint32_t) * 8) - 1) / 8;
1134 EFSYS_KMEM_ALLOC(enp->en_esip, bitmap_size, fsftp->fsft_bitmap);
1135 if (!fsftp->fsft_bitmap) {
1140 EFSYS_KMEM_ALLOC(enp->en_esip,
1141 fsftp->fsft_size * sizeof (*fsftp->fsft_spec),
1143 if (!fsftp->fsft_spec) {
1147 memset(fsftp->fsft_spec, 0,
1148 fsftp->fsft_size * sizeof (*fsftp->fsft_spec));
1161 falconsiena_filter_fini(enp);
1164 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1169 falconsiena_filter_fini(
1170 __in efx_nic_t *enp)
1172 falconsiena_filter_t *fsfp = enp->en_filter.ef_falconsiena_filter;
1173 falconsiena_filter_tbl_id_t tbl_id;
1175 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1176 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1181 for (tbl_id = 0; tbl_id < EFX_FS_FILTER_NTBLS; tbl_id++) {
1182 falconsiena_filter_tbl_t *fsftp = &fsfp->fsf_tbl[tbl_id];
1183 unsigned int bitmap_size;
1185 EFX_STATIC_ASSERT(sizeof (fsftp->fsft_bitmap[0]) ==
1188 (fsftp->fsft_size + (sizeof (uint32_t) * 8) - 1) / 8;
1190 if (fsftp->fsft_bitmap != NULL) {
1191 EFSYS_KMEM_FREE(enp->en_esip, bitmap_size,
1192 fsftp->fsft_bitmap);
1193 fsftp->fsft_bitmap = NULL;
1196 if (fsftp->fsft_spec != NULL) {
1197 EFSYS_KMEM_FREE(enp->en_esip, fsftp->fsft_size *
1198 sizeof (*fsftp->fsft_spec), fsftp->fsft_spec);
1199 fsftp->fsft_spec = NULL;
1203 EFSYS_KMEM_FREE(enp->en_esip, sizeof (falconsiena_filter_t),
1204 enp->en_filter.ef_falconsiena_filter);
1207 /* Restore filter state after a reset */
1208 static __checkReturn efx_rc_t
1209 falconsiena_filter_restore(
1210 __in efx_nic_t *enp)
1212 falconsiena_filter_t *fsfp = enp->en_filter.ef_falconsiena_filter;
1213 falconsiena_filter_tbl_id_t tbl_id;
1214 falconsiena_filter_tbl_t *fsftp;
1215 falconsiena_filter_spec_t *spec;
1221 EFSYS_LOCK(enp->en_eslp, state);
1223 for (tbl_id = 0; tbl_id < EFX_FS_FILTER_NTBLS; tbl_id++) {
1224 fsftp = &fsfp->fsf_tbl[tbl_id];
1225 for (filter_idx = 0;
1226 filter_idx < fsftp->fsft_size;
1228 if (!falconsiena_filter_test_used(fsftp, filter_idx))
1231 spec = &fsftp->fsft_spec[filter_idx];
1232 if ((rc = falconsiena_filter_build(&filter, spec)) != 0)
1234 if ((rc = falconsiena_filter_push_entry(enp,
1235 spec->fsfs_type, filter_idx, &filter)) != 0)
1240 falconsiena_filter_push_rx_limits(enp);
1241 falconsiena_filter_push_tx_limits(enp);
1243 EFSYS_UNLOCK(enp->en_eslp, state);
1251 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1253 EFSYS_UNLOCK(enp->en_eslp, state);
1258 static __checkReturn efx_rc_t
1259 falconsiena_filter_add(
1260 __in efx_nic_t *enp,
1261 __inout efx_filter_spec_t *spec,
1262 __in boolean_t may_replace)
1265 falconsiena_filter_spec_t fs_spec;
1266 falconsiena_filter_t *fsfp = enp->en_filter.ef_falconsiena_filter;
1267 falconsiena_filter_tbl_id_t tbl_id;
1268 falconsiena_filter_tbl_t *fsftp;
1269 falconsiena_filter_spec_t *saved_fs_spec;
1277 EFSYS_ASSERT3P(spec, !=, NULL);
1279 if ((rc = falconsiena_filter_spec_from_gen_spec(&fs_spec, spec)) != 0)
1282 tbl_id = falconsiena_filter_tbl_id(fs_spec.fsfs_type);
1283 fsftp = &fsfp->fsf_tbl[tbl_id];
1285 if (fsftp->fsft_size == 0) {
1290 key = falconsiena_filter_build(&filter, &fs_spec);
1292 EFSYS_LOCK(enp->en_eslp, state);
1294 rc = falconsiena_filter_search(fsftp, &fs_spec, key, B_TRUE,
1295 &filter_idx, &depth);
1299 EFSYS_ASSERT3U(filter_idx, <, fsftp->fsft_size);
1300 saved_fs_spec = &fsftp->fsft_spec[filter_idx];
1302 if (falconsiena_filter_test_used(fsftp, filter_idx)) {
1303 if (may_replace == B_FALSE) {
1308 falconsiena_filter_set_used(fsftp, filter_idx);
1309 *saved_fs_spec = fs_spec;
1311 if (fsfp->fsf_depth[fs_spec.fsfs_type] < depth) {
1312 fsfp->fsf_depth[fs_spec.fsfs_type] = depth;
1313 if (tbl_id == EFX_FS_FILTER_TBL_TX_IP ||
1314 tbl_id == EFX_FS_FILTER_TBL_TX_MAC)
1315 falconsiena_filter_push_tx_limits(enp);
1317 falconsiena_filter_push_rx_limits(enp);
1320 falconsiena_filter_push_entry(enp, fs_spec.fsfs_type,
1321 filter_idx, &filter);
1323 EFSYS_UNLOCK(enp->en_eslp, state);
1330 EFSYS_UNLOCK(enp->en_eslp, state);
1337 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1341 static __checkReturn efx_rc_t
1342 falconsiena_filter_delete(
1343 __in efx_nic_t *enp,
1344 __inout efx_filter_spec_t *spec)
1347 falconsiena_filter_spec_t fs_spec;
1348 falconsiena_filter_t *fsfp = enp->en_filter.ef_falconsiena_filter;
1349 falconsiena_filter_tbl_id_t tbl_id;
1350 falconsiena_filter_tbl_t *fsftp;
1357 EFSYS_ASSERT3P(spec, !=, NULL);
1359 if ((rc = falconsiena_filter_spec_from_gen_spec(&fs_spec, spec)) != 0)
1362 tbl_id = falconsiena_filter_tbl_id(fs_spec.fsfs_type);
1363 fsftp = &fsfp->fsf_tbl[tbl_id];
1365 key = falconsiena_filter_build(&filter, &fs_spec);
1367 EFSYS_LOCK(enp->en_eslp, state);
1369 rc = falconsiena_filter_search(fsftp, &fs_spec, key, B_FALSE,
1370 &filter_idx, &depth);
1374 falconsiena_filter_clear_entry(enp, fsftp, filter_idx);
1375 if (fsftp->fsft_used == 0)
1376 falconsiena_filter_reset_search_depth(fsfp, tbl_id);
1378 EFSYS_UNLOCK(enp->en_eslp, state);
1382 EFSYS_UNLOCK(enp->en_eslp, state);
1386 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1390 #define MAX_SUPPORTED 4
1392 static __checkReturn efx_rc_t
1393 falconsiena_filter_supported_filters(
1394 __in efx_nic_t *enp,
1395 __out uint32_t *list,
1396 __out size_t *length)
1399 uint32_t rx_matches[MAX_SUPPORTED];
1407 rx_matches[index++] =
1408 EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
1409 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT |
1410 EFX_FILTER_MATCH_REM_HOST | EFX_FILTER_MATCH_REM_PORT;
1412 rx_matches[index++] =
1413 EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
1414 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT;
1416 if (enp->en_features & EFX_FEATURE_MAC_HEADER_FILTERS) {
1417 rx_matches[index++] =
1418 EFX_FILTER_MATCH_OUTER_VID | EFX_FILTER_MATCH_LOC_MAC;
1420 rx_matches[index++] = EFX_FILTER_MATCH_LOC_MAC;
1423 EFSYS_ASSERT3U(index, <=, MAX_SUPPORTED);
1426 memcpy(list, rx_matches, *length);
1435 #undef MAX_SUPPORTED
1437 #endif /* EFSYS_OPT_FALCON || EFSYS_OPT_SIENA */
1439 #endif /* EFSYS_OPT_FILTER */