Skip to content

Commit 0b03f84

Browse files
Ovidiu PanaitSasha Levin
authored andcommitted
net: stmmac: Fix VLAN HW state restore
[ Upstream commit bd7ad51 ] When the network interface is opened or resumed, a DMA reset is performed, which resets all hardware state, including VLAN state. Currently, only the resume path is restoring the VLAN state via stmmac_restore_hw_vlan_rx_fltr(), but that is incomplete: the VLAN hash table and the VLAN_TAG control bits are not restored. Therefore, add stmmac_vlan_restore(), which restores the full VLAN state by updating both the HW filter entries and the hash table, and call it from both the open and resume paths. The VLAN restore is moved outside of phylink_rx_clk_stop_block/unblock in the resume path because receive clock stop is already disabled when stmmac supports VLAN. Also, remove the hash readback code in vlan_restore_hw_rx_fltr() that attempts to restore VTHM by reading VLAN_HASH_TABLE, as it always reads zero after DMA reset, making it dead code. Fixes: 3cd1cfc ("net: stmmac: Implement VLAN Hash Filtering in XGMAC") 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-4-ovidiu.panait.rb@renesas.com Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 0f11b10 commit 0b03f84

2 files changed

Lines changed: 22 additions & 12 deletions

File tree

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

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ static void stmmac_tx_timer_arm(struct stmmac_priv *priv, u32 queue);
140140
static void stmmac_flush_tx_descriptors(struct stmmac_priv *priv, int queue);
141141
static void stmmac_set_dma_operation_mode(struct stmmac_priv *priv, u32 txmode,
142142
u32 rxmode, u32 chan);
143+
static int stmmac_vlan_restore(struct stmmac_priv *priv);
143144

144145
#ifdef CONFIG_DEBUG_FS
145146
static const struct net_device_ops stmmac_netdev_ops;
@@ -4064,6 +4065,8 @@ static int __stmmac_open(struct net_device *dev,
40644065

40654066
phylink_start(priv->phylink);
40664067

4068+
stmmac_vlan_restore(priv);
4069+
40674070
ret = stmmac_request_irq(dev);
40684071
if (ret)
40694072
goto irq_error;
@@ -6805,6 +6808,23 @@ static int stmmac_vlan_rx_kill_vid(struct net_device *ndev, __be16 proto, u16 vi
68056808
return ret;
68066809
}
68076810

6811+
static int stmmac_vlan_restore(struct stmmac_priv *priv)
6812+
{
6813+
int ret;
6814+
6815+
if (!(priv->dev->features & NETIF_F_VLAN_FEATURES))
6816+
return 0;
6817+
6818+
if (priv->hw->num_vlan)
6819+
stmmac_restore_hw_vlan_rx_fltr(priv, priv->dev, priv->hw);
6820+
6821+
ret = stmmac_vlan_update(priv, priv->num_double_vlans);
6822+
if (ret)
6823+
netdev_err(priv->dev, "Failed to restore VLANs\n");
6824+
6825+
return ret;
6826+
}
6827+
68086828
static int stmmac_bpf(struct net_device *dev, struct netdev_bpf *bpf)
68096829
{
68106830
struct stmmac_priv *priv = netdev_priv(dev);
@@ -8197,10 +8217,10 @@ int stmmac_resume(struct device *dev)
81978217
stmmac_init_coalesce(priv);
81988218
phylink_rx_clk_stop_block(priv->phylink);
81998219
stmmac_set_rx_mode(ndev);
8200-
8201-
stmmac_restore_hw_vlan_rx_fltr(priv, ndev, priv->hw);
82028220
phylink_rx_clk_stop_unblock(priv->phylink);
82038221

8222+
stmmac_vlan_restore(priv);
8223+
82048224
stmmac_enable_all_queues(priv);
82058225
stmmac_enable_all_dma_irq(priv);
82068226

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

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -139,9 +139,6 @@ static int vlan_del_hw_rx_fltr(struct net_device *dev,
139139
static void vlan_restore_hw_rx_fltr(struct net_device *dev,
140140
struct mac_device_info *hw)
141141
{
142-
void __iomem *ioaddr = hw->pcsr;
143-
u32 value;
144-
u32 hash;
145142
u32 val;
146143
int i;
147144

@@ -158,13 +155,6 @@ static void vlan_restore_hw_rx_fltr(struct net_device *dev,
158155
vlan_write_filter(dev, hw, i, val);
159156
}
160157
}
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-
}
168158
}
169159

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

0 commit comments

Comments
 (0)