summaryrefslogtreecommitdiffstats
path: root/sys/dev/sfxge/common/efx_filter.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/sfxge/common/efx_filter.c')
-rw-r--r--sys/dev/sfxge/common/efx_filter.c1722
1 files changed, 1066 insertions, 656 deletions
diff --git a/sys/dev/sfxge/common/efx_filter.c b/sys/dev/sfxge/common/efx_filter.c
index e8455db..7ae7ea5 100644
--- a/sys/dev/sfxge/common/efx_filter.c
+++ b/sys/dev/sfxge/common/efx_filter.c
@@ -1,26 +1,31 @@
/*-
- * Copyright 2007-2009 Solarflare Communications Inc. All rights reserved.
+ * Copyright (c) 2007-2015 Solarflare Communications Inc.
+ * All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
+ * modification, are permitted provided that the following conditions are met:
*
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are
+ * those of the authors and should not be interpreted as representing official
+ * policies, either expressed or implied, of the FreeBSD Project.
*/
#include <sys/cdefs.h>
@@ -35,24 +40,569 @@ __FBSDID("$FreeBSD$");
#if EFSYS_OPT_FILTER
-/* "Fudge factors" - difference between programmed value and actual depth.
+#if EFSYS_OPT_FALCON || EFSYS_OPT_SIENA
+
+static __checkReturn int
+falconsiena_filter_init(
+ __in efx_nic_t *enp);
+
+static void
+falconsiena_filter_fini(
+ __in efx_nic_t *enp);
+
+static __checkReturn int
+falconsiena_filter_restore(
+ __in efx_nic_t *enp);
+
+static __checkReturn int
+falconsiena_filter_add(
+ __in efx_nic_t *enp,
+ __inout efx_filter_spec_t *spec,
+ __in boolean_t may_replace);
+
+static __checkReturn int
+falconsiena_filter_delete(
+ __in efx_nic_t *enp,
+ __inout efx_filter_spec_t *spec);
+
+static __checkReturn int
+falconsiena_filter_supported_filters(
+ __in efx_nic_t *enp,
+ __out uint32_t *list,
+ __out size_t *length);
+
+#endif /* EFSYS_OPT_FALCON || EFSYS_OPT_SIENA */
+
+#if EFSYS_OPT_FALCON
+static efx_filter_ops_t __efx_filter_falcon_ops = {
+ falconsiena_filter_init, /* efo_init */
+ falconsiena_filter_fini, /* efo_fini */
+ falconsiena_filter_restore, /* efo_restore */
+ falconsiena_filter_add, /* efo_add */
+ falconsiena_filter_delete, /* efo_delete */
+ falconsiena_filter_supported_filters, /* efo_supported_filters */
+ NULL, /* efo_reconfigure */
+};
+#endif /* EFSYS_OPT_FALCON */
+
+#if EFSYS_OPT_SIENA
+static efx_filter_ops_t __efx_filter_siena_ops = {
+ falconsiena_filter_init, /* efo_init */
+ falconsiena_filter_fini, /* efo_fini */
+ falconsiena_filter_restore, /* efo_restore */
+ falconsiena_filter_add, /* efo_add */
+ falconsiena_filter_delete, /* efo_delete */
+ falconsiena_filter_supported_filters, /* efo_supported_filters */
+ NULL, /* efo_reconfigure */
+};
+#endif /* EFSYS_OPT_SIENA */
+
+#if EFSYS_OPT_HUNTINGTON
+static efx_filter_ops_t __efx_filter_hunt_ops = {
+ hunt_filter_init, /* efo_init */
+ hunt_filter_fini, /* efo_fini */
+ hunt_filter_restore, /* efo_restore */
+ hunt_filter_add, /* efo_add */
+ hunt_filter_delete, /* efo_delete */
+ hunt_filter_supported_filters, /* efo_supported_filters */
+ hunt_filter_reconfigure, /* efo_reconfigure */
+};
+#endif /* EFSYS_OPT_HUNTINGTON */
+
+ __checkReturn int
+efx_filter_insert(
+ __in efx_nic_t *enp,
+ __inout efx_filter_spec_t *spec)
+{
+ efx_filter_ops_t *efop = enp->en_efop;
+
+ EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
+ EFSYS_ASSERT3P(spec, !=, NULL);
+ EFSYS_ASSERT3U(spec->efs_flags, &, EFX_FILTER_FLAG_RX);
+
+ return (efop->efo_add(enp, spec, B_FALSE));
+}
+
+ __checkReturn int
+efx_filter_remove(
+ __in efx_nic_t *enp,
+ __inout efx_filter_spec_t *spec)
+{
+ efx_filter_ops_t *efop = enp->en_efop;
+
+ EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
+ EFSYS_ASSERT3P(spec, !=, NULL);
+ EFSYS_ASSERT3U(spec->efs_flags, &, EFX_FILTER_FLAG_RX);
+
+#if EFSYS_OPT_RX_SCALE
+ spec->efs_rss_context = enp->en_rss_context;
+#endif
+
+ return (efop->efo_delete(enp, spec));
+}
+
+ __checkReturn int
+efx_filter_restore(
+ __in efx_nic_t *enp)
+{
+ int rc;
+
+ EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
+
+ if ((rc = enp->en_efop->efo_restore(enp)) != 0)
+ goto fail1;
+
+ return (0);
+
+fail1:
+ EFSYS_PROBE1(fail1, int, rc);
+
+ return (rc);
+}
+
+ __checkReturn int
+efx_filter_init(
+ __in efx_nic_t *enp)
+{
+ efx_filter_ops_t *efop;
+ int rc;
+
+ /* Check that efx_filter_spec_t is 64 bytes. */
+ EFX_STATIC_ASSERT(sizeof (efx_filter_spec_t) == 64);
+
+ EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+ EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
+ EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_FILTER));
+
+ switch (enp->en_family) {
+#if EFSYS_OPT_FALCON
+ case EFX_FAMILY_FALCON:
+ efop = (efx_filter_ops_t *)&__efx_filter_falcon_ops;
+ break;
+#endif /* EFSYS_OPT_FALCON */
+
+#if EFSYS_OPT_SIENA
+ case EFX_FAMILY_SIENA:
+ efop = (efx_filter_ops_t *)&__efx_filter_siena_ops;
+ break;
+#endif /* EFSYS_OPT_SIENA */
+
+#if EFSYS_OPT_HUNTINGTON
+ case EFX_FAMILY_HUNTINGTON:
+ efop = (efx_filter_ops_t *)&__efx_filter_hunt_ops;
+ break;
+#endif /* EFSYS_OPT_HUNTINGTON */
+
+ default:
+ EFSYS_ASSERT(0);
+ rc = ENOTSUP;
+ goto fail1;
+ }
+
+ if ((rc = efop->efo_init(enp)) != 0)
+ goto fail2;
+
+ enp->en_efop = efop;
+ enp->en_mod_flags |= EFX_MOD_FILTER;
+ return (0);
+
+fail2:
+ EFSYS_PROBE(fail2);
+fail1:
+ EFSYS_PROBE1(fail1, int, rc);
+
+ enp->en_efop = NULL;
+ enp->en_mod_flags &= ~EFX_MOD_FILTER;
+ return (rc);
+}
+
+ void
+efx_filter_fini(
+ __in efx_nic_t *enp)
+{
+ EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+ EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
+ EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
+
+ enp->en_efop->efo_fini(enp);
+
+ enp->en_efop = NULL;
+ enp->en_mod_flags &= ~EFX_MOD_FILTER;
+}
+
+ __checkReturn int
+efx_filter_supported_filters(
+ __in efx_nic_t *enp,
+ __out uint32_t *list,
+ __out size_t *length)
+{
+ int rc;
+
+ EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+ EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
+ EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
+ EFSYS_ASSERT(enp->en_efop->efo_supported_filters != NULL);
+
+ if ((rc = enp->en_efop->efo_supported_filters(enp, list, length)) != 0)
+ goto fail1;
+
+ return (0);
+
+fail1:
+ EFSYS_PROBE1(fail1, int, rc);
+
+ return (rc);
+}
+
+ __checkReturn int
+efx_filter_reconfigure(
+ __in efx_nic_t *enp,
+ __in_ecount(6) uint8_t const *mac_addr,
+ __in boolean_t all_unicst,
+ __in boolean_t mulcst,
+ __in boolean_t all_mulcst,
+ __in boolean_t brdcst,
+ __in_ecount(6*count) uint8_t const *addrs,
+ __in int count)
+{
+ int rc;
+
+ EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+ EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
+ EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
+
+ if (enp->en_efop->efo_reconfigure != NULL) {
+ if ((rc = enp->en_efop->efo_reconfigure(enp, mac_addr,
+ all_unicst, mulcst,
+ all_mulcst, brdcst,
+ addrs, count)) != 0)
+ goto fail1;
+ }
+
+ return (0);
+
+fail1:
+ EFSYS_PROBE1(fail1, int, rc);
+
+ return (rc);
+}
+
+ void
+efx_filter_spec_init_rx(
+ __inout efx_filter_spec_t *spec,
+ __in efx_filter_priority_t priority,
+ __in efx_filter_flag_t flags,
+ __in efx_rxq_t *erp)
+{
+ EFSYS_ASSERT3P(spec, !=, NULL);
+ EFSYS_ASSERT3P(erp, !=, NULL);
+ EFSYS_ASSERT((flags & ~(EFX_FILTER_FLAG_RX_RSS |
+ EFX_FILTER_FLAG_RX_SCATTER)) == 0);
+
+ memset(spec, 0, sizeof (*spec));
+ spec->efs_priority = priority;
+ spec->efs_flags = EFX_FILTER_FLAG_RX | flags;
+ spec->efs_rss_context = EFX_FILTER_SPEC_RSS_CONTEXT_DEFAULT;
+ spec->efs_dmaq_id = (uint16_t)erp->er_index;
+}
+
+ void
+efx_filter_spec_init_tx(
+ __inout efx_filter_spec_t *spec,
+ __in efx_txq_t *etp)
+{
+ EFSYS_ASSERT3P(spec, !=, NULL);
+ EFSYS_ASSERT3P(etp, !=, NULL);
+
+ memset(spec, 0, sizeof (*spec));
+ spec->efs_priority = EFX_FILTER_PRI_REQUIRED;
+ spec->efs_flags = EFX_FILTER_FLAG_TX;
+ spec->efs_dmaq_id = (uint16_t)etp->et_index;
+}
+
+
+/*
+ * Specify IPv4 host, transport protocol and port in a filter specification
+ */
+__checkReturn int
+efx_filter_spec_set_ipv4_local(
+ __inout efx_filter_spec_t *spec,
+ __in uint8_t proto,
+ __in uint32_t host,
+ __in uint16_t port)
+{
+ EFSYS_ASSERT3P(spec, !=, NULL);
+
+ spec->efs_match_flags |=
+ EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
+ EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT;
+ spec->efs_ether_type = EFX_ETHER_TYPE_IPV4;
+ spec->efs_ip_proto = proto;
+ spec->efs_loc_host.eo_u32[0] = host;
+ spec->efs_loc_port = port;
+ return (0);
+}
+
+/*
+ * Specify IPv4 hosts, transport protocol and ports in a filter specification
+ */
+__checkReturn int
+efx_filter_spec_set_ipv4_full(
+ __inout efx_filter_spec_t *spec,
+ __in uint8_t proto,
+ __in uint32_t lhost,
+ __in uint16_t lport,
+ __in uint32_t rhost,
+ __in uint16_t rport)
+{
+ EFSYS_ASSERT3P(spec, !=, NULL);
+
+ spec->efs_match_flags |=
+ EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
+ EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT |
+ EFX_FILTER_MATCH_REM_HOST | EFX_FILTER_MATCH_REM_PORT;
+ spec->efs_ether_type = EFX_ETHER_TYPE_IPV4;
+ spec->efs_ip_proto = proto;
+ spec->efs_loc_host.eo_u32[0] = lhost;
+ spec->efs_loc_port = lport;
+ spec->efs_rem_host.eo_u32[0] = rhost;
+ spec->efs_rem_port = rport;
+ return (0);
+}
+
+/*
+ * Specify local Ethernet address and/or VID in filter specification
+ */
+__checkReturn int
+efx_filter_spec_set_eth_local(
+ __inout efx_filter_spec_t *spec,
+ __in uint16_t vid,
+ __in const uint8_t *addr)
+{
+ EFSYS_ASSERT3P(spec, !=, NULL);
+ EFSYS_ASSERT3P(addr, !=, NULL);
+
+ if (vid == EFX_FILTER_SPEC_VID_UNSPEC && addr == NULL)
+ return (EINVAL);
+
+ if (vid != EFX_FILTER_SPEC_VID_UNSPEC) {
+ spec->efs_match_flags |= EFX_FILTER_MATCH_OUTER_VID;
+ spec->efs_outer_vid = vid;
+ }
+ if (addr != NULL) {
+ spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_MAC;
+ memcpy(spec->efs_loc_mac, addr, EFX_MAC_ADDR_LEN);
+ }
+ return (0);
+}
+
+/*
+ * Specify matching otherwise-unmatched unicast in a filter specification
+ */
+__checkReturn int
+efx_filter_spec_set_uc_def(
+ __inout efx_filter_spec_t *spec)
+{
+ EFSYS_ASSERT3P(spec, !=, NULL);
+
+ spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_MAC_IG;
+ return (0);
+}
+
+/*
+ * Specify matching otherwise-unmatched multicast in a filter specification
+ */
+__checkReturn int
+efx_filter_spec_set_mc_def(
+ __inout efx_filter_spec_t *spec)
+{
+ EFSYS_ASSERT3P(spec, !=, NULL);
+
+ spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_MAC_IG;
+ spec->efs_loc_mac[0] = 1;
+ return (0);
+}
+
+
+
+#if EFSYS_OPT_FALCON || EFSYS_OPT_SIENA
+
+/*
+ * "Fudge factors" - difference between programmed value and actual depth.
* Due to pipelined implementation we need to program H/W with a value that
* is larger than the hop limit we want.
*/
-#define FILTER_CTL_SRCH_FUDGE_WILD 3
-#define FILTER_CTL_SRCH_FUDGE_FULL 1
+#define FILTER_CTL_SRCH_FUDGE_WILD 3
+#define FILTER_CTL_SRCH_FUDGE_FULL 1
-/* Hard maximum hop limit. Hardware will time-out beyond 200-something.
+/*
+ * Hard maximum hop limit. Hardware will time-out beyond 200-something.
* We also need to avoid infinite loops in efx_filter_search() when the
* table is full.
*/
-#define FILTER_CTL_SRCH_MAX 200
+#define FILTER_CTL_SRCH_MAX 200
-/* The filter hash function is LFSR polynomial x^16 + x^3 + 1 of a 32-bit
- * key derived from the n-tuple. */
+static __checkReturn int
+falconsiena_filter_spec_from_gen_spec(
+ __out falconsiena_filter_spec_t *fs_spec,
+ __in efx_filter_spec_t *gen_spec)
+{
+ int rc;
+ boolean_t is_full = B_FALSE;
+
+ if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX)
+ EFSYS_ASSERT3U(gen_spec->efs_flags, ==, EFX_FILTER_FLAG_TX);
+ else
+ EFSYS_ASSERT3U(gen_spec->efs_flags, &, EFX_FILTER_FLAG_RX);
+
+ /* Falconsiena only has one RSS context */
+ if ((gen_spec->efs_flags & EFX_FILTER_FLAG_RX_RSS) &&
+ gen_spec->efs_rss_context != 0) {
+ rc = EINVAL;
+ goto fail1;
+ }
+
+ fs_spec->fsfs_flags = gen_spec->efs_flags;
+ fs_spec->fsfs_dmaq_id = gen_spec->efs_dmaq_id;
+
+ switch (gen_spec->efs_match_flags) {
+ case EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
+ EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT |
+ EFX_FILTER_MATCH_REM_HOST | EFX_FILTER_MATCH_REM_PORT:
+ is_full = B_TRUE;
+ /* Fall through */
+ case EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
+ EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT: {
+ uint32_t rhost, host1, host2;
+ uint16_t rport, port1, port2;
+
+ if (gen_spec->efs_ether_type != EFX_ETHER_TYPE_IPV4) {
+ rc = ENOTSUP;
+ goto fail2;
+ }
+ if (gen_spec->efs_loc_port == 0 ||
+ (is_full && gen_spec->efs_rem_port == 0)) {
+ rc = EINVAL;
+ goto fail3;
+ }
+ switch (gen_spec->efs_ip_proto) {
+ case EFX_IPPROTO_TCP:
+ if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX) {
+ fs_spec->fsfs_type = (is_full ?
+ EFX_FS_FILTER_TX_TCP_FULL :
+ EFX_FS_FILTER_TX_TCP_WILD);
+ } else {
+ fs_spec->fsfs_type = (is_full ?
+ EFX_FS_FILTER_RX_TCP_FULL :
+ EFX_FS_FILTER_RX_TCP_WILD);
+ }
+ break;
+ case EFX_IPPROTO_UDP:
+ if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX) {
+ fs_spec->fsfs_type = (is_full ?
+ EFX_FS_FILTER_TX_UDP_FULL :
+ EFX_FS_FILTER_TX_UDP_WILD);
+ } else {
+ fs_spec->fsfs_type = (is_full ?
+ EFX_FS_FILTER_RX_UDP_FULL :
+ EFX_FS_FILTER_RX_UDP_WILD);
+ }
+ break;
+ default:
+ rc = ENOTSUP;
+ goto fail4;
+ }
+ /*
+ * The filter is constructed in terms of source and destination,
+ * with the odd wrinkle that the ports are swapped in a UDP
+ * wildcard filter. We need to convert from local and remote
+ * addresses (zero for a wildcard).
+ */
+ rhost = is_full ? gen_spec->efs_rem_host.eo_u32[0] : 0;
+ rport = is_full ? gen_spec->efs_rem_port : 0;
+ if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX) {
+ host1 = gen_spec->efs_loc_host.eo_u32[0];
+ host2 = rhost;
+ } else {
+ host1 = rhost;
+ host2 = gen_spec->efs_loc_host.eo_u32[0];
+ }
+ if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX) {
+ if (fs_spec->fsfs_type == EFX_FS_FILTER_TX_UDP_WILD) {
+ port1 = rport;
+ port2 = gen_spec->efs_loc_port;
+ } else {
+ port1 = gen_spec->efs_loc_port;
+ port2 = rport;
+ }
+ } else {
+ if (fs_spec->fsfs_type == EFX_FS_FILTER_RX_UDP_WILD) {
+ port1 = gen_spec->efs_loc_port;
+ port2 = rport;
+ } else {
+ port1 = rport;
+ port2 = gen_spec->efs_loc_port;
+ }
+ }
+ fs_spec->fsfs_dword[0] = (host1 << 16) | port1;
+ fs_spec->fsfs_dword[1] = (port2 << 16) | (host1 >> 16);
+ fs_spec->fsfs_dword[2] = host2;
+ break;
+ }
+
+ case EFX_FILTER_MATCH_LOC_MAC | EFX_FILTER_MATCH_OUTER_VID:
+ is_full = B_TRUE;
+ /* Fall through */
+ case EFX_FILTER_MATCH_LOC_MAC:
+ if (gen_spec->efs_flags & EFX_FILTER_FLAG_TX) {
+ fs_spec->fsfs_type = (is_full ?
+ EFX_FS_FILTER_TX_MAC_FULL :
+ EFX_FS_FILTER_TX_MAC_WILD);
+ } else {
+ fs_spec->fsfs_type = (is_full ?
+ EFX_FS_FILTER_RX_MAC_FULL :
+ EFX_FS_FILTER_RX_MAC_WILD);
+ }
+ fs_spec->fsfs_dword[0] = is_full ? gen_spec->efs_outer_vid : 0;
+ fs_spec->fsfs_dword[1] =
+ gen_spec->efs_loc_mac[2] << 24 |
+ gen_spec->efs_loc_mac[3] << 16 |
+ gen_spec->efs_loc_mac[4] << 8 |
+ gen_spec->efs_loc_mac[5];
+ fs_spec->fsfs_dword[2] =
+ gen_spec->efs_loc_mac[0] << 8 |
+ gen_spec->efs_loc_mac[1];
+ break;
+
+ default:
+ EFSYS_ASSERT(B_FALSE);
+ rc = ENOTSUP;
+ goto fail5;
+ }
+
+ return (0);
+
+fail5:
+ EFSYS_PROBE(fail5);
+fail4:
+ EFSYS_PROBE(fail4);
+fail3:
+ EFSYS_PROBE(fail3);
+fail2:
+ EFSYS_PROBE(fail2);
+fail1:
+ EFSYS_PROBE1(fail1, int, rc);
+
+ return (rc);
+}
+
+/*
+ * The filter hash function is LFSR polynomial x^16 + x^3 + 1 of a 32-bit
+ * key derived from the n-tuple.
+ */
static uint16_t
-efx_filter_tbl_hash(
- __in uint32_t key)
+falconsiena_filter_tbl_hash(
+ __in uint32_t key)
{
uint16_t tmp;
@@ -69,119 +619,119 @@ efx_filter_tbl_hash(
return (tmp);
}
-
-/* To allow for hash collisions, filter search continues at these
- * increments from the first possible entry selected by the hash. */
+/*
+ * To allow for hash collisions, filter search continues at these
+ * increments from the first possible entry selected by the hash.
+ */
static uint16_t
-efx_filter_tbl_increment(
+falconsiena_filter_tbl_increment(
__in uint32_t key)
{
return ((uint16_t)(key * 2 - 1));
}
static __checkReturn boolean_t
-efx_filter_test_used(
- __in efx_filter_tbl_t *eftp,
+falconsiena_filter_test_used(
+ __in falconsiena_filter_tbl_t *fsftp,
__in unsigned int index)
{
- EFSYS_ASSERT3P(eftp->eft_bitmap, !=, NULL);
- return ((eftp->eft_bitmap[index / 32] & (1 << (index % 32))) != 0);
+ EFSYS_ASSERT3P(fsftp->fsft_bitmap, !=, NULL);
+ return ((fsftp->fsft_bitmap[index / 32] & (1 << (index % 32))) != 0);
}
static void
-efx_filter_set_used(
- __in efx_filter_tbl_t *eftp,
+falconsiena_filter_set_used(
+ __in falconsiena_filter_tbl_t *fsftp,
__in unsigned int index)
{
- EFSYS_ASSERT3P(eftp->eft_bitmap, !=, NULL);
- eftp->eft_bitmap[index / 32] |= (1 << (index % 32));
- ++eftp->eft_used;
+ EFSYS_ASSERT3P(fsftp->fsft_bitmap, !=, NULL);
+ fsftp->fsft_bitmap[index / 32] |= (1 << (index % 32));
+ ++fsftp->fsft_used;
}
static void
-efx_filter_clear_used(
- __in efx_filter_tbl_t *eftp,
+falconsiena_filter_clear_used(
+ __in falconsiena_filter_tbl_t *fsftp,
__in unsigned int index)
{
- EFSYS_ASSERT3P(eftp->eft_bitmap, !=, NULL);
- eftp->eft_bitmap[index / 32] &= ~(1 << (index % 32));
+ EFSYS_ASSERT3P(fsftp->fsft_bitmap, !=, NULL);
+ fsftp->fsft_bitmap[index / 32] &= ~(1 << (index % 32));
- --eftp->eft_used;
- EFSYS_ASSERT3U(eftp->eft_used, >=, 0);
+ --fsftp->fsft_used;
+ EFSYS_ASSERT3U(fsftp->fsft_used, >=, 0);
}
-static efx_filter_tbl_id_t
-efx_filter_tbl_id(
- __in efx_filter_type_t type)
+static falconsiena_filter_tbl_id_t
+falconsiena_filter_tbl_id(
+ __in falconsiena_filter_type_t type)
{
- efx_filter_tbl_id_t tbl_id;
-
- switch (type)
- {
- case EFX_FILTER_RX_TCP_FULL:
- case EFX_FILTER_RX_TCP_WILD:
- case EFX_FILTER_RX_UDP_FULL:
- case EFX_FILTER_RX_UDP_WILD:
- tbl_id = EFX_FILTER_TBL_RX_IP;
+ falconsiena_filter_tbl_id_t tbl_id;
+
+ switch (type) {
+ case EFX_FS_FILTER_RX_TCP_FULL:
+ case EFX_FS_FILTER_RX_TCP_WILD:
+ case EFX_FS_FILTER_RX_UDP_FULL:
+ case EFX_FS_FILTER_RX_UDP_WILD:
+ tbl_id = EFX_FS_FILTER_TBL_RX_IP;
break;
#if EFSYS_OPT_SIENA
- case EFX_FILTER_RX_MAC_FULL:
- case EFX_FILTER_RX_MAC_WILD:
- tbl_id = EFX_FILTER_TBL_RX_MAC;
+ case EFX_FS_FILTER_RX_MAC_FULL:
+ case EFX_FS_FILTER_RX_MAC_WILD:
+ tbl_id = EFX_FS_FILTER_TBL_RX_MAC;
break;
- case EFX_FILTER_TX_TCP_FULL:
- case EFX_FILTER_TX_TCP_WILD:
- case EFX_FILTER_TX_UDP_FULL:
- case EFX_FILTER_TX_UDP_WILD:
- tbl_id = EFX_FILTER_TBL_TX_IP;
+ case EFX_FS_FILTER_TX_TCP_FULL:
+ case EFX_FS_FILTER_TX_TCP_WILD:
+ case EFX_FS_FILTER_TX_UDP_FULL:
+ case EFX_FS_FILTER_TX_UDP_WILD:
+ tbl_id = EFX_FS_FILTER_TBL_TX_IP;
break;
- case EFX_FILTER_TX_MAC_FULL:
- case EFX_FILTER_TX_MAC_WILD:
- tbl_id = EFX_FILTER_TBL_RX_MAC;
+ case EFX_FS_FILTER_TX_MAC_FULL:
+ case EFX_FS_FILTER_TX_MAC_WILD:
+ tbl_id = EFX_FS_FILTER_TBL_TX_MAC;
break;
#endif /* EFSYS_OPT_SIENA */
default:
EFSYS_ASSERT(B_FALSE);
+ tbl_id = EFX_FS_FILTER_NTBLS;
break;
}
return (tbl_id);
}
static void
-efx_filter_reset_search_depth(
- __inout efx_filter_t *efp,
- __in efx_filter_tbl_id_t tbl_id)
+falconsiena_filter_reset_search_depth(
+ __inout falconsiena_filter_t *fsfp,
+ __in falconsiena_filter_tbl_id_t tbl_id)
{
- switch (tbl_id)
- {
- case EFX_FILTER_TBL_RX_IP:
- efp->ef_depth[EFX_FILTER_RX_TCP_FULL] = 0;
- efp->ef_depth[EFX_FILTER_RX_TCP_WILD] = 0;
- efp->ef_depth[EFX_FILTER_RX_UDP_FULL] = 0;
- efp->ef_depth[EFX_FILTER_RX_UDP_WILD] = 0;
+ switch (tbl_id) {
+ case EFX_FS_FILTER_TBL_RX_IP:
+ fsfp->fsf_depth[EFX_FS_FILTER_RX_TCP_FULL] = 0;
+ fsfp->fsf_depth[EFX_FS_FILTER_RX_TCP_WILD] = 0;
+ fsfp->fsf_depth[EFX_FS_FILTER_RX_UDP_FULL] = 0;
+ fsfp->fsf_depth[EFX_FS_FILTER_RX_UDP_WILD] = 0;
break;
#if EFSYS_OPT_SIENA
- case EFX_FILTER_TBL_RX_MAC:
- efp->ef_depth[EFX_FILTER_RX_MAC_FULL] = 0;
- efp->ef_depth[EFX_FILTER_RX_MAC_WILD] = 0;
+ case EFX_FS_FILTER_TBL_RX_MAC:
+ fsfp->fsf_depth[EFX_FS_FILTER_RX_MAC_FULL] = 0;
+ fsfp->fsf_depth[EFX_FS_FILTER_RX_MAC_WILD] = 0;
break;
- case EFX_FILTER_TBL_TX_IP:
- efp->ef_depth[EFX_FILTER_TX_TCP_FULL] = 0;
- efp->ef_depth[EFX_FILTER_TX_TCP_WILD] = 0;
- efp->ef_depth[EFX_FILTER_TX_UDP_FULL] = 0;
- efp->ef_depth[EFX_FILTER_TX_UDP_WILD] = 0;
+ case EFX_FS_FILTER_TBL_TX_IP:
+ fsfp->fsf_depth[EFX_FS_FILTER_TX_TCP_FULL] = 0;
+ fsfp->fsf_depth[EFX_FS_FILTER_TX_TCP_WILD] = 0;
+ fsfp->fsf_depth[EFX_FS_FILTER_TX_UDP_FULL] = 0;
+ fsfp->fsf_depth[EFX_FS_FILTER_TX_UDP_WILD] = 0;
break;
- case EFX_FILTER_TBL_TX_MAC:
- efp->ef_depth[EFX_FILTER_TX_MAC_FULL] = 0;
- efp->ef_depth[EFX_FILTER_TX_MAC_WILD] = 0;
+ case EFX_FS_FILTER_TBL_TX_MAC:
+ fsfp->fsf_depth[EFX_FS_FILTER_TX_MAC_FULL] = 0;
+ fsfp->fsf_depth[EFX_FS_FILTER_TX_MAC_WILD] = 0;
break;
#endif /* EFSYS_OPT_SIENA */
@@ -192,36 +742,36 @@ efx_filter_reset_search_depth(
}
static void
-efx_filter_push_rx_limits(
+falconsiena_filter_push_rx_limits(
__in efx_nic_t *enp)
{
- efx_filter_t *efp = &enp->en_filter;
+ falconsiena_filter_t *fsfp = enp->en_filter.ef_falconsiena_filter;
efx_oword_t oword;
EFX_BAR_READO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
EFX_SET_OWORD_FIELD(oword, FRF_AZ_TCP_FULL_SRCH_LIMIT,
- efp->ef_depth[EFX_FILTER_RX_TCP_FULL] +
+ fsfp->fsf_depth[EFX_FS_FILTER_RX_TCP_FULL] +
FILTER_CTL_SRCH_FUDGE_FULL);
EFX_SET_OWORD_FIELD(oword, FRF_AZ_TCP_WILD_SRCH_LIMIT,
- efp->ef_depth[EFX_FILTER_RX_TCP_WILD] +
+ fsfp->fsf_depth[EFX_FS_FILTER_RX_TCP_WILD] +
FILTER_CTL_SRCH_FUDGE_WILD);
EFX_SET_OWORD_FIELD(oword, FRF_AZ_UDP_FULL_SRCH_LIMIT,
- efp->ef_depth[EFX_FILTER_RX_UDP_FULL] +
+ fsfp->fsf_depth[EFX_FS_FILTER_RX_UDP_FULL] +
FILTER_CTL_SRCH_FUDGE_FULL);
EFX_SET_OWORD_FIELD(oword, FRF_AZ_UDP_WILD_SRCH_LIMIT,
- efp->ef_depth[EFX_FILTER_RX_UDP_WILD] +
+ fsfp->fsf_depth[EFX_FS_FILTER_RX_UDP_WILD] +
FILTER_CTL_SRCH_FUDGE_WILD);
#if EFSYS_OPT_SIENA
- if (efp->ef_tbl[EFX_FILTER_TBL_RX_MAC].eft_size) {
+ if (fsfp->fsf_tbl[EFX_FS_FILTER_TBL_RX_MAC].fsft_size) {
EFX_SET_OWORD_FIELD(oword,
FRF_CZ_ETHERNET_FULL_SEARCH_LIMIT,
- efp->ef_depth[EFX_FILTER_RX_MAC_FULL] +
+ fsfp->fsf_depth[EFX_FS_FILTER_RX_MAC_FULL] +
FILTER_CTL_SRCH_FUDGE_FULL);
EFX_SET_OWORD_FIELD(oword,
FRF_CZ_ETHERNET_WILDCARD_SEARCH_LIMIT,
- efp->ef_depth[EFX_FILTER_RX_MAC_WILD] +
+ fsfp->fsf_depth[EFX_FS_FILTER_RX_MAC_WILD] +
FILTER_CTL_SRCH_FUDGE_WILD);
}
#endif /* EFSYS_OPT_SIENA */
@@ -230,150 +780,177 @@ efx_filter_push_rx_limits(
}
static void
-efx_filter_push_tx_limits(
+falconsiena_filter_push_tx_limits(
__in efx_nic_t *enp)
{
- efx_filter_t *efp = &enp->en_filter;
+ falconsiena_filter_t *fsfp = enp->en_filter.ef_falconsiena_filter;
efx_oword_t oword;
- if (efp->ef_tbl[EFX_FILTER_TBL_TX_IP].eft_size == 0)
- return;
-
EFX_BAR_READO(enp, FR_AZ_TX_CFG_REG, &oword);
- EFX_SET_OWORD_FIELD(oword, FRF_CZ_TX_TCPIP_FILTER_FULL_SEARCH_RANGE,
- efp->ef_depth[EFX_FILTER_TX_TCP_FULL] +
- FILTER_CTL_SRCH_FUDGE_FULL);
- EFX_SET_OWORD_FIELD(oword, FRF_CZ_TX_TCPIP_FILTER_WILD_SEARCH_RANGE,
- efp->ef_depth[EFX_FILTER_TX_TCP_WILD] +
- FILTER_CTL_SRCH_FUDGE_WILD);
- EFX_SET_OWORD_FIELD(oword, FRF_CZ_TX_UDPIP_FILTER_FULL_SEARCH_RANGE,
- efp->ef_depth[EFX_FILTER_TX_UDP_FULL] +
- FILTER_CTL_SRCH_FUDGE_FULL);
- EFX_SET_OWORD_FIELD(oword, FRF_CZ_TX_UDPIP_FILTER_WILD_SEARCH_RANGE,
- efp->ef_depth[EFX_FILTER_TX_UDP_WILD] +
- FILTER_CTL_SRCH_FUDGE_WILD);
+ if (fsfp->fsf_tbl[EFX_FS_FILTER_TBL_TX_IP].fsft_size != 0) {
+ EFX_SET_OWORD_FIELD(oword,
+ FRF_CZ_TX_TCPIP_FILTER_FULL_SEARCH_RANGE,
+ fsfp->fsf_depth[EFX_FS_FILTER_TX_TCP_FULL] +
+ FILTER_CTL_SRCH_FUDGE_FULL);
+ EFX_SET_OWORD_FIELD(oword,
+ FRF_CZ_TX_TCPIP_FILTER_WILD_SEARCH_RANGE,
+ fsfp->fsf_depth[EFX_FS_FILTER_TX_TCP_WILD] +
+ FILTER_CTL_SRCH_FUDGE_WILD);
+ EFX_SET_OWORD_FIELD(oword,
+ FRF_CZ_TX_UDPIP_FILTER_FULL_SEARCH_RANGE,
+ fsfp->fsf_depth[EFX_FS_FILTER_TX_UDP_FULL] +
+ FILTER_CTL_SRCH_FUDGE_FULL);
+ EFX_SET_OWORD_FIELD(oword,
+ FRF_CZ_TX_UDPIP_FILTER_WILD_SEARCH_RANGE,
+ fsfp->fsf_depth[EFX_FS_FILTER_TX_UDP_WILD] +
+ FILTER_CTL_SRCH_FUDGE_WILD);
+ }
+
+ if (fsfp->fsf_tbl[EFX_FS_FILTER_TBL_TX_MAC].fsft_size != 0) {
+ EFX_SET_OWORD_FIELD(
+ oword, FRF_CZ_TX_ETH_FILTER_FULL_SEARCH_RANGE,
+ fsfp->fsf_depth[EFX_FS_FILTER_TX_MAC_FULL] +
+ FILTER_CTL_SRCH_FUDGE_FULL);
+ EFX_SET_OWORD_FIELD(
+ oword, FRF_CZ_TX_ETH_FILTER_WILD_SEARCH_RANGE,
+ fsfp->fsf_depth[EFX_FS_FILTER_TX_MAC_WILD] +
+ FILTER_CTL_SRCH_FUDGE_WILD);
+ }
EFX_BAR_WRITEO(enp, FR_AZ_TX_CFG_REG, &oword);
}
/* Build a filter entry and return its n-tuple key. */
static __checkReturn uint32_t
-efx_filter_build(
+falconsiena_filter_build(
__out efx_oword_t *filter,
- __in efx_filter_spec_t *spec)
+ __in falconsiena_filter_spec_t *spec)
{
uint32_t dword3;
uint32_t key;
- uint8_t type = spec->efs_type;
- uint8_t flags = spec->efs_flags;
+ uint8_t type = spec->fsfs_type;
+ uint32_t flags = spec->fsfs_flags;
- switch (efx_filter_tbl_id(type)) {
- case EFX_FILTER_TBL_RX_IP: {
- boolean_t is_udp = (type == EFX_FILTER_RX_UDP_FULL ||
- type == EFX_FILTER_RX_UDP_WILD);
+ switch (falconsiena_filter_tbl_id(type)) {
+ case EFX_FS_FILTER_TBL_RX_IP: {
+ boolean_t is_udp = (type == EFX_FS_FILTER_RX_UDP_FULL ||
+ type == EFX_FS_FILTER_RX_UDP_WILD);
EFX_POPULATE_OWORD_7(*filter,
- FRF_BZ_RSS_EN, (flags & EFX_FILTER_FLAG_RX_RSS) ? 1 : 0,
- FRF_BZ_SCATTER_EN, (flags & EFX_FILTER_FLAG_RX_SCATTER) ? 1 : 0,
+ FRF_BZ_RSS_EN,
+ (flags & EFX_FILTER_FLAG_RX_RSS) ? 1 : 0,
+ FRF_BZ_SCATTER_EN,
+ (flags & EFX_FILTER_FLAG_RX_SCATTER) ? 1 : 0,
FRF_AZ_TCP_UDP, is_udp,
- FRF_AZ_RXQ_ID, spec->efs_dmaq_id,
- EFX_DWORD_2, spec->efs_dword[2],
- EFX_DWORD_1, spec->efs_dword[1],
- EFX_DWORD_0, spec->efs_dword[0]);
+ FRF_AZ_RXQ_ID, spec->fsfs_dmaq_id,
+ EFX_DWORD_2, spec->fsfs_dword[2],
+ EFX_DWORD_1, spec->fsfs_dword[1],
+ EFX_DWORD_0, spec->fsfs_dword[0]);
dword3 = is_udp;
break;
}
#if EFSYS_OPT_SIENA
- case EFX_FILTER_TBL_RX_MAC: {
- boolean_t is_wild = (type == EFX_FILTER_RX_MAC_WILD);
- EFX_POPULATE_OWORD_8(*filter,
- FRF_CZ_RMFT_RSS_EN, (flags & EFX_FILTER_FLAG_RX_RSS) ? 1 : 0,
- FRF_CZ_RMFT_SCATTER_EN, (flags & EFX_FILTER_FLAG_RX_SCATTER) ? 1 : 0,
- FRF_CZ_RMFT_IP_OVERRIDE, (flags & EFX_FILTER_FLAG_RX_OVERRIDE_IP) ? 1 : 0,
- FRF_CZ_RMFT_RXQ_ID, spec->efs_dmaq_id,
+ case EFX_FS_FILTER_TBL_RX_MAC: {
+ boolean_t is_wild = (type == EFX_FS_FILTER_RX_MAC_WILD);
+ EFX_POPULATE_OWORD_7(*filter,
+ FRF_CZ_RMFT_RSS_EN,
+ (flags & EFX_FILTER_FLAG_RX_RSS) ? 1 : 0,
+ FRF_CZ_RMFT_SCATTER_EN,
+ (flags & EFX_FILTER_FLAG_RX_SCATTER) ? 1 : 0,
+ FRF_CZ_RMFT_RXQ_ID, spec->fsfs_dmaq_id,
FRF_CZ_RMFT_WILDCARD_MATCH, is_wild,
- FRF_CZ_RMFT_DEST_MAC_DW1, spec->efs_dword[2],
- FRF_CZ_RMFT_DEST_MAC_DW0, spec->efs_dword[1],
- FRF_CZ_RMFT_VLAN_ID, spec->efs_dword[0]);
+ FRF_CZ_RMFT_DEST_MAC_DW1, spec->fsfs_dword[2],
+ FRF_CZ_RMFT_DEST_MAC_DW0, spec->fsfs_dword[1],
+ FRF_CZ_RMFT_VLAN_ID, spec->fsfs_dword[0]);
dword3 = is_wild;
break;
}
#endif /* EFSYS_OPT_SIENA */
- case EFX_FILTER_TBL_TX_IP: {
- boolean_t is_udp = (type == EFX_FILTER_TX_UDP_FULL ||
- type == EFX_FILTER_TX_UDP_WILD);
+ case EFX_FS_FILTER_TBL_TX_IP: {
+ boolean_t is_udp = (type == EFX_FS_FILTER_TX_UDP_FULL ||
+ type == EFX_FS_FILTER_TX_UDP_WILD);
EFX_POPULATE_OWORD_5(*filter,
FRF_CZ_TIFT_TCP_UDP, is_udp,
- FRF_CZ_TIFT_TXQ_ID, spec->efs_dmaq_id,
- EFX_DWORD_2, spec->efs_dword[2],
- EFX_DWORD_1, spec->efs_dword[1],
- EFX_DWORD_0, spec->efs_dword[0]);
- dword3 = is_udp | spec->efs_dmaq_id << 1;
+ FRF_CZ_TIFT_TXQ_ID, spec->fsfs_dmaq_id,
+ EFX_DWORD_2, spec->fsfs_dword[2],
+ EFX_DWORD_1, spec->fsfs_dword[1],
+ EFX_DWORD_0, spec->fsfs_dword[0]);
+ dword3 = is_udp | spec->fsfs_dmaq_id << 1;
break;
}
#if EFSYS_OPT_SIENA
- case EFX_FILTER_TBL_TX_MAC: {
- boolean_t is_wild = (type == EFX_FILTER_TX_MAC_WILD);
+ case EFX_FS_FILTER_TBL_TX_MAC: {
+ boolean_t is_wild = (type == EFX_FS_FILTER_TX_MAC_WILD);
EFX_POPULATE_OWORD_5(*filter,
- FRF_CZ_TMFT_TXQ_ID, spec->efs_dmaq_id,
+ FRF_CZ_TMFT_TXQ_ID, spec->fsfs_dmaq_id,
FRF_CZ_TMFT_WILDCARD_MATCH, is_wild,
- FRF_CZ_TMFT_SRC_MAC_DW1, spec->efs_dword[2],
- FRF_CZ_TMFT_SRC_MAC_DW0, spec->efs_dword[1],
- FRF_CZ_TMFT_VLAN_ID, spec->efs_dword[0]);
- dword3 = is_wild | spec->efs_dmaq_id << 1;
+ FRF_CZ_TMFT_SRC_MAC_DW1, spec->fsfs_dword[2],
+ FRF_CZ_TMFT_SRC_MAC_DW0, spec->fsfs_dword[1],
+ FRF_CZ_TMFT_VLAN_ID, spec->fsfs_dword[0]);
+ dword3 = is_wild | spec->fsfs_dmaq_id << 1;
break;
}
#endif /* EFSYS_OPT_SIENA */
default:
EFSYS_ASSERT(B_FALSE);
+ return (0);
}
- key = spec->efs_dword[0] ^ spec->efs_dword[1] ^ spec->efs_dword[2] ^ dword3;
+ key =
+ spec->fsfs_dword[0] ^
+ spec->fsfs_dword[1] ^
+ spec->fsfs_dword[2] ^
+ dword3;
+
return (key);
}
static __checkReturn int
-efx_filter_push_entry(
+falconsiena_filter_push_entry(
__inout efx_nic_t *enp,
- __in efx_filter_type_t type,
+ __in falconsiena_filter_type_t type,
__in int index,
__in efx_oword_t *eop)
{
int rc;
- switch (type)
- {
- case EFX_FILTER_RX_TCP_FULL:
- case EFX_FILTER_RX_TCP_WILD:
- case EFX_FILTER_RX_UDP_FULL:
- case EFX_FILTER_RX_UDP_WILD:
- EFX_BAR_TBL_WRITEO(enp, FR_AZ_RX_FILTER_TBL0, index, eop);
+ switch (type) {
+ case EFX_FS_FILTER_RX_TCP_FULL:
+ case EFX_FS_FILTER_RX_TCP_WILD:
+ case EFX_FS_FILTER_RX_UDP_FULL:
+ case EFX_FS_FILTER_RX_UDP_WILD:
+ EFX_BAR_TBL_WRITEO(enp, FR_AZ_RX_FILTER_TBL0, index,
+ eop, B_TRUE);
break;
#if EFSYS_OPT_SIENA
- case EFX_FILTER_RX_MAC_FULL:
- case EFX_FILTER_RX_MAC_WILD:
- EFX_BAR_TBL_WRITEO(enp, FR_CZ_RX_MAC_FILTER_TBL0, index, eop);
+ case EFX_FS_FILTER_RX_MAC_FULL:
+ case EFX_FS_FILTER_RX_MAC_WILD:
+ EFX_BAR_TBL_WRITEO(enp, FR_CZ_RX_MAC_FILTER_TBL0, index,
+ eop, B_TRUE);
break;
- case EFX_FILTER_TX_TCP_FULL:
- case EFX_FILTER_TX_TCP_WILD:
- case EFX_FILTER_TX_UDP_FULL:
- case EFX_FILTER_TX_UDP_WILD:
- EFX_BAR_TBL_WRITEO(enp, FR_CZ_TX_FILTER_TBL0, index, eop);
+ case EFX_FS_FILTER_TX_TCP_FULL:
+ case EFX_FS_FILTER_TX_TCP_WILD:
+ case EFX_FS_FILTER_TX_UDP_FULL:
+ case EFX_FS_FILTER_TX_UDP_WILD:
+ EFX_BAR_TBL_WRITEO(enp, FR_CZ_TX_FILTER_TBL0, index,
+ eop, B_TRUE);
break;
- case EFX_FILTER_TX_MAC_FULL:
- case EFX_FILTER_TX_MAC_WILD:
- EFX_BAR_TBL_WRITEO(enp, FR_CZ_TX_MAC_FILTER_TBL0, index, eop);
+ case EFX_FS_FILTER_TX_MAC_FULL:
+ case EFX_FS_FILTER_TX_MAC_WILD:
+ EFX_BAR_TBL_WRITEO(enp, FR_CZ_TX_MAC_FILTER_TBL0, index,
+ eop, B_TRUE);
break;
#endif /* EFSYS_OPT_SIENA */
default:
+ EFSYS_ASSERT(B_FALSE);
rc = ENOTSUP;
goto fail1;
}
@@ -385,30 +962,34 @@ fail1:
static __checkReturn boolean_t
-efx_filter_equal(
- __in const efx_filter_spec_t *left,
- __in const efx_filter_spec_t *right)
+falconsiena_filter_equal(
+ __in const falconsiena_filter_spec_t *left,
+ __in const falconsiena_filter_spec_t *right)
{
- efx_filter_tbl_id_t tbl_id = efx_filter_tbl_id(left->efs_type);
+ falconsiena_filter_tbl_id_t tbl_id;
- if (left->efs_type != right->efs_type)
+ tbl_id = falconsiena_filter_tbl_id(left->fsfs_type);
+
+
+ if (left->fsfs_type != right->fsfs_type)
return (B_FALSE);
- if (memcmp(left->efs_dword, right->efs_dword, sizeof(left->efs_dword)))
+ if (memcmp(left->fsfs_dword, right->fsfs_dword,
+ sizeof (left->fsfs_dword)))
return (B_FALSE);
- if ((tbl_id == EFX_FILTER_TBL_TX_IP ||
- tbl_id == EFX_FILTER_TBL_TX_MAC) &&
- left->efs_dmaq_id != right->efs_dmaq_id)
+ if ((tbl_id == EFX_FS_FILTER_TBL_TX_IP ||
+ tbl_id == EFX_FS_FILTER_TBL_TX_MAC) &&
+ left->fsfs_dmaq_id != right->fsfs_dmaq_id)
return (B_FALSE);
return (B_TRUE);
}
static __checkReturn int
-efx_filter_search(
- __in efx_filter_tbl_t *eftp,
- __in efx_filter_spec_t *spec,
+falconsiena_filter_search(
+ __in falconsiena_filter_tbl_t *fsftp,
+ __in falconsiena_filter_spec_t *spec,
__in uint32_t key,
__in boolean_t for_insert,
__out int *filter_index,
@@ -416,18 +997,20 @@ efx_filter_search(
{
unsigned hash, incr, filter_idx, depth;
- hash = efx_filter_tbl_hash(key);
- incr = efx_filter_tbl_increment(key);
+ hash = falconsiena_filter_tbl_hash(key);
+ incr = falconsiena_filter_tbl_increment(key);
- filter_idx = hash & (eftp->eft_size - 1);
+ filter_idx = hash & (fsftp->fsft_size - 1);
depth = 1;
for (;;) {
- /* Return success if entry is used and matches this spec
+ /*
+ * Return success if entry is used and matches this spec
* or entry is unused and we are trying to insert.
*/
- if (efx_filter_test_used(eftp, filter_idx) ?
- efx_filter_equal(spec, &eftp->eft_spec[filter_idx]) :
+ if (falconsiena_filter_test_used(fsftp, filter_idx) ?
+ falconsiena_filter_equal(spec,
+ &fsftp->fsft_spec[filter_idx]) :
for_insert) {
*filter_index = filter_idx;
*depth_required = depth;
@@ -436,594 +1019,421 @@ efx_filter_search(
/* Return failure if we reached the maximum search depth */
if (depth == FILTER_CTL_SRCH_MAX)
- return for_insert ? EBUSY : ENOENT;
+ return (for_insert ? EBUSY : ENOENT);
- filter_idx = (filter_idx + incr) & (eftp->eft_size - 1);
+ filter_idx = (filter_idx + incr) & (fsftp->fsft_size - 1);
++depth;
}
}
- __checkReturn int
-efx_filter_insert_filter(
- __in efx_nic_t *enp,
- __in efx_filter_spec_t *spec,
- __in boolean_t replace)
-{
- efx_filter_t *efp = &enp->en_filter;
- efx_filter_tbl_id_t tbl_id = efx_filter_tbl_id(spec->efs_type);
- efx_filter_tbl_t *eftp = &efp->ef_tbl[tbl_id];
- efx_filter_spec_t *saved_spec;
- efx_oword_t filter;
- int filter_idx;
- unsigned int depth;
- int state;
- uint32_t key;
- int rc;
-
- if (eftp->eft_size == 0)
- return (EINVAL);
-
- key = efx_filter_build(&filter, spec);
-
- EFSYS_LOCK(enp->en_eslp, state);
-
- rc = efx_filter_search(eftp, spec, key, B_TRUE, &filter_idx, &depth);
- if (rc != 0)
- goto done;
-
- EFSYS_ASSERT3U(filter_idx, <, eftp->eft_size);
- saved_spec = &eftp->eft_spec[filter_idx];
-
- if (efx_filter_test_used(eftp, filter_idx)) {
- if (replace == B_FALSE) {
- rc = EEXIST;
- goto done;
- }
- }
- efx_filter_set_used(eftp, filter_idx);
- *saved_spec = *spec;
-
- if (efp->ef_depth[spec->efs_type] < depth) {
- efp->ef_depth[spec->efs_type] = depth;
- if (tbl_id == EFX_FILTER_TBL_TX_IP ||
- tbl_id == EFX_FILTER_TBL_TX_MAC)
- efx_filter_push_tx_limits(enp);
- else
- efx_filter_push_rx_limits(enp);
- }
-
- efx_filter_push_entry(enp, spec->efs_type, filter_idx, &filter);
-
-done:
- EFSYS_UNLOCK(enp->en_eslp, state);
- return (rc);
-}
-
static void
-efx_filter_clear_entry(
+falconsiena_filter_clear_entry(
__in efx_nic_t *enp,
- __in efx_filter_tbl_t *eftp,
+ __in falconsiena_filter_tbl_t *fsftp,
__in int index)
{
efx_oword_t filter;
- if (efx_filter_test_used(eftp, index)) {
- efx_filter_clear_used(eftp, index);
+ if (falconsiena_filter_test_used(fsftp, index)) {
+ falconsiena_filter_clear_used(fsftp, index);
EFX_ZERO_OWORD(filter);
- efx_filter_push_entry(enp, eftp->eft_spec[index].efs_type,
+ falconsiena_filter_push_entry(enp,
+ fsftp->fsft_spec[index].fsfs_type,
index, &filter);
- memset(&eftp->eft_spec[index], 0, sizeof(eftp->eft_spec[0]));
+ memset(&fsftp->fsft_spec[index],
+ 0, sizeof (fsftp->fsft_spec[0]));
}
}
- __checkReturn int
-efx_filter_remove_filter(
- __in efx_nic_t *enp,
- __in efx_filter_spec_t *spec)
-{
- efx_filter_t *efp = &enp->en_filter;
- efx_filter_tbl_id_t tbl_id = efx_filter_tbl_id(spec->efs_type);
- efx_filter_tbl_t *eftp = &efp->ef_tbl[tbl_id];
- efx_filter_spec_t *saved_spec;
- efx_oword_t filter;
- int filter_idx;
- unsigned int depth;
- int state;
- uint32_t key;
- int rc;
-
- key = efx_filter_build(&filter, spec);
-
- EFSYS_LOCK(enp->en_eslp, state);
-
- rc = efx_filter_search(eftp, spec, key, B_FALSE, &filter_idx, &depth);
- if (rc != 0)
- goto out;
-
- saved_spec = &eftp->eft_spec[filter_idx];
-
- efx_filter_clear_entry(enp, eftp, filter_idx);
- if (eftp->eft_used == 0)
- efx_filter_reset_search_depth(efp, tbl_id);
-
- rc = 0;
-
-out:
- EFSYS_UNLOCK(enp->en_eslp, state);
- return (rc);
-}
-
- void
-efx_filter_remove_index(
- __inout efx_nic_t *enp,
- __in efx_filter_type_t type,
- __in int index)
-{
- efx_filter_t *efp = &enp->en_filter;
- efx_filter_tbl_id_t tbl_id = efx_filter_tbl_id(type);
- efx_filter_tbl_t *eftp = &efp->ef_tbl[tbl_id];
- int state;
-
- if (index < 0)
- return;
-
- EFSYS_LOCK(enp->en_eslp, state);
-
- efx_filter_clear_entry(enp, eftp, index);
- if (eftp->eft_used == 0)
- efx_filter_reset_search_depth(efp, tbl_id);
-
- EFSYS_UNLOCK(enp->en_eslp, state);
-}
-
void
-efx_filter_tbl_clear(
- __inout efx_nic_t *enp,
- __in efx_filter_tbl_id_t tbl_id)
+falconsiena_filter_tbl_clear(
+ __in efx_nic_t *enp,
+ __in falconsiena_filter_tbl_id_t tbl_id)
{
- efx_filter_t *efp = &enp->en_filter;
- efx_filter_tbl_t *eftp = &efp->ef_tbl[tbl_id];
+ falconsiena_filter_t *fsfp = enp->en_filter.ef_falconsiena_filter;
+ falconsiena_filter_tbl_t *fsftp = &fsfp->fsf_tbl[tbl_id];
int index;
int state;
EFSYS_LOCK(enp->en_eslp, state);
- for (index = 0; index < eftp->eft_size; ++index) {
- efx_filter_clear_entry(enp, eftp, index);
+ for (index = 0; index < fsftp->fsft_size; ++index) {
+ falconsiena_filter_clear_entry(enp, fsftp, index);
}
- if (eftp->eft_used == 0)
- efx_filter_reset_search_depth(efp, tbl_id);
+ if (fsftp->fsft_used == 0)
+ falconsiena_filter_reset_search_depth(fsfp, tbl_id);
EFSYS_UNLOCK(enp->en_eslp, state);
}
-/* Restore filter state after a reset */
- void
-efx_filter_restore(
+static __checkReturn int
+falconsiena_filter_init(
__in efx_nic_t *enp)
{
- efx_filter_t *efp = &enp->en_filter;
- efx_filter_tbl_id_t tbl_id;
- efx_filter_tbl_t *eftp;
- efx_filter_spec_t *spec;
- efx_oword_t filter;
- int filter_idx;
- int state;
-
- EFSYS_LOCK(enp->en_eslp, state);
+ falconsiena_filter_t *fsfp;
+ falconsiena_filter_tbl_t *fsftp;
+ int tbl_id;
+ int rc;
- for (tbl_id = 0; tbl_id < EFX_FILTER_NTBLS; tbl_id++) {
- eftp = &efp->ef_tbl[tbl_id];
- for (filter_idx = 0; filter_idx < eftp->eft_size; filter_idx++) {
- if (!efx_filter_test_used(eftp, filter_idx))
- continue;
+ EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (falconsiena_filter_t), fsfp);
- spec = &eftp->eft_spec[filter_idx];
- efx_filter_build(&filter, spec);
- efx_filter_push_entry(enp, spec->efs_type,
- filter_idx, &filter);
- }
+ if (!fsfp) {
+ rc = ENOMEM;
+ goto fail1;
}
- efx_filter_push_rx_limits(enp);
- efx_filter_push_tx_limits(enp);
-
- EFSYS_UNLOCK(enp->en_eslp, state);
-}
-
- void
-efx_filter_redirect_index(
- __inout efx_nic_t *enp,
- __in efx_filter_type_t type,
- __in int filter_index,
- __in int rxq_index)
-{
- efx_filter_t *efp = &enp->en_filter;
- efx_filter_tbl_t *eftp =
- &efp->ef_tbl[efx_filter_tbl_id(type)];
- efx_filter_spec_t *spec;
- efx_oword_t filter;
- int state;
-
- EFSYS_LOCK(enp->en_eslp, state);
+ enp->en_filter.ef_falconsiena_filter = fsfp;
- spec = &eftp->eft_spec[filter_index];
- spec->efs_dmaq_id = (uint16_t)rxq_index;
-
- efx_filter_build(&filter, spec);
- efx_filter_push_entry(enp, spec->efs_type, filter_index, &filter);
-
- EFSYS_UNLOCK(enp->en_eslp, state);
-}
-
- __checkReturn int
-efx_filter_init(
- __in efx_nic_t *enp)
-{
- efx_filter_t *efp = &enp->en_filter;
- efx_filter_tbl_t *eftp;
- int tbl_id;
- int rc;
-
- EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
- EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
- EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_FILTER));
-
- switch (enp->en_family)
- {
+ switch (enp->en_family) {
#if EFSYS_OPT_FALCON
case EFX_FAMILY_FALCON:
- eftp = &efp->ef_tbl[EFX_FILTER_TBL_RX_IP];
- eftp->eft_size = FR_AZ_RX_FILTER_TBL0_ROWS;
+ fsftp = &fsfp->fsf_tbl[EFX_FS_FILTER_TBL_RX_IP];
+ fsftp->fsft_size = FR_AZ_RX_FILTER_TBL0_ROWS;
break;
#endif /* EFSYS_OPT_FALCON */
#if EFSYS_OPT_SIENA
case EFX_FAMILY_SIENA:
- eftp = &efp->ef_tbl[EFX_FILTER_TBL_RX_IP];
- eftp->eft_size = FR_AZ_RX_FILTER_TBL0_ROWS;
+ fsftp = &fsfp->fsf_tbl[EFX_FS_FILTER_TBL_RX_IP];
+ fsftp->fsft_size = FR_AZ_RX_FILTER_TBL0_ROWS;
- eftp = &efp->ef_tbl[EFX_FILTER_TBL_RX_MAC];
- eftp->eft_size = FR_CZ_RX_MAC_FILTER_TBL0_ROWS;
+ fsftp = &fsfp->fsf_tbl[EFX_FS_FILTER_TBL_RX_MAC];
+ fsftp->fsft_size = FR_CZ_RX_MAC_FILTER_TBL0_ROWS;
- eftp = &efp->ef_tbl[EFX_FILTER_TBL_TX_IP];
- eftp->eft_size = FR_CZ_TX_FILTER_TBL0_ROWS;
+ fsftp = &fsfp->fsf_tbl[EFX_FS_FILTER_TBL_TX_IP];
+ fsftp->fsft_size = FR_CZ_TX_FILTER_TBL0_ROWS;
- eftp = &efp->ef_tbl[EFX_FILTER_TBL_TX_MAC];
- eftp->eft_size = FR_CZ_TX_MAC_FILTER_TBL0_ROWS;
+ fsftp = &fsfp->fsf_tbl[EFX_FS_FILTER_TBL_TX_MAC];
+ fsftp->fsft_size = FR_CZ_TX_MAC_FILTER_TBL0_ROWS;
break;
#endif /* EFSYS_OPT_SIENA */
default:
rc = ENOTSUP;
- goto fail1;
+ goto fail2;
}
- for (tbl_id = 0; tbl_id < EFX_FILTER_NTBLS; tbl_id++) {
+ for (tbl_id = 0; tbl_id < EFX_FS_FILTER_NTBLS; tbl_id++) {
unsigned int bitmap_size;
- eftp = &efp->ef_tbl[tbl_id];
- if (eftp->eft_size == 0)
+ fsftp = &fsfp->fsf_tbl[tbl_id];
+ if (fsftp->fsft_size == 0)
continue;
- EFX_STATIC_ASSERT(sizeof(eftp->eft_bitmap[0]) == sizeof(uint32_t));
- bitmap_size = (eftp->eft_size + (sizeof(uint32_t) * 8) - 1) / 8;
+ EFX_STATIC_ASSERT(sizeof (fsftp->fsft_bitmap[0]) ==
+ sizeof (uint32_t));
+ bitmap_size =
+ (fsftp->fsft_size + (sizeof (uint32_t) * 8) - 1) / 8;
- EFSYS_KMEM_ALLOC(enp->en_esip, bitmap_size, eftp->eft_bitmap);
- if (!eftp->eft_bitmap) {
+ EFSYS_KMEM_ALLOC(enp->en_esip, bitmap_size, fsftp->fsft_bitmap);
+ if (!fsftp->fsft_bitmap) {
rc = ENOMEM;
- goto fail2;
+ goto fail3;
}
- EFSYS_KMEM_ALLOC(enp->en_esip, eftp->eft_size * sizeof(*eftp->eft_spec),
- eftp->eft_spec);
- if (!eftp->eft_spec) {
+ EFSYS_KMEM_ALLOC(enp->en_esip,
+ fsftp->fsft_size * sizeof (*fsftp->fsft_spec),
+ fsftp->fsft_spec);
+ if (!fsftp->fsft_spec) {
rc = ENOMEM;
- goto fail3;
+ goto fail4;
}
- memset(eftp->eft_spec, 0, eftp->eft_size * sizeof(*eftp->eft_spec));
+ memset(fsftp->fsft_spec, 0,
+ fsftp->fsft_size * sizeof (*fsftp->fsft_spec));
}
- enp->en_mod_flags |= EFX_MOD_FILTER;
return (0);
+fail4:
+ EFSYS_PROBE(fail4);
+
fail3:
EFSYS_PROBE(fail3);
fail2:
EFSYS_PROBE(fail2);
- efx_filter_fini(enp);
+ falconsiena_filter_fini(enp);
fail1:
EFSYS_PROBE1(fail1, int, rc);
return (rc);
}
- void
-efx_filter_fini(
+static void
+falconsiena_filter_fini(
__in efx_nic_t *enp)
{
- efx_filter_t *efp = &enp->en_filter;
- efx_filter_tbl_id_t tbl_id;
+ falconsiena_filter_t *fsfp = enp->en_filter.ef_falconsiena_filter;
+ falconsiena_filter_tbl_id_t tbl_id;
EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
- for (tbl_id = 0; tbl_id < EFX_FILTER_NTBLS; tbl_id++) {
- efx_filter_tbl_t *eftp = &efp->ef_tbl[tbl_id];
+ if (fsfp == NULL)
+ return;
+
+ for (tbl_id = 0; tbl_id < EFX_FS_FILTER_NTBLS; tbl_id++) {
+ falconsiena_filter_tbl_t *fsftp = &fsfp->fsf_tbl[tbl_id];
unsigned int bitmap_size;
- EFX_STATIC_ASSERT(sizeof(eftp->eft_bitmap[0]) == sizeof(uint32_t));
- bitmap_size = (eftp->eft_size + (sizeof(uint32_t) * 8) - 1) / 8;
+ EFX_STATIC_ASSERT(sizeof (fsftp->fsft_bitmap[0]) ==
+ sizeof (uint32_t));
+ bitmap_size =
+ (fsftp->fsft_size + (sizeof (uint32_t) * 8) - 1) / 8;
- if (eftp->eft_bitmap != NULL) {
+ if (fsftp->fsft_bitmap != NULL) {
EFSYS_KMEM_FREE(enp->en_esip, bitmap_size,
- eftp->eft_bitmap);
- eftp->eft_bitmap = NULL;
+ fsftp->fsft_bitmap);
+ fsftp->fsft_bitmap = NULL;
}
- if (eftp->eft_spec != NULL) {
- EFSYS_KMEM_FREE(enp->en_esip, eftp->eft_size *
- sizeof(*eftp->eft_spec), eftp->eft_spec);
- eftp->eft_spec = NULL;
+ if (fsftp->fsft_spec != NULL) {
+ EFSYS_KMEM_FREE(enp->en_esip, fsftp->fsft_size *
+ sizeof (*fsftp->fsft_spec), fsftp->fsft_spec);
+ fsftp->fsft_spec = NULL;
}
}
- enp->en_mod_flags &= ~EFX_MOD_FILTER;
+ EFSYS_KMEM_FREE(enp->en_esip, sizeof (falconsiena_filter_t),
+ enp->en_filter.ef_falconsiena_filter);
}
-extern void
-efx_filter_spec_rx_ipv4_tcp_full(
- __inout efx_filter_spec_t *spec,
- __in unsigned int flags,
- __in uint32_t src_ip,
- __in uint16_t src_tcp,
- __in uint32_t dest_ip,
- __in uint16_t dest_tcp)
+/* Restore filter state after a reset */
+static __checkReturn int
+falconsiena_filter_restore(
+ __in efx_nic_t *enp)
{
- EFSYS_ASSERT3P(spec, !=, NULL);
- EFSYS_ASSERT((flags & ~(EFX_FILTER_FLAG_RX_RSS |
- EFX_FILTER_FLAG_RX_SCATTER)) == 0);
+ falconsiena_filter_t *fsfp = enp->en_filter.ef_falconsiena_filter;
+ falconsiena_filter_tbl_id_t tbl_id;
+ falconsiena_filter_tbl_t *fsftp;
+ falconsiena_filter_spec_t *spec;
+ efx_oword_t filter;
+ int filter_idx;
+ int state;
+ int rc;
- spec->efs_type = EFX_FILTER_RX_TCP_FULL;
- spec->efs_flags = (uint8_t)flags;
- spec->efs_dword[0] = src_tcp | src_ip << 16;
- spec->efs_dword[1] = dest_tcp << 16 | src_ip >> 16;
- spec->efs_dword[2] = dest_ip;
-}
+ EFSYS_LOCK(enp->en_eslp, state);
-extern void
-efx_filter_spec_rx_ipv4_tcp_wild(
- __inout efx_filter_spec_t *spec,
- __in unsigned int flags,
- __in uint32_t dest_ip,
- __in uint16_t dest_tcp)
-{
- EFSYS_ASSERT3P(spec, !=, NULL);
- EFSYS_ASSERT((flags & ~(EFX_FILTER_FLAG_RX_RSS |
- EFX_FILTER_FLAG_RX_SCATTER)) == 0);
+ for (tbl_id = 0; tbl_id < EFX_FS_FILTER_NTBLS; tbl_id++) {
+ fsftp = &fsfp->fsf_tbl[tbl_id];
+ for (filter_idx = 0;
+ filter_idx < fsftp->fsft_size;
+ filter_idx++) {
+ if (!falconsiena_filter_test_used(fsftp, filter_idx))
+ continue;
- spec->efs_type = EFX_FILTER_RX_TCP_WILD;
- spec->efs_flags = (uint8_t)flags;
- spec->efs_dword[0] = 0;
- spec->efs_dword[1] = dest_tcp << 16;
- spec->efs_dword[2] = dest_ip;
-}
+ spec = &fsftp->fsft_spec[filter_idx];
+ if ((rc = falconsiena_filter_build(&filter, spec)) != 0)
+ goto fail1;
+ if ((rc = falconsiena_filter_push_entry(enp,
+ spec->fsfs_type, filter_idx, &filter)) != 0)
+ goto fail2;
+ }
+ }
-extern void
-efx_filter_spec_rx_ipv4_udp_full(
- __inout efx_filter_spec_t *spec,
- __in unsigned int flags,
- __in uint32_t src_ip,
- __in uint16_t src_udp,
- __in uint32_t dest_ip,
- __in uint16_t dest_udp)
-{
- EFSYS_ASSERT3P(spec, !=, NULL);
- EFSYS_ASSERT((flags & ~(EFX_FILTER_FLAG_RX_RSS |
- EFX_FILTER_FLAG_RX_SCATTER)) == 0);
+ falconsiena_filter_push_rx_limits(enp);
+ falconsiena_filter_push_tx_limits(enp);
- spec->efs_type = EFX_FILTER_RX_UDP_FULL;
- spec->efs_flags = (uint8_t)flags;
- spec->efs_dword[0] = src_udp | src_ip << 16;
- spec->efs_dword[1] = dest_udp << 16 | src_ip >> 16;
- spec->efs_dword[2] = dest_ip;
-}
+ EFSYS_UNLOCK(enp->en_eslp, state);
-extern void
-efx_filter_spec_rx_ipv4_udp_wild(
- __inout efx_filter_spec_t *spec,
- __in unsigned int flags,
- __in uint32_t dest_ip,
- __in uint16_t dest_udp)
-{
- EFSYS_ASSERT3P(spec, !=, NULL);
- EFSYS_ASSERT((flags & ~(EFX_FILTER_FLAG_RX_RSS |
- EFX_FILTER_FLAG_RX_SCATTER)) == 0);
+ return (0);
- spec->efs_type = EFX_FILTER_RX_UDP_WILD;
- spec->efs_flags = (uint8_t)flags;
- spec->efs_dword[0] = dest_udp;
- spec->efs_dword[1] = 0;
- spec->efs_dword[2] = dest_ip;
-}
+fail2:
+ EFSYS_PROBE(fail2);
-#if EFSYS_OPT_SIENA
-extern void
-efx_filter_spec_rx_mac_full(
- __inout efx_filter_spec_t *spec,
- __in unsigned int flags,
- __in uint16_t vlan_id,
- __in uint8_t *dest_mac)
-{
- EFSYS_ASSERT3P(spec, !=, NULL);
- EFSYS_ASSERT3P(dest_mac, !=, NULL);
- EFSYS_ASSERT((flags & ~(EFX_FILTER_FLAG_RX_RSS |
- EFX_FILTER_FLAG_RX_SCATTER |
- EFX_FILTER_FLAG_RX_OVERRIDE_IP)) == 0);
-
- spec->efs_type = EFX_FILTER_RX_MAC_FULL;
- spec->efs_flags = (uint8_t)flags;
- spec->efs_dword[0] = vlan_id;
- spec->efs_dword[1] =
- dest_mac[2] << 24 |
- dest_mac[3] << 16 |
- dest_mac[4] << 8 |
- dest_mac[5];
- spec->efs_dword[2] =
- dest_mac[0] << 8 |
- dest_mac[1];
-}
-#endif /* EFSYS_OPT_SIENA */
+fail1:
+ EFSYS_PROBE1(fail1, int, rc);
-#if EFSYS_OPT_SIENA
-extern void
-efx_filter_spec_rx_mac_wild(
- __inout efx_filter_spec_t *spec,
- __in unsigned int flags,
- __in uint8_t *dest_mac)
-{
- EFSYS_ASSERT3P(spec, !=, NULL);
- EFSYS_ASSERT3P(dest_mac, !=, NULL);
- EFSYS_ASSERT((flags & ~(EFX_FILTER_FLAG_RX_RSS |
- EFX_FILTER_FLAG_RX_SCATTER |
- EFX_FILTER_FLAG_RX_OVERRIDE_IP)) == 0);
-
- spec->efs_type = EFX_FILTER_RX_MAC_WILD;
- spec->efs_flags = (uint8_t)flags;
- spec->efs_dword[0] = 0;
- spec->efs_dword[1] =
- dest_mac[2] << 24 |
- dest_mac[3] << 16 |
- dest_mac[4] << 8 |
- dest_mac[5];
- spec->efs_dword[2] =
- dest_mac[0] << 8 |
- dest_mac[1];
+ EFSYS_UNLOCK(enp->en_eslp, state);
+
+ return (rc);
}
-#endif /* EFSYS_OPT_SIENA */
-#if EFSYS_OPT_SIENA
-extern void
-efx_filter_spec_tx_ipv4_tcp_full(
+static __checkReturn int
+falconsiena_filter_add(
+ __in efx_nic_t *enp,
__inout efx_filter_spec_t *spec,
- __in uint32_t src_ip,
- __in uint16_t src_tcp,
- __in uint32_t dest_ip,
- __in uint16_t dest_tcp)
+ __in boolean_t may_replace)
{
- EFSYS_ASSERT3P(spec, !=, NULL);
+ int rc;
+ falconsiena_filter_spec_t fs_spec;
+ falconsiena_filter_t *fsfp = enp->en_filter.ef_falconsiena_filter;
+ falconsiena_filter_tbl_id_t tbl_id;
+ falconsiena_filter_tbl_t *fsftp;
+ falconsiena_filter_spec_t *saved_fs_spec;
+ efx_oword_t filter;
+ int filter_idx;
+ unsigned int depth;
+ int state;
+ uint32_t key;
- spec->efs_type = EFX_FILTER_TX_TCP_FULL;
- spec->efs_flags = 0;
- spec->efs_dword[0] = src_tcp | src_ip << 16;
- spec->efs_dword[1] = dest_tcp << 16 | src_ip >> 16;
- spec->efs_dword[2] = dest_ip;
-}
-#endif /* EFSYS_OPT_SIENA */
-#if EFSYS_OPT_SIENA
-extern void
-efx_filter_spec_tx_ipv4_tcp_wild(
- __inout efx_filter_spec_t *spec,
- __in uint32_t src_ip,
- __in uint16_t src_tcp)
-{
EFSYS_ASSERT3P(spec, !=, NULL);
- spec->efs_type = EFX_FILTER_TX_TCP_WILD;
- spec->efs_flags = 0;
- spec->efs_dword[0] = 0;
- spec->efs_dword[1] = src_tcp << 16;
- spec->efs_dword[2] = src_ip;
-}
-#endif /* EFSYS_OPT_SIENA */
+ if ((rc = falconsiena_filter_spec_from_gen_spec(&fs_spec, spec)) != 0)
+ goto fail1;
-#if EFSYS_OPT_SIENA
-extern void
-efx_filter_spec_tx_ipv4_udp_full(
- __inout efx_filter_spec_t *spec,
- __in uint32_t src_ip,
- __in uint16_t src_udp,
- __in uint32_t dest_ip,
- __in uint16_t dest_udp)
-{
- EFSYS_ASSERT3P(spec, !=, NULL);
+ tbl_id = falconsiena_filter_tbl_id(fs_spec.fsfs_type);
+ fsftp = &fsfp->fsf_tbl[tbl_id];
- spec->efs_type = EFX_FILTER_TX_UDP_FULL;
- spec->efs_flags = 0;
- spec->efs_dword[0] = src_udp | src_ip << 16;
- spec->efs_dword[1] = dest_udp << 16 | src_ip >> 16;
- spec->efs_dword[2] = dest_ip;
-}
-#endif /* EFSYS_OPT_SIENA */
+ if (fsftp->fsft_size == 0) {
+ rc = EINVAL;
+ goto fail2;
+ }
-#if EFSYS_OPT_SIENA
-extern void
-efx_filter_spec_tx_ipv4_udp_wild(
- __inout efx_filter_spec_t *spec,
- __in uint32_t src_ip,
- __in uint16_t src_udp)
-{
- EFSYS_ASSERT3P(spec, !=, NULL);
+ key = falconsiena_filter_build(&filter, &fs_spec);
+
+ EFSYS_LOCK(enp->en_eslp, state);
+
+ rc = falconsiena_filter_search(fsftp, &fs_spec, key, B_TRUE,
+ &filter_idx, &depth);
+ if (rc != 0)
+ goto fail3;
+
+ EFSYS_ASSERT3U(filter_idx, <, fsftp->fsft_size);
+ saved_fs_spec = &fsftp->fsft_spec[filter_idx];
+
+ if (falconsiena_filter_test_used(fsftp, filter_idx)) {
+ if (may_replace == B_FALSE) {
+ rc = EEXIST;
+ goto fail4;
+ }
+ }
+ falconsiena_filter_set_used(fsftp, filter_idx);
+ *saved_fs_spec = fs_spec;
+
+ if (fsfp->fsf_depth[fs_spec.fsfs_type] < depth) {
+ fsfp->fsf_depth[fs_spec.fsfs_type] = depth;
+ if (tbl_id == EFX_FS_FILTER_TBL_TX_IP ||
+ tbl_id == EFX_FS_FILTER_TBL_TX_MAC)
+ falconsiena_filter_push_tx_limits(enp);
+ else
+ falconsiena_filter_push_rx_limits(enp);
+ }
+
+ falconsiena_filter_push_entry(enp, fs_spec.fsfs_type,
+ filter_idx, &filter);
+
+ EFSYS_UNLOCK(enp->en_eslp, state);
+ return (0);
+
+fail4:
+ EFSYS_PROBE(fail4);
- spec->efs_type = EFX_FILTER_TX_UDP_WILD;
- spec->efs_flags = 0;
- spec->efs_dword[0] = src_udp;
- spec->efs_dword[1] = 0;
- spec->efs_dword[2] = src_ip;
+fail3:
+ EFSYS_UNLOCK(enp->en_eslp, state);
+ EFSYS_PROBE(fail3);
+
+fail2:
+ EFSYS_PROBE(fail2);
+
+fail1:
+ EFSYS_PROBE1(fail1, int, rc);
+ return (rc);
}
-#endif /* EFSYS_OPT_SIENA */
-#if EFSYS_OPT_SIENA
-extern void
-efx_filter_spec_tx_mac_full(
- __inout efx_filter_spec_t *spec,
- __in uint16_t vlan_id,
- __in uint8_t *src_mac)
+static __checkReturn int
+falconsiena_filter_delete(
+ __in efx_nic_t *enp,
+ __inout efx_filter_spec_t *spec)
{
+ int rc;
+ falconsiena_filter_spec_t fs_spec;
+ falconsiena_filter_t *fsfp = enp->en_filter.ef_falconsiena_filter;
+ falconsiena_filter_tbl_id_t tbl_id;
+ falconsiena_filter_tbl_t *fsftp;
+ falconsiena_filter_spec_t *saved_spec;
+ efx_oword_t filter;
+ int filter_idx;
+ unsigned int depth;
+ int state;
+ uint32_t key;
+
EFSYS_ASSERT3P(spec, !=, NULL);
- EFSYS_ASSERT3P(src_mac, !=, NULL);
-
- spec->efs_type = EFX_FILTER_TX_MAC_FULL;
- spec->efs_flags = 0;
- spec->efs_dword[0] = vlan_id;
- spec->efs_dword[1] =
- src_mac[2] << 24 |
- src_mac[3] << 16 |
- src_mac[4] << 8 |
- src_mac[5];
- spec->efs_dword[2] =
- src_mac[0] << 8 |
- src_mac[1];
+
+ if ((rc = falconsiena_filter_spec_from_gen_spec(&fs_spec, spec)) != 0)
+ goto fail1;
+
+ tbl_id = falconsiena_filter_tbl_id(fs_spec.fsfs_type);
+ fsftp = &fsfp->fsf_tbl[tbl_id];
+
+ key = falconsiena_filter_build(&filter, &fs_spec);
+
+ EFSYS_LOCK(enp->en_eslp, state);
+
+ rc = falconsiena_filter_search(fsftp, &fs_spec, key, B_FALSE,
+ &filter_idx, &depth);
+ if (rc != 0)
+ goto fail2;
+
+ saved_spec = &fsftp->fsft_spec[filter_idx];
+
+ falconsiena_filter_clear_entry(enp, fsftp, filter_idx);
+ if (fsftp->fsft_used == 0)
+ falconsiena_filter_reset_search_depth(fsfp, tbl_id);
+
+ EFSYS_UNLOCK(enp->en_eslp, state);
+ return (0);
+
+fail2:
+ EFSYS_UNLOCK(enp->en_eslp, state);
+ EFSYS_PROBE(fail2);
+
+fail1:
+ EFSYS_PROBE1(fail1, int, rc);
+ return (rc);
}
-#endif /* EFSYS_OPT_SIENA */
-#if EFSYS_OPT_SIENA
-extern void
-efx_filter_spec_tx_mac_wild(
- __inout efx_filter_spec_t *spec,
- __in uint8_t *src_mac)
+#define MAX_SUPPORTED 4
+
+static __checkReturn int
+falconsiena_filter_supported_filters(
+ __in efx_nic_t *enp,
+ __out uint32_t *list,
+ __out size_t *length)
{
- EFSYS_ASSERT3P(spec, !=, NULL);
- EFSYS_ASSERT3P(src_mac, !=, NULL);
-
- spec->efs_type = EFX_FILTER_TX_MAC_WILD;
- spec->efs_flags = 0;
- spec->efs_dword[0] = 0;
- spec->efs_dword[1] =
- src_mac[2] << 24 |
- src_mac[3] << 16 |
- src_mac[4] << 8 |
- src_mac[5];
- spec->efs_dword[2] =
- src_mac[0] << 8 |
- src_mac[1];
+ int index = 0;
+ uint32_t rx_matches[MAX_SUPPORTED];
+ int rc;
+
+ if (list == NULL) {
+ rc = EINVAL;
+ goto fail1;
+ }
+
+ rx_matches[index++] =
+ EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
+ EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT |
+ EFX_FILTER_MATCH_REM_HOST | EFX_FILTER_MATCH_REM_PORT;
+
+ rx_matches[index++] =
+ EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
+ EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT;
+
+ if (enp->en_features & EFX_FEATURE_MAC_HEADER_FILTERS) {
+ rx_matches[index++] =
+ EFX_FILTER_MATCH_OUTER_VID | EFX_FILTER_MATCH_LOC_MAC;
+
+ rx_matches[index++] = EFX_FILTER_MATCH_LOC_MAC;
+ }
+
+ EFSYS_ASSERT3U(index, <=, MAX_SUPPORTED);
+
+ *length = index;
+ memcpy(list, rx_matches, *length);
+
+ return (0);
+
+fail1:
+
+ return (rc);
}
-#endif /* EFSYS_OPT_SIENA */
+#undef MAX_SUPPORTED
+
+#endif /* EFSYS_OPT_FALCON || EFSYS_OPT_SIENA */
#endif /* EFSYS_OPT_FILTER */
OpenPOWER on IntegriCloud