diff options
| author | Serge Semin <fancer.lancer@gmail.com> | 2025-03-12 16:51:21 +0300 |
|---|---|---|
| committer | Serge Semin <fancer.lancer@gmail.com> | 2026-08-13 20:34:37 +0300 |
| commit | 8275a29fddf22f5a588347585b9cc6ea2ee91b7a (patch) | |
| tree | 3e8f20f0a6f31910d9a710d91bd5f729bc3fb507 | |
| parent | 20747923ecfc7d104a4820859e036d822033a6ef (diff) | |
| download | linux-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.h | 2 | ||||
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac.h | 2 | ||||
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 34 | ||||
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c | 23 |
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, }; |
