1 /* SPDX-License-Identifier: BSD-3-Clause
3 * Copyright (c) 2007-2018 Solarflare Communications Inc.
15 static __checkReturn efx_rc_t
23 static __checkReturn efx_rc_t
27 static __checkReturn efx_rc_t
30 __inout efx_filter_spec_t
*spec
,
31 __in boolean_t may_replace
);
33 static __checkReturn efx_rc_t
36 __inout efx_filter_spec_t
*spec
);
38 static __checkReturn efx_rc_t
39 siena_filter_supported_filters(
41 __out_ecount(buffer_length
) uint32_t *buffer
,
42 __in
size_t buffer_length
,
43 __out
size_t *list_lengthp
);
45 #endif /* EFSYS_OPT_SIENA */
48 static const efx_filter_ops_t __efx_filter_siena_ops
= {
49 siena_filter_init
, /* efo_init */
50 siena_filter_fini
, /* efo_fini */
51 siena_filter_restore
, /* efo_restore */
52 siena_filter_add
, /* efo_add */
53 siena_filter_delete
, /* efo_delete */
54 siena_filter_supported_filters
, /* efo_supported_filters */
55 NULL
, /* efo_reconfigure */
57 #endif /* EFSYS_OPT_SIENA */
60 static const efx_filter_ops_t __efx_filter_ef10_ops
= {
61 ef10_filter_init
, /* efo_init */
62 ef10_filter_fini
, /* efo_fini */
63 ef10_filter_restore
, /* efo_restore */
64 ef10_filter_add
, /* efo_add */
65 ef10_filter_delete
, /* efo_delete */
66 ef10_filter_supported_filters
, /* efo_supported_filters */
67 ef10_filter_reconfigure
, /* efo_reconfigure */
69 #endif /* EFX_OPTS_EF10() */
71 __checkReturn efx_rc_t
74 __inout efx_filter_spec_t
*spec
)
76 const efx_filter_ops_t
*efop
= enp
->en_efop
;
77 efx_nic_cfg_t
*encp
= &(enp
->en_nic_cfg
);
80 EFSYS_ASSERT3U(enp
->en_mod_flags
, &, EFX_MOD_FILTER
);
81 EFSYS_ASSERT3P(spec
, !=, NULL
);
82 EFSYS_ASSERT3U(spec
->efs_flags
, &, EFX_FILTER_FLAG_RX
);
84 if ((spec
->efs_flags
& EFX_FILTER_FLAG_ACTION_MARK
) &&
85 !encp
->enc_filter_action_mark_supported
) {
90 if ((spec
->efs_flags
& EFX_FILTER_FLAG_ACTION_FLAG
) &&
91 !encp
->enc_filter_action_flag_supported
) {
96 return (efop
->efo_add(enp
, spec
, B_FALSE
));
101 EFSYS_PROBE1(fail1
, efx_rc_t
, rc
);
106 __checkReturn efx_rc_t
109 __inout efx_filter_spec_t
*spec
)
111 const efx_filter_ops_t
*efop
= enp
->en_efop
;
113 EFSYS_ASSERT3U(enp
->en_mod_flags
, &, EFX_MOD_FILTER
);
114 EFSYS_ASSERT3P(spec
, !=, NULL
);
115 EFSYS_ASSERT3U(spec
->efs_flags
, &, EFX_FILTER_FLAG_RX
);
117 return (efop
->efo_delete(enp
, spec
));
120 __checkReturn efx_rc_t
126 EFSYS_ASSERT3U(enp
->en_mod_flags
, &, EFX_MOD_FILTER
);
128 if ((rc
= enp
->en_efop
->efo_restore(enp
)) != 0)
134 EFSYS_PROBE1(fail1
, efx_rc_t
, rc
);
139 __checkReturn efx_rc_t
143 const efx_filter_ops_t
*efop
;
146 EFSYS_ASSERT3U(enp
->en_magic
, ==, EFX_NIC_MAGIC
);
147 EFSYS_ASSERT3U(enp
->en_mod_flags
, &, EFX_MOD_PROBE
);
148 EFSYS_ASSERT(!(enp
->en_mod_flags
& EFX_MOD_FILTER
));
150 switch (enp
->en_family
) {
152 case EFX_FAMILY_SIENA
:
153 efop
= &__efx_filter_siena_ops
;
155 #endif /* EFSYS_OPT_SIENA */
157 #if EFSYS_OPT_HUNTINGTON
158 case EFX_FAMILY_HUNTINGTON
:
159 efop
= &__efx_filter_ef10_ops
;
161 #endif /* EFSYS_OPT_HUNTINGTON */
163 #if EFSYS_OPT_MEDFORD
164 case EFX_FAMILY_MEDFORD
:
165 efop
= &__efx_filter_ef10_ops
;
167 #endif /* EFSYS_OPT_MEDFORD */
169 #if EFSYS_OPT_MEDFORD2
170 case EFX_FAMILY_MEDFORD2
:
171 efop
= &__efx_filter_ef10_ops
;
173 #endif /* EFSYS_OPT_MEDFORD2 */
181 if ((rc
= efop
->efo_init(enp
)) != 0)
185 enp
->en_mod_flags
|= EFX_MOD_FILTER
;
191 EFSYS_PROBE1(fail1
, efx_rc_t
, rc
);
194 enp
->en_mod_flags
&= ~EFX_MOD_FILTER
;
202 EFSYS_ASSERT3U(enp
->en_magic
, ==, EFX_NIC_MAGIC
);
203 EFSYS_ASSERT3U(enp
->en_mod_flags
, &, EFX_MOD_PROBE
);
204 EFSYS_ASSERT3U(enp
->en_mod_flags
, &, EFX_MOD_FILTER
);
206 enp
->en_efop
->efo_fini(enp
);
209 enp
->en_mod_flags
&= ~EFX_MOD_FILTER
;
213 * Query the possible combinations of match flags which can be filtered on.
214 * These are returned as a list, of which each 32 bit element is a bitmask
215 * formed of EFX_FILTER_MATCH flags.
217 * The combinations are ordered in priority from highest to lowest.
219 * If the provided buffer is too short to hold the list, the call with fail with
220 * ENOSPC and *list_lengthp will be set to the buffer length required.
222 __checkReturn efx_rc_t
223 efx_filter_supported_filters(
225 __out_ecount(buffer_length
) uint32_t *buffer
,
226 __in
size_t buffer_length
,
227 __out
size_t *list_lengthp
)
231 EFSYS_ASSERT3U(enp
->en_magic
, ==, EFX_NIC_MAGIC
);
232 EFSYS_ASSERT3U(enp
->en_mod_flags
, &, EFX_MOD_PROBE
);
233 EFSYS_ASSERT3U(enp
->en_mod_flags
, &, EFX_MOD_FILTER
);
234 EFSYS_ASSERT(enp
->en_efop
->efo_supported_filters
!= NULL
);
236 if (buffer
== NULL
) {
241 rc
= enp
->en_efop
->efo_supported_filters(enp
, buffer
, buffer_length
,
251 EFSYS_PROBE1(fail1
, efx_rc_t
, rc
);
256 __checkReturn efx_rc_t
257 efx_filter_reconfigure(
259 __in_ecount(6) uint8_t const *mac_addr
,
260 __in boolean_t all_unicst
,
261 __in boolean_t mulcst
,
262 __in boolean_t all_mulcst
,
263 __in boolean_t brdcst
,
264 __in_ecount(6*count
) uint8_t const *addrs
,
269 EFSYS_ASSERT3U(enp
->en_magic
, ==, EFX_NIC_MAGIC
);
270 EFSYS_ASSERT3U(enp
->en_mod_flags
, &, EFX_MOD_PROBE
);
271 EFSYS_ASSERT3U(enp
->en_mod_flags
, &, EFX_MOD_FILTER
);
273 if (enp
->en_efop
->efo_reconfigure
!= NULL
) {
274 if ((rc
= enp
->en_efop
->efo_reconfigure(enp
, mac_addr
,
284 EFSYS_PROBE1(fail1
, efx_rc_t
, rc
);
290 efx_filter_spec_init_rx(
291 __out efx_filter_spec_t
*spec
,
292 __in efx_filter_priority_t priority
,
293 __in efx_filter_flags_t flags
,
296 EFSYS_ASSERT3P(spec
, !=, NULL
);
297 EFSYS_ASSERT3P(erp
, !=, NULL
);
298 EFSYS_ASSERT((flags
& ~(EFX_FILTER_FLAG_RX_RSS
|
299 EFX_FILTER_FLAG_RX_SCATTER
)) == 0);
301 memset(spec
, 0, sizeof (*spec
));
302 spec
->efs_priority
= priority
;
303 spec
->efs_flags
= EFX_FILTER_FLAG_RX
| flags
;
304 spec
->efs_rss_context
= EFX_RSS_CONTEXT_DEFAULT
;
305 spec
->efs_dmaq_id
= (uint16_t)erp
->er_index
;
309 efx_filter_spec_init_tx(
310 __out efx_filter_spec_t
*spec
,
313 EFSYS_ASSERT3P(spec
, !=, NULL
);
314 EFSYS_ASSERT3P(etp
, !=, NULL
);
316 memset(spec
, 0, sizeof (*spec
));
317 spec
->efs_priority
= EFX_FILTER_PRI_REQUIRED
;
318 spec
->efs_flags
= EFX_FILTER_FLAG_TX
;
319 spec
->efs_dmaq_id
= (uint16_t)etp
->et_index
;
324 * Specify IPv4 host, transport protocol and port in a filter specification
326 __checkReturn efx_rc_t
327 efx_filter_spec_set_ipv4_local(
328 __inout efx_filter_spec_t
*spec
,
333 EFSYS_ASSERT3P(spec
, !=, NULL
);
335 spec
->efs_match_flags
|=
336 EFX_FILTER_MATCH_ETHER_TYPE
| EFX_FILTER_MATCH_IP_PROTO
|
337 EFX_FILTER_MATCH_LOC_HOST
| EFX_FILTER_MATCH_LOC_PORT
;
338 spec
->efs_ether_type
= EFX_ETHER_TYPE_IPV4
;
339 spec
->efs_ip_proto
= proto
;
340 spec
->efs_loc_host
.eo_u32
[0] = host
;
341 spec
->efs_loc_port
= port
;
346 * Specify IPv4 hosts, transport protocol and ports in a filter specification
348 __checkReturn efx_rc_t
349 efx_filter_spec_set_ipv4_full(
350 __inout efx_filter_spec_t
*spec
,
357 EFSYS_ASSERT3P(spec
, !=, NULL
);
359 spec
->efs_match_flags
|=
360 EFX_FILTER_MATCH_ETHER_TYPE
| EFX_FILTER_MATCH_IP_PROTO
|
361 EFX_FILTER_MATCH_LOC_HOST
| EFX_FILTER_MATCH_LOC_PORT
|
362 EFX_FILTER_MATCH_REM_HOST
| EFX_FILTER_MATCH_REM_PORT
;
363 spec
->efs_ether_type
= EFX_ETHER_TYPE_IPV4
;
364 spec
->efs_ip_proto
= proto
;
365 spec
->efs_loc_host
.eo_u32
[0] = lhost
;
366 spec
->efs_loc_port
= lport
;
367 spec
->efs_rem_host
.eo_u32
[0] = rhost
;
368 spec
->efs_rem_port
= rport
;
373 * Specify local Ethernet address and/or VID in filter specification
375 __checkReturn efx_rc_t
376 efx_filter_spec_set_eth_local(
377 __inout efx_filter_spec_t
*spec
,
379 __in
const uint8_t *addr
)
381 EFSYS_ASSERT3P(spec
, !=, NULL
);
382 EFSYS_ASSERT3P(addr
, !=, NULL
);
384 if (vid
== EFX_FILTER_SPEC_VID_UNSPEC
&& addr
== NULL
)
387 if (vid
!= EFX_FILTER_SPEC_VID_UNSPEC
) {
388 spec
->efs_match_flags
|= EFX_FILTER_MATCH_OUTER_VID
;
389 spec
->efs_outer_vid
= vid
;
392 spec
->efs_match_flags
|= EFX_FILTER_MATCH_LOC_MAC
;
393 memcpy(spec
->efs_loc_mac
, addr
, EFX_MAC_ADDR_LEN
);
399 efx_filter_spec_set_ether_type(
400 __inout efx_filter_spec_t
*spec
,
401 __in
uint16_t ether_type
)
403 EFSYS_ASSERT3P(spec
, !=, NULL
);
405 spec
->efs_ether_type
= ether_type
;
406 spec
->efs_match_flags
|= EFX_FILTER_MATCH_ETHER_TYPE
;
410 * Specify matching otherwise-unmatched unicast in a filter specification
412 __checkReturn efx_rc_t
413 efx_filter_spec_set_uc_def(
414 __inout efx_filter_spec_t
*spec
)
416 EFSYS_ASSERT3P(spec
, !=, NULL
);
418 spec
->efs_match_flags
|= EFX_FILTER_MATCH_UNKNOWN_UCAST_DST
;
423 * Specify matching otherwise-unmatched multicast in a filter specification
425 __checkReturn efx_rc_t
426 efx_filter_spec_set_mc_def(
427 __inout efx_filter_spec_t
*spec
)
429 EFSYS_ASSERT3P(spec
, !=, NULL
);
431 spec
->efs_match_flags
|= EFX_FILTER_MATCH_UNKNOWN_MCAST_DST
;
436 __checkReturn efx_rc_t
437 efx_filter_spec_set_encap_type(
438 __inout efx_filter_spec_t
*spec
,
439 __in efx_tunnel_protocol_t encap_type
,
440 __in efx_filter_inner_frame_match_t inner_frame_match
)
442 uint32_t match_flags
= EFX_FILTER_MATCH_ENCAP_TYPE
;
446 EFSYS_ASSERT3P(spec
, !=, NULL
);
448 switch (encap_type
) {
449 case EFX_TUNNEL_PROTOCOL_VXLAN
:
450 case EFX_TUNNEL_PROTOCOL_GENEVE
:
451 ip_proto
= EFX_IPPROTO_UDP
;
453 case EFX_TUNNEL_PROTOCOL_NVGRE
:
454 ip_proto
= EFX_IPPROTO_GRE
;
462 switch (inner_frame_match
) {
463 case EFX_FILTER_INNER_FRAME_MATCH_UNKNOWN_MCAST_DST
:
464 match_flags
|= EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST
;
466 case EFX_FILTER_INNER_FRAME_MATCH_UNKNOWN_UCAST_DST
:
467 match_flags
|= EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST
;
469 case EFX_FILTER_INNER_FRAME_MATCH_OTHER
:
470 /* This is for when specific inner frames are to be matched. */
478 spec
->efs_encap_type
= encap_type
;
479 spec
->efs_ip_proto
= ip_proto
;
480 spec
->efs_match_flags
|= (match_flags
| EFX_FILTER_MATCH_IP_PROTO
);
487 EFSYS_PROBE1(fail1
, efx_rc_t
, rc
);
493 * Specify inner and outer Ethernet address and VNI or VSID in tunnel filter
496 static __checkReturn efx_rc_t
497 efx_filter_spec_set_tunnel(
498 __inout efx_filter_spec_t
*spec
,
499 __in efx_tunnel_protocol_t encap_type
,
500 __in
const uint8_t *vni_or_vsid
,
501 __in
const uint8_t *inner_addr
,
502 __in
const uint8_t *outer_addr
)
506 EFSYS_ASSERT3P(spec
, !=, NULL
);
507 EFSYS_ASSERT3P(vni_or_vsid
, !=, NULL
);
508 EFSYS_ASSERT3P(inner_addr
, !=, NULL
);
509 EFSYS_ASSERT3P(outer_addr
, !=, NULL
);
511 switch (encap_type
) {
512 case EFX_TUNNEL_PROTOCOL_VXLAN
:
513 case EFX_TUNNEL_PROTOCOL_GENEVE
:
514 case EFX_TUNNEL_PROTOCOL_NVGRE
:
521 if ((inner_addr
== NULL
) && (outer_addr
== NULL
)) {
526 if (vni_or_vsid
!= NULL
) {
527 spec
->efs_match_flags
|= EFX_FILTER_MATCH_VNI_OR_VSID
;
528 memcpy(spec
->efs_vni_or_vsid
, vni_or_vsid
, EFX_VNI_OR_VSID_LEN
);
530 if (outer_addr
!= NULL
) {
531 spec
->efs_match_flags
|= EFX_FILTER_MATCH_LOC_MAC
;
532 memcpy(spec
->efs_loc_mac
, outer_addr
, EFX_MAC_ADDR_LEN
);
534 if (inner_addr
!= NULL
) {
535 spec
->efs_match_flags
|= EFX_FILTER_MATCH_IFRM_LOC_MAC
;
536 memcpy(spec
->efs_ifrm_loc_mac
, inner_addr
, EFX_MAC_ADDR_LEN
);
539 spec
->efs_match_flags
|= EFX_FILTER_MATCH_ENCAP_TYPE
;
540 spec
->efs_encap_type
= encap_type
;
547 EFSYS_PROBE1(fail1
, efx_rc_t
, rc
);
553 * Specify inner and outer Ethernet address and VNI in VXLAN filter
556 __checkReturn efx_rc_t
557 efx_filter_spec_set_vxlan(
558 __inout efx_filter_spec_t
*spec
,
559 __in
const uint8_t *vni
,
560 __in
const uint8_t *inner_addr
,
561 __in
const uint8_t *outer_addr
)
563 return efx_filter_spec_set_tunnel(spec
, EFX_TUNNEL_PROTOCOL_VXLAN
,
564 vni
, inner_addr
, outer_addr
);
568 * Specify inner and outer Ethernet address and VNI in Geneve filter
571 __checkReturn efx_rc_t
572 efx_filter_spec_set_geneve(
573 __inout efx_filter_spec_t
*spec
,
574 __in
const uint8_t *vni
,
575 __in
const uint8_t *inner_addr
,
576 __in
const uint8_t *outer_addr
)
578 return efx_filter_spec_set_tunnel(spec
, EFX_TUNNEL_PROTOCOL_GENEVE
,
579 vni
, inner_addr
, outer_addr
);
583 * Specify inner and outer Ethernet address and vsid in NVGRE filter
586 __checkReturn efx_rc_t
587 efx_filter_spec_set_nvgre(
588 __inout efx_filter_spec_t
*spec
,
589 __in
const uint8_t *vsid
,
590 __in
const uint8_t *inner_addr
,
591 __in
const uint8_t *outer_addr
)
593 return efx_filter_spec_set_tunnel(spec
, EFX_TUNNEL_PROTOCOL_NVGRE
,
594 vsid
, inner_addr
, outer_addr
);
597 #if EFSYS_OPT_RX_SCALE
598 __checkReturn efx_rc_t
599 efx_filter_spec_set_rss_context(
600 __inout efx_filter_spec_t
*spec
,
601 __in
uint32_t rss_context
)
605 EFSYS_ASSERT3P(spec
, !=, NULL
);
607 /* The filter must have been created with EFX_FILTER_FLAG_RX_RSS. */
608 if ((spec
->efs_flags
& EFX_FILTER_FLAG_RX_RSS
) == 0) {
613 spec
->efs_rss_context
= rss_context
;
618 EFSYS_PROBE1(fail1
, efx_rc_t
, rc
);
627 * "Fudge factors" - difference between programmed value and actual depth.
628 * Due to pipelined implementation we need to program H/W with a value that
629 * is larger than the hop limit we want.
631 #define FILTER_CTL_SRCH_FUDGE_WILD 3
632 #define FILTER_CTL_SRCH_FUDGE_FULL 1
635 * Hard maximum hop limit. Hardware will time-out beyond 200-something.
636 * We also need to avoid infinite loops in efx_filter_search() when the
639 #define FILTER_CTL_SRCH_MAX 200
641 static __checkReturn efx_rc_t
642 siena_filter_spec_from_gen_spec(
643 __out siena_filter_spec_t
*sf_spec
,
644 __in efx_filter_spec_t
*gen_spec
)
647 boolean_t is_full
= B_FALSE
;
649 if (gen_spec
->efs_flags
& EFX_FILTER_FLAG_TX
)
650 EFSYS_ASSERT3U(gen_spec
->efs_flags
, ==, EFX_FILTER_FLAG_TX
);
652 EFSYS_ASSERT3U(gen_spec
->efs_flags
, &, EFX_FILTER_FLAG_RX
);
654 /* Siena only has one RSS context */
655 if ((gen_spec
->efs_flags
& EFX_FILTER_FLAG_RX_RSS
) &&
656 gen_spec
->efs_rss_context
!= EFX_RSS_CONTEXT_DEFAULT
) {
661 sf_spec
->sfs_flags
= gen_spec
->efs_flags
;
662 sf_spec
->sfs_dmaq_id
= gen_spec
->efs_dmaq_id
;
664 switch (gen_spec
->efs_match_flags
) {
665 case EFX_FILTER_MATCH_ETHER_TYPE
| EFX_FILTER_MATCH_IP_PROTO
|
666 EFX_FILTER_MATCH_LOC_HOST
| EFX_FILTER_MATCH_LOC_PORT
|
667 EFX_FILTER_MATCH_REM_HOST
| EFX_FILTER_MATCH_REM_PORT
:
670 case EFX_FILTER_MATCH_ETHER_TYPE
| EFX_FILTER_MATCH_IP_PROTO
|
671 EFX_FILTER_MATCH_LOC_HOST
| EFX_FILTER_MATCH_LOC_PORT
: {
672 uint32_t rhost
, host1
, host2
;
673 uint16_t rport
, port1
, port2
;
675 if (gen_spec
->efs_ether_type
!= EFX_ETHER_TYPE_IPV4
) {
679 if (gen_spec
->efs_loc_port
== 0 ||
680 (is_full
&& gen_spec
->efs_rem_port
== 0)) {
684 switch (gen_spec
->efs_ip_proto
) {
685 case EFX_IPPROTO_TCP
:
686 if (gen_spec
->efs_flags
& EFX_FILTER_FLAG_TX
) {
687 sf_spec
->sfs_type
= (is_full
?
688 EFX_SIENA_FILTER_TX_TCP_FULL
:
689 EFX_SIENA_FILTER_TX_TCP_WILD
);
691 sf_spec
->sfs_type
= (is_full
?
692 EFX_SIENA_FILTER_RX_TCP_FULL
:
693 EFX_SIENA_FILTER_RX_TCP_WILD
);
696 case EFX_IPPROTO_UDP
:
697 if (gen_spec
->efs_flags
& EFX_FILTER_FLAG_TX
) {
698 sf_spec
->sfs_type
= (is_full
?
699 EFX_SIENA_FILTER_TX_UDP_FULL
:
700 EFX_SIENA_FILTER_TX_UDP_WILD
);
702 sf_spec
->sfs_type
= (is_full
?
703 EFX_SIENA_FILTER_RX_UDP_FULL
:
704 EFX_SIENA_FILTER_RX_UDP_WILD
);
712 * The filter is constructed in terms of source and destination,
713 * with the odd wrinkle that the ports are swapped in a UDP
714 * wildcard filter. We need to convert from local and remote
715 * addresses (zero for a wildcard).
717 rhost
= is_full
? gen_spec
->efs_rem_host
.eo_u32
[0] : 0;
718 rport
= is_full
? gen_spec
->efs_rem_port
: 0;
719 if (gen_spec
->efs_flags
& EFX_FILTER_FLAG_TX
) {
720 host1
= gen_spec
->efs_loc_host
.eo_u32
[0];
724 host2
= gen_spec
->efs_loc_host
.eo_u32
[0];
726 if (gen_spec
->efs_flags
& EFX_FILTER_FLAG_TX
) {
727 if (sf_spec
->sfs_type
==
728 EFX_SIENA_FILTER_TX_UDP_WILD
) {
730 port2
= gen_spec
->efs_loc_port
;
732 port1
= gen_spec
->efs_loc_port
;
736 if (sf_spec
->sfs_type
==
737 EFX_SIENA_FILTER_RX_UDP_WILD
) {
738 port1
= gen_spec
->efs_loc_port
;
742 port2
= gen_spec
->efs_loc_port
;
745 sf_spec
->sfs_dword
[0] = (host1
<< 16) | port1
;
746 sf_spec
->sfs_dword
[1] = (port2
<< 16) | (host1
>> 16);
747 sf_spec
->sfs_dword
[2] = host2
;
751 case EFX_FILTER_MATCH_LOC_MAC
| EFX_FILTER_MATCH_OUTER_VID
:
754 case EFX_FILTER_MATCH_LOC_MAC
:
755 if (gen_spec
->efs_flags
& EFX_FILTER_FLAG_TX
) {
756 sf_spec
->sfs_type
= (is_full
?
757 EFX_SIENA_FILTER_TX_MAC_FULL
:
758 EFX_SIENA_FILTER_TX_MAC_WILD
);
760 sf_spec
->sfs_type
= (is_full
?
761 EFX_SIENA_FILTER_RX_MAC_FULL
:
762 EFX_SIENA_FILTER_RX_MAC_WILD
);
764 sf_spec
->sfs_dword
[0] = is_full
? gen_spec
->efs_outer_vid
: 0;
765 sf_spec
->sfs_dword
[1] =
766 gen_spec
->efs_loc_mac
[2] << 24 |
767 gen_spec
->efs_loc_mac
[3] << 16 |
768 gen_spec
->efs_loc_mac
[4] << 8 |
769 gen_spec
->efs_loc_mac
[5];
770 sf_spec
->sfs_dword
[2] =
771 gen_spec
->efs_loc_mac
[0] << 8 |
772 gen_spec
->efs_loc_mac
[1];
776 EFSYS_ASSERT(B_FALSE
);
792 EFSYS_PROBE1(fail1
, efx_rc_t
, rc
);
798 * The filter hash function is LFSR polynomial x^16 + x^3 + 1 of a 32-bit
799 * key derived from the n-tuple.
802 siena_filter_tbl_hash(
807 /* First 16 rounds */
808 tmp
= 0x1fff ^ (uint16_t)(key
>> 16);
809 tmp
= tmp
^ tmp
>> 3 ^ tmp
>> 6;
810 tmp
= tmp
^ tmp
>> 9;
813 tmp
= tmp
^ tmp
<< 13 ^ (uint16_t)(key
& 0xffff);
814 tmp
= tmp
^ tmp
>> 3 ^ tmp
>> 6;
815 tmp
= tmp
^ tmp
>> 9;
821 * To allow for hash collisions, filter search continues at these
822 * increments from the first possible entry selected by the hash.
825 siena_filter_tbl_increment(
828 return ((uint16_t)(key
* 2 - 1));
831 static __checkReturn boolean_t
832 siena_filter_test_used(
833 __in siena_filter_tbl_t
*sftp
,
834 __in
unsigned int index
)
836 EFSYS_ASSERT3P(sftp
->sft_bitmap
, !=, NULL
);
837 return ((sftp
->sft_bitmap
[index
/ 32] & (1 << (index
% 32))) != 0);
841 siena_filter_set_used(
842 __in siena_filter_tbl_t
*sftp
,
843 __in
unsigned int index
)
845 EFSYS_ASSERT3P(sftp
->sft_bitmap
, !=, NULL
);
846 sftp
->sft_bitmap
[index
/ 32] |= (1 << (index
% 32));
851 siena_filter_clear_used(
852 __in siena_filter_tbl_t
*sftp
,
853 __in
unsigned int index
)
855 EFSYS_ASSERT3P(sftp
->sft_bitmap
, !=, NULL
);
856 sftp
->sft_bitmap
[index
/ 32] &= ~(1 << (index
% 32));
859 EFSYS_ASSERT3U(sftp
->sft_used
, >=, 0);
863 static siena_filter_tbl_id_t
865 __in siena_filter_type_t type
)
867 siena_filter_tbl_id_t tbl_id
;
870 case EFX_SIENA_FILTER_RX_TCP_FULL
:
871 case EFX_SIENA_FILTER_RX_TCP_WILD
:
872 case EFX_SIENA_FILTER_RX_UDP_FULL
:
873 case EFX_SIENA_FILTER_RX_UDP_WILD
:
874 tbl_id
= EFX_SIENA_FILTER_TBL_RX_IP
;
877 case EFX_SIENA_FILTER_RX_MAC_FULL
:
878 case EFX_SIENA_FILTER_RX_MAC_WILD
:
879 tbl_id
= EFX_SIENA_FILTER_TBL_RX_MAC
;
882 case EFX_SIENA_FILTER_TX_TCP_FULL
:
883 case EFX_SIENA_FILTER_TX_TCP_WILD
:
884 case EFX_SIENA_FILTER_TX_UDP_FULL
:
885 case EFX_SIENA_FILTER_TX_UDP_WILD
:
886 tbl_id
= EFX_SIENA_FILTER_TBL_TX_IP
;
889 case EFX_SIENA_FILTER_TX_MAC_FULL
:
890 case EFX_SIENA_FILTER_TX_MAC_WILD
:
891 tbl_id
= EFX_SIENA_FILTER_TBL_TX_MAC
;
895 EFSYS_ASSERT(B_FALSE
);
896 tbl_id
= EFX_SIENA_FILTER_NTBLS
;
903 siena_filter_reset_search_depth(
904 __inout siena_filter_t
*sfp
,
905 __in siena_filter_tbl_id_t tbl_id
)
908 case EFX_SIENA_FILTER_TBL_RX_IP
:
909 sfp
->sf_depth
[EFX_SIENA_FILTER_RX_TCP_FULL
] = 0;
910 sfp
->sf_depth
[EFX_SIENA_FILTER_RX_TCP_WILD
] = 0;
911 sfp
->sf_depth
[EFX_SIENA_FILTER_RX_UDP_FULL
] = 0;
912 sfp
->sf_depth
[EFX_SIENA_FILTER_RX_UDP_WILD
] = 0;
915 case EFX_SIENA_FILTER_TBL_RX_MAC
:
916 sfp
->sf_depth
[EFX_SIENA_FILTER_RX_MAC_FULL
] = 0;
917 sfp
->sf_depth
[EFX_SIENA_FILTER_RX_MAC_WILD
] = 0;
920 case EFX_SIENA_FILTER_TBL_TX_IP
:
921 sfp
->sf_depth
[EFX_SIENA_FILTER_TX_TCP_FULL
] = 0;
922 sfp
->sf_depth
[EFX_SIENA_FILTER_TX_TCP_WILD
] = 0;
923 sfp
->sf_depth
[EFX_SIENA_FILTER_TX_UDP_FULL
] = 0;
924 sfp
->sf_depth
[EFX_SIENA_FILTER_TX_UDP_WILD
] = 0;
927 case EFX_SIENA_FILTER_TBL_TX_MAC
:
928 sfp
->sf_depth
[EFX_SIENA_FILTER_TX_MAC_FULL
] = 0;
929 sfp
->sf_depth
[EFX_SIENA_FILTER_TX_MAC_WILD
] = 0;
933 EFSYS_ASSERT(B_FALSE
);
939 siena_filter_push_rx_limits(
942 siena_filter_t
*sfp
= enp
->en_filter
.ef_siena_filter
;
945 EFX_BAR_READO(enp
, FR_AZ_RX_FILTER_CTL_REG
, &oword
);
947 EFX_SET_OWORD_FIELD(oword
, FRF_AZ_TCP_FULL_SRCH_LIMIT
,
948 sfp
->sf_depth
[EFX_SIENA_FILTER_RX_TCP_FULL
] +
949 FILTER_CTL_SRCH_FUDGE_FULL
);
950 EFX_SET_OWORD_FIELD(oword
, FRF_AZ_TCP_WILD_SRCH_LIMIT
,
951 sfp
->sf_depth
[EFX_SIENA_FILTER_RX_TCP_WILD
] +
952 FILTER_CTL_SRCH_FUDGE_WILD
);
953 EFX_SET_OWORD_FIELD(oword
, FRF_AZ_UDP_FULL_SRCH_LIMIT
,
954 sfp
->sf_depth
[EFX_SIENA_FILTER_RX_UDP_FULL
] +
955 FILTER_CTL_SRCH_FUDGE_FULL
);
956 EFX_SET_OWORD_FIELD(oword
, FRF_AZ_UDP_WILD_SRCH_LIMIT
,
957 sfp
->sf_depth
[EFX_SIENA_FILTER_RX_UDP_WILD
] +
958 FILTER_CTL_SRCH_FUDGE_WILD
);
960 if (sfp
->sf_tbl
[EFX_SIENA_FILTER_TBL_RX_MAC
].sft_size
) {
961 EFX_SET_OWORD_FIELD(oword
,
962 FRF_CZ_ETHERNET_FULL_SEARCH_LIMIT
,
963 sfp
->sf_depth
[EFX_SIENA_FILTER_RX_MAC_FULL
] +
964 FILTER_CTL_SRCH_FUDGE_FULL
);
965 EFX_SET_OWORD_FIELD(oword
,
966 FRF_CZ_ETHERNET_WILDCARD_SEARCH_LIMIT
,
967 sfp
->sf_depth
[EFX_SIENA_FILTER_RX_MAC_WILD
] +
968 FILTER_CTL_SRCH_FUDGE_WILD
);
971 EFX_BAR_WRITEO(enp
, FR_AZ_RX_FILTER_CTL_REG
, &oword
);
975 siena_filter_push_tx_limits(
978 siena_filter_t
*sfp
= enp
->en_filter
.ef_siena_filter
;
981 EFX_BAR_READO(enp
, FR_AZ_TX_CFG_REG
, &oword
);
983 if (sfp
->sf_tbl
[EFX_SIENA_FILTER_TBL_TX_IP
].sft_size
!= 0) {
984 EFX_SET_OWORD_FIELD(oword
,
985 FRF_CZ_TX_TCPIP_FILTER_FULL_SEARCH_RANGE
,
986 sfp
->sf_depth
[EFX_SIENA_FILTER_TX_TCP_FULL
] +
987 FILTER_CTL_SRCH_FUDGE_FULL
);
988 EFX_SET_OWORD_FIELD(oword
,
989 FRF_CZ_TX_TCPIP_FILTER_WILD_SEARCH_RANGE
,
990 sfp
->sf_depth
[EFX_SIENA_FILTER_TX_TCP_WILD
] +
991 FILTER_CTL_SRCH_FUDGE_WILD
);
992 EFX_SET_OWORD_FIELD(oword
,
993 FRF_CZ_TX_UDPIP_FILTER_FULL_SEARCH_RANGE
,
994 sfp
->sf_depth
[EFX_SIENA_FILTER_TX_UDP_FULL
] +
995 FILTER_CTL_SRCH_FUDGE_FULL
);
996 EFX_SET_OWORD_FIELD(oword
,
997 FRF_CZ_TX_UDPIP_FILTER_WILD_SEARCH_RANGE
,
998 sfp
->sf_depth
[EFX_SIENA_FILTER_TX_UDP_WILD
] +
999 FILTER_CTL_SRCH_FUDGE_WILD
);
1002 if (sfp
->sf_tbl
[EFX_SIENA_FILTER_TBL_TX_MAC
].sft_size
!= 0) {
1003 EFX_SET_OWORD_FIELD(
1004 oword
, FRF_CZ_TX_ETH_FILTER_FULL_SEARCH_RANGE
,
1005 sfp
->sf_depth
[EFX_SIENA_FILTER_TX_MAC_FULL
] +
1006 FILTER_CTL_SRCH_FUDGE_FULL
);
1007 EFX_SET_OWORD_FIELD(
1008 oword
, FRF_CZ_TX_ETH_FILTER_WILD_SEARCH_RANGE
,
1009 sfp
->sf_depth
[EFX_SIENA_FILTER_TX_MAC_WILD
] +
1010 FILTER_CTL_SRCH_FUDGE_WILD
);
1013 EFX_BAR_WRITEO(enp
, FR_AZ_TX_CFG_REG
, &oword
);
1016 /* Build a filter entry and return its n-tuple key. */
1017 static __checkReturn
uint32_t
1019 __out efx_oword_t
*filter
,
1020 __in siena_filter_spec_t
*spec
)
1024 uint8_t type
= spec
->sfs_type
;
1025 uint32_t flags
= spec
->sfs_flags
;
1027 switch (siena_filter_tbl_id(type
)) {
1028 case EFX_SIENA_FILTER_TBL_RX_IP
: {
1029 boolean_t is_udp
= (type
== EFX_SIENA_FILTER_RX_UDP_FULL
||
1030 type
== EFX_SIENA_FILTER_RX_UDP_WILD
);
1031 EFX_POPULATE_OWORD_7(*filter
,
1033 (flags
& EFX_FILTER_FLAG_RX_RSS
) ? 1 : 0,
1035 (flags
& EFX_FILTER_FLAG_RX_SCATTER
) ? 1 : 0,
1036 FRF_AZ_TCP_UDP
, is_udp
,
1037 FRF_AZ_RXQ_ID
, spec
->sfs_dmaq_id
,
1038 EFX_DWORD_2
, spec
->sfs_dword
[2],
1039 EFX_DWORD_1
, spec
->sfs_dword
[1],
1040 EFX_DWORD_0
, spec
->sfs_dword
[0]);
1045 case EFX_SIENA_FILTER_TBL_RX_MAC
: {
1046 boolean_t is_wild
= (type
== EFX_SIENA_FILTER_RX_MAC_WILD
);
1047 EFX_POPULATE_OWORD_7(*filter
,
1049 (flags
& EFX_FILTER_FLAG_RX_RSS
) ? 1 : 0,
1050 FRF_CZ_RMFT_SCATTER_EN
,
1051 (flags
& EFX_FILTER_FLAG_RX_SCATTER
) ? 1 : 0,
1052 FRF_CZ_RMFT_RXQ_ID
, spec
->sfs_dmaq_id
,
1053 FRF_CZ_RMFT_WILDCARD_MATCH
, is_wild
,
1054 FRF_CZ_RMFT_DEST_MAC_DW1
, spec
->sfs_dword
[2],
1055 FRF_CZ_RMFT_DEST_MAC_DW0
, spec
->sfs_dword
[1],
1056 FRF_CZ_RMFT_VLAN_ID
, spec
->sfs_dword
[0]);
1061 case EFX_SIENA_FILTER_TBL_TX_IP
: {
1062 boolean_t is_udp
= (type
== EFX_SIENA_FILTER_TX_UDP_FULL
||
1063 type
== EFX_SIENA_FILTER_TX_UDP_WILD
);
1064 EFX_POPULATE_OWORD_5(*filter
,
1065 FRF_CZ_TIFT_TCP_UDP
, is_udp
,
1066 FRF_CZ_TIFT_TXQ_ID
, spec
->sfs_dmaq_id
,
1067 EFX_DWORD_2
, spec
->sfs_dword
[2],
1068 EFX_DWORD_1
, spec
->sfs_dword
[1],
1069 EFX_DWORD_0
, spec
->sfs_dword
[0]);
1070 dword3
= is_udp
| spec
->sfs_dmaq_id
<< 1;
1074 case EFX_SIENA_FILTER_TBL_TX_MAC
: {
1075 boolean_t is_wild
= (type
== EFX_SIENA_FILTER_TX_MAC_WILD
);
1076 EFX_POPULATE_OWORD_5(*filter
,
1077 FRF_CZ_TMFT_TXQ_ID
, spec
->sfs_dmaq_id
,
1078 FRF_CZ_TMFT_WILDCARD_MATCH
, is_wild
,
1079 FRF_CZ_TMFT_SRC_MAC_DW1
, spec
->sfs_dword
[2],
1080 FRF_CZ_TMFT_SRC_MAC_DW0
, spec
->sfs_dword
[1],
1081 FRF_CZ_TMFT_VLAN_ID
, spec
->sfs_dword
[0]);
1082 dword3
= is_wild
| spec
->sfs_dmaq_id
<< 1;
1087 EFSYS_ASSERT(B_FALSE
);
1088 EFX_ZERO_OWORD(*filter
);
1093 spec
->sfs_dword
[0] ^
1094 spec
->sfs_dword
[1] ^
1095 spec
->sfs_dword
[2] ^
1101 static __checkReturn efx_rc_t
1102 siena_filter_push_entry(
1103 __inout efx_nic_t
*enp
,
1104 __in siena_filter_type_t type
,
1106 __in efx_oword_t
*eop
)
1111 case EFX_SIENA_FILTER_RX_TCP_FULL
:
1112 case EFX_SIENA_FILTER_RX_TCP_WILD
:
1113 case EFX_SIENA_FILTER_RX_UDP_FULL
:
1114 case EFX_SIENA_FILTER_RX_UDP_WILD
:
1115 EFX_BAR_TBL_WRITEO(enp
, FR_AZ_RX_FILTER_TBL0
, index
,
1119 case EFX_SIENA_FILTER_RX_MAC_FULL
:
1120 case EFX_SIENA_FILTER_RX_MAC_WILD
:
1121 EFX_BAR_TBL_WRITEO(enp
, FR_CZ_RX_MAC_FILTER_TBL0
, index
,
1125 case EFX_SIENA_FILTER_TX_TCP_FULL
:
1126 case EFX_SIENA_FILTER_TX_TCP_WILD
:
1127 case EFX_SIENA_FILTER_TX_UDP_FULL
:
1128 case EFX_SIENA_FILTER_TX_UDP_WILD
:
1129 EFX_BAR_TBL_WRITEO(enp
, FR_CZ_TX_FILTER_TBL0
, index
,
1133 case EFX_SIENA_FILTER_TX_MAC_FULL
:
1134 case EFX_SIENA_FILTER_TX_MAC_WILD
:
1135 EFX_BAR_TBL_WRITEO(enp
, FR_CZ_TX_MAC_FILTER_TBL0
, index
,
1140 EFSYS_ASSERT(B_FALSE
);
1151 static __checkReturn boolean_t
1153 __in
const siena_filter_spec_t
*left
,
1154 __in
const siena_filter_spec_t
*right
)
1156 siena_filter_tbl_id_t tbl_id
;
1158 tbl_id
= siena_filter_tbl_id(left
->sfs_type
);
1161 if (left
->sfs_type
!= right
->sfs_type
)
1164 if (memcmp(left
->sfs_dword
, right
->sfs_dword
,
1165 sizeof (left
->sfs_dword
)))
1168 if ((tbl_id
== EFX_SIENA_FILTER_TBL_TX_IP
||
1169 tbl_id
== EFX_SIENA_FILTER_TBL_TX_MAC
) &&
1170 left
->sfs_dmaq_id
!= right
->sfs_dmaq_id
)
1176 static __checkReturn efx_rc_t
1177 siena_filter_search(
1178 __in siena_filter_tbl_t
*sftp
,
1179 __in siena_filter_spec_t
*spec
,
1181 __in boolean_t for_insert
,
1182 __out
int *filter_index
,
1183 __out
unsigned int *depth_required
)
1185 unsigned int hash
, incr
, filter_idx
, depth
;
1187 hash
= siena_filter_tbl_hash(key
);
1188 incr
= siena_filter_tbl_increment(key
);
1190 filter_idx
= hash
& (sftp
->sft_size
- 1);
1195 * Return success if entry is used and matches this spec
1196 * or entry is unused and we are trying to insert.
1198 if (siena_filter_test_used(sftp
, filter_idx
) ?
1199 siena_filter_equal(spec
,
1200 &sftp
->sft_spec
[filter_idx
]) :
1202 *filter_index
= filter_idx
;
1203 *depth_required
= depth
;
1207 /* Return failure if we reached the maximum search depth */
1208 if (depth
== FILTER_CTL_SRCH_MAX
)
1209 return (for_insert
? EBUSY
: ENOENT
);
1211 filter_idx
= (filter_idx
+ incr
) & (sftp
->sft_size
- 1);
1217 siena_filter_clear_entry(
1218 __in efx_nic_t
*enp
,
1219 __in siena_filter_tbl_t
*sftp
,
1224 if (siena_filter_test_used(sftp
, index
)) {
1225 siena_filter_clear_used(sftp
, index
);
1227 EFX_ZERO_OWORD(filter
);
1228 siena_filter_push_entry(enp
,
1229 sftp
->sft_spec
[index
].sfs_type
,
1232 memset(&sftp
->sft_spec
[index
],
1233 0, sizeof (sftp
->sft_spec
[0]));
1238 siena_filter_tbl_clear(
1239 __in efx_nic_t
*enp
,
1240 __in siena_filter_tbl_id_t tbl_id
)
1242 siena_filter_t
*sfp
= enp
->en_filter
.ef_siena_filter
;
1243 siena_filter_tbl_t
*sftp
= &sfp
->sf_tbl
[tbl_id
];
1245 efsys_lock_state_t state
;
1247 EFSYS_LOCK(enp
->en_eslp
, state
);
1249 for (index
= 0; index
< sftp
->sft_size
; ++index
) {
1250 siena_filter_clear_entry(enp
, sftp
, index
);
1253 if (sftp
->sft_used
== 0)
1254 siena_filter_reset_search_depth(sfp
, tbl_id
);
1256 EFSYS_UNLOCK(enp
->en_eslp
, state
);
1259 static __checkReturn efx_rc_t
1261 __in efx_nic_t
*enp
)
1263 siena_filter_t
*sfp
;
1264 siena_filter_tbl_t
*sftp
;
1268 EFSYS_KMEM_ALLOC(enp
->en_esip
, sizeof (siena_filter_t
), sfp
);
1275 enp
->en_filter
.ef_siena_filter
= sfp
;
1277 switch (enp
->en_family
) {
1278 case EFX_FAMILY_SIENA
:
1279 sftp
= &sfp
->sf_tbl
[EFX_SIENA_FILTER_TBL_RX_IP
];
1280 sftp
->sft_size
= FR_AZ_RX_FILTER_TBL0_ROWS
;
1282 sftp
= &sfp
->sf_tbl
[EFX_SIENA_FILTER_TBL_RX_MAC
];
1283 sftp
->sft_size
= FR_CZ_RX_MAC_FILTER_TBL0_ROWS
;
1285 sftp
= &sfp
->sf_tbl
[EFX_SIENA_FILTER_TBL_TX_IP
];
1286 sftp
->sft_size
= FR_CZ_TX_FILTER_TBL0_ROWS
;
1288 sftp
= &sfp
->sf_tbl
[EFX_SIENA_FILTER_TBL_TX_MAC
];
1289 sftp
->sft_size
= FR_CZ_TX_MAC_FILTER_TBL0_ROWS
;
1297 for (tbl_id
= 0; tbl_id
< EFX_SIENA_FILTER_NTBLS
; tbl_id
++) {
1298 unsigned int bitmap_size
;
1300 sftp
= &sfp
->sf_tbl
[tbl_id
];
1301 if (sftp
->sft_size
== 0)
1304 EFX_STATIC_ASSERT(sizeof (sftp
->sft_bitmap
[0]) ==
1307 (sftp
->sft_size
+ (sizeof (uint32_t) * 8) - 1) / 8;
1309 EFSYS_KMEM_ALLOC(enp
->en_esip
, bitmap_size
, sftp
->sft_bitmap
);
1310 if (!sftp
->sft_bitmap
) {
1315 EFSYS_KMEM_ALLOC(enp
->en_esip
,
1316 sftp
->sft_size
* sizeof (*sftp
->sft_spec
),
1318 if (!sftp
->sft_spec
) {
1322 memset(sftp
->sft_spec
, 0,
1323 sftp
->sft_size
* sizeof (*sftp
->sft_spec
));
1336 siena_filter_fini(enp
);
1339 EFSYS_PROBE1(fail1
, efx_rc_t
, rc
);
1345 __in efx_nic_t
*enp
)
1347 siena_filter_t
*sfp
= enp
->en_filter
.ef_siena_filter
;
1348 siena_filter_tbl_id_t tbl_id
;
1350 EFSYS_ASSERT3U(enp
->en_magic
, ==, EFX_NIC_MAGIC
);
1351 EFSYS_ASSERT3U(enp
->en_mod_flags
, &, EFX_MOD_PROBE
);
1356 for (tbl_id
= 0; tbl_id
< EFX_SIENA_FILTER_NTBLS
; tbl_id
++) {
1357 siena_filter_tbl_t
*sftp
= &sfp
->sf_tbl
[tbl_id
];
1358 unsigned int bitmap_size
;
1360 EFX_STATIC_ASSERT(sizeof (sftp
->sft_bitmap
[0]) ==
1363 (sftp
->sft_size
+ (sizeof (uint32_t) * 8) - 1) / 8;
1365 if (sftp
->sft_bitmap
!= NULL
) {
1366 EFSYS_KMEM_FREE(enp
->en_esip
, bitmap_size
,
1368 sftp
->sft_bitmap
= NULL
;
1371 if (sftp
->sft_spec
!= NULL
) {
1372 EFSYS_KMEM_FREE(enp
->en_esip
, sftp
->sft_size
*
1373 sizeof (*sftp
->sft_spec
), sftp
->sft_spec
);
1374 sftp
->sft_spec
= NULL
;
1378 EFSYS_KMEM_FREE(enp
->en_esip
, sizeof (siena_filter_t
),
1379 enp
->en_filter
.ef_siena_filter
);
1382 /* Restore filter state after a reset */
1383 static __checkReturn efx_rc_t
1384 siena_filter_restore(
1385 __in efx_nic_t
*enp
)
1387 siena_filter_t
*sfp
= enp
->en_filter
.ef_siena_filter
;
1388 siena_filter_tbl_id_t tbl_id
;
1389 siena_filter_tbl_t
*sftp
;
1390 siena_filter_spec_t
*spec
;
1393 efsys_lock_state_t state
;
1397 EFSYS_LOCK(enp
->en_eslp
, state
);
1399 for (tbl_id
= 0; tbl_id
< EFX_SIENA_FILTER_NTBLS
; tbl_id
++) {
1400 sftp
= &sfp
->sf_tbl
[tbl_id
];
1401 for (filter_idx
= 0;
1402 filter_idx
< sftp
->sft_size
;
1404 if (!siena_filter_test_used(sftp
, filter_idx
))
1407 spec
= &sftp
->sft_spec
[filter_idx
];
1408 if ((key
= siena_filter_build(&filter
, spec
)) == 0) {
1412 if ((rc
= siena_filter_push_entry(enp
,
1413 spec
->sfs_type
, filter_idx
, &filter
)) != 0)
1418 siena_filter_push_rx_limits(enp
);
1419 siena_filter_push_tx_limits(enp
);
1421 EFSYS_UNLOCK(enp
->en_eslp
, state
);
1429 EFSYS_PROBE1(fail1
, efx_rc_t
, rc
);
1431 EFSYS_UNLOCK(enp
->en_eslp
, state
);
1436 static __checkReturn efx_rc_t
1438 __in efx_nic_t
*enp
,
1439 __inout efx_filter_spec_t
*spec
,
1440 __in boolean_t may_replace
)
1443 siena_filter_spec_t sf_spec
;
1444 siena_filter_t
*sfp
= enp
->en_filter
.ef_siena_filter
;
1445 siena_filter_tbl_id_t tbl_id
;
1446 siena_filter_tbl_t
*sftp
;
1447 siena_filter_spec_t
*saved_sf_spec
;
1451 efsys_lock_state_t state
;
1455 EFSYS_ASSERT3P(spec
, !=, NULL
);
1457 if ((rc
= siena_filter_spec_from_gen_spec(&sf_spec
, spec
)) != 0)
1460 tbl_id
= siena_filter_tbl_id(sf_spec
.sfs_type
);
1461 sftp
= &sfp
->sf_tbl
[tbl_id
];
1463 if (sftp
->sft_size
== 0) {
1468 key
= siena_filter_build(&filter
, &sf_spec
);
1470 EFSYS_LOCK(enp
->en_eslp
, state
);
1472 rc
= siena_filter_search(sftp
, &sf_spec
, key
, B_TRUE
,
1473 &filter_idx
, &depth
);
1477 EFSYS_ASSERT3U(filter_idx
, <, sftp
->sft_size
);
1478 saved_sf_spec
= &sftp
->sft_spec
[filter_idx
];
1480 if (siena_filter_test_used(sftp
, filter_idx
)) {
1481 if (may_replace
== B_FALSE
) {
1486 siena_filter_set_used(sftp
, filter_idx
);
1487 *saved_sf_spec
= sf_spec
;
1489 if (sfp
->sf_depth
[sf_spec
.sfs_type
] < depth
) {
1490 sfp
->sf_depth
[sf_spec
.sfs_type
] = depth
;
1491 if (tbl_id
== EFX_SIENA_FILTER_TBL_TX_IP
||
1492 tbl_id
== EFX_SIENA_FILTER_TBL_TX_MAC
)
1493 siena_filter_push_tx_limits(enp
);
1495 siena_filter_push_rx_limits(enp
);
1498 siena_filter_push_entry(enp
, sf_spec
.sfs_type
,
1499 filter_idx
, &filter
);
1501 EFSYS_UNLOCK(enp
->en_eslp
, state
);
1508 EFSYS_UNLOCK(enp
->en_eslp
, state
);
1515 EFSYS_PROBE1(fail1
, efx_rc_t
, rc
);
1519 static __checkReturn efx_rc_t
1520 siena_filter_delete(
1521 __in efx_nic_t
*enp
,
1522 __inout efx_filter_spec_t
*spec
)
1525 siena_filter_spec_t sf_spec
;
1526 siena_filter_t
*sfp
= enp
->en_filter
.ef_siena_filter
;
1527 siena_filter_tbl_id_t tbl_id
;
1528 siena_filter_tbl_t
*sftp
;
1532 efsys_lock_state_t state
;
1535 EFSYS_ASSERT3P(spec
, !=, NULL
);
1537 if ((rc
= siena_filter_spec_from_gen_spec(&sf_spec
, spec
)) != 0)
1540 tbl_id
= siena_filter_tbl_id(sf_spec
.sfs_type
);
1541 sftp
= &sfp
->sf_tbl
[tbl_id
];
1543 key
= siena_filter_build(&filter
, &sf_spec
);
1545 EFSYS_LOCK(enp
->en_eslp
, state
);
1547 rc
= siena_filter_search(sftp
, &sf_spec
, key
, B_FALSE
,
1548 &filter_idx
, &depth
);
1552 siena_filter_clear_entry(enp
, sftp
, filter_idx
);
1553 if (sftp
->sft_used
== 0)
1554 siena_filter_reset_search_depth(sfp
, tbl_id
);
1556 EFSYS_UNLOCK(enp
->en_eslp
, state
);
1560 EFSYS_UNLOCK(enp
->en_eslp
, state
);
1564 EFSYS_PROBE1(fail1
, efx_rc_t
, rc
);
1568 #define SIENA_MAX_SUPPORTED_MATCHES 4
1570 static __checkReturn efx_rc_t
1571 siena_filter_supported_filters(
1572 __in efx_nic_t
*enp
,
1573 __out_ecount(buffer_length
) uint32_t *buffer
,
1574 __in
size_t buffer_length
,
1575 __out
size_t *list_lengthp
)
1578 uint32_t rx_matches
[SIENA_MAX_SUPPORTED_MATCHES
];
1582 rx_matches
[index
++] =
1583 EFX_FILTER_MATCH_ETHER_TYPE
| EFX_FILTER_MATCH_IP_PROTO
|
1584 EFX_FILTER_MATCH_LOC_HOST
| EFX_FILTER_MATCH_LOC_PORT
|
1585 EFX_FILTER_MATCH_REM_HOST
| EFX_FILTER_MATCH_REM_PORT
;
1587 rx_matches
[index
++] =
1588 EFX_FILTER_MATCH_ETHER_TYPE
| EFX_FILTER_MATCH_IP_PROTO
|
1589 EFX_FILTER_MATCH_LOC_HOST
| EFX_FILTER_MATCH_LOC_PORT
;
1591 if (enp
->en_features
& EFX_FEATURE_MAC_HEADER_FILTERS
) {
1592 rx_matches
[index
++] =
1593 EFX_FILTER_MATCH_OUTER_VID
| EFX_FILTER_MATCH_LOC_MAC
;
1595 rx_matches
[index
++] = EFX_FILTER_MATCH_LOC_MAC
;
1598 EFSYS_ASSERT3U(index
, <=, SIENA_MAX_SUPPORTED_MATCHES
);
1599 list_length
= index
;
1601 *list_lengthp
= list_length
;
1603 if (buffer_length
< list_length
) {
1608 memcpy(buffer
, rx_matches
, list_length
* sizeof (rx_matches
[0]));
1613 EFSYS_PROBE1(fail1
, efx_rc_t
, rc
);
1618 #undef MAX_SUPPORTED
1620 #endif /* EFSYS_OPT_SIENA */
1622 #endif /* EFSYS_OPT_FILTER */