]> git.ipfire.org Git - thirdparty/openwrt.git/commitdiff
realtek: pcs: revive dead ports after RTL8382M start 22087/head
authorMarkus Stockhausen <markus.stockhausen@gmx.de>
Wed, 11 Feb 2026 15:20:32 +0000 (16:20 +0100)
committerHauke Mehrtens <hauke@hauke-m.de>
Sun, 1 Mar 2026 01:02:29 +0000 (02:02 +0100)
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@gmx.de>
Link: https://github.com/openwrt/openwrt/pull/21956
Signed-off-by: Robert Marko <robimarko@gmail.com>
(cherry picked from commit 0839c5c9f21d6d0fe5c8c1a764371a5b1a3637ff)
Manually resolved merge conflicts.
Signed-off-by: Goetz Goerisch <ggoerisch@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/22087
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
target/linux/realtek/files-6.12/drivers/net/pcs/pcs-rtl-otto.c

index 9147ba1572c1014b24a882a933d351be87022df1..adbf43db3f5c9513db0b87124897bcecdd18fefe 100644 (file)
@@ -134,6 +134,7 @@ struct rtpcs_serdes {
        struct rtpcs_ctrl *ctrl;
        u8 id;
        enum rtpcs_sds_mode mode;
+       bool first_start;
 
        bool rx_pol_inv;
        bool tx_pol_inv;
@@ -557,6 +558,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;
 }
 
@@ -2938,6 +2953,8 @@ static int rtpcs_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
                ret = ctrl->cfg->setup_serdes(link->sds, interface);
                if (ret < 0)
                        goto out;
+
+               link->sds->first_start = false;
        }
 
        if (ctrl->cfg->set_autoneg) {
@@ -3070,7 +3087,9 @@ 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;
        }