diff mbox series

[net-next,v1] net: stmmac: xgmac: add support for HW-accelerated VLAN stripping

Message ID 20240705062808.805071-1-0x1207@gmail.com (mailing list archive)
State New, archived
Headers show
Series [net-next,v1] net: stmmac: xgmac: add support for HW-accelerated VLAN stripping | expand

Commit Message

Furong Xu July 5, 2024, 6:28 a.m. UTC
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@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(-)

Comments

Michal Kubiak July 5, 2024, 10:28 a.m. UTC | #1
On Fri, Jul 05, 2024 at 02:28:08PM +0800, Furong Xu wrote:
> 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.

typo: extends
Or maybe: This patch adds the same support for xgmac core.

> 
> Signed-off-by: Furong Xu <0x1207@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);

RCT format of declarations is not met.
(However, in this particular case it can be debatable because it would
require introducing a new line).

> +
> +	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
> 
>

The patch looks mostly OK, but I would request to improve a description in
the commit message.

Thanks,
Michal
Andrew Lunn July 5, 2024, 2:07 p.m. UTC | #2
On Fri, Jul 05, 2024 at 02:28:08PM +0800, Furong Xu wrote:
> 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@gmail.com>

Please take a look at this email discussion:

https://lore.kernel.org/netdev/20240527093339.30883-1-boon.khai.ng@intel.com/T/

It would be good if you worked with Intel, rather than repeat the same
mistakes they made.

    Andrew

---
pw-bot: cr
diff mbox series

Patch

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;
 	}