aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux
diff options
context:
space:
mode:
authorJo-Philipp Wich <jo@mein.io>2018-02-11 20:24:37 +0100
committerJo-Philipp Wich <jo@mein.io>2018-02-14 16:43:29 +0100
commitbb4002c79dd8ea7bec9643707277944da90d002c (patch)
treeb05a37c7f9adff13382d47e3d3a169f98fe22d9b /target/linux
parentb9aca834e812efc9d0bb2701eab8c78f2efb0367 (diff)
downloadupstream-bb4002c79dd8ea7bec9643707277944da90d002c.tar.gz
upstream-bb4002c79dd8ea7bec9643707277944da90d002c.tar.bz2
upstream-bb4002c79dd8ea7bec9643707277944da90d002c.zip
ramips: don't clobber vlans with remapped vid on mt7530/762x switches
Avoid overwriting vlan entries with remapped vid in later iterations of the vlan enumeration loop of mt7530_apply_config(). Fix the problem by refactoring the code to first reset the entire table, then reprogram only vlans with members to prevent overwriting configured vlans with unconfigured ones. Fixes FS#1147, FS#1341 Signed-off-by: Jo-Philipp Wich <jo@mein.io>
Diffstat (limited to 'target/linux')
-rw-r--r--target/linux/ramips/files-4.9/drivers/net/ethernet/mtk/mt7530.c89
1 files changed, 53 insertions, 36 deletions
diff --git a/target/linux/ramips/files-4.9/drivers/net/ethernet/mtk/mt7530.c b/target/linux/ramips/files-4.9/drivers/net/ethernet/mtk/mt7530.c
index 439d8c2661..e61f9fd8d3 100644
--- a/target/linux/ramips/files-4.9/drivers/net/ethernet/mtk/mt7530.c
+++ b/target/linux/ramips/files-4.9/drivers/net/ethernet/mtk/mt7530.c
@@ -497,6 +497,52 @@ mt7530_get_vid(struct switch_dev *dev, const struct switch_attr *attr,
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(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 (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);
+#else
+ mt7530_vtcr(priv, 1, vlan);
+#endif
+}
+
static int
mt7530_apply_config(struct switch_dev *dev)
{
@@ -553,48 +599,19 @@ mt7530_apply_config(struct switch_dev *dev)
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;
-#ifndef CONFIG_SOC_MT7621
- /* 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);
-#endif
- /* 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 */
-#ifdef CONFIG_SOC_MT7621
- mt7530_vtcr(priv, 1, vid);
-#else
- mt7530_vtcr(priv, 1, i);
-#endif
+ mt7530_write_vlan_entry(priv, i, vid, member, etags);
}
/* Port Default PVID */