Skip to content

Commit bd7ad51

Browse files
Ovidiu Panaitkuba-moo
authored andcommitted
net: stmmac: Fix VLAN HW state restore
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>
1 parent e38200e commit bd7ad51

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
@@ -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;
@@ -6853,6 +6856,23 @@ static int stmmac_vlan_rx_kill_vid(struct net_device *ndev, __be16 proto, u16 vi
68536856
return ret;
68546857
}
68556858

6859+
static int stmmac_vlan_restore(struct stmmac_priv *priv)
6860+
{
6861+
int ret;
6862+
6863+
if (!(priv->dev->features & NETIF_F_VLAN_FEATURES))
6864+
return 0;
6865+
6866+
if (priv->hw->num_vlan)
6867+
stmmac_restore_hw_vlan_rx_fltr(priv, priv->dev, priv->hw);
6868+
6869+
ret = stmmac_vlan_update(priv, priv->num_double_vlans);
6870+
if (ret)
6871+
netdev_err(priv->dev, "Failed to restore VLANs\n");
6872+
6873+
return ret;
6874+
}
6875+
68566876
static int stmmac_bpf(struct net_device *dev, struct netdev_bpf *bpf)
68576877
{
68586878
struct stmmac_priv *priv = netdev_priv(dev);
@@ -8277,10 +8297,10 @@ int stmmac_resume(struct device *dev)
82778297
stmmac_init_coalesce(priv);
82788298
phylink_rx_clk_stop_block(priv->phylink);
82798299
stmmac_set_rx_mode(ndev);
8280-
8281-
stmmac_restore_hw_vlan_rx_fltr(priv, ndev, priv->hw);
82828300
phylink_rx_clk_stop_unblock(priv->phylink);
82838301

8302+
stmmac_vlan_restore(priv);
8303+
82848304
stmmac_enable_all_queues(priv);
82858305
stmmac_enable_all_dma_irq(priv);
82868306

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)