summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarkus Stockhausen2026-02-11 15:20:32 +0000
committerRobert Marko2026-02-12 15:58:46 +0000
commit0839c5c9f21d6d0fe5c8c1a764371a5b1a3637ff (patch)
tree1b4a5b609a94c9e74b603da1ec690c80aaea766b
parent8bf37836d62f001562c78238f41f4d05a31d606a (diff)
downloadopenwrt-0839c5c9f21d6d0fe5c8c1a764371a5b1a3637ff.tar.gz
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@gmx.de> Link: https://github.com/openwrt/openwrt/pull/21956 Signed-off-by: Robert Marko <robimarko@gmail.com>
-rw-r--r--target/linux/realtek/files-6.12/drivers/net/pcs/pcs-rtl-otto.c20
1 files changed, 19 insertions, 1 deletions
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;
}