summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSerge Semin <fancer.lancer@gmail.com>2025-03-12 16:51:21 +0300
committerSerge Semin <fancer.lancer@gmail.com>2026-08-13 20:34:37 +0300
commit8275a29fddf22f5a588347585b9cc6ea2ee91b7a (patch)
tree3e8f20f0a6f31910d9a710d91bd5f729bc3fb507
parent20747923ecfc7d104a4820859e036d822033a6ef (diff)
downloadlinux-8275a29fddf22f5a588347585b9cc6ea2ee91b7a.tar.gz
linux-8275a29fddf22f5a588347585b9cc6ea2ee91b7a.zip
net: stmmac: vlan: Drop double VLAN enabling for 802.1ad Rx-frames
The commit c657f86106c8 ("net: stmmac: vlan: Disable 802.1AD tag insertion offload") has dropped the double VLAN erroneous insertion for Tx frames. The Rx VLAN-frames filtering code also suffers from that feature being enabled but with much less harm. The feature is enabled if VLAN S-TAG filtering is requested, but it never actually activated since the ERIVLT and EIVLS flags aren't touched by the code. Presumably the EDVLP flag setting up used to be working in conjunction with the VLAN-insertion feature, since it enables the double VLAN processing for both Rx and _Tx_ paths. So without it no inner VLAN would be inserted if requested. But that feature has been incorrectly enabled for the S-VLAN frames and dropped in the framework of the commit c657f86106c8 ("net: stmmac: vlan: Disable 802.1AD tag insertion offload") thus fixing a completely broken 802.1ad tags support added in the initial commit 30d932279dc2 ("net: stmmac: Add support for VLAN Insertion Offload"). So let's drop the code currently handling the EDVLP flag setting up. Also fix the naming around the just dropped code to describing the actual feature the entities are utilized for - enable S-VLAN filtering. After this change there will be almost no the double VLAN feature trace left in the driver. The only leftovers are stmmac_desc_ops::set_vlan_tag() callbacks but the respective part doesn't effect the controller state, so be it for now. Note though based on [1, 2, 3] Double VLAN processing feature must be available and enabled so the *GMACs could properly perform the L2/L3 checksum verification of the frames with one-level inner VLAN tagged. Let's unconditionally enable it thus speeding up the incoming Double VLAN tagged frames handling. [1] DesignWare Cores XLGMAC - Enterprise Ethernet MAC, Revision 2.00a, September 2017, p.181. [1] DesignWare Cores XGMAC - 10G Ethernet MAC Databook, Revision 3.20a, September 2022, p.253. [2] DesignWare® Cores Ethernet Quality-of-Service, Revision 5.20a, April 2020, p.368. Fixes: 3cd1cfcba26e ("net: stmmac: Implement VLAN Hash Filtering in XGMAC") Signed-off-by: Serge Semin <fancer.lancer@gmail.com>
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/hwif.h2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac.h2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_main.c34
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c23
4 files changed, 37 insertions, 24 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
index 7328791e236f..e4b28b3a62cc 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
@@ -629,7 +629,7 @@ struct stmmac_est_ops {
struct stmmac_vlan_ops {
/* VLAN */
void (*update_vlan_hash)(struct mac_device_info *hw, u32 hash,
- bool is_double);
+ bool is_svlan);
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 cd0531b52257..b1188d897936 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -375,7 +375,7 @@ struct stmmac_priv {
void __iomem *ptpaddr;
void __iomem *estaddr;
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
- unsigned int num_double_vlans;
+ unsigned int num_svlans;
int sfty_irq;
int sfty_ce_irq;
int sfty_ue_irq;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index f154a0037d8d..14027a0e34d6 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -7127,7 +7127,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, bool is_svlan)
{
u32 crc, hash = 0;
u16 vid = 0;
@@ -7141,7 +7141,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, is_svlan);
}
/* FIXME: This may need RXC to be running, but it may be called with BH
@@ -7150,8 +7150,8 @@ 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;
+ unsigned int num_svlans;
+ bool is_svlan = false;
int ret;
ret = pm_runtime_resume_and_get(priv->device);
@@ -7159,11 +7159,11 @@ static int stmmac_vlan_rx_add_vid(struct net_device *ndev, __be16 proto, u16 vid
return ret;
if (be16_to_cpu(proto) == ETH_P_8021AD)
- is_double = true;
+ is_svlan = true;
set_bit(vid, priv->active_vlans);
- num_double_vlans = priv->num_double_vlans + is_double;
- ret = stmmac_vlan_update(priv, num_double_vlans);
+ num_svlans = priv->num_svlans + is_svlan;
+ ret = stmmac_vlan_update(priv, num_svlans);
if (ret) {
clear_bit(vid, priv->active_vlans);
goto err_pm_put;
@@ -7173,12 +7173,12 @@ 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, priv->num_svlans);
goto err_pm_put;
}
}
- priv->num_double_vlans = num_double_vlans;
+ priv->num_svlans = num_svlans;
err_pm_put:
pm_runtime_put(priv->device);
@@ -7192,8 +7192,8 @@ err_pm_put:
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;
+ unsigned int num_svlans;
+ bool is_svlan = false;
int ret;
ret = pm_runtime_resume_and_get(priv->device);
@@ -7201,11 +7201,11 @@ static int stmmac_vlan_rx_kill_vid(struct net_device *ndev, __be16 proto, u16 vi
return ret;
if (be16_to_cpu(proto) == ETH_P_8021AD)
- is_double = true;
+ is_svlan = true;
clear_bit(vid, priv->active_vlans);
- num_double_vlans = priv->num_double_vlans - is_double;
- ret = stmmac_vlan_update(priv, num_double_vlans);
+ num_svlans = priv->num_svlans - is_double;
+ ret = stmmac_vlan_update(priv, num_svlans);
if (ret) {
set_bit(vid, priv->active_vlans);
goto del_vlan_error;
@@ -7215,12 +7215,12 @@ 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, priv->num_svlans);
goto del_vlan_error;
}
}
- priv->num_double_vlans = num_double_vlans;
+ priv->num_svlans = num_svlans;
del_vlan_error:
pm_runtime_put(priv->device);
@@ -7236,7 +7236,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, priv->num_svlans);
}
static int stmmac_bpf(struct net_device *dev, struct netdev_bpf *bpf)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c
index 4ed7f7f031f4..a6ade06a7ae0 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c
@@ -190,7 +190,7 @@ static void vlan_restore_hw_rx_fltr(struct net_device *dev,
}
static void vlan_update_hash(struct mac_device_info *hw, u32 hash,
- bool is_double)
+ bool is_svlan)
{
void __iomem *ioaddr = hw->pcsr;
u32 value;
@@ -201,18 +201,16 @@ static void vlan_update_hash(struct mac_device_info *hw, u32 hash,
if (hash) {
value |= VLAN_VTHM | VLAN_ETV;
- if (is_double) {
- value |= VLAN_EDVLP;
+ if (is_svlan) {
value |= VLAN_ESVL;
value |= VLAN_DOVLTC;
} else {
- value &= ~VLAN_EDVLP;
value &= ~VLAN_ESVL;
value &= ~VLAN_DOVLTC;
}
} else {
value &= ~(VLAN_VTHM | VLAN_ETV);
- value &= ~(VLAN_EDVLP | VLAN_ESVL);
+ value &= ~VLAN_ESVL;
value &= ~VLAN_DOVLTC;
}
@@ -259,11 +257,25 @@ static void vlan_set_hw_mode(struct mac_device_info *hw)
/* Do not strip VLAN on Receive */
value |= VLAN_TAG_STRIP_NONE;
+ /* Activate Double VLAN for Rx COE */
+ value |= VLAN_EDVLP;
+
/* Enable outer VLAN Tag in Rx DMA descriptor */
value |= VLAN_TAG_CTRL_EVLRXS;
writel(value, ioaddr + VLAN_TAG);
}
+static void dwxlgmac2_vlan_set_hw_mode(struct mac_device_info *hw)
+{
+ void __iomem *ioaddr = hw->pcsr;
+ u32 value = readl(ioaddr + VLAN_TAG);
+
+ /* Activate Double VLAN for Rx COE */
+ value |= VLAN_EDVLP;
+
+ writel(value, ioaddr + VLAN_TAG);
+}
+
const struct stmmac_vlan_ops dwmac4_vlan_ops = {
.update_vlan_hash = vlan_update_hash,
.enable_vlan = vlan_enable,
@@ -276,6 +288,7 @@ const struct stmmac_vlan_ops dwmac4_vlan_ops = {
const struct stmmac_vlan_ops dwxlgmac2_vlan_ops = {
.update_vlan_hash = vlan_update_hash,
+ .set_hw_vlan_mode = dwxlgmac2_vlan_set_hw_mode,
.enable_vlan = vlan_enable,
};