2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2007-2016 Solarflare Communications Inc.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
10 * 1. Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
18 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 * The views and conclusions contained in the software and documentation are
29 * those of the authors and should not be interpreted as representing official
30 * policies, either expressed or implied, of the FreeBSD Project.
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
44 static __checkReturn efx_rc_t
52 static __checkReturn efx_rc_t
56 static __checkReturn efx_rc_t
59 __inout efx_filter_spec_t *spec,
60 __in boolean_t may_replace);
62 static __checkReturn efx_rc_t
65 __inout efx_filter_spec_t *spec);
67 static __checkReturn efx_rc_t
68 siena_filter_supported_filters(
70 __out_ecount(buffer_length) uint32_t *buffer,
71 __in size_t buffer_length,
72 __out size_t *list_lengthp);
74 #endif /* EFSYS_OPT_SIENA */
77 static const efx_filter_ops_t __efx_filter_siena_ops = {
78 siena_filter_init, /* efo_init */
79 siena_filter_fini, /* efo_fini */
80 siena_filter_restore, /* efo_restore */
81 siena_filter_add, /* efo_add */
82 siena_filter_delete, /* efo_delete */
83 siena_filter_supported_filters, /* efo_supported_filters */
84 NULL, /* efo_reconfigure */
86 #endif /* EFSYS_OPT_SIENA */
88 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
89 static const efx_filter_ops_t __efx_filter_ef10_ops = {
90 ef10_filter_init, /* efo_init */
91 ef10_filter_fini, /* efo_fini */
92 ef10_filter_restore, /* efo_restore */
93 ef10_filter_add, /* efo_add */
94 ef10_filter_delete, /* efo_delete */
95 ef10_filter_supported_filters, /* efo_supported_filters */
96 ef10_filter_reconfigure, /* efo_reconfigure */
98 #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
100 __checkReturn efx_rc_t
103 __inout efx_filter_spec_t *spec)
105 const efx_filter_ops_t *efop = enp->en_efop;
106 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
109 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
110 EFSYS_ASSERT3P(spec, !=, NULL);
111 EFSYS_ASSERT3U(spec->efs_flags, &, EFX_FILTER_FLAG_RX);
113 if ((spec->efs_flags & EFX_FILTER_FLAG_ACTION_MARK) &&
114 !encp->enc_filter_action_mark_supported) {
119 if ((spec->efs_flags & EFX_FILTER_FLAG_ACTION_FLAG) &&
120 !encp->enc_filter_action_flag_supported) {
125 return (efop->efo_add(enp, spec, B_FALSE));
130 EFSYS_PROBE1(fail1, efx_rc_t, rc);
135 __checkReturn efx_rc_t
138 __inout efx_filter_spec_t *spec)
140 const efx_filter_ops_t *efop = enp->en_efop;
142 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
143 EFSYS_ASSERT3P(spec, !=, NULL);
144 EFSYS_ASSERT3U(spec->efs_flags, &, EFX_FILTER_FLAG_RX);
146 return (efop->efo_delete(enp, spec));
149 __checkReturn efx_rc_t
155 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
157 if ((rc = enp->en_efop->efo_restore(enp)) != 0)
163 EFSYS_PROBE1(fail1, efx_rc_t, rc);
168 __checkReturn efx_rc_t
172 const efx_filter_ops_t *efop;
175 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
176 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
177 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_FILTER));
179 switch (enp->en_family) {
181 case EFX_FAMILY_SIENA:
182 efop = &__efx_filter_siena_ops;
184 #endif /* EFSYS_OPT_SIENA */
186 #if EFSYS_OPT_HUNTINGTON
187 case EFX_FAMILY_HUNTINGTON:
188 efop = &__efx_filter_ef10_ops;
190 #endif /* EFSYS_OPT_HUNTINGTON */
192 #if EFSYS_OPT_MEDFORD
193 case EFX_FAMILY_MEDFORD:
194 efop = &__efx_filter_ef10_ops;
196 #endif /* EFSYS_OPT_MEDFORD */
198 #if EFSYS_OPT_MEDFORD2
199 case EFX_FAMILY_MEDFORD2:
200 efop = &__efx_filter_ef10_ops;
202 #endif /* EFSYS_OPT_MEDFORD2 */
210 if ((rc = efop->efo_init(enp)) != 0)
214 enp->en_mod_flags |= EFX_MOD_FILTER;
220 EFSYS_PROBE1(fail1, efx_rc_t, rc);
223 enp->en_mod_flags &= ~EFX_MOD_FILTER;
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);
235 enp->en_efop->efo_fini(enp);
238 enp->en_mod_flags &= ~EFX_MOD_FILTER;
242 * Query the possible combinations of match flags which can be filtered on.
243 * These are returned as a list, of which each 32 bit element is a bitmask
244 * formed of EFX_FILTER_MATCH flags.
246 * The combinations are ordered in priority from highest to lowest.
248 * If the provided buffer is too short to hold the list, the call with fail with
249 * ENOSPC and *list_lengthp will be set to the buffer length required.
251 __checkReturn efx_rc_t
252 efx_filter_supported_filters(
254 __out_ecount(buffer_length) uint32_t *buffer,
255 __in size_t buffer_length,
256 __out size_t *list_lengthp)
260 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
261 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
262 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
263 EFSYS_ASSERT(enp->en_efop->efo_supported_filters != NULL);
265 if (buffer == NULL) {
270 rc = enp->en_efop->efo_supported_filters(enp, buffer, buffer_length,
280 EFSYS_PROBE1(fail1, efx_rc_t, rc);
285 __checkReturn efx_rc_t
286 efx_filter_reconfigure(
288 __in_ecount(6) uint8_t const *mac_addr,
289 __in boolean_t all_unicst,
290 __in boolean_t mulcst,
291 __in boolean_t all_mulcst,
292 __in boolean_t brdcst,
293 __in_ecount(6*count) uint8_t const *addrs,
298 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
299 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
300 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
302 if (enp->en_efop->efo_reconfigure != NULL) {
303 if ((rc = enp->en_efop->efo_reconfigure(enp, mac_addr,
313 EFSYS_PROBE1(fail1, efx_rc_t, rc);
319 efx_filter_spec_init_rx(
320 __out efx_filter_spec_t *spec,
321 __in efx_filter_priority_t priority,
322 __in efx_filter_flags_t flags,
325 EFSYS_ASSERT3P(spec, !=, NULL);
326 EFSYS_ASSERT3P(erp, !=, NULL);
327 EFSYS_ASSERT((flags & ~(EFX_FILTER_FLAG_RX_RSS |
328 EFX_FILTER_FLAG_RX_SCATTER)) == 0);
330 memset(spec, 0, sizeof (*spec));
331 spec->efs_priority = priority;
332 spec->efs_flags = EFX_FILTER_FLAG_RX | flags;
333 spec->efs_rss_context = EFX_RSS_CONTEXT_DEFAULT;
334 spec->efs_dmaq_id = (uint16_t)erp->er_index;
338 efx_filter_spec_init_tx(
339 __out efx_filter_spec_t *spec,
342 EFSYS_ASSERT3P(spec, !=, NULL);
343 EFSYS_ASSERT3P(etp, !=, NULL);
345 memset(spec, 0, sizeof (*spec));
346 spec->efs_priority = EFX_FILTER_PRI_REQUIRED;
347 spec->efs_flags = EFX_FILTER_FLAG_TX;
348 spec->efs_dmaq_id = (uint16_t)etp->et_index;
353 * Specify IPv4 host, transport protocol and port in a filter specification
355 __checkReturn efx_rc_t
356 efx_filter_spec_set_ipv4_local(
357 __inout efx_filter_spec_t *spec,
362 EFSYS_ASSERT3P(spec, !=, NULL);
364 spec->efs_match_flags |=
365 EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
366 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT;
367 spec->efs_ether_type = EFX_ETHER_TYPE_IPV4;
368 spec->efs_ip_proto = proto;
369 spec->efs_loc_host.eo_u32[0] = host;
370 spec->efs_loc_port = port;
375 * Specify IPv4 hosts, transport protocol and ports in a filter specification
377 __checkReturn efx_rc_t
378 efx_filter_spec_set_ipv4_full(
379 __inout efx_filter_spec_t *spec,
386 EFSYS_ASSERT3P(spec, !=, NULL);
388 spec->efs_match_flags |=
389 EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
390 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT |
391 EFX_FILTER_MATCH_REM_HOST | EFX_FILTER_MATCH_REM_PORT;
392 spec->efs_ether_type = EFX_ETHER_TYPE_IPV4;
393 spec->efs_ip_proto = proto;
394 spec->efs_loc_host.eo_u32[0] = lhost;
395 spec->efs_loc_port = lport;
396 spec->efs_rem_host.eo_u32[0] = rhost;
397 spec->efs_rem_port = rport;
402 * Specify local Ethernet address and/or VID in filter specification
404 __checkReturn efx_rc_t
405 efx_filter_spec_set_eth_local(
406 __inout efx_filter_spec_t *spec,
408 __in const uint8_t *addr)
410 EFSYS_ASSERT3P(spec, !=, NULL);
411 EFSYS_ASSERT3P(addr, !=, NULL);
413 if (vid == EFX_FILTER_SPEC_VID_UNSPEC && addr == NULL)
416 if (vid != EFX_FILTER_SPEC_VID_UNSPEC) {
417 spec->efs_match_flags |= EFX_FILTER_MATCH_OUTER_VID;
418 spec->efs_outer_vid = vid;
421 spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_MAC;
422 memcpy(spec->efs_loc_mac, addr, EFX_MAC_ADDR_LEN);
428 efx_filter_spec_set_ether_type(
429 __inout efx_filter_spec_t *spec,
430 __in uint16_t ether_type)
432 EFSYS_ASSERT3P(spec, !=, NULL);
434 spec->efs_ether_type = ether_type;
435 spec->efs_match_flags |= EFX_FILTER_MATCH_ETHER_TYPE;
439 * Specify matching otherwise-unmatched unicast in a filter specification
441 __checkReturn efx_rc_t
442 efx_filter_spec_set_uc_def(
443 __inout efx_filter_spec_t *spec)
445 EFSYS_ASSERT3P(spec, !=, NULL);
447 spec->efs_match_flags |= EFX_FILTER_MATCH_UNKNOWN_UCAST_DST;
452 * Specify matching otherwise-unmatched multicast in a filter specification
454 __checkReturn efx_rc_t
455 efx_filter_spec_set_mc_def(
456 __inout efx_filter_spec_t *spec)
458 EFSYS_ASSERT3P(spec, !=, NULL);
460 spec->efs_match_flags |= EFX_FILTER_MATCH_UNKNOWN_MCAST_DST;
465 __checkReturn efx_rc_t
466 efx_filter_spec_set_encap_type(
467 __inout efx_filter_spec_t *spec,
468 __in efx_tunnel_protocol_t encap_type,
469 __in efx_filter_inner_frame_match_t inner_frame_match)
471 uint32_t match_flags = EFX_FILTER_MATCH_ENCAP_TYPE;
475 EFSYS_ASSERT3P(spec, !=, NULL);
477 switch (encap_type) {
478 case EFX_TUNNEL_PROTOCOL_VXLAN:
479 case EFX_TUNNEL_PROTOCOL_GENEVE:
480 ip_proto = EFX_IPPROTO_UDP;
482 case EFX_TUNNEL_PROTOCOL_NVGRE:
483 ip_proto = EFX_IPPROTO_GRE;
491 switch (inner_frame_match) {
492 case EFX_FILTER_INNER_FRAME_MATCH_UNKNOWN_MCAST_DST:
493 match_flags |= EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST;
495 case EFX_FILTER_INNER_FRAME_MATCH_UNKNOWN_UCAST_DST:
496 match_flags |= EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST;
498 case EFX_FILTER_INNER_FRAME_MATCH_OTHER:
499 /* This is for when specific inner frames are to be matched. */
507 spec->efs_encap_type = encap_type;
508 spec->efs_ip_proto = ip_proto;
509 spec->efs_match_flags |= (match_flags | EFX_FILTER_MATCH_IP_PROTO);
516 EFSYS_PROBE1(fail1, efx_rc_t, rc);
522 * Specify inner and outer Ethernet address and VXLAN ID in filter
525 __checkReturn efx_rc_t
526 efx_filter_spec_set_vxlan_full(
527 __inout efx_filter_spec_t *spec,
528 __in const uint8_t *vxlan_id,
529 __in const uint8_t *inner_addr,
530 __in const uint8_t *outer_addr)
532 EFSYS_ASSERT3P(spec, !=, NULL);
533 EFSYS_ASSERT3P(vxlan_id, !=, NULL);
534 EFSYS_ASSERT3P(inner_addr, !=, NULL);
535 EFSYS_ASSERT3P(outer_addr, !=, NULL);
537 if ((inner_addr == NULL) && (outer_addr == NULL))
540 if (vxlan_id != NULL) {
541 spec->efs_match_flags |= EFX_FILTER_MATCH_VNI_OR_VSID;
542 memcpy(spec->efs_vni_or_vsid, vxlan_id, EFX_VNI_OR_VSID_LEN);
544 if (outer_addr != NULL) {
545 spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_MAC;
546 memcpy(spec->efs_loc_mac, outer_addr, EFX_MAC_ADDR_LEN);
548 if (inner_addr != NULL) {
549 spec->efs_match_flags |= EFX_FILTER_MATCH_IFRM_LOC_MAC;
550 memcpy(spec->efs_ifrm_loc_mac, inner_addr, EFX_MAC_ADDR_LEN);
552 spec->efs_match_flags |= EFX_FILTER_MATCH_ENCAP_TYPE;
553 spec->efs_encap_type = EFX_TUNNEL_PROTOCOL_VXLAN;
558 #if EFSYS_OPT_RX_SCALE
559 __checkReturn efx_rc_t
560 efx_filter_spec_set_rss_context(
561 __inout efx_filter_spec_t *spec,
562 __in uint32_t rss_context)
566 EFSYS_ASSERT3P(spec, !=, NULL);
568 /* The filter must have been created with EFX_FILTER_FLAG_RX_RSS. */
569 if ((spec->efs_flags & EFX_FILTER_FLAG_RX_RSS) == 0) {
574 spec->efs_rss_context = rss_context;
579 EFSYS_PROBE1(fail1, efx_rc_t, rc);
588 * "Fudge factors" - difference between programmed value and actual depth.
589 * Due to pipelined implementation we need to program H/W with a value that
590 * is larger than the hop limit we want.
592 #define FILTER_CTL_SRCH_FUDGE_WILD 3
593 #define FILTER_CTL_SRCH_FUDGE_FULL 1
596 * Hard maximum hop limit. Hardware will time-out beyond 200-something.
597 * We also need to avoid infinite loops in efx_filter_search() when the
600 #define FILTER_CTL_SRCH_MAX 200
602 static __checkReturn efx_rc_t
603 siena_filter_spec_from_gen_spec(
604 __out siena_filter_spec_t *sf_spec,
605 __in efx_filter_spec_t *gen_spec)
608 boolean_t is_full = B_FALSE;
610 if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX)
611 EFSYS_ASSERT3U(gen_spec->efs_flags, ==, EFX_FILTER_FLAG_TX);
613 EFSYS_ASSERT3U(gen_spec->efs_flags, &, EFX_FILTER_FLAG_RX);
615 /* Siena only has one RSS context */
616 if ((gen_spec->efs_flags & EFX_FILTER_FLAG_RX_RSS) &&
617 gen_spec->efs_rss_context != EFX_RSS_CONTEXT_DEFAULT) {
622 sf_spec->sfs_flags = gen_spec->efs_flags;
623 sf_spec->sfs_dmaq_id = gen_spec->efs_dmaq_id;
625 switch (gen_spec->efs_match_flags) {
626 case EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
627 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT |
628 EFX_FILTER_MATCH_REM_HOST | EFX_FILTER_MATCH_REM_PORT:
631 case EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
632 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT: {
633 uint32_t rhost, host1, host2;
634 uint16_t rport, port1, port2;
636 if (gen_spec->efs_ether_type != EFX_ETHER_TYPE_IPV4) {
640 if (gen_spec->efs_loc_port == 0 ||
641 (is_full && gen_spec->efs_rem_port == 0)) {
645 switch (gen_spec->efs_ip_proto) {
646 case EFX_IPPROTO_TCP:
647 if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX) {
648 sf_spec->sfs_type = (is_full ?
649 EFX_SIENA_FILTER_TX_TCP_FULL :
650 EFX_SIENA_FILTER_TX_TCP_WILD);
652 sf_spec->sfs_type = (is_full ?
653 EFX_SIENA_FILTER_RX_TCP_FULL :
654 EFX_SIENA_FILTER_RX_TCP_WILD);
657 case EFX_IPPROTO_UDP:
658 if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX) {
659 sf_spec->sfs_type = (is_full ?
660 EFX_SIENA_FILTER_TX_UDP_FULL :
661 EFX_SIENA_FILTER_TX_UDP_WILD);
663 sf_spec->sfs_type = (is_full ?
664 EFX_SIENA_FILTER_RX_UDP_FULL :
665 EFX_SIENA_FILTER_RX_UDP_WILD);
673 * The filter is constructed in terms of source and destination,
674 * with the odd wrinkle that the ports are swapped in a UDP
675 * wildcard filter. We need to convert from local and remote
676 * addresses (zero for a wildcard).
678 rhost = is_full ? gen_spec->efs_rem_host.eo_u32[0] : 0;
679 rport = is_full ? gen_spec->efs_rem_port : 0;
680 if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX) {
681 host1 = gen_spec->efs_loc_host.eo_u32[0];
685 host2 = gen_spec->efs_loc_host.eo_u32[0];
687 if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX) {
688 if (sf_spec->sfs_type ==
689 EFX_SIENA_FILTER_TX_UDP_WILD) {
691 port2 = gen_spec->efs_loc_port;
693 port1 = gen_spec->efs_loc_port;
697 if (sf_spec->sfs_type ==
698 EFX_SIENA_FILTER_RX_UDP_WILD) {
699 port1 = gen_spec->efs_loc_port;
703 port2 = gen_spec->efs_loc_port;
706 sf_spec->sfs_dword[0] = (host1 << 16) | port1;
707 sf_spec->sfs_dword[1] = (port2 << 16) | (host1 >> 16);
708 sf_spec->sfs_dword[2] = host2;
712 case EFX_FILTER_MATCH_LOC_MAC | EFX_FILTER_MATCH_OUTER_VID:
715 case EFX_FILTER_MATCH_LOC_MAC:
716 if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX) {
717 sf_spec->sfs_type = (is_full ?
718 EFX_SIENA_FILTER_TX_MAC_FULL :
719 EFX_SIENA_FILTER_TX_MAC_WILD);
721 sf_spec->sfs_type = (is_full ?
722 EFX_SIENA_FILTER_RX_MAC_FULL :
723 EFX_SIENA_FILTER_RX_MAC_WILD);
725 sf_spec->sfs_dword[0] = is_full ? gen_spec->efs_outer_vid : 0;
726 sf_spec->sfs_dword[1] =
727 gen_spec->efs_loc_mac[2] << 24 |
728 gen_spec->efs_loc_mac[3] << 16 |
729 gen_spec->efs_loc_mac[4] << 8 |
730 gen_spec->efs_loc_mac[5];
731 sf_spec->sfs_dword[2] =
732 gen_spec->efs_loc_mac[0] << 8 |
733 gen_spec->efs_loc_mac[1];
737 EFSYS_ASSERT(B_FALSE);
753 EFSYS_PROBE1(fail1, efx_rc_t, rc);
759 * The filter hash function is LFSR polynomial x^16 + x^3 + 1 of a 32-bit
760 * key derived from the n-tuple.
763 siena_filter_tbl_hash(
768 /* First 16 rounds */
769 tmp = 0x1fff ^ (uint16_t)(key >> 16);
770 tmp = tmp ^ tmp >> 3 ^ tmp >> 6;
771 tmp = tmp ^ tmp >> 9;
774 tmp = tmp ^ tmp << 13 ^ (uint16_t)(key & 0xffff);
775 tmp = tmp ^ tmp >> 3 ^ tmp >> 6;
776 tmp = tmp ^ tmp >> 9;
782 * To allow for hash collisions, filter search continues at these
783 * increments from the first possible entry selected by the hash.
786 siena_filter_tbl_increment(
789 return ((uint16_t)(key * 2 - 1));
792 static __checkReturn boolean_t
793 siena_filter_test_used(
794 __in siena_filter_tbl_t *sftp,
795 __in unsigned int index)
797 EFSYS_ASSERT3P(sftp->sft_bitmap, !=, NULL);
798 return ((sftp->sft_bitmap[index / 32] & (1 << (index % 32))) != 0);
802 siena_filter_set_used(
803 __in siena_filter_tbl_t *sftp,
804 __in unsigned int index)
806 EFSYS_ASSERT3P(sftp->sft_bitmap, !=, NULL);
807 sftp->sft_bitmap[index / 32] |= (1 << (index % 32));
812 siena_filter_clear_used(
813 __in siena_filter_tbl_t *sftp,
814 __in unsigned int index)
816 EFSYS_ASSERT3P(sftp->sft_bitmap, !=, NULL);
817 sftp->sft_bitmap[index / 32] &= ~(1 << (index % 32));
820 EFSYS_ASSERT3U(sftp->sft_used, >=, 0);
824 static siena_filter_tbl_id_t
826 __in siena_filter_type_t type)
828 siena_filter_tbl_id_t tbl_id;
831 case EFX_SIENA_FILTER_RX_TCP_FULL:
832 case EFX_SIENA_FILTER_RX_TCP_WILD:
833 case EFX_SIENA_FILTER_RX_UDP_FULL:
834 case EFX_SIENA_FILTER_RX_UDP_WILD:
835 tbl_id = EFX_SIENA_FILTER_TBL_RX_IP;
838 case EFX_SIENA_FILTER_RX_MAC_FULL:
839 case EFX_SIENA_FILTER_RX_MAC_WILD:
840 tbl_id = EFX_SIENA_FILTER_TBL_RX_MAC;
843 case EFX_SIENA_FILTER_TX_TCP_FULL:
844 case EFX_SIENA_FILTER_TX_TCP_WILD:
845 case EFX_SIENA_FILTER_TX_UDP_FULL:
846 case EFX_SIENA_FILTER_TX_UDP_WILD:
847 tbl_id = EFX_SIENA_FILTER_TBL_TX_IP;
850 case EFX_SIENA_FILTER_TX_MAC_FULL:
851 case EFX_SIENA_FILTER_TX_MAC_WILD:
852 tbl_id = EFX_SIENA_FILTER_TBL_TX_MAC;
856 EFSYS_ASSERT(B_FALSE);
857 tbl_id = EFX_SIENA_FILTER_NTBLS;
864 siena_filter_reset_search_depth(
865 __inout siena_filter_t *sfp,
866 __in siena_filter_tbl_id_t tbl_id)
869 case EFX_SIENA_FILTER_TBL_RX_IP:
870 sfp->sf_depth[EFX_SIENA_FILTER_RX_TCP_FULL] = 0;
871 sfp->sf_depth[EFX_SIENA_FILTER_RX_TCP_WILD] = 0;
872 sfp->sf_depth[EFX_SIENA_FILTER_RX_UDP_FULL] = 0;
873 sfp->sf_depth[EFX_SIENA_FILTER_RX_UDP_WILD] = 0;
876 case EFX_SIENA_FILTER_TBL_RX_MAC:
877 sfp->sf_depth[EFX_SIENA_FILTER_RX_MAC_FULL] = 0;
878 sfp->sf_depth[EFX_SIENA_FILTER_RX_MAC_WILD] = 0;
881 case EFX_SIENA_FILTER_TBL_TX_IP:
882 sfp->sf_depth[EFX_SIENA_FILTER_TX_TCP_FULL] = 0;
883 sfp->sf_depth[EFX_SIENA_FILTER_TX_TCP_WILD] = 0;
884 sfp->sf_depth[EFX_SIENA_FILTER_TX_UDP_FULL] = 0;
885 sfp->sf_depth[EFX_SIENA_FILTER_TX_UDP_WILD] = 0;
888 case EFX_SIENA_FILTER_TBL_TX_MAC:
889 sfp->sf_depth[EFX_SIENA_FILTER_TX_MAC_FULL] = 0;
890 sfp->sf_depth[EFX_SIENA_FILTER_TX_MAC_WILD] = 0;
894 EFSYS_ASSERT(B_FALSE);
900 siena_filter_push_rx_limits(
903 siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
906 EFX_BAR_READO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
908 EFX_SET_OWORD_FIELD(oword, FRF_AZ_TCP_FULL_SRCH_LIMIT,
909 sfp->sf_depth[EFX_SIENA_FILTER_RX_TCP_FULL] +
910 FILTER_CTL_SRCH_FUDGE_FULL);
911 EFX_SET_OWORD_FIELD(oword, FRF_AZ_TCP_WILD_SRCH_LIMIT,
912 sfp->sf_depth[EFX_SIENA_FILTER_RX_TCP_WILD] +
913 FILTER_CTL_SRCH_FUDGE_WILD);
914 EFX_SET_OWORD_FIELD(oword, FRF_AZ_UDP_FULL_SRCH_LIMIT,
915 sfp->sf_depth[EFX_SIENA_FILTER_RX_UDP_FULL] +
916 FILTER_CTL_SRCH_FUDGE_FULL);
917 EFX_SET_OWORD_FIELD(oword, FRF_AZ_UDP_WILD_SRCH_LIMIT,
918 sfp->sf_depth[EFX_SIENA_FILTER_RX_UDP_WILD] +
919 FILTER_CTL_SRCH_FUDGE_WILD);
921 if (sfp->sf_tbl[EFX_SIENA_FILTER_TBL_RX_MAC].sft_size) {
922 EFX_SET_OWORD_FIELD(oword,
923 FRF_CZ_ETHERNET_FULL_SEARCH_LIMIT,
924 sfp->sf_depth[EFX_SIENA_FILTER_RX_MAC_FULL] +
925 FILTER_CTL_SRCH_FUDGE_FULL);
926 EFX_SET_OWORD_FIELD(oword,
927 FRF_CZ_ETHERNET_WILDCARD_SEARCH_LIMIT,
928 sfp->sf_depth[EFX_SIENA_FILTER_RX_MAC_WILD] +
929 FILTER_CTL_SRCH_FUDGE_WILD);
932 EFX_BAR_WRITEO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
936 siena_filter_push_tx_limits(
939 siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
942 EFX_BAR_READO(enp, FR_AZ_TX_CFG_REG, &oword);
944 if (sfp->sf_tbl[EFX_SIENA_FILTER_TBL_TX_IP].sft_size != 0) {
945 EFX_SET_OWORD_FIELD(oword,
946 FRF_CZ_TX_TCPIP_FILTER_FULL_SEARCH_RANGE,
947 sfp->sf_depth[EFX_SIENA_FILTER_TX_TCP_FULL] +
948 FILTER_CTL_SRCH_FUDGE_FULL);
949 EFX_SET_OWORD_FIELD(oword,
950 FRF_CZ_TX_TCPIP_FILTER_WILD_SEARCH_RANGE,
951 sfp->sf_depth[EFX_SIENA_FILTER_TX_TCP_WILD] +
952 FILTER_CTL_SRCH_FUDGE_WILD);
953 EFX_SET_OWORD_FIELD(oword,
954 FRF_CZ_TX_UDPIP_FILTER_FULL_SEARCH_RANGE,
955 sfp->sf_depth[EFX_SIENA_FILTER_TX_UDP_FULL] +
956 FILTER_CTL_SRCH_FUDGE_FULL);
957 EFX_SET_OWORD_FIELD(oword,
958 FRF_CZ_TX_UDPIP_FILTER_WILD_SEARCH_RANGE,
959 sfp->sf_depth[EFX_SIENA_FILTER_TX_UDP_WILD] +
960 FILTER_CTL_SRCH_FUDGE_WILD);
963 if (sfp->sf_tbl[EFX_SIENA_FILTER_TBL_TX_MAC].sft_size != 0) {
965 oword, FRF_CZ_TX_ETH_FILTER_FULL_SEARCH_RANGE,
966 sfp->sf_depth[EFX_SIENA_FILTER_TX_MAC_FULL] +
967 FILTER_CTL_SRCH_FUDGE_FULL);
969 oword, FRF_CZ_TX_ETH_FILTER_WILD_SEARCH_RANGE,
970 sfp->sf_depth[EFX_SIENA_FILTER_TX_MAC_WILD] +
971 FILTER_CTL_SRCH_FUDGE_WILD);
974 EFX_BAR_WRITEO(enp, FR_AZ_TX_CFG_REG, &oword);
977 /* Build a filter entry and return its n-tuple key. */
978 static __checkReturn uint32_t
980 __out efx_oword_t *filter,
981 __in siena_filter_spec_t *spec)
985 uint8_t type = spec->sfs_type;
986 uint32_t flags = spec->sfs_flags;
988 switch (siena_filter_tbl_id(type)) {
989 case EFX_SIENA_FILTER_TBL_RX_IP: {
990 boolean_t is_udp = (type == EFX_SIENA_FILTER_RX_UDP_FULL ||
991 type == EFX_SIENA_FILTER_RX_UDP_WILD);
992 EFX_POPULATE_OWORD_7(*filter,
994 (flags & EFX_FILTER_FLAG_RX_RSS) ? 1 : 0,
996 (flags & EFX_FILTER_FLAG_RX_SCATTER) ? 1 : 0,
997 FRF_AZ_TCP_UDP, is_udp,
998 FRF_AZ_RXQ_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]);
1006 case EFX_SIENA_FILTER_TBL_RX_MAC: {
1007 boolean_t is_wild = (type == EFX_SIENA_FILTER_RX_MAC_WILD);
1008 EFX_POPULATE_OWORD_7(*filter,
1010 (flags & EFX_FILTER_FLAG_RX_RSS) ? 1 : 0,
1011 FRF_CZ_RMFT_SCATTER_EN,
1012 (flags & EFX_FILTER_FLAG_RX_SCATTER) ? 1 : 0,
1013 FRF_CZ_RMFT_RXQ_ID, spec->sfs_dmaq_id,
1014 FRF_CZ_RMFT_WILDCARD_MATCH, is_wild,
1015 FRF_CZ_RMFT_DEST_MAC_DW1, spec->sfs_dword[2],
1016 FRF_CZ_RMFT_DEST_MAC_DW0, spec->sfs_dword[1],
1017 FRF_CZ_RMFT_VLAN_ID, spec->sfs_dword[0]);
1022 case EFX_SIENA_FILTER_TBL_TX_IP: {
1023 boolean_t is_udp = (type == EFX_SIENA_FILTER_TX_UDP_FULL ||
1024 type == EFX_SIENA_FILTER_TX_UDP_WILD);
1025 EFX_POPULATE_OWORD_5(*filter,
1026 FRF_CZ_TIFT_TCP_UDP, is_udp,
1027 FRF_CZ_TIFT_TXQ_ID, spec->sfs_dmaq_id,
1028 EFX_DWORD_2, spec->sfs_dword[2],
1029 EFX_DWORD_1, spec->sfs_dword[1],
1030 EFX_DWORD_0, spec->sfs_dword[0]);
1031 dword3 = is_udp | spec->sfs_dmaq_id << 1;
1035 case EFX_SIENA_FILTER_TBL_TX_MAC: {
1036 boolean_t is_wild = (type == EFX_SIENA_FILTER_TX_MAC_WILD);
1037 EFX_POPULATE_OWORD_5(*filter,
1038 FRF_CZ_TMFT_TXQ_ID, spec->sfs_dmaq_id,
1039 FRF_CZ_TMFT_WILDCARD_MATCH, is_wild,
1040 FRF_CZ_TMFT_SRC_MAC_DW1, spec->sfs_dword[2],
1041 FRF_CZ_TMFT_SRC_MAC_DW0, spec->sfs_dword[1],
1042 FRF_CZ_TMFT_VLAN_ID, spec->sfs_dword[0]);
1043 dword3 = is_wild | spec->sfs_dmaq_id << 1;
1048 EFSYS_ASSERT(B_FALSE);
1049 EFX_ZERO_OWORD(*filter);
1054 spec->sfs_dword[0] ^
1055 spec->sfs_dword[1] ^
1056 spec->sfs_dword[2] ^
1062 static __checkReturn efx_rc_t
1063 siena_filter_push_entry(
1064 __inout efx_nic_t *enp,
1065 __in siena_filter_type_t type,
1067 __in efx_oword_t *eop)
1072 case EFX_SIENA_FILTER_RX_TCP_FULL:
1073 case EFX_SIENA_FILTER_RX_TCP_WILD:
1074 case EFX_SIENA_FILTER_RX_UDP_FULL:
1075 case EFX_SIENA_FILTER_RX_UDP_WILD:
1076 EFX_BAR_TBL_WRITEO(enp, FR_AZ_RX_FILTER_TBL0, index,
1080 case EFX_SIENA_FILTER_RX_MAC_FULL:
1081 case EFX_SIENA_FILTER_RX_MAC_WILD:
1082 EFX_BAR_TBL_WRITEO(enp, FR_CZ_RX_MAC_FILTER_TBL0, index,
1086 case EFX_SIENA_FILTER_TX_TCP_FULL:
1087 case EFX_SIENA_FILTER_TX_TCP_WILD:
1088 case EFX_SIENA_FILTER_TX_UDP_FULL:
1089 case EFX_SIENA_FILTER_TX_UDP_WILD:
1090 EFX_BAR_TBL_WRITEO(enp, FR_CZ_TX_FILTER_TBL0, index,
1094 case EFX_SIENA_FILTER_TX_MAC_FULL:
1095 case EFX_SIENA_FILTER_TX_MAC_WILD:
1096 EFX_BAR_TBL_WRITEO(enp, FR_CZ_TX_MAC_FILTER_TBL0, index,
1101 EFSYS_ASSERT(B_FALSE);
1112 static __checkReturn boolean_t
1114 __in const siena_filter_spec_t *left,
1115 __in const siena_filter_spec_t *right)
1117 siena_filter_tbl_id_t tbl_id;
1119 tbl_id = siena_filter_tbl_id(left->sfs_type);
1122 if (left->sfs_type != right->sfs_type)
1125 if (memcmp(left->sfs_dword, right->sfs_dword,
1126 sizeof (left->sfs_dword)))
1129 if ((tbl_id == EFX_SIENA_FILTER_TBL_TX_IP ||
1130 tbl_id == EFX_SIENA_FILTER_TBL_TX_MAC) &&
1131 left->sfs_dmaq_id != right->sfs_dmaq_id)
1137 static __checkReturn efx_rc_t
1138 siena_filter_search(
1139 __in siena_filter_tbl_t *sftp,
1140 __in siena_filter_spec_t *spec,
1142 __in boolean_t for_insert,
1143 __out int *filter_index,
1144 __out unsigned int *depth_required)
1146 unsigned int hash, incr, filter_idx, depth;
1148 hash = siena_filter_tbl_hash(key);
1149 incr = siena_filter_tbl_increment(key);
1151 filter_idx = hash & (sftp->sft_size - 1);
1156 * Return success if entry is used and matches this spec
1157 * or entry is unused and we are trying to insert.
1159 if (siena_filter_test_used(sftp, filter_idx) ?
1160 siena_filter_equal(spec,
1161 &sftp->sft_spec[filter_idx]) :
1163 *filter_index = filter_idx;
1164 *depth_required = depth;
1168 /* Return failure if we reached the maximum search depth */
1169 if (depth == FILTER_CTL_SRCH_MAX)
1170 return (for_insert ? EBUSY : ENOENT);
1172 filter_idx = (filter_idx + incr) & (sftp->sft_size - 1);
1178 siena_filter_clear_entry(
1179 __in efx_nic_t *enp,
1180 __in siena_filter_tbl_t *sftp,
1185 if (siena_filter_test_used(sftp, index)) {
1186 siena_filter_clear_used(sftp, index);
1188 EFX_ZERO_OWORD(filter);
1189 siena_filter_push_entry(enp,
1190 sftp->sft_spec[index].sfs_type,
1193 memset(&sftp->sft_spec[index],
1194 0, sizeof (sftp->sft_spec[0]));
1199 siena_filter_tbl_clear(
1200 __in efx_nic_t *enp,
1201 __in siena_filter_tbl_id_t tbl_id)
1203 siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
1204 siena_filter_tbl_t *sftp = &sfp->sf_tbl[tbl_id];
1206 efsys_lock_state_t state;
1208 EFSYS_LOCK(enp->en_eslp, state);
1210 for (index = 0; index < sftp->sft_size; ++index) {
1211 siena_filter_clear_entry(enp, sftp, index);
1214 if (sftp->sft_used == 0)
1215 siena_filter_reset_search_depth(sfp, tbl_id);
1217 EFSYS_UNLOCK(enp->en_eslp, state);
1220 static __checkReturn efx_rc_t
1222 __in efx_nic_t *enp)
1224 siena_filter_t *sfp;
1225 siena_filter_tbl_t *sftp;
1229 EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (siena_filter_t), sfp);
1236 enp->en_filter.ef_siena_filter = sfp;
1238 switch (enp->en_family) {
1239 case EFX_FAMILY_SIENA:
1240 sftp = &sfp->sf_tbl[EFX_SIENA_FILTER_TBL_RX_IP];
1241 sftp->sft_size = FR_AZ_RX_FILTER_TBL0_ROWS;
1243 sftp = &sfp->sf_tbl[EFX_SIENA_FILTER_TBL_RX_MAC];
1244 sftp->sft_size = FR_CZ_RX_MAC_FILTER_TBL0_ROWS;
1246 sftp = &sfp->sf_tbl[EFX_SIENA_FILTER_TBL_TX_IP];
1247 sftp->sft_size = FR_CZ_TX_FILTER_TBL0_ROWS;
1249 sftp = &sfp->sf_tbl[EFX_SIENA_FILTER_TBL_TX_MAC];
1250 sftp->sft_size = FR_CZ_TX_MAC_FILTER_TBL0_ROWS;
1258 for (tbl_id = 0; tbl_id < EFX_SIENA_FILTER_NTBLS; tbl_id++) {
1259 unsigned int bitmap_size;
1261 sftp = &sfp->sf_tbl[tbl_id];
1262 if (sftp->sft_size == 0)
1265 EFX_STATIC_ASSERT(sizeof (sftp->sft_bitmap[0]) ==
1268 (sftp->sft_size + (sizeof (uint32_t) * 8) - 1) / 8;
1270 EFSYS_KMEM_ALLOC(enp->en_esip, bitmap_size, sftp->sft_bitmap);
1271 if (!sftp->sft_bitmap) {
1276 EFSYS_KMEM_ALLOC(enp->en_esip,
1277 sftp->sft_size * sizeof (*sftp->sft_spec),
1279 if (!sftp->sft_spec) {
1283 memset(sftp->sft_spec, 0,
1284 sftp->sft_size * sizeof (*sftp->sft_spec));
1297 siena_filter_fini(enp);
1300 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1306 __in efx_nic_t *enp)
1308 siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
1309 siena_filter_tbl_id_t tbl_id;
1311 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1312 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1317 for (tbl_id = 0; tbl_id < EFX_SIENA_FILTER_NTBLS; tbl_id++) {
1318 siena_filter_tbl_t *sftp = &sfp->sf_tbl[tbl_id];
1319 unsigned int bitmap_size;
1321 EFX_STATIC_ASSERT(sizeof (sftp->sft_bitmap[0]) ==
1324 (sftp->sft_size + (sizeof (uint32_t) * 8) - 1) / 8;
1326 if (sftp->sft_bitmap != NULL) {
1327 EFSYS_KMEM_FREE(enp->en_esip, bitmap_size,
1329 sftp->sft_bitmap = NULL;
1332 if (sftp->sft_spec != NULL) {
1333 EFSYS_KMEM_FREE(enp->en_esip, sftp->sft_size *
1334 sizeof (*sftp->sft_spec), sftp->sft_spec);
1335 sftp->sft_spec = NULL;
1339 EFSYS_KMEM_FREE(enp->en_esip, sizeof (siena_filter_t),
1340 enp->en_filter.ef_siena_filter);
1343 /* Restore filter state after a reset */
1344 static __checkReturn efx_rc_t
1345 siena_filter_restore(
1346 __in efx_nic_t *enp)
1348 siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
1349 siena_filter_tbl_id_t tbl_id;
1350 siena_filter_tbl_t *sftp;
1351 siena_filter_spec_t *spec;
1354 efsys_lock_state_t state;
1358 EFSYS_LOCK(enp->en_eslp, state);
1360 for (tbl_id = 0; tbl_id < EFX_SIENA_FILTER_NTBLS; tbl_id++) {
1361 sftp = &sfp->sf_tbl[tbl_id];
1362 for (filter_idx = 0;
1363 filter_idx < sftp->sft_size;
1365 if (!siena_filter_test_used(sftp, filter_idx))
1368 spec = &sftp->sft_spec[filter_idx];
1369 if ((key = siena_filter_build(&filter, spec)) == 0) {
1373 if ((rc = siena_filter_push_entry(enp,
1374 spec->sfs_type, filter_idx, &filter)) != 0)
1379 siena_filter_push_rx_limits(enp);
1380 siena_filter_push_tx_limits(enp);
1382 EFSYS_UNLOCK(enp->en_eslp, state);
1390 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1392 EFSYS_UNLOCK(enp->en_eslp, state);
1397 static __checkReturn efx_rc_t
1399 __in efx_nic_t *enp,
1400 __inout efx_filter_spec_t *spec,
1401 __in boolean_t may_replace)
1404 siena_filter_spec_t sf_spec;
1405 siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
1406 siena_filter_tbl_id_t tbl_id;
1407 siena_filter_tbl_t *sftp;
1408 siena_filter_spec_t *saved_sf_spec;
1412 efsys_lock_state_t state;
1416 EFSYS_ASSERT3P(spec, !=, NULL);
1418 if ((rc = siena_filter_spec_from_gen_spec(&sf_spec, spec)) != 0)
1421 tbl_id = siena_filter_tbl_id(sf_spec.sfs_type);
1422 sftp = &sfp->sf_tbl[tbl_id];
1424 if (sftp->sft_size == 0) {
1429 key = siena_filter_build(&filter, &sf_spec);
1431 EFSYS_LOCK(enp->en_eslp, state);
1433 rc = siena_filter_search(sftp, &sf_spec, key, B_TRUE,
1434 &filter_idx, &depth);
1438 EFSYS_ASSERT3U(filter_idx, <, sftp->sft_size);
1439 saved_sf_spec = &sftp->sft_spec[filter_idx];
1441 if (siena_filter_test_used(sftp, filter_idx)) {
1442 if (may_replace == B_FALSE) {
1447 siena_filter_set_used(sftp, filter_idx);
1448 *saved_sf_spec = sf_spec;
1450 if (sfp->sf_depth[sf_spec.sfs_type] < depth) {
1451 sfp->sf_depth[sf_spec.sfs_type] = depth;
1452 if (tbl_id == EFX_SIENA_FILTER_TBL_TX_IP ||
1453 tbl_id == EFX_SIENA_FILTER_TBL_TX_MAC)
1454 siena_filter_push_tx_limits(enp);
1456 siena_filter_push_rx_limits(enp);
1459 siena_filter_push_entry(enp, sf_spec.sfs_type,
1460 filter_idx, &filter);
1462 EFSYS_UNLOCK(enp->en_eslp, state);
1469 EFSYS_UNLOCK(enp->en_eslp, state);
1476 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1480 static __checkReturn efx_rc_t
1481 siena_filter_delete(
1482 __in efx_nic_t *enp,
1483 __inout efx_filter_spec_t *spec)
1486 siena_filter_spec_t sf_spec;
1487 siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
1488 siena_filter_tbl_id_t tbl_id;
1489 siena_filter_tbl_t *sftp;
1493 efsys_lock_state_t state;
1496 EFSYS_ASSERT3P(spec, !=, NULL);
1498 if ((rc = siena_filter_spec_from_gen_spec(&sf_spec, spec)) != 0)
1501 tbl_id = siena_filter_tbl_id(sf_spec.sfs_type);
1502 sftp = &sfp->sf_tbl[tbl_id];
1504 key = siena_filter_build(&filter, &sf_spec);
1506 EFSYS_LOCK(enp->en_eslp, state);
1508 rc = siena_filter_search(sftp, &sf_spec, key, B_FALSE,
1509 &filter_idx, &depth);
1513 siena_filter_clear_entry(enp, sftp, filter_idx);
1514 if (sftp->sft_used == 0)
1515 siena_filter_reset_search_depth(sfp, tbl_id);
1517 EFSYS_UNLOCK(enp->en_eslp, state);
1521 EFSYS_UNLOCK(enp->en_eslp, state);
1525 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1529 #define SIENA_MAX_SUPPORTED_MATCHES 4
1531 static __checkReturn efx_rc_t
1532 siena_filter_supported_filters(
1533 __in efx_nic_t *enp,
1534 __out_ecount(buffer_length) uint32_t *buffer,
1535 __in size_t buffer_length,
1536 __out size_t *list_lengthp)
1539 uint32_t rx_matches[SIENA_MAX_SUPPORTED_MATCHES];
1543 rx_matches[index++] =
1544 EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
1545 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT |
1546 EFX_FILTER_MATCH_REM_HOST | EFX_FILTER_MATCH_REM_PORT;
1548 rx_matches[index++] =
1549 EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
1550 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT;
1552 if (enp->en_features & EFX_FEATURE_MAC_HEADER_FILTERS) {
1553 rx_matches[index++] =
1554 EFX_FILTER_MATCH_OUTER_VID | EFX_FILTER_MATCH_LOC_MAC;
1556 rx_matches[index++] = EFX_FILTER_MATCH_LOC_MAC;
1559 EFSYS_ASSERT3U(index, <=, SIENA_MAX_SUPPORTED_MATCHES);
1560 list_length = index;
1562 *list_lengthp = list_length;
1564 if (buffer_length < list_length) {
1569 memcpy(buffer, rx_matches, list_length * sizeof (rx_matches[0]));
1574 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1579 #undef MAX_SUPPORTED
1581 #endif /* EFSYS_OPT_SIENA */
1583 #endif /* EFSYS_OPT_FILTER */