diff mbox series

[v2,3/4] realtek: fix standalone ports in presence of static fdb entries

Message ID 20230506172855.1138748-4-jan@3e8.eu
State Accepted
Delegated to: Sander Vanheule
Headers show
Series realtek: fix multiple issues with L2 forwarding | expand

Commit Message

Jan Hoffmann May 6, 2023, 5:28 p.m. UTC
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>
---
 .../files-5.10/drivers/net/dsa/rtl83xx/dsa.c      | 15 +++++++++++++++
 .../files-5.10/drivers/net/dsa/rtl83xx/rtl838x.c  | 10 ++++++++++
 .../files-5.10/drivers/net/dsa/rtl83xx/rtl838x.h  | 14 ++++++++++++++
 .../files-5.10/drivers/net/dsa/rtl83xx/rtl839x.c  | 11 +++++++++++
 .../files-5.15/drivers/net/dsa/rtl83xx/dsa.c      | 15 +++++++++++++++
 .../files-5.15/drivers/net/dsa/rtl83xx/rtl838x.c  | 10 ++++++++++
 .../files-5.15/drivers/net/dsa/rtl83xx/rtl838x.h  | 14 ++++++++++++++
 .../files-5.15/drivers/net/dsa/rtl83xx/rtl839x.c  | 11 +++++++++++
 8 files changed, 100 insertions(+)
diff mbox series

Patch

diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/dsa.c b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/dsa.c
index b5b39336a684..2d603cd42cdf 100644
--- a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/dsa.c
+++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/dsa.c
@@ -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);
 }
 
diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.c b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.c
index 9ce50989790e..74ad03127687 100644
--- a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.c
+++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.c
@@ -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,
diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.h b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.h
index 19049e4c957a..3f1f1d49f8e7 100644
--- a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.h
+++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.h
@@ -251,6 +251,19 @@ 
 #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);
diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl839x.c b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl839x.c
index 986a4b5f45c7..c34bff78d73b 100644
--- a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl839x.c
+++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl839x.c
@@ -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,
diff --git a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c
index 3ecdda205f47..703306498e04 100644
--- a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c
+++ b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c
@@ -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);
 }
 
diff --git a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl838x.c b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl838x.c
index 504b29822a1f..606066aeea9b 100644
--- a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl838x.c
+++ b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl838x.c
@@ -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,
diff --git a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl838x.h b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl838x.h
index a4bfc285a60c..bfab576e06ec 100644
--- a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl838x.h
+++ b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl838x.h
@@ -249,6 +249,19 @@ 
 #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);
diff --git a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl839x.c b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl839x.c
index 06fdbd893619..fe5572a4476e 100644
--- a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl839x.c
+++ b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl839x.c
@@ -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,