diff options
| author | Serge Semin <fancer.lancer@gmail.com> | 2026-08-12 10:24:04 +0300 |
|---|---|---|
| committer | Serge Semin <fancer.lancer@gmail.com> | 2026-08-13 20:34:38 +0300 |
| commit | 13f0c6abd92b8c772492b68e511e9bb58e92e5eb (patch) | |
| tree | c1390828bc0ae627f3fec0467fa4bb4a49d7a98a | |
| parent | 8275a29fddf22f5a588347585b9cc6ea2ee91b7a (diff) | |
| download | linux-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.c | 3 | ||||
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c | 30 |
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; } |
