From 623cdc4ffeef8e95ba7ab02288c044b2186d121a Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Thu, 15 Feb 2018 10:47:04 +0100 Subject: ramips: backport mt7530/762x switch fixes dc7a1e8555 ("ramips: fix reporting effective VLAN ID on MT7621 switches") 341b1427fc ("ramips: properly map pvid for vlans with remapped vid on mt7530/762x switches") bb4002c79d ("ramips: don't clobber vlans with remapped vid on mt7530/762x switches") Fixes FS#991, FS#1147, FS#1341 Signed-off-by: Jo-Philipp Wich --- .../linux/ramips/patches-4.4/0519-gsw_mt7621.patch | 259 +++++++++++++++++++-- 1 file changed, 239 insertions(+), 20 deletions(-) (limited to 'target/linux') diff --git a/target/linux/ramips/patches-4.4/0519-gsw_mt7621.patch b/target/linux/ramips/patches-4.4/0519-gsw_mt7621.patch index e146de2..5f0594c 100644 --- a/target/linux/ramips/patches-4.4/0519-gsw_mt7621.patch +++ b/target/linux/ramips/patches-4.4/0519-gsw_mt7621.patch @@ -1,31 +1,250 @@ --- a/drivers/net/ethernet/mediatek/mt7530.c +++ b/drivers/net/ethernet/mediatek/mt7530.c -@@ -547,6 +547,7 @@ mt7530_apply_config(struct switch_dev *d - u8 etags = priv->vlan_entries[i].etags; - u32 val; +@@ -44,6 +44,12 @@ + #define MT7530_MAX_VID 4095 + #define MT7530_MIN_VID 0 + ++#define MT7530_PORT_MIB_TXB_ID 2 /* TxGOC */ ++#define MT7530_PORT_MIB_RXB_ID 6 /* RxGOC */ ++ ++#define MT7621_PORT_MIB_TXB_ID 18 /* TxByte */ ++#define MT7621_PORT_MIB_RXB_ID 37 /* RxByte */ ++ + /* registers */ + #define REG_ESW_VLAN_VTCR 0x90 + #define REG_ESW_VLAN_VAWD1 0x94 +@@ -214,6 +220,12 @@ struct mt7530_mapping { + .members = { 0, 0x7e, 0x41 }, + .etags = { 0, 0x40, 0x40 }, + .vids = { 0, 1, 2 }, ++ }, { ++ .name = "lwlll", ++ .pvids = { 1, 2, 1, 1, 1, 1, 1 }, ++ .members = { 0, 0x7d, 0x42 }, ++ .etags = { 0, 0x40, 0x40 }, ++ .vids = { 0, 1, 2 }, + }, + }; +@@ -467,6 +479,14 @@ mt7530_set_vid(struct switch_dev *dev, c + } + + static int ++mt7621_get_vid(struct switch_dev *dev, const struct switch_attr *attr, ++ struct switch_val *val) ++{ ++ val->value.i = val->port_vlan; ++ return 0; ++} ++ ++static int + mt7530_get_vid(struct switch_dev *dev, const struct switch_attr *attr, + struct switch_val *val) + { +@@ -485,6 +505,52 @@ mt7530_get_vid(struct switch_dev *dev, c + return 0; + } + ++static void ++mt7530_write_vlan_entry(struct mt7530_priv *priv, int vlan, u16 vid, ++ u8 ports, u8 etags) ++{ ++ int port; ++ u32 val; ++ +#ifndef CONFIG_SOC_MT7621 - /* vid of vlan */ - val = mt7530_r32(priv, REG_ESW_VLAN_VTIM(i)); - if (i % 2 == 0) { -@@ -557,7 +558,7 @@ mt7530_apply_config(struct switch_dev *d - val |= (vid << 12); - } - mt7530_w32(priv, REG_ESW_VLAN_VTIM(i), val); -- ++ /* vid of vlan */ ++ val = mt7530_r32(priv, REG_ESW_VLAN_VTIM(vlan)); ++ if (vlan % 2 == 0) { ++ val &= 0xfff000; ++ val |= vid; ++ } else { ++ val &= 0xfff; ++ val |= (vid << 12); ++ } ++ mt7530_w32(priv, REG_ESW_VLAN_VTIM(vlan), val); +#endif - /* vlan port membership */ - if (member) - mt7530_w32(priv, REG_ESW_VLAN_VAWD1, REG_ESW_VLAN_VAWD1_IVL_MAC | -@@ -577,7 +578,11 @@ mt7530_apply_config(struct switch_dev *d - mt7530_w32(priv, REG_ESW_VLAN_VAWD2, val); - - /* write to vlan table */ ++ ++ /* vlan port membership */ ++ if (ports) ++ mt7530_w32(priv, REG_ESW_VLAN_VAWD1, REG_ESW_VLAN_VAWD1_IVL_MAC | ++ REG_ESW_VLAN_VAWD1_VTAG_EN | (ports << 16) | ++ REG_ESW_VLAN_VAWD1_VALID); ++ else ++ mt7530_w32(priv, REG_ESW_VLAN_VAWD1, 0); ++ ++ /* egress mode */ ++ val = 0; ++ for (port = 0; port < MT7530_NUM_PORTS; port++) { ++ if (etags & BIT(port)) ++ val |= ETAG_CTRL_TAG << (port * 2); ++ else ++ val |= ETAG_CTRL_UNTAG << (port * 2); ++ } ++ mt7530_w32(priv, REG_ESW_VLAN_VAWD2, val); ++ ++ /* write to vlan table */ +#ifdef CONFIG_SOC_MT7621 -+ mt7530_vtcr(priv, 1, vid); ++ mt7530_vtcr(priv, 1, vid); +#else - mt7530_vtcr(priv, 1, i); ++ mt7530_vtcr(priv, 1, vlan); +#endif ++} ++ + static int + mt7530_apply_config(struct switch_dev *dev) + { +@@ -541,51 +607,33 @@ mt7530_apply_config(struct switch_dev *d + mt7530_w32(priv, REG_ESW_PORT_PVC(i), pvc_mode); + } + ++ /* first clear the swtich vlan table */ ++ for (i = 0; i < MT7530_NUM_VLANS; i++) ++ mt7530_write_vlan_entry(priv, i, i, 0, 0); ++ ++ /* now program only vlans with members to avoid ++ clobbering remapped entries in later iterations */ + for (i = 0; i < MT7530_NUM_VLANS; i++) { + u16 vid = priv->vlan_entries[i].vid; + u8 member = priv->vlan_entries[i].member; + u8 etags = priv->vlan_entries[i].etags; +- u32 val; + +- /* vid of vlan */ +- val = mt7530_r32(priv, REG_ESW_VLAN_VTIM(i)); +- if (i % 2 == 0) { +- val &= 0xfff000; +- val |= vid; +- } else { +- val &= 0xfff; +- val |= (vid << 12); +- } +- mt7530_w32(priv, REG_ESW_VLAN_VTIM(i), val); +- +- /* vlan port membership */ + if (member) +- mt7530_w32(priv, REG_ESW_VLAN_VAWD1, REG_ESW_VLAN_VAWD1_IVL_MAC | +- REG_ESW_VLAN_VAWD1_VTAG_EN | (member << 16) | +- REG_ESW_VLAN_VAWD1_VALID); +- else +- mt7530_w32(priv, REG_ESW_VLAN_VAWD1, 0); +- +- /* egress mode */ +- val = 0; +- for (j = 0; j < MT7530_NUM_PORTS; j++) { +- if (etags & BIT(j)) +- val |= ETAG_CTRL_TAG << (j * 2); +- else +- val |= ETAG_CTRL_UNTAG << (j * 2); +- } +- mt7530_w32(priv, REG_ESW_VLAN_VAWD2, val); +- +- /* write to vlan table */ +- mt7530_vtcr(priv, 1, i); ++ mt7530_write_vlan_entry(priv, i, vid, member, etags); } /* Port Default PVID */ + for (i = 0; i < MT7530_NUM_PORTS; i++) { ++ int vlan = priv->port_entries[i].pvid; ++ u16 pvid = 0; + u32 val; ++ ++ if (vlan < MT7530_NUM_VLANS && priv->vlan_entries[vlan].member) ++ pvid = priv->vlan_entries[vlan].vid; ++ + val = mt7530_r32(priv, REG_ESW_PORT_PPBV1(i)); + val &= ~0xfff; +- val |= priv->port_entries[i].pvid; ++ val |= pvid; + mt7530_w32(priv, REG_ESW_PORT_PPBV1(i), val); + } + +@@ -739,6 +787,34 @@ static int mt7530_sw_get_port_mib(struct + return 0; + } + ++static int mt7530_get_port_stats(struct switch_dev *dev, int port, ++ struct switch_port_stats *stats) ++{ ++ struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); ++ ++ if (port < 0 || port >= MT7530_NUM_PORTS) ++ return -EINVAL; ++ ++ stats->tx_bytes = get_mib_counter_port_7620(priv, MT7530_PORT_MIB_TXB_ID, port); ++ stats->rx_bytes = get_mib_counter_port_7620(priv, MT7530_PORT_MIB_RXB_ID, port); ++ ++ return 0; ++} ++ ++static int mt7621_get_port_stats(struct switch_dev *dev, int port, ++ struct switch_port_stats *stats) ++{ ++ struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); ++ ++ if (port < 0 || port >= MT7530_NUM_PORTS) ++ return -EINVAL; ++ ++ stats->tx_bytes = get_mib_counter(priv, MT7621_PORT_MIB_TXB_ID, port); ++ stats->rx_bytes = get_mib_counter(priv, MT7621_PORT_MIB_RXB_ID, port); ++ ++ return 0; ++} ++ + static const struct switch_attr mt7530_global[] = { + { + .type = SWITCH_TYPE_INT, +@@ -767,6 +843,17 @@ static const struct switch_attr mt7621_p + }, + }; + ++static const struct switch_attr mt7621_vlan[] = { ++ { ++ .type = SWITCH_TYPE_INT, ++ .name = "vid", ++ .description = "VLAN ID (0-4094)", ++ .set = mt7530_set_vid, ++ .get = mt7621_get_vid, ++ .max = 4094, ++ }, ++}; ++ + static const struct switch_attr mt7530_port[] = { + { + .type = SWITCH_TYPE_STRING, +@@ -798,14 +885,15 @@ static const struct switch_dev_ops mt762 + .n_attr = ARRAY_SIZE(mt7621_port), + }, + .attr_vlan = { +- .attr = mt7530_vlan, +- .n_attr = ARRAY_SIZE(mt7530_vlan), ++ .attr = mt7621_vlan, ++ .n_attr = ARRAY_SIZE(mt7621_vlan), + }, + .get_vlan_ports = mt7530_get_vlan_ports, + .set_vlan_ports = mt7530_set_vlan_ports, + .get_port_pvid = mt7530_get_port_pvid, + .set_port_pvid = mt7530_set_port_pvid, + .get_port_link = mt7530_get_port_link, ++ .get_port_stats = mt7621_get_port_stats, + .apply_config = mt7530_apply_config, + .reset_switch = mt7530_reset_switch, + }; +@@ -828,6 +916,7 @@ static const struct switch_dev_ops mt753 + .get_port_pvid = mt7530_get_port_pvid, + .set_port_pvid = mt7530_set_port_pvid, + .get_port_link = mt7530_get_port_link, ++ .get_port_stats = mt7530_get_port_stats, + .apply_config = mt7530_apply_config, + .reset_switch = mt7530_reset_switch, + }; +@@ -881,7 +970,7 @@ mt7530_probe(struct device *dev, void __ + + /* magic vodoo */ + if (!IS_ENABLED(CONFIG_SOC_MT7621) && bus && mt7530_r32(mt7530, REG_HWTRAP) != 0x1117edf) { +- dev_info(dev, "fixing up MHWTRAP register - bootloader probably played with it\n"); ++ dev_info(dev, "fixing up MHWTRAP register - bootloader probably played with it\n"); + mt7530_w32(mt7530, REG_HWTRAP, 0x1117edf); + } + dev_info(dev, "loaded %s driver\n", swdev->name); -- cgit v1.1