realtek: fix standalone ports in presence of static fdb entries
authorJan Hoffmann <jan@3e8.eu>
Sat, 6 May 2023 17:28:54 +0000 (19:28 +0200)
committerSander Vanheule <sander@svanheule.net>
Sun, 7 May 2023 17:07:34 +0000 (19:07 +0200)
The registers L2_PORT_STATIC_MV_ACT seem to specify the action to take
when the source address of a packet exists as a static fdb entry on
another port. By default the configured action is to drop such packets.

For standalone ports, this behaviour is undesired, as all traffic should
be forwarded to the CPU. So change the action to forward on standalone
ports.

A situation where this issue can occur is when a non-offloaded bond
interface is part of a bridge. In that case, the CPU port will have fdb
entries for devices connected to the bond interface, which are managed
by the assisted learning feature.

For now, this is only implemented for RTL838x/RTL839x, as the available
set of registers differs for the other devices.

Signed-off-by: Jan Hoffmann <jan@3e8.eu>
target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/dsa.c
target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.c
target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.h
target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl839x.c
target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c
target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl838x.c
target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl838x.h
target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl839x.c

index b5b39336a6849dec3c45a21c9b5210eefebfe168..2d603cd42cdfc13da71dd2c72d9b9a2b176c5396 100644 (file)
@@ -197,6 +197,14 @@ static int rtl83xx_setup(struct dsa_switch *ds)
        }
        priv->r->traffic_set(priv->cpu_port, BIT_ULL(priv->cpu_port));
 
+       /* For standalone ports, forward packets even if a static fdb
+        * entry for the source address exists on another port.
+        */
+       if (priv->r->set_static_move_action) {
+               for (i = 0; i <= priv->cpu_port; i++)
+                       priv->r->set_static_move_action(i, true);
+       }
+
        if (priv->family_id == RTL8380_FAMILY_ID)
                rtl838x_print_matrix();
        else
@@ -1217,6 +1225,10 @@ static int rtl83xx_port_bridge_join(struct dsa_switch *ds, int port,
                priv->r->traffic_set(port, v);
        }
        priv->ports[port].pm |= port_bitmap;
+
+       if (priv->r->set_static_move_action)
+               priv->r->set_static_move_action(port, false);
+
        mutex_unlock(&priv->reg_mutex);
 
        return 0;
@@ -1258,6 +1270,9 @@ static void rtl83xx_port_bridge_leave(struct dsa_switch *ds, int port,
        }
        priv->ports[port].pm &= ~port_bitmap;
 
+       if (priv->r->set_static_move_action)
+               priv->r->set_static_move_action(port, true);
+
        mutex_unlock(&priv->reg_mutex);
 }
 
index 9ce50989790e12ab45c7dc38c962f39b973ef107..74ad03127687c61eca213a5767112810f7bf7ec3 100644 (file)
@@ -559,6 +559,15 @@ static void rtl838x_enable_bcast_flood(int port, bool enable)
 
 }
 
+static void rtl838x_set_static_move_action(int port, bool forward)
+{
+       int shift = MV_ACT_PORT_SHIFT(port);
+       u32 val = forward ? MV_ACT_FORWARD : MV_ACT_DROP;
+
+       sw_w32_mask(MV_ACT_MASK << shift, val << shift,
+                   RTL838X_L2_PORT_STATIC_MV_ACT(port));
+}
+
 static void rtl838x_stp_get(struct rtl838x_switch_priv *priv, u16 msti, u32 port_state[])
 {
        int i;
@@ -1750,6 +1759,7 @@ const struct rtl838x_reg rtl838x_reg = {
        .enable_flood = rtl838x_enable_flood,
        .enable_mcast_flood = rtl838x_enable_mcast_flood,
        .enable_bcast_flood = rtl838x_enable_bcast_flood,
+       .set_static_move_action = rtl838x_set_static_move_action,
        .stp_get = rtl838x_stp_get,
        .stp_set = rtl838x_stp_set,
        .mac_port_ctrl = rtl838x_mac_port_ctrl,
index 19049e4c957a069212b4521d39592004571eb011..3f1f1d49f8e711bcd7e13d65aed02b4da6daefd6 100644 (file)
 #define RTL930X_L2_PORT_NEW_SA_FWD(p)          (0x8FF4 + (((p / 10) << 2)))
 #define RTL931X_L2_PORT_NEW_SA_FWD(p)          (0xC830 + (((p / 10) << 2)))
 
+#define RTL838X_L2_PORT_MV_ACT(p)              (0x335c + (((p >> 4) << 2)))
+#define RTL839X_L2_PORT_MV_ACT(p)              (0x3b80 + (((p >> 4) << 2)))
+
+#define RTL838X_L2_PORT_STATIC_MV_ACT(p)       (0x327c + (((p >> 4) << 2)))
+#define RTL839X_L2_PORT_STATIC_MV_ACT(p)       (0x38dc + (((p >> 4) << 2)))
+
+#define MV_ACT_PORT_SHIFT(p)                   ((p % 16) * 2)
+#define MV_ACT_MASK                            0x3
+#define MV_ACT_FORWARD                         0
+#define MV_ACT_DROP                            1
+#define MV_ACT_TRAP2CPU                                2
+#define MV_ACT_COPY2CPU                                3
+
 #define RTL930X_ST_CTRL                                (0x8798)
 
 #define RTL930X_L2_PORT_SABLK_CTRL             (0x905c)
@@ -982,6 +995,7 @@ struct rtl838x_reg {
        void (*enable_flood)(int port, bool enable);
        void (*enable_mcast_flood)(int port, bool enable);
        void (*enable_bcast_flood)(int port, bool enable);
+       void (*set_static_move_action)(int port, bool forward);
        void (*stp_get)(struct rtl838x_switch_priv *priv, u16 msti, u32 port_state[]);
        void (*stp_set)(struct rtl838x_switch_priv *priv, u16 msti, u32 port_state[]);
        int  (*mac_force_mode_ctrl)(int port);
index 986a4b5f45c7c1bd394691420a084cb9498c4a9d..c34bff78d73b5a9ca1e8aafcced6110f0bed933c 100644 (file)
@@ -602,6 +602,16 @@ static void rtl839x_enable_bcast_flood(int port, bool enable)
 {
 
 }
+
+static void rtl839x_set_static_move_action(int port, bool forward)
+{
+       int shift = MV_ACT_PORT_SHIFT(port);
+       u32 val = forward ? MV_ACT_FORWARD : MV_ACT_DROP;
+
+       sw_w32_mask(MV_ACT_MASK << shift, val << shift,
+                   RTL839X_L2_PORT_STATIC_MV_ACT(port));
+}
+
 irqreturn_t rtl839x_switch_irq(int irq, void *dev_id)
 {
        struct dsa_switch *ds = dev_id;
@@ -1893,6 +1903,7 @@ const struct rtl838x_reg rtl839x_reg = {
        .enable_flood = rtl839x_enable_flood,
        .enable_mcast_flood = rtl839x_enable_mcast_flood,
        .enable_bcast_flood = rtl839x_enable_bcast_flood,
+       .set_static_move_action = rtl839x_set_static_move_action,
        .stp_get = rtl839x_stp_get,
        .stp_set = rtl839x_stp_set,
        .mac_force_mode_ctrl = rtl839x_mac_force_mode_ctrl,
index 3ecdda205f47f619727932d5a303b9b417fe8ae3..703306498e04dbbe9d0856995966d42d3fae3f84 100644 (file)
@@ -188,6 +188,14 @@ static int rtl83xx_setup(struct dsa_switch *ds)
        }
        priv->r->traffic_set(priv->cpu_port, BIT_ULL(priv->cpu_port));
 
+       /* For standalone ports, forward packets even if a static fdb
+        * entry for the source address exists on another port.
+        */
+       if (priv->r->set_static_move_action) {
+               for (int i = 0; i <= priv->cpu_port; i++)
+                       priv->r->set_static_move_action(i, true);
+       }
+
        if (priv->family_id == RTL8380_FAMILY_ID)
                rtl838x_print_matrix();
        else
@@ -1202,6 +1210,10 @@ static int rtl83xx_port_bridge_join(struct dsa_switch *ds, int port,
                priv->r->traffic_set(port, v);
        }
        priv->ports[port].pm |= port_bitmap;
+
+       if (priv->r->set_static_move_action)
+               priv->r->set_static_move_action(port, false);
+
        mutex_unlock(&priv->reg_mutex);
 
        return 0;
@@ -1242,6 +1254,9 @@ static void rtl83xx_port_bridge_leave(struct dsa_switch *ds, int port,
        }
        priv->ports[port].pm &= ~port_bitmap;
 
+       if (priv->r->set_static_move_action)
+               priv->r->set_static_move_action(port, true);
+
        mutex_unlock(&priv->reg_mutex);
 }
 
index 504b29822a1fca7f7f185676285323bb598ad1b6..606066aeea9b511c5734f74ce538a8076080f90a 100644 (file)
@@ -543,6 +543,15 @@ static void rtl838x_enable_bcast_flood(int port, bool enable)
 
 }
 
+static void rtl838x_set_static_move_action(int port, bool forward)
+{
+       int shift = MV_ACT_PORT_SHIFT(port);
+       u32 val = forward ? MV_ACT_FORWARD : MV_ACT_DROP;
+
+       sw_w32_mask(MV_ACT_MASK << shift, val << shift,
+                   RTL838X_L2_PORT_STATIC_MV_ACT(port));
+}
+
 static void rtl838x_stp_get(struct rtl838x_switch_priv *priv, u16 msti, u32 port_state[])
 {
        u32 cmd = 1 << 15 | /* Execute cmd */
@@ -1717,6 +1726,7 @@ const struct rtl838x_reg rtl838x_reg = {
        .enable_flood = rtl838x_enable_flood,
        .enable_mcast_flood = rtl838x_enable_mcast_flood,
        .enable_bcast_flood = rtl838x_enable_bcast_flood,
+       .set_static_move_action = rtl838x_set_static_move_action,
        .stp_get = rtl838x_stp_get,
        .stp_set = rtl838x_stp_set,
        .mac_port_ctrl = rtl838x_mac_port_ctrl,
index a4bfc285a60ce2dfe3403491cfbee4d71ce139ea..bfab576e06ecedebe6f12eebd8a12fe0b4cba50f 100644 (file)
 #define RTL930X_L2_PORT_NEW_SA_FWD(p)          (0x8FF4 + (((p / 10) << 2)))
 #define RTL931X_L2_PORT_NEW_SA_FWD(p)          (0xC830 + (((p / 10) << 2)))
 
+#define RTL838X_L2_PORT_MV_ACT(p)              (0x335c + (((p >> 4) << 2)))
+#define RTL839X_L2_PORT_MV_ACT(p)              (0x3b80 + (((p >> 4) << 2)))
+
+#define RTL838X_L2_PORT_STATIC_MV_ACT(p)       (0x327c + (((p >> 4) << 2)))
+#define RTL839X_L2_PORT_STATIC_MV_ACT(p)       (0x38dc + (((p >> 4) << 2)))
+
+#define MV_ACT_PORT_SHIFT(p)                   ((p % 16) * 2)
+#define MV_ACT_MASK                            0x3
+#define MV_ACT_FORWARD                         0
+#define MV_ACT_DROP                            1
+#define MV_ACT_TRAP2CPU                                2
+#define MV_ACT_COPY2CPU                                3
+
 #define RTL930X_ST_CTRL                                (0x8798)
 
 #define RTL930X_L2_PORT_SABLK_CTRL             (0x905c)
@@ -978,6 +991,7 @@ struct rtl838x_reg {
        void (*enable_flood)(int port, bool enable);
        void (*enable_mcast_flood)(int port, bool enable);
        void (*enable_bcast_flood)(int port, bool enable);
+       void (*set_static_move_action)(int port, bool forward);
        void (*stp_get)(struct rtl838x_switch_priv *priv, u16 msti, u32 port_state[]);
        void (*stp_set)(struct rtl838x_switch_priv *priv, u16 msti, u32 port_state[]);
        int  (*mac_force_mode_ctrl)(int port);
index 06fdbd8936190f5759e5a919d03f2641daa71636..fe5572a4476ebb851c1d5a6b25589a177503696c 100644 (file)
@@ -590,6 +590,16 @@ static void rtl839x_enable_bcast_flood(int port, bool enable)
 {
 
 }
+
+static void rtl839x_set_static_move_action(int port, bool forward)
+{
+       int shift = MV_ACT_PORT_SHIFT(port);
+       u32 val = forward ? MV_ACT_FORWARD : MV_ACT_DROP;
+
+       sw_w32_mask(MV_ACT_MASK << shift, val << shift,
+                   RTL839X_L2_PORT_STATIC_MV_ACT(port));
+}
+
 irqreturn_t rtl839x_switch_irq(int irq, void *dev_id)
 {
        struct dsa_switch *ds = dev_id;
@@ -1855,6 +1865,7 @@ const struct rtl838x_reg rtl839x_reg = {
        .enable_flood = rtl839x_enable_flood,
        .enable_mcast_flood = rtl839x_enable_mcast_flood,
        .enable_bcast_flood = rtl839x_enable_bcast_flood,
+       .set_static_move_action = rtl839x_set_static_move_action,
        .stp_get = rtl839x_stp_get,
        .stp_set = rtl839x_stp_set,
        .mac_force_mode_ctrl = rtl839x_mac_force_mode_ctrl,