rtl838x: merge bmork's vlan fixes
authorJohn Crispin <john@phrozen.org>
Tue, 24 Nov 2020 12:58:35 +0000 (13:58 +0100)
committerJohn Crispin <john@phrozen.org>
Tue, 24 Nov 2020 14:55:59 +0000 (15:55 +0100)
Signed-off-by: Bjørn Mork <bjorn@mork.no>
target/linux/rtl838x/files-5.4/drivers/net/dsa/rtl83xx/debugfs.c
target/linux/rtl838x/files-5.4/drivers/net/dsa/rtl83xx/dsa.c
target/linux/rtl838x/files-5.4/drivers/net/dsa/rtl83xx/rtl838x.c
target/linux/rtl838x/files-5.4/drivers/net/dsa/rtl83xx/rtl838x.h
target/linux/rtl838x/files-5.4/drivers/net/dsa/rtl83xx/rtl839x.c

index 826b63526034defc2207acdc4b7b10abf8180636..af24e8fa42a326f69a5670d498c9dec88f320bfa 100644 (file)
@@ -38,6 +38,10 @@ static int rtl838x_dbgfs_port_init(struct dentry *parent, struct rtl838x_switch_
 
        debugfs_create_u32("id", 0444, port_dir, &priv->ports[port].dp->index);
 
+
+       debugfs_create_x32("vlan_port_tag_sts_ctrl", 0644, port_dir,
+                          (u32 *)(RTL838X_SW_BASE + RTL838X_VLAN_PORT_TAG_STS_CTRL(port)));
+
        port_ctrl_regset = devm_kzalloc(priv->dev, sizeof(*port_ctrl_regset), GFP_KERNEL);
        if (!port_ctrl_regset)
                return -ENOMEM;
index bd756dd88f9524386a48f7007e4d60bd884ef5cb..a0717e1d9a1e40dd98984b99abeb2e77955983e1 100644 (file)
@@ -201,6 +201,8 @@ static int rtl83xx_setup(struct dsa_switch *ds)
 
        rtl83xx_init_stats(priv);
 
+       ds->configure_vlan_while_not_filtering = true;
+
        /* Enable MAC Polling PHY again */
        rtl83xx_enable_phy_polling(priv);
        pr_debug("Please wait until PHY is settled\n");
@@ -449,6 +451,9 @@ static int rtl83xx_port_enable(struct dsa_switch *ds, int port,
        pr_debug("%s: %x %d", __func__, (u32) priv, port);
        priv->ports[port].enable = true;
 
+       /* enable inner tagging on egress, do not keep any tags */
+       sw_w32(1, priv->r->vlan_port_tag_sts_ctrl(port));
+
        if (dsa_is_cpu_port(ds, port))
                return 0;
 
@@ -794,7 +799,6 @@ static void rtl83xx_vlan_add(struct dsa_switch *ds, int port,
        struct rtl838x_vlan_info info = {};
        struct rtl838x_switch_priv *priv = ds->priv;
        int v;
-       u64 portmask;
 
        pr_debug("%s port %d, vid_end %d, vid_end %d, flags %x\n", __func__,
                port, vlan->vid_begin, vlan->vid_end, vlan->flags);
@@ -808,28 +812,36 @@ static void rtl83xx_vlan_add(struct dsa_switch *ds, int port,
        mutex_lock(&priv->reg_mutex);
 
        if (vlan->flags & BRIDGE_VLAN_INFO_PVID) {
-               for (v = vlan->vid_begin; v <= vlan->vid_end; v++) {
-                       /* Set both inner and outer PVID of the port */
-                       sw_w32((v << 16) | v, priv->r->vlan_port_pb(port));
-               }
+               /* Set both inner and outer PVID of the port */
+               sw_w32((vlan->vid_end << 16) | vlan->vid_end << 2, priv->r->vlan_port_pb(port));
+               priv->ports[port].pvid = vlan->vid_end;
        }
 
-       if (vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED) {
-               for (v = vlan->vid_begin; v <= vlan->vid_end; v++) {
-                       /* Get untagged port memberships of this vlan */
-                       priv->r->vlan_tables_read(v, &info);
-                       portmask = info.untagged_ports | BIT(port);
-                       pr_debug("Untagged ports, VLAN %d: %llx\n", v, portmask);
-                       priv->r->vlan_set_untagged(v, portmask);
-               }
-       } else {
-               for (v = vlan->vid_begin; v <= vlan->vid_end; v++) {
-                       /* Get tagged port memberships of this vlan */
-                       priv->r->vlan_tables_read(v, &info);
-                       info.tagged_ports |= BIT(port);
-                       pr_debug("Tagged ports, VLAN %d: %llx\n", v, info.tagged_ports);
-                       priv->r->vlan_set_tagged(v, &info);
+       for (v = vlan->vid_begin; v <= vlan->vid_end; v++) {
+               /* Get port memberships of this vlan */
+               priv->r->vlan_tables_read(v, &info);
+
+               /* new VLAN? */
+               if (!info.tagged_ports) {
+                       info.fid = 0;
+                       info.hash_mc_fid = false;
+                       info.hash_uc_fid = false;
+                       info.profile_id = 0;
                }
+
+               /* sanitize untagged_ports - must be a subset */
+               if (info.untagged_ports & ~info.tagged_ports)
+                       info.untagged_ports = 0;
+
+               info.tagged_ports |= BIT_ULL(port);
+               if (vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED)
+                       info.untagged_ports |= BIT_ULL(port);
+
+               priv->r->vlan_set_untagged(v, info.untagged_ports);
+               pr_debug("Untagged ports, VLAN %d: %llx\n", v, info.untagged_ports);
+
+               priv->r->vlan_set_tagged(v, &info);
+               pr_debug("Tagged ports, VLAN %d: %llx\n", v, info.tagged_ports);
        }
 
        mutex_unlock(&priv->reg_mutex);
@@ -841,7 +853,7 @@ static int rtl83xx_vlan_del(struct dsa_switch *ds, int port,
        struct rtl838x_vlan_info info;
        struct rtl838x_switch_priv *priv = ds->priv;
        int v;
-       u64 portmask;
+       u16 pvid;
 
        pr_debug("%s: port %d, vid_end %d, vid_end %d, flags %x\n", __func__,
                port, vlan->vid_begin, vlan->vid_end, vlan->flags);
@@ -853,24 +865,27 @@ static int rtl83xx_vlan_del(struct dsa_switch *ds, int port,
        }
 
        mutex_lock(&priv->reg_mutex);
+       pvid = priv->ports[port].pvid;
 
        for (v = vlan->vid_begin; v <= vlan->vid_end; v++) {
-               /* Reset both inner and out PVID of the port */
-               sw_w32(0, priv->r->vlan_port_pb(port));
-
-               if (vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED) {
-                       /* Get untagged port memberships of this vlan */
-                       priv->r->vlan_tables_read(v, &info);
-                       portmask = info.untagged_ports & (~(1ULL << port));
-                       pr_debug("Untagged ports, VLAN %d: %llx\n", v, portmask);
-                       priv->r->vlan_set_untagged(v, portmask);
-               }
+               /* Reset to default if removing the current PVID */
+               if (v == pvid)
+                       sw_w32(0, priv->r->vlan_port_pb(port));
 
-               /* Get tagged port memberships of this vlan */
+               /* Get port memberships of this vlan */
                priv->r->vlan_tables_read(v, &info);
-               info.tagged_ports &= (~(1ULL << port));
-               pr_debug("Tagged ports, VLAN %d: %llx\n", v, info.tagged_ports);
+
+               /* remove port from both tables */
+               info.untagged_ports &= (~BIT_ULL(port));
+               /* always leave vid 1 */
+               if (v != 1)
+                       info.tagged_ports &= (~BIT_ULL(port));
+
+               priv->r->vlan_set_untagged(v, info.untagged_ports);
+               pr_debug("Untagged ports, VLAN %d: %llx\n", v, info.untagged_ports);
+
                priv->r->vlan_set_tagged(v, &info);
+               pr_debug("Tagged ports, VLAN %d: %llx\n", v, info.tagged_ports);
        }
        mutex_unlock(&priv->reg_mutex);
 
index 4b2a2d14341a47a6b367143c1a50625cc714cfbb..c7b5873e99c30cb94696affb3aa24aa02ae4ae57 100644 (file)
@@ -240,6 +240,11 @@ static inline int rtl838x_vlan_port_pb(int port)
        return RTL838X_VLAN_PORT_PB_VLAN(port);
 }
 
+static inline int rtl838x_vlan_port_tag_sts_ctrl(int port)
+{
+       return RTL838X_VLAN_PORT_TAG_STS_CTRL(port);
+}
+
 const struct rtl838x_reg rtl838x_reg = {
        .mask_port_reg_be = rtl838x_mask_port_reg,
        .set_port_reg_be = rtl838x_set_port_reg,
@@ -284,6 +289,7 @@ const struct rtl838x_reg rtl838x_reg = {
        .vlan_port_egr_filter = rtl838x_vlan_port_egr_filter,
        .vlan_port_igr_filter = rtl838x_vlan_port_igr_filter,
        .vlan_port_pb = rtl838x_vlan_port_pb,
+       .vlan_port_tag_sts_ctrl = rtl838x_vlan_port_tag_sts_ctrl,
 };
 
 irqreturn_t rtl838x_switch_irq(int irq, void *dev_id)
index f120aba81a4674d1f1c1d5c0f03da0ad36dcdfb8..1ebb4dff72e75d929e3f0755a17ada750ee076d3 100644 (file)
 #define RTL838X_VLAN_PORT_IGR_FLTR(port)       (0x3A7C + (((port >> 4) << 2)))
 #define RTL838X_VLAN_PORT_IGR_FLTR_0           (0x3A7C)
 #define RTL838X_VLAN_PORT_IGR_FLTR_1           (0x3A7C + 4)
+#define RTL838X_VLAN_PORT_TAG_STS_CTRL(port)   (0xA530 + (((port) << 2)))
 #define RTL839X_VLAN_PROFILE(idx)              (0x25C0 + (((idx) << 3)))
 #define RTL839X_VLAN_CTRL                      (0x26D4)
 #define RTL839X_VLAN_PORT_PB_VLAN(port)                (0x26D8 + (((port) << 2)))
 #define RTL839X_VLAN_PORT_IGR_FLTR(port)       (0x27B4 + (((port >> 4) << 2)))
 #define RTL839X_VLAN_PORT_EGR_FLTR(port)       (0x27C4 + (((port >> 5) << 2)))
+#define RTL839X_VLAN_PORT_TAG_STS_CTRL(port)   (0x6828 + (((port) << 2)))
 
 /* Table 0/1 access registers */
 #define RTL838X_TBL_ACCESS_CTRL_0              (0x6914)
@@ -264,6 +266,7 @@ struct rtl838x_reg {
        int (*vlan_port_egr_filter)(int port);
        int (*vlan_port_igr_filter)(int port);
        int (*vlan_port_pb)(int port);
+       int (*vlan_port_tag_sts_ctrl)(int port);
 };
 
 struct rtl838x_switch_priv {
index 8a694b129d77df5370850cbdb0bb44fd0c9341ac..8dd123f609f1c1a7403ef5306d3b45ed195a1319 100644 (file)
@@ -308,6 +308,11 @@ static inline int rtl839x_vlan_port_pb(int port)
        return RTL839X_VLAN_PORT_PB_VLAN(port);
 }
 
+static inline int rtl839x_vlan_port_tag_sts_ctrl(int port)
+{
+       return RTL839X_VLAN_PORT_TAG_STS_CTRL(port);
+}
+
 const struct rtl838x_reg rtl839x_reg = {
        .mask_port_reg_be = rtl839x_mask_port_reg_be,
        .set_port_reg_be = rtl839x_set_port_reg_be,
@@ -352,6 +357,7 @@ const struct rtl838x_reg rtl839x_reg = {
        .vlan_port_egr_filter = rtl839x_vlan_port_egr_filter,
        .vlan_port_igr_filter = rtl839x_vlan_port_igr_filter,
        .vlan_port_pb = rtl839x_vlan_port_pb,
+       .vlan_port_tag_sts_ctrl = rtl839x_vlan_port_tag_sts_ctrl,
 };
 
 irqreturn_t rtl839x_switch_irq(int irq, void *dev_id)