[PATCH net] net: stmmac: propagate PTP addend and system time programming errors
Lorenzo Bianconi
lorenzo.bianconi at oss.qualcomm.com
Sun Sep 20 06:00:02 PDT 2026
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 <lorenzo.bianconi at oss.qualcomm.com>
---
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 <lorenzo.bianconi at oss.qualcomm.com>
More information about the linux-arm-kernel
mailing list