]> git.ipfire.org Git - thirdparty/openwrt.git/commitdiff
realtek: pcs: rtl930x: fix 10g RX idle waiting
authorJonas Jelonek <jelonek.jonas@gmail.com>
Mon, 16 Mar 2026 12:10:14 +0000 (13:10 +0100)
committerRobert Marko <robimarko@gmail.com>
Sat, 21 Mar 2026 22:06:10 +0000 (23:06 +0100)
Our implementation waiting for RX idle signal of a 10G SerDes deviates
from what the SDK does. While we timeout after 100 reads and thus cannot
really control the real time, the SDK times out after 10ms. Adjust that
accordingly by switching the timeout to ktime_* functions with a 10ms
timeout as per the SDK.

While at it, improve the overall style of the function a bit.

Suggested-by: Markus Stockhausen <markus.stockhausen@gmx.de>
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/22450
Signed-off-by: Robert Marko <robimarko@gmail.com>
target/linux/realtek/files-6.12/drivers/net/pcs/pcs-rtl-otto.c

index 151cc650bf68a0298b4b4560af724c630bb81fe0..98a09eaa1c208795cc37e91fc18ae5d047501c24 100644 (file)
@@ -2664,26 +2664,27 @@ static void rtpcs_930x_phy_enable_10g_1g(struct rtpcs_serdes *sds)
 static int rtpcs_930x_sds_10g_idle(struct rtpcs_serdes *sds)
 {
        struct rtpcs_serdes *even_sds = rtpcs_sds_get_even(sds);
-       bool busy;
-       int i = 0;
+       ktime_t timeout;
+       int bit, busy;
+
+       bit = (sds == even_sds) ? 0 : 1;
+       timeout = ktime_add_us(ktime_get(), 10000); /* timeout after 10 msecs */
 
        do {
-               if (sds == even_sds) {
-                       rtpcs_sds_write_bits(sds, 0x1f, 0x2, 15, 0, 53);
-                       busy = !!rtpcs_sds_read_bits(sds, 0x1f, 0x14, 0, 0);
-               } else {
-                       rtpcs_sds_write_bits(even_sds, 0x1f, 0x2, 15, 0, 53);
-                       busy = !!rtpcs_sds_read_bits(even_sds, 0x1f, 0x14, 1, 1);
-               }
-               i++;
-       } while (busy && i < 100);
+               rtpcs_sds_write(even_sds, 0x1f, 0x2, 53);
+               busy = rtpcs_sds_read_bits(even_sds, 0x1f, 0x14, bit, bit);
+               if (busy < 0)
+                       return busy;
 
-       if (i < 100)
-               return 0;
+               if (!busy)
+                       return 0;
+
+               usleep_range(100, 200); /* wait ~100 usecs before retry */
+       } while (ktime_before(ktime_get(), timeout));
 
-       pr_warn("%s WARNING: Waiting for RX idle timed out, SDS %d\n",
+       pr_warn("%s: WARNING Waiting for RX idle timed out, SDS %d\n",
                __func__, sds->id);
-       return -EIO;
+       return -ETIMEDOUT;
 }
 
 static int rtpcs_930x_sds_set_polarity(struct rtpcs_serdes *sds,