[PATCH net v4 3/7] net: stmmac: Rework S-VLAN handling
Ovidiu Panait
ovidiu.panait.rb at renesas.com
Tue Sep 8 09:43:05 PDT 2026
The ESVL and DOVLTC bits control S-VLAN tag processing and have
nothing to do with the double VLAN feature, which only provides a way
to process an additional inner VLAN tag. However, the driver code
that handles them always refers to "double VLAN", which is unrelated
and makes the implementation confusing. The driver does not use any
of the inner VLAN tag features, and the networking core does not
support offloads for the inner tag anyway.
To simplify the logic and to reduce the confusion regarding S-Tag vs
double VLAN handling, drop the is_double logic and add a hw_svlan_en
flag that is set when S-Tag hardware handling is enabled.
Suggested-by: Joseph Steel <recv.jo at gmail.com>
Signed-off-by: Ovidiu Panait <ovidiu.panait.rb at renesas.com>
---
v4 changes:
- New patch.
drivers/net/ethernet/stmicro/stmmac/common.h | 1 +
drivers/net/ethernet/stmicro/stmmac/hwif.h | 3 +-
drivers/net/ethernet/stmicro/stmmac/stmmac.h | 1 -
.../net/ethernet/stmicro/stmmac/stmmac_main.c | 31 ++++----------
.../net/ethernet/stmicro/stmmac/stmmac_vlan.c | 42 ++++++++-----------
5 files changed, 28 insertions(+), 50 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 927ea6230073..1dd4fc7e7a96 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -634,6 +634,7 @@ struct mac_device_info {
bool vlan_fail_q_en;
u8 vlan_fail_q;
bool hw_vlan_en;
+ bool hw_svlan_en;
bool reverse_sgmii_enable;
/* This spinlock protects read-modify-write of the interrupt
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
index 6f26dbf95ce1..bfd68f8460c8 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
@@ -632,8 +632,7 @@ struct stmmac_est_ops {
struct stmmac_vlan_ops {
/* VLAN */
- void (*update_vlan_hash)(struct mac_device_info *hw, u32 hash,
- bool is_double);
+ void (*update_vlan_hash)(struct mac_device_info *hw, u32 hash);
void (*enable_vlan)(struct mac_device_info *hw, u32 type);
void (*rx_hw_vlan)(struct mac_device_info *hw, struct dma_desc *rx_desc,
struct sk_buff *skb);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index 7582fca63741..7520bdcb7c6b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -344,7 +344,6 @@ struct stmmac_priv {
void __iomem *ptpaddr;
void __iomem *estaddr;
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
- unsigned int num_double_vlans;
int sfty_irq;
struct stmmac_msi *msi;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 24d64cce1d87..cd9671493b41 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -6813,7 +6813,7 @@ 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)
{
u32 crc, hash = 0;
u16 vid = 0;
@@ -6827,7 +6827,7 @@ static int stmmac_vlan_update(struct stmmac_priv *priv, bool is_double)
if (!netif_running(priv->dev))
return 0;
- return stmmac_update_vlan_hash(priv, priv->hw, hash, is_double);
+ return stmmac_update_vlan_hash(priv, priv->hw, hash);
}
/* FIXME: This may need RXC to be running, but it may be called with BH
@@ -6836,20 +6836,14 @@ static int stmmac_vlan_update(struct stmmac_priv *priv, bool is_double)
static int stmmac_vlan_rx_add_vid(struct net_device *ndev, __be16 proto, u16 vid)
{
struct stmmac_priv *priv = netdev_priv(ndev);
- unsigned int num_double_vlans;
- bool is_double = false;
int ret;
ret = pm_runtime_resume_and_get(priv->device);
if (ret < 0)
return ret;
- if (be16_to_cpu(proto) == ETH_P_8021AD)
- is_double = true;
-
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);
if (ret) {
clear_bit(vid, priv->active_vlans);
goto err_pm_put;
@@ -6859,13 +6853,11 @@ static int stmmac_vlan_rx_add_vid(struct net_device *ndev, __be16 proto, u16 vid
ret = stmmac_add_hw_vlan_rx_fltr(priv, ndev, priv->hw, proto, vid);
if (ret) {
clear_bit(vid, priv->active_vlans);
- stmmac_vlan_update(priv, priv->num_double_vlans);
+ stmmac_vlan_update(priv);
goto err_pm_put;
}
}
- priv->num_double_vlans = num_double_vlans;
-
err_pm_put:
pm_runtime_put(priv->device);
@@ -6878,20 +6870,14 @@ static int stmmac_vlan_rx_add_vid(struct net_device *ndev, __be16 proto, u16 vid
static int stmmac_vlan_rx_kill_vid(struct net_device *ndev, __be16 proto, u16 vid)
{
struct stmmac_priv *priv = netdev_priv(ndev);
- unsigned int num_double_vlans;
- bool is_double = false;
int ret;
ret = pm_runtime_resume_and_get(priv->device);
if (ret < 0)
return ret;
- if (be16_to_cpu(proto) == ETH_P_8021AD)
- is_double = true;
-
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);
if (ret) {
set_bit(vid, priv->active_vlans);
goto del_vlan_error;
@@ -6901,13 +6887,11 @@ static int stmmac_vlan_rx_kill_vid(struct net_device *ndev, __be16 proto, u16 vi
ret = stmmac_del_hw_vlan_rx_fltr(priv, ndev, priv->hw, proto, vid);
if (ret) {
set_bit(vid, priv->active_vlans);
- stmmac_vlan_update(priv, priv->num_double_vlans);
+ stmmac_vlan_update(priv);
goto del_vlan_error;
}
}
- priv->num_double_vlans = num_double_vlans;
-
del_vlan_error:
pm_runtime_put(priv->device);
@@ -6922,7 +6906,7 @@ static void stmmac_vlan_restore(struct stmmac_priv *priv)
if (priv->hw->num_vlan)
stmmac_restore_hw_vlan_rx_fltr(priv, priv->dev, priv->hw);
- stmmac_vlan_update(priv, priv->num_double_vlans);
+ stmmac_vlan_update(priv);
}
static int stmmac_bpf(struct net_device *dev, struct netdev_bpf *bpf)
@@ -7962,6 +7946,7 @@ static int __stmmac_dvr_probe(struct device *device,
#ifdef STMMAC_VLAN_TAG_USED
/* Both mac100 and gmac support receive VLAN tag detection */
ndev->features |= NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_STAG_RX;
+ priv->hw->hw_svlan_en = true;
if (dwmac_is_xmac(priv->plat->core_type)) {
ndev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX;
priv->hw->hw_vlan_en = true;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c
index 200b34588c7f..fbb99b70ac27 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c
@@ -161,8 +161,7 @@ static void vlan_restore_hw_rx_fltr(struct net_device *dev,
vlan_write_filter(dev, hw, i, hw->vlan_filter[i]);
}
-static void vlan_update_hash(struct mac_device_info *hw, u32 hash,
- bool is_double)
+static void vlan_update_hash(struct mac_device_info *hw, u32 hash)
{
void __iomem *ioaddr = hw->pcsr;
u32 value;
@@ -173,18 +172,9 @@ static void vlan_update_hash(struct mac_device_info *hw, u32 hash,
if (hash) {
value |= VLAN_VTHM | VLAN_ETV;
- if (is_double) {
- value |= VLAN_ESVL;
- value |= VLAN_DOVLTC;
- } else {
- value &= ~VLAN_ESVL;
- value &= ~VLAN_DOVLTC;
- }
-
writel(value, ioaddr + VLAN_TAG);
} else {
- value &= ~(VLAN_VTHM | VLAN_ETV | VLAN_ESVL);
- value &= ~VLAN_DOVLTC;
+ value &= ~(VLAN_VTHM | VLAN_ETV);
value &= ~VLAN_VID;
writel(value, ioaddr + VLAN_TAG);
@@ -220,6 +210,12 @@ static void vlan_set_hw_mode(struct mac_device_info *hw)
u32 value = readl(ioaddr + VLAN_TAG);
value |= VLAN_EDVLP;
+
+ if (hw->hw_svlan_en)
+ value |= VLAN_ESVL | VLAN_DOVLTC;
+ else
+ value &= ~(VLAN_ESVL | VLAN_DOVLTC);
+
value &= ~VLAN_TAG_CTRL_EVLS_MASK;
if (hw->hw_vlan_en)
@@ -234,8 +230,7 @@ static void vlan_set_hw_mode(struct mac_device_info *hw)
writel(value, ioaddr + VLAN_TAG);
}
-static void dwxgmac2_update_vlan_hash(struct mac_device_info *hw, u32 hash,
- bool is_double)
+static void dwxgmac2_update_vlan_hash(struct mac_device_info *hw, u32 hash)
{
void __iomem *ioaddr = hw->pcsr;
@@ -251,13 +246,6 @@ static void dwxgmac2_update_vlan_hash(struct mac_device_info *hw, u32 hash,
value = readl(ioaddr + VLAN_TAG);
value |= VLAN_VTHM | VLAN_ETV;
- if (is_double) {
- value |= VLAN_ESVL;
- value |= VLAN_DOVLTC;
- } else {
- value &= ~VLAN_ESVL;
- value &= ~VLAN_DOVLTC;
- }
value &= ~VLAN_VID;
writel(value, ioaddr + VLAN_TAG);
@@ -270,8 +258,7 @@ static void dwxgmac2_update_vlan_hash(struct mac_device_info *hw, u32 hash,
value = readl(ioaddr + VLAN_TAG);
- value &= ~(VLAN_VTHM | VLAN_ETV | VLAN_ESVL);
- value &= ~VLAN_DOVLTC;
+ value &= ~(VLAN_VTHM | VLAN_ETV);
value &= ~VLAN_VID;
writel(value, ioaddr + VLAN_TAG);
@@ -283,7 +270,14 @@ static void dwxlgmac2_set_hw_vlan_mode(struct mac_device_info *hw)
void __iomem *ioaddr = hw->pcsr;
u32 value = readl(ioaddr + VLAN_TAG);
- writel(value | VLAN_EDVLP, ioaddr + VLAN_TAG);
+ value |= VLAN_EDVLP;
+
+ if (hw->hw_svlan_en)
+ value |= VLAN_ESVL | VLAN_DOVLTC;
+ else
+ value &= ~(VLAN_ESVL | VLAN_DOVLTC);
+
+ writel(value, ioaddr + VLAN_TAG);
}
const struct stmmac_vlan_ops dwmac_vlan_ops = {
--
2.34.1
More information about the linux-arm-kernel
mailing list