[patch 23/26] timekeeping: Prepare do_adtimex() for PTP clocks
From: Thomas Gleixner <hidden>
Date: 2025-05-13 15:13:39
Also in:
lkml
Exclude ADJ_TAI, leap seconds and PPS functionality and provide a time stamp based on the actual clock. Signed-off-by: Thomas Gleixner <redacted> --- kernel/time/timekeeping.c | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) ---
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c@@ -58,6 +58,17 @@ static struct tk_data timekeeper_data[TI /* The core timekeeper */ #define tk_core (timekeeper_data[TIMEKEEPER_CORE]) +#ifdef CONFIG_POSIX_PTP_CLOCKS +static inline bool tk_get_ptp_ts64(unsigned int tkid, struct timespec64 *ts) +{ + return ktime_get_ptp_ts64(CLOCK_PTP + tkid - TIMEKEEPER_PTP, ts); +} +#else +static inline bool tk_get_ptp_ts64(unsigned int tkid, struct timespec64 *ts) +{ + return false; +} +#endif /* flag for if timekeeping is suspended */ int __read_mostly timekeeping_suspended;
@@ -2503,7 +2514,7 @@ ktime_t ktime_get_update_offsets_now(uns /* * timekeeping_validate_timex - Ensures the timex is ok for use in do_adjtimex */ -static int timekeeping_validate_timex(const struct __kernel_timex *txc) +static int timekeeping_validate_timex(const struct __kernel_timex *txc, bool ptp_clock) { if (txc->modes & ADJ_ADJTIME) { /* singleshot must not be used with any other mode bits */
@@ -2562,6 +2573,21 @@ static int timekeeping_validate_timex(co return -EINVAL; } + if (!ptp_clock) + return 0; + + /* PTP clocks are TAI based and do not have leap seconds */ + if (txc->status & (STA_INS | STA_DEL)) + return -EINVAL; + + /* No TAI offset setting */ + if (txc->modes & ADJ_TAI) + return -EINVAL; + + /* No PPS support either */ + if (txc->status & (STA_PPSFREQ | STA_PPSTIME)) + return -EINVAL; + return 0; }
@@ -2592,15 +2618,22 @@ static int __do_adjtimex(struct tk_data struct timekeeper *tks = &tkd->shadow_timekeeper; struct timespec64 ts; s32 orig_tai, tai; + bool ptp_clock; int ret; + ptp_clock = IS_ENABLED(CONFIG_POSIX_PTP_CLOCKS) && tkd->timekeeper.id != TIMEKEEPER_CORE; + /* Validate the data before disabling interrupts */ - ret = timekeeping_validate_timex(txc); + ret = timekeeping_validate_timex(txc, ptp_clock); if (ret) return ret; add_device_randomness(txc, sizeof(*txc)); - ktime_get_real_ts64(&ts); + if (!ptp_clock) + ktime_get_real_ts64(&ts); + else + tk_get_ptp_ts64(tkd->timekeeper.id, &ts); + add_device_randomness(&ts, sizeof(ts)); guard(raw_spinlock_irqsave)(&tkd->lock);