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 */
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 /* EFX_OPTS_EF10() */
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_MANUAL;
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 VNI or VSID in tunnel filter
496 static __checkReturn efx_rc_t
497 efx_filter_spec_set_tunnel(
498 __inout efx_filter_spec_t *spec,
499 __in efx_tunnel_protocol_t encap_type,
500 __in const uint8_t *vni_or_vsid,
501 __in const uint8_t *inner_addr,
502 __in const uint8_t *outer_addr)
506 EFSYS_ASSERT3P(spec, !=, NULL);
507 EFSYS_ASSERT3P(vni_or_vsid, !=, NULL);
508 EFSYS_ASSERT3P(inner_addr, !=, NULL);
509 EFSYS_ASSERT3P(outer_addr, !=, NULL);
511 switch (encap_type) {
512 case EFX_TUNNEL_PROTOCOL_VXLAN:
513 case EFX_TUNNEL_PROTOCOL_GENEVE:
514 case EFX_TUNNEL_PROTOCOL_NVGRE:
521 if ((inner_addr == NULL) && (outer_addr == NULL)) {
526 if (vni_or_vsid != NULL) {
527 spec->efs_match_flags |= EFX_FILTER_MATCH_VNI_OR_VSID;
528 memcpy(spec->efs_vni_or_vsid, vni_or_vsid, EFX_VNI_OR_VSID_LEN);
530 if (outer_addr != NULL) {
531 spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_MAC;
532 memcpy(spec->efs_loc_mac, outer_addr, EFX_MAC_ADDR_LEN);
534 if (inner_addr != NULL) {
535 spec->efs_match_flags |= EFX_FILTER_MATCH_IFRM_LOC_MAC;
536 memcpy(spec->efs_ifrm_loc_mac, inner_addr, EFX_MAC_ADDR_LEN);
539 spec->efs_match_flags |= EFX_FILTER_MATCH_ENCAP_TYPE;
540 spec->efs_encap_type = encap_type;
547 EFSYS_PROBE1(fail1, efx_rc_t, rc);
553 * Specify inner and outer Ethernet address and VNI in VXLAN filter
556 __checkReturn efx_rc_t
557 efx_filter_spec_set_vxlan(
558 __inout efx_filter_spec_t *spec,
559 __in const uint8_t *vni,
560 __in const uint8_t *inner_addr,
561 __in const uint8_t *outer_addr)
563 return efx_filter_spec_set_tunnel(spec, EFX_TUNNEL_PROTOCOL_VXLAN,
564 vni, inner_addr, outer_addr);
568 * Specify inner and outer Ethernet address and VNI in Geneve filter
571 __checkReturn efx_rc_t
572 efx_filter_spec_set_geneve(
573 __inout efx_filter_spec_t *spec,
574 __in const uint8_t *vni,
575 __in const uint8_t *inner_addr,
576 __in const uint8_t *outer_addr)
578 return efx_filter_spec_set_tunnel(spec, EFX_TUNNEL_PROTOCOL_GENEVE,
579 vni, inner_addr, outer_addr);
583 * Specify inner and outer Ethernet address and vsid in NVGRE filter
586 __checkReturn efx_rc_t
587 efx_filter_spec_set_nvgre(
588 __inout efx_filter_spec_t *spec,
589 __in const uint8_t *vsid,
590 __in const uint8_t *inner_addr,
591 __in const uint8_t *outer_addr)
593 return efx_filter_spec_set_tunnel(spec, EFX_TUNNEL_PROTOCOL_NVGRE,
594 vsid, inner_addr, outer_addr);
597 #if EFSYS_OPT_RX_SCALE
598 __checkReturn efx_rc_t
599 efx_filter_spec_set_rss_context(
600 __inout efx_filter_spec_t *spec,
601 __in uint32_t rss_context)
605 EFSYS_ASSERT3P(spec, !=, NULL);
607 /* The filter must have been created with EFX_FILTER_FLAG_RX_RSS. */
608 if ((spec->efs_flags & EFX_FILTER_FLAG_RX_RSS) == 0) {
613 spec->efs_rss_context = rss_context;
618 EFSYS_PROBE1(fail1, efx_rc_t, rc);
627 * "Fudge factors" - difference between programmed value and actual depth.
628 * Due to pipelined implementation we need to program H/W with a value that
629 * is larger than the hop limit we want.
631 #define FILTER_CTL_SRCH_FUDGE_WILD 3
632 #define FILTER_CTL_SRCH_FUDGE_FULL 1
635 * Hard maximum hop limit. Hardware will time-out beyond 200-something.
636 * We also need to avoid infinite loops in efx_filter_search() when the
639 #define FILTER_CTL_SRCH_MAX 200
641 static __checkReturn efx_rc_t
642 siena_filter_spec_from_gen_spec(
643 __out siena_filter_spec_t *sf_spec,
644 __in efx_filter_spec_t *gen_spec)
647 boolean_t is_full = B_FALSE;
649 if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX)
650 EFSYS_ASSERT3U(gen_spec->efs_flags, ==, EFX_FILTER_FLAG_TX);
652 EFSYS_ASSERT3U(gen_spec->efs_flags, &, EFX_FILTER_FLAG_RX);
654 /* Siena only has one RSS context */
655 if ((gen_spec->efs_flags & EFX_FILTER_FLAG_RX_RSS) &&
656 gen_spec->efs_rss_context != EFX_RSS_CONTEXT_DEFAULT) {
661 sf_spec->sfs_flags = gen_spec->efs_flags;
662 sf_spec->sfs_dmaq_id = gen_spec->efs_dmaq_id;
664 switch (gen_spec->efs_match_flags) {
665 case EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
666 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT |
667 EFX_FILTER_MATCH_REM_HOST | EFX_FILTER_MATCH_REM_PORT:
670 case EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
671 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT: {
672 uint32_t rhost, host1, host2;
673 uint16_t rport, port1, port2;
675 if (gen_spec->efs_ether_type != EFX_ETHER_TYPE_IPV4) {
679 if (gen_spec->efs_loc_port == 0 ||
680 (is_full && gen_spec->efs_rem_port == 0)) {
684 switch (gen_spec->efs_ip_proto) {
685 case EFX_IPPROTO_TCP:
686 if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX) {
687 sf_spec->sfs_type = (is_full ?
688 EFX_SIENA_FILTER_TX_TCP_FULL :
689 EFX_SIENA_FILTER_TX_TCP_WILD);
691 sf_spec->sfs_type = (is_full ?
692 EFX_SIENA_FILTER_RX_TCP_FULL :
693 EFX_SIENA_FILTER_RX_TCP_WILD);
696 case EFX_IPPROTO_UDP:
697 if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX) {
698 sf_spec->sfs_type = (is_full ?
699 EFX_SIENA_FILTER_TX_UDP_FULL :
700 EFX_SIENA_FILTER_TX_UDP_WILD);
702 sf_spec->sfs_type = (is_full ?
703 EFX_SIENA_FILTER_RX_UDP_FULL :
704 EFX_SIENA_FILTER_RX_UDP_WILD);
712 * The filter is constructed in terms of source and destination,
713 * with the odd wrinkle that the ports are swapped in a UDP
714 * wildcard filter. We need to convert from local and remote
715 * addresses (zero for a wildcard).
717 rhost = is_full ? gen_spec->efs_rem_host.eo_u32[0] : 0;
718 rport = is_full ? gen_spec->efs_rem_port : 0;
719 if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX) {
720 host1 = gen_spec->efs_loc_host.eo_u32[0];
724 host2 = gen_spec->efs_loc_host.eo_u32[0];
726 if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX) {
727 if (sf_spec->sfs_type ==
728 EFX_SIENA_FILTER_TX_UDP_WILD) {
730 port2 = gen_spec->efs_loc_port;
732 port1 = gen_spec->efs_loc_port;
736 if (sf_spec->sfs_type ==
737 EFX_SIENA_FILTER_RX_UDP_WILD) {
738 port1 = gen_spec->efs_loc_port;
742 port2 = gen_spec->efs_loc_port;
745 sf_spec->sfs_dword[0] = (host1 << 16) | port1;
746 sf_spec->sfs_dword[1] = (port2 << 16) | (host1 >> 16);
747 sf_spec->sfs_dword[2] = host2;
751 case EFX_FILTER_MATCH_LOC_MAC | EFX_FILTER_MATCH_OUTER_VID:
754 case EFX_FILTER_MATCH_LOC_MAC:
755 if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX) {
756 sf_spec->sfs_type = (is_full ?
757 EFX_SIENA_FILTER_TX_MAC_FULL :
758 EFX_SIENA_FILTER_TX_MAC_WILD);
760 sf_spec->sfs_type = (is_full ?
761 EFX_SIENA_FILTER_RX_MAC_FULL :
762 EFX_SIENA_FILTER_RX_MAC_WILD);
764 sf_spec->sfs_dword[0] = is_full ? gen_spec->efs_outer_vid : 0;
765 sf_spec->sfs_dword[1] =
766 gen_spec->efs_loc_mac[2] << 24 |
767 gen_spec->efs_loc_mac[3] << 16 |
768 gen_spec->efs_loc_mac[4] << 8 |
769 gen_spec->efs_loc_mac[5];
770 sf_spec->sfs_dword[2] =
771 gen_spec->efs_loc_mac[0] << 8 |
772 gen_spec->efs_loc_mac[1];
776 EFSYS_ASSERT(B_FALSE);
792 EFSYS_PROBE1(fail1, efx_rc_t, rc);
798 * The filter hash function is LFSR polynomial x^16 + x^3 + 1 of a 32-bit
799 * key derived from the n-tuple.
802 siena_filter_tbl_hash(
807 /* First 16 rounds */
808 tmp = 0x1fff ^ (uint16_t)(key >> 16);
809 tmp = tmp ^ tmp >> 3 ^ tmp >> 6;
810 tmp = tmp ^ tmp >> 9;
813 tmp = tmp ^ tmp << 13 ^ (uint16_t)(key & 0xffff);
814 tmp = tmp ^ tmp >> 3 ^ tmp >> 6;
815 tmp = tmp ^ tmp >> 9;
821 * To allow for hash collisions, filter search continues at these
822 * increments from the first possible entry selected by the hash.
825 siena_filter_tbl_increment(
828 return ((uint16_t)(key * 2 - 1));
831 static __checkReturn boolean_t
832 siena_filter_test_used(
833 __in siena_filter_tbl_t *sftp,
834 __in unsigned int index)
836 EFSYS_ASSERT3P(sftp->sft_bitmap, !=, NULL);
837 return ((sftp->sft_bitmap[index / 32] & (1 << (index % 32))) != 0);
841 siena_filter_set_used(
842 __in siena_filter_tbl_t *sftp,
843 __in unsigned int index)
845 EFSYS_ASSERT3P(sftp->sft_bitmap, !=, NULL);
846 sftp->sft_bitmap[index / 32] |= (1 << (index % 32));
851 siena_filter_clear_used(
852 __in siena_filter_tbl_t *sftp,
853 __in unsigned int index)
855 EFSYS_ASSERT3P(sftp->sft_bitmap, !=, NULL);
856 sftp->sft_bitmap[index / 32] &= ~(1 << (index % 32));
859 EFSYS_ASSERT3U(sftp->sft_used, >=, 0);
863 static siena_filter_tbl_id_t
865 __in siena_filter_type_t type)
867 siena_filter_tbl_id_t tbl_id;
870 case EFX_SIENA_FILTER_RX_TCP_FULL:
871 case EFX_SIENA_FILTER_RX_TCP_WILD:
872 case EFX_SIENA_FILTER_RX_UDP_FULL:
873 case EFX_SIENA_FILTER_RX_UDP_WILD:
874 tbl_id = EFX_SIENA_FILTER_TBL_RX_IP;
877 case EFX_SIENA_FILTER_RX_MAC_FULL:
878 case EFX_SIENA_FILTER_RX_MAC_WILD:
879 tbl_id = EFX_SIENA_FILTER_TBL_RX_MAC;
882 case EFX_SIENA_FILTER_TX_TCP_FULL:
883 case EFX_SIENA_FILTER_TX_TCP_WILD:
884 case EFX_SIENA_FILTER_TX_UDP_FULL:
885 case EFX_SIENA_FILTER_TX_UDP_WILD:
886 tbl_id = EFX_SIENA_FILTER_TBL_TX_IP;
889 case EFX_SIENA_FILTER_TX_MAC_FULL:
890 case EFX_SIENA_FILTER_TX_MAC_WILD:
891 tbl_id = EFX_SIENA_FILTER_TBL_TX_MAC;
895 EFSYS_ASSERT(B_FALSE);
896 tbl_id = EFX_SIENA_FILTER_NTBLS;
903 siena_filter_reset_search_depth(
904 __inout siena_filter_t *sfp,
905 __in siena_filter_tbl_id_t tbl_id)
908 case EFX_SIENA_FILTER_TBL_RX_IP:
909 sfp->sf_depth[EFX_SIENA_FILTER_RX_TCP_FULL] = 0;
910 sfp->sf_depth[EFX_SIENA_FILTER_RX_TCP_WILD] = 0;
911 sfp->sf_depth[EFX_SIENA_FILTER_RX_UDP_FULL] = 0;
912 sfp->sf_depth[EFX_SIENA_FILTER_RX_UDP_WILD] = 0;
915 case EFX_SIENA_FILTER_TBL_RX_MAC:
916 sfp->sf_depth[EFX_SIENA_FILTER_RX_MAC_FULL] = 0;
917 sfp->sf_depth[EFX_SIENA_FILTER_RX_MAC_WILD] = 0;
920 case EFX_SIENA_FILTER_TBL_TX_IP:
921 sfp->sf_depth[EFX_SIENA_FILTER_TX_TCP_FULL] = 0;
922 sfp->sf_depth[EFX_SIENA_FILTER_TX_TCP_WILD] = 0;
923 sfp->sf_depth[EFX_SIENA_FILTER_TX_UDP_FULL] = 0;
924 sfp->sf_depth[EFX_SIENA_FILTER_TX_UDP_WILD] = 0;
927 case EFX_SIENA_FILTER_TBL_TX_MAC:
928 sfp->sf_depth[EFX_SIENA_FILTER_TX_MAC_FULL] = 0;
929 sfp->sf_depth[EFX_SIENA_FILTER_TX_MAC_WILD] = 0;
933 EFSYS_ASSERT(B_FALSE);
939 siena_filter_push_rx_limits(
942 siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
945 EFX_BAR_READO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
947 EFX_SET_OWORD_FIELD(oword, FRF_AZ_TCP_FULL_SRCH_LIMIT,
948 sfp->sf_depth[EFX_SIENA_FILTER_RX_TCP_FULL] +
949 FILTER_CTL_SRCH_FUDGE_FULL);
950 EFX_SET_OWORD_FIELD(oword, FRF_AZ_TCP_WILD_SRCH_LIMIT,
951 sfp->sf_depth[EFX_SIENA_FILTER_RX_TCP_WILD] +
952 FILTER_CTL_SRCH_FUDGE_WILD);
953 EFX_SET_OWORD_FIELD(oword, FRF_AZ_UDP_FULL_SRCH_LIMIT,
954 sfp->sf_depth[EFX_SIENA_FILTER_RX_UDP_FULL] +
955 FILTER_CTL_SRCH_FUDGE_FULL);
956 EFX_SET_OWORD_FIELD(oword, FRF_AZ_UDP_WILD_SRCH_LIMIT,
957 sfp->sf_depth[EFX_SIENA_FILTER_RX_UDP_WILD] +
958 FILTER_CTL_SRCH_FUDGE_WILD);
960 if (sfp->sf_tbl[EFX_SIENA_FILTER_TBL_RX_MAC].sft_size) {
961 EFX_SET_OWORD_FIELD(oword,
962 FRF_CZ_ETHERNET_FULL_SEARCH_LIMIT,
963 sfp->sf_depth[EFX_SIENA_FILTER_RX_MAC_FULL] +
964 FILTER_CTL_SRCH_FUDGE_FULL);
965 EFX_SET_OWORD_FIELD(oword,
966 FRF_CZ_ETHERNET_WILDCARD_SEARCH_LIMIT,
967 sfp->sf_depth[EFX_SIENA_FILTER_RX_MAC_WILD] +
968 FILTER_CTL_SRCH_FUDGE_WILD);
971 EFX_BAR_WRITEO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
975 siena_filter_push_tx_limits(
978 siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
981 EFX_BAR_READO(enp, FR_AZ_TX_CFG_REG, &oword);
983 if (sfp->sf_tbl[EFX_SIENA_FILTER_TBL_TX_IP].sft_size != 0) {
984 EFX_SET_OWORD_FIELD(oword,
985 FRF_CZ_TX_TCPIP_FILTER_FULL_SEARCH_RANGE,
986 sfp->sf_depth[EFX_SIENA_FILTER_TX_TCP_FULL] +
987 FILTER_CTL_SRCH_FUDGE_FULL);
988 EFX_SET_OWORD_FIELD(oword,
989 FRF_CZ_TX_TCPIP_FILTER_WILD_SEARCH_RANGE,
990 sfp->sf_depth[EFX_SIENA_FILTER_TX_TCP_WILD] +
991 FILTER_CTL_SRCH_FUDGE_WILD);
992 EFX_SET_OWORD_FIELD(oword,
993 FRF_CZ_TX_UDPIP_FILTER_FULL_SEARCH_RANGE,
994 sfp->sf_depth[EFX_SIENA_FILTER_TX_UDP_FULL] +
995 FILTER_CTL_SRCH_FUDGE_FULL);
996 EFX_SET_OWORD_FIELD(oword,
997 FRF_CZ_TX_UDPIP_FILTER_WILD_SEARCH_RANGE,
998 sfp->sf_depth[EFX_SIENA_FILTER_TX_UDP_WILD] +
999 FILTER_CTL_SRCH_FUDGE_WILD);
1002 if (sfp->sf_tbl[EFX_SIENA_FILTER_TBL_TX_MAC].sft_size != 0) {
1003 EFX_SET_OWORD_FIELD(
1004 oword, FRF_CZ_TX_ETH_FILTER_FULL_SEARCH_RANGE,
1005 sfp->sf_depth[EFX_SIENA_FILTER_TX_MAC_FULL] +
1006 FILTER_CTL_SRCH_FUDGE_FULL);
1007 EFX_SET_OWORD_FIELD(
1008 oword, FRF_CZ_TX_ETH_FILTER_WILD_SEARCH_RANGE,
1009 sfp->sf_depth[EFX_SIENA_FILTER_TX_MAC_WILD] +
1010 FILTER_CTL_SRCH_FUDGE_WILD);
1013 EFX_BAR_WRITEO(enp, FR_AZ_TX_CFG_REG, &oword);
1016 /* Build a filter entry and return its n-tuple key. */
1017 static __checkReturn uint32_t
1019 __out efx_oword_t *filter,
1020 __in siena_filter_spec_t *spec)
1024 uint8_t type = spec->sfs_type;
1025 uint32_t flags = spec->sfs_flags;
1027 switch (siena_filter_tbl_id(type)) {
1028 case EFX_SIENA_FILTER_TBL_RX_IP: {
1029 boolean_t is_udp = (type == EFX_SIENA_FILTER_RX_UDP_FULL ||
1030 type == EFX_SIENA_FILTER_RX_UDP_WILD);
1031 EFX_POPULATE_OWORD_7(*filter,
1033 (flags & EFX_FILTER_FLAG_RX_RSS) ? 1 : 0,
1035 (flags & EFX_FILTER_FLAG_RX_SCATTER) ? 1 : 0,
1036 FRF_AZ_TCP_UDP, is_udp,
1037 FRF_AZ_RXQ_ID, spec->sfs_dmaq_id,
1038 EFX_DWORD_2, spec->sfs_dword[2],
1039 EFX_DWORD_1, spec->sfs_dword[1],
1040 EFX_DWORD_0, spec->sfs_dword[0]);
1045 case EFX_SIENA_FILTER_TBL_RX_MAC: {
1046 boolean_t is_wild = (type == EFX_SIENA_FILTER_RX_MAC_WILD);
1047 EFX_POPULATE_OWORD_7(*filter,
1049 (flags & EFX_FILTER_FLAG_RX_RSS) ? 1 : 0,
1050 FRF_CZ_RMFT_SCATTER_EN,
1051 (flags & EFX_FILTER_FLAG_RX_SCATTER) ? 1 : 0,
1052 FRF_CZ_RMFT_RXQ_ID, spec->sfs_dmaq_id,
1053 FRF_CZ_RMFT_WILDCARD_MATCH, is_wild,
1054 FRF_CZ_RMFT_DEST_MAC_DW1, spec->sfs_dword[2],
1055 FRF_CZ_RMFT_DEST_MAC_DW0, spec->sfs_dword[1],
1056 FRF_CZ_RMFT_VLAN_ID, spec->sfs_dword[0]);
1061 case EFX_SIENA_FILTER_TBL_TX_IP: {
1062 boolean_t is_udp = (type == EFX_SIENA_FILTER_TX_UDP_FULL ||
1063 type == EFX_SIENA_FILTER_TX_UDP_WILD);
1064 EFX_POPULATE_OWORD_5(*filter,
1065 FRF_CZ_TIFT_TCP_UDP, is_udp,
1066 FRF_CZ_TIFT_TXQ_ID, spec->sfs_dmaq_id,
1067 EFX_DWORD_2, spec->sfs_dword[2],
1068 EFX_DWORD_1, spec->sfs_dword[1],
1069 EFX_DWORD_0, spec->sfs_dword[0]);
1070 dword3 = is_udp | spec->sfs_dmaq_id << 1;
1074 case EFX_SIENA_FILTER_TBL_TX_MAC: {
1075 boolean_t is_wild = (type == EFX_SIENA_FILTER_TX_MAC_WILD);
1076 EFX_POPULATE_OWORD_5(*filter,
1077 FRF_CZ_TMFT_TXQ_ID, spec->sfs_dmaq_id,
1078 FRF_CZ_TMFT_WILDCARD_MATCH, is_wild,
1079 FRF_CZ_TMFT_SRC_MAC_DW1, spec->sfs_dword[2],
1080 FRF_CZ_TMFT_SRC_MAC_DW0, spec->sfs_dword[1],
1081 FRF_CZ_TMFT_VLAN_ID, spec->sfs_dword[0]);
1082 dword3 = is_wild | spec->sfs_dmaq_id << 1;
1087 EFSYS_ASSERT(B_FALSE);
1088 EFX_ZERO_OWORD(*filter);
1093 spec->sfs_dword[0] ^
1094 spec->sfs_dword[1] ^
1095 spec->sfs_dword[2] ^
1101 static __checkReturn efx_rc_t
1102 siena_filter_push_entry(
1103 __inout efx_nic_t *enp,
1104 __in siena_filter_type_t type,
1106 __in efx_oword_t *eop)
1111 case EFX_SIENA_FILTER_RX_TCP_FULL:
1112 case EFX_SIENA_FILTER_RX_TCP_WILD:
1113 case EFX_SIENA_FILTER_RX_UDP_FULL:
1114 case EFX_SIENA_FILTER_RX_UDP_WILD:
1115 EFX_BAR_TBL_WRITEO(enp, FR_AZ_RX_FILTER_TBL0, index,
1119 case EFX_SIENA_FILTER_RX_MAC_FULL:
1120 case EFX_SIENA_FILTER_RX_MAC_WILD:
1121 EFX_BAR_TBL_WRITEO(enp, FR_CZ_RX_MAC_FILTER_TBL0, index,
1125 case EFX_SIENA_FILTER_TX_TCP_FULL:
1126 case EFX_SIENA_FILTER_TX_TCP_WILD:
1127 case EFX_SIENA_FILTER_TX_UDP_FULL:
1128 case EFX_SIENA_FILTER_TX_UDP_WILD:
1129 EFX_BAR_TBL_WRITEO(enp, FR_CZ_TX_FILTER_TBL0, index,
1133 case EFX_SIENA_FILTER_TX_MAC_FULL:
1134 case EFX_SIENA_FILTER_TX_MAC_WILD:
1135 EFX_BAR_TBL_WRITEO(enp, FR_CZ_TX_MAC_FILTER_TBL0, index,
1140 EFSYS_ASSERT(B_FALSE);
1151 static __checkReturn boolean_t
1153 __in const siena_filter_spec_t *left,
1154 __in const siena_filter_spec_t *right)
1156 siena_filter_tbl_id_t tbl_id;
1158 tbl_id = siena_filter_tbl_id(left->sfs_type);
1161 if (left->sfs_type != right->sfs_type)
1164 if (memcmp(left->sfs_dword, right->sfs_dword,
1165 sizeof (left->sfs_dword)))
1168 if ((tbl_id == EFX_SIENA_FILTER_TBL_TX_IP ||
1169 tbl_id == EFX_SIENA_FILTER_TBL_TX_MAC) &&
1170 left->sfs_dmaq_id != right->sfs_dmaq_id)
1176 static __checkReturn efx_rc_t
1177 siena_filter_search(
1178 __in siena_filter_tbl_t *sftp,
1179 __in siena_filter_spec_t *spec,
1181 __in boolean_t for_insert,
1182 __out int *filter_index,
1183 __out unsigned int *depth_required)
1185 unsigned int hash, incr, filter_idx, depth;
1187 hash = siena_filter_tbl_hash(key);
1188 incr = siena_filter_tbl_increment(key);
1190 filter_idx = hash & (sftp->sft_size - 1);
1195 * Return success if entry is used and matches this spec
1196 * or entry is unused and we are trying to insert.
1198 if (siena_filter_test_used(sftp, filter_idx) ?
1199 siena_filter_equal(spec,
1200 &sftp->sft_spec[filter_idx]) :
1202 *filter_index = filter_idx;
1203 *depth_required = depth;
1207 /* Return failure if we reached the maximum search depth */
1208 if (depth == FILTER_CTL_SRCH_MAX)
1209 return (for_insert ? EBUSY : ENOENT);
1211 filter_idx = (filter_idx + incr) & (sftp->sft_size - 1);
1217 siena_filter_clear_entry(
1218 __in efx_nic_t *enp,
1219 __in siena_filter_tbl_t *sftp,
1224 if (siena_filter_test_used(sftp, index)) {
1225 siena_filter_clear_used(sftp, index);
1227 EFX_ZERO_OWORD(filter);
1228 siena_filter_push_entry(enp,
1229 sftp->sft_spec[index].sfs_type,
1232 memset(&sftp->sft_spec[index],
1233 0, sizeof (sftp->sft_spec[0]));
1238 siena_filter_tbl_clear(
1239 __in efx_nic_t *enp,
1240 __in siena_filter_tbl_id_t tbl_id)
1242 siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
1243 siena_filter_tbl_t *sftp = &sfp->sf_tbl[tbl_id];
1245 efsys_lock_state_t state;
1247 EFSYS_LOCK(enp->en_eslp, state);
1249 for (index = 0; index < sftp->sft_size; ++index) {
1250 siena_filter_clear_entry(enp, sftp, index);
1253 if (sftp->sft_used == 0)
1254 siena_filter_reset_search_depth(sfp, tbl_id);
1256 EFSYS_UNLOCK(enp->en_eslp, state);
1259 static __checkReturn efx_rc_t
1261 __in efx_nic_t *enp)
1263 siena_filter_t *sfp;
1264 siena_filter_tbl_t *sftp;
1268 EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (siena_filter_t), sfp);
1275 enp->en_filter.ef_siena_filter = sfp;
1277 switch (enp->en_family) {
1278 case EFX_FAMILY_SIENA:
1279 sftp = &sfp->sf_tbl[EFX_SIENA_FILTER_TBL_RX_IP];
1280 sftp->sft_size = FR_AZ_RX_FILTER_TBL0_ROWS;
1282 sftp = &sfp->sf_tbl[EFX_SIENA_FILTER_TBL_RX_MAC];
1283 sftp->sft_size = FR_CZ_RX_MAC_FILTER_TBL0_ROWS;
1285 sftp = &sfp->sf_tbl[EFX_SIENA_FILTER_TBL_TX_IP];
1286 sftp->sft_size = FR_CZ_TX_FILTER_TBL0_ROWS;
1288 sftp = &sfp->sf_tbl[EFX_SIENA_FILTER_TBL_TX_MAC];
1289 sftp->sft_size = FR_CZ_TX_MAC_FILTER_TBL0_ROWS;
1297 for (tbl_id = 0; tbl_id < EFX_SIENA_FILTER_NTBLS; tbl_id++) {
1298 unsigned int bitmap_size;
1300 sftp = &sfp->sf_tbl[tbl_id];
1301 if (sftp->sft_size == 0)
1304 EFX_STATIC_ASSERT(sizeof (sftp->sft_bitmap[0]) ==
1307 (sftp->sft_size + (sizeof (uint32_t) * 8) - 1) / 8;
1309 EFSYS_KMEM_ALLOC(enp->en_esip, bitmap_size, sftp->sft_bitmap);
1310 if (!sftp->sft_bitmap) {
1315 EFSYS_KMEM_ALLOC(enp->en_esip,
1316 sftp->sft_size * sizeof (*sftp->sft_spec),
1318 if (!sftp->sft_spec) {
1322 memset(sftp->sft_spec, 0,
1323 sftp->sft_size * sizeof (*sftp->sft_spec));
1336 siena_filter_fini(enp);
1339 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1345 __in efx_nic_t *enp)
1347 siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
1348 siena_filter_tbl_id_t tbl_id;
1350 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1351 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1356 for (tbl_id = 0; tbl_id < EFX_SIENA_FILTER_NTBLS; tbl_id++) {
1357 siena_filter_tbl_t *sftp = &sfp->sf_tbl[tbl_id];
1358 unsigned int bitmap_size;
1360 EFX_STATIC_ASSERT(sizeof (sftp->sft_bitmap[0]) ==
1363 (sftp->sft_size + (sizeof (uint32_t) * 8) - 1) / 8;
1365 if (sftp->sft_bitmap != NULL) {
1366 EFSYS_KMEM_FREE(enp->en_esip, bitmap_size,
1368 sftp->sft_bitmap = NULL;
1371 if (sftp->sft_spec != NULL) {
1372 EFSYS_KMEM_FREE(enp->en_esip, sftp->sft_size *
1373 sizeof (*sftp->sft_spec), sftp->sft_spec);
1374 sftp->sft_spec = NULL;
1378 EFSYS_KMEM_FREE(enp->en_esip, sizeof (siena_filter_t),
1379 enp->en_filter.ef_siena_filter);
1382 /* Restore filter state after a reset */
1383 static __checkReturn efx_rc_t
1384 siena_filter_restore(
1385 __in efx_nic_t *enp)
1387 siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
1388 siena_filter_tbl_id_t tbl_id;
1389 siena_filter_tbl_t *sftp;
1390 siena_filter_spec_t *spec;
1393 efsys_lock_state_t state;
1397 EFSYS_LOCK(enp->en_eslp, state);
1399 for (tbl_id = 0; tbl_id < EFX_SIENA_FILTER_NTBLS; tbl_id++) {
1400 sftp = &sfp->sf_tbl[tbl_id];
1401 for (filter_idx = 0;
1402 filter_idx < sftp->sft_size;
1404 if (!siena_filter_test_used(sftp, filter_idx))
1407 spec = &sftp->sft_spec[filter_idx];
1408 if ((key = siena_filter_build(&filter, spec)) == 0) {
1412 if ((rc = siena_filter_push_entry(enp,
1413 spec->sfs_type, filter_idx, &filter)) != 0)
1418 siena_filter_push_rx_limits(enp);
1419 siena_filter_push_tx_limits(enp);
1421 EFSYS_UNLOCK(enp->en_eslp, state);
1429 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1431 EFSYS_UNLOCK(enp->en_eslp, state);
1436 static __checkReturn efx_rc_t
1438 __in efx_nic_t *enp,
1439 __inout efx_filter_spec_t *spec,
1440 __in boolean_t may_replace)
1443 siena_filter_spec_t sf_spec;
1444 siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
1445 siena_filter_tbl_id_t tbl_id;
1446 siena_filter_tbl_t *sftp;
1447 siena_filter_spec_t *saved_sf_spec;
1451 efsys_lock_state_t state;
1455 EFSYS_ASSERT3P(spec, !=, NULL);
1457 if ((rc = siena_filter_spec_from_gen_spec(&sf_spec, spec)) != 0)
1460 tbl_id = siena_filter_tbl_id(sf_spec.sfs_type);
1461 sftp = &sfp->sf_tbl[tbl_id];
1463 if (sftp->sft_size == 0) {
1468 key = siena_filter_build(&filter, &sf_spec);
1470 EFSYS_LOCK(enp->en_eslp, state);
1472 rc = siena_filter_search(sftp, &sf_spec, key, B_TRUE,
1473 &filter_idx, &depth);
1477 EFSYS_ASSERT3U(filter_idx, <, sftp->sft_size);
1478 saved_sf_spec = &sftp->sft_spec[filter_idx];
1480 if (siena_filter_test_used(sftp, filter_idx)) {
1481 if (may_replace == B_FALSE) {
1486 siena_filter_set_used(sftp, filter_idx);
1487 *saved_sf_spec = sf_spec;
1489 if (sfp->sf_depth[sf_spec.sfs_type] < depth) {
1490 sfp->sf_depth[sf_spec.sfs_type] = depth;
1491 if (tbl_id == EFX_SIENA_FILTER_TBL_TX_IP ||
1492 tbl_id == EFX_SIENA_FILTER_TBL_TX_MAC)
1493 siena_filter_push_tx_limits(enp);
1495 siena_filter_push_rx_limits(enp);
1498 siena_filter_push_entry(enp, sf_spec.sfs_type,
1499 filter_idx, &filter);
1501 EFSYS_UNLOCK(enp->en_eslp, state);
1508 EFSYS_UNLOCK(enp->en_eslp, state);
1515 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1519 static __checkReturn efx_rc_t
1520 siena_filter_delete(
1521 __in efx_nic_t *enp,
1522 __inout efx_filter_spec_t *spec)
1525 siena_filter_spec_t sf_spec;
1526 siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
1527 siena_filter_tbl_id_t tbl_id;
1528 siena_filter_tbl_t *sftp;
1532 efsys_lock_state_t state;
1535 EFSYS_ASSERT3P(spec, !=, NULL);
1537 if ((rc = siena_filter_spec_from_gen_spec(&sf_spec, spec)) != 0)
1540 tbl_id = siena_filter_tbl_id(sf_spec.sfs_type);
1541 sftp = &sfp->sf_tbl[tbl_id];
1543 key = siena_filter_build(&filter, &sf_spec);
1545 EFSYS_LOCK(enp->en_eslp, state);
1547 rc = siena_filter_search(sftp, &sf_spec, key, B_FALSE,
1548 &filter_idx, &depth);
1552 siena_filter_clear_entry(enp, sftp, filter_idx);
1553 if (sftp->sft_used == 0)
1554 siena_filter_reset_search_depth(sfp, tbl_id);
1556 EFSYS_UNLOCK(enp->en_eslp, state);
1560 EFSYS_UNLOCK(enp->en_eslp, state);
1564 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1568 #define SIENA_MAX_SUPPORTED_MATCHES 4
1570 static __checkReturn efx_rc_t
1571 siena_filter_supported_filters(
1572 __in efx_nic_t *enp,
1573 __out_ecount(buffer_length) uint32_t *buffer,
1574 __in size_t buffer_length,
1575 __out size_t *list_lengthp)
1578 uint32_t rx_matches[SIENA_MAX_SUPPORTED_MATCHES];
1582 rx_matches[index++] =
1583 EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
1584 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT |
1585 EFX_FILTER_MATCH_REM_HOST | EFX_FILTER_MATCH_REM_PORT;
1587 rx_matches[index++] =
1588 EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
1589 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT;
1591 if (enp->en_features & EFX_FEATURE_MAC_HEADER_FILTERS) {
1592 rx_matches[index++] =
1593 EFX_FILTER_MATCH_OUTER_VID | EFX_FILTER_MATCH_LOC_MAC;
1595 rx_matches[index++] = EFX_FILTER_MATCH_LOC_MAC;
1598 EFSYS_ASSERT3U(index, <=, SIENA_MAX_SUPPORTED_MATCHES);
1599 list_length = index;
1601 *list_lengthp = list_length;
1603 if (buffer_length < list_length) {
1608 memcpy(buffer, rx_matches, list_length * sizeof (rx_matches[0]));
1613 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1618 #undef MAX_SUPPORTED
1620 #endif /* EFSYS_OPT_SIENA */
1622 #endif /* EFSYS_OPT_FILTER */