realtek: rtl931x: Fix unsafe MAC_L2_GLOBAL_CTRL2 access
Some checks are pending
Build Kernel / Build all affected Kernels (push) Waiting to run

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>
This commit is contained in:
Sven Eckelmann 2025-08-20 05:19:31 +02:00 committed by Robert Marko
parent ea5a749311
commit d2beb6bdc4
2 changed files with 24 additions and 10 deletions

View file

@ -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 = <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;

View 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