diff options
| author | Serge Semin <fancer.lancer@gmail.com> | 2025-03-07 14:03:09 +0300 |
|---|---|---|
| committer | Serge Semin <fancer.lancer@gmail.com> | 2026-08-13 20:34:12 +0300 |
| commit | a69d2bad1218cae53e09c671a610c7d6c719b61a (patch) | |
| tree | 949f82193dd6b869267422699f131c75980f0609 | |
| parent | 5eeb71f19acb81724c6ba962bd32e599691b4faf (diff) | |
| download | linux-gmac/fix9/vlan.tar.gz linux-gmac/fix9/vlan.zip | |
net: stmmac: dwxgmac2: Add Double VLAN processing feature detectiongmac/fix9/vlan
The MAC_HW_Feature3.DVLAN flag has been available since the DW XGMAC
IP-core v3.00a, but the Double VLAN Processing feature can be enable since
the v2.00a version (or later than v1.20a). Thus it's incorrect to
determine the DVLAN feature availability based on the flag state on the
early versions of the IP-core. Since we don't know since what particular
IP-core version the Double VLAN Processing feature is available let's
provide the auto-detection procedure for any of them if DVLAN flag has
been met cleared.
The auto-detection procedure is created by checking the
MAC_VLAN_Tag.EIVLRXS (Enable Inner VLAN Tag in Rx Status) flag
writability. The IP-cores databooks define the flag as 0x0 after reset and
available only if the DWCXG_DOUBLE_VLAN_EN parameter is enabled. Otherwise
it's reserved, RO and zero.
Signed-off-by: Serge Semin <fancer.lancer@gmail.com>
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c | 20 | ||||
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.h | 1 |
2 files changed, 21 insertions, 0 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c index a50f79a47266..a05f448bfd7a 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c @@ -6,6 +6,7 @@ #include <linux/iopoll.h> #include "stmmac.h" +#include "stmmac_vlan.h" #include "dwxgmac2.h" static int dwxgmac2_dma_reset(void __iomem *ioaddr) @@ -388,6 +389,20 @@ static int dwxgmac2_dma_interrupt(struct stmmac_priv *priv, return ret; } +static bool dwxgmac2_det_hw_dvlan(void __iomem *ioaddr) +{ + u32 tmp; + + tmp = readl(ioaddr + VLAN_TAG); + writel(tmp ^ VLAN_EIVLRXS, ioaddr + VLAN_TAG); + if (tmp != readl(ioaddr + VLAN_TAG)) { + writel(tmp, ioaddr + VLAN_TAG); + return true; + } + + return false; +} + static int dwxgmac2_get_hw_feature(void __iomem *ioaddr, struct dma_features *dma_cap) { @@ -492,7 +507,12 @@ static int dwxgmac2_get_hw_feature(void __iomem *ioaddr, dma_cap->estsel = (hw_cap & XGMAC_HWFEAT_ESTSEL) >> 19; dma_cap->ttsfd = (hw_cap & XGMAC_HWFEAT_TTSFD) >> 16; dma_cap->asp = (hw_cap & XGMAC_HWFEAT_ASP) >> 14; + + /* Double VLAN Tagging (flag is unavailable prior DW XGMAC v3.00a) */ dma_cap->dvlan = (hw_cap & XGMAC_HWFEAT_DVLAN) >> 13; + if (!dma_cap->dvlan) + dma_cap->dvlan = dwxgmac2_det_hw_dvlan(ioaddr); + dma_cap->frpes = (hw_cap & XGMAC_HWFEAT_FRPES) >> 11; dma_cap->frpbs = (hw_cap & XGMAC_HWFEAT_FRPPB) >> 9; dma_cap->pou_ost_en = (hw_cap & XGMAC_HWFEAT_POUOST) >> 8; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.h index 5143c0fbda26..a138f4fdc4d8 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.h @@ -15,6 +15,7 @@ #define VLAN_INCL 0x00000060 /* MAC VLAN */ +#define VLAN_EIVLRXS BIT(31) #define VLAN_EDVLP BIT(26) #define VLAN_VTHM BIT(25) #define VLAN_DOVLTC BIT(20) |
