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 efx_filter_replacement_policy_t policy);
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 if (spec->efs_priority == EFX_FILTER_PRI_AUTO) {
101 return (efop->efo_add(enp, spec,
102 EFX_FILTER_REPLACEMENT_HIGHER_PRIORITY));
109 EFSYS_PROBE1(fail1, efx_rc_t, rc);
114 __checkReturn efx_rc_t
117 __inout efx_filter_spec_t *spec)
119 const efx_filter_ops_t *efop = enp->en_efop;
121 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
122 EFSYS_ASSERT3P(spec, !=, NULL);
123 EFSYS_ASSERT3U(spec->efs_flags, &, EFX_FILTER_FLAG_RX);
125 return (efop->efo_delete(enp, spec));
128 __checkReturn efx_rc_t
134 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
136 if ((rc = enp->en_efop->efo_restore(enp)) != 0)
142 EFSYS_PROBE1(fail1, efx_rc_t, rc);
147 __checkReturn efx_rc_t
151 const efx_filter_ops_t *efop;
154 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
155 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
156 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_FILTER));
158 switch (enp->en_family) {
160 case EFX_FAMILY_SIENA:
161 efop = &__efx_filter_siena_ops;
163 #endif /* EFSYS_OPT_SIENA */
165 #if EFSYS_OPT_HUNTINGTON
166 case EFX_FAMILY_HUNTINGTON:
167 efop = &__efx_filter_ef10_ops;
169 #endif /* EFSYS_OPT_HUNTINGTON */
171 #if EFSYS_OPT_MEDFORD
172 case EFX_FAMILY_MEDFORD:
173 efop = &__efx_filter_ef10_ops;
175 #endif /* EFSYS_OPT_MEDFORD */
177 #if EFSYS_OPT_MEDFORD2
178 case EFX_FAMILY_MEDFORD2:
179 efop = &__efx_filter_ef10_ops;
181 #endif /* EFSYS_OPT_MEDFORD2 */
189 if ((rc = efop->efo_init(enp)) != 0)
193 enp->en_mod_flags |= EFX_MOD_FILTER;
199 EFSYS_PROBE1(fail1, efx_rc_t, rc);
202 enp->en_mod_flags &= ~EFX_MOD_FILTER;
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);
214 enp->en_efop->efo_fini(enp);
217 enp->en_mod_flags &= ~EFX_MOD_FILTER;
221 * Query the possible combinations of match flags which can be filtered on.
222 * These are returned as a list, of which each 32 bit element is a bitmask
223 * formed of EFX_FILTER_MATCH flags.
225 * The combinations are ordered in priority from highest to lowest.
227 * If the provided buffer is too short to hold the list, the call with fail with
228 * ENOSPC and *list_lengthp will be set to the buffer length required.
230 __checkReturn efx_rc_t
231 efx_filter_supported_filters(
233 __out_ecount(buffer_length) uint32_t *buffer,
234 __in size_t buffer_length,
235 __out size_t *list_lengthp)
239 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
240 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
241 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
242 EFSYS_ASSERT(enp->en_efop->efo_supported_filters != NULL);
244 if (buffer == NULL) {
249 rc = enp->en_efop->efo_supported_filters(enp, buffer, buffer_length,
259 EFSYS_PROBE1(fail1, efx_rc_t, rc);
264 __checkReturn efx_rc_t
265 efx_filter_reconfigure(
267 __in_ecount(6) uint8_t const *mac_addr,
268 __in boolean_t all_unicst,
269 __in boolean_t mulcst,
270 __in boolean_t all_mulcst,
271 __in boolean_t brdcst,
272 __in_ecount(6*count) uint8_t const *addrs,
277 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
278 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
279 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
281 if (enp->en_efop->efo_reconfigure != NULL) {
282 if ((rc = enp->en_efop->efo_reconfigure(enp, mac_addr,
292 EFSYS_PROBE1(fail1, efx_rc_t, rc);
298 efx_filter_spec_init_rx(
299 __out efx_filter_spec_t *spec,
300 __in efx_filter_priority_t priority,
301 __in efx_filter_flags_t flags,
304 EFSYS_ASSERT3P(spec, !=, NULL);
305 EFSYS_ASSERT3P(erp, !=, NULL);
306 EFSYS_ASSERT((flags & ~(EFX_FILTER_FLAG_RX_RSS |
307 EFX_FILTER_FLAG_RX_SCATTER)) == 0);
309 memset(spec, 0, sizeof (*spec));
310 spec->efs_priority = priority;
311 spec->efs_flags = EFX_FILTER_FLAG_RX | flags;
312 spec->efs_rss_context = EFX_RSS_CONTEXT_DEFAULT;
313 spec->efs_dmaq_id = (uint16_t)erp->er_index;
317 efx_filter_spec_init_tx(
318 __out efx_filter_spec_t *spec,
321 EFSYS_ASSERT3P(spec, !=, NULL);
322 EFSYS_ASSERT3P(etp, !=, NULL);
324 memset(spec, 0, sizeof (*spec));
325 spec->efs_priority = EFX_FILTER_PRI_MANUAL;
326 spec->efs_flags = EFX_FILTER_FLAG_TX;
327 spec->efs_dmaq_id = (uint16_t)etp->et_index;
332 * Specify IPv4 host, transport protocol and port in a filter specification
334 __checkReturn efx_rc_t
335 efx_filter_spec_set_ipv4_local(
336 __inout efx_filter_spec_t *spec,
341 EFSYS_ASSERT3P(spec, !=, NULL);
343 spec->efs_match_flags |=
344 EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
345 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT;
346 spec->efs_ether_type = EFX_ETHER_TYPE_IPV4;
347 spec->efs_ip_proto = proto;
348 spec->efs_loc_host.eo_u32[0] = host;
349 spec->efs_loc_port = port;
354 * Specify IPv4 hosts, transport protocol and ports in a filter specification
356 __checkReturn efx_rc_t
357 efx_filter_spec_set_ipv4_full(
358 __inout efx_filter_spec_t *spec,
365 EFSYS_ASSERT3P(spec, !=, NULL);
367 spec->efs_match_flags |=
368 EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
369 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT |
370 EFX_FILTER_MATCH_REM_HOST | EFX_FILTER_MATCH_REM_PORT;
371 spec->efs_ether_type = EFX_ETHER_TYPE_IPV4;
372 spec->efs_ip_proto = proto;
373 spec->efs_loc_host.eo_u32[0] = lhost;
374 spec->efs_loc_port = lport;
375 spec->efs_rem_host.eo_u32[0] = rhost;
376 spec->efs_rem_port = rport;
381 * Specify local Ethernet address and/or VID in filter specification
383 __checkReturn efx_rc_t
384 efx_filter_spec_set_eth_local(
385 __inout efx_filter_spec_t *spec,
387 __in const uint8_t *addr)
389 EFSYS_ASSERT3P(spec, !=, NULL);
390 EFSYS_ASSERT3P(addr, !=, NULL);
392 if (vid == EFX_FILTER_SPEC_VID_UNSPEC && addr == NULL)
395 if (vid != EFX_FILTER_SPEC_VID_UNSPEC) {
396 spec->efs_match_flags |= EFX_FILTER_MATCH_OUTER_VID;
397 spec->efs_outer_vid = vid;
400 spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_MAC;
401 memcpy(spec->efs_loc_mac, addr, EFX_MAC_ADDR_LEN);
407 efx_filter_spec_set_ether_type(
408 __inout efx_filter_spec_t *spec,
409 __in uint16_t ether_type)
411 EFSYS_ASSERT3P(spec, !=, NULL);
413 spec->efs_ether_type = ether_type;
414 spec->efs_match_flags |= EFX_FILTER_MATCH_ETHER_TYPE;
418 * Specify matching otherwise-unmatched unicast in a filter specification
420 __checkReturn efx_rc_t
421 efx_filter_spec_set_uc_def(
422 __inout efx_filter_spec_t *spec)
424 EFSYS_ASSERT3P(spec, !=, NULL);
426 spec->efs_match_flags |= EFX_FILTER_MATCH_UNKNOWN_UCAST_DST;
431 * Specify matching otherwise-unmatched multicast in a filter specification
433 __checkReturn efx_rc_t
434 efx_filter_spec_set_mc_def(
435 __inout efx_filter_spec_t *spec)
437 EFSYS_ASSERT3P(spec, !=, NULL);
439 spec->efs_match_flags |= EFX_FILTER_MATCH_UNKNOWN_MCAST_DST;
444 __checkReturn efx_rc_t
445 efx_filter_spec_set_encap_type(
446 __inout efx_filter_spec_t *spec,
447 __in efx_tunnel_protocol_t encap_type,
448 __in efx_filter_inner_frame_match_t inner_frame_match)
450 uint32_t match_flags = EFX_FILTER_MATCH_ENCAP_TYPE;
454 EFSYS_ASSERT3P(spec, !=, NULL);
456 switch (encap_type) {
457 case EFX_TUNNEL_PROTOCOL_VXLAN:
458 case EFX_TUNNEL_PROTOCOL_GENEVE:
459 ip_proto = EFX_IPPROTO_UDP;
461 case EFX_TUNNEL_PROTOCOL_NVGRE:
462 ip_proto = EFX_IPPROTO_GRE;
470 switch (inner_frame_match) {
471 case EFX_FILTER_INNER_FRAME_MATCH_UNKNOWN_MCAST_DST:
472 match_flags |= EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST;
474 case EFX_FILTER_INNER_FRAME_MATCH_UNKNOWN_UCAST_DST:
475 match_flags |= EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST;
477 case EFX_FILTER_INNER_FRAME_MATCH_OTHER:
478 /* This is for when specific inner frames are to be matched. */
486 spec->efs_encap_type = encap_type;
487 spec->efs_ip_proto = ip_proto;
488 spec->efs_match_flags |= (match_flags | EFX_FILTER_MATCH_IP_PROTO);
495 EFSYS_PROBE1(fail1, efx_rc_t, rc);
501 * Specify inner and outer Ethernet address and VNI or VSID in tunnel filter
504 static __checkReturn efx_rc_t
505 efx_filter_spec_set_tunnel(
506 __inout efx_filter_spec_t *spec,
507 __in efx_tunnel_protocol_t encap_type,
508 __in const uint8_t *vni_or_vsid,
509 __in const uint8_t *inner_addr,
510 __in const uint8_t *outer_addr)
514 EFSYS_ASSERT3P(spec, !=, NULL);
515 EFSYS_ASSERT3P(vni_or_vsid, !=, NULL);
516 EFSYS_ASSERT3P(inner_addr, !=, NULL);
517 EFSYS_ASSERT3P(outer_addr, !=, NULL);
519 switch (encap_type) {
520 case EFX_TUNNEL_PROTOCOL_VXLAN:
521 case EFX_TUNNEL_PROTOCOL_GENEVE:
522 case EFX_TUNNEL_PROTOCOL_NVGRE:
529 if ((inner_addr == NULL) && (outer_addr == NULL)) {
534 if (vni_or_vsid != NULL) {
535 spec->efs_match_flags |= EFX_FILTER_MATCH_VNI_OR_VSID;
536 memcpy(spec->efs_vni_or_vsid, vni_or_vsid, EFX_VNI_OR_VSID_LEN);
538 if (outer_addr != NULL) {
539 spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_MAC;
540 memcpy(spec->efs_loc_mac, outer_addr, EFX_MAC_ADDR_LEN);
542 if (inner_addr != NULL) {
543 spec->efs_match_flags |= EFX_FILTER_MATCH_IFRM_LOC_MAC;
544 memcpy(spec->efs_ifrm_loc_mac, inner_addr, EFX_MAC_ADDR_LEN);
547 spec->efs_match_flags |= EFX_FILTER_MATCH_ENCAP_TYPE;
548 spec->efs_encap_type = encap_type;
555 EFSYS_PROBE1(fail1, efx_rc_t, rc);
561 * Specify inner and outer Ethernet address and VNI in VXLAN filter
564 __checkReturn efx_rc_t
565 efx_filter_spec_set_vxlan(
566 __inout efx_filter_spec_t *spec,
567 __in const uint8_t *vni,
568 __in const uint8_t *inner_addr,
569 __in const uint8_t *outer_addr)
571 return efx_filter_spec_set_tunnel(spec, EFX_TUNNEL_PROTOCOL_VXLAN,
572 vni, inner_addr, outer_addr);
576 * Specify inner and outer Ethernet address and VNI in Geneve filter
579 __checkReturn efx_rc_t
580 efx_filter_spec_set_geneve(
581 __inout efx_filter_spec_t *spec,
582 __in const uint8_t *vni,
583 __in const uint8_t *inner_addr,
584 __in const uint8_t *outer_addr)
586 return efx_filter_spec_set_tunnel(spec, EFX_TUNNEL_PROTOCOL_GENEVE,
587 vni, inner_addr, outer_addr);
591 * Specify inner and outer Ethernet address and vsid in NVGRE filter
594 __checkReturn efx_rc_t
595 efx_filter_spec_set_nvgre(
596 __inout efx_filter_spec_t *spec,
597 __in const uint8_t *vsid,
598 __in const uint8_t *inner_addr,
599 __in const uint8_t *outer_addr)
601 return efx_filter_spec_set_tunnel(spec, EFX_TUNNEL_PROTOCOL_NVGRE,
602 vsid, inner_addr, outer_addr);
605 #if EFSYS_OPT_RX_SCALE
606 __checkReturn efx_rc_t
607 efx_filter_spec_set_rss_context(
608 __inout efx_filter_spec_t *spec,
609 __in uint32_t rss_context)
613 EFSYS_ASSERT3P(spec, !=, NULL);
615 /* The filter must have been created with EFX_FILTER_FLAG_RX_RSS. */
616 if ((spec->efs_flags & EFX_FILTER_FLAG_RX_RSS) == 0) {
621 spec->efs_rss_context = rss_context;
626 EFSYS_PROBE1(fail1, efx_rc_t, rc);
635 * "Fudge factors" - difference between programmed value and actual depth.
636 * Due to pipelined implementation we need to program H/W with a value that
637 * is larger than the hop limit we want.
639 #define FILTER_CTL_SRCH_FUDGE_WILD 3
640 #define FILTER_CTL_SRCH_FUDGE_FULL 1
643 * Hard maximum hop limit. Hardware will time-out beyond 200-something.
644 * We also need to avoid infinite loops in efx_filter_search() when the
647 #define FILTER_CTL_SRCH_MAX 200
649 static __checkReturn efx_rc_t
650 siena_filter_spec_from_gen_spec(
651 __out siena_filter_spec_t *sf_spec,
652 __in efx_filter_spec_t *gen_spec)
655 boolean_t is_full = B_FALSE;
657 if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX)
658 EFSYS_ASSERT3U(gen_spec->efs_flags, ==, EFX_FILTER_FLAG_TX);
660 EFSYS_ASSERT3U(gen_spec->efs_flags, &, EFX_FILTER_FLAG_RX);
662 /* Siena only has one RSS context */
663 if ((gen_spec->efs_flags & EFX_FILTER_FLAG_RX_RSS) &&
664 gen_spec->efs_rss_context != EFX_RSS_CONTEXT_DEFAULT) {
669 sf_spec->sfs_flags = gen_spec->efs_flags;
670 sf_spec->sfs_dmaq_id = gen_spec->efs_dmaq_id;
672 switch (gen_spec->efs_match_flags) {
673 case EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
674 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT |
675 EFX_FILTER_MATCH_REM_HOST | EFX_FILTER_MATCH_REM_PORT:
678 case EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
679 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT: {
680 uint32_t rhost, host1, host2;
681 uint16_t rport, port1, port2;
683 if (gen_spec->efs_ether_type != EFX_ETHER_TYPE_IPV4) {
687 if (gen_spec->efs_loc_port == 0 ||
688 (is_full && gen_spec->efs_rem_port == 0)) {
692 switch (gen_spec->efs_ip_proto) {
693 case EFX_IPPROTO_TCP:
694 if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX) {
695 sf_spec->sfs_type = (is_full ?
696 EFX_SIENA_FILTER_TX_TCP_FULL :
697 EFX_SIENA_FILTER_TX_TCP_WILD);
699 sf_spec->sfs_type = (is_full ?
700 EFX_SIENA_FILTER_RX_TCP_FULL :
701 EFX_SIENA_FILTER_RX_TCP_WILD);
704 case EFX_IPPROTO_UDP:
705 if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX) {
706 sf_spec->sfs_type = (is_full ?
707 EFX_SIENA_FILTER_TX_UDP_FULL :
708 EFX_SIENA_FILTER_TX_UDP_WILD);
710 sf_spec->sfs_type = (is_full ?
711 EFX_SIENA_FILTER_RX_UDP_FULL :
712 EFX_SIENA_FILTER_RX_UDP_WILD);
720 * The filter is constructed in terms of source and destination,
721 * with the odd wrinkle that the ports are swapped in a UDP
722 * wildcard filter. We need to convert from local and remote
723 * addresses (zero for a wildcard).
725 rhost = is_full ? gen_spec->efs_rem_host.eo_u32[0] : 0;
726 rport = is_full ? gen_spec->efs_rem_port : 0;
727 if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX) {
728 host1 = gen_spec->efs_loc_host.eo_u32[0];
732 host2 = gen_spec->efs_loc_host.eo_u32[0];
734 if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX) {
735 if (sf_spec->sfs_type ==
736 EFX_SIENA_FILTER_TX_UDP_WILD) {
738 port2 = gen_spec->efs_loc_port;
740 port1 = gen_spec->efs_loc_port;
744 if (sf_spec->sfs_type ==
745 EFX_SIENA_FILTER_RX_UDP_WILD) {
746 port1 = gen_spec->efs_loc_port;
750 port2 = gen_spec->efs_loc_port;
753 sf_spec->sfs_dword[0] = (host1 << 16) | port1;
754 sf_spec->sfs_dword[1] = (port2 << 16) | (host1 >> 16);
755 sf_spec->sfs_dword[2] = host2;
759 case EFX_FILTER_MATCH_LOC_MAC | EFX_FILTER_MATCH_OUTER_VID:
762 case EFX_FILTER_MATCH_LOC_MAC:
763 if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX) {
764 sf_spec->sfs_type = (is_full ?
765 EFX_SIENA_FILTER_TX_MAC_FULL :
766 EFX_SIENA_FILTER_TX_MAC_WILD);
768 sf_spec->sfs_type = (is_full ?
769 EFX_SIENA_FILTER_RX_MAC_FULL :
770 EFX_SIENA_FILTER_RX_MAC_WILD);
772 sf_spec->sfs_dword[0] = is_full ? gen_spec->efs_outer_vid : 0;
773 sf_spec->sfs_dword[1] =
774 gen_spec->efs_loc_mac[2] << 24 |
775 gen_spec->efs_loc_mac[3] << 16 |
776 gen_spec->efs_loc_mac[4] << 8 |
777 gen_spec->efs_loc_mac[5];
778 sf_spec->sfs_dword[2] =
779 gen_spec->efs_loc_mac[0] << 8 |
780 gen_spec->efs_loc_mac[1];
784 EFSYS_ASSERT(B_FALSE);
800 EFSYS_PROBE1(fail1, efx_rc_t, rc);
806 * The filter hash function is LFSR polynomial x^16 + x^3 + 1 of a 32-bit
807 * key derived from the n-tuple.
810 siena_filter_tbl_hash(
815 /* First 16 rounds */
816 tmp = 0x1fff ^ (uint16_t)(key >> 16);
817 tmp = tmp ^ tmp >> 3 ^ tmp >> 6;
818 tmp = tmp ^ tmp >> 9;
821 tmp = tmp ^ tmp << 13 ^ (uint16_t)(key & 0xffff);
822 tmp = tmp ^ tmp >> 3 ^ tmp >> 6;
823 tmp = tmp ^ tmp >> 9;
829 * To allow for hash collisions, filter search continues at these
830 * increments from the first possible entry selected by the hash.
833 siena_filter_tbl_increment(
836 return ((uint16_t)(key * 2 - 1));
839 static __checkReturn boolean_t
840 siena_filter_test_used(
841 __in siena_filter_tbl_t *sftp,
842 __in unsigned int index)
844 EFSYS_ASSERT3P(sftp->sft_bitmap, !=, NULL);
845 return ((sftp->sft_bitmap[index / 32] & (1 << (index % 32))) != 0);
849 siena_filter_set_used(
850 __in siena_filter_tbl_t *sftp,
851 __in unsigned int index)
853 EFSYS_ASSERT3P(sftp->sft_bitmap, !=, NULL);
854 sftp->sft_bitmap[index / 32] |= (1 << (index % 32));
859 siena_filter_clear_used(
860 __in siena_filter_tbl_t *sftp,
861 __in unsigned int index)
863 EFSYS_ASSERT3P(sftp->sft_bitmap, !=, NULL);
864 sftp->sft_bitmap[index / 32] &= ~(1 << (index % 32));
867 EFSYS_ASSERT3U(sftp->sft_used, >=, 0);
871 static siena_filter_tbl_id_t
873 __in siena_filter_type_t type)
875 siena_filter_tbl_id_t tbl_id;
878 case EFX_SIENA_FILTER_RX_TCP_FULL:
879 case EFX_SIENA_FILTER_RX_TCP_WILD:
880 case EFX_SIENA_FILTER_RX_UDP_FULL:
881 case EFX_SIENA_FILTER_RX_UDP_WILD:
882 tbl_id = EFX_SIENA_FILTER_TBL_RX_IP;
885 case EFX_SIENA_FILTER_RX_MAC_FULL:
886 case EFX_SIENA_FILTER_RX_MAC_WILD:
887 tbl_id = EFX_SIENA_FILTER_TBL_RX_MAC;
890 case EFX_SIENA_FILTER_TX_TCP_FULL:
891 case EFX_SIENA_FILTER_TX_TCP_WILD:
892 case EFX_SIENA_FILTER_TX_UDP_FULL:
893 case EFX_SIENA_FILTER_TX_UDP_WILD:
894 tbl_id = EFX_SIENA_FILTER_TBL_TX_IP;
897 case EFX_SIENA_FILTER_TX_MAC_FULL:
898 case EFX_SIENA_FILTER_TX_MAC_WILD:
899 tbl_id = EFX_SIENA_FILTER_TBL_TX_MAC;
903 EFSYS_ASSERT(B_FALSE);
904 tbl_id = EFX_SIENA_FILTER_NTBLS;
911 siena_filter_reset_search_depth(
912 __inout siena_filter_t *sfp,
913 __in siena_filter_tbl_id_t tbl_id)
916 case EFX_SIENA_FILTER_TBL_RX_IP:
917 sfp->sf_depth[EFX_SIENA_FILTER_RX_TCP_FULL] = 0;
918 sfp->sf_depth[EFX_SIENA_FILTER_RX_TCP_WILD] = 0;
919 sfp->sf_depth[EFX_SIENA_FILTER_RX_UDP_FULL] = 0;
920 sfp->sf_depth[EFX_SIENA_FILTER_RX_UDP_WILD] = 0;
923 case EFX_SIENA_FILTER_TBL_RX_MAC:
924 sfp->sf_depth[EFX_SIENA_FILTER_RX_MAC_FULL] = 0;
925 sfp->sf_depth[EFX_SIENA_FILTER_RX_MAC_WILD] = 0;
928 case EFX_SIENA_FILTER_TBL_TX_IP:
929 sfp->sf_depth[EFX_SIENA_FILTER_TX_TCP_FULL] = 0;
930 sfp->sf_depth[EFX_SIENA_FILTER_TX_TCP_WILD] = 0;
931 sfp->sf_depth[EFX_SIENA_FILTER_TX_UDP_FULL] = 0;
932 sfp->sf_depth[EFX_SIENA_FILTER_TX_UDP_WILD] = 0;
935 case EFX_SIENA_FILTER_TBL_TX_MAC:
936 sfp->sf_depth[EFX_SIENA_FILTER_TX_MAC_FULL] = 0;
937 sfp->sf_depth[EFX_SIENA_FILTER_TX_MAC_WILD] = 0;
941 EFSYS_ASSERT(B_FALSE);
947 siena_filter_push_rx_limits(
950 siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
953 EFX_BAR_READO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
955 EFX_SET_OWORD_FIELD(oword, FRF_AZ_TCP_FULL_SRCH_LIMIT,
956 sfp->sf_depth[EFX_SIENA_FILTER_RX_TCP_FULL] +
957 FILTER_CTL_SRCH_FUDGE_FULL);
958 EFX_SET_OWORD_FIELD(oword, FRF_AZ_TCP_WILD_SRCH_LIMIT,
959 sfp->sf_depth[EFX_SIENA_FILTER_RX_TCP_WILD] +
960 FILTER_CTL_SRCH_FUDGE_WILD);
961 EFX_SET_OWORD_FIELD(oword, FRF_AZ_UDP_FULL_SRCH_LIMIT,
962 sfp->sf_depth[EFX_SIENA_FILTER_RX_UDP_FULL] +
963 FILTER_CTL_SRCH_FUDGE_FULL);
964 EFX_SET_OWORD_FIELD(oword, FRF_AZ_UDP_WILD_SRCH_LIMIT,
965 sfp->sf_depth[EFX_SIENA_FILTER_RX_UDP_WILD] +
966 FILTER_CTL_SRCH_FUDGE_WILD);
968 if (sfp->sf_tbl[EFX_SIENA_FILTER_TBL_RX_MAC].sft_size) {
969 EFX_SET_OWORD_FIELD(oword,
970 FRF_CZ_ETHERNET_FULL_SEARCH_LIMIT,
971 sfp->sf_depth[EFX_SIENA_FILTER_RX_MAC_FULL] +
972 FILTER_CTL_SRCH_FUDGE_FULL);
973 EFX_SET_OWORD_FIELD(oword,
974 FRF_CZ_ETHERNET_WILDCARD_SEARCH_LIMIT,
975 sfp->sf_depth[EFX_SIENA_FILTER_RX_MAC_WILD] +
976 FILTER_CTL_SRCH_FUDGE_WILD);
979 EFX_BAR_WRITEO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
983 siena_filter_push_tx_limits(
986 siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
989 EFX_BAR_READO(enp, FR_AZ_TX_CFG_REG, &oword);
991 if (sfp->sf_tbl[EFX_SIENA_FILTER_TBL_TX_IP].sft_size != 0) {
992 EFX_SET_OWORD_FIELD(oword,
993 FRF_CZ_TX_TCPIP_FILTER_FULL_SEARCH_RANGE,
994 sfp->sf_depth[EFX_SIENA_FILTER_TX_TCP_FULL] +
995 FILTER_CTL_SRCH_FUDGE_FULL);
996 EFX_SET_OWORD_FIELD(oword,
997 FRF_CZ_TX_TCPIP_FILTER_WILD_SEARCH_RANGE,
998 sfp->sf_depth[EFX_SIENA_FILTER_TX_TCP_WILD] +
999 FILTER_CTL_SRCH_FUDGE_WILD);
1000 EFX_SET_OWORD_FIELD(oword,
1001 FRF_CZ_TX_UDPIP_FILTER_FULL_SEARCH_RANGE,
1002 sfp->sf_depth[EFX_SIENA_FILTER_TX_UDP_FULL] +
1003 FILTER_CTL_SRCH_FUDGE_FULL);
1004 EFX_SET_OWORD_FIELD(oword,
1005 FRF_CZ_TX_UDPIP_FILTER_WILD_SEARCH_RANGE,
1006 sfp->sf_depth[EFX_SIENA_FILTER_TX_UDP_WILD] +
1007 FILTER_CTL_SRCH_FUDGE_WILD);
1010 if (sfp->sf_tbl[EFX_SIENA_FILTER_TBL_TX_MAC].sft_size != 0) {
1011 EFX_SET_OWORD_FIELD(
1012 oword, FRF_CZ_TX_ETH_FILTER_FULL_SEARCH_RANGE,
1013 sfp->sf_depth[EFX_SIENA_FILTER_TX_MAC_FULL] +
1014 FILTER_CTL_SRCH_FUDGE_FULL);
1015 EFX_SET_OWORD_FIELD(
1016 oword, FRF_CZ_TX_ETH_FILTER_WILD_SEARCH_RANGE,
1017 sfp->sf_depth[EFX_SIENA_FILTER_TX_MAC_WILD] +
1018 FILTER_CTL_SRCH_FUDGE_WILD);
1021 EFX_BAR_WRITEO(enp, FR_AZ_TX_CFG_REG, &oword);
1024 /* Build a filter entry and return its n-tuple key. */
1025 static __checkReturn uint32_t
1027 __out efx_oword_t *filter,
1028 __in siena_filter_spec_t *spec)
1032 uint8_t type = spec->sfs_type;
1033 uint32_t flags = spec->sfs_flags;
1035 switch (siena_filter_tbl_id(type)) {
1036 case EFX_SIENA_FILTER_TBL_RX_IP: {
1037 boolean_t is_udp = (type == EFX_SIENA_FILTER_RX_UDP_FULL ||
1038 type == EFX_SIENA_FILTER_RX_UDP_WILD);
1039 EFX_POPULATE_OWORD_7(*filter,
1041 (flags & EFX_FILTER_FLAG_RX_RSS) ? 1 : 0,
1043 (flags & EFX_FILTER_FLAG_RX_SCATTER) ? 1 : 0,
1044 FRF_AZ_TCP_UDP, is_udp,
1045 FRF_AZ_RXQ_ID, spec->sfs_dmaq_id,
1046 EFX_DWORD_2, spec->sfs_dword[2],
1047 EFX_DWORD_1, spec->sfs_dword[1],
1048 EFX_DWORD_0, spec->sfs_dword[0]);
1053 case EFX_SIENA_FILTER_TBL_RX_MAC: {
1054 boolean_t is_wild = (type == EFX_SIENA_FILTER_RX_MAC_WILD);
1055 EFX_POPULATE_OWORD_7(*filter,
1057 (flags & EFX_FILTER_FLAG_RX_RSS) ? 1 : 0,
1058 FRF_CZ_RMFT_SCATTER_EN,
1059 (flags & EFX_FILTER_FLAG_RX_SCATTER) ? 1 : 0,
1060 FRF_CZ_RMFT_RXQ_ID, spec->sfs_dmaq_id,
1061 FRF_CZ_RMFT_WILDCARD_MATCH, is_wild,
1062 FRF_CZ_RMFT_DEST_MAC_DW1, spec->sfs_dword[2],
1063 FRF_CZ_RMFT_DEST_MAC_DW0, spec->sfs_dword[1],
1064 FRF_CZ_RMFT_VLAN_ID, spec->sfs_dword[0]);
1069 case EFX_SIENA_FILTER_TBL_TX_IP: {
1070 boolean_t is_udp = (type == EFX_SIENA_FILTER_TX_UDP_FULL ||
1071 type == EFX_SIENA_FILTER_TX_UDP_WILD);
1072 EFX_POPULATE_OWORD_5(*filter,
1073 FRF_CZ_TIFT_TCP_UDP, is_udp,
1074 FRF_CZ_TIFT_TXQ_ID, spec->sfs_dmaq_id,
1075 EFX_DWORD_2, spec->sfs_dword[2],
1076 EFX_DWORD_1, spec->sfs_dword[1],
1077 EFX_DWORD_0, spec->sfs_dword[0]);
1078 dword3 = is_udp | spec->sfs_dmaq_id << 1;
1082 case EFX_SIENA_FILTER_TBL_TX_MAC: {
1083 boolean_t is_wild = (type == EFX_SIENA_FILTER_TX_MAC_WILD);
1084 EFX_POPULATE_OWORD_5(*filter,
1085 FRF_CZ_TMFT_TXQ_ID, spec->sfs_dmaq_id,
1086 FRF_CZ_TMFT_WILDCARD_MATCH, is_wild,
1087 FRF_CZ_TMFT_SRC_MAC_DW1, spec->sfs_dword[2],
1088 FRF_CZ_TMFT_SRC_MAC_DW0, spec->sfs_dword[1],
1089 FRF_CZ_TMFT_VLAN_ID, spec->sfs_dword[0]);
1090 dword3 = is_wild | spec->sfs_dmaq_id << 1;
1095 EFSYS_ASSERT(B_FALSE);
1096 EFX_ZERO_OWORD(*filter);
1101 spec->sfs_dword[0] ^
1102 spec->sfs_dword[1] ^
1103 spec->sfs_dword[2] ^
1109 static __checkReturn efx_rc_t
1110 siena_filter_push_entry(
1111 __inout efx_nic_t *enp,
1112 __in siena_filter_type_t type,
1114 __in efx_oword_t *eop)
1119 case EFX_SIENA_FILTER_RX_TCP_FULL:
1120 case EFX_SIENA_FILTER_RX_TCP_WILD:
1121 case EFX_SIENA_FILTER_RX_UDP_FULL:
1122 case EFX_SIENA_FILTER_RX_UDP_WILD:
1123 EFX_BAR_TBL_WRITEO(enp, FR_AZ_RX_FILTER_TBL0, index,
1127 case EFX_SIENA_FILTER_RX_MAC_FULL:
1128 case EFX_SIENA_FILTER_RX_MAC_WILD:
1129 EFX_BAR_TBL_WRITEO(enp, FR_CZ_RX_MAC_FILTER_TBL0, index,
1133 case EFX_SIENA_FILTER_TX_TCP_FULL:
1134 case EFX_SIENA_FILTER_TX_TCP_WILD:
1135 case EFX_SIENA_FILTER_TX_UDP_FULL:
1136 case EFX_SIENA_FILTER_TX_UDP_WILD:
1137 EFX_BAR_TBL_WRITEO(enp, FR_CZ_TX_FILTER_TBL0, index,
1141 case EFX_SIENA_FILTER_TX_MAC_FULL:
1142 case EFX_SIENA_FILTER_TX_MAC_WILD:
1143 EFX_BAR_TBL_WRITEO(enp, FR_CZ_TX_MAC_FILTER_TBL0, index,
1148 EFSYS_ASSERT(B_FALSE);
1159 static __checkReturn boolean_t
1161 __in const siena_filter_spec_t *left,
1162 __in const siena_filter_spec_t *right)
1164 siena_filter_tbl_id_t tbl_id;
1166 tbl_id = siena_filter_tbl_id(left->sfs_type);
1169 if (left->sfs_type != right->sfs_type)
1172 if (memcmp(left->sfs_dword, right->sfs_dword,
1173 sizeof (left->sfs_dword)))
1176 if ((tbl_id == EFX_SIENA_FILTER_TBL_TX_IP ||
1177 tbl_id == EFX_SIENA_FILTER_TBL_TX_MAC) &&
1178 left->sfs_dmaq_id != right->sfs_dmaq_id)
1184 static __checkReturn efx_rc_t
1185 siena_filter_search(
1186 __in siena_filter_tbl_t *sftp,
1187 __in siena_filter_spec_t *spec,
1189 __in boolean_t for_insert,
1190 __out int *filter_index,
1191 __out unsigned int *depth_required)
1193 unsigned int hash, incr, filter_idx, depth;
1195 hash = siena_filter_tbl_hash(key);
1196 incr = siena_filter_tbl_increment(key);
1198 filter_idx = hash & (sftp->sft_size - 1);
1203 * Return success if entry is used and matches this spec
1204 * or entry is unused and we are trying to insert.
1206 if (siena_filter_test_used(sftp, filter_idx) ?
1207 siena_filter_equal(spec,
1208 &sftp->sft_spec[filter_idx]) :
1210 *filter_index = filter_idx;
1211 *depth_required = depth;
1215 /* Return failure if we reached the maximum search depth */
1216 if (depth == FILTER_CTL_SRCH_MAX)
1217 return (for_insert ? EBUSY : ENOENT);
1219 filter_idx = (filter_idx + incr) & (sftp->sft_size - 1);
1225 siena_filter_clear_entry(
1226 __in efx_nic_t *enp,
1227 __in siena_filter_tbl_t *sftp,
1232 if (siena_filter_test_used(sftp, index)) {
1233 siena_filter_clear_used(sftp, index);
1235 EFX_ZERO_OWORD(filter);
1236 siena_filter_push_entry(enp,
1237 sftp->sft_spec[index].sfs_type,
1240 memset(&sftp->sft_spec[index],
1241 0, sizeof (sftp->sft_spec[0]));
1246 siena_filter_tbl_clear(
1247 __in efx_nic_t *enp,
1248 __in siena_filter_tbl_id_t tbl_id)
1250 siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
1251 siena_filter_tbl_t *sftp = &sfp->sf_tbl[tbl_id];
1253 efsys_lock_state_t state;
1255 EFSYS_LOCK(enp->en_eslp, state);
1257 for (index = 0; index < sftp->sft_size; ++index) {
1258 siena_filter_clear_entry(enp, sftp, index);
1261 if (sftp->sft_used == 0)
1262 siena_filter_reset_search_depth(sfp, tbl_id);
1264 EFSYS_UNLOCK(enp->en_eslp, state);
1267 static __checkReturn efx_rc_t
1269 __in efx_nic_t *enp)
1271 siena_filter_t *sfp;
1272 siena_filter_tbl_t *sftp;
1276 EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (siena_filter_t), sfp);
1283 enp->en_filter.ef_siena_filter = sfp;
1285 switch (enp->en_family) {
1286 case EFX_FAMILY_SIENA:
1287 sftp = &sfp->sf_tbl[EFX_SIENA_FILTER_TBL_RX_IP];
1288 sftp->sft_size = FR_AZ_RX_FILTER_TBL0_ROWS;
1290 sftp = &sfp->sf_tbl[EFX_SIENA_FILTER_TBL_RX_MAC];
1291 sftp->sft_size = FR_CZ_RX_MAC_FILTER_TBL0_ROWS;
1293 sftp = &sfp->sf_tbl[EFX_SIENA_FILTER_TBL_TX_IP];
1294 sftp->sft_size = FR_CZ_TX_FILTER_TBL0_ROWS;
1296 sftp = &sfp->sf_tbl[EFX_SIENA_FILTER_TBL_TX_MAC];
1297 sftp->sft_size = FR_CZ_TX_MAC_FILTER_TBL0_ROWS;
1305 for (tbl_id = 0; tbl_id < EFX_SIENA_FILTER_NTBLS; tbl_id++) {
1306 unsigned int bitmap_size;
1308 sftp = &sfp->sf_tbl[tbl_id];
1309 if (sftp->sft_size == 0)
1312 EFX_STATIC_ASSERT(sizeof (sftp->sft_bitmap[0]) ==
1315 (sftp->sft_size + (sizeof (uint32_t) * 8) - 1) / 8;
1317 EFSYS_KMEM_ALLOC(enp->en_esip, bitmap_size, sftp->sft_bitmap);
1318 if (!sftp->sft_bitmap) {
1323 EFSYS_KMEM_ALLOC(enp->en_esip,
1324 sftp->sft_size * sizeof (*sftp->sft_spec),
1326 if (!sftp->sft_spec) {
1330 memset(sftp->sft_spec, 0,
1331 sftp->sft_size * sizeof (*sftp->sft_spec));
1344 siena_filter_fini(enp);
1347 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1353 __in efx_nic_t *enp)
1355 siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
1356 siena_filter_tbl_id_t tbl_id;
1358 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1359 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1364 for (tbl_id = 0; tbl_id < EFX_SIENA_FILTER_NTBLS; tbl_id++) {
1365 siena_filter_tbl_t *sftp = &sfp->sf_tbl[tbl_id];
1366 unsigned int bitmap_size;
1368 EFX_STATIC_ASSERT(sizeof (sftp->sft_bitmap[0]) ==
1371 (sftp->sft_size + (sizeof (uint32_t) * 8) - 1) / 8;
1373 if (sftp->sft_bitmap != NULL) {
1374 EFSYS_KMEM_FREE(enp->en_esip, bitmap_size,
1376 sftp->sft_bitmap = NULL;
1379 if (sftp->sft_spec != NULL) {
1380 EFSYS_KMEM_FREE(enp->en_esip, sftp->sft_size *
1381 sizeof (*sftp->sft_spec), sftp->sft_spec);
1382 sftp->sft_spec = NULL;
1386 EFSYS_KMEM_FREE(enp->en_esip, sizeof (siena_filter_t),
1387 enp->en_filter.ef_siena_filter);
1390 /* Restore filter state after a reset */
1391 static __checkReturn efx_rc_t
1392 siena_filter_restore(
1393 __in efx_nic_t *enp)
1395 siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
1396 siena_filter_tbl_id_t tbl_id;
1397 siena_filter_tbl_t *sftp;
1398 siena_filter_spec_t *spec;
1401 efsys_lock_state_t state;
1405 EFSYS_LOCK(enp->en_eslp, state);
1407 for (tbl_id = 0; tbl_id < EFX_SIENA_FILTER_NTBLS; tbl_id++) {
1408 sftp = &sfp->sf_tbl[tbl_id];
1409 for (filter_idx = 0;
1410 filter_idx < sftp->sft_size;
1412 if (!siena_filter_test_used(sftp, filter_idx))
1415 spec = &sftp->sft_spec[filter_idx];
1416 if ((key = siena_filter_build(&filter, spec)) == 0) {
1420 if ((rc = siena_filter_push_entry(enp,
1421 spec->sfs_type, filter_idx, &filter)) != 0)
1426 siena_filter_push_rx_limits(enp);
1427 siena_filter_push_tx_limits(enp);
1429 EFSYS_UNLOCK(enp->en_eslp, state);
1437 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1439 EFSYS_UNLOCK(enp->en_eslp, state);
1444 static __checkReturn efx_rc_t
1446 __in efx_nic_t *enp,
1447 __inout efx_filter_spec_t *spec,
1448 __in efx_filter_replacement_policy_t policy)
1451 siena_filter_spec_t sf_spec;
1452 siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
1453 siena_filter_tbl_id_t tbl_id;
1454 siena_filter_tbl_t *sftp;
1455 siena_filter_spec_t *saved_sf_spec;
1459 efsys_lock_state_t state;
1463 EFSYS_ASSERT3P(spec, !=, NULL);
1465 if ((rc = siena_filter_spec_from_gen_spec(&sf_spec, spec)) != 0)
1468 tbl_id = siena_filter_tbl_id(sf_spec.sfs_type);
1469 sftp = &sfp->sf_tbl[tbl_id];
1471 if (sftp->sft_size == 0) {
1476 key = siena_filter_build(&filter, &sf_spec);
1478 EFSYS_LOCK(enp->en_eslp, state);
1480 rc = siena_filter_search(sftp, &sf_spec, key, B_TRUE,
1481 &filter_idx, &depth);
1485 EFSYS_ASSERT3U(filter_idx, <, sftp->sft_size);
1486 saved_sf_spec = &sftp->sft_spec[filter_idx];
1488 if (siena_filter_test_used(sftp, filter_idx)) {
1489 /* All Siena filter are considered the same priority */
1491 case EFX_FILTER_REPLACEMENT_NEVER:
1492 case EFX_FILTER_REPLACEMENT_HIGHER_PRIORITY:
1495 case EFX_FILTER_REPLACEMENT_HIGHER_OR_EQUAL_PRIORITY:
1502 siena_filter_set_used(sftp, filter_idx);
1503 *saved_sf_spec = sf_spec;
1505 if (sfp->sf_depth[sf_spec.sfs_type] < depth) {
1506 sfp->sf_depth[sf_spec.sfs_type] = depth;
1507 if (tbl_id == EFX_SIENA_FILTER_TBL_TX_IP ||
1508 tbl_id == EFX_SIENA_FILTER_TBL_TX_MAC)
1509 siena_filter_push_tx_limits(enp);
1511 siena_filter_push_rx_limits(enp);
1514 siena_filter_push_entry(enp, sf_spec.sfs_type,
1515 filter_idx, &filter);
1517 EFSYS_UNLOCK(enp->en_eslp, state);
1524 EFSYS_UNLOCK(enp->en_eslp, state);
1531 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1535 static __checkReturn efx_rc_t
1536 siena_filter_delete(
1537 __in efx_nic_t *enp,
1538 __inout efx_filter_spec_t *spec)
1541 siena_filter_spec_t sf_spec;
1542 siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
1543 siena_filter_tbl_id_t tbl_id;
1544 siena_filter_tbl_t *sftp;
1548 efsys_lock_state_t state;
1551 EFSYS_ASSERT3P(spec, !=, NULL);
1553 if ((rc = siena_filter_spec_from_gen_spec(&sf_spec, spec)) != 0)
1556 tbl_id = siena_filter_tbl_id(sf_spec.sfs_type);
1557 sftp = &sfp->sf_tbl[tbl_id];
1559 key = siena_filter_build(&filter, &sf_spec);
1561 EFSYS_LOCK(enp->en_eslp, state);
1563 rc = siena_filter_search(sftp, &sf_spec, key, B_FALSE,
1564 &filter_idx, &depth);
1568 siena_filter_clear_entry(enp, sftp, filter_idx);
1569 if (sftp->sft_used == 0)
1570 siena_filter_reset_search_depth(sfp, tbl_id);
1572 EFSYS_UNLOCK(enp->en_eslp, state);
1576 EFSYS_UNLOCK(enp->en_eslp, state);
1580 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1584 #define SIENA_MAX_SUPPORTED_MATCHES 4
1586 static __checkReturn efx_rc_t
1587 siena_filter_supported_filters(
1588 __in efx_nic_t *enp,
1589 __out_ecount(buffer_length) uint32_t *buffer,
1590 __in size_t buffer_length,
1591 __out size_t *list_lengthp)
1594 uint32_t rx_matches[SIENA_MAX_SUPPORTED_MATCHES];
1598 rx_matches[index++] =
1599 EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
1600 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT |
1601 EFX_FILTER_MATCH_REM_HOST | EFX_FILTER_MATCH_REM_PORT;
1603 rx_matches[index++] =
1604 EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
1605 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT;
1607 if (enp->en_features & EFX_FEATURE_MAC_HEADER_FILTERS) {
1608 rx_matches[index++] =
1609 EFX_FILTER_MATCH_OUTER_VID | EFX_FILTER_MATCH_LOC_MAC;
1611 rx_matches[index++] = EFX_FILTER_MATCH_LOC_MAC;
1614 EFSYS_ASSERT3U(index, <=, SIENA_MAX_SUPPORTED_MATCHES);
1615 list_length = index;
1617 *list_lengthp = list_length;
1619 if (buffer_length < list_length) {
1624 memcpy(buffer, rx_matches, list_length * sizeof (rx_matches[0]));
1629 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1634 #undef MAX_SUPPORTED
1636 #endif /* EFSYS_OPT_SIENA */
1638 #endif /* EFSYS_OPT_FILTER */