From d7804253678eb18d2be950e0542364b50be096a9 Mon Sep 17 00:00:00 2001 From: James Clark Date: Thu, 8 Oct 2026 17:38:09 +0700 Subject: [PATCH] net: stmmac: ptp: switch to gettimex64() interface The stmmac PTP support currently implements the gettime64 callback to retrieve the hardware clock time. Update the implementation to provide the gettimex64 callback instead, adding support for the PTP_SYS_OFFSET_EXTENDED ioctl. The system clock readings are taken around the read of the nanoseconds register in get_systime(), so get_systime() gains a ptp_system_timestamp argument. Reviewed-by: Nicolai Buchwitz Assisted-by: LLM Signed-off-by: James Clark Reviewed-by: Vadim Fedorenko Link: https://patch.msgid.link/20261008103809.1848255-1-jjc@jclark.com Signed-off-by: Paolo Abeni --- drivers/net/ethernet/stmicro/stmmac/hwif.h | 5 ++++- .../ethernet/stmicro/stmmac/stmmac_hwtstamp.c | 7 +++++-- .../net/ethernet/stmicro/stmmac/stmmac_ptp.c | 21 ++++++++++--------- .../stmicro/stmmac/stmmac_selftests.c | 4 ++-- .../net/ethernet/stmicro/stmmac/stmmac_tc.c | 3 ++- 5 files changed, 24 insertions(+), 16 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h index 2e63614d93a4..50b590d67d87 100644 --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h @@ -493,6 +493,8 @@ struct stmmac_ops { #define stmmac_fpe_map_preemption_class(__priv, __args...) \ stmmac_do_callback(__priv, mac, fpe_map_preemption_class, __args) +struct ptp_system_timestamp; + /* PTP and HW Timer helpers */ struct stmmac_hwtimestamp { void (*config_hw_tstamping) (void __iomem *ioaddr, u32 data); @@ -502,7 +504,8 @@ struct stmmac_hwtimestamp { int (*config_addend) (void __iomem *ioaddr, u32 addend); int (*adjust_systime) (void __iomem *ioaddr, u32 sec, u32 nsec, int add_sub, int gmac4); - void (*get_systime) (void __iomem *ioaddr, u64 *systime); + void (*get_systime)(void __iomem *ioaddr, u64 *systime, + struct ptp_system_timestamp *sts); void (*get_ptptime)(void __iomem *ioaddr, u64 *ptp_time); void (*timestamp_interrupt)(struct stmmac_priv *priv); void (*hwtstamp_correct_latency)(struct stmmac_priv *priv); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c index b9a985fa772c..870c740b4a50 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c @@ -183,7 +183,8 @@ static int adjust_systime(void __iomem *ioaddr, u32 sec, u32 nsec, 10, 100000); } -static void get_systime(void __iomem *ioaddr, u64 *systime) +static void get_systime(void __iomem *ioaddr, u64 *systime, + struct ptp_system_timestamp *sts) { u64 ns, sec0, sec1; @@ -191,8 +192,10 @@ static void get_systime(void __iomem *ioaddr, u64 *systime) sec1 = readl_relaxed(ioaddr + PTP_STSR); do { sec0 = sec1; + ptp_read_system_prets(sts); /* Get the TSSS value */ - ns = readl_relaxed(ioaddr + PTP_STNSR); + ns = readl(ioaddr + PTP_STNSR); + ptp_read_system_postts(sts); /* Get the TSS value */ sec1 = readl_relaxed(ioaddr + PTP_STSR); } while (sec0 != sec1); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c index 3bfcc9760dce..e54a3c887826 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c @@ -89,7 +89,8 @@ static int stmmac_adjust_time(struct ptp_clock_info *ptp, s64 delta) u64 cycle_time; mutex_lock(&priv->est_lock); - priv->ptp_clock_ops.gettime64(&priv->ptp_clock_ops, ¤t_time); + priv->ptp_clock_ops.gettimex64(&priv->ptp_clock_ops, + ¤t_time, NULL); current_time_ns = timespec64_to_ktime(current_time); time.tv_nsec = priv->est->btr_reserve[0]; time.tv_sec = priv->est->btr_reserve[1]; @@ -114,15 +115,15 @@ static int stmmac_adjust_time(struct ptp_clock_info *ptp, s64 delta) } /** - * stmmac_get_time - * + * stmmac_get_timex - read the PTP clock, with system timestamps if requested * @ptp: pointer to ptp_clock_info structure * @ts: pointer to hold time/result + * @sts: pointer to hold system timestamps around the read, or NULL * - * Description: this function will read the current time from the - * hardware clock and store it in @ts. + * Return: 0 */ -static int stmmac_get_time(struct ptp_clock_info *ptp, struct timespec64 *ts) +static int stmmac_get_timex(struct ptp_clock_info *ptp, struct timespec64 *ts, + struct ptp_system_timestamp *sts) { struct stmmac_priv *priv = container_of(ptp, struct stmmac_priv, ptp_clock_ops); @@ -130,7 +131,7 @@ static int stmmac_get_time(struct ptp_clock_info *ptp, struct timespec64 *ts) u64 ns = 0; read_lock_irqsave(&priv->ptp_lock, flags); - stmmac_get_systime(priv, priv->ptpaddr, &ns); + stmmac_get_systime(priv, priv->ptpaddr, &ns, sts); read_unlock_irqrestore(&priv->ptp_lock, flags); *ts = ns_to_timespec64(ns); @@ -200,7 +201,7 @@ static int stmmac_enable(struct ptp_clock_info *ptp, target_ns = cfg->start.tv_nsec + ((u64)cfg->start.tv_sec * NSEC_PER_SEC); - stmmac_get_systime(priv, priv->ptpaddr, &ns); + stmmac_get_systime(priv, priv->ptpaddr, &ns, NULL); if (ns > TIME64_MAX - PTP_SAFE_TIME_OFFSET_NS) return -EINVAL; @@ -304,7 +305,7 @@ const struct ptp_clock_info stmmac_ptp_clock_ops = { .pps = 0, .adjfine = stmmac_adjust_freq, .adjtime = stmmac_adjust_time, - .gettime64 = stmmac_get_time, + .gettimex64 = stmmac_get_timex, .settime64 = stmmac_set_time, .enable = stmmac_enable, }; @@ -321,7 +322,7 @@ const struct ptp_clock_info dwmac1000_ptp_clock_ops = { .pps = 0, .adjfine = stmmac_adjust_freq, .adjtime = stmmac_adjust_time, - .gettime64 = stmmac_get_time, + .gettimex64 = stmmac_get_timex, .settime64 = stmmac_set_time, .enable = dwmac1000_ptp_enable, }; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c index 369c8f4170f8..38cc8fbf2d65 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c @@ -1778,7 +1778,7 @@ static int stmmac_test_tbs(struct stmmac_priv *priv) return ret; read_lock_irqsave(&priv->ptp_lock, flags); - stmmac_get_systime(priv, priv->ptpaddr, &curr_time); + stmmac_get_systime(priv, priv->ptpaddr, &curr_time, NULL); read_unlock_irqrestore(&priv->ptp_lock, flags); if (!curr_time) { @@ -1800,7 +1800,7 @@ static int stmmac_test_tbs(struct stmmac_priv *priv) /* Check if expected time has elapsed */ read_lock_irqsave(&priv->ptp_lock, flags); - stmmac_get_systime(priv, priv->ptpaddr, &curr_time); + stmmac_get_systime(priv, priv->ptpaddr, &curr_time, NULL); read_unlock_irqrestore(&priv->ptp_lock, flags); if ((curr_time - start_time) < STMMAC_TBS_LT_OFFSET) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c index ea1f97d6f0bd..b09e9a89cee8 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c @@ -1073,7 +1073,8 @@ static int tc_taprio_configure(struct stmmac_priv *priv, mutex_lock(&priv->est_lock); /* Adjust for real system time */ - priv->ptp_clock_ops.gettime64(&priv->ptp_clock_ops, ¤t_time); + priv->ptp_clock_ops.gettimex64(&priv->ptp_clock_ops, ¤t_time, + NULL); current_time_ns = timespec64_to_ktime(current_time); time = stmmac_calc_tas_basetime(qopt->base_time, current_time_ns, qopt->cycle_time);