aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Price <nick@spun.io>2026-07-19 16:40:36 +0000
committerAdrian Chadd <adrian@FreeBSD.org>2026-07-19 16:40:36 +0000
commitdcede1ec9de3b24fc9fbeeebc99ca34d226995f9 (patch)
treed0de3df25cdeb26fb455a09b2a3df869f01b3a41
parentd6915bffb7b68d9b55fa3db4e5709463549c379e (diff)
-rw-r--r--sys/dev/aq/aq_hw.c3
-rw-r--r--sys/dev/aq/aq_hw_llh.c8
-rw-r--r--sys/dev/aq/aq_hw_llh.h4
-rw-r--r--sys/dev/aq/aq_hw_llh_internal.h13
-rw-r--r--sys/dev/aq/aq_main.c43
-rw-r--r--sys/dev/aq/aq_ring.c10
6 files changed, 62 insertions, 19 deletions
diff --git a/sys/dev/aq/aq_hw.c b/sys/dev/aq/aq_hw.c
index da07c876b959..1ad9d2e15ed7 100644
--- a/sys/dev/aq/aq_hw.c
+++ b/sys/dev/aq/aq_hw.c
@@ -459,6 +459,9 @@ aq_hw_offload_set(struct aq_hw *hw)
/* LSO offloads*/
tdm_large_send_offload_en_set(hw, 0xFFFFFFFFU);
+ /* Outer (S-VLAN) tag parse mode */
+ rpo_outer_vlan_tag_mode_set(hw, 1U);
+
{
uint32_t i = 0;
uint32_t val = (8U < HW_ATL_B0_LRO_RXD_MAX) ? 0x3U :
diff --git a/sys/dev/aq/aq_hw_llh.c b/sys/dev/aq/aq_hw_llh.c
index eb053a4bdce6..dba02c467e55 100644
--- a/sys/dev/aq/aq_hw_llh.c
+++ b/sys/dev/aq/aq_hw_llh.c
@@ -1442,6 +1442,14 @@ rpo_tcp_udp_crc_offload_en_set(struct aq_hw *aq_hw,
}
void
+rpo_outer_vlan_tag_mode_set(struct aq_hw *aq_hw, uint32_t outer_vlan_tag_mode)
+{
+ AQ_WRITE_REG_BIT(aq_hw, rpo_outer_vl_ins_mode_adr,
+ rpo_outer_vl_ins_mode_msk, rpo_outer_vl_ins_mode_shift,
+ outer_vlan_tag_mode);
+}
+
+void
rpo_lro_en_set(struct aq_hw *aq_hw, uint32_t lro_en)
{
AQ_WRITE_REG(aq_hw, rpo_lro_en_adr, lro_en);
diff --git a/sys/dev/aq/aq_hw_llh.h b/sys/dev/aq/aq_hw_llh.h
index 68cc666be1a3..47011295aa4c 100644
--- a/sys/dev/aq/aq_hw_llh.h
+++ b/sys/dev/aq/aq_hw_llh.h
@@ -808,6 +808,10 @@ void rpo_rx_desc_vlan_stripping_set(struct aq_hw *aq_hw,
void rpo_tcp_udp_crc_offload_en_set(struct aq_hw *aq_hw,
uint32_t tcp_udp_crc_offload_en);
+/* set RX outer (S-VLAN) tag parse mode */
+void rpo_outer_vlan_tag_mode_set(struct aq_hw *aq_hw,
+ uint32_t outer_vlan_tag_mode);
+
/* Set LRO Patch Optimization Enable. */
void rpo_lro_patch_optimization_en_set(struct aq_hw *aq_hw,
uint32_t lro_patch_optimization_en);
diff --git a/sys/dev/aq/aq_hw_llh_internal.h b/sys/dev/aq/aq_hw_llh_internal.h
index bad3c1640cf8..fa1c9a83985b 100644
--- a/sys/dev/aq/aq_hw_llh_internal.h
+++ b/sys/dev/aq/aq_hw_llh_internal.h
@@ -2145,6 +2145,19 @@
/* default value of bitfield ipv4_chk_en */
#define rpo_ipv4chk_en_default 0x0
+/* register address for bitfield outer_vl_ins_mode */
+#define rpo_outer_vl_ins_mode_adr 0x00005580
+/* bitmask for bitfield outer_vl_ins_mode */
+#define rpo_outer_vl_ins_mode_msk 0x00000004
+/* inverted bitmask for bitfield outer_vl_ins_mode */
+#define rpo_outer_vl_ins_mode_mskn 0xfffffffb
+/* lower bit position of bitfield outer_vl_ins_mode */
+#define rpo_outer_vl_ins_mode_shift 2
+/* width of bitfield outer_vl_ins_mode */
+#define rpo_outer_vl_ins_mode_width 1
+/* default value of bitfield outer_vl_ins_mode */
+#define rpo_outer_vl_ins_mode_default 0x0
+
/* rx desc{d}_vl_strip bitfield definitions
* preprocessor definitions for the bitfield "desc{d}_vl_strip".
* parameter: descriptor {d} | stride size 0x20 | range [0, 31]
diff --git a/sys/dev/aq/aq_main.c b/sys/dev/aq/aq_main.c
index d4f687fee8f1..5d2d9061c548 100644
--- a/sys/dev/aq/aq_main.c
+++ b/sys/dev/aq/aq_main.c
@@ -371,10 +371,12 @@ aq_if_attach_pre(if_ctx_t ctx)
softc->admin_ticks = 0;
iflib_set_mac(ctx, hw->mac_addr);
- scctx->isc_tx_csum_flags = CSUM_IP | CSUM_TCP | CSUM_UDP | CSUM_TSO;
+ scctx->isc_tx_csum_flags = CSUM_IP | CSUM_TCP | CSUM_UDP | CSUM_TSO |
+ CSUM_IP6_TCP | CSUM_IP6_UDP | CSUM_IP6_TSO;
scctx->isc_capabilities = IFCAP_RXCSUM | IFCAP_TXCSUM | IFCAP_HWCSUM |
- IFCAP_TSO | IFCAP_LRO | IFCAP_JUMBO_MTU | IFCAP_VLAN_HWFILTER |
- IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_HWCSUM;
+ IFCAP_HWCSUM_IPV6 | IFCAP_TSO | IFCAP_LRO | IFCAP_JUMBO_MTU |
+ IFCAP_VLAN_HWFILTER | IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING |
+ IFCAP_VLAN_HWCSUM | IFCAP_VLAN_HWTSO;
scctx->isc_capenable = scctx->isc_capabilities;
scctx->isc_tx_nsegments = 31;
scctx->isc_tx_tso_segments_max = 31;
@@ -739,6 +741,11 @@ aq_if_init(if_ctx_t ctx)
aq_hw_udp_rss_enable(hw, aq_enable_rss_udp);
aq_hw_set_link_speed(hw, hw->link_rate);
+ /* iflib does not replay filter state after init; aq_hw_init() clears it. */
+ aq_if_multi_set(ctx);
+ if (aq_if_promisc_set(ctx, if_getflags(iflib_get_ifp(ctx))) != 0)
+ device_printf(softc->dev, "could not restore promiscuous mode\n");
+
AQ_DBG_EXIT(0);
}
@@ -822,14 +829,18 @@ aq_if_multi_set(if_ctx_t ctx)
if_t ifp = iflib_get_ifp(ctx);
struct aq_hw *hw = &softc->hw;
AQ_DBG_ENTER();
- softc->mcnt = if_llmaddr_count(iflib_get_ifp(ctx));
- if (softc->mcnt >= AQ_HW_MAC_MAX) {
- aq_hw_set_promisc(hw, !!(if_getflags(ifp) & IFF_PROMISC),
- aq_is_vlan_promisc_required(softc),
- !!(if_getflags(ifp) & IFF_ALLMULTI) || aq_is_mc_promisc_required(softc));
- } else {
- if_foreach_llmaddr(iflib_get_ifp(ctx), &aq_mc_filter_apply, softc);
+ softc->mcnt = if_llmaddr_count(ifp);
+
+ /* Reconcile HW to the current list: clear stale slots, reprogram. */
+ if (softc->mcnt < AQ_HW_MAC_MAX) {
+ for (int i = 1; i < AQ_HW_MAC_MAX; i++)
+ rpfl2_uc_flr_en_set(hw, 0U, i);
+ if_foreach_llmaddr(ifp, &aq_mc_filter_apply, softc);
}
+
+ aq_hw_set_promisc(hw, !!(if_getflags(ifp) & IFF_PROMISC),
+ aq_is_vlan_promisc_required(softc),
+ !!(if_getflags(ifp) & IFF_ALLMULTI) || aq_is_mc_promisc_required(softc));
AQ_DBG_EXIT(0);
}
@@ -1056,11 +1067,9 @@ aq_is_vlan_promisc_required(struct aq_dev *softc)
bit_count(softc->vlan_tags, 0, 4096, &vlan_tag_count);
- if (vlan_tag_count <= AQ_HW_VLAN_MAX_FILTERS)
- return (false);
- else
- return (true);
-
+ /* Filter only with 1..16 VLANs; 0 or >16 pass all tags. */
+ return (vlan_tag_count == 0 ||
+ vlan_tag_count > AQ_HW_VLAN_MAX_FILTERS);
}
static void
@@ -1087,7 +1096,9 @@ aq_update_vlan_filters(struct aq_dev *softc)
}
hw_atl_b0_hw_vlan_set(hw, aq_vlans);
- hw_atl_b0_hw_vlan_promisc_set(hw, aq_is_vlan_promisc_required(softc));
+ hw_atl_b0_hw_vlan_promisc_set(hw,
+ aq_is_vlan_promisc_required(softc) ||
+ (if_getflags(iflib_get_ifp(softc->ctx)) & IFF_PROMISC) != 0);
}
/* VLAN support */
diff --git a/sys/dev/aq/aq_ring.c b/sys/dev/aq/aq_ring.c
index 311a5c9abf28..8307fb0b3474 100644
--- a/sys/dev/aq/aq_ring.c
+++ b/sys/dev/aq/aq_ring.c
@@ -110,7 +110,9 @@ aq_ring_rx_init(struct aq_hw *hw, struct aq_ring *ring)
rdm_rx_desc_head_buff_size_set(hw, 0U, ring->index);
rdm_rx_desc_head_splitting_set(hw, 0U, ring->index);
- rpo_rx_desc_vlan_stripping_set(hw, 0U, ring->index);
+ rpo_rx_desc_vlan_stripping_set(hw,
+ (if_getcapenable(iflib_get_ifp(ring->dev->ctx)) &
+ IFCAP_VLAN_HWTAGGING) != 0 ? 1U : 0U, ring->index);
/* Rx ring set mode */
@@ -363,7 +365,8 @@ aq_isc_rxd_pkt_get(void *arg, if_rxd_info_t ri)
ri->iri_frags[i].irf_idx = cidx;
ri->iri_frags[i].irf_len = len;
- if ((rx_desc->wb.pkt_type & 0x60) != 0) {
+ if ((if_getcapenable(ifp) & IFCAP_VLAN_HWTAGGING) != 0 &&
+ (rx_desc->wb.pkt_type & 0x60) != 0) {
ri->iri_flags |= M_VLANTAG;
ri->iri_vtag = le32toh(rx_desc->wb.vlan);
}
@@ -405,7 +408,8 @@ aq_setup_offloads(struct aq_dev *aq_dev, if_pkt_info_t pi, volatile struct aq_tx
{
AQ_DBG_ENTER();
txd->cmd |= tx_desc_cmd_fcs;
- txd->cmd |= (pi->ipi_csum_flags & (CSUM_IP|CSUM_TSO)) ?
+ txd->cmd |= ((pi->ipi_flags & IPI_TX_IPV4) &&
+ (pi->ipi_csum_flags & (CSUM_IP | CSUM_IP_TSO))) ?
tx_desc_cmd_ipv4 : 0;
txd->cmd |= (pi->ipi_csum_flags & (CSUM_IP_TCP | CSUM_IP6_TCP |
CSUM_IP_UDP | CSUM_IP6_UDP)) ? tx_desc_cmd_l4cs : 0;