From d2beb6bdc43f5a6f0b33932dbff673c5eb3edd8c Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Wed, 20 Aug 2025 05:19:31 +0200 Subject: [PATCH] realtek: rtl931x: Fix unsafe MAC_L2_GLOBAL_CTRL2 access MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 Link: https://github.com/openwrt/openwrt/pull/19815 Signed-off-by: Robert Marko --- target/linux/realtek/dts/rtl931x.dtsi | 24 +++++++++++++++++++ .../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 462c3ea9b0f..c048485c1bc 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@1b0007d4 { @@ -273,6 +293,10 @@ #interrupt-cells = <3>; interrupts = ; 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 0d3fc91ea26..44f0fe5357a 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 -- 2.47.3