From 0724412c58896b765fff77d63907729d298fbb67 Mon Sep 17 00:00:00 2001 From: Markus Stockhausen Date: Tue, 5 Aug 2025 11:46:40 -0400 Subject: [PATCH] realtek: RTL838x harden ethernet driver against fuzzying 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 Link: https://github.com/openwrt/openwrt/pull/19679 Signed-off-by: Robert Marko --- .../files-6.12/drivers/net/ethernet/rtl838x_eth.c | 10 ++++++---- .../files-6.12/drivers/net/ethernet/rtl838x_eth.h | 1 + 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.c b/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.c index 66b808dba91..37dab0f2db7 100644 --- a/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.c +++ b/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.c @@ -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) { + /* 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++) { - 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++) { - 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 */ diff --git a/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.h b/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.h index 24c750b4032..edeea8f6e2b 100644 --- a/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.h +++ b/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.h @@ -165,6 +165,7 @@ #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) -- 2.47.2