[openwrt/openwrt] realtek: rtl931x: Fix unsafe MAC_L2_GLOBAL_CTRL2 access

LEDE Commits lede-commits at lists.infradead.org
Wed Sep 3 00:54:59 PDT 2025


robimarko pushed a commit to openwrt/openwrt.git, branch main:
https://git.openwrt.org/d2beb6bdc43f5a6f0b33932dbff673c5eb3edd8c

commit d2beb6bdc43f5a6f0b33932dbff673c5eb3edd8c
Author: Sven Eckelmann <sven at narfation.org>
AuthorDate: Wed Aug 20 05:19:31 2025 +0200

    realtek: rtl931x: Fix unsafe MAC_L2_GLOBAL_CTRL2 access
    
    Registers must not be accessed in parallel by multiple drivers.
    Read-modify-write operations are not atomic, and the result of parallel
    access is undefined.
    
    The MAC_L2_GLOBAL_CTRL2 register is essentially a pin configuration
    register and is represented by a pinmux node in the devicetree.  Operations
    on this register by the realtek,rtl838x-eth driver must therefore also be
    reflected in the devicetree.
    
    Since the MDIO sets used are board-specific, the pins must be enabled in
    the board’s devicetree.  This can be achieved using the pinctrl properties
    for the realtek,rtl83xx-switch.
    
        &switch0 {
            pinctrl-names = "default";
            pinctrl-0 = <&pinmux_enable_mdc_mdio_0>,
                        <&pinmux_enable_mdc_mdio_1>;
            ....
        };
    
    Signed-off-by: Sven Eckelmann <sven at narfation.org>
    Link: https://github.com/openwrt/openwrt/pull/19815
    Signed-off-by: Robert Marko <robimarko at gmail.com>
---
 target/linux/realtek/dts/rtl931x.dtsi              | 24 ++++++++++++++++++++++
 .../files-6.12/drivers/net/ethernet/rtl838x_eth.c  | 10 ---------
 2 files changed, 24 insertions(+), 10 deletions(-)

diff --git a/target/linux/realtek/dts/rtl931x.dtsi b/target/linux/realtek/dts/rtl931x.dtsi
index 462c3ea9b0..c048485c1b 100644
--- a/target/linux/realtek/dts/rtl931x.dtsi
+++ b/target/linux/realtek/dts/rtl931x.dtsi
@@ -240,6 +240,22 @@
 			pinctrl-single,bits = <0x0 0x10000 0x10000>;
 		};
 
+		pinmux_enable_mdc_mdio_3: enable-mdc-mdio-3 {
+			pinctrl-single,bits = <0x0 0x1000 0x1000>;
+		};
+
+		pinmux_enable_mdc_mdio_2: enable-mdc-mdio-2 {
+			pinctrl-single,bits = <0x0 0x800 0x800>;
+		};
+
+		pinmux_enable_mdc_mdio_1: enable-mdc-mdio-1 {
+			pinctrl-single,bits = <0x0 0x400 0x400>;
+		};
+
+		pinmux_enable_mdc_mdio_0: enable-mdc-mdio-0 {
+			pinctrl-single,bits = <0x0 0x200 0x200>;
+		};
+
 		/* Enable GPIO6 and GPIO7, possibly unknown others */
 		pinmux_disable_jtag: disable_jtag {
 			pinctrl-single,bits = <0x0 0x0 0x8000>;
@@ -249,6 +265,10 @@
 		pinmux_disable_sys_led: disable_sys_led {
 			pinctrl-single,bits = <0x0 0x0 0x100>;
 		};
+
+		pinmux_disable_ext_cpu: disable-ext-cpu {
+			pinctrl-single,bits = <0x0 0x0 0x4>;
+		};
 	};
 
 	pinmux at 1b0007d4 {
@@ -273,6 +293,10 @@
 		#interrupt-cells = <3>;
 		interrupts = <GIC_SHARED 16 IRQ_TYPE_LEVEL_HIGH>;
 		phy-mode = "internal";
+
+		pinctrl-0 = <&pinmux_disable_ext_cpu>;
+		pinctrl-names = "default";
+
 		fixed-link {
 			speed = <1000>;
 			full-duplex;
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 0d3fc91ea2..44f0fe5357 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
@@ -913,9 +913,6 @@ static int rtl838x_eth_open(struct net_device *ndev)
 		/* Trap MLD and IGMP messages to CPU_PORT */
 		sw_w32((0x2 << 3) | 0x2,  RTL931X_VLAN_APP_PKT_CTRL);
 
-		/* Disable External CPU access to switch, clear EXT_CPU_EN */
-		sw_w32_mask(BIT(2), 0, RTL931X_MAC_L2_GLOBAL_CTRL2);
-
 		/* Set PCIE_PWR_DOWN */
 		sw_w32_mask(0, BIT(1), RTL931X_PS_SOC_CTRL);
 		break;
@@ -2972,7 +2969,6 @@ static int rtmdio_930x_reset(struct mii_bus *bus)
 static int rtmdio_931x_reset(struct mii_bus *bus)
 {
 	struct rtmdio_bus_priv *priv = bus->priv;
-	bool mdc_on[RTMDIO_MAX_SMI_BUS] = { 0 };
 	u32 poll_sel[4] = { 0 };
 	u32 poll_ctrl = 0;
 	u32 c45_mask = 0;
@@ -2995,7 +2991,6 @@ static int rtmdio_931x_reset(struct mii_bus *bus)
 		pos = (i * 2) % 32;
 		poll_sel[i / 16] |= priv->smi_bus[i] << pos;
 		poll_ctrl |= BIT(20 + priv->smi_bus[i]);
-		mdc_on[priv->smi_bus[i]] = true;
 	}
 
 	/* Configure which SMI bus is behind which port number */
@@ -3005,18 +3000,13 @@ static int rtmdio_931x_reset(struct mii_bus *bus)
 	}
 
 	/* Configure which SMI busses */
-	pr_info("%s: WAS RTL931X_MAC_L2_GLOBAL_CTRL2 %08x\n", __func__, sw_r32(RTL931X_MAC_L2_GLOBAL_CTRL2));
 	pr_info("c45_mask: %08x, RTL931X_SMI_GLB_CTRL0 was %X", c45_mask, sw_r32(RTL931X_SMI_GLB_CTRL0));
 	for (int i = 0; i < RTMDIO_MAX_SMI_BUS; i++) {
 		/* bus is polled in c45 */
 		if (priv->smi_bus_isc45[i])
 			c45_mask |= 0x2 << (i * 2);  /* Std. C45, non-standard is 0x3 */
-		/* Enable bus access via MDC */
-		if (mdc_on[i])
-			sw_w32_mask(0, BIT(9 + i), RTL931X_MAC_L2_GLOBAL_CTRL2);
 	}
 
-	pr_info("%s: RTL931X_MAC_L2_GLOBAL_CTRL2 %08x\n", __func__, sw_r32(RTL931X_MAC_L2_GLOBAL_CTRL2));
 	pr_info("c45_mask: %08x, RTL931X_SMI_GLB_CTRL0 was %X", c45_mask, sw_r32(RTL931X_SMI_GLB_CTRL0));
 
 	/* We have a 10G PHY enable polling




More information about the lede-commits mailing list