[PATCH net] net: stmmac: propagate PTP addend and system time programming errors
From: Lorenzo Bianconi <hidden>
Date: 2026-09-20 13:00:39
Also in:
linux-arm-kernel
Subsystem:
networking drivers, stmmac ethernet driver, the rest · Maintainers:
Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Maxime Chevallier, Linus Torvalds
stmmac_update_subsecond_increment() ignores the error returned by
stmmac_config_addend(), and stmmac_init_tstamp_counter() discards the
addend and system time programming errors, always returning success. A
failure to program the addend (PTP_TCR_TSADDREG) or to initialize the
system time counter (PTP_TCR_TSINIT) is therefore silently swallowed,
leaving the hardware timestamp counter in a non-running or partially
configured state while the driver keeps operating as if timestamping
were up. This matters for TAPRIO/EST offloading, which derives the gate
base time from the hardware timestamp counter.
Return error codes from stmmac_update_subsecond_increment(),
stmmac_init_tstamp_counter() and stmmac_dl_ts_coarse_set() instead of
silently returning success.
Fixes: cc4c9001ce31 ("net: stmmac: Switch stmmac_hwtimestamp to generic HW Interface Helpers")
Signed-off-by: Lorenzo Bianconi <redacted>
---
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 89 ++++++++++++++++++-----
1 file changed, 69 insertions(+), 20 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 1fb5f804ea23..52587ecb1a54 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c@@ -601,31 +601,63 @@ static void stmmac_get_rx_hwtstamp(struct stmmac_priv *priv, struct dma_desc *p, } } -static void stmmac_update_subsecond_increment(struct stmmac_priv *priv) +static void stmmac_restore_subsecond_increment(struct stmmac_priv *priv, + u32 default_addend, + u32 systime_flags) { bool xmac = dwmac_is_xmac(priv->plat->core_type); - u32 sec_inc = 0; + u32 sec_inc; + + stmmac_config_addend(priv, priv->ptpaddr, default_addend); + stmmac_config_hw_tstamping(priv, priv->ptpaddr, systime_flags); + stmmac_config_sub_second_increment(priv, priv->ptpaddr, + priv->plat->clk_ptp_rate, + xmac, &sec_inc); + priv->default_addend = default_addend; + priv->sub_second_inc = sec_inc; +} + +static int stmmac_update_subsecond_increment(struct stmmac_priv *priv, + u32 systime_flags) +{ + bool xmac = dwmac_is_xmac(priv->plat->core_type); + u32 sec_inc = 0, val; u64 temp = 0; + int ret; - stmmac_config_hw_tstamping(priv, priv->ptpaddr, priv->systime_flags); + stmmac_config_hw_tstamping(priv, priv->ptpaddr, systime_flags); /* program Sub Second Increment reg */ stmmac_config_sub_second_increment(priv, priv->ptpaddr, priv->plat->clk_ptp_rate, xmac, &sec_inc); - temp = div_u64(1000000000ULL, sec_inc); - - /* Store sub second increment for later use */ - priv->sub_second_inc = sec_inc; + if (!sec_inc) { + ret = -EINVAL; + goto error; + } /* calculate default added value: * formula is : * addend = (2^32)/freq_div_ratio; * where, freq_div_ratio = 1e9ns/sec_inc */ + temp = div_u64(1000000000ULL, sec_inc); temp = (u64)(temp << 32); - priv->default_addend = div_u64(temp, priv->plat->clk_ptp_rate); - stmmac_config_addend(priv, priv->ptpaddr, priv->default_addend); + val = div_u64(temp, priv->plat->clk_ptp_rate); + + ret = stmmac_config_addend(priv, priv->ptpaddr, val); + if (ret) + goto error; + + priv->sub_second_inc = sec_inc; + priv->default_addend = val; + + return 0; +error: + /* Restore previous configuration */ + stmmac_restore_subsecond_increment(priv, priv->default_addend, + priv->systime_flags); + return ret; } /**
@@ -864,25 +896,37 @@ static int stmmac_hwtstamp_get(struct net_device *dev, static int stmmac_init_tstamp_counter(struct stmmac_priv *priv, u32 systime_flags) { + u32 default_addend = priv->default_addend; struct timespec64 now; + int ret; if (!priv->plat->clk_ptp_rate) { netdev_err(priv->dev, "Invalid PTP clock rate"); return -EINVAL; } - stmmac_config_hw_tstamping(priv, priv->ptpaddr, systime_flags); - priv->systime_flags = systime_flags; - - stmmac_update_subsecond_increment(priv); + ret = stmmac_update_subsecond_increment(priv, systime_flags); + if (ret) + return ret; /* initialize system time */ ktime_get_real_ts64(&now); /* lower 32 bits of tv_sec are safe until y2106 */ - stmmac_init_systime(priv, priv->ptpaddr, (u32)now.tv_sec, now.tv_nsec); + ret = stmmac_init_systime(priv, priv->ptpaddr, (u32)now.tv_sec, + now.tv_nsec); + if (ret) + goto error; + + priv->systime_flags = systime_flags; return 0; +error: + /* Restore previous configuration */ + stmmac_restore_subsecond_increment(priv, default_addend, + priv->systime_flags); + + return ret; } /**
@@ -7693,18 +7737,23 @@ static int stmmac_dl_ts_coarse_set(struct devlink *dl, u32 id, { struct stmmac_devlink_priv *dl_priv = devlink_priv(dl); struct stmmac_priv *priv = dl_priv->stmmac_priv; + u32 systime_flags = priv->systime_flags; + int ret; - priv->tsfupdt_coarse = ctx->val.vbool; - - if (priv->tsfupdt_coarse) - priv->systime_flags &= ~PTP_TCR_TSCFUPDT; + if (ctx->val.vbool) + systime_flags &= ~PTP_TCR_TSCFUPDT; else - priv->systime_flags |= PTP_TCR_TSCFUPDT; + systime_flags |= PTP_TCR_TSCFUPDT; /* In Coarse mode, we can use a smaller subsecond increment, let's * reconfigure the systime, subsecond increment and addend. */ - stmmac_update_subsecond_increment(priv); + ret = stmmac_update_subsecond_increment(priv, systime_flags); + if (ret) + return ret; + + priv->tsfupdt_coarse = ctx->val.vbool; + priv->systime_flags = systime_flags; return 0; }
--- base-commit: 1e24c4f2ee44be0eee94092b5d13cbdb4bdf0d60 change-id: 20260920-stmmac-ptp-added-systime-error-bc9566262f2f Best regards, -- Lorenzo Bianconi [off-list ref]