[openwrt/openwrt] realtek: pcs: revive dead ports after RTL8382M start

LEDE Commits lede-commits at lists.infradead.org
Thu Feb 12 07:58:53 PST 2026


robimarko pushed a commit to openwrt/openwrt.git, branch main:
https://git.openwrt.org/0839c5c9f21d6d0fe5c8c1a764371a5b1a3637ff

commit 0839c5c9f21d6d0fe5c8c1a764371a5b1a3637ff
Author: Markus Stockhausen <markus.stockhausen at gmx.de>
AuthorDate: Wed Feb 11 16:20:32 2026 +0100

    realtek: pcs: revive dead ports after RTL8382M start
    
    SerDes attached ports that are connected during switch
    boot might not be able to transmit any data after SerDes
    setup. Especially ports that passed traffic before (e.g.
    for tftp initramfs boot) seem to be affected. Ports that
    are connected later do not show this issue.
    
    It turns out that the old SerDes setup never really worked
    on RTL8382 and the pcs refactoring (with dynamic SerDes
    start and stop) totally changed the order of network bringup
    in contrast to Realtek SDK.
    
    Fix this by restaring the switch queue whenever a SerDes
    goes up for the first time.
    
    Fixes: e956adf ("realtek: rtl838x: setup SDS in PCS driver")
    Signed-off-by: Markus Stockhausen <markus.stockhausen at gmx.de>
    Link: https://github.com/openwrt/openwrt/pull/21956
    Signed-off-by: Robert Marko <robimarko at gmail.com>
---
 .../files-6.12/drivers/net/pcs/pcs-rtl-otto.c        | 20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/target/linux/realtek/files-6.12/drivers/net/pcs/pcs-rtl-otto.c b/target/linux/realtek/files-6.12/drivers/net/pcs/pcs-rtl-otto.c
index 98d099d1bc..713abf68b9 100644
--- a/target/linux/realtek/files-6.12/drivers/net/pcs/pcs-rtl-otto.c
+++ b/target/linux/realtek/files-6.12/drivers/net/pcs/pcs-rtl-otto.c
@@ -179,6 +179,7 @@ struct rtpcs_serdes {
 	enum rtpcs_sds_mode hw_mode;
 	u8 id;
 	u8 num_of_links;
+	bool first_start;
 
 	bool rx_pol_inv;
 	bool tx_pol_inv;
@@ -766,6 +767,20 @@ static int rtpcs_838x_setup_serdes(struct rtpcs_serdes *sds,
 	rtpcs_sds_write(sds, 0, 3, 0x7106);
 
 	rtpcs_838x_sds_power(sds, true);
+
+	/*
+	 * Run a switch queue reset after the first start of a SerDes. This recovers ports that
+	 * were already connected during boot and will not pass traffic. Sometimes the bug can
+	 * be seen in registers INGR_DBG_REG0-INGR_DBG_REG2 but this is quite erratic. The SDK
+	 * seems to have no issues because it starts all SerDes then PHYs and runs a queue reset
+	 * finally during NIC start.
+	 *
+	 * Of course this is totally wrong here and should be part of the DSA driver. But
+	 * implementing it over there requires more tricks than this (e.g. delayed work).
+	 */
+	if (sds->first_start)
+		regmap_write(sds->ctrl->map, RTPCS_838X_RST_GLB_CTRL_0, 0x4);
+
 	return 0;
 }
 
@@ -3779,6 +3794,8 @@ static int rtpcs_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
 		ret = ctrl->cfg->setup_serdes(sds, hw_mode);
 		if (ret < 0)
 			goto out;
+
+		sds->first_start = false;
 	} else {
 		dev_dbg(ctrl->dev, "SerDes %u already in mode %s, no change\n",
 			 sds->id, phy_modes(interface));
@@ -3915,9 +3932,10 @@ static int rtpcs_probe(struct platform_device *pdev)
 
 	for (i = 0; i < ctrl->cfg->serdes_count; i++) {
 		sds = &ctrl->serdes[i];
+
 		sds->ctrl = ctrl;
+		sds->first_start = true;
 		sds->id = i;
-
 		sds->ops = ctrl->cfg->sds_ops;
 	}
 




More information about the lede-commits mailing list