summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSven Eckelmann2025-08-20 03:19:31 +0000
committerRobert Marko2025-09-03 07:54:51 +0000
commitd2beb6bdc43f5a6f0b33932dbff673c5eb3edd8c (patch)
tree7cf3a3c12ba2c2cd1ab85066c24f6c29695cbee2
parentea5a749311a5c1a5dce85915e0039b1db93f703e (diff)
downloadopenwrt-d2beb6bdc43f5a6f0b33932dbff673c5eb3edd8c.tar.gz
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@narfation.org> Link: https://github.com/openwrt/openwrt/pull/19815 Signed-off-by: Robert Marko <robimarko@gmail.com>
-rw-r--r--target/linux/realtek/dts/rtl931x.dtsi24
-rw-r--r--target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.c10
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@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