kernel: backport MediaTek jumbo frame support
Allow MTU up to 2026 on mediatek, ramips/mt7621 targets. Signed-off-by: DENG Qingfang <dqfext@gmail.com> Tested-by: Arınç ÜNAL <arinc.unal@arinc9.com> Tested-by: Stijn Tintel <stijn@linux-ipv6.be>
This commit is contained in:
		 DENG Qingfang
					DENG Qingfang
				
			
				
					committed by
					
						 Stijn Tintel
						Stijn Tintel
					
				
			
			
				
	
			
			
			 Stijn Tintel
						Stijn Tintel
					
				
			
						parent
						
							7a1ce08bdb
						
					
				
				
					commit
					637a3aaa6f
				
			| @@ -0,0 +1,138 @@ | |||||||
|  | From 4fd59792097a6b2fb949d41264386a7ecade469e Mon Sep 17 00:00:00 2001 | ||||||
|  | From: DENG Qingfang <dqfext@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@gmail.com> | ||||||
|  | Reviewed-by: Andrew Lunn <andrew@lunn.ch> | ||||||
|  | Link: https://lore.kernel.org/r/20210125042046.5599-1-dqfext@gmail.com | ||||||
|  | Signed-off-by: Jakub Kicinski <kuba@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 | ||||||
|  | @@ -355,7 +355,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! */ | ||||||
|  | @@ -782,8 +782,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)); | ||||||
|  | @@ -794,7 +794,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; | ||||||
|  |  } | ||||||
|  | @@ -2606,6 +2606,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); | ||||||
|  | @@ -2902,6 +2931,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, | ||||||
|  | @@ -3004,7 +3034,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 | ||||||
|  | @@ -20,12 +20,13 @@ | ||||||
|  |  #include "mtk_ppe.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		512 | ||||||
|  |  #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 | \ | ||||||
|  | @@ -352,7 +353,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) | ||||||
| @@ -0,0 +1,112 @@ | |||||||
|  | From 9470174e7581e75a8ebd78964997314dfc2e706c Mon Sep 17 00:00:00 2001 | ||||||
|  | From: DENG Qingfang <dqfext@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@gmail.com> | ||||||
|  | Link: https://lore.kernel.org/r/20201103050618.11419-1-dqfext@gmail.com | ||||||
|  | Signed-off-by: Jakub Kicinski <kuba@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 | ||||||
|  | @@ -1015,6 +1015,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) | ||||||
|  |  { | ||||||
|  | @@ -2652,6 +2699,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, | ||||||
|  | @@ -301,6 +304,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 | ||||||
| @@ -0,0 +1,36 @@ | |||||||
|  | From 771c8901568dd8776a260aa93db41be88a60389e Mon Sep 17 00:00:00 2001 | ||||||
|  | From: DENG Qingfang <dqfext@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@gmail.com> | ||||||
|  | Acked-by: Landen Chao <landen.chao@mediatek.com> | ||||||
|  | Reviewed-by: Vladimir Oltean <olteanv@gmail.com> | ||||||
|  | Link: https://lore.kernel.org/r/20201210170322.3433-1-dqfext@gmail.com | ||||||
|  | Signed-off-by: Jakub Kicinski <kuba@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 | ||||||
|  | @@ -1703,6 +1703,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); | ||||||
|  | @@ -1947,6 +1948,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); | ||||||
		Reference in New Issue
	
	Block a user