summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSerge Semin <fancer.lancer@gmail.com>2025-04-16 21:01:02 +0300
committerSerge Semin <fancer.lancer@gmail.com>2026-08-13 20:34:12 +0300
commitd6cd34229a19ff94da813d53bc5845748a590f22 (patch)
treefc6b03098ca09796985efa83913ef4205de5f71d
parent28b7ceecaa507209e6e7224241f253d0c6887f08 (diff)
downloadlinux-d6cd34229a19ff94da813d53bc5845748a590f22.tar.gz
linux-d6cd34229a19ff94da813d53bc5845748a590f22.zip
net: stmmac: vlan: Fix VLAN_TAG register override on perfect-match
The stmmac_vlan_update() method falls back to the basic perfect filter case if no VLAN hash filter detected. In that case the method completely overrides the VLAN_TAG register clearing the settings like EVLRXS or EVLS, which are required for the VLAN interface to work correctly. For instance EVLRXS activates VLAN Tag in Rx status getting the Rx DMA-descriptors. So let's fix that in a way it has been done for DW XGMAC VLAN in commit 907a076881f1 ("net: stmmac: xgmac: fix incorrect XGMAC_VLAN_TAG register writting") - by using the already read value of the VLAN_TAG register. Fixes: c7ab0b8088d7 ("net: stmmac: Fallback to VLAN Perfect filtering if HASH is not available") Signed-off-by: Serge Semin <fancer.lancer@gmail.com>
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c5
1 files changed, 3 insertions, 2 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c
index 7f1e34e62eee..c553cf6b772e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c
@@ -216,8 +216,8 @@ static void vlan_update_hash(struct mac_device_info *hw, u32 hash,
writel(value, ioaddr + VLAN_TAG);
} else if (perfect_match) {
- u32 value = VLAN_ETV;
-
+ value &= ~VLAN_VTHM;
+ value |= VLAN_ETV;
if (is_double) {
value |= VLAN_EDVLP;
value |= VLAN_ESVL;
@@ -228,6 +228,7 @@ static void vlan_update_hash(struct mac_device_info *hw, u32 hash,
value &= ~VLAN_DOVLTC;
}
+ value &= ~VLAN_VID;
writel(value | perfect_match, ioaddr + VLAN_TAG);
} else {
value &= ~(VLAN_VTHM | VLAN_ETV);