From 34cc22a9ce6ae0228dcd09a57df23aea62e22b04 Mon Sep 17 00:00:00 2001 From: Alexander Goodkind Date: Thu, 29 Oct 2026 18:05:17 -0700 Subject: [PATCH] net: ethernet: mediatek: preserve sibling PPE bindings __mtk_ppe_check_skb() clears entry->hash for flows bound to other hardware slots in the same software hash bucket. mtk_flow_offload_stats() then skips their hardware counter updates. L2 cleanup also frees sibling subflows without invalidating their hardware rules. Restrict both cleanup paths to entries assigned to the inspected slot. Two UDP trials reproduced the counter failure on a GL-MT3000/MT7981 running unmodified OpenWrt 25.12.5 with Linux 6.12.94: 1. Start a UDP connection. 2. Add a control connection in a different hash bucket. 3. Add a connection in the first connection's hash bucket. AI code review of the original patch identified the cleanup problem in L2 subflows. Full ARM64 builds with allmodconfig and allyesconfig passed before and after the patch using GCC 14.2.0 and W=1, without new warnings. The builds used CONFIG_WERROR=n because the unmodified ARM64 kernel already emits warnings. Hardware testing has not run for this revision. Fixes: c4f033d9e03e ("net: ethernet: mtk_eth_soc: rework hardware flow table management") Fixes: 33fc42de3327 ("net: ethernet: mtk_eth_soc: support creating mac address based offload entries") Link: https://github.com/openwrt/openwrt/pull/26107 Signed-off-by: Alexander Goodkind Reviewed-by: Simon Horman Link: https://patch.msgid.link/20261030010517.45639-1-alex@goodkind.io Signed-off-by: Paolo Abeni --- drivers/net/ethernet/mediatek/mtk_ppe.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c index 8451dc3fd00a..d8fa1f2b4324 100644 --- a/drivers/net/ethernet/mediatek/mtk_ppe.c +++ b/drivers/net/ethernet/mediatek/mtk_ppe.c @@ -754,8 +754,7 @@ void __mtk_ppe_check_skb(struct mtk_ppe *ppe, struct sk_buff *skb, u16 hash) hlist_for_each_entry_safe(entry, n, head, list) { if (entry->type == MTK_FLOW_TYPE_L2_SUBFLOW) { - if (unlikely(FIELD_GET(MTK_FOE_IB1_STATE, hwe->ib1) == - MTK_FOE_STATE_BIND)) + if (entry->hash != hash) continue; entry->hash = 0xffff; @@ -764,7 +763,7 @@ void __mtk_ppe_check_skb(struct mtk_ppe *ppe, struct sk_buff *skb, u16 hash) } if (found || !mtk_flow_entry_match(ppe->eth, entry, hwe)) { - if (entry->hash != 0xffff) + if (entry->hash == hash) entry->hash = 0xffff; continue; }