]> git.ipfire.org Git - thirdparty/openwrt.git/commitdiff
realtek: rtl931x: Fix unsafe MAC_L2_GLOBAL_CTRL2 access 19815/head
authorSven Eckelmann <sven@narfation.org>
Wed, 20 Aug 2025 03:19:31 +0000 (05:19 +0200)
committerRobert Marko <robimarko@gmail.com>
Wed, 3 Sep 2025 07:54:51 +0000 (09:54 +0200)
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@narfation.org>
Link: https://github.com/openwrt/openwrt/pull/19815
Signed-off-by: Robert Marko <robimarko@gmail.com>
target/linux/realtek/dts/rtl931x.dtsi
target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.c

index 462c3ea9b0f05f63bcb3e6c216918631b1222e01..c048485c1bc5f693807d3977e624fbca5ae9b971 100644 (file)
                        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>;
                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 {
                #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;
index 0d3fc91ea26de36a0965076713ac75d6fc838313..44f0fe5357a5b34f77d4019b5752ab11ecef4b9b 100644 (file)
@@ -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