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 if (spec->efs_priority == EFX_FILTER_PRI_AUTO) {
101 return (efop->efo_add(enp, spec, B_FALSE));
108 EFSYS_PROBE1(fail1, efx_rc_t, rc);
113 __checkReturn efx_rc_t
116 __inout efx_filter_spec_t *spec)
118 const efx_filter_ops_t *efop = enp->en_efop;
120 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
121 EFSYS_ASSERT3P(spec, !=, NULL);
122 EFSYS_ASSERT3U(spec->efs_flags, &, EFX_FILTER_FLAG_RX);
124 return (efop->efo_delete(enp, spec));
127 __checkReturn efx_rc_t
133 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
135 if ((rc = enp->en_efop->efo_restore(enp)) != 0)
141 EFSYS_PROBE1(fail1, efx_rc_t, rc);
146 __checkReturn efx_rc_t
150 const efx_filter_ops_t *efop;
153 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
154 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
155 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_FILTER));
157 switch (enp->en_family) {
159 case EFX_FAMILY_SIENA:
160 efop = &__efx_filter_siena_ops;
162 #endif /* EFSYS_OPT_SIENA */
164 #if EFSYS_OPT_HUNTINGTON
165 case EFX_FAMILY_HUNTINGTON:
166 efop = &__efx_filter_ef10_ops;
168 #endif /* EFSYS_OPT_HUNTINGTON */
170 #if EFSYS_OPT_MEDFORD
171 case EFX_FAMILY_MEDFORD:
172 efop = &__efx_filter_ef10_ops;
174 #endif /* EFSYS_OPT_MEDFORD */
176 #if EFSYS_OPT_MEDFORD2
177 case EFX_FAMILY_MEDFORD2:
178 efop = &__efx_filter_ef10_ops;
180 #endif /* EFSYS_OPT_MEDFORD2 */
188 if ((rc = efop->efo_init(enp)) != 0)
192 enp->en_mod_flags |= EFX_MOD_FILTER;
198 EFSYS_PROBE1(fail1, efx_rc_t, rc);
201 enp->en_mod_flags &= ~EFX_MOD_FILTER;
209 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
210 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
211 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
213 enp->en_efop->efo_fini(enp);
216 enp->en_mod_flags &= ~EFX_MOD_FILTER;
220 * Query the possible combinations of match flags which can be filtered on.
221 * These are returned as a list, of which each 32 bit element is a bitmask
222 * formed of EFX_FILTER_MATCH flags.
224 * The combinations are ordered in priority from highest to lowest.
226 * If the provided buffer is too short to hold the list, the call with fail with
227 * ENOSPC and *list_lengthp will be set to the buffer length required.
229 __checkReturn efx_rc_t
230 efx_filter_supported_filters(
232 __out_ecount(buffer_length) uint32_t *buffer,
233 __in size_t buffer_length,
234 __out size_t *list_lengthp)
238 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
239 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
240 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
241 EFSYS_ASSERT(enp->en_efop->efo_supported_filters != NULL);
243 if (buffer == NULL) {
248 rc = enp->en_efop->efo_supported_filters(enp, buffer, buffer_length,
258 EFSYS_PROBE1(fail1, efx_rc_t, rc);
263 __checkReturn efx_rc_t
264 efx_filter_reconfigure(
266 __in_ecount(6) uint8_t const *mac_addr,
267 __in boolean_t all_unicst,
268 __in boolean_t mulcst,
269 __in boolean_t all_mulcst,
270 __in boolean_t brdcst,
271 __in_ecount(6*count) uint8_t const *addrs,
276 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
277 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
278 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
280 if (enp->en_efop->efo_reconfigure != NULL) {
281 if ((rc = enp->en_efop->efo_reconfigure(enp, mac_addr,
291 EFSYS_PROBE1(fail1, efx_rc_t, rc);
297 efx_filter_spec_init_rx(
298 __out efx_filter_spec_t *spec,
299 __in efx_filter_priority_t priority,
300 __in efx_filter_flags_t flags,
303 EFSYS_ASSERT3P(spec, !=, NULL);
304 EFSYS_ASSERT3P(erp, !=, NULL);
305 EFSYS_ASSERT((flags & ~(EFX_FILTER_FLAG_RX_RSS |
306 EFX_FILTER_FLAG_RX_SCATTER)) == 0);
308 memset(spec, 0, sizeof (*spec));
309 spec->efs_priority = priority;
310 spec->efs_flags = EFX_FILTER_FLAG_RX | flags;
311 spec->efs_rss_context = EFX_RSS_CONTEXT_DEFAULT;
312 spec->efs_dmaq_id = (uint16_t)erp->er_index;
316 efx_filter_spec_init_tx(
317 __out efx_filter_spec_t *spec,
320 EFSYS_ASSERT3P(spec, !=, NULL);
321 EFSYS_ASSERT3P(etp, !=, NULL);
323 memset(spec, 0, sizeof (*spec));
324 spec->efs_priority = EFX_FILTER_PRI_MANUAL;
325 spec->efs_flags = EFX_FILTER_FLAG_TX;
326 spec->efs_dmaq_id = (uint16_t)etp->et_index;
331 * Specify IPv4 host, transport protocol and port in a filter specification
333 __checkReturn efx_rc_t
334 efx_filter_spec_set_ipv4_local(
335 __inout efx_filter_spec_t *spec,
340 EFSYS_ASSERT3P(spec, !=, NULL);
342 spec->efs_match_flags |=
343 EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
344 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT;
345 spec->efs_ether_type = EFX_ETHER_TYPE_IPV4;
346 spec->efs_ip_proto = proto;
347 spec->efs_loc_host.eo_u32[0] = host;
348 spec->efs_loc_port = port;
353 * Specify IPv4 hosts, transport protocol and ports in a filter specification
355 __checkReturn efx_rc_t
356 efx_filter_spec_set_ipv4_full(
357 __inout efx_filter_spec_t *spec,
364 EFSYS_ASSERT3P(spec, !=, NULL);
366 spec->efs_match_flags |=
367 EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
368 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT |
369 EFX_FILTER_MATCH_REM_HOST | EFX_FILTER_MATCH_REM_PORT;
370 spec->efs_ether_type = EFX_ETHER_TYPE_IPV4;
371 spec->efs_ip_proto = proto;
372 spec->efs_loc_host.eo_u32[0] = lhost;
373 spec->efs_loc_port = lport;
374 spec->efs_rem_host.eo_u32[0] = rhost;
375 spec->efs_rem_port = rport;
380 * Specify local Ethernet address and/or VID in filter specification
382 __checkReturn efx_rc_t
383 efx_filter_spec_set_eth_local(
384 __inout efx_filter_spec_t *spec,
386 __in const uint8_t *addr)
388 EFSYS_ASSERT3P(spec, !=, NULL);
389 EFSYS_ASSERT3P(addr, !=, NULL);
391 if (vid == EFX_FILTER_SPEC_VID_UNSPEC && addr == NULL)
394 if (vid != EFX_FILTER_SPEC_VID_UNSPEC) {
395 spec->efs_match_flags |= EFX_FILTER_MATCH_OUTER_VID;
396 spec->efs_outer_vid = vid;
399 spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_MAC;
400 memcpy(spec->efs_loc_mac, addr, EFX_MAC_ADDR_LEN);
406 efx_filter_spec_set_ether_type(
407 __inout efx_filter_spec_t *spec,
408 __in uint16_t ether_type)
410 EFSYS_ASSERT3P(spec, !=, NULL);
412 spec->efs_ether_type = ether_type;
413 spec->efs_match_flags |= EFX_FILTER_MATCH_ETHER_TYPE;
417 * Specify matching otherwise-unmatched unicast in a filter specification
419 __checkReturn efx_rc_t
420 efx_filter_spec_set_uc_def(
421 __inout efx_filter_spec_t *spec)
423 EFSYS_ASSERT3P(spec, !=, NULL);
425 spec->efs_match_flags |= EFX_FILTER_MATCH_UNKNOWN_UCAST_DST;
430 * Specify matching otherwise-unmatched multicast in a filter specification
432 __checkReturn efx_rc_t
433 efx_filter_spec_set_mc_def(
434 __inout efx_filter_spec_t *spec)
436 EFSYS_ASSERT3P(spec, !=, NULL);
438 spec->efs_match_flags |= EFX_FILTER_MATCH_UNKNOWN_MCAST_DST;
443 __checkReturn efx_rc_t
444 efx_filter_spec_set_encap_type(
445 __inout efx_filter_spec_t *spec,
446 __in efx_tunnel_protocol_t encap_type,
447 __in efx_filter_inner_frame_match_t inner_frame_match)
449 uint32_t match_flags = EFX_FILTER_MATCH_ENCAP_TYPE;
453 EFSYS_ASSERT3P(spec, !=, NULL);
455 switch (encap_type) {
456 case EFX_TUNNEL_PROTOCOL_VXLAN:
457 case EFX_TUNNEL_PROTOCOL_GENEVE:
458 ip_proto = EFX_IPPROTO_UDP;
460 case EFX_TUNNEL_PROTOCOL_NVGRE:
461 ip_proto = EFX_IPPROTO_GRE;
469 switch (inner_frame_match) {
470 case EFX_FILTER_INNER_FRAME_MATCH_UNKNOWN_MCAST_DST:
471 match_flags |= EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST;
473 case EFX_FILTER_INNER_FRAME_MATCH_UNKNOWN_UCAST_DST:
474 match_flags |= EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST;
476 case EFX_FILTER_INNER_FRAME_MATCH_OTHER:
477 /* This is for when specific inner frames are to be matched. */
485 spec->efs_encap_type = encap_type;
486 spec->efs_ip_proto = ip_proto;
487 spec->efs_match_flags |= (match_flags | EFX_FILTER_MATCH_IP_PROTO);
494 EFSYS_PROBE1(fail1, efx_rc_t, rc);
500 * Specify inner and outer Ethernet address and VNI or VSID in tunnel filter
503 static __checkReturn efx_rc_t
504 efx_filter_spec_set_tunnel(
505 __inout efx_filter_spec_t *spec,
506 __in efx_tunnel_protocol_t encap_type,
507 __in const uint8_t *vni_or_vsid,
508 __in const uint8_t *inner_addr,
509 __in const uint8_t *outer_addr)
513 EFSYS_ASSERT3P(spec, !=, NULL);
514 EFSYS_ASSERT3P(vni_or_vsid, !=, NULL);
515 EFSYS_ASSERT3P(inner_addr, !=, NULL);
516 EFSYS_ASSERT3P(outer_addr, !=, NULL);
518 switch (encap_type) {
519 case EFX_TUNNEL_PROTOCOL_VXLAN:
520 case EFX_TUNNEL_PROTOCOL_GENEVE:
521 case EFX_TUNNEL_PROTOCOL_NVGRE:
528 if ((inner_addr == NULL) && (outer_addr == NULL)) {
533 if (vni_or_vsid != NULL) {
534 spec->efs_match_flags |= EFX_FILTER_MATCH_VNI_OR_VSID;
535 memcpy(spec->efs_vni_or_vsid, vni_or_vsid, EFX_VNI_OR_VSID_LEN);
537 if (outer_addr != NULL) {
538 spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_MAC;
539 memcpy(spec->efs_loc_mac, outer_addr, EFX_MAC_ADDR_LEN);
541 if (inner_addr != NULL) {
542 spec->efs_match_flags |= EFX_FILTER_MATCH_IFRM_LOC_MAC;
543 memcpy(spec->efs_ifrm_loc_mac, inner_addr, EFX_MAC_ADDR_LEN);
546 spec->efs_match_flags |= EFX_FILTER_MATCH_ENCAP_TYPE;
547 spec->efs_encap_type = encap_type;
554 EFSYS_PROBE1(fail1, efx_rc_t, rc);
560 * Specify inner and outer Ethernet address and VNI in VXLAN filter
563 __checkReturn efx_rc_t
564 efx_filter_spec_set_vxlan(
565 __inout efx_filter_spec_t *spec,
566 __in const uint8_t *vni,
567 __in const uint8_t *inner_addr,
568 __in const uint8_t *outer_addr)
570 return efx_filter_spec_set_tunnel(spec, EFX_TUNNEL_PROTOCOL_VXLAN,
571 vni, inner_addr, outer_addr);
575 * Specify inner and outer Ethernet address and VNI in Geneve filter
578 __checkReturn efx_rc_t
579 efx_filter_spec_set_geneve(
580 __inout efx_filter_spec_t *spec,
581 __in const uint8_t *vni,
582 __in const uint8_t *inner_addr,
583 __in const uint8_t *outer_addr)
585 return efx_filter_spec_set_tunnel(spec, EFX_TUNNEL_PROTOCOL_GENEVE,
586 vni, inner_addr, outer_addr);
590 * Specify inner and outer Ethernet address and vsid in NVGRE filter
593 __checkReturn efx_rc_t
594 efx_filter_spec_set_nvgre(
595 __inout efx_filter_spec_t *spec,
596 __in const uint8_t *vsid,
597 __in const uint8_t *inner_addr,
598 __in const uint8_t *outer_addr)
600 return efx_filter_spec_set_tunnel(spec, EFX_TUNNEL_PROTOCOL_NVGRE,
601 vsid, inner_addr, outer_addr);
604 #if EFSYS_OPT_RX_SCALE
605 __checkReturn efx_rc_t
606 efx_filter_spec_set_rss_context(
607 __inout efx_filter_spec_t *spec,
608 __in uint32_t rss_context)
612 EFSYS_ASSERT3P(spec, !=, NULL);
614 /* The filter must have been created with EFX_FILTER_FLAG_RX_RSS. */
615 if ((spec->efs_flags & EFX_FILTER_FLAG_RX_RSS) == 0) {
620 spec->efs_rss_context = rss_context;
625 EFSYS_PROBE1(fail1, efx_rc_t, rc);
634 * "Fudge factors" - difference between programmed value and actual depth.
635 * Due to pipelined implementation we need to program H/W with a value that
636 * is larger than the hop limit we want.
638 #define FILTER_CTL_SRCH_FUDGE_WILD 3
639 #define FILTER_CTL_SRCH_FUDGE_FULL 1
642 * Hard maximum hop limit. Hardware will time-out beyond 200-something.
643 * We also need to avoid infinite loops in efx_filter_search() when the
646 #define FILTER_CTL_SRCH_MAX 200
648 static __checkReturn efx_rc_t
649 siena_filter_spec_from_gen_spec(
650 __out siena_filter_spec_t *sf_spec,
651 __in efx_filter_spec_t *gen_spec)
654 boolean_t is_full = B_FALSE;
656 if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX)
657 EFSYS_ASSERT3U(gen_spec->efs_flags, ==, EFX_FILTER_FLAG_TX);
659 EFSYS_ASSERT3U(gen_spec->efs_flags, &, EFX_FILTER_FLAG_RX);
661 /* Siena only has one RSS context */
662 if ((gen_spec->efs_flags & EFX_FILTER_FLAG_RX_RSS) &&
663 gen_spec->efs_rss_context != EFX_RSS_CONTEXT_DEFAULT) {
668 sf_spec->sfs_flags = gen_spec->efs_flags;
669 sf_spec->sfs_dmaq_id = gen_spec->efs_dmaq_id;
671 switch (gen_spec->efs_match_flags) {
672 case EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
673 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT |
674 EFX_FILTER_MATCH_REM_HOST | EFX_FILTER_MATCH_REM_PORT:
677 case EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
678 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT: {
679 uint32_t rhost, host1, host2;
680 uint16_t rport, port1, port2;
682 if (gen_spec->efs_ether_type != EFX_ETHER_TYPE_IPV4) {
686 if (gen_spec->efs_loc_port == 0 ||
687 (is_full && gen_spec->efs_rem_port == 0)) {
691 switch (gen_spec->efs_ip_proto) {
692 case EFX_IPPROTO_TCP:
693 if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX) {
694 sf_spec->sfs_type = (is_full ?
695 EFX_SIENA_FILTER_TX_TCP_FULL :
696 EFX_SIENA_FILTER_TX_TCP_WILD);
698 sf_spec->sfs_type = (is_full ?
699 EFX_SIENA_FILTER_RX_TCP_FULL :
700 EFX_SIENA_FILTER_RX_TCP_WILD);
703 case EFX_IPPROTO_UDP:
704 if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX) {
705 sf_spec->sfs_type = (is_full ?
706 EFX_SIENA_FILTER_TX_UDP_FULL :
707 EFX_SIENA_FILTER_TX_UDP_WILD);
709 sf_spec->sfs_type = (is_full ?
710 EFX_SIENA_FILTER_RX_UDP_FULL :
711 EFX_SIENA_FILTER_RX_UDP_WILD);
719 * The filter is constructed in terms of source and destination,
720 * with the odd wrinkle that the ports are swapped in a UDP
721 * wildcard filter. We need to convert from local and remote
722 * addresses (zero for a wildcard).
724 rhost = is_full ? gen_spec->efs_rem_host.eo_u32[0] : 0;
725 rport = is_full ? gen_spec->efs_rem_port : 0;
726 if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX) {
727 host1 = gen_spec->efs_loc_host.eo_u32[0];
731 host2 = gen_spec->efs_loc_host.eo_u32[0];
733 if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX) {
734 if (sf_spec->sfs_type ==
735 EFX_SIENA_FILTER_TX_UDP_WILD) {
737 port2 = gen_spec->efs_loc_port;
739 port1 = gen_spec->efs_loc_port;
743 if (sf_spec->sfs_type ==
744 EFX_SIENA_FILTER_RX_UDP_WILD) {
745 port1 = gen_spec->efs_loc_port;
749 port2 = gen_spec->efs_loc_port;
752 sf_spec->sfs_dword[0] = (host1 << 16) | port1;
753 sf_spec->sfs_dword[1] = (port2 << 16) | (host1 >> 16);
754 sf_spec->sfs_dword[2] = host2;
758 case EFX_FILTER_MATCH_LOC_MAC | EFX_FILTER_MATCH_OUTER_VID:
761 case EFX_FILTER_MATCH_LOC_MAC:
762 if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX) {
763 sf_spec->sfs_type = (is_full ?
764 EFX_SIENA_FILTER_TX_MAC_FULL :
765 EFX_SIENA_FILTER_TX_MAC_WILD);
767 sf_spec->sfs_type = (is_full ?
768 EFX_SIENA_FILTER_RX_MAC_FULL :
769 EFX_SIENA_FILTER_RX_MAC_WILD);
771 sf_spec->sfs_dword[0] = is_full ? gen_spec->efs_outer_vid : 0;
772 sf_spec->sfs_dword[1] =
773 gen_spec->efs_loc_mac[2] << 24 |
774 gen_spec->efs_loc_mac[3] << 16 |
775 gen_spec->efs_loc_mac[4] << 8 |
776 gen_spec->efs_loc_mac[5];
777 sf_spec->sfs_dword[2] =
778 gen_spec->efs_loc_mac[0] << 8 |
779 gen_spec->efs_loc_mac[1];
783 EFSYS_ASSERT(B_FALSE);
799 EFSYS_PROBE1(fail1, efx_rc_t, rc);
805 * The filter hash function is LFSR polynomial x^16 + x^3 + 1 of a 32-bit
806 * key derived from the n-tuple.
809 siena_filter_tbl_hash(
814 /* First 16 rounds */
815 tmp = 0x1fff ^ (uint16_t)(key >> 16);
816 tmp = tmp ^ tmp >> 3 ^ tmp >> 6;
817 tmp = tmp ^ tmp >> 9;
820 tmp = tmp ^ tmp << 13 ^ (uint16_t)(key & 0xffff);
821 tmp = tmp ^ tmp >> 3 ^ tmp >> 6;
822 tmp = tmp ^ tmp >> 9;
828 * To allow for hash collisions, filter search continues at these
829 * increments from the first possible entry selected by the hash.
832 siena_filter_tbl_increment(
835 return ((uint16_t)(key * 2 - 1));
838 static __checkReturn boolean_t
839 siena_filter_test_used(
840 __in siena_filter_tbl_t *sftp,
841 __in unsigned int index)
843 EFSYS_ASSERT3P(sftp->sft_bitmap, !=, NULL);
844 return ((sftp->sft_bitmap[index / 32] & (1 << (index % 32))) != 0);
848 siena_filter_set_used(
849 __in siena_filter_tbl_t *sftp,
850 __in unsigned int index)
852 EFSYS_ASSERT3P(sftp->sft_bitmap, !=, NULL);
853 sftp->sft_bitmap[index / 32] |= (1 << (index % 32));
858 siena_filter_clear_used(
859 __in siena_filter_tbl_t *sftp,
860 __in unsigned int index)
862 EFSYS_ASSERT3P(sftp->sft_bitmap, !=, NULL);
863 sftp->sft_bitmap[index / 32] &= ~(1 << (index % 32));
866 EFSYS_ASSERT3U(sftp->sft_used, >=, 0);
870 static siena_filter_tbl_id_t
872 __in siena_filter_type_t type)
874 siena_filter_tbl_id_t tbl_id;
877 case EFX_SIENA_FILTER_RX_TCP_FULL:
878 case EFX_SIENA_FILTER_RX_TCP_WILD:
879 case EFX_SIENA_FILTER_RX_UDP_FULL:
880 case EFX_SIENA_FILTER_RX_UDP_WILD:
881 tbl_id = EFX_SIENA_FILTER_TBL_RX_IP;
884 case EFX_SIENA_FILTER_RX_MAC_FULL:
885 case EFX_SIENA_FILTER_RX_MAC_WILD:
886 tbl_id = EFX_SIENA_FILTER_TBL_RX_MAC;
889 case EFX_SIENA_FILTER_TX_TCP_FULL:
890 case EFX_SIENA_FILTER_TX_TCP_WILD:
891 case EFX_SIENA_FILTER_TX_UDP_FULL:
892 case EFX_SIENA_FILTER_TX_UDP_WILD:
893 tbl_id = EFX_SIENA_FILTER_TBL_TX_IP;
896 case EFX_SIENA_FILTER_TX_MAC_FULL:
897 case EFX_SIENA_FILTER_TX_MAC_WILD:
898 tbl_id = EFX_SIENA_FILTER_TBL_TX_MAC;
902 EFSYS_ASSERT(B_FALSE);
903 tbl_id = EFX_SIENA_FILTER_NTBLS;
910 siena_filter_reset_search_depth(
911 __inout siena_filter_t *sfp,
912 __in siena_filter_tbl_id_t tbl_id)
915 case EFX_SIENA_FILTER_TBL_RX_IP:
916 sfp->sf_depth[EFX_SIENA_FILTER_RX_TCP_FULL] = 0;
917 sfp->sf_depth[EFX_SIENA_FILTER_RX_TCP_WILD] = 0;
918 sfp->sf_depth[EFX_SIENA_FILTER_RX_UDP_FULL] = 0;
919 sfp->sf_depth[EFX_SIENA_FILTER_RX_UDP_WILD] = 0;
922 case EFX_SIENA_FILTER_TBL_RX_MAC:
923 sfp->sf_depth[EFX_SIENA_FILTER_RX_MAC_FULL] = 0;
924 sfp->sf_depth[EFX_SIENA_FILTER_RX_MAC_WILD] = 0;
927 case EFX_SIENA_FILTER_TBL_TX_IP:
928 sfp->sf_depth[EFX_SIENA_FILTER_TX_TCP_FULL] = 0;
929 sfp->sf_depth[EFX_SIENA_FILTER_TX_TCP_WILD] = 0;
930 sfp->sf_depth[EFX_SIENA_FILTER_TX_UDP_FULL] = 0;
931 sfp->sf_depth[EFX_SIENA_FILTER_TX_UDP_WILD] = 0;
934 case EFX_SIENA_FILTER_TBL_TX_MAC:
935 sfp->sf_depth[EFX_SIENA_FILTER_TX_MAC_FULL] = 0;
936 sfp->sf_depth[EFX_SIENA_FILTER_TX_MAC_WILD] = 0;
940 EFSYS_ASSERT(B_FALSE);
946 siena_filter_push_rx_limits(
949 siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
952 EFX_BAR_READO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
954 EFX_SET_OWORD_FIELD(oword, FRF_AZ_TCP_FULL_SRCH_LIMIT,
955 sfp->sf_depth[EFX_SIENA_FILTER_RX_TCP_FULL] +
956 FILTER_CTL_SRCH_FUDGE_FULL);
957 EFX_SET_OWORD_FIELD(oword, FRF_AZ_TCP_WILD_SRCH_LIMIT,
958 sfp->sf_depth[EFX_SIENA_FILTER_RX_TCP_WILD] +
959 FILTER_CTL_SRCH_FUDGE_WILD);
960 EFX_SET_OWORD_FIELD(oword, FRF_AZ_UDP_FULL_SRCH_LIMIT,
961 sfp->sf_depth[EFX_SIENA_FILTER_RX_UDP_FULL] +
962 FILTER_CTL_SRCH_FUDGE_FULL);
963 EFX_SET_OWORD_FIELD(oword, FRF_AZ_UDP_WILD_SRCH_LIMIT,
964 sfp->sf_depth[EFX_SIENA_FILTER_RX_UDP_WILD] +
965 FILTER_CTL_SRCH_FUDGE_WILD);
967 if (sfp->sf_tbl[EFX_SIENA_FILTER_TBL_RX_MAC].sft_size) {
968 EFX_SET_OWORD_FIELD(oword,
969 FRF_CZ_ETHERNET_FULL_SEARCH_LIMIT,
970 sfp->sf_depth[EFX_SIENA_FILTER_RX_MAC_FULL] +
971 FILTER_CTL_SRCH_FUDGE_FULL);
972 EFX_SET_OWORD_FIELD(oword,
973 FRF_CZ_ETHERNET_WILDCARD_SEARCH_LIMIT,
974 sfp->sf_depth[EFX_SIENA_FILTER_RX_MAC_WILD] +
975 FILTER_CTL_SRCH_FUDGE_WILD);
978 EFX_BAR_WRITEO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
982 siena_filter_push_tx_limits(
985 siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
988 EFX_BAR_READO(enp, FR_AZ_TX_CFG_REG, &oword);
990 if (sfp->sf_tbl[EFX_SIENA_FILTER_TBL_TX_IP].sft_size != 0) {
991 EFX_SET_OWORD_FIELD(oword,
992 FRF_CZ_TX_TCPIP_FILTER_FULL_SEARCH_RANGE,
993 sfp->sf_depth[EFX_SIENA_FILTER_TX_TCP_FULL] +
994 FILTER_CTL_SRCH_FUDGE_FULL);
995 EFX_SET_OWORD_FIELD(oword,
996 FRF_CZ_TX_TCPIP_FILTER_WILD_SEARCH_RANGE,
997 sfp->sf_depth[EFX_SIENA_FILTER_TX_TCP_WILD] +
998 FILTER_CTL_SRCH_FUDGE_WILD);
999 EFX_SET_OWORD_FIELD(oword,
1000 FRF_CZ_TX_UDPIP_FILTER_FULL_SEARCH_RANGE,
1001 sfp->sf_depth[EFX_SIENA_FILTER_TX_UDP_FULL] +
1002 FILTER_CTL_SRCH_FUDGE_FULL);
1003 EFX_SET_OWORD_FIELD(oword,
1004 FRF_CZ_TX_UDPIP_FILTER_WILD_SEARCH_RANGE,
1005 sfp->sf_depth[EFX_SIENA_FILTER_TX_UDP_WILD] +
1006 FILTER_CTL_SRCH_FUDGE_WILD);
1009 if (sfp->sf_tbl[EFX_SIENA_FILTER_TBL_TX_MAC].sft_size != 0) {
1010 EFX_SET_OWORD_FIELD(
1011 oword, FRF_CZ_TX_ETH_FILTER_FULL_SEARCH_RANGE,
1012 sfp->sf_depth[EFX_SIENA_FILTER_TX_MAC_FULL] +
1013 FILTER_CTL_SRCH_FUDGE_FULL);
1014 EFX_SET_OWORD_FIELD(
1015 oword, FRF_CZ_TX_ETH_FILTER_WILD_SEARCH_RANGE,
1016 sfp->sf_depth[EFX_SIENA_FILTER_TX_MAC_WILD] +
1017 FILTER_CTL_SRCH_FUDGE_WILD);
1020 EFX_BAR_WRITEO(enp, FR_AZ_TX_CFG_REG, &oword);
1023 /* Build a filter entry and return its n-tuple key. */
1024 static __checkReturn uint32_t
1026 __out efx_oword_t *filter,
1027 __in siena_filter_spec_t *spec)
1031 uint8_t type = spec->sfs_type;
1032 uint32_t flags = spec->sfs_flags;
1034 switch (siena_filter_tbl_id(type)) {
1035 case EFX_SIENA_FILTER_TBL_RX_IP: {
1036 boolean_t is_udp = (type == EFX_SIENA_FILTER_RX_UDP_FULL ||
1037 type == EFX_SIENA_FILTER_RX_UDP_WILD);
1038 EFX_POPULATE_OWORD_7(*filter,
1040 (flags & EFX_FILTER_FLAG_RX_RSS) ? 1 : 0,
1042 (flags & EFX_FILTER_FLAG_RX_SCATTER) ? 1 : 0,
1043 FRF_AZ_TCP_UDP, is_udp,
1044 FRF_AZ_RXQ_ID, spec->sfs_dmaq_id,
1045 EFX_DWORD_2, spec->sfs_dword[2],
1046 EFX_DWORD_1, spec->sfs_dword[1],
1047 EFX_DWORD_0, spec->sfs_dword[0]);
1052 case EFX_SIENA_FILTER_TBL_RX_MAC: {
1053 boolean_t is_wild = (type == EFX_SIENA_FILTER_RX_MAC_WILD);
1054 EFX_POPULATE_OWORD_7(*filter,
1056 (flags & EFX_FILTER_FLAG_RX_RSS) ? 1 : 0,
1057 FRF_CZ_RMFT_SCATTER_EN,
1058 (flags & EFX_FILTER_FLAG_RX_SCATTER) ? 1 : 0,
1059 FRF_CZ_RMFT_RXQ_ID, spec->sfs_dmaq_id,
1060 FRF_CZ_RMFT_WILDCARD_MATCH, is_wild,
1061 FRF_CZ_RMFT_DEST_MAC_DW1, spec->sfs_dword[2],
1062 FRF_CZ_RMFT_DEST_MAC_DW0, spec->sfs_dword[1],
1063 FRF_CZ_RMFT_VLAN_ID, spec->sfs_dword[0]);
1068 case EFX_SIENA_FILTER_TBL_TX_IP: {
1069 boolean_t is_udp = (type == EFX_SIENA_FILTER_TX_UDP_FULL ||
1070 type == EFX_SIENA_FILTER_TX_UDP_WILD);
1071 EFX_POPULATE_OWORD_5(*filter,
1072 FRF_CZ_TIFT_TCP_UDP, is_udp,
1073 FRF_CZ_TIFT_TXQ_ID, spec->sfs_dmaq_id,
1074 EFX_DWORD_2, spec->sfs_dword[2],
1075 EFX_DWORD_1, spec->sfs_dword[1],
1076 EFX_DWORD_0, spec->sfs_dword[0]);
1077 dword3 = is_udp | spec->sfs_dmaq_id << 1;
1081 case EFX_SIENA_FILTER_TBL_TX_MAC: {
1082 boolean_t is_wild = (type == EFX_SIENA_FILTER_TX_MAC_WILD);
1083 EFX_POPULATE_OWORD_5(*filter,
1084 FRF_CZ_TMFT_TXQ_ID, spec->sfs_dmaq_id,
1085 FRF_CZ_TMFT_WILDCARD_MATCH, is_wild,
1086 FRF_CZ_TMFT_SRC_MAC_DW1, spec->sfs_dword[2],
1087 FRF_CZ_TMFT_SRC_MAC_DW0, spec->sfs_dword[1],
1088 FRF_CZ_TMFT_VLAN_ID, spec->sfs_dword[0]);
1089 dword3 = is_wild | spec->sfs_dmaq_id << 1;
1094 EFSYS_ASSERT(B_FALSE);
1095 EFX_ZERO_OWORD(*filter);
1100 spec->sfs_dword[0] ^
1101 spec->sfs_dword[1] ^
1102 spec->sfs_dword[2] ^
1108 static __checkReturn efx_rc_t
1109 siena_filter_push_entry(
1110 __inout efx_nic_t *enp,
1111 __in siena_filter_type_t type,
1113 __in efx_oword_t *eop)
1118 case EFX_SIENA_FILTER_RX_TCP_FULL:
1119 case EFX_SIENA_FILTER_RX_TCP_WILD:
1120 case EFX_SIENA_FILTER_RX_UDP_FULL:
1121 case EFX_SIENA_FILTER_RX_UDP_WILD:
1122 EFX_BAR_TBL_WRITEO(enp, FR_AZ_RX_FILTER_TBL0, index,
1126 case EFX_SIENA_FILTER_RX_MAC_FULL:
1127 case EFX_SIENA_FILTER_RX_MAC_WILD:
1128 EFX_BAR_TBL_WRITEO(enp, FR_CZ_RX_MAC_FILTER_TBL0, index,
1132 case EFX_SIENA_FILTER_TX_TCP_FULL:
1133 case EFX_SIENA_FILTER_TX_TCP_WILD:
1134 case EFX_SIENA_FILTER_TX_UDP_FULL:
1135 case EFX_SIENA_FILTER_TX_UDP_WILD:
1136 EFX_BAR_TBL_WRITEO(enp, FR_CZ_TX_FILTER_TBL0, index,
1140 case EFX_SIENA_FILTER_TX_MAC_FULL:
1141 case EFX_SIENA_FILTER_TX_MAC_WILD:
1142 EFX_BAR_TBL_WRITEO(enp, FR_CZ_TX_MAC_FILTER_TBL0, index,
1147 EFSYS_ASSERT(B_FALSE);
1158 static __checkReturn boolean_t
1160 __in const siena_filter_spec_t *left,
1161 __in const siena_filter_spec_t *right)
1163 siena_filter_tbl_id_t tbl_id;
1165 tbl_id = siena_filter_tbl_id(left->sfs_type);
1168 if (left->sfs_type != right->sfs_type)
1171 if (memcmp(left->sfs_dword, right->sfs_dword,
1172 sizeof (left->sfs_dword)))
1175 if ((tbl_id == EFX_SIENA_FILTER_TBL_TX_IP ||
1176 tbl_id == EFX_SIENA_FILTER_TBL_TX_MAC) &&
1177 left->sfs_dmaq_id != right->sfs_dmaq_id)
1183 static __checkReturn efx_rc_t
1184 siena_filter_search(
1185 __in siena_filter_tbl_t *sftp,
1186 __in siena_filter_spec_t *spec,
1188 __in boolean_t for_insert,
1189 __out int *filter_index,
1190 __out unsigned int *depth_required)
1192 unsigned int hash, incr, filter_idx, depth;
1194 hash = siena_filter_tbl_hash(key);
1195 incr = siena_filter_tbl_increment(key);
1197 filter_idx = hash & (sftp->sft_size - 1);
1202 * Return success if entry is used and matches this spec
1203 * or entry is unused and we are trying to insert.
1205 if (siena_filter_test_used(sftp, filter_idx) ?
1206 siena_filter_equal(spec,
1207 &sftp->sft_spec[filter_idx]) :
1209 *filter_index = filter_idx;
1210 *depth_required = depth;
1214 /* Return failure if we reached the maximum search depth */
1215 if (depth == FILTER_CTL_SRCH_MAX)
1216 return (for_insert ? EBUSY : ENOENT);
1218 filter_idx = (filter_idx + incr) & (sftp->sft_size - 1);
1224 siena_filter_clear_entry(
1225 __in efx_nic_t *enp,
1226 __in siena_filter_tbl_t *sftp,
1231 if (siena_filter_test_used(sftp, index)) {
1232 siena_filter_clear_used(sftp, index);
1234 EFX_ZERO_OWORD(filter);
1235 siena_filter_push_entry(enp,
1236 sftp->sft_spec[index].sfs_type,
1239 memset(&sftp->sft_spec[index],
1240 0, sizeof (sftp->sft_spec[0]));
1245 siena_filter_tbl_clear(
1246 __in efx_nic_t *enp,
1247 __in siena_filter_tbl_id_t tbl_id)
1249 siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
1250 siena_filter_tbl_t *sftp = &sfp->sf_tbl[tbl_id];
1252 efsys_lock_state_t state;
1254 EFSYS_LOCK(enp->en_eslp, state);
1256 for (index = 0; index < sftp->sft_size; ++index) {
1257 siena_filter_clear_entry(enp, sftp, index);
1260 if (sftp->sft_used == 0)
1261 siena_filter_reset_search_depth(sfp, tbl_id);
1263 EFSYS_UNLOCK(enp->en_eslp, state);
1266 static __checkReturn efx_rc_t
1268 __in efx_nic_t *enp)
1270 siena_filter_t *sfp;
1271 siena_filter_tbl_t *sftp;
1275 EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (siena_filter_t), sfp);
1282 enp->en_filter.ef_siena_filter = sfp;
1284 switch (enp->en_family) {
1285 case EFX_FAMILY_SIENA:
1286 sftp = &sfp->sf_tbl[EFX_SIENA_FILTER_TBL_RX_IP];
1287 sftp->sft_size = FR_AZ_RX_FILTER_TBL0_ROWS;
1289 sftp = &sfp->sf_tbl[EFX_SIENA_FILTER_TBL_RX_MAC];
1290 sftp->sft_size = FR_CZ_RX_MAC_FILTER_TBL0_ROWS;
1292 sftp = &sfp->sf_tbl[EFX_SIENA_FILTER_TBL_TX_IP];
1293 sftp->sft_size = FR_CZ_TX_FILTER_TBL0_ROWS;
1295 sftp = &sfp->sf_tbl[EFX_SIENA_FILTER_TBL_TX_MAC];
1296 sftp->sft_size = FR_CZ_TX_MAC_FILTER_TBL0_ROWS;
1304 for (tbl_id = 0; tbl_id < EFX_SIENA_FILTER_NTBLS; tbl_id++) {
1305 unsigned int bitmap_size;
1307 sftp = &sfp->sf_tbl[tbl_id];
1308 if (sftp->sft_size == 0)
1311 EFX_STATIC_ASSERT(sizeof (sftp->sft_bitmap[0]) ==
1314 (sftp->sft_size + (sizeof (uint32_t) * 8) - 1) / 8;
1316 EFSYS_KMEM_ALLOC(enp->en_esip, bitmap_size, sftp->sft_bitmap);
1317 if (!sftp->sft_bitmap) {
1322 EFSYS_KMEM_ALLOC(enp->en_esip,
1323 sftp->sft_size * sizeof (*sftp->sft_spec),
1325 if (!sftp->sft_spec) {
1329 memset(sftp->sft_spec, 0,
1330 sftp->sft_size * sizeof (*sftp->sft_spec));
1343 siena_filter_fini(enp);
1346 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1352 __in efx_nic_t *enp)
1354 siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
1355 siena_filter_tbl_id_t tbl_id;
1357 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1358 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
1363 for (tbl_id = 0; tbl_id < EFX_SIENA_FILTER_NTBLS; tbl_id++) {
1364 siena_filter_tbl_t *sftp = &sfp->sf_tbl[tbl_id];
1365 unsigned int bitmap_size;
1367 EFX_STATIC_ASSERT(sizeof (sftp->sft_bitmap[0]) ==
1370 (sftp->sft_size + (sizeof (uint32_t) * 8) - 1) / 8;
1372 if (sftp->sft_bitmap != NULL) {
1373 EFSYS_KMEM_FREE(enp->en_esip, bitmap_size,
1375 sftp->sft_bitmap = NULL;
1378 if (sftp->sft_spec != NULL) {
1379 EFSYS_KMEM_FREE(enp->en_esip, sftp->sft_size *
1380 sizeof (*sftp->sft_spec), sftp->sft_spec);
1381 sftp->sft_spec = NULL;
1385 EFSYS_KMEM_FREE(enp->en_esip, sizeof (siena_filter_t),
1386 enp->en_filter.ef_siena_filter);
1389 /* Restore filter state after a reset */
1390 static __checkReturn efx_rc_t
1391 siena_filter_restore(
1392 __in efx_nic_t *enp)
1394 siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
1395 siena_filter_tbl_id_t tbl_id;
1396 siena_filter_tbl_t *sftp;
1397 siena_filter_spec_t *spec;
1400 efsys_lock_state_t state;
1404 EFSYS_LOCK(enp->en_eslp, state);
1406 for (tbl_id = 0; tbl_id < EFX_SIENA_FILTER_NTBLS; tbl_id++) {
1407 sftp = &sfp->sf_tbl[tbl_id];
1408 for (filter_idx = 0;
1409 filter_idx < sftp->sft_size;
1411 if (!siena_filter_test_used(sftp, filter_idx))
1414 spec = &sftp->sft_spec[filter_idx];
1415 if ((key = siena_filter_build(&filter, spec)) == 0) {
1419 if ((rc = siena_filter_push_entry(enp,
1420 spec->sfs_type, filter_idx, &filter)) != 0)
1425 siena_filter_push_rx_limits(enp);
1426 siena_filter_push_tx_limits(enp);
1428 EFSYS_UNLOCK(enp->en_eslp, state);
1436 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1438 EFSYS_UNLOCK(enp->en_eslp, state);
1443 static __checkReturn efx_rc_t
1445 __in efx_nic_t *enp,
1446 __inout efx_filter_spec_t *spec,
1447 __in boolean_t may_replace)
1450 siena_filter_spec_t sf_spec;
1451 siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
1452 siena_filter_tbl_id_t tbl_id;
1453 siena_filter_tbl_t *sftp;
1454 siena_filter_spec_t *saved_sf_spec;
1458 efsys_lock_state_t state;
1462 EFSYS_ASSERT3P(spec, !=, NULL);
1464 if ((rc = siena_filter_spec_from_gen_spec(&sf_spec, spec)) != 0)
1467 tbl_id = siena_filter_tbl_id(sf_spec.sfs_type);
1468 sftp = &sfp->sf_tbl[tbl_id];
1470 if (sftp->sft_size == 0) {
1475 key = siena_filter_build(&filter, &sf_spec);
1477 EFSYS_LOCK(enp->en_eslp, state);
1479 rc = siena_filter_search(sftp, &sf_spec, key, B_TRUE,
1480 &filter_idx, &depth);
1484 EFSYS_ASSERT3U(filter_idx, <, sftp->sft_size);
1485 saved_sf_spec = &sftp->sft_spec[filter_idx];
1487 if (siena_filter_test_used(sftp, filter_idx)) {
1488 if (may_replace == B_FALSE) {
1493 siena_filter_set_used(sftp, filter_idx);
1494 *saved_sf_spec = sf_spec;
1496 if (sfp->sf_depth[sf_spec.sfs_type] < depth) {
1497 sfp->sf_depth[sf_spec.sfs_type] = depth;
1498 if (tbl_id == EFX_SIENA_FILTER_TBL_TX_IP ||
1499 tbl_id == EFX_SIENA_FILTER_TBL_TX_MAC)
1500 siena_filter_push_tx_limits(enp);
1502 siena_filter_push_rx_limits(enp);
1505 siena_filter_push_entry(enp, sf_spec.sfs_type,
1506 filter_idx, &filter);
1508 EFSYS_UNLOCK(enp->en_eslp, state);
1515 EFSYS_UNLOCK(enp->en_eslp, state);
1522 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1526 static __checkReturn efx_rc_t
1527 siena_filter_delete(
1528 __in efx_nic_t *enp,
1529 __inout efx_filter_spec_t *spec)
1532 siena_filter_spec_t sf_spec;
1533 siena_filter_t *sfp = enp->en_filter.ef_siena_filter;
1534 siena_filter_tbl_id_t tbl_id;
1535 siena_filter_tbl_t *sftp;
1539 efsys_lock_state_t state;
1542 EFSYS_ASSERT3P(spec, !=, NULL);
1544 if ((rc = siena_filter_spec_from_gen_spec(&sf_spec, spec)) != 0)
1547 tbl_id = siena_filter_tbl_id(sf_spec.sfs_type);
1548 sftp = &sfp->sf_tbl[tbl_id];
1550 key = siena_filter_build(&filter, &sf_spec);
1552 EFSYS_LOCK(enp->en_eslp, state);
1554 rc = siena_filter_search(sftp, &sf_spec, key, B_FALSE,
1555 &filter_idx, &depth);
1559 siena_filter_clear_entry(enp, sftp, filter_idx);
1560 if (sftp->sft_used == 0)
1561 siena_filter_reset_search_depth(sfp, tbl_id);
1563 EFSYS_UNLOCK(enp->en_eslp, state);
1567 EFSYS_UNLOCK(enp->en_eslp, state);
1571 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1575 #define SIENA_MAX_SUPPORTED_MATCHES 4
1577 static __checkReturn efx_rc_t
1578 siena_filter_supported_filters(
1579 __in efx_nic_t *enp,
1580 __out_ecount(buffer_length) uint32_t *buffer,
1581 __in size_t buffer_length,
1582 __out size_t *list_lengthp)
1585 uint32_t rx_matches[SIENA_MAX_SUPPORTED_MATCHES];
1589 rx_matches[index++] =
1590 EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
1591 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT |
1592 EFX_FILTER_MATCH_REM_HOST | EFX_FILTER_MATCH_REM_PORT;
1594 rx_matches[index++] =
1595 EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
1596 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT;
1598 if (enp->en_features & EFX_FEATURE_MAC_HEADER_FILTERS) {
1599 rx_matches[index++] =
1600 EFX_FILTER_MATCH_OUTER_VID | EFX_FILTER_MATCH_LOC_MAC;
1602 rx_matches[index++] = EFX_FILTER_MATCH_LOC_MAC;
1605 EFSYS_ASSERT3U(index, <=, SIENA_MAX_SUPPORTED_MATCHES);
1606 list_length = index;
1608 *list_lengthp = list_length;
1610 if (buffer_length < list_length) {
1615 memcpy(buffer, rx_matches, list_length * sizeof (rx_matches[0]));
1620 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1625 #undef MAX_SUPPORTED
1627 #endif /* EFSYS_OPT_SIENA */
1629 #endif /* EFSYS_OPT_FILTER */