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;
77 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
80 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
81 EFSYS_ASSERT3P(spec, !=, NULL);
82 EFSYS_ASSERT3U(spec->efs_flags, &, EFX_FILTER_FLAG_RX);
84 if ((spec->efs_flags & EFX_FILTER_FLAG_ACTION_MARK) &&
85 !encp->enc_filter_action_mark_supported) {
90 if ((spec->efs_flags & EFX_FILTER_FLAG_ACTION_FLAG) &&
91 !encp->enc_filter_action_flag_supported) {
96 return (efop->efo_add(enp, spec, B_FALSE));
101 EFSYS_PROBE1(fail1, efx_rc_t, rc);
106 __checkReturn efx_rc_t
109 __inout efx_filter_spec_t *spec)
111 const efx_filter_ops_t *efop = enp->en_efop;
113 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
114 EFSYS_ASSERT3P(spec, !=, NULL);
115 EFSYS_ASSERT3U(spec->efs_flags, &, EFX_FILTER_FLAG_RX);
117 return (efop->efo_delete(enp, spec));
120 __checkReturn efx_rc_t
126 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
128 if ((rc = enp->en_efop->efo_restore(enp)) != 0)
134 EFSYS_PROBE1(fail1, efx_rc_t, rc);
139 __checkReturn efx_rc_t
143 const efx_filter_ops_t *efop;
146 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
147 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
148 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_FILTER));
150 switch (enp->en_family) {
152 case EFX_FAMILY_SIENA:
153 efop = &__efx_filter_siena_ops;
155 #endif /* EFSYS_OPT_SIENA */
157 #if EFSYS_OPT_HUNTINGTON
158 case EFX_FAMILY_HUNTINGTON:
159 efop = &__efx_filter_ef10_ops;
161 #endif /* EFSYS_OPT_HUNTINGTON */
163 #if EFSYS_OPT_MEDFORD
164 case EFX_FAMILY_MEDFORD:
165 efop = &__efx_filter_ef10_ops;
167 #endif /* EFSYS_OPT_MEDFORD */
169 #if EFSYS_OPT_MEDFORD2
170 case EFX_FAMILY_MEDFORD2:
171 efop = &__efx_filter_ef10_ops;
173 #endif /* EFSYS_OPT_MEDFORD2 */
181 if ((rc = efop->efo_init(enp)) != 0)
185 enp->en_mod_flags |= EFX_MOD_FILTER;
191 EFSYS_PROBE1(fail1, efx_rc_t, rc);
194 enp->en_mod_flags &= ~EFX_MOD_FILTER;
202 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
203 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
204 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
206 enp->en_efop->efo_fini(enp);
209 enp->en_mod_flags &= ~EFX_MOD_FILTER;
213 * Query the possible combinations of match flags which can be filtered on.
214 * These are returned as a list, of which each 32 bit element is a bitmask
215 * formed of EFX_FILTER_MATCH flags.
217 * The combinations are ordered in priority from highest to lowest.
219 * If the provided buffer is too short to hold the list, the call with fail with
220 * ENOSPC and *list_lengthp will be set to the buffer length required.
222 __checkReturn efx_rc_t
223 efx_filter_supported_filters(
225 __out_ecount(buffer_length) uint32_t *buffer,
226 __in size_t buffer_length,
227 __out size_t *list_lengthp)
231 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
232 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
233 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
234 EFSYS_ASSERT(enp->en_efop->efo_supported_filters != NULL);
236 if (buffer == NULL) {
241 rc = enp->en_efop->efo_supported_filters(enp, buffer, buffer_length,
251 EFSYS_PROBE1(fail1, efx_rc_t, rc);
256 __checkReturn efx_rc_t
257 efx_filter_reconfigure(
259 __in_ecount(6) uint8_t const *mac_addr,
260 __in boolean_t all_unicst,
261 __in boolean_t mulcst,
262 __in boolean_t all_mulcst,
263 __in boolean_t brdcst,
264 __in_ecount(6*count) uint8_t const *addrs,
269 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
270 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
271 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
273 if (enp->en_efop->efo_reconfigure != NULL) {
274 if ((rc = enp->en_efop->efo_reconfigure(enp, mac_addr,
284 EFSYS_PROBE1(fail1, efx_rc_t, rc);
290 efx_filter_spec_init_rx(
291 __out efx_filter_spec_t *spec,
292 __in efx_filter_priority_t priority,
293 __in efx_filter_flags_t flags,
296 EFSYS_ASSERT3P(spec, !=, NULL);
297 EFSYS_ASSERT3P(erp, !=, NULL);
298 EFSYS_ASSERT((flags & ~(EFX_FILTER_FLAG_RX_RSS |
299 EFX_FILTER_FLAG_RX_SCATTER)) == 0);
301 memset(spec, 0, sizeof (*spec));
302 spec->efs_priority = priority;
303 spec->efs_flags = EFX_FILTER_FLAG_RX | flags;
304 spec->efs_rss_context = EFX_RSS_CONTEXT_DEFAULT;
305 spec->efs_dmaq_id = (uint16_t)erp->er_index;
309 efx_filter_spec_init_tx(
310 __out efx_filter_spec_t *spec,
313 EFSYS_ASSERT3P(spec, !=, NULL);
314 EFSYS_ASSERT3P(etp, !=, NULL);
316 memset(spec, 0, sizeof (*spec));
317 spec->efs_priority = EFX_FILTER_PRI_REQUIRED;
318 spec->efs_flags = EFX_FILTER_FLAG_TX;
319 spec->efs_dmaq_id = (uint16_t)etp->et_index;
324 * Specify IPv4 host, transport protocol and port in a filter specification
326 __checkReturn efx_rc_t
327 efx_filter_spec_set_ipv4_local(
328 __inout efx_filter_spec_t *spec,
333 EFSYS_ASSERT3P(spec, !=, NULL);
335 spec->efs_match_flags |=
336 EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
337 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT;
338 spec->efs_ether_type = EFX_ETHER_TYPE_IPV4;
339 spec->efs_ip_proto = proto;
340 spec->efs_loc_host.eo_u32[0] = host;
341 spec->efs_loc_port = port;
346 * Specify IPv4 hosts, transport protocol and ports in a filter specification
348 __checkReturn efx_rc_t
349 efx_filter_spec_set_ipv4_full(
350 __inout efx_filter_spec_t *spec,
357 EFSYS_ASSERT3P(spec, !=, NULL);
359 spec->efs_match_flags |=
360 EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
361 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT |
362 EFX_FILTER_MATCH_REM_HOST | EFX_FILTER_MATCH_REM_PORT;
363 spec->efs_ether_type = EFX_ETHER_TYPE_IPV4;
364 spec->efs_ip_proto = proto;
365 spec->efs_loc_host.eo_u32[0] = lhost;
366 spec->efs_loc_port = lport;
367 spec->efs_rem_host.eo_u32[0] = rhost;
368 spec->efs_rem_port = rport;
373 * Specify local Ethernet address and/or VID in filter specification
375 __checkReturn efx_rc_t
376 efx_filter_spec_set_eth_local(
377 __inout efx_filter_spec_t *spec,
379 __in const uint8_t *addr)
381 EFSYS_ASSERT3P(spec, !=, NULL);
382 EFSYS_ASSERT3P(addr, !=, NULL);
384 if (vid == EFX_FILTER_SPEC_VID_UNSPEC && addr == NULL)
387 if (vid != EFX_FILTER_SPEC_VID_UNSPEC) {
388 spec->efs_match_flags |= EFX_FILTER_MATCH_OUTER_VID;
389 spec->efs_outer_vid = vid;
392 spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_MAC;
393 memcpy(spec->efs_loc_mac, addr, EFX_MAC_ADDR_LEN);
399 efx_filter_spec_set_ether_type(
400 __inout efx_filter_spec_t *spec,
401 __in uint16_t ether_type)
403 EFSYS_ASSERT3P(spec, !=, NULL);
405 spec->efs_ether_type = ether_type;
406 spec->efs_match_flags |= EFX_FILTER_MATCH_ETHER_TYPE;
410 * Specify matching otherwise-unmatched unicast in a filter specification
412 __checkReturn efx_rc_t
413 efx_filter_spec_set_uc_def(
414 __inout efx_filter_spec_t *spec)
416 EFSYS_ASSERT3P(spec, !=, NULL);
418 spec->efs_match_flags |= EFX_FILTER_MATCH_UNKNOWN_UCAST_DST;
423 * Specify matching otherwise-unmatched multicast in a filter specification
425 __checkReturn efx_rc_t
426 efx_filter_spec_set_mc_def(
427 __inout efx_filter_spec_t *spec)
429 EFSYS_ASSERT3P(spec, !=, NULL);
431 spec->efs_match_flags |= EFX_FILTER_MATCH_UNKNOWN_MCAST_DST;
436 __checkReturn efx_rc_t
437 efx_filter_spec_set_encap_type(
438 __inout efx_filter_spec_t *spec,
439 __in efx_tunnel_protocol_t encap_type,
440 __in efx_filter_inner_frame_match_t inner_frame_match)
442 uint32_t match_flags = EFX_FILTER_MATCH_ENCAP_TYPE;
446 EFSYS_ASSERT3P(spec, !=, NULL);
448 switch (encap_type) {
449 case EFX_TUNNEL_PROTOCOL_VXLAN:
450 case EFX_TUNNEL_PROTOCOL_GENEVE:
451 ip_proto = EFX_IPPROTO_UDP;
453 case EFX_TUNNEL_PROTOCOL_NVGRE:
454 ip_proto = EFX_IPPROTO_GRE;
462 switch (inner_frame_match) {
463 case EFX_FILTER_INNER_FRAME_MATCH_UNKNOWN_MCAST_DST:
464 match_flags |= EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST;
466 case EFX_FILTER_INNER_FRAME_MATCH_UNKNOWN_UCAST_DST:
467 match_flags |= EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST;
469 case EFX_FILTER_INNER_FRAME_MATCH_OTHER:
470 /* This is for when specific inner frames are to be matched. */
478 spec->efs_encap_type = encap_type;
479 spec->efs_ip_proto = ip_proto;
480 spec->efs_match_flags |= (match_flags | EFX_FILTER_MATCH_IP_PROTO);
487 EFSYS_PROBE1(fail1, efx_rc_t, rc);
493 * Specify inner and outer Ethernet address and VXLAN ID in filter
496 __checkReturn efx_rc_t
497 efx_filter_spec_set_vxlan_full(
498 __inout efx_filter_spec_t *spec,
499 __in const uint8_t *vxlan_id,
500 __in const uint8_t *inner_addr,
501 __in const uint8_t *outer_addr)
503 EFSYS_ASSERT3P(spec, !=, NULL);
504 EFSYS_ASSERT3P(vxlan_id, !=, NULL);
505 EFSYS_ASSERT3P(inner_addr, !=, NULL);
506 EFSYS_ASSERT3P(outer_addr, !=, NULL);
508 if ((inner_addr == NULL) && (outer_addr == NULL))
511 if (vxlan_id != NULL) {
512 spec->efs_match_flags |= EFX_FILTER_MATCH_VNI_OR_VSID;
513 memcpy(spec->efs_vni_or_vsid, vxlan_id, EFX_VNI_OR_VSID_LEN);
515 if (outer_addr != NULL) {
516 spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_MAC;
517 memcpy(spec->efs_loc_mac, outer_addr, EFX_MAC_ADDR_LEN);
519 if (inner_addr != NULL) {
520 spec->efs_match_flags |= EFX_FILTER_MATCH_IFRM_LOC_MAC;
521 memcpy(spec->efs_ifrm_loc_mac, inner_addr, EFX_MAC_ADDR_LEN);
523 spec->efs_match_flags |= EFX_FILTER_MATCH_ENCAP_TYPE;
524 spec->efs_encap_type = EFX_TUNNEL_PROTOCOL_VXLAN;
529 #if EFSYS_OPT_RX_SCALE
530 __checkReturn efx_rc_t
531 efx_filter_spec_set_rss_context(
532 __inout efx_filter_spec_t *spec,
533 __in uint32_t rss_context)
537 EFSYS_ASSERT3P(spec, !=, NULL);
539 /* The filter must have been created with EFX_FILTER_FLAG_RX_RSS. */
540 if ((spec->efs_flags & EFX_FILTER_FLAG_RX_RSS) == 0) {
545 spec->efs_rss_context = rss_context;
550 EFSYS_PROBE1(fail1, efx_rc_t, rc);
559 * "Fudge factors" - difference between programmed value and actual depth.
560 * Due to pipelined implementation we need to program H/W with a value that
561 * is larger than the hop limit we want.
563 #define FILTER_CTL_SRCH_FUDGE_WILD 3
564 #define FILTER_CTL_SRCH_FUDGE_FULL 1
567 * Hard maximum hop limit. Hardware will time-out beyond 200-something.
568 * We also need to avoid infinite loops in efx_filter_search() when the
571 #define FILTER_CTL_SRCH_MAX 200
573 static __checkReturn efx_rc_t
574 siena_filter_spec_from_gen_spec(
575 __out siena_filter_spec_t *sf_spec,
576 __in efx_filter_spec_t *gen_spec)
579 boolean_t is_full = B_FALSE;
581 if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX)
582 EFSYS_ASSERT3U(gen_spec->efs_flags, ==, EFX_FILTER_FLAG_TX);
584 EFSYS_ASSERT3U(gen_spec->efs_flags, &, EFX_FILTER_FLAG_RX);
586 /* Siena only has one RSS context */
587 if ((gen_spec->efs_flags & EFX_FILTER_FLAG_RX_RSS) &&
588 gen_spec->efs_rss_context != EFX_RSS_CONTEXT_DEFAULT) {
593 sf_spec->sfs_flags = gen_spec->efs_flags;
594 sf_spec->sfs_dmaq_id = gen_spec->efs_dmaq_id;
596 switch (gen_spec->efs_match_flags) {
597 case EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
598 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT |
599 EFX_FILTER_MATCH_REM_HOST | EFX_FILTER_MATCH_REM_PORT:
602 case EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
603 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT: {
604 uint32_t rhost, host1, host2;
605 uint16_t rport, port1, port2;
607 if (gen_spec->efs_ether_type != EFX_ETHER_TYPE_IPV4) {
611 if (gen_spec->efs_loc_port == 0 ||
612 (is_full && gen_spec->efs_rem_port == 0)) {
616 switch (gen_spec->efs_ip_proto) {
617 case EFX_IPPROTO_TCP:
618 if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX) {
619 sf_spec->sfs_type = (is_full ?
620 EFX_SIENA_FILTER_TX_TCP_FULL :
621 EFX_SIENA_FILTER_TX_TCP_WILD);
623 sf_spec->sfs_type = (is_full ?
624 EFX_SIENA_FILTER_RX_TCP_FULL :
625 EFX_SIENA_FILTER_RX_TCP_WILD);
628 case EFX_IPPROTO_UDP:
629 if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX) {
630 sf_spec->sfs_type = (is_full ?
631 EFX_SIENA_FILTER_TX_UDP_FULL :
632 EFX_SIENA_FILTER_TX_UDP_WILD);
634 sf_spec->sfs_type = (is_full ?
635 EFX_SIENA_FILTER_RX_UDP_FULL :
636 EFX_SIENA_FILTER_RX_UDP_WILD);
644 * The filter is constructed in terms of source and destination,
645 * with the odd wrinkle that the ports are swapped in a UDP
646 * wildcard filter. We need to convert from local and remote
647 * addresses (zero for a wildcard).
649 rhost = is_full ? gen_spec->efs_rem_host.eo_u32[0] : 0;
650 rport = is_full ? gen_spec->efs_rem_port : 0;
651 if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX) {
652 host1 = gen_spec->efs_loc_host.eo_u32[0];
656 host2 = gen_spec->efs_loc_host.eo_u32[0];
658 if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX) {
659 if (sf_spec->sfs_type ==
660 EFX_SIENA_FILTER_TX_UDP_WILD) {
662 port2 = gen_spec->efs_loc_port;
664 port1 = gen_spec->efs_loc_port;
668 if (sf_spec->sfs_type ==
669 EFX_SIENA_FILTER_RX_UDP_WILD) {
670 port1 = gen_spec->efs_loc_port;
674 port2 = gen_spec->efs_loc_port;
677 sf_spec->sfs_dword[0] = (host1 << 16) | port1;
678 sf_spec->sfs_dword[1] = (port2 << 16) | (host1 >> 16);
679 sf_spec->sfs_dword[2] = host2;
683 case EFX_FILTER_MATCH_LOC_MAC | EFX_FILTER_MATCH_OUTER_VID:
686 case EFX_FILTER_MATCH_LOC_MAC:
687 if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX) {
688 sf_spec->sfs_type = (is_full ?
689 EFX_SIENA_FILTER_TX_MAC_FULL :
690 EFX_SIENA_FILTER_TX_MAC_WILD);
692 sf_spec->sfs_type = (is_full ?
693 EFX_SIENA_FILTER_RX_MAC_FULL :
694 EFX_SIENA_FILTER_RX_MAC_WILD);
696 sf_spec->sfs_dword[0] = is_full ? gen_spec->efs_outer_vid : 0;
697 sf_spec->sfs_dword[1] =
698 gen_spec->efs_loc_mac[2] << 24 |
699 gen_spec->efs_loc_mac[3] << 16 |
700 gen_spec->efs_loc_mac[4] << 8 |
701 gen_spec->efs_loc_mac[5];
702 sf_spec->sfs_dword[2] =
703 gen_spec->efs_loc_mac[0] << 8 |
704 gen_spec->efs_loc_mac[1];
708 EFSYS_ASSERT(B_FALSE);
724 EFSYS_PROBE1(fail1, efx_rc_t, rc);
730 * The filter hash function is LFSR polynomial x^16 + x^3 + 1 of a 32-bit
731 * key derived from the n-tuple.
734 siena_filter_tbl_hash(
739 /* First 16 rounds */
740 tmp = 0x1fff ^ (uint16_t)(key >> 16);
741 tmp = tmp ^ tmp >> 3 ^ tmp >> 6;
742 tmp = tmp ^ tmp >> 9;
745 tmp = tmp ^ tmp << 13 ^ (uint16_t)(key & 0xffff);
746 tmp = tmp ^ tmp >> 3 ^ tmp >> 6;
747 tmp = tmp ^ tmp >> 9;
753 * To allow for hash collisions, filter search continues at these
754 * increments from the first possible entry selected by the hash.
757 siena_filter_tbl_increment(
760 return ((uint16_t)(key * 2 - 1));
763 static __checkReturn boolean_t
764 siena_filter_test_used(
765 __in siena_filter_tbl_t *sftp,
766 __in unsigned int index)
768 EFSYS_ASSERT3P(sftp->sft_bitmap, !=, NULL);
769 return ((sftp->sft_bitmap[index / 32] & (1 << (index % 32))) != 0);
773 siena_filter_set_used(
774 __in siena_filter_tbl_t *sftp,
775 __in unsigned int index)
777 EFSYS_ASSERT3P(sftp->sft_bitmap, !=, NULL);
778 sftp->sft_bitmap[index / 32] |= (1 << (index % 32));
783 siena_filter_clear_used(
784 __in siena_filter_tbl_t *sftp,
785 __in unsigned int index)
787 EFSYS_ASSERT3P(sftp->sft_bitmap, !=, NULL);
788 sftp->sft_bitmap[index / 32] &= ~(1 << (index % 32));
791 EFSYS_ASSERT3U(sftp->sft_used, >=, 0);
795 static siena_filter_tbl_id_t
797 __in siena_filter_type_t type)
799 siena_filter_tbl_id_t tbl_id;
802 case EFX_SIENA_FILTER_RX_TCP_FULL:
803 case EFX_SIENA_FILTER_RX_TCP_WILD:
804 case EFX_SIENA_FILTER_RX_UDP_FULL:
805 case EFX_SIENA_FILTER_RX_UDP_WILD:
806 tbl_id = EFX_SIENA_FILTER_TBL_RX_IP;
809 case EFX_SIENA_FILTER_RX_MAC_FULL:
810 case EFX_SIENA_FILTER_RX_MAC_WILD:
811 tbl_id = EFX_SIENA_FILTER_TBL_RX_MAC;
814 case EFX_SIENA_FILTER_TX_TCP_FULL:
815 case EFX_SIENA_FILTER_TX_TCP_WILD:
816 case EFX_SIENA_FILTER_TX_UDP_FULL:
817 case EFX_SIENA_FILTER_TX_UDP_WILD:
818 tbl_id = EFX_SIENA_FILTER_TBL_TX_IP;
821 case EFX_SIENA_FILTER_TX_MAC_FULL:
822 case EFX_SIENA_FILTER_TX_MAC_WILD:
823 tbl_id = EFX_SIENA_FILTER_TBL_TX_MAC;
827 EFSYS_ASSERT(B_FALSE);
828 tbl_id = EFX_SIENA_FILTER_NTBLS;
835 siena_filter_reset_search_depth(
836 __inout siena_filter_t *sfp,
837 __in siena_filter_tbl_id_t tbl_id)
840 case EFX_SIENA_FILTER_TBL_RX_IP:
841 sfp->sf_depth[EFX_SIENA_FILTER_RX_TCP_FULL] = 0;
842 sfp->sf_depth[EFX_SIENA_FILTER_RX_TCP_WILD] = 0;
843 sfp->sf_depth[EFX_SIENA_FILTER_RX_UDP_FULL] = 0;
844 sfp->sf_depth[EFX_SIENA_FILTER_RX_UDP_WILD] = 0;
847 case EFX_SIENA_FILTER_TBL_RX_MAC:
848 sfp->sf_depth[EFX_SIENA_FILTER_RX_MAC_FULL] = 0;
849 sfp->sf_depth[EFX_SIENA_FILTER_RX_MAC_WILD] = 0;
852 case EFX_SIENA_FILTER_TBL_TX_IP:
853 sfp->sf_depth[EFX_SIENA_FILTER_TX_TCP_FULL] = 0;
854 sfp->sf_depth[EFX_SIENA_FILTER_TX_TCP_WILD] = 0;
855 sfp->sf_depth[EFX_SIENA_FILTER_TX_UDP_FULL] = 0;
856 sfp->sf_depth[EFX_SIENA_FILTER_TX_UDP_WILD] = 0;
859 case EFX_SIENA_FILTER_TBL_TX_MAC:
860 sfp->sf_depth[EFX_SIENA_FILTER_TX_MAC_FULL] = 0;
861 sfp->sf_depth[EFX_SIENA_FILTER_TX_MAC_WILD] = 0;
865 EFSYS_ASSERT(B_FALSE);
871 siena_filter_push_rx_limits(
874 siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
877 EFX_BAR_READO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
879 EFX_SET_OWORD_FIELD(oword, FRF_AZ_TCP_FULL_SRCH_LIMIT,
880 sfp->sf_depth[EFX_SIENA_FILTER_RX_TCP_FULL] +
881 FILTER_CTL_SRCH_FUDGE_FULL);
882 EFX_SET_OWORD_FIELD(oword, FRF_AZ_TCP_WILD_SRCH_LIMIT,
883 sfp->sf_depth[EFX_SIENA_FILTER_RX_TCP_WILD] +
884 FILTER_CTL_SRCH_FUDGE_WILD);
885 EFX_SET_OWORD_FIELD(oword, FRF_AZ_UDP_FULL_SRCH_LIMIT,
886 sfp->sf_depth[EFX_SIENA_FILTER_RX_UDP_FULL] +
887 FILTER_CTL_SRCH_FUDGE_FULL);
888 EFX_SET_OWORD_FIELD(oword, FRF_AZ_UDP_WILD_SRCH_LIMIT,
889 sfp->sf_depth[EFX_SIENA_FILTER_RX_UDP_WILD] +
890 FILTER_CTL_SRCH_FUDGE_WILD);
892 if (sfp->sf_tbl[EFX_SIENA_FILTER_TBL_RX_MAC].sft_size) {
893 EFX_SET_OWORD_FIELD(oword,
894 FRF_CZ_ETHERNET_FULL_SEARCH_LIMIT,
895 sfp->sf_depth[EFX_SIENA_FILTER_RX_MAC_FULL] +
896 FILTER_CTL_SRCH_FUDGE_FULL);
897 EFX_SET_OWORD_FIELD(oword,
898 FRF_CZ_ETHERNET_WILDCARD_SEARCH_LIMIT,
899 sfp->sf_depth[EFX_SIENA_FILTER_RX_MAC_WILD] +
900 FILTER_CTL_SRCH_FUDGE_WILD);
903 EFX_BAR_WRITEO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
907 siena_filter_push_tx_limits(
910 siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
913 EFX_BAR_READO(enp, FR_AZ_TX_CFG_REG, &oword);
915 if (sfp->sf_tbl[EFX_SIENA_FILTER_TBL_TX_IP].sft_size != 0) {
916 EFX_SET_OWORD_FIELD(oword,
917 FRF_CZ_TX_TCPIP_FILTER_FULL_SEARCH_RANGE,
918 sfp->sf_depth[EFX_SIENA_FILTER_TX_TCP_FULL] +
919 FILTER_CTL_SRCH_FUDGE_FULL);
920 EFX_SET_OWORD_FIELD(oword,
921 FRF_CZ_TX_TCPIP_FILTER_WILD_SEARCH_RANGE,
922 sfp->sf_depth[EFX_SIENA_FILTER_TX_TCP_WILD] +
923 FILTER_CTL_SRCH_FUDGE_WILD);
924 EFX_SET_OWORD_FIELD(oword,
925 FRF_CZ_TX_UDPIP_FILTER_FULL_SEARCH_RANGE,
926 sfp->sf_depth[EFX_SIENA_FILTER_TX_UDP_FULL] +
927 FILTER_CTL_SRCH_FUDGE_FULL);
928 EFX_SET_OWORD_FIELD(oword,
929 FRF_CZ_TX_UDPIP_FILTER_WILD_SEARCH_RANGE,
930 sfp->sf_depth[EFX_SIENA_FILTER_TX_UDP_WILD] +
931 FILTER_CTL_SRCH_FUDGE_WILD);
934 if (sfp->sf_tbl[EFX_SIENA_FILTER_TBL_TX_MAC].sft_size != 0) {
936 oword, FRF_CZ_TX_ETH_FILTER_FULL_SEARCH_RANGE,
937 sfp->sf_depth[EFX_SIENA_FILTER_TX_MAC_FULL] +
938 FILTER_CTL_SRCH_FUDGE_FULL);
940 oword, FRF_CZ_TX_ETH_FILTER_WILD_SEARCH_RANGE,
941 sfp->sf_depth[EFX_SIENA_FILTER_TX_MAC_WILD] +
942 FILTER_CTL_SRCH_FUDGE_WILD);
945 EFX_BAR_WRITEO(enp, FR_AZ_TX_CFG_REG, &oword);
948 /* Build a filter entry and return its n-tuple key. */
949 static __checkReturn uint32_t
951 __out efx_oword_t *filter,
952 __in siena_filter_spec_t *spec)
956 uint8_t type = spec->sfs_type;
957 uint32_t flags = spec->sfs_flags;
959 switch (siena_filter_tbl_id(type)) {
960 case EFX_SIENA_FILTER_TBL_RX_IP: {
961 boolean_t is_udp = (type == EFX_SIENA_FILTER_RX_UDP_FULL ||
962 type == EFX_SIENA_FILTER_RX_UDP_WILD);
963 EFX_POPULATE_OWORD_7(*filter,
965 (flags & EFX_FILTER_FLAG_RX_RSS) ? 1 : 0,
967 (flags & EFX_FILTER_FLAG_RX_SCATTER) ? 1 : 0,
968 FRF_AZ_TCP_UDP, is_udp,
969 FRF_AZ_RXQ_ID, spec->sfs_dmaq_id,
970 EFX_DWORD_2, spec->sfs_dword[2],
971 EFX_DWORD_1, spec->sfs_dword[1],
972 EFX_DWORD_0, spec->sfs_dword[0]);
977 case EFX_SIENA_FILTER_TBL_RX_MAC: {
978 boolean_t is_wild = (type == EFX_SIENA_FILTER_RX_MAC_WILD);
979 EFX_POPULATE_OWORD_7(*filter,
981 (flags & EFX_FILTER_FLAG_RX_RSS) ? 1 : 0,
982 FRF_CZ_RMFT_SCATTER_EN,
983 (flags & EFX_FILTER_FLAG_RX_SCATTER) ? 1 : 0,
984 FRF_CZ_RMFT_RXQ_ID, spec->sfs_dmaq_id,
985 FRF_CZ_RMFT_WILDCARD_MATCH, is_wild,
986 FRF_CZ_RMFT_DEST_MAC_DW1, spec->sfs_dword[2],
987 FRF_CZ_RMFT_DEST_MAC_DW0, spec->sfs_dword[1],
988 FRF_CZ_RMFT_VLAN_ID, spec->sfs_dword[0]);
993 case EFX_SIENA_FILTER_TBL_TX_IP: {
994 boolean_t is_udp = (type == EFX_SIENA_FILTER_TX_UDP_FULL ||
995 type == EFX_SIENA_FILTER_TX_UDP_WILD);
996 EFX_POPULATE_OWORD_5(*filter,
997 FRF_CZ_TIFT_TCP_UDP, is_udp,
998 FRF_CZ_TIFT_TXQ_ID, spec->sfs_dmaq_id,
999 EFX_DWORD_2, spec->sfs_dword[2],
1000 EFX_DWORD_1, spec->sfs_dword[1],
1001 EFX_DWORD_0, spec->sfs_dword[0]);
1002 dword3 = is_udp | spec->sfs_dmaq_id << 1;
1006 case EFX_SIENA_FILTER_TBL_TX_MAC: {
1007 boolean_t is_wild = (type == EFX_SIENA_FILTER_TX_MAC_WILD);
1008 EFX_POPULATE_OWORD_5(*filter,
1009 FRF_CZ_TMFT_TXQ_ID, spec->sfs_dmaq_id,
1010 FRF_CZ_TMFT_WILDCARD_MATCH, is_wild,
1011 FRF_CZ_TMFT_SRC_MAC_DW1, spec->sfs_dword[2],
1012 FRF_CZ_TMFT_SRC_MAC_DW0, spec->sfs_dword[1],
1013 FRF_CZ_TMFT_VLAN_ID, spec->sfs_dword[0]);
1014 dword3 = is_wild | spec->sfs_dmaq_id << 1;
1019 EFSYS_ASSERT(B_FALSE);
1020 EFX_ZERO_OWORD(*filter);
1025 spec->sfs_dword[0] ^
1026 spec->sfs_dword[1] ^
1027 spec->sfs_dword[2] ^
1033 static __checkReturn efx_rc_t
1034 siena_filter_push_entry(
1035 __inout efx_nic_t *enp,
1036 __in siena_filter_type_t type,
1038 __in efx_oword_t *eop)
1043 case EFX_SIENA_FILTER_RX_TCP_FULL:
1044 case EFX_SIENA_FILTER_RX_TCP_WILD:
1045 case EFX_SIENA_FILTER_RX_UDP_FULL:
1046 case EFX_SIENA_FILTER_RX_UDP_WILD:
1047 EFX_BAR_TBL_WRITEO(enp, FR_AZ_RX_FILTER_TBL0, index,
1051 case EFX_SIENA_FILTER_RX_MAC_FULL:
1052 case EFX_SIENA_FILTER_RX_MAC_WILD:
1053 EFX_BAR_TBL_WRITEO(enp, FR_CZ_RX_MAC_FILTER_TBL0, index,
1057 case EFX_SIENA_FILTER_TX_TCP_FULL:
1058 case EFX_SIENA_FILTER_TX_TCP_WILD:
1059 case EFX_SIENA_FILTER_TX_UDP_FULL:
1060 case EFX_SIENA_FILTER_TX_UDP_WILD:
1061 EFX_BAR_TBL_WRITEO(enp, FR_CZ_TX_FILTER_TBL0, index,
1065 case EFX_SIENA_FILTER_TX_MAC_FULL:
1066 case EFX_SIENA_FILTER_TX_MAC_WILD:
1067 EFX_BAR_TBL_WRITEO(enp, FR_CZ_TX_MAC_FILTER_TBL0, index,
1072 EFSYS_ASSERT(B_FALSE);
1083 static __checkReturn boolean_t
1085 __in const siena_filter_spec_t *left,
1086 __in const siena_filter_spec_t *right)
1088 siena_filter_tbl_id_t tbl_id;
1090 tbl_id = siena_filter_tbl_id(left->sfs_type);
1093 if (left->sfs_type != right->sfs_type)
1096 if (memcmp(left->sfs_dword, right->sfs_dword,
1097 sizeof (left->sfs_dword)))
1100 if ((tbl_id == EFX_SIENA_FILTER_TBL_TX_IP ||
1101 tbl_id == EFX_SIENA_FILTER_TBL_TX_MAC) &&
1102 left->sfs_dmaq_id != right->sfs_dmaq_id)
1108 static __checkReturn efx_rc_t
1109 siena_filter_search(
1110 __in siena_filter_tbl_t *sftp,
1111 __in siena_filter_spec_t *spec,
1113 __in boolean_t for_insert,
1114 __out int *filter_index,
1115 __out unsigned int *depth_required)
1117 unsigned int hash, incr, filter_idx, depth;
1119 hash = siena_filter_tbl_hash(key);
1120 incr = siena_filter_tbl_increment(key);
1122 filter_idx = hash & (sftp->sft_size - 1);
1127 * Return success if entry is used and matches this spec
1128 * or entry is unused and we are trying to insert.
1130 if (siena_filter_test_used(sftp, filter_idx) ?
1131 siena_filter_equal(spec,
1132 &sftp->sft_spec[filter_idx]) :
1134 *filter_index = filter_idx;
1135 *depth_required = depth;
1139 /* Return failure if we reached the maximum search depth */
1140 if (depth == FILTER_CTL_SRCH_MAX)
1141 return (for_insert ? EBUSY : ENOENT);
1143 filter_idx = (filter_idx + incr) & (sftp->sft_size - 1);
1149 siena_filter_clear_entry(
1150 __in efx_nic_t *enp,
1151 __in siena_filter_tbl_t *sftp,
1156 if (siena_filter_test_used(sftp, index)) {
1157 siena_filter_clear_used(sftp, index);
1159 EFX_ZERO_OWORD(filter);
1160 siena_filter_push_entry(enp,
1161 sftp->sft_spec[index].sfs_type,
1164 memset(&sftp->sft_spec[index],
1165 0, sizeof (sftp->sft_spec[0]));
1170 siena_filter_tbl_clear(
1171 __in efx_nic_t *enp,
1172 __in siena_filter_tbl_id_t tbl_id)
1174 siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
1175 siena_filter_tbl_t *sftp = &sfp->sf_tbl[tbl_id];
1177 efsys_lock_state_t state;
1179 EFSYS_LOCK(enp->en_eslp, state);
1181 for (index = 0; index < sftp->sft_size; ++index) {
1182 siena_filter_clear_entry(enp, sftp, index);
1185 if (sftp->sft_used == 0)
1186 siena_filter_reset_search_depth(sfp, tbl_id);
1188 EFSYS_UNLOCK(enp->en_eslp, state);
1191 static __checkReturn efx_rc_t
1193 __in efx_nic_t *enp)
1195 siena_filter_t *sfp;
1196 siena_filter_tbl_t *sftp;
1200 EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (siena_filter_t), sfp);
1207 enp->en_filter.ef_siena_filter = sfp;
1209 switch (enp->en_family) {
1210 case EFX_FAMILY_SIENA:
1211 sftp = &sfp->sf_tbl[EFX_SIENA_FILTER_TBL_RX_IP];
1212 sftp->sft_size = FR_AZ_RX_FILTER_TBL0_ROWS;
1214 sftp = &sfp->sf_tbl[EFX_SIENA_FILTER_TBL_RX_MAC];
1215 sftp->sft_size = FR_CZ_RX_MAC_FILTER_TBL0_ROWS;
1217 sftp = &sfp->sf_tbl[EFX_SIENA_FILTER_TBL_TX_IP];
1218 sftp->sft_size = FR_CZ_TX_FILTER_TBL0_ROWS;
1220 sftp = &sfp->sf_tbl[EFX_SIENA_FILTER_TBL_TX_MAC];
1221 sftp->sft_size = FR_CZ_TX_MAC_FILTER_TBL0_ROWS;
1229 for (tbl_id = 0; tbl_id < EFX_SIENA_FILTER_NTBLS; tbl_id++) {
1230 unsigned int bitmap_size;
1232 sftp = &sfp->sf_tbl[tbl_id];
1233 if (sftp->sft_size == 0)
1236 EFX_STATIC_ASSERT(sizeof (sftp->sft_bitmap[0]) ==
1239 (sftp->sft_size + (sizeof (uint32_t) * 8) - 1) / 8;
1241 EFSYS_KMEM_ALLOC(enp->en_esip, bitmap_size, sftp->sft_bitmap);
1242 if (!sftp->sft_bitmap) {
1247 EFSYS_KMEM_ALLOC(enp->en_esip,
1248 sftp->sft_size * sizeof (*sftp->sft_spec),
1250 if (!sftp->sft_spec) {
1254 memset(sftp->sft_spec, 0,
1255 sftp->sft_size * sizeof (*sftp->sft_spec));
1268 siena_filter_fini(enp);
1271 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1277 __in efx_nic_t *enp)
1279 siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
1280 siena_filter_tbl_id_t tbl_id;
1282 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1283 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1288 for (tbl_id = 0; tbl_id < EFX_SIENA_FILTER_NTBLS; tbl_id++) {
1289 siena_filter_tbl_t *sftp = &sfp->sf_tbl[tbl_id];
1290 unsigned int bitmap_size;
1292 EFX_STATIC_ASSERT(sizeof (sftp->sft_bitmap[0]) ==
1295 (sftp->sft_size + (sizeof (uint32_t) * 8) - 1) / 8;
1297 if (sftp->sft_bitmap != NULL) {
1298 EFSYS_KMEM_FREE(enp->en_esip, bitmap_size,
1300 sftp->sft_bitmap = NULL;
1303 if (sftp->sft_spec != NULL) {
1304 EFSYS_KMEM_FREE(enp->en_esip, sftp->sft_size *
1305 sizeof (*sftp->sft_spec), sftp->sft_spec);
1306 sftp->sft_spec = NULL;
1310 EFSYS_KMEM_FREE(enp->en_esip, sizeof (siena_filter_t),
1311 enp->en_filter.ef_siena_filter);
1314 /* Restore filter state after a reset */
1315 static __checkReturn efx_rc_t
1316 siena_filter_restore(
1317 __in efx_nic_t *enp)
1319 siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
1320 siena_filter_tbl_id_t tbl_id;
1321 siena_filter_tbl_t *sftp;
1322 siena_filter_spec_t *spec;
1325 efsys_lock_state_t state;
1329 EFSYS_LOCK(enp->en_eslp, state);
1331 for (tbl_id = 0; tbl_id < EFX_SIENA_FILTER_NTBLS; tbl_id++) {
1332 sftp = &sfp->sf_tbl[tbl_id];
1333 for (filter_idx = 0;
1334 filter_idx < sftp->sft_size;
1336 if (!siena_filter_test_used(sftp, filter_idx))
1339 spec = &sftp->sft_spec[filter_idx];
1340 if ((key = siena_filter_build(&filter, spec)) == 0) {
1344 if ((rc = siena_filter_push_entry(enp,
1345 spec->sfs_type, filter_idx, &filter)) != 0)
1350 siena_filter_push_rx_limits(enp);
1351 siena_filter_push_tx_limits(enp);
1353 EFSYS_UNLOCK(enp->en_eslp, state);
1361 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1363 EFSYS_UNLOCK(enp->en_eslp, state);
1368 static __checkReturn efx_rc_t
1370 __in efx_nic_t *enp,
1371 __inout efx_filter_spec_t *spec,
1372 __in boolean_t may_replace)
1375 siena_filter_spec_t sf_spec;
1376 siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
1377 siena_filter_tbl_id_t tbl_id;
1378 siena_filter_tbl_t *sftp;
1379 siena_filter_spec_t *saved_sf_spec;
1383 efsys_lock_state_t state;
1387 EFSYS_ASSERT3P(spec, !=, NULL);
1389 if ((rc = siena_filter_spec_from_gen_spec(&sf_spec, spec)) != 0)
1392 tbl_id = siena_filter_tbl_id(sf_spec.sfs_type);
1393 sftp = &sfp->sf_tbl[tbl_id];
1395 if (sftp->sft_size == 0) {
1400 key = siena_filter_build(&filter, &sf_spec);
1402 EFSYS_LOCK(enp->en_eslp, state);
1404 rc = siena_filter_search(sftp, &sf_spec, key, B_TRUE,
1405 &filter_idx, &depth);
1409 EFSYS_ASSERT3U(filter_idx, <, sftp->sft_size);
1410 saved_sf_spec = &sftp->sft_spec[filter_idx];
1412 if (siena_filter_test_used(sftp, filter_idx)) {
1413 if (may_replace == B_FALSE) {
1418 siena_filter_set_used(sftp, filter_idx);
1419 *saved_sf_spec = sf_spec;
1421 if (sfp->sf_depth[sf_spec.sfs_type] < depth) {
1422 sfp->sf_depth[sf_spec.sfs_type] = depth;
1423 if (tbl_id == EFX_SIENA_FILTER_TBL_TX_IP ||
1424 tbl_id == EFX_SIENA_FILTER_TBL_TX_MAC)
1425 siena_filter_push_tx_limits(enp);
1427 siena_filter_push_rx_limits(enp);
1430 siena_filter_push_entry(enp, sf_spec.sfs_type,
1431 filter_idx, &filter);
1433 EFSYS_UNLOCK(enp->en_eslp, state);
1440 EFSYS_UNLOCK(enp->en_eslp, state);
1447 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1451 static __checkReturn efx_rc_t
1452 siena_filter_delete(
1453 __in efx_nic_t *enp,
1454 __inout efx_filter_spec_t *spec)
1457 siena_filter_spec_t sf_spec;
1458 siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
1459 siena_filter_tbl_id_t tbl_id;
1460 siena_filter_tbl_t *sftp;
1464 efsys_lock_state_t state;
1467 EFSYS_ASSERT3P(spec, !=, NULL);
1469 if ((rc = siena_filter_spec_from_gen_spec(&sf_spec, spec)) != 0)
1472 tbl_id = siena_filter_tbl_id(sf_spec.sfs_type);
1473 sftp = &sfp->sf_tbl[tbl_id];
1475 key = siena_filter_build(&filter, &sf_spec);
1477 EFSYS_LOCK(enp->en_eslp, state);
1479 rc = siena_filter_search(sftp, &sf_spec, key, B_FALSE,
1480 &filter_idx, &depth);
1484 siena_filter_clear_entry(enp, sftp, filter_idx);
1485 if (sftp->sft_used == 0)
1486 siena_filter_reset_search_depth(sfp, tbl_id);
1488 EFSYS_UNLOCK(enp->en_eslp, state);
1492 EFSYS_UNLOCK(enp->en_eslp, state);
1496 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1500 #define SIENA_MAX_SUPPORTED_MATCHES 4
1502 static __checkReturn efx_rc_t
1503 siena_filter_supported_filters(
1504 __in efx_nic_t *enp,
1505 __out_ecount(buffer_length) uint32_t *buffer,
1506 __in size_t buffer_length,
1507 __out size_t *list_lengthp)
1510 uint32_t rx_matches[SIENA_MAX_SUPPORTED_MATCHES];
1514 rx_matches[index++] =
1515 EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
1516 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT |
1517 EFX_FILTER_MATCH_REM_HOST | EFX_FILTER_MATCH_REM_PORT;
1519 rx_matches[index++] =
1520 EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
1521 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT;
1523 if (enp->en_features & EFX_FEATURE_MAC_HEADER_FILTERS) {
1524 rx_matches[index++] =
1525 EFX_FILTER_MATCH_OUTER_VID | EFX_FILTER_MATCH_LOC_MAC;
1527 rx_matches[index++] = EFX_FILTER_MATCH_LOC_MAC;
1530 EFSYS_ASSERT3U(index, <=, SIENA_MAX_SUPPORTED_MATCHES);
1531 list_length = index;
1533 *list_lengthp = list_length;
1535 if (buffer_length < list_length) {
1540 memcpy(buffer, rx_matches, list_length * sizeof (rx_matches[0]));
1545 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1550 #undef MAX_SUPPORTED
1552 #endif /* EFSYS_OPT_SIENA */
1554 #endif /* EFSYS_OPT_FILTER */