Skip to content

Commit c52f641

Browse files
Ovidiu PanaitSasha Levin
authored andcommitted
net: stmmac: Defer VLAN HW configuration when interface is down
[ Upstream commit 2cd70e3 ] VLAN register accesses on the MAC side require the PHY RX clock to be active. When the network interface is down, the PHY is suspended and the RX clock is unavailable, causing VLAN operations to fail with timeouts. The VLAN core automatically removes VID 0 after the interface goes down and re-adds it when it comes back up, so these timeouts happen during normal interface down/up: # 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 Adding VLANs while the interface is down also fails: # ip link add link end1 name end1.10 type vlan id 10 renesas-gbeth 15c40000.ethernet end1: Timeout accessing MAC_VLAN_Tag_Filter RTNETLINK answers: Device or resource busy To fix this, check if the interface is up before accessing VLAN registers. The software state is always kept up to date regardless of interface state. When the interface is brought up, stmmac_vlan_restore() is called to write the VLAN state to hardware. Fixes: ed64639 ("net: stmmac: Add support for VLAN Rx filtering") Signed-off-by: Ovidiu Panait <ovidiu.panait.rb@renesas.com> Link: https://patch.msgid.link/20260303145828.7845-5-ovidiu.panait.rb@renesas.com Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 0b03f84 commit c52f641

2 files changed

Lines changed: 26 additions & 19 deletions

File tree

drivers/net/ethernet/stmicro/stmmac/stmmac_main.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6721,6 +6721,9 @@ static int stmmac_vlan_update(struct stmmac_priv *priv, bool is_double)
67216721
hash = 0;
67226722
}
67236723

6724+
if (!netif_running(priv->dev))
6725+
return 0;
6726+
67246727
return stmmac_update_vlan_hash(priv, priv->hw, hash, pmatch, is_double);
67256728
}
67266729

drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,9 @@ static int vlan_add_hw_rx_fltr(struct net_device *dev,
7676
}
7777

7878
hw->vlan_filter[0] = vid;
79-
vlan_write_single(dev, vid);
79+
80+
if (netif_running(dev))
81+
vlan_write_single(dev, vid);
8082

8183
return 0;
8284
}
@@ -97,12 +99,15 @@ static int vlan_add_hw_rx_fltr(struct net_device *dev,
9799
return -EPERM;
98100
}
99101

100-
ret = vlan_write_filter(dev, hw, index, val);
102+
if (netif_running(dev)) {
103+
ret = vlan_write_filter(dev, hw, index, val);
104+
if (ret)
105+
return ret;
106+
}
101107

102-
if (!ret)
103-
hw->vlan_filter[index] = val;
108+
hw->vlan_filter[index] = val;
104109

105-
return ret;
110+
return 0;
106111
}
107112

108113
static int vlan_del_hw_rx_fltr(struct net_device *dev,
@@ -115,7 +120,9 @@ static int vlan_del_hw_rx_fltr(struct net_device *dev,
115120
if (hw->num_vlan == 1) {
116121
if ((hw->vlan_filter[0] & VLAN_TAG_VID) == vid) {
117122
hw->vlan_filter[0] = 0;
118-
vlan_write_single(dev, 0);
123+
124+
if (netif_running(dev))
125+
vlan_write_single(dev, 0);
119126
}
120127
return 0;
121128
}
@@ -124,22 +131,23 @@ static int vlan_del_hw_rx_fltr(struct net_device *dev,
124131
for (i = 0; i < hw->num_vlan; i++) {
125132
if ((hw->vlan_filter[i] & VLAN_TAG_DATA_VEN) &&
126133
((hw->vlan_filter[i] & VLAN_TAG_DATA_VID) == vid)) {
127-
ret = vlan_write_filter(dev, hw, i, 0);
128134

129-
if (!ret)
130-
hw->vlan_filter[i] = 0;
131-
else
132-
return ret;
135+
if (netif_running(dev)) {
136+
ret = vlan_write_filter(dev, hw, i, 0);
137+
if (ret)
138+
return ret;
139+
}
140+
141+
hw->vlan_filter[i] = 0;
133142
}
134143
}
135144

136-
return ret;
145+
return 0;
137146
}
138147

139148
static void vlan_restore_hw_rx_fltr(struct net_device *dev,
140149
struct mac_device_info *hw)
141150
{
142-
u32 val;
143151
int i;
144152

145153
/* Single Rx VLAN Filter */
@@ -149,12 +157,8 @@ static void vlan_restore_hw_rx_fltr(struct net_device *dev,
149157
}
150158

151159
/* Extended Rx VLAN Filter Enable */
152-
for (i = 0; i < hw->num_vlan; i++) {
153-
if (hw->vlan_filter[i] & VLAN_TAG_DATA_VEN) {
154-
val = hw->vlan_filter[i];
155-
vlan_write_filter(dev, hw, i, val);
156-
}
157-
}
160+
for (i = 0; i < hw->num_vlan; i++)
161+
vlan_write_filter(dev, hw, i, hw->vlan_filter[i]);
158162
}
159163

160164
static void vlan_update_hash(struct mac_device_info *hw, u32 hash,

0 commit comments

Comments
 (0)