diff mbox series

[v1,2/2] realtek: consistently flood RMA frames

Message ID 20220912200652.54877-2-sander@svanheule.net
State Accepted
Delegated to: Sander Vanheule
Headers show
Series [v1,1/2] realtek: remove RTL839x path in RTL838x multicast | expand

Commit Message

Sander Vanheule Sept. 12, 2022, 8:06 p.m. UTC
The switches support different actions for incoming ethernet multicast
frames with Reserved Multicast Addresses (01-80-C2-00-00-{01-2F}). The
current code will set the 2-bit action field to FLOOD (0x3) for most
classes, but the highest bit is always unset for the relevant control
registers. This means the DROP (0x1) action being used for these
classes; whatever class the MSB happens to be in.

For RTL838x, this results in {20,23-2F} frames being dropped, instead of
flooding all ports. On other switch generations, {0F,1F,2F} frames are
dropped. This is inconsistent, and appears to be a mistake. Remove this
inconsistency by flooding all multicast frames with RMA addresses.

Signed-off-by: Sander Vanheule <sander@svanheule.net>
---
 .../drivers/net/ethernet/rtl838x_eth.c        | 70 +++++++++++--------
 1 file changed, 40 insertions(+), 30 deletions(-)
diff mbox series

Patch

diff --git a/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c b/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c
index fcb6a6d10e6d..c4cbcfded843 100644
--- a/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c
+++ b/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c
@@ -1032,20 +1032,30 @@  static int rtl838x_eth_stop(struct net_device *ndev)
 
 static void rtl838x_eth_set_multicast_list(struct net_device *ndev)
 {
+	/*
+	 * Flood all classes of RMA addresses (01-80-C2-00-00-{01..2F})
+	 * CTRL_0_FULL = GENMASK(21, 0) = 0x3FFFFF
+	 */
 	if (!(ndev->flags & (IFF_PROMISC | IFF_ALLMULTI))) {
 		sw_w32(0x0, RTL838X_RMA_CTRL_0);
 		sw_w32(0x0, RTL838X_RMA_CTRL_1);
 	}
 	if (ndev->flags & IFF_ALLMULTI)
-		sw_w32(0x1fffff, RTL838X_RMA_CTRL_0);
+		sw_w32(GENMASK(21, 0), RTL838X_RMA_CTRL_0);
 	if (ndev->flags & IFF_PROMISC) {
-		sw_w32(0x1fffff, RTL838X_RMA_CTRL_0);
+		sw_w32(GENMASK(21, 0), RTL838X_RMA_CTRL_0);
 		sw_w32(0x7fff, RTL838X_RMA_CTRL_1);
 	}
 }
 
 static void rtl839x_eth_set_multicast_list(struct net_device *ndev)
 {
+	/*
+	 * Flood all classes of RMA addresses (01-80-C2-00-00-{01..2F})
+	 * CTRL_0_FULL = GENMASK(31, 2) = 0xFFFFFFFC
+	 * Lower two bits are reserved, corresponding to RMA 01-80-C2-00-00-00
+	 * CTRL_1_FULL = CTRL_2_FULL = GENMASK(31, 0)
+	 */
 	if (!(ndev->flags & (IFF_PROMISC | IFF_ALLMULTI))) {
 		sw_w32(0x0, RTL839X_RMA_CTRL_0);
 		sw_w32(0x0, RTL839X_RMA_CTRL_1);
@@ -1053,54 +1063,54 @@  static void rtl839x_eth_set_multicast_list(struct net_device *ndev)
 		sw_w32(0x0, RTL839X_RMA_CTRL_3);
 	}
 	if (ndev->flags & IFF_ALLMULTI) {
-		sw_w32(0x7fffffff, RTL839X_RMA_CTRL_0);
-		sw_w32(0x7fffffff, RTL839X_RMA_CTRL_1);
-		sw_w32(0x7fffffff, RTL839X_RMA_CTRL_2);
+		sw_w32(GENMASK(31, 2), RTL839X_RMA_CTRL_0);
+		sw_w32(GENMASK(31, 0), RTL839X_RMA_CTRL_1);
+		sw_w32(GENMASK(31, 0), RTL839X_RMA_CTRL_2);
 	}
 	if (ndev->flags & IFF_PROMISC) {
-		sw_w32(0x7fffffff, RTL839X_RMA_CTRL_0);
-		sw_w32(0x7fffffff, RTL839X_RMA_CTRL_1);
-		sw_w32(0x7fffffff, RTL839X_RMA_CTRL_2);
+		sw_w32(GENMASK(31, 2), RTL839X_RMA_CTRL_0);
+		sw_w32(GENMASK(31, 0), RTL839X_RMA_CTRL_1);
+		sw_w32(GENMASK(31, 0), RTL839X_RMA_CTRL_2);
 		sw_w32(0x3ff, RTL839X_RMA_CTRL_3);
 	}
 }
 
 static void rtl930x_eth_set_multicast_list(struct net_device *ndev)
 {
-	if (!(ndev->flags & (IFF_PROMISC | IFF_ALLMULTI))) {
+	/*
+	 * Flood all classes of RMA addresses (01-80-C2-00-00-{01..2F})
+	 * CTRL_0_FULL = GENMASK(31, 2) = 0xFFFFFFFC
+	 * Lower two bits are reserved, corresponding to RMA 01-80-C2-00-00-00
+	 * CTRL_1_FULL = CTRL_2_FULL = GENMASK(31, 0)
+	 */
+	if (ndev->flags & (IFF_ALLMULTI | IFF_PROMISC)) {
+		sw_w32(GENMASK(31, 2), RTL930X_RMA_CTRL_0);
+		sw_w32(GENMASK(31, 0), RTL930X_RMA_CTRL_1);
+		sw_w32(GENMASK(31, 0), RTL930X_RMA_CTRL_2);
+	} else {
 		sw_w32(0x0, RTL930X_RMA_CTRL_0);
 		sw_w32(0x0, RTL930X_RMA_CTRL_1);
 		sw_w32(0x0, RTL930X_RMA_CTRL_2);
 	}
-	if (ndev->flags & IFF_ALLMULTI) {
-		sw_w32(0x7fffffff, RTL930X_RMA_CTRL_0);
-		sw_w32(0x7fffffff, RTL930X_RMA_CTRL_1);
-		sw_w32(0x7fffffff, RTL930X_RMA_CTRL_2);
-	}
-	if (ndev->flags & IFF_PROMISC) {
-		sw_w32(0x7fffffff, RTL930X_RMA_CTRL_0);
-		sw_w32(0x7fffffff, RTL930X_RMA_CTRL_1);
-		sw_w32(0x7fffffff, RTL930X_RMA_CTRL_2);
-	}
 }
 
 static void rtl931x_eth_set_multicast_list(struct net_device *ndev)
 {
-	if (!(ndev->flags & (IFF_PROMISC | IFF_ALLMULTI))) {
+	/*
+	 * Flood all classes of RMA addresses (01-80-C2-00-00-{01..2F})
+	 * CTRL_0_FULL = GENMASK(31, 2) = 0xFFFFFFFC
+	 * Lower two bits are reserved, corresponding to RMA 01-80-C2-00-00-00.
+	 * CTRL_1_FULL = CTRL_2_FULL = GENMASK(31, 0)
+	 */
+	if (ndev->flags & (IFF_ALLMULTI | IFF_PROMISC)) {
+		sw_w32(GENMASK(31, 2), RTL931X_RMA_CTRL_0);
+		sw_w32(GENMASK(31, 0), RTL931X_RMA_CTRL_1);
+		sw_w32(GENMASK(31, 0), RTL931X_RMA_CTRL_2);
+	} else {
 		sw_w32(0x0, RTL931X_RMA_CTRL_0);
 		sw_w32(0x0, RTL931X_RMA_CTRL_1);
 		sw_w32(0x0, RTL931X_RMA_CTRL_2);
 	}
-	if (ndev->flags & IFF_ALLMULTI) {
-		sw_w32(0x7fffffff, RTL931X_RMA_CTRL_0);
-		sw_w32(0x7fffffff, RTL931X_RMA_CTRL_1);
-		sw_w32(0x7fffffff, RTL931X_RMA_CTRL_2);
-	}
-	if (ndev->flags & IFF_PROMISC) {
-		sw_w32(0x7fffffff, RTL931X_RMA_CTRL_0);
-		sw_w32(0x7fffffff, RTL931X_RMA_CTRL_1);
-		sw_w32(0x7fffffff, RTL931X_RMA_CTRL_2);
-	}
 }
 
 static void rtl838x_eth_tx_timeout(struct net_device *ndev, unsigned int txqueue)