[PATCH] kernel: backport MediaTek jumbo frame support to 5.10

DENG Qingfang dqfext at gmail.com
Fri May 21 00:15:22 PDT 2021


Allow MTU up to 2026 on mediatek, ramips/mt7621 targets

Signed-off-by: DENG Qingfang <dqfext at gmail.com>
---
 ...thernet-mediatek-support-setting-MTU.patch | 138 ++++++++++++++++++
 ...1-net-dsa-mt7530-support-setting-MTU.patch | 112 ++++++++++++++
 ...-dsa-mt7530-enable-MTU-normalization.patch |  36 +++++
 3 files changed, 286 insertions(+)
 create mode 100644 target/linux/generic/backport-5.10/604-v5.12-net-ethernet-mediatek-support-setting-MTU.patch
 create mode 100644 target/linux/generic/backport-5.10/760-v5.11-net-dsa-mt7530-support-setting-MTU.patch
 create mode 100644 target/linux/generic/backport-5.10/761-v5.11-net-dsa-mt7530-enable-MTU-normalization.patch

diff --git a/target/linux/generic/backport-5.10/604-v5.12-net-ethernet-mediatek-support-setting-MTU.patch b/target/linux/generic/backport-5.10/604-v5.12-net-ethernet-mediatek-support-setting-MTU.patch
new file mode 100644
index 0000000000..8b995f817d
--- /dev/null
+++ b/target/linux/generic/backport-5.10/604-v5.12-net-ethernet-mediatek-support-setting-MTU.patch
@@ -0,0 +1,138 @@
+From 4fd59792097a6b2fb949d41264386a7ecade469e Mon Sep 17 00:00:00 2001
+From: DENG Qingfang <dqfext at gmail.com>
+Date: Mon, 25 Jan 2021 12:20:46 +0800
+Subject: [PATCH] net: ethernet: mediatek: support setting MTU
+
+MT762x HW, except for MT7628, supports frame length up to 2048
+(maximum length on GDM), so allow setting MTU up to 2030.
+
+Also set the default frame length to the hardware default 1518.
+
+Signed-off-by: DENG Qingfang <dqfext at gmail.com>
+Reviewed-by: Andrew Lunn <andrew at lunn.ch>
+Link: https://lore.kernel.org/r/20210125042046.5599-1-dqfext@gmail.com
+Signed-off-by: Jakub Kicinski <kuba at kernel.org>
+---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 43 ++++++++++++++++++---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.h | 12 ++++--
+ 2 files changed, 47 insertions(+), 8 deletions(-)
+
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -353,7 +353,7 @@ static void mtk_mac_config(struct phylin
+ 	/* Setup gmac */
+ 	mcr_cur = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id));
+ 	mcr_new = mcr_cur;
+-	mcr_new |= MAC_MCR_MAX_RX_1536 | MAC_MCR_IPG_CFG | MAC_MCR_FORCE_MODE |
++	mcr_new |= MAC_MCR_IPG_CFG | MAC_MCR_FORCE_MODE |
+ 		   MAC_MCR_BACKOFF_EN | MAC_MCR_BACKPR_EN | MAC_MCR_FORCE_LINK;
+ 
+ 	/* Only update control register when needed! */
+@@ -759,8 +759,8 @@ static void mtk_get_stats64(struct net_d
+ static inline int mtk_max_frag_size(int mtu)
+ {
+ 	/* make sure buf_size will be at least MTK_MAX_RX_LENGTH */
+-	if (mtu + MTK_RX_ETH_HLEN < MTK_MAX_RX_LENGTH)
+-		mtu = MTK_MAX_RX_LENGTH - MTK_RX_ETH_HLEN;
++	if (mtu + MTK_RX_ETH_HLEN < MTK_MAX_RX_LENGTH_2K)
++		mtu = MTK_MAX_RX_LENGTH_2K - MTK_RX_ETH_HLEN;
+ 
+ 	return SKB_DATA_ALIGN(MTK_RX_HLEN + mtu) +
+ 		SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+@@ -771,7 +771,7 @@ static inline int mtk_max_buf_size(int f
+ 	int buf_size = frag_size - NET_SKB_PAD - NET_IP_ALIGN -
+ 		       SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+ 
+-	WARN_ON(buf_size < MTK_MAX_RX_LENGTH);
++	WARN_ON(buf_size < MTK_MAX_RX_LENGTH_2K);
+ 
+ 	return buf_size;
+ }
+@@ -2499,6 +2499,35 @@ static void mtk_uninit(struct net_device
+ 	mtk_rx_irq_disable(eth, ~0);
+ }
+ 
++static int mtk_change_mtu(struct net_device *dev, int new_mtu)
++{
++	int length = new_mtu + MTK_RX_ETH_HLEN;
++	struct mtk_mac *mac = netdev_priv(dev);
++	struct mtk_eth *eth = mac->hw;
++	u32 mcr_cur, mcr_new;
++
++	if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) {
++		mcr_cur = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id));
++		mcr_new = mcr_cur & ~MAC_MCR_MAX_RX_MASK;
++
++		if (length <= 1518)
++			mcr_new |= MAC_MCR_MAX_RX(MAC_MCR_MAX_RX_1518);
++		else if (length <= 1536)
++			mcr_new |= MAC_MCR_MAX_RX(MAC_MCR_MAX_RX_1536);
++		else if (length <= 1552)
++			mcr_new |= MAC_MCR_MAX_RX(MAC_MCR_MAX_RX_1552);
++		else
++			mcr_new |= MAC_MCR_MAX_RX(MAC_MCR_MAX_RX_2048);
++
++		if (mcr_new != mcr_cur)
++			mtk_w32(mac->hw, mcr_new, MTK_MAC_MCR(mac->id));
++	}
++
++	dev->mtu = new_mtu;
++
++	return 0;
++}
++
+ static int mtk_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+ {
+ 	struct mtk_mac *mac = netdev_priv(dev);
+@@ -2795,6 +2824,7 @@ static const struct net_device_ops mtk_n
+ 	.ndo_set_mac_address	= mtk_set_mac_address,
+ 	.ndo_validate_addr	= eth_validate_addr,
+ 	.ndo_do_ioctl		= mtk_do_ioctl,
++	.ndo_change_mtu		= mtk_change_mtu,
+ 	.ndo_tx_timeout		= mtk_tx_timeout,
+ 	.ndo_get_stats64        = mtk_get_stats64,
+ 	.ndo_fix_features	= mtk_fix_features,
+@@ -2896,7 +2926,10 @@ static int mtk_add_mac(struct mtk_eth *e
+ 	eth->netdev[id]->irq = eth->irq[0];
+ 	eth->netdev[id]->dev.of_node = np;
+ 
+-	eth->netdev[id]->max_mtu = MTK_MAX_RX_LENGTH - MTK_RX_ETH_HLEN;
++	if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628))
++		eth->netdev[id]->max_mtu = MTK_MAX_RX_LENGTH - MTK_RX_ETH_HLEN;
++	else
++		eth->netdev[id]->max_mtu = MTK_MAX_RX_LENGTH_2K - MTK_RX_ETH_HLEN;
+ 
+ 	return 0;
+ 
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+@@ -17,12 +17,13 @@
+ #include <linux/phylink.h>
+ 
+ #define MTK_QDMA_PAGE_SIZE	2048
+-#define	MTK_MAX_RX_LENGTH	1536
++#define MTK_MAX_RX_LENGTH	1536
++#define MTK_MAX_RX_LENGTH_2K	2048
+ #define MTK_TX_DMA_BUF_LEN	0x3fff
+ #define MTK_DMA_SIZE		256
+ #define MTK_NAPI_WEIGHT		64
+ #define MTK_MAC_COUNT		2
+-#define MTK_RX_ETH_HLEN		(VLAN_ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN)
++#define MTK_RX_ETH_HLEN		(ETH_HLEN + ETH_FCS_LEN)
+ #define MTK_RX_HLEN		(NET_SKB_PAD + MTK_RX_ETH_HLEN + NET_IP_ALIGN)
+ #define MTK_DMA_DUMMY_DESC	0xffffffff
+ #define MTK_DEFAULT_MSG_ENABLE	(NETIF_MSG_DRV | \
+@@ -321,7 +322,12 @@
+ 
+ /* Mac control registers */
+ #define MTK_MAC_MCR(x)		(0x10100 + (x * 0x100))
+-#define MAC_MCR_MAX_RX_1536	BIT(24)
++#define MAC_MCR_MAX_RX_MASK	GENMASK(25, 24)
++#define MAC_MCR_MAX_RX(_x)	(MAC_MCR_MAX_RX_MASK & ((_x) << 24))
++#define MAC_MCR_MAX_RX_1518	0x0
++#define MAC_MCR_MAX_RX_1536	0x1
++#define MAC_MCR_MAX_RX_1552	0x2
++#define MAC_MCR_MAX_RX_2048	0x3
+ #define MAC_MCR_IPG_CFG		(BIT(18) | BIT(16))
+ #define MAC_MCR_FORCE_MODE	BIT(15)
+ #define MAC_MCR_TX_EN		BIT(14)
diff --git a/target/linux/generic/backport-5.10/760-v5.11-net-dsa-mt7530-support-setting-MTU.patch b/target/linux/generic/backport-5.10/760-v5.11-net-dsa-mt7530-support-setting-MTU.patch
new file mode 100644
index 0000000000..cf03935ef1
--- /dev/null
+++ b/target/linux/generic/backport-5.10/760-v5.11-net-dsa-mt7530-support-setting-MTU.patch
@@ -0,0 +1,112 @@
+From 9470174e7581e75a8ebd78964997314dfc2e706c Mon Sep 17 00:00:00 2001
+From: DENG Qingfang <dqfext at gmail.com>
+Date: Tue, 3 Nov 2020 13:06:18 +0800
+Subject: [PATCH] net: dsa: mt7530: support setting MTU
+
+MT7530/7531 has a global RX packet length register, which can be used
+to set MTU.
+
+Supported packet length values are 1522 (1518 if untagged), 1536,
+1552, and multiple of 1024 (from 2048 to 15360).
+
+Signed-off-by: DENG Qingfang <dqfext at gmail.com>
+Link: https://lore.kernel.org/r/20201103050618.11419-1-dqfext@gmail.com
+Signed-off-by: Jakub Kicinski <kuba at kernel.org>
+---
+ drivers/net/dsa/mt7530.c | 49 ++++++++++++++++++++++++++++++++++++++++
+ drivers/net/dsa/mt7530.h | 12 ++++++++++
+ 2 files changed, 61 insertions(+)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -1021,6 +1021,53 @@ mt7530_port_disable(struct dsa_switch *d
+ 	mutex_unlock(&priv->reg_mutex);
+ }
+ 
++static int
++mt7530_port_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
++{
++	struct mt7530_priv *priv = ds->priv;
++	struct mii_bus *bus = priv->bus;
++	int length;
++	u32 val;
++
++	/* When a new MTU is set, DSA always set the CPU port's MTU to the
++	 * largest MTU of the slave ports. Because the switch only has a global
++	 * RX length register, only allowing CPU port here is enough.
++	 */
++	if (!dsa_is_cpu_port(ds, port))
++		return 0;
++
++	mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
++
++	val = mt7530_mii_read(priv, MT7530_GMACCR);
++	val &= ~MAX_RX_PKT_LEN_MASK;
++
++	/* RX length also includes Ethernet header, MTK tag, and FCS length */
++	length = new_mtu + ETH_HLEN + MTK_HDR_LEN + ETH_FCS_LEN;
++	if (length <= 1522) {
++		val |= MAX_RX_PKT_LEN_1522;
++	} else if (length <= 1536) {
++		val |= MAX_RX_PKT_LEN_1536;
++	} else if (length <= 1552) {
++		val |= MAX_RX_PKT_LEN_1552;
++	} else {
++		val &= ~MAX_RX_JUMBO_MASK;
++		val |= MAX_RX_JUMBO(DIV_ROUND_UP(length, 1024));
++		val |= MAX_RX_PKT_LEN_JUMBO;
++	}
++
++	mt7530_mii_write(priv, MT7530_GMACCR, val);
++
++	mutex_unlock(&bus->mdio_lock);
++
++	return 0;
++}
++
++static int
++mt7530_port_max_mtu(struct dsa_switch *ds, int port)
++{
++	return MT7530_MAX_MTU;
++}
++
+ static void
+ mt7530_stp_state_set(struct dsa_switch *ds, int port, u8 state)
+ {
+@@ -2519,6 +2566,8 @@ static const struct dsa_switch_ops mt753
+ 	.get_sset_count		= mt7530_get_sset_count,
+ 	.port_enable		= mt7530_port_enable,
+ 	.port_disable		= mt7530_port_disable,
++	.port_change_mtu	= mt7530_port_change_mtu,
++	.port_max_mtu		= mt7530_port_max_mtu,
+ 	.port_stp_state_set	= mt7530_stp_state_set,
+ 	.port_bridge_join	= mt7530_port_bridge_join,
+ 	.port_bridge_leave	= mt7530_port_bridge_leave,
+--- a/drivers/net/dsa/mt7530.h
++++ b/drivers/net/dsa/mt7530.h
+@@ -11,6 +11,9 @@
+ #define MT7530_NUM_FDB_RECORDS		2048
+ #define MT7530_ALL_MEMBERS		0xff
+ 
++#define MTK_HDR_LEN	4
++#define MT7530_MAX_MTU	(15 * 1024 - ETH_HLEN - ETH_FCS_LEN - MTK_HDR_LEN)
++
+ enum mt753x_id {
+ 	ID_MT7530 = 0,
+ 	ID_MT7621 = 1,
+@@ -289,6 +292,15 @@ enum mt7530_vlan_port_attr {
+ #define MT7531_DBG_CNT(x)		(0x3018 + (x) * 0x100)
+ #define  MT7531_DIS_CLR			BIT(31)
+ 
++#define MT7530_GMACCR			0x30e0
++#define  MAX_RX_JUMBO(x)		((x) << 2)
++#define  MAX_RX_JUMBO_MASK		GENMASK(5, 2)
++#define  MAX_RX_PKT_LEN_MASK		GENMASK(1, 0)
++#define  MAX_RX_PKT_LEN_1522		0x0
++#define  MAX_RX_PKT_LEN_1536		0x1
++#define  MAX_RX_PKT_LEN_1552		0x2
++#define  MAX_RX_PKT_LEN_JUMBO		0x3
++
+ /* Register for MIB */
+ #define MT7530_PORT_MIB_COUNTER(x)	(0x4000 + (x) * 0x100)
+ #define MT7530_MIB_CCR			0x4fe0
diff --git a/target/linux/generic/backport-5.10/761-v5.11-net-dsa-mt7530-enable-MTU-normalization.patch b/target/linux/generic/backport-5.10/761-v5.11-net-dsa-mt7530-enable-MTU-normalization.patch
new file mode 100644
index 0000000000..a09852380e
--- /dev/null
+++ b/target/linux/generic/backport-5.10/761-v5.11-net-dsa-mt7530-enable-MTU-normalization.patch
@@ -0,0 +1,36 @@
+From 771c8901568dd8776a260aa93db41be88a60389e Mon Sep 17 00:00:00 2001
+From: DENG Qingfang <dqfext at gmail.com>
+Date: Fri, 11 Dec 2020 01:03:22 +0800
+Subject: [PATCH] net: dsa: mt7530: enable MTU normalization
+
+MT7530 has a global RX length register, so we are actually changing its
+MRU.
+Enable MTU normalization for this reason.
+
+Signed-off-by: DENG Qingfang <dqfext at gmail.com>
+Acked-by: Landen Chao <landen.chao at mediatek.com>
+Reviewed-by: Vladimir Oltean <olteanv at gmail.com>
+Link: https://lore.kernel.org/r/20201210170322.3433-1-dqfext@gmail.com
+Signed-off-by: Jakub Kicinski <kuba at kernel.org>
+---
+ drivers/net/dsa/mt7530.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -1617,6 +1617,7 @@ mt7530_setup(struct dsa_switch *ds)
+ 	 */
+ 	dn = dsa_to_port(ds, MT7530_CPU_PORT)->master->dev.of_node->parent;
+ 	ds->configure_vlan_while_not_filtering = true;
++	ds->mtu_enforcement_ingress = true;
+ 
+ 	if (priv->id == ID_MT7530) {
+ 		regulator_set_voltage(priv->core_pwr, 1000000, 1000000);
+@@ -1855,6 +1856,7 @@ mt7531_setup(struct dsa_switch *ds)
+ 	}
+ 
+ 	ds->configure_vlan_while_not_filtering = true;
++	ds->mtu_enforcement_ingress = true;
+ 
+ 	/* Flush the FDB table */
+ 	ret = mt7530_fdb_cmd(priv, MT7530_FDB_FLUSH, NULL);
-- 
2.25.1




More information about the openwrt-devel mailing list