mirror of
https://github.com/openwrt/openwrt.git
synced 2025-02-20 17:32:57 +00:00
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:
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);
|
Loading…
x
Reference in New Issue
Block a user