1 /* SPDX-License-Identifier: BSD-3-Clause
3 * Copyright (c) 2007-2018 Solarflare Communications Inc.
15 static __checkReturn efx_rc_t
23 static __checkReturn efx_rc_t
27 static __checkReturn efx_rc_t
30 __inout efx_filter_spec_t *spec,
31 __in boolean_t may_replace);
33 static __checkReturn efx_rc_t
36 __inout efx_filter_spec_t *spec);
38 static __checkReturn efx_rc_t
39 siena_filter_supported_filters(
41 __out_ecount(buffer_length) uint32_t *buffer,
42 __in size_t buffer_length,
43 __out size_t *list_lengthp);
45 #endif /* EFSYS_OPT_SIENA */
48 static const efx_filter_ops_t __efx_filter_siena_ops = {
49 siena_filter_init, /* efo_init */
50 siena_filter_fini, /* efo_fini */
51 siena_filter_restore, /* efo_restore */
52 siena_filter_add, /* efo_add */
53 siena_filter_delete, /* efo_delete */
54 siena_filter_supported_filters, /* efo_supported_filters */
55 NULL, /* efo_reconfigure */
57 #endif /* EFSYS_OPT_SIENA */
59 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
60 static const efx_filter_ops_t __efx_filter_ef10_ops = {
61 ef10_filter_init, /* efo_init */
62 ef10_filter_fini, /* efo_fini */
63 ef10_filter_restore, /* efo_restore */
64 ef10_filter_add, /* efo_add */
65 ef10_filter_delete, /* efo_delete */
66 ef10_filter_supported_filters, /* efo_supported_filters */
67 ef10_filter_reconfigure, /* efo_reconfigure */
69 #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
71 __checkReturn efx_rc_t
74 __inout efx_filter_spec_t *spec)
76 const efx_filter_ops_t *efop = enp->en_efop;
78 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
79 EFSYS_ASSERT3P(spec, !=, NULL);
80 EFSYS_ASSERT3U(spec->efs_flags, &, EFX_FILTER_FLAG_RX);
82 return (efop->efo_add(enp, spec, B_FALSE));
85 __checkReturn efx_rc_t
88 __inout efx_filter_spec_t *spec)
90 const efx_filter_ops_t *efop = enp->en_efop;
92 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
93 EFSYS_ASSERT3P(spec, !=, NULL);
94 EFSYS_ASSERT3U(spec->efs_flags, &, EFX_FILTER_FLAG_RX);
96 return (efop->efo_delete(enp, spec));
99 __checkReturn efx_rc_t
105 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
107 if ((rc = enp->en_efop->efo_restore(enp)) != 0)
113 EFSYS_PROBE1(fail1, efx_rc_t, rc);
118 __checkReturn efx_rc_t
122 const efx_filter_ops_t *efop;
125 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
126 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
127 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_FILTER));
129 switch (enp->en_family) {
131 case EFX_FAMILY_SIENA:
132 efop = &__efx_filter_siena_ops;
134 #endif /* EFSYS_OPT_SIENA */
136 #if EFSYS_OPT_HUNTINGTON
137 case EFX_FAMILY_HUNTINGTON:
138 efop = &__efx_filter_ef10_ops;
140 #endif /* EFSYS_OPT_HUNTINGTON */
142 #if EFSYS_OPT_MEDFORD
143 case EFX_FAMILY_MEDFORD:
144 efop = &__efx_filter_ef10_ops;
146 #endif /* EFSYS_OPT_MEDFORD */
148 #if EFSYS_OPT_MEDFORD2
149 case EFX_FAMILY_MEDFORD2:
150 efop = &__efx_filter_ef10_ops;
152 #endif /* EFSYS_OPT_MEDFORD2 */
160 if ((rc = efop->efo_init(enp)) != 0)
164 enp->en_mod_flags |= EFX_MOD_FILTER;
170 EFSYS_PROBE1(fail1, efx_rc_t, rc);
173 enp->en_mod_flags &= ~EFX_MOD_FILTER;
181 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
182 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
183 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
185 enp->en_efop->efo_fini(enp);
188 enp->en_mod_flags &= ~EFX_MOD_FILTER;
192 * Query the possible combinations of match flags which can be filtered on.
193 * These are returned as a list, of which each 32 bit element is a bitmask
194 * formed of EFX_FILTER_MATCH flags.
196 * The combinations are ordered in priority from highest to lowest.
198 * If the provided buffer is too short to hold the list, the call with fail with
199 * ENOSPC and *list_lengthp will be set to the buffer length required.
201 __checkReturn efx_rc_t
202 efx_filter_supported_filters(
204 __out_ecount(buffer_length) uint32_t *buffer,
205 __in size_t buffer_length,
206 __out size_t *list_lengthp)
210 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
211 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
212 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
213 EFSYS_ASSERT(enp->en_efop->efo_supported_filters != NULL);
215 if (buffer == NULL) {
220 rc = enp->en_efop->efo_supported_filters(enp, buffer, buffer_length,
230 EFSYS_PROBE1(fail1, efx_rc_t, rc);
235 __checkReturn efx_rc_t
236 efx_filter_reconfigure(
238 __in_ecount(6) uint8_t const *mac_addr,
239 __in boolean_t all_unicst,
240 __in boolean_t mulcst,
241 __in boolean_t all_mulcst,
242 __in boolean_t brdcst,
243 __in_ecount(6*count) uint8_t const *addrs,
248 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
249 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
250 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
252 if (enp->en_efop->efo_reconfigure != NULL) {
253 if ((rc = enp->en_efop->efo_reconfigure(enp, mac_addr,
263 EFSYS_PROBE1(fail1, efx_rc_t, rc);
269 efx_filter_spec_init_rx(
270 __out efx_filter_spec_t *spec,
271 __in efx_filter_priority_t priority,
272 __in efx_filter_flags_t flags,
275 EFSYS_ASSERT3P(spec, !=, NULL);
276 EFSYS_ASSERT3P(erp, !=, NULL);
277 EFSYS_ASSERT((flags & ~(EFX_FILTER_FLAG_RX_RSS |
278 EFX_FILTER_FLAG_RX_SCATTER)) == 0);
280 memset(spec, 0, sizeof (*spec));
281 spec->efs_priority = priority;
282 spec->efs_flags = EFX_FILTER_FLAG_RX | flags;
283 spec->efs_rss_context = EFX_RSS_CONTEXT_DEFAULT;
284 spec->efs_dmaq_id = (uint16_t)erp->er_index;
288 efx_filter_spec_init_tx(
289 __out efx_filter_spec_t *spec,
292 EFSYS_ASSERT3P(spec, !=, NULL);
293 EFSYS_ASSERT3P(etp, !=, NULL);
295 memset(spec, 0, sizeof (*spec));
296 spec->efs_priority = EFX_FILTER_PRI_REQUIRED;
297 spec->efs_flags = EFX_FILTER_FLAG_TX;
298 spec->efs_dmaq_id = (uint16_t)etp->et_index;
303 * Specify IPv4 host, transport protocol and port in a filter specification
305 __checkReturn efx_rc_t
306 efx_filter_spec_set_ipv4_local(
307 __inout efx_filter_spec_t *spec,
312 EFSYS_ASSERT3P(spec, !=, NULL);
314 spec->efs_match_flags |=
315 EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
316 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT;
317 spec->efs_ether_type = EFX_ETHER_TYPE_IPV4;
318 spec->efs_ip_proto = proto;
319 spec->efs_loc_host.eo_u32[0] = host;
320 spec->efs_loc_port = port;
325 * Specify IPv4 hosts, transport protocol and ports in a filter specification
327 __checkReturn efx_rc_t
328 efx_filter_spec_set_ipv4_full(
329 __inout efx_filter_spec_t *spec,
336 EFSYS_ASSERT3P(spec, !=, NULL);
338 spec->efs_match_flags |=
339 EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
340 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT |
341 EFX_FILTER_MATCH_REM_HOST | EFX_FILTER_MATCH_REM_PORT;
342 spec->efs_ether_type = EFX_ETHER_TYPE_IPV4;
343 spec->efs_ip_proto = proto;
344 spec->efs_loc_host.eo_u32[0] = lhost;
345 spec->efs_loc_port = lport;
346 spec->efs_rem_host.eo_u32[0] = rhost;
347 spec->efs_rem_port = rport;
352 * Specify local Ethernet address and/or VID in filter specification
354 __checkReturn efx_rc_t
355 efx_filter_spec_set_eth_local(
356 __inout efx_filter_spec_t *spec,
358 __in const uint8_t *addr)
360 EFSYS_ASSERT3P(spec, !=, NULL);
361 EFSYS_ASSERT3P(addr, !=, NULL);
363 if (vid == EFX_FILTER_SPEC_VID_UNSPEC && addr == NULL)
366 if (vid != EFX_FILTER_SPEC_VID_UNSPEC) {
367 spec->efs_match_flags |= EFX_FILTER_MATCH_OUTER_VID;
368 spec->efs_outer_vid = vid;
371 spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_MAC;
372 memcpy(spec->efs_loc_mac, addr, EFX_MAC_ADDR_LEN);
378 efx_filter_spec_set_ether_type(
379 __inout efx_filter_spec_t *spec,
380 __in uint16_t ether_type)
382 EFSYS_ASSERT3P(spec, !=, NULL);
384 spec->efs_ether_type = ether_type;
385 spec->efs_match_flags |= EFX_FILTER_MATCH_ETHER_TYPE;
389 * Specify matching otherwise-unmatched unicast in a filter specification
391 __checkReturn efx_rc_t
392 efx_filter_spec_set_uc_def(
393 __inout efx_filter_spec_t *spec)
395 EFSYS_ASSERT3P(spec, !=, NULL);
397 spec->efs_match_flags |= EFX_FILTER_MATCH_UNKNOWN_UCAST_DST;
402 * Specify matching otherwise-unmatched multicast in a filter specification
404 __checkReturn efx_rc_t
405 efx_filter_spec_set_mc_def(
406 __inout efx_filter_spec_t *spec)
408 EFSYS_ASSERT3P(spec, !=, NULL);
410 spec->efs_match_flags |= EFX_FILTER_MATCH_UNKNOWN_MCAST_DST;
415 __checkReturn efx_rc_t
416 efx_filter_spec_set_encap_type(
417 __inout efx_filter_spec_t *spec,
418 __in efx_tunnel_protocol_t encap_type,
419 __in efx_filter_inner_frame_match_t inner_frame_match)
421 uint32_t match_flags = EFX_FILTER_MATCH_ENCAP_TYPE;
425 EFSYS_ASSERT3P(spec, !=, NULL);
427 switch (encap_type) {
428 case EFX_TUNNEL_PROTOCOL_VXLAN:
429 case EFX_TUNNEL_PROTOCOL_GENEVE:
430 ip_proto = EFX_IPPROTO_UDP;
432 case EFX_TUNNEL_PROTOCOL_NVGRE:
433 ip_proto = EFX_IPPROTO_GRE;
441 switch (inner_frame_match) {
442 case EFX_FILTER_INNER_FRAME_MATCH_UNKNOWN_MCAST_DST:
443 match_flags |= EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST;
445 case EFX_FILTER_INNER_FRAME_MATCH_UNKNOWN_UCAST_DST:
446 match_flags |= EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST;
448 case EFX_FILTER_INNER_FRAME_MATCH_OTHER:
449 /* This is for when specific inner frames are to be matched. */
457 spec->efs_encap_type = encap_type;
458 spec->efs_ip_proto = ip_proto;
459 spec->efs_match_flags |= (match_flags | EFX_FILTER_MATCH_IP_PROTO);
466 EFSYS_PROBE1(fail1, efx_rc_t, rc);
472 * Specify inner and outer Ethernet address and VXLAN ID in filter
475 __checkReturn efx_rc_t
476 efx_filter_spec_set_vxlan_full(
477 __inout efx_filter_spec_t *spec,
478 __in const uint8_t *vxlan_id,
479 __in const uint8_t *inner_addr,
480 __in const uint8_t *outer_addr)
482 EFSYS_ASSERT3P(spec, !=, NULL);
483 EFSYS_ASSERT3P(vxlan_id, !=, NULL);
484 EFSYS_ASSERT3P(inner_addr, !=, NULL);
485 EFSYS_ASSERT3P(outer_addr, !=, NULL);
487 if ((inner_addr == NULL) && (outer_addr == NULL))
490 if (vxlan_id != NULL) {
491 spec->efs_match_flags |= EFX_FILTER_MATCH_VNI_OR_VSID;
492 memcpy(spec->efs_vni_or_vsid, vxlan_id, EFX_VNI_OR_VSID_LEN);
494 if (outer_addr != NULL) {
495 spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_MAC;
496 memcpy(spec->efs_loc_mac, outer_addr, EFX_MAC_ADDR_LEN);
498 if (inner_addr != NULL) {
499 spec->efs_match_flags |= EFX_FILTER_MATCH_IFRM_LOC_MAC;
500 memcpy(spec->efs_ifrm_loc_mac, inner_addr, EFX_MAC_ADDR_LEN);
502 spec->efs_match_flags |= EFX_FILTER_MATCH_ENCAP_TYPE;
503 spec->efs_encap_type = EFX_TUNNEL_PROTOCOL_VXLAN;
508 #if EFSYS_OPT_RX_SCALE
509 __checkReturn efx_rc_t
510 efx_filter_spec_set_rss_context(
511 __inout efx_filter_spec_t *spec,
512 __in uint32_t rss_context)
516 EFSYS_ASSERT3P(spec, !=, NULL);
518 /* The filter must have been created with EFX_FILTER_FLAG_RX_RSS. */
519 if ((spec->efs_flags & EFX_FILTER_FLAG_RX_RSS) == 0) {
524 spec->efs_rss_context = rss_context;
529 EFSYS_PROBE1(fail1, efx_rc_t, rc);
538 * "Fudge factors" - difference between programmed value and actual depth.
539 * Due to pipelined implementation we need to program H/W with a value that
540 * is larger than the hop limit we want.
542 #define FILTER_CTL_SRCH_FUDGE_WILD 3
543 #define FILTER_CTL_SRCH_FUDGE_FULL 1
546 * Hard maximum hop limit. Hardware will time-out beyond 200-something.
547 * We also need to avoid infinite loops in efx_filter_search() when the
550 #define FILTER_CTL_SRCH_MAX 200
552 static __checkReturn efx_rc_t
553 siena_filter_spec_from_gen_spec(
554 __out siena_filter_spec_t *sf_spec,
555 __in efx_filter_spec_t *gen_spec)
558 boolean_t is_full = B_FALSE;
560 if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX)
561 EFSYS_ASSERT3U(gen_spec->efs_flags, ==, EFX_FILTER_FLAG_TX);
563 EFSYS_ASSERT3U(gen_spec->efs_flags, &, EFX_FILTER_FLAG_RX);
565 /* Siena only has one RSS context */
566 if ((gen_spec->efs_flags & EFX_FILTER_FLAG_RX_RSS) &&
567 gen_spec->efs_rss_context != EFX_RSS_CONTEXT_DEFAULT) {
572 sf_spec->sfs_flags = gen_spec->efs_flags;
573 sf_spec->sfs_dmaq_id = gen_spec->efs_dmaq_id;
575 switch (gen_spec->efs_match_flags) {
576 case EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
577 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT |
578 EFX_FILTER_MATCH_REM_HOST | EFX_FILTER_MATCH_REM_PORT:
581 case EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
582 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT: {
583 uint32_t rhost, host1, host2;
584 uint16_t rport, port1, port2;
586 if (gen_spec->efs_ether_type != EFX_ETHER_TYPE_IPV4) {
590 if (gen_spec->efs_loc_port == 0 ||
591 (is_full && gen_spec->efs_rem_port == 0)) {
595 switch (gen_spec->efs_ip_proto) {
596 case EFX_IPPROTO_TCP:
597 if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX) {
598 sf_spec->sfs_type = (is_full ?
599 EFX_SIENA_FILTER_TX_TCP_FULL :
600 EFX_SIENA_FILTER_TX_TCP_WILD);
602 sf_spec->sfs_type = (is_full ?
603 EFX_SIENA_FILTER_RX_TCP_FULL :
604 EFX_SIENA_FILTER_RX_TCP_WILD);
607 case EFX_IPPROTO_UDP:
608 if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX) {
609 sf_spec->sfs_type = (is_full ?
610 EFX_SIENA_FILTER_TX_UDP_FULL :
611 EFX_SIENA_FILTER_TX_UDP_WILD);
613 sf_spec->sfs_type = (is_full ?
614 EFX_SIENA_FILTER_RX_UDP_FULL :
615 EFX_SIENA_FILTER_RX_UDP_WILD);
623 * The filter is constructed in terms of source and destination,
624 * with the odd wrinkle that the ports are swapped in a UDP
625 * wildcard filter. We need to convert from local and remote
626 * addresses (zero for a wildcard).
628 rhost = is_full ? gen_spec->efs_rem_host.eo_u32[0] : 0;
629 rport = is_full ? gen_spec->efs_rem_port : 0;
630 if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX) {
631 host1 = gen_spec->efs_loc_host.eo_u32[0];
635 host2 = gen_spec->efs_loc_host.eo_u32[0];
637 if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX) {
638 if (sf_spec->sfs_type ==
639 EFX_SIENA_FILTER_TX_UDP_WILD) {
641 port2 = gen_spec->efs_loc_port;
643 port1 = gen_spec->efs_loc_port;
647 if (sf_spec->sfs_type ==
648 EFX_SIENA_FILTER_RX_UDP_WILD) {
649 port1 = gen_spec->efs_loc_port;
653 port2 = gen_spec->efs_loc_port;
656 sf_spec->sfs_dword[0] = (host1 << 16) | port1;
657 sf_spec->sfs_dword[1] = (port2 << 16) | (host1 >> 16);
658 sf_spec->sfs_dword[2] = host2;
662 case EFX_FILTER_MATCH_LOC_MAC | EFX_FILTER_MATCH_OUTER_VID:
665 case EFX_FILTER_MATCH_LOC_MAC:
666 if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX) {
667 sf_spec->sfs_type = (is_full ?
668 EFX_SIENA_FILTER_TX_MAC_FULL :
669 EFX_SIENA_FILTER_TX_MAC_WILD);
671 sf_spec->sfs_type = (is_full ?
672 EFX_SIENA_FILTER_RX_MAC_FULL :
673 EFX_SIENA_FILTER_RX_MAC_WILD);
675 sf_spec->sfs_dword[0] = is_full ? gen_spec->efs_outer_vid : 0;
676 sf_spec->sfs_dword[1] =
677 gen_spec->efs_loc_mac[2] << 24 |
678 gen_spec->efs_loc_mac[3] << 16 |
679 gen_spec->efs_loc_mac[4] << 8 |
680 gen_spec->efs_loc_mac[5];
681 sf_spec->sfs_dword[2] =
682 gen_spec->efs_loc_mac[0] << 8 |
683 gen_spec->efs_loc_mac[1];
687 EFSYS_ASSERT(B_FALSE);
703 EFSYS_PROBE1(fail1, efx_rc_t, rc);
709 * The filter hash function is LFSR polynomial x^16 + x^3 + 1 of a 32-bit
710 * key derived from the n-tuple.
713 siena_filter_tbl_hash(
718 /* First 16 rounds */
719 tmp = 0x1fff ^ (uint16_t)(key >> 16);
720 tmp = tmp ^ tmp >> 3 ^ tmp >> 6;
721 tmp = tmp ^ tmp >> 9;
724 tmp = tmp ^ tmp << 13 ^ (uint16_t)(key & 0xffff);
725 tmp = tmp ^ tmp >> 3 ^ tmp >> 6;
726 tmp = tmp ^ tmp >> 9;
732 * To allow for hash collisions, filter search continues at these
733 * increments from the first possible entry selected by the hash.
736 siena_filter_tbl_increment(
739 return ((uint16_t)(key * 2 - 1));
742 static __checkReturn boolean_t
743 siena_filter_test_used(
744 __in siena_filter_tbl_t *sftp,
745 __in unsigned int index)
747 EFSYS_ASSERT3P(sftp->sft_bitmap, !=, NULL);
748 return ((sftp->sft_bitmap[index / 32] & (1 << (index % 32))) != 0);
752 siena_filter_set_used(
753 __in siena_filter_tbl_t *sftp,
754 __in unsigned int index)
756 EFSYS_ASSERT3P(sftp->sft_bitmap, !=, NULL);
757 sftp->sft_bitmap[index / 32] |= (1 << (index % 32));
762 siena_filter_clear_used(
763 __in siena_filter_tbl_t *sftp,
764 __in unsigned int index)
766 EFSYS_ASSERT3P(sftp->sft_bitmap, !=, NULL);
767 sftp->sft_bitmap[index / 32] &= ~(1 << (index % 32));
770 EFSYS_ASSERT3U(sftp->sft_used, >=, 0);
774 static siena_filter_tbl_id_t
776 __in siena_filter_type_t type)
778 siena_filter_tbl_id_t tbl_id;
781 case EFX_SIENA_FILTER_RX_TCP_FULL:
782 case EFX_SIENA_FILTER_RX_TCP_WILD:
783 case EFX_SIENA_FILTER_RX_UDP_FULL:
784 case EFX_SIENA_FILTER_RX_UDP_WILD:
785 tbl_id = EFX_SIENA_FILTER_TBL_RX_IP;
788 case EFX_SIENA_FILTER_RX_MAC_FULL:
789 case EFX_SIENA_FILTER_RX_MAC_WILD:
790 tbl_id = EFX_SIENA_FILTER_TBL_RX_MAC;
793 case EFX_SIENA_FILTER_TX_TCP_FULL:
794 case EFX_SIENA_FILTER_TX_TCP_WILD:
795 case EFX_SIENA_FILTER_TX_UDP_FULL:
796 case EFX_SIENA_FILTER_TX_UDP_WILD:
797 tbl_id = EFX_SIENA_FILTER_TBL_TX_IP;
800 case EFX_SIENA_FILTER_TX_MAC_FULL:
801 case EFX_SIENA_FILTER_TX_MAC_WILD:
802 tbl_id = EFX_SIENA_FILTER_TBL_TX_MAC;
806 EFSYS_ASSERT(B_FALSE);
807 tbl_id = EFX_SIENA_FILTER_NTBLS;
814 siena_filter_reset_search_depth(
815 __inout siena_filter_t *sfp,
816 __in siena_filter_tbl_id_t tbl_id)
819 case EFX_SIENA_FILTER_TBL_RX_IP:
820 sfp->sf_depth[EFX_SIENA_FILTER_RX_TCP_FULL] = 0;
821 sfp->sf_depth[EFX_SIENA_FILTER_RX_TCP_WILD] = 0;
822 sfp->sf_depth[EFX_SIENA_FILTER_RX_UDP_FULL] = 0;
823 sfp->sf_depth[EFX_SIENA_FILTER_RX_UDP_WILD] = 0;
826 case EFX_SIENA_FILTER_TBL_RX_MAC:
827 sfp->sf_depth[EFX_SIENA_FILTER_RX_MAC_FULL] = 0;
828 sfp->sf_depth[EFX_SIENA_FILTER_RX_MAC_WILD] = 0;
831 case EFX_SIENA_FILTER_TBL_TX_IP:
832 sfp->sf_depth[EFX_SIENA_FILTER_TX_TCP_FULL] = 0;
833 sfp->sf_depth[EFX_SIENA_FILTER_TX_TCP_WILD] = 0;
834 sfp->sf_depth[EFX_SIENA_FILTER_TX_UDP_FULL] = 0;
835 sfp->sf_depth[EFX_SIENA_FILTER_TX_UDP_WILD] = 0;
838 case EFX_SIENA_FILTER_TBL_TX_MAC:
839 sfp->sf_depth[EFX_SIENA_FILTER_TX_MAC_FULL] = 0;
840 sfp->sf_depth[EFX_SIENA_FILTER_TX_MAC_WILD] = 0;
844 EFSYS_ASSERT(B_FALSE);
850 siena_filter_push_rx_limits(
853 siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
856 EFX_BAR_READO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
858 EFX_SET_OWORD_FIELD(oword, FRF_AZ_TCP_FULL_SRCH_LIMIT,
859 sfp->sf_depth[EFX_SIENA_FILTER_RX_TCP_FULL] +
860 FILTER_CTL_SRCH_FUDGE_FULL);
861 EFX_SET_OWORD_FIELD(oword, FRF_AZ_TCP_WILD_SRCH_LIMIT,
862 sfp->sf_depth[EFX_SIENA_FILTER_RX_TCP_WILD] +
863 FILTER_CTL_SRCH_FUDGE_WILD);
864 EFX_SET_OWORD_FIELD(oword, FRF_AZ_UDP_FULL_SRCH_LIMIT,
865 sfp->sf_depth[EFX_SIENA_FILTER_RX_UDP_FULL] +
866 FILTER_CTL_SRCH_FUDGE_FULL);
867 EFX_SET_OWORD_FIELD(oword, FRF_AZ_UDP_WILD_SRCH_LIMIT,
868 sfp->sf_depth[EFX_SIENA_FILTER_RX_UDP_WILD] +
869 FILTER_CTL_SRCH_FUDGE_WILD);
871 if (sfp->sf_tbl[EFX_SIENA_FILTER_TBL_RX_MAC].sft_size) {
872 EFX_SET_OWORD_FIELD(oword,
873 FRF_CZ_ETHERNET_FULL_SEARCH_LIMIT,
874 sfp->sf_depth[EFX_SIENA_FILTER_RX_MAC_FULL] +
875 FILTER_CTL_SRCH_FUDGE_FULL);
876 EFX_SET_OWORD_FIELD(oword,
877 FRF_CZ_ETHERNET_WILDCARD_SEARCH_LIMIT,
878 sfp->sf_depth[EFX_SIENA_FILTER_RX_MAC_WILD] +
879 FILTER_CTL_SRCH_FUDGE_WILD);
882 EFX_BAR_WRITEO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
886 siena_filter_push_tx_limits(
889 siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
892 EFX_BAR_READO(enp, FR_AZ_TX_CFG_REG, &oword);
894 if (sfp->sf_tbl[EFX_SIENA_FILTER_TBL_TX_IP].sft_size != 0) {
895 EFX_SET_OWORD_FIELD(oword,
896 FRF_CZ_TX_TCPIP_FILTER_FULL_SEARCH_RANGE,
897 sfp->sf_depth[EFX_SIENA_FILTER_TX_TCP_FULL] +
898 FILTER_CTL_SRCH_FUDGE_FULL);
899 EFX_SET_OWORD_FIELD(oword,
900 FRF_CZ_TX_TCPIP_FILTER_WILD_SEARCH_RANGE,
901 sfp->sf_depth[EFX_SIENA_FILTER_TX_TCP_WILD] +
902 FILTER_CTL_SRCH_FUDGE_WILD);
903 EFX_SET_OWORD_FIELD(oword,
904 FRF_CZ_TX_UDPIP_FILTER_FULL_SEARCH_RANGE,
905 sfp->sf_depth[EFX_SIENA_FILTER_TX_UDP_FULL] +
906 FILTER_CTL_SRCH_FUDGE_FULL);
907 EFX_SET_OWORD_FIELD(oword,
908 FRF_CZ_TX_UDPIP_FILTER_WILD_SEARCH_RANGE,
909 sfp->sf_depth[EFX_SIENA_FILTER_TX_UDP_WILD] +
910 FILTER_CTL_SRCH_FUDGE_WILD);
913 if (sfp->sf_tbl[EFX_SIENA_FILTER_TBL_TX_MAC].sft_size != 0) {
915 oword, FRF_CZ_TX_ETH_FILTER_FULL_SEARCH_RANGE,
916 sfp->sf_depth[EFX_SIENA_FILTER_TX_MAC_FULL] +
917 FILTER_CTL_SRCH_FUDGE_FULL);
919 oword, FRF_CZ_TX_ETH_FILTER_WILD_SEARCH_RANGE,
920 sfp->sf_depth[EFX_SIENA_FILTER_TX_MAC_WILD] +
921 FILTER_CTL_SRCH_FUDGE_WILD);
924 EFX_BAR_WRITEO(enp, FR_AZ_TX_CFG_REG, &oword);
927 /* Build a filter entry and return its n-tuple key. */
928 static __checkReturn uint32_t
930 __out efx_oword_t *filter,
931 __in siena_filter_spec_t *spec)
935 uint8_t type = spec->sfs_type;
936 uint32_t flags = spec->sfs_flags;
938 switch (siena_filter_tbl_id(type)) {
939 case EFX_SIENA_FILTER_TBL_RX_IP: {
940 boolean_t is_udp = (type == EFX_SIENA_FILTER_RX_UDP_FULL ||
941 type == EFX_SIENA_FILTER_RX_UDP_WILD);
942 EFX_POPULATE_OWORD_7(*filter,
944 (flags & EFX_FILTER_FLAG_RX_RSS) ? 1 : 0,
946 (flags & EFX_FILTER_FLAG_RX_SCATTER) ? 1 : 0,
947 FRF_AZ_TCP_UDP, is_udp,
948 FRF_AZ_RXQ_ID, spec->sfs_dmaq_id,
949 EFX_DWORD_2, spec->sfs_dword[2],
950 EFX_DWORD_1, spec->sfs_dword[1],
951 EFX_DWORD_0, spec->sfs_dword[0]);
956 case EFX_SIENA_FILTER_TBL_RX_MAC: {
957 boolean_t is_wild = (type == EFX_SIENA_FILTER_RX_MAC_WILD);
958 EFX_POPULATE_OWORD_7(*filter,
960 (flags & EFX_FILTER_FLAG_RX_RSS) ? 1 : 0,
961 FRF_CZ_RMFT_SCATTER_EN,
962 (flags & EFX_FILTER_FLAG_RX_SCATTER) ? 1 : 0,
963 FRF_CZ_RMFT_RXQ_ID, spec->sfs_dmaq_id,
964 FRF_CZ_RMFT_WILDCARD_MATCH, is_wild,
965 FRF_CZ_RMFT_DEST_MAC_DW1, spec->sfs_dword[2],
966 FRF_CZ_RMFT_DEST_MAC_DW0, spec->sfs_dword[1],
967 FRF_CZ_RMFT_VLAN_ID, spec->sfs_dword[0]);
972 case EFX_SIENA_FILTER_TBL_TX_IP: {
973 boolean_t is_udp = (type == EFX_SIENA_FILTER_TX_UDP_FULL ||
974 type == EFX_SIENA_FILTER_TX_UDP_WILD);
975 EFX_POPULATE_OWORD_5(*filter,
976 FRF_CZ_TIFT_TCP_UDP, is_udp,
977 FRF_CZ_TIFT_TXQ_ID, spec->sfs_dmaq_id,
978 EFX_DWORD_2, spec->sfs_dword[2],
979 EFX_DWORD_1, spec->sfs_dword[1],
980 EFX_DWORD_0, spec->sfs_dword[0]);
981 dword3 = is_udp | spec->sfs_dmaq_id << 1;
985 case EFX_SIENA_FILTER_TBL_TX_MAC: {
986 boolean_t is_wild = (type == EFX_SIENA_FILTER_TX_MAC_WILD);
987 EFX_POPULATE_OWORD_5(*filter,
988 FRF_CZ_TMFT_TXQ_ID, spec->sfs_dmaq_id,
989 FRF_CZ_TMFT_WILDCARD_MATCH, is_wild,
990 FRF_CZ_TMFT_SRC_MAC_DW1, spec->sfs_dword[2],
991 FRF_CZ_TMFT_SRC_MAC_DW0, spec->sfs_dword[1],
992 FRF_CZ_TMFT_VLAN_ID, spec->sfs_dword[0]);
993 dword3 = is_wild | spec->sfs_dmaq_id << 1;
998 EFSYS_ASSERT(B_FALSE);
999 EFX_ZERO_OWORD(*filter);
1004 spec->sfs_dword[0] ^
1005 spec->sfs_dword[1] ^
1006 spec->sfs_dword[2] ^
1012 static __checkReturn efx_rc_t
1013 siena_filter_push_entry(
1014 __inout efx_nic_t *enp,
1015 __in siena_filter_type_t type,
1017 __in efx_oword_t *eop)
1022 case EFX_SIENA_FILTER_RX_TCP_FULL:
1023 case EFX_SIENA_FILTER_RX_TCP_WILD:
1024 case EFX_SIENA_FILTER_RX_UDP_FULL:
1025 case EFX_SIENA_FILTER_RX_UDP_WILD:
1026 EFX_BAR_TBL_WRITEO(enp, FR_AZ_RX_FILTER_TBL0, index,
1030 case EFX_SIENA_FILTER_RX_MAC_FULL:
1031 case EFX_SIENA_FILTER_RX_MAC_WILD:
1032 EFX_BAR_TBL_WRITEO(enp, FR_CZ_RX_MAC_FILTER_TBL0, index,
1036 case EFX_SIENA_FILTER_TX_TCP_FULL:
1037 case EFX_SIENA_FILTER_TX_TCP_WILD:
1038 case EFX_SIENA_FILTER_TX_UDP_FULL:
1039 case EFX_SIENA_FILTER_TX_UDP_WILD:
1040 EFX_BAR_TBL_WRITEO(enp, FR_CZ_TX_FILTER_TBL0, index,
1044 case EFX_SIENA_FILTER_TX_MAC_FULL:
1045 case EFX_SIENA_FILTER_TX_MAC_WILD:
1046 EFX_BAR_TBL_WRITEO(enp, FR_CZ_TX_MAC_FILTER_TBL0, index,
1051 EFSYS_ASSERT(B_FALSE);
1062 static __checkReturn boolean_t
1064 __in const siena_filter_spec_t *left,
1065 __in const siena_filter_spec_t *right)
1067 siena_filter_tbl_id_t tbl_id;
1069 tbl_id = siena_filter_tbl_id(left->sfs_type);
1072 if (left->sfs_type != right->sfs_type)
1075 if (memcmp(left->sfs_dword, right->sfs_dword,
1076 sizeof (left->sfs_dword)))
1079 if ((tbl_id == EFX_SIENA_FILTER_TBL_TX_IP ||
1080 tbl_id == EFX_SIENA_FILTER_TBL_TX_MAC) &&
1081 left->sfs_dmaq_id != right->sfs_dmaq_id)
1087 static __checkReturn efx_rc_t
1088 siena_filter_search(
1089 __in siena_filter_tbl_t *sftp,
1090 __in siena_filter_spec_t *spec,
1092 __in boolean_t for_insert,
1093 __out int *filter_index,
1094 __out unsigned int *depth_required)
1096 unsigned int hash, incr, filter_idx, depth;
1098 hash = siena_filter_tbl_hash(key);
1099 incr = siena_filter_tbl_increment(key);
1101 filter_idx = hash & (sftp->sft_size - 1);
1106 * Return success if entry is used and matches this spec
1107 * or entry is unused and we are trying to insert.
1109 if (siena_filter_test_used(sftp, filter_idx) ?
1110 siena_filter_equal(spec,
1111 &sftp->sft_spec[filter_idx]) :
1113 *filter_index = filter_idx;
1114 *depth_required = depth;
1118 /* Return failure if we reached the maximum search depth */
1119 if (depth == FILTER_CTL_SRCH_MAX)
1120 return (for_insert ? EBUSY : ENOENT);
1122 filter_idx = (filter_idx + incr) & (sftp->sft_size - 1);
1128 siena_filter_clear_entry(
1129 __in efx_nic_t *enp,
1130 __in siena_filter_tbl_t *sftp,
1135 if (siena_filter_test_used(sftp, index)) {
1136 siena_filter_clear_used(sftp, index);
1138 EFX_ZERO_OWORD(filter);
1139 siena_filter_push_entry(enp,
1140 sftp->sft_spec[index].sfs_type,
1143 memset(&sftp->sft_spec[index],
1144 0, sizeof (sftp->sft_spec[0]));
1149 siena_filter_tbl_clear(
1150 __in efx_nic_t *enp,
1151 __in siena_filter_tbl_id_t tbl_id)
1153 siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
1154 siena_filter_tbl_t *sftp = &sfp->sf_tbl[tbl_id];
1156 efsys_lock_state_t state;
1158 EFSYS_LOCK(enp->en_eslp, state);
1160 for (index = 0; index < sftp->sft_size; ++index) {
1161 siena_filter_clear_entry(enp, sftp, index);
1164 if (sftp->sft_used == 0)
1165 siena_filter_reset_search_depth(sfp, tbl_id);
1167 EFSYS_UNLOCK(enp->en_eslp, state);
1170 static __checkReturn efx_rc_t
1172 __in efx_nic_t *enp)
1174 siena_filter_t *sfp;
1175 siena_filter_tbl_t *sftp;
1179 EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (siena_filter_t), sfp);
1186 enp->en_filter.ef_siena_filter = sfp;
1188 switch (enp->en_family) {
1189 case EFX_FAMILY_SIENA:
1190 sftp = &sfp->sf_tbl[EFX_SIENA_FILTER_TBL_RX_IP];
1191 sftp->sft_size = FR_AZ_RX_FILTER_TBL0_ROWS;
1193 sftp = &sfp->sf_tbl[EFX_SIENA_FILTER_TBL_RX_MAC];
1194 sftp->sft_size = FR_CZ_RX_MAC_FILTER_TBL0_ROWS;
1196 sftp = &sfp->sf_tbl[EFX_SIENA_FILTER_TBL_TX_IP];
1197 sftp->sft_size = FR_CZ_TX_FILTER_TBL0_ROWS;
1199 sftp = &sfp->sf_tbl[EFX_SIENA_FILTER_TBL_TX_MAC];
1200 sftp->sft_size = FR_CZ_TX_MAC_FILTER_TBL0_ROWS;
1208 for (tbl_id = 0; tbl_id < EFX_SIENA_FILTER_NTBLS; tbl_id++) {
1209 unsigned int bitmap_size;
1211 sftp = &sfp->sf_tbl[tbl_id];
1212 if (sftp->sft_size == 0)
1215 EFX_STATIC_ASSERT(sizeof (sftp->sft_bitmap[0]) ==
1218 (sftp->sft_size + (sizeof (uint32_t) * 8) - 1) / 8;
1220 EFSYS_KMEM_ALLOC(enp->en_esip, bitmap_size, sftp->sft_bitmap);
1221 if (!sftp->sft_bitmap) {
1226 EFSYS_KMEM_ALLOC(enp->en_esip,
1227 sftp->sft_size * sizeof (*sftp->sft_spec),
1229 if (!sftp->sft_spec) {
1233 memset(sftp->sft_spec, 0,
1234 sftp->sft_size * sizeof (*sftp->sft_spec));
1247 siena_filter_fini(enp);
1250 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1256 __in efx_nic_t *enp)
1258 siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
1259 siena_filter_tbl_id_t tbl_id;
1261 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1262 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1267 for (tbl_id = 0; tbl_id < EFX_SIENA_FILTER_NTBLS; tbl_id++) {
1268 siena_filter_tbl_t *sftp = &sfp->sf_tbl[tbl_id];
1269 unsigned int bitmap_size;
1271 EFX_STATIC_ASSERT(sizeof (sftp->sft_bitmap[0]) ==
1274 (sftp->sft_size + (sizeof (uint32_t) * 8) - 1) / 8;
1276 if (sftp->sft_bitmap != NULL) {
1277 EFSYS_KMEM_FREE(enp->en_esip, bitmap_size,
1279 sftp->sft_bitmap = NULL;
1282 if (sftp->sft_spec != NULL) {
1283 EFSYS_KMEM_FREE(enp->en_esip, sftp->sft_size *
1284 sizeof (*sftp->sft_spec), sftp->sft_spec);
1285 sftp->sft_spec = NULL;
1289 EFSYS_KMEM_FREE(enp->en_esip, sizeof (siena_filter_t),
1290 enp->en_filter.ef_siena_filter);
1293 /* Restore filter state after a reset */
1294 static __checkReturn efx_rc_t
1295 siena_filter_restore(
1296 __in efx_nic_t *enp)
1298 siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
1299 siena_filter_tbl_id_t tbl_id;
1300 siena_filter_tbl_t *sftp;
1301 siena_filter_spec_t *spec;
1304 efsys_lock_state_t state;
1308 EFSYS_LOCK(enp->en_eslp, state);
1310 for (tbl_id = 0; tbl_id < EFX_SIENA_FILTER_NTBLS; tbl_id++) {
1311 sftp = &sfp->sf_tbl[tbl_id];
1312 for (filter_idx = 0;
1313 filter_idx < sftp->sft_size;
1315 if (!siena_filter_test_used(sftp, filter_idx))
1318 spec = &sftp->sft_spec[filter_idx];
1319 if ((key = siena_filter_build(&filter, spec)) == 0) {
1323 if ((rc = siena_filter_push_entry(enp,
1324 spec->sfs_type, filter_idx, &filter)) != 0)
1329 siena_filter_push_rx_limits(enp);
1330 siena_filter_push_tx_limits(enp);
1332 EFSYS_UNLOCK(enp->en_eslp, state);
1340 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1342 EFSYS_UNLOCK(enp->en_eslp, state);
1347 static __checkReturn efx_rc_t
1349 __in efx_nic_t *enp,
1350 __inout efx_filter_spec_t *spec,
1351 __in boolean_t may_replace)
1354 siena_filter_spec_t sf_spec;
1355 siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
1356 siena_filter_tbl_id_t tbl_id;
1357 siena_filter_tbl_t *sftp;
1358 siena_filter_spec_t *saved_sf_spec;
1362 efsys_lock_state_t state;
1366 EFSYS_ASSERT3P(spec, !=, NULL);
1368 if ((rc = siena_filter_spec_from_gen_spec(&sf_spec, spec)) != 0)
1371 tbl_id = siena_filter_tbl_id(sf_spec.sfs_type);
1372 sftp = &sfp->sf_tbl[tbl_id];
1374 if (sftp->sft_size == 0) {
1379 key = siena_filter_build(&filter, &sf_spec);
1381 EFSYS_LOCK(enp->en_eslp, state);
1383 rc = siena_filter_search(sftp, &sf_spec, key, B_TRUE,
1384 &filter_idx, &depth);
1388 EFSYS_ASSERT3U(filter_idx, <, sftp->sft_size);
1389 saved_sf_spec = &sftp->sft_spec[filter_idx];
1391 if (siena_filter_test_used(sftp, filter_idx)) {
1392 if (may_replace == B_FALSE) {
1397 siena_filter_set_used(sftp, filter_idx);
1398 *saved_sf_spec = sf_spec;
1400 if (sfp->sf_depth[sf_spec.sfs_type] < depth) {
1401 sfp->sf_depth[sf_spec.sfs_type] = depth;
1402 if (tbl_id == EFX_SIENA_FILTER_TBL_TX_IP ||
1403 tbl_id == EFX_SIENA_FILTER_TBL_TX_MAC)
1404 siena_filter_push_tx_limits(enp);
1406 siena_filter_push_rx_limits(enp);
1409 siena_filter_push_entry(enp, sf_spec.sfs_type,
1410 filter_idx, &filter);
1412 EFSYS_UNLOCK(enp->en_eslp, state);
1419 EFSYS_UNLOCK(enp->en_eslp, state);
1426 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1430 static __checkReturn efx_rc_t
1431 siena_filter_delete(
1432 __in efx_nic_t *enp,
1433 __inout efx_filter_spec_t *spec)
1436 siena_filter_spec_t sf_spec;
1437 siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
1438 siena_filter_tbl_id_t tbl_id;
1439 siena_filter_tbl_t *sftp;
1443 efsys_lock_state_t state;
1446 EFSYS_ASSERT3P(spec, !=, NULL);
1448 if ((rc = siena_filter_spec_from_gen_spec(&sf_spec, spec)) != 0)
1451 tbl_id = siena_filter_tbl_id(sf_spec.sfs_type);
1452 sftp = &sfp->sf_tbl[tbl_id];
1454 key = siena_filter_build(&filter, &sf_spec);
1456 EFSYS_LOCK(enp->en_eslp, state);
1458 rc = siena_filter_search(sftp, &sf_spec, key, B_FALSE,
1459 &filter_idx, &depth);
1463 siena_filter_clear_entry(enp, sftp, filter_idx);
1464 if (sftp->sft_used == 0)
1465 siena_filter_reset_search_depth(sfp, tbl_id);
1467 EFSYS_UNLOCK(enp->en_eslp, state);
1471 EFSYS_UNLOCK(enp->en_eslp, state);
1475 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1479 #define SIENA_MAX_SUPPORTED_MATCHES 4
1481 static __checkReturn efx_rc_t
1482 siena_filter_supported_filters(
1483 __in efx_nic_t *enp,
1484 __out_ecount(buffer_length) uint32_t *buffer,
1485 __in size_t buffer_length,
1486 __out size_t *list_lengthp)
1489 uint32_t rx_matches[SIENA_MAX_SUPPORTED_MATCHES];
1493 rx_matches[index++] =
1494 EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
1495 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT |
1496 EFX_FILTER_MATCH_REM_HOST | EFX_FILTER_MATCH_REM_PORT;
1498 rx_matches[index++] =
1499 EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
1500 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT;
1502 if (enp->en_features & EFX_FEATURE_MAC_HEADER_FILTERS) {
1503 rx_matches[index++] =
1504 EFX_FILTER_MATCH_OUTER_VID | EFX_FILTER_MATCH_LOC_MAC;
1506 rx_matches[index++] = EFX_FILTER_MATCH_LOC_MAC;
1509 EFSYS_ASSERT3U(index, <=, SIENA_MAX_SUPPORTED_MATCHES);
1510 list_length = index;
1512 *list_lengthp = list_length;
1514 if (buffer_length < list_length) {
1519 memcpy(buffer, rx_matches, list_length * sizeof (rx_matches[0]));
1524 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1529 #undef MAX_SUPPORTED
1531 #endif /* EFSYS_OPT_SIENA */
1533 #endif /* EFSYS_OPT_FILTER */