summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSerge Semin <fancer.lancer@gmail.com>2026-08-12 10:24:04 +0300
committerSerge Semin <fancer.lancer@gmail.com>2026-08-13 20:34:38 +0300
commit13f0c6abd92b8c772492b68e511e9bb58e92e5eb (patch)
treec1390828bc0ae627f3fec0467fa4bb4a49d7a98a
parent8275a29fddf22f5a588347585b9cc6ea2ee91b7a (diff)
downloadlinux-13f0c6abd92b8c772492b68e511e9bb58e92e5eb.tar.gz
linux-13f0c6abd92b8c772492b68e511e9bb58e92e5eb.zip
net: stmmac: vlan: Avoid writing to MAC_VLAN_Tag_Filter on iface down
It was found out that the problem with the VLAN filters setting up is in the missing PHY RXC clock when EEE is enabled and the interface being down. As a result any attempt to create a virtual VLAN interface causes the error like: # ip link add link end1 name end1.5 type vlan id 5 15c40000.ethernet end1: Timeout accessing MAC_VLAN_Tag_Filter RTNETLINK answers: Device or resource busy # ip link set end1 down renesas-gbeth 15c40000.ethernet end1: Timeout accessing MAC_VLAN_Tag_Filter renesas-gbeth 15c40000.ethernet end1: failed to kill vid 0081/0 This was fixed in the commit c171e679ee66 ("net: stmmac: Disable EEE RX clock stop when VLAN is enabled") and commit 2cd70e3968f5 ("net: stmmac: Defer VLAN HW configuration when interface is down"). So the problem is no longer exist. But the later commit has turned to be too aggressive in fixing it by adding the netif_running() check on each VLAN CSRs access. In the meantime writing to the normal MAC VLAN CSRs won't cause any problem, the timeout happens only in the MAC_VLAN_Tag_Filter indirect access. See the log messages above. So let's drop the redundant netif_running() checks and add a single one to the vlan_write_filter() method. The method will return -EAGAIN error in case if the access could be performed right now so the callee would do that again later when the interface is brought up. Signed-off-by: Serge Semin <fancer.lancer@gmail.com>
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_main.c3
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c30
2 files changed, 16 insertions, 17 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 14027a0e34d6..d746064011ab 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -7138,9 +7138,6 @@ static int stmmac_vlan_update(struct stmmac_priv *priv, bool is_svlan)
hash |= (1 << crc);
}
- if (!netif_running(priv->dev))
- return 0;
-
return stmmac_update_vlan_hash(priv, priv->hw, hash, is_svlan);
}
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c
index a6ade06a7ae0..293589addf2d 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c
@@ -33,6 +33,14 @@ static int vlan_write_filter(struct net_device *dev,
if (index >= hw->num_vlan)
return -EINVAL;
+ /* Indirect VLAN Tag filter access inteface requires PHY RXC clock to
+ * be running. Retry when the interface is up.
+ */
+ if (!netif_running(dev)) {
+ netdev_dbg(dev, "Skip writing Extended VLAN filter entry\n");
+ return -EAGAIN;
+ }
+
writel(data, ioaddr + VLAN_TAG_DATA);
val = readl(ioaddr + VLAN_TAG);
@@ -88,8 +96,7 @@ static int vlan_add_hw_rx_fltr(struct net_device *dev,
return -EPERM;
}
- if (netif_running(dev))
- vlan_write_single(dev, val);
+ vlan_write_single(dev, val);
hw->vlan_filter[0] = val;
@@ -114,11 +121,9 @@ static int vlan_add_hw_rx_fltr(struct net_device *dev,
return -EPERM;
}
- if (netif_running(dev)) {
- ret = vlan_write_filter(dev, hw, index, val);
- if (ret)
- return ret;
- }
+ ret = vlan_write_filter(dev, hw, index, val);
+ if (ret && ret != -EAGAIN)
+ return ret;
hw->vlan_filter[index] = val;
@@ -142,8 +147,7 @@ static int vlan_del_hw_rx_fltr(struct net_device *dev,
if (is_stag != !!(hw->vlan_filter[0] & VLAN_TAG_ERSVLM))
return 0;
- if (netif_running(dev))
- vlan_write_single(dev, 0);
+ vlan_write_single(dev, 0);
hw->vlan_filter[0] = 0;
@@ -161,11 +165,9 @@ static int vlan_del_hw_rx_fltr(struct net_device *dev,
if (is_stag != !!(hw->vlan_filter[i] & VLAN_TAG_DATA_ERSVLM))
continue;
- if (netif_running(dev)) {
- ret = vlan_write_filter(dev, hw, i, 0);
- if (ret)
- return ret;
- }
+ ret = vlan_write_filter(dev, hw, i, 0);
+ if (ret && ret != -EAGAIN)
+ return ret;
hw->vlan_filter[i] = 0;
}