From 383c4469e4fdaa365cbf3a1e02bde2b50a229b48 Mon Sep 17 00:00:00 2001 From: Jonas Jelonek Date: Wed, 20 May 2026 21:43:33 +0000 Subject: [PATCH] realtek: pcs: rtl930x: force IP mode OFF in deactivate, unforce for MAC modes Make deactivate fully restore the SerDes to an inert state at both the MAC and IP layers. Previously deactivate only zeroed the MAC mode via set_mode(OFF), which on the default branch only writes the MAC mode register and leaves the IP mode register untouched. The IP mode register then retained whatever the previous bring-up left behind (force=1 with a stale mode value, or force=0 from boot defaults), making "deactivate" not fully deactivate the SerDes. Replace the set_mode(OFF) call with explicit set_mac_mode(OFF) plus set_ip_mode(OFF). The latter writes force=1 with mode=OFF, pinning the IP block to OFF until a subsequent bring-up takes a defined action. This forced-OFF state would break MAC-driven modes (USXGMII / QSGMII / XSGMII), which set only the MAC mode register and rely on the IP block following along. To compensate, add an explicit unforce of the IP mode force-bit (page 0x1f reg 0x09 bit 6) at the start of the MAC-mode branch of rtpcs_930x_sds_set_mode. IP-mode bring-up via apply_ip_mode is unaffected -- it re-asserts force=1 with the target mode value, which overrides the deactivate force-OFF. Net result: deactivate fully and explicitly deactivates the SerDes; each set_mode path takes its own responsibility for the IP mode register state. The previous asymmetric behaviour (set_mode default branch silently not touching the IP register) is now explicit code rather than an implicit accident-of-dispatch. Verified on RTL930x hardware: SGMII, 2500BASE-X, 10GBASE-R, USXGMII-QX and XSGMII all bring up correctly with link, traffic and iperf3 as expected. Link: https://github.com/openwrt/openwrt/pull/23513 Signed-off-by: Jonas Jelonek --- .../files-6.18/drivers/net/pcs/pcs-rtl-otto.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c index 99a9ee5ec02..7c70a0c0864 100644 --- a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c +++ b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c @@ -1852,6 +1852,14 @@ static int rtpcs_930x_sds_set_mode(struct rtpcs_serdes *sds, enum rtpcs_sds_mode break; } + /* + * MAC-driven modes: release the IP mode force-lock so the MAC side + * takes over. deactivate forces IP=OFF; this undoes that. + */ + ret = rtpcs_sds_write_bits(sds, 0x1f, 0x09, 6, 6, 0); + if (ret) + return ret; + ret = rtpcs_93xx_sds_set_mac_mode(sds, hw_mode); if (ret) return ret; @@ -1866,7 +1874,12 @@ static int rtpcs_930x_sds_deactivate(struct rtpcs_serdes *sds) /* Power down the SerDes core analog block. */ rtpcs_930x_sds_set_power(sds, false); - ret = rtpcs_930x_sds_set_mode(sds, RTPCS_SDS_MODE_OFF); + /* Force MAC and IP mode registers to OFF, leaving the SerDes inert. */ + ret = rtpcs_93xx_sds_set_mac_mode(sds, RTPCS_SDS_MODE_OFF); + if (ret) + return ret; + + ret = rtpcs_93xx_sds_set_ip_mode(sds, RTPCS_SDS_MODE_OFF); if (ret) return ret; -- 2.47.3