From 913daed7916c96db2a2ea99b1e2fad624de511ef Mon Sep 17 00:00:00 2001 From: Jonas Jelonek Date: Tue, 13 Oct 2026 19:28:39 +0000 Subject: [PATCH] realtek: pcs: rtl930x: refine RX calibration diagnostics Add debug-level tracing for calibration requests, readiness polling, attempts and results, retries, coefficient refinement and mode-change invalidation. Record symbol-error samples, attempt duration and mutex wait time to diagnose acquisition and scheduling issues. Demote per-attempt link and error-count failures to debug level since later attempts can recover. Include measured counts, thresholds, mode and attempt context, sharing named XSGMII limits between checks and messages. Retain warnings for exhausted attempts and errors for failed register accesses. Assisted-By: ChatGPT (OpenAI GPT-6.1 Sol) Link: https://github.com/openwrt/openwrt/pull/25882 Signed-off-by: Jonas Jelonek --- .../files-6.18/drivers/net/pcs/pcs-rtl-otto.c | 61 ++++++++++++++++--- 1 file changed, 52 insertions(+), 9 deletions(-) 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 1eb1f98c78f..b352f932995 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 @@ -21,6 +21,8 @@ #define RTPCS_RXCAL_POLL_MS 500 #define RTPCS_RXCAL_MAX_TRIES 3 #define RTPCS_RXCAL_RETRY_MS 1000 +#define RTPCS_RXCAL_XSG_MAX_ERR_DELTA 100 +#define RTPCS_RXCAL_XSG_ERR_SATURATION 0xffff00 #define RTPCS_SPEED_10 0 #define RTPCS_SPEED_100 1 @@ -3048,23 +3050,30 @@ static int rtpcs_930x_sds_check_calibration(struct rtpcs_serdes *sds, usleep_range(1000, 2000); errors2 = rtpcs_930x_sds_sym_err_get(sds, hw_mode); + dev_dbg(sds->ctrl->dev, "SerDes %u: RX calibration symbol errors %u -> %u\n", + sds->id, errors1, errors2); + if (!rtpcs_930x_sds_rx_link_up(sds)) { - dev_warn(sds->ctrl->dev, "SerDes %u: RX link down after calibration\n", sds->id); + dev_dbg(sds->ctrl->dev, "SerDes %u: RX link down after calibration (mode=%u, attempt=%u/%u)\n", + sds->id, hw_mode, sds->rxcal_tries, RTPCS_RXCAL_MAX_TRIES); return 1; } switch (hw_mode) { case RTPCS_SDS_MODE_XSGMII: - if ((errors2 - errors1 > 100) || (errors1 >= 0xffff00) || (errors2 >= 0xffff00)) { - dev_err(sds->ctrl->dev, "SerDes %u: XSGMII error rate too high\n", - sds->id); + if ((errors2 - errors1 > RTPCS_RXCAL_XSG_MAX_ERR_DELTA) || + (errors1 >= RTPCS_RXCAL_XSG_ERR_SATURATION) || + (errors2 >= RTPCS_RXCAL_XSG_ERR_SATURATION)) { + dev_dbg(sds->ctrl->dev, "SerDes %u: XSGMII errors %u -> %u, delta=%u (max %u), saturation=%#x\n", + sds->id, errors1, errors2, errors2 - errors1, + RTPCS_RXCAL_XSG_MAX_ERR_DELTA, RTPCS_RXCAL_XSG_ERR_SATURATION); return 1; } break; default: if (errors2 > 0) { - dev_err(sds->ctrl->dev, "SerDes %u: symbol error rate too high\n", - sds->id); + dev_dbg(sds->ctrl->dev, "SerDes %u: symbol errors %u (expected 0)\n", + sds->id, errors2); return 1; } break; @@ -3076,36 +3085,57 @@ static int rtpcs_930x_sds_check_calibration(struct rtpcs_serdes *sds, static void rtpcs_930x_rx_cali_work_handler(struct work_struct *work) { struct rtpcs_serdes *sds, *even_sds; + unsigned long lock_start, attempt_start; bool calib_failed, rxcal_ready; int latch_sts, bit, ret; sds = container_of(to_delayed_work(work), struct rtpcs_serdes, cali_work); + lock_start = jiffies; mutex_lock(&sds->ctrl->lock); - if (!sds->rxcal_pending) + dev_dbg(sds->ctrl->dev, + "SerDes %u: RX calibration worker entered, mode=%u pending=%u lock-wait=%u ms\n", + sds->id, sds->hw_mode, sds->rxcal_pending, + jiffies_to_msecs(jiffies - lock_start)); + + if (!sds->rxcal_pending) { + dev_dbg(sds->ctrl->dev, "SerDes %u: RX calibration request no longer pending\n", + sds->id); goto unlock; + } /* Select the 10G RX status readback. */ even_sds = rtpcs_sds_get_even(sds); bit = (sds == even_sds) ? 0 : 1; ret = rtpcs_sds_write_mask(even_sds, PAGE_WDIG, WDIG_REG02, RTL93XX_DBGO_SEL_0, RTL930X_DBGO_SEL_0_RX_STATUS); - if (ret < 0) + if (ret < 0) { + dev_err(sds->ctrl->dev, "SerDes %u: RX calibration status selection failed: %d\n", + sds->id, ret); goto terminate; + } ret = rtpcs_sds_read_bits(even_sds, PAGE_WDIG, WDIG_REG20, bit, bit); - if (ret < 0) + if (ret < 0) { + dev_err(sds->ctrl->dev, "SerDes %u: RX calibration idle-status read failed: %d\n", + sds->id, ret); goto terminate; + } /* The SDK permits calibration when RX_IDLE is deasserted. */ rxcal_ready = !ret; if (!rxcal_ready) { + dev_dbg(sds->ctrl->dev, "SerDes %u: RX not ready for calibration, checking again in %u ms\n", + sds->id, RTPCS_RXCAL_POLL_MS); schedule_delayed_work(&sds->cali_work, msecs_to_jiffies(RTPCS_RXCAL_POLL_MS)); goto unlock; } + attempt_start = jiffies; sds->rxcal_tries++; + dev_dbg(sds->ctrl->dev, "SerDes %u: RX calibration attempt %u/%u\n", + sds->id, sds->rxcal_tries, RTPCS_RXCAL_MAX_TRIES); rtpcs_930x_sds_rxcal_init(sds, sds->hw_mode); rtpcs_930x_sds_rxcal_fgcal(sds); rtpcs_930x_sds_rxcal_vth_tap0_adapt_lock(sds); @@ -3125,6 +3155,8 @@ static void rtpcs_930x_rx_cali_work_handler(struct work_struct *work) goto terminate; } if (latch_sts) { + dev_dbg(sds->ctrl->dev, "SerDes %u: RX calibration repeating VTH/TAP0 adaptation\n", + sds->id); rtpcs_930x_sds_rxeq_dfe_disable(sds); rtpcs_930x_sds_rxcal_vth_tap0_adapt_lock(sds); rtpcs_930x_sds_rxeq_dfe_taps_adapt(sds); @@ -3133,8 +3165,14 @@ static void rtpcs_930x_rx_cali_work_handler(struct work_struct *work) msleep(50); calib_failed = rtpcs_930x_sds_check_calibration(sds, sds->hw_mode); + dev_dbg(sds->ctrl->dev, "SerDes %u: RX calibration attempt %u/%u %s after %u ms\n", + sds->id, sds->rxcal_tries, RTPCS_RXCAL_MAX_TRIES, + calib_failed ? "failed" : "passed", + jiffies_to_msecs(jiffies - attempt_start)); if (calib_failed) { if (sds->rxcal_tries < RTPCS_RXCAL_MAX_TRIES) { + dev_dbg(sds->ctrl->dev, "SerDes %u: retrying RX calibration in %u ms\n", + sds->id, RTPCS_RXCAL_RETRY_MS); schedule_delayed_work(&sds->cali_work, msecs_to_jiffies(RTPCS_RXCAL_RETRY_MS)); goto unlock; @@ -3432,6 +3470,8 @@ static int rtpcs_930x_sds_post_config(struct rtpcs_serdes *sds, enum rtpcs_sds_m rtpcs_930x_sds_rxcal_init(sds, hw_mode); + dev_dbg(sds->ctrl->dev, "SerDes %u: arming RX calibration for mode %u\n", + sds->id, hw_mode); sds->rxcal_tries = 0; sds->rxcal_pending = true; mod_delayed_work(system_wq, &sds->cali_work, msecs_to_jiffies(1000)); @@ -4560,6 +4600,9 @@ static int rtpcs_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, scoped_guard(mutex, &ctrl->lock) { mode_changed = sds->hw_mode != hw_mode || sds->usxgmii_submode != submode; if (mode_changed) { + if (sds->rxcal_pending) + dev_dbg(ctrl->dev, "SerDes %u: invalidating pending RX calibration for mode change\n", + sds->id); sds->rxcal_pending = false; ret = rtpcs_sds_config_polarity(sds, interface);