]> git.ipfire.org Git - thirdparty/openwrt.git/commitdiff
realtek: RTL838x harden ethernet driver against fuzzying main master 19679/head
authorMarkus Stockhausen <markus.stockhausen@gmx.de>
Tue, 5 Aug 2025 15:46:40 +0000 (11:46 -0400)
committerRobert Marko <robimarko@gmail.com>
Mon, 11 Aug 2025 13:18:09 +0000 (15:18 +0200)
While checking setup routines for stability and completeness,
random RTL838x SoC I/O areas were intentionally overwritten.
As soon as L2_CTRL_1->FAST_AGE_OUT is set to 1, the system
stalls during bootup. Analysis shows that it loops endlessly
in rtl838x_hw_stop()

/* Flush L2 address cache */
if (priv->family_id == RTL8380_FAMILY_ID) {
for (int i = 0; i <= priv->cpu_port; i++) {
sw_w32(1 << 26 | 1 << 23 | i << 5, priv->r->l2_tbl_flush_ctrl);
do { } while (sw_r32(priv->r->l2_tbl_flush_ctrl) & (1 << 26));
}

This is exactly the same logic as in the vendor GPL. There
are no hints about possible timeouts or issues. The reason is
still unclear. Nevertheless harden the function for further fuzzy
tests. Do this by resetting the configuration value to its SoC
default.

Additionally convert some shifts to BIT() for better readability.

Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
Link: https://github.com/openwrt/openwrt/pull/19679
Signed-off-by: Robert Marko <robimarko@gmail.com>
target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.c
target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.h

index 66b808dba913a619b0b03b2827d7799f31086476..37dab0f2db73f69e871524f399bd012577e456cf 100644 (file)
@@ -947,14 +947,16 @@ static void rtl838x_hw_stop(struct rtl838x_eth_priv *priv)
 
        /* Flush L2 address cache */
        if (priv->family_id == RTL8380_FAMILY_ID) {
 
        /* Flush L2 address cache */
        if (priv->family_id == RTL8380_FAMILY_ID) {
+               /* Disable FAST_AGE_OUT otherwise flush will hang */
+               sw_w32_mask(BIT(23), 0, RTL838X_L2_CTRL_1);
                for (int i = 0; i <= priv->cpu_port; i++) {
                for (int i = 0; i <= priv->cpu_port; i++) {
-                       sw_w32(1 << 26 | 1 << 23 | i << 5, priv->r->l2_tbl_flush_ctrl);
-                       do { } while (sw_r32(priv->r->l2_tbl_flush_ctrl) & (1 << 26));
+                       sw_w32(BIT(26) | BIT(23) | i << 5, priv->r->l2_tbl_flush_ctrl);
+                       do { } while (sw_r32(priv->r->l2_tbl_flush_ctrl) & BIT(26));
                }
        } else if (priv->family_id == RTL8390_FAMILY_ID) {
                for (int i = 0; i <= priv->cpu_port; i++) {
                }
        } else if (priv->family_id == RTL8390_FAMILY_ID) {
                for (int i = 0; i <= priv->cpu_port; i++) {
-                       sw_w32(1 << 28 | 1 << 25 | i << 5, priv->r->l2_tbl_flush_ctrl);
-                       do { } while (sw_r32(priv->r->l2_tbl_flush_ctrl) & (1 << 28));
+                       sw_w32(BIT(28) | BIT(25) | i << 5, priv->r->l2_tbl_flush_ctrl);
+                       do { } while (sw_r32(priv->r->l2_tbl_flush_ctrl) & BIT(28));
                }
        }
        /* TODO: L2 flush register is 64 bit on RTL931X and 930X */
                }
        }
        /* TODO: L2 flush register is 64 bit on RTL931X and 930X */
index 24c750b40327064d00b63bc1b1981d726916b7f9..edeea8f6e2b07f6fc7eb7bba4a337f868e083b05 100644 (file)
 #define RTL839X_L2_NOTIFICATION_CTRL           (0x7808)
 #define RTL931X_L2_NTFY_CTRL                   (0xCDC8)
 #define RTL838X_L2_CTRL_0                      (0x3200)
 #define RTL839X_L2_NOTIFICATION_CTRL           (0x7808)
 #define RTL931X_L2_NTFY_CTRL                   (0xCDC8)
 #define RTL838X_L2_CTRL_0                      (0x3200)
+#define RTL838X_L2_CTRL_1                      (0x3204)
 #define RTL839X_L2_CTRL_0                      (0x3800)
 #define RTL930X_L2_CTRL                                (0x8FD8)
 #define RTL931X_L2_CTRL                                (0xC800)
 #define RTL839X_L2_CTRL_0                      (0x3800)
 #define RTL930X_L2_CTRL                                (0x8FD8)
 #define RTL931X_L2_CTRL                                (0xC800)