summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSerge Semin <fancer.lancer@gmail.com>2025-03-07 14:03:09 +0300
committerSerge Semin <fancer.lancer@gmail.com>2026-08-13 20:34:12 +0300
commita69d2bad1218cae53e09c671a610c7d6c719b61a (patch)
tree949f82193dd6b869267422699f131c75980f0609
parent5eeb71f19acb81724c6ba962bd32e599691b4faf (diff)
downloadlinux-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.c20
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.h1
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)