[PATCH net-next v1] net: stmmac: xgmac: add support for HW-accelerated VLAN stripping
Furong Xu
0x1207 at gmail.com
Thu Jul 4 23:28:08 PDT 2024
Commit 750011e239a5 ("net: stmmac: Add support for HW-accelerated VLAN
stripping") introduced MAC level VLAN tag stripping for gmac4 core.
This patch extend the support to xgmac core.
Signed-off-by: Furong Xu <0x1207 at gmail.com>
---
.../net/ethernet/stmicro/stmmac/dwxgmac2.h | 7 ++++
.../ethernet/stmicro/stmmac/dwxgmac2_core.c | 39 +++++++++++++++++++
.../ethernet/stmicro/stmmac/dwxgmac2_descs.c | 19 +++++++++
.../net/ethernet/stmicro/stmmac/stmmac_main.c | 2 +-
4 files changed, 66 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
index 6a2c7d22df1e..db3217784cb0 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
@@ -60,6 +60,10 @@
#define XGMAC_VLAN_TAG 0x00000050
#define XGMAC_VLAN_EDVLP BIT(26)
#define XGMAC_VLAN_VTHM BIT(25)
+#define XGMAC_VLAN_TAG_CTRL_EVLRXS BIT(24)
+#define XGMAC_VLAN_TAG_CTRL_EVLS GENMASK(22, 21)
+#define XGMAC_VLAN_TAG_STRIP_NONE 0x0
+#define XGMAC_VLAN_TAG_STRIP_ALL 0x3
#define XGMAC_VLAN_DOVLTC BIT(20)
#define XGMAC_VLAN_ESVL BIT(18)
#define XGMAC_VLAN_ETV BIT(16)
@@ -477,6 +481,7 @@
#define XGMAC_TDES3_VLTV BIT(16)
#define XGMAC_TDES3_VT GENMASK(15, 0)
#define XGMAC_TDES3_FL GENMASK(14, 0)
+#define XGMAC_RDES0_VLAN_TAG GENMASK(15, 0)
#define XGMAC_RDES2_HL GENMASK(9, 0)
#define XGMAC_RDES3_OWN BIT(31)
#define XGMAC_RDES3_CTXT BIT(30)
@@ -490,6 +495,8 @@
#define XGMAC_L34T_IP4UDP 0x2
#define XGMAC_L34T_IP6TCP 0x9
#define XGMAC_L34T_IP6UDP 0xA
+#define XGMAC_RDES3_L2T GENMASK(19, 16)
+#define XGMAC_L2T_SINGLE_C_VLAN 0x9
#define XGMAC_RDES3_ES BIT(15)
#define XGMAC_RDES3_PL GENMASK(13, 0)
#define XGMAC_RDES3_TSD BIT(6)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
index 6a987cf598e4..89ac9ad6164a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
@@ -1530,6 +1530,41 @@ static void dwxgmac3_fpe_configure(void __iomem *ioaddr, struct stmmac_fpe_cfg *
writel(value, ioaddr + XGMAC_FPE_CTRL_STS);
}
+static void dwxgmac2_rx_hw_vlan(struct mac_device_info *hw,
+ struct dma_desc *rx_desc, struct sk_buff *skb)
+{
+ u16 vid;
+
+ if (!hw->desc->get_rx_vlan_valid(rx_desc))
+ return;
+
+ vid = hw->desc->get_rx_vlan_tci(rx_desc);
+
+ __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vid);
+}
+
+static void dwxgmac2_set_hw_vlan_mode(struct mac_device_info *hw)
+{
+ void __iomem *ioaddr = hw->pcsr;
+ u32 value = readl(ioaddr + XGMAC_VLAN_TAG);
+
+ value &= ~XGMAC_VLAN_TAG_CTRL_EVLS;
+
+ if (hw->hw_vlan_en)
+ /* Always strip VLAN on Receive */
+ value |= FIELD_PREP(XGMAC_VLAN_TAG_CTRL_EVLS,
+ XGMAC_VLAN_TAG_STRIP_ALL);
+ else
+ /* Do not strip VLAN on Receive */
+ value |= FIELD_PREP(XGMAC_VLAN_TAG_CTRL_EVLS,
+ XGMAC_VLAN_TAG_STRIP_NONE);
+
+ /* Enable outer VLAN Tag in Rx DMA descriptor */
+ value |= XGMAC_VLAN_TAG_CTRL_EVLRXS;
+
+ writel(value, ioaddr + XGMAC_VLAN_TAG);
+}
+
const struct stmmac_ops dwxgmac210_ops = {
.core_init = dwxgmac2_core_init,
.set_mac = dwxgmac2_set_mac,
@@ -1571,6 +1606,8 @@ const struct stmmac_ops dwxgmac210_ops = {
.config_l4_filter = dwxgmac2_config_l4_filter,
.set_arp_offload = dwxgmac2_set_arp_offload,
.fpe_configure = dwxgmac3_fpe_configure,
+ .rx_hw_vlan = dwxgmac2_rx_hw_vlan,
+ .set_hw_vlan_mode = dwxgmac2_set_hw_vlan_mode,
};
static void dwxlgmac2_rx_queue_enable(struct mac_device_info *hw, u8 mode,
@@ -1628,6 +1665,8 @@ const struct stmmac_ops dwxlgmac2_ops = {
.config_l4_filter = dwxgmac2_config_l4_filter,
.set_arp_offload = dwxgmac2_set_arp_offload,
.fpe_configure = dwxgmac3_fpe_configure,
+ .rx_hw_vlan = dwxgmac2_rx_hw_vlan,
+ .set_hw_vlan_mode = dwxgmac2_set_hw_vlan_mode,
};
int dwxgmac2_setup(struct stmmac_priv *priv)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c
index fc82862a612c..f5293f75fbb4 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c
@@ -67,6 +67,23 @@ static int dwxgmac2_get_tx_ls(struct dma_desc *p)
return (le32_to_cpu(p->des3) & XGMAC_RDES3_LD) > 0;
}
+static u16 dwxgmac2_wrback_get_rx_vlan_tci(struct dma_desc *p)
+{
+ return (le32_to_cpu(p->des0) & XGMAC_RDES0_VLAN_TAG);
+}
+
+static bool dwxgmac2_wrback_get_rx_vlan_valid(struct dma_desc *p)
+{
+ u32 l2_type;
+
+ if (!(le32_to_cpu(p->des3) & XGMAC_RDES3_LD))
+ return false;
+
+ l2_type = FIELD_GET(XGMAC_RDES3_L2T, le32_to_cpu(p->des3));
+
+ return (l2_type == XGMAC_L2T_SINGLE_C_VLAN);
+}
+
static int dwxgmac2_get_rx_frame_len(struct dma_desc *p, int rx_coe)
{
return (le32_to_cpu(p->des3) & XGMAC_RDES3_PL);
@@ -349,6 +366,8 @@ const struct stmmac_desc_ops dwxgmac210_desc_ops = {
.set_tx_owner = dwxgmac2_set_tx_owner,
.set_rx_owner = dwxgmac2_set_rx_owner,
.get_tx_ls = dwxgmac2_get_tx_ls,
+ .get_rx_vlan_tci = dwxgmac2_wrback_get_rx_vlan_tci,
+ .get_rx_vlan_valid = dwxgmac2_wrback_get_rx_vlan_valid,
.get_rx_frame_len = dwxgmac2_get_rx_frame_len,
.enable_tx_timestamp = dwxgmac2_enable_tx_timestamp,
.get_tx_timestamp_status = dwxgmac2_get_tx_timestamp_status,
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 4b6a359e5a94..6f594c455d0f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -7663,7 +7663,7 @@ 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;
- if (priv->plat->has_gmac4) {
+ if (priv->plat->has_gmac4 || priv->plat->has_xgmac) {
ndev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX;
priv->hw->hw_vlan_en = true;
}
--
2.34.1
More information about the linux-arm-kernel
mailing list