timekeeping: Prepare for cross timestamps on arbitrary clock IDs

PTP device system crosstime stamps support only CLOCK_REALTIME, which is
meaningless for AUX clocks. The PTP core hands in the clock ID already, so
prepare the core code to honor it.

 - Add a new sys_systime field to struct system_device_crosststamp which
   aliases the sys_realtime field. Once all users are converted
   sys_realtime can be removed.

 - Prepare get_device_system_crosststamp() and the related code for it by
   switching to sys_systime and providing the initial changes to utilize
   different time keepers.

No functional change intended.

Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Tested-by: David Woodhouse <dwmw@amazon.co.uk>
Tested-by: Arthur Kiyanovski <akiyano@amazon.com>
Reviewed-by: David Woodhouse <dwmw@amazon.co.uk>
Reviewed-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
Link: https://patch.msgid.link/20260529195557.846634842@kernel.org
This commit is contained in:
Thomas Gleixner
2026-05-29 22:01:00 +02:00
parent b21d442c9a
commit 09fb74f77e
2 changed files with 41 additions and 26 deletions

View File

@@ -319,13 +319,18 @@ struct system_counterval_t {
* @device: Device time
* @sys_counter: Clocksource counter value simultaneous with device time
* @sys_realtime: Realtime simultaneous with device time
* @sys_systime: System time for @clock_id
* @sys_monoraw: Monotonic raw simultaneous with device time
*/
struct system_device_crosststamp {
clockid_t clock_id;
ktime_t device;
struct system_counterval_t sys_counter;
ktime_t sys_realtime;
union {
/* realtime goes away once all users are converted */
ktime_t sys_realtime;
ktime_t sys_systime;
};
ktime_t sys_monoraw;
};

View File

@@ -1312,7 +1312,7 @@ static int adjust_historical_crosststamp(struct system_time_snapshot *history,
struct system_device_crosststamp *ts)
{
struct timekeeper *tk = &tk_core.timekeeper;
u64 corr_raw, corr_real;
u64 corr_raw, corr_sys;
bool interp_forward;
int ret;
@@ -1329,8 +1329,7 @@ static int adjust_historical_crosststamp(struct system_time_snapshot *history,
* Scale the monotonic raw time delta by:
* partial_history_cycles / total_history_cycles
*/
corr_raw = (u64)ktime_to_ns(
ktime_sub(ts->sys_monoraw, history->monoraw));
corr_raw = (u64)ktime_to_ns(ktime_sub(ts->sys_monoraw, history->monoraw));
ret = scale64_check_overflow(partial_history_cycles,
total_history_cycles, &corr_raw);
if (ret)
@@ -1338,30 +1337,29 @@ static int adjust_historical_crosststamp(struct system_time_snapshot *history,
/*
* If there is a discontinuity in the history, scale monotonic raw
* correction by:
* mult(real)/mult(raw) yielding the realtime correction
* Otherwise, calculate the realtime correction similar to monotonic
* raw calculation
* correction by:
* mult(sys)/mult(raw) yielding the system time correction
*
* Otherwise, calculate the system time correction similar to monotonic
* raw calculation
*/
if (discontinuity) {
corr_real = mul_u64_u32_div
(corr_raw, tk->tkr_mono.mult, tk->tkr_raw.mult);
corr_sys = mul_u64_u32_div(corr_raw, tk->tkr_mono.mult, tk->tkr_raw.mult);
} else {
corr_real = (u64)ktime_to_ns(
ktime_sub(ts->sys_realtime, history->systime));
ret = scale64_check_overflow(partial_history_cycles,
total_history_cycles, &corr_real);
corr_sys = (u64)ktime_to_ns(ktime_sub(ts->sys_systime, history->systime));
ret = scale64_check_overflow(partial_history_cycles, total_history_cycles,
&corr_sys);
if (ret)
return ret;
}
/* Fixup monotonic raw and real time time values */
/* Fixup monotonic raw and system time time values */
if (interp_forward) {
ts->sys_monoraw = ktime_add_ns(history->monoraw, corr_raw);
ts->sys_realtime = ktime_add_ns(history->systime, corr_real);
ts->sys_systime = ktime_add_ns(history->systime, corr_sys);
} else {
ts->sys_monoraw = ktime_sub_ns(ts->sys_monoraw, corr_raw);
ts->sys_realtime = ktime_sub_ns(ts->sys_realtime, corr_real);
ts->sys_systime = ktime_sub_ns(ts->sys_systime, corr_sys);
}
return 0;
@@ -1505,16 +1503,29 @@ int get_device_system_crosststamp(int (*get_time_fn)
struct system_device_crosststamp *xtstamp)
{
u64 syscnt_cycles, cycles, now, interval_start;
struct timekeeper *tk = &tk_core.timekeeper;
unsigned int seq, clock_was_set_seq = 0;
ktime_t base_real, base_raw;
u64 nsec_real, nsec_raw;
ktime_t base_sys, base_raw, *offs;
u64 nsec_sys, nsec_raw;
u8 cs_was_changed_seq;
bool do_interp;
struct timekeeper *tk;
struct tk_data *tkd;
int ret;
switch (xtstamp->clock_id) {
case CLOCK_REALTIME:
tkd = &tk_core;
offs = &tk_core.timekeeper.offs_real;
break;
default:
WARN_ON_ONCE(1);
return -ENODEV;
}
tk = &tkd->timekeeper;
do {
seq = read_seqcount_begin(&tk_core.seq);
seq = read_seqcount_begin(&tkd->seq);
/*
* Try to synchronously capture device time and a system
* counter value calling back into the device driver
@@ -1549,15 +1560,14 @@ int get_device_system_crosststamp(int (*get_time_fn)
do_interp = false;
}
base_real = ktime_add(tk->tkr_mono.base,
tk_core.timekeeper.offs_real);
base_sys = ktime_add(tk->tkr_mono.base, *offs);
base_raw = tk->tkr_raw.base;
nsec_real = timekeeping_cycles_to_ns(&tk->tkr_mono, cycles);
nsec_sys = timekeeping_cycles_to_ns(&tk->tkr_mono, cycles);
nsec_raw = timekeeping_cycles_to_ns(&tk->tkr_raw, cycles);
} while (read_seqcount_retry(&tk_core.seq, seq));
} while (read_seqcount_retry(&tkd->seq, seq));
xtstamp->sys_realtime = ktime_add_ns(base_real, nsec_real);
xtstamp->sys_systime = ktime_add_ns(base_sys, nsec_sys);
xtstamp->sys_monoraw = ktime_add_ns(base_raw, nsec_raw);
/*