Skip to content

Commit ae779bc

Browse files
committed
Merge branch 'net-stmmac-fix-vlan-handling-when-interface-is-down'
Ovidiu Panait says: ==================== net: stmmac: Fix VLAN handling when interface is down 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 Patch 4 fixes this by adding checks in the VLAN paths for netif_running(), and skipping register accesses if the interface is down. Only the software state is updated in this case. When the interface is brought up, the VLAN state is restored to hardware. Patches 1-3 fix some issues in the existing VLAN implementation. ==================== Link: https://patch.msgid.link/20260303145828.7845-1-ovidiu.panait.rb@renesas.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2 parents 550921c + 2cd70e3 commit ae779bc

3 files changed

Lines changed: 79 additions & 35 deletions

File tree

drivers/net/ethernet/stmicro/stmmac/stmmac.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ struct stmmac_priv {
323323
void __iomem *ptpaddr;
324324
void __iomem *estaddr;
325325
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
326+
unsigned int num_double_vlans;
326327
int sfty_irq;
327328
int sfty_ce_irq;
328329
int sfty_ue_irq;

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

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ static void stmmac_tx_timer_arm(struct stmmac_priv *priv, u32 queue);
156156
static void stmmac_flush_tx_descriptors(struct stmmac_priv *priv, int queue);
157157
static void stmmac_set_dma_operation_mode(struct stmmac_priv *priv, u32 txmode,
158158
u32 rxmode, u32 chan);
159+
static int stmmac_vlan_restore(struct stmmac_priv *priv);
159160

160161
#ifdef CONFIG_DEBUG_FS
161162
static const struct net_device_ops stmmac_netdev_ops;
@@ -4107,6 +4108,8 @@ static int __stmmac_open(struct net_device *dev,
41074108

41084109
phylink_start(priv->phylink);
41094110

4111+
stmmac_vlan_restore(priv);
4112+
41104113
ret = stmmac_request_irq(dev);
41114114
if (ret)
41124115
goto irq_error;
@@ -6766,6 +6769,9 @@ static int stmmac_vlan_update(struct stmmac_priv *priv, bool is_double)
67666769
hash = 0;
67676770
}
67686771

6772+
if (!netif_running(priv->dev))
6773+
return 0;
6774+
67696775
return stmmac_update_vlan_hash(priv, priv->hw, hash, pmatch, is_double);
67706776
}
67716777

@@ -6775,6 +6781,7 @@ static int stmmac_vlan_update(struct stmmac_priv *priv, bool is_double)
67756781
static int stmmac_vlan_rx_add_vid(struct net_device *ndev, __be16 proto, u16 vid)
67766782
{
67776783
struct stmmac_priv *priv = netdev_priv(ndev);
6784+
unsigned int num_double_vlans;
67786785
bool is_double = false;
67796786
int ret;
67806787

@@ -6786,17 +6793,24 @@ static int stmmac_vlan_rx_add_vid(struct net_device *ndev, __be16 proto, u16 vid
67866793
is_double = true;
67876794

67886795
set_bit(vid, priv->active_vlans);
6789-
ret = stmmac_vlan_update(priv, is_double);
6796+
num_double_vlans = priv->num_double_vlans + is_double;
6797+
ret = stmmac_vlan_update(priv, num_double_vlans);
67906798
if (ret) {
67916799
clear_bit(vid, priv->active_vlans);
67926800
goto err_pm_put;
67936801
}
67946802

67956803
if (priv->hw->num_vlan) {
67966804
ret = stmmac_add_hw_vlan_rx_fltr(priv, ndev, priv->hw, proto, vid);
6797-
if (ret)
6805+
if (ret) {
6806+
clear_bit(vid, priv->active_vlans);
6807+
stmmac_vlan_update(priv, priv->num_double_vlans);
67986808
goto err_pm_put;
6809+
}
67996810
}
6811+
6812+
priv->num_double_vlans = num_double_vlans;
6813+
68006814
err_pm_put:
68016815
pm_runtime_put(priv->device);
68026816

@@ -6809,6 +6823,7 @@ static int stmmac_vlan_rx_add_vid(struct net_device *ndev, __be16 proto, u16 vid
68096823
static int stmmac_vlan_rx_kill_vid(struct net_device *ndev, __be16 proto, u16 vid)
68106824
{
68116825
struct stmmac_priv *priv = netdev_priv(ndev);
6826+
unsigned int num_double_vlans;
68126827
bool is_double = false;
68136828
int ret;
68146829

@@ -6820,21 +6835,47 @@ static int stmmac_vlan_rx_kill_vid(struct net_device *ndev, __be16 proto, u16 vi
68206835
is_double = true;
68216836

68226837
clear_bit(vid, priv->active_vlans);
6838+
num_double_vlans = priv->num_double_vlans - is_double;
6839+
ret = stmmac_vlan_update(priv, num_double_vlans);
6840+
if (ret) {
6841+
set_bit(vid, priv->active_vlans);
6842+
goto del_vlan_error;
6843+
}
68236844

68246845
if (priv->hw->num_vlan) {
68256846
ret = stmmac_del_hw_vlan_rx_fltr(priv, ndev, priv->hw, proto, vid);
6826-
if (ret)
6847+
if (ret) {
6848+
set_bit(vid, priv->active_vlans);
6849+
stmmac_vlan_update(priv, priv->num_double_vlans);
68276850
goto del_vlan_error;
6851+
}
68286852
}
68296853

6830-
ret = stmmac_vlan_update(priv, is_double);
6854+
priv->num_double_vlans = num_double_vlans;
68316855

68326856
del_vlan_error:
68336857
pm_runtime_put(priv->device);
68346858

68356859
return ret;
68366860
}
68376861

6862+
static int stmmac_vlan_restore(struct stmmac_priv *priv)
6863+
{
6864+
int ret;
6865+
6866+
if (!(priv->dev->features & NETIF_F_VLAN_FEATURES))
6867+
return 0;
6868+
6869+
if (priv->hw->num_vlan)
6870+
stmmac_restore_hw_vlan_rx_fltr(priv, priv->dev, priv->hw);
6871+
6872+
ret = stmmac_vlan_update(priv, priv->num_double_vlans);
6873+
if (ret)
6874+
netdev_err(priv->dev, "Failed to restore VLANs\n");
6875+
6876+
return ret;
6877+
}
6878+
68386879
static int stmmac_bpf(struct net_device *dev, struct netdev_bpf *bpf)
68396880
{
68406881
struct stmmac_priv *priv = netdev_priv(dev);
@@ -8259,10 +8300,10 @@ int stmmac_resume(struct device *dev)
82598300
stmmac_init_coalesce(priv);
82608301
phylink_rx_clk_stop_block(priv->phylink);
82618302
stmmac_set_rx_mode(ndev);
8262-
8263-
stmmac_restore_hw_vlan_rx_fltr(priv, ndev, priv->hw);
82648303
phylink_rx_clk_stop_unblock(priv->phylink);
82658304

8305+
stmmac_vlan_restore(priv);
8306+
82668307
stmmac_enable_all_queues(priv);
82678308
stmmac_enable_all_dma_irq(priv);
82688309

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

Lines changed: 31 additions & 29 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,25 +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-
void __iomem *ioaddr = hw->pcsr;
143-
u32 value;
144-
u32 hash;
145-
u32 val;
146151
int i;
147152

148153
/* Single Rx VLAN Filter */
@@ -152,19 +157,8 @@ static void vlan_restore_hw_rx_fltr(struct net_device *dev,
152157
}
153158

154159
/* Extended Rx VLAN Filter Enable */
155-
for (i = 0; i < hw->num_vlan; i++) {
156-
if (hw->vlan_filter[i] & VLAN_TAG_DATA_VEN) {
157-
val = hw->vlan_filter[i];
158-
vlan_write_filter(dev, hw, i, val);
159-
}
160-
}
161-
162-
hash = readl(ioaddr + VLAN_HASH_TABLE);
163-
if (hash & VLAN_VLHT) {
164-
value = readl(ioaddr + VLAN_TAG);
165-
value |= VLAN_VTHM;
166-
writel(value, ioaddr + VLAN_TAG);
167-
}
160+
for (i = 0; i < hw->num_vlan; i++)
161+
vlan_write_filter(dev, hw, i, hw->vlan_filter[i]);
168162
}
169163

170164
static void vlan_update_hash(struct mac_device_info *hw, u32 hash,
@@ -183,6 +177,10 @@ static void vlan_update_hash(struct mac_device_info *hw, u32 hash,
183177
value |= VLAN_EDVLP;
184178
value |= VLAN_ESVL;
185179
value |= VLAN_DOVLTC;
180+
} else {
181+
value &= ~VLAN_EDVLP;
182+
value &= ~VLAN_ESVL;
183+
value &= ~VLAN_DOVLTC;
186184
}
187185

188186
writel(value, ioaddr + VLAN_TAG);
@@ -193,6 +191,10 @@ static void vlan_update_hash(struct mac_device_info *hw, u32 hash,
193191
value |= VLAN_EDVLP;
194192
value |= VLAN_ESVL;
195193
value |= VLAN_DOVLTC;
194+
} else {
195+
value &= ~VLAN_EDVLP;
196+
value &= ~VLAN_ESVL;
197+
value &= ~VLAN_DOVLTC;
196198
}
197199

198200
writel(value | perfect_match, ioaddr + VLAN_TAG);

0 commit comments

Comments
 (0)