realtek: pcs: rtl931x: gate symErr success on actual link status
symErr reads 0 both when the link is clean and when there's no signal at all to decode errors from - the counter only increments when the PCS is actively decoding something and finds a mismatch, so a dead link and a healthy one are indistinguishable from symErr alone. Confirmed on hardware: symErr read 0x0 while the port had no link. Add rtpcs_931x_sds_10gr_link_up(), reading the same status bit as the vendor SDK's _phy_rtl9310_linkSts_get() default case, and require it alongside a low symErr count before declaring a calibration check successful. A link that isn't actually up yet now keeps the retry loop going instead of being misread as a clean, working link. Also observed on hardware: the retry budget sometimes runs out while symErr is still nonzero, but the link comes up and works fine anyway - the count just hasn't fully settled within the budget. Since that's not an actual problem, keep the final message at dev_dbg when link_up is true; only warn when the link genuinely never came up. Link: https://github.com/openwrt/openwrt/pull/24542 Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
This commit is contained in:
parent
7ed1c1d472
commit
4e7a9a7969
1 changed files with 21 additions and 5 deletions
|
|
@ -3089,6 +3089,11 @@ static int rtpcs_931x_sds_fiber_get_symerr(struct rtpcs_serdes *sds,
|
|||
return symerr;
|
||||
}
|
||||
|
||||
static bool rtpcs_931x_sds_10gr_link_up(struct rtpcs_serdes *sds)
|
||||
{
|
||||
return rtpcs_sds_read_bits(sds, PAGE_TGR_STD_1, 0x0, 12, 12) == 1;
|
||||
}
|
||||
|
||||
static void rtpcs_931x_sds_clear_symerr(struct rtpcs_serdes *sds,
|
||||
enum rtpcs_sds_mode hw_mode)
|
||||
{
|
||||
|
|
@ -3438,6 +3443,7 @@ static void rtpcs_931x_sds_rxcal_fiber_adapt(struct rtpcs_serdes *sds)
|
|||
unsigned int vth_p = 0, vth_n = 0, sum_p = 0, sum_n = 0;
|
||||
struct device *dev = sds->ctrl->dev;
|
||||
int i, samples = 0, symerr = -1;
|
||||
bool link_up = false;
|
||||
|
||||
dev_dbg(dev, "SerDes %u fiber RX calibration...\n", sds->id);
|
||||
/* per-port calibration offset in the SDK, kept 0 here */
|
||||
|
|
@ -3488,18 +3494,28 @@ static void rtpcs_931x_sds_rxcal_fiber_adapt(struct rtpcs_serdes *sds)
|
|||
rtpcs_931x_sds_clear_symerr(sds, RTPCS_SDS_MODE_10GBASER);
|
||||
msleep(300);
|
||||
symerr = rtpcs_931x_sds_fiber_get_symerr(sds, RTPCS_SDS_MODE_10GBASER);
|
||||
link_up = rtpcs_931x_sds_10gr_link_up(sds);
|
||||
dev_dbg(dev, "SerDes %u symErr check %d: linkUp=%d symErr=0x%x\n", sds->id,
|
||||
i + 1, link_up, symerr);
|
||||
|
||||
dev_dbg(dev, "SerDes %u symErr check %d: 0x%x\n", sds->id, i + 1, symerr);
|
||||
|
||||
if (symerr >= 0 && symerr <= 5) {
|
||||
/*
|
||||
* symErr also reads 0 with no signal at all, not just a clean
|
||||
* link - don't trust it without link_up confirming there's
|
||||
* actually something being decoded.
|
||||
*/
|
||||
if (link_up && symerr >= 0 && symerr <= 5) {
|
||||
dev_dbg(dev, "SerDes %u fiber RX calibration OK (check %d)\n",
|
||||
sds->id, i + 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
dev_warn(dev, "SerDes %u fiber RX calibration failed after %d symErr checks\n",
|
||||
sds->id, i);
|
||||
if (link_up)
|
||||
dev_dbg(dev, "SerDes %u fiber RX calibration: symErr still 0x%x after %d checks, link up anyway\n",
|
||||
sds->id, symerr, i);
|
||||
else
|
||||
dev_warn(dev, "SerDes %u fiber RX calibration failed after %d symErr checks\n",
|
||||
sds->id, i);
|
||||
}
|
||||
|
||||
static int rtpcs_931x_sds_get_pll_select(struct rtpcs_serdes *sds, enum rtpcs_sds_pll_type *pll)
|
||||
|
|
|
|||
Loading…
Reference in a new issue