mirror of https://github.com/hak5/openwrt.git
ramips: backport mt7530/762x switch fixes
lede-17.01dc7a1e8555
("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 <jo@mein.io>
parent
b15d54e659
commit
623cdc4ffe
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue