[PATCH net-next 3/4] net: stmmac: Add write_hw parameter to VLAN filter operations
From: Ovidiu Panait
Date: Mon Feb 23 2026 - 07:50:11 EST
Add a write_hw parameter to the VLAN add/delete HW filter functions and
to stmmac_vlan_update(). This flag controls whether the actual hardware
register accesses are performed. When set to false, only the software
state is updated.
The next commit will use this to defer hardware writes when the
interface is down.
No functional change.
Signed-off-by: Ovidiu Panait <ovidiu.panait.rb@xxxxxxxxxxx>
---
drivers/net/ethernet/stmicro/stmmac/hwif.h | 6 ++--
.../net/ethernet/stmicro/stmmac/stmmac_main.c | 23 ++++++++-----
.../net/ethernet/stmicro/stmmac/stmmac_vlan.c | 34 ++++++++++++-------
3 files changed, 40 insertions(+), 23 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
index 0db96a387259..d7598c76251f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
@@ -647,10 +647,12 @@ struct stmmac_vlan_ops {
void (*set_hw_vlan_mode)(struct mac_device_info *hw);
int (*add_hw_vlan_rx_fltr)(struct net_device *dev,
struct mac_device_info *hw,
- __be16 proto, u16 vid);
+ __be16 proto, u16 vid,
+ bool write_hw);
int (*del_hw_vlan_rx_fltr)(struct net_device *dev,
struct mac_device_info *hw,
- __be16 proto, u16 vid);
+ __be16 proto, u16 vid,
+ bool write_hw);
void (*restore_hw_vlan_rx_fltr)(struct net_device *dev,
struct mac_device_info *hw);
};
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 45f2f3492dbd..536668a0d6dd 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -6748,7 +6748,8 @@ static u32 stmmac_vid_crc32_le(__le16 vid_le)
return crc;
}
-static int stmmac_vlan_update(struct stmmac_priv *priv, bool is_double)
+static int stmmac_vlan_update(struct stmmac_priv *priv, bool is_double,
+ bool write_hw)
{
u32 crc, hash = 0;
u16 pmatch = 0;
@@ -6770,7 +6771,11 @@ static int stmmac_vlan_update(struct stmmac_priv *priv, bool is_double)
hash = 0;
}
- return stmmac_update_vlan_hash(priv, priv->hw, hash, pmatch, is_double);
+ if (write_hw)
+ return stmmac_update_vlan_hash(priv, priv->hw, hash, pmatch,
+ is_double);
+
+ return 0;
}
/* FIXME: This may need RXC to be running, but it may be called with BH
@@ -6792,17 +6797,18 @@ static int stmmac_vlan_rx_add_vid(struct net_device *ndev, __be16 proto, u16 vid
set_bit(vid, priv->active_vlans);
num_double_vlans = priv->num_double_vlans + is_double;
- ret = stmmac_vlan_update(priv, num_double_vlans);
+ ret = stmmac_vlan_update(priv, num_double_vlans, true);
if (ret) {
clear_bit(vid, priv->active_vlans);
goto err_pm_put;
}
if (priv->hw->num_vlan) {
- ret = stmmac_add_hw_vlan_rx_fltr(priv, ndev, priv->hw, proto, vid);
+ ret = stmmac_add_hw_vlan_rx_fltr(priv, ndev, priv->hw, proto,
+ vid, true);
if (ret) {
clear_bit(vid, priv->active_vlans);
- stmmac_vlan_update(priv, priv->num_double_vlans);
+ stmmac_vlan_update(priv, priv->num_double_vlans, true);
goto err_pm_put;
}
}
@@ -6834,17 +6840,18 @@ static int stmmac_vlan_rx_kill_vid(struct net_device *ndev, __be16 proto, u16 vi
clear_bit(vid, priv->active_vlans);
num_double_vlans = priv->num_double_vlans - is_double;
- ret = stmmac_vlan_update(priv, num_double_vlans);
+ ret = stmmac_vlan_update(priv, num_double_vlans, true);
if (ret) {
set_bit(vid, priv->active_vlans);
goto del_vlan_error;
}
if (priv->hw->num_vlan) {
- ret = stmmac_del_hw_vlan_rx_fltr(priv, ndev, priv->hw, proto, vid);
+ ret = stmmac_del_hw_vlan_rx_fltr(priv, ndev, priv->hw, proto,
+ vid, true);
if (ret) {
set_bit(vid, priv->active_vlans);
- stmmac_vlan_update(priv, priv->num_double_vlans);
+ stmmac_vlan_update(priv, priv->num_double_vlans, true);
goto del_vlan_error;
}
}
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c
index de1a70e1c86e..b74c173da1b5 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c
@@ -53,7 +53,8 @@ static int vlan_write_filter(struct net_device *dev,
static int vlan_add_hw_rx_fltr(struct net_device *dev,
struct mac_device_info *hw,
- __be16 proto, u16 vid)
+ __be16 proto, u16 vid,
+ bool write_hw)
{
int index = -1;
u32 val = 0;
@@ -76,7 +77,8 @@ static int vlan_add_hw_rx_fltr(struct net_device *dev,
}
hw->vlan_filter[0] = vid;
- vlan_write_single(dev, vid);
+ if (write_hw)
+ vlan_write_single(dev, vid);
return 0;
}
@@ -97,17 +99,21 @@ static int vlan_add_hw_rx_fltr(struct net_device *dev,
return -EPERM;
}
- ret = vlan_write_filter(dev, hw, index, val);
+ if (write_hw) {
+ ret = vlan_write_filter(dev, hw, index, val);
+ if (ret)
+ return ret;
+ }
- if (!ret)
- hw->vlan_filter[index] = val;
+ hw->vlan_filter[index] = val;
- return ret;
+ return 0;
}
static int vlan_del_hw_rx_fltr(struct net_device *dev,
struct mac_device_info *hw,
- __be16 proto, u16 vid)
+ __be16 proto, u16 vid,
+ bool write_hw)
{
int i, ret = 0;
@@ -115,7 +121,8 @@ static int vlan_del_hw_rx_fltr(struct net_device *dev,
if (hw->num_vlan == 1) {
if ((hw->vlan_filter[0] & VLAN_TAG_VID) == vid) {
hw->vlan_filter[0] = 0;
- vlan_write_single(dev, 0);
+ if (write_hw)
+ vlan_write_single(dev, 0);
}
return 0;
}
@@ -124,12 +131,13 @@ static int vlan_del_hw_rx_fltr(struct net_device *dev,
for (i = 0; i < hw->num_vlan; i++) {
if ((hw->vlan_filter[i] & VLAN_TAG_DATA_VEN) &&
((hw->vlan_filter[i] & VLAN_TAG_DATA_VID) == vid)) {
- ret = vlan_write_filter(dev, hw, i, 0);
+ if (write_hw) {
+ ret = vlan_write_filter(dev, hw, i, 0);
+ if (ret)
+ return ret;
+ }
- if (!ret)
- hw->vlan_filter[i] = 0;
- else
- return ret;
+ hw->vlan_filter[i] = 0;
}
}
--
2.34.1