mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
timekeeping: Account for monotonicity adjustment in ntp_error
timekeeping_apply_adjustment() modifies xtime_nsec to ensure monotonicity
when mult changes:
xtime_nsec -= offset
This ensures that the time reported to userspace does not jump when the
multiplier is adjusted from one tick to the next. However, the ntp_error
accumulator which tracks the difference between intended and actual
clock position was not being updated to reflect this additional
discrepancy.
An earlier attempt at this compensation existed as:
ntp_error -= (interval - offset) << ntp_error_shift
but was removed in commit c2cda2a5bd ("timekeeping/ntp: Don't align
NTP frequency adjustments to ticks") because it was a major source of
NTP error. That's because (interval - offset) was wrong: the subtraction
of "interval" prematurely accounted for the changed xtime_interval of
the next tick, which would be correctly accounted in the next
accumulation anyway — a double subtraction.
What is actually needed is just the "offset" part: ntp_error must be
told that xtime_nsec moved by "offset" without a corresponding change
in the intended position. For the normal ±1 mult dithering this is
negligible (the adjustments cancel over time), but for larger mult
changes — such as when an external reference clock sets a new
frequency — the one-time uncompensated offset is significant.
Fix by adjusting ntp_error by the correct amount:
ntp_error += offset << ntp_error_shift
This keeps ntp_error consistent with the actual xtime_nsec position
after the adjustment, and ensures the discrepancy is correctly smoothed
away over time and the clock returns to where it should have been.
Fixes: c2cda2a5bd ("timekeeping/ntp: Don't align NTP frequency adjustments to ticks")
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Assisted-by: Kiro:claude-opus-4.6-1m
Acked-by: John Stultz <jstultz@google.com>
Link: https://patch.msgid.link/20260621220051.1030462-3-dwmw2@infradead.org
This commit is contained in:
committed by
Thomas Gleixner
parent
79b8bd857b
commit
b7befd6d91
@@ -2404,6 +2404,11 @@ static __always_inline void timekeeping_apply_adjustment(struct timekeeper *tk,
|
||||
* xtime_nsec_2 = xtime_nsec_1 - offset
|
||||
* Which simplifies to:
|
||||
* xtime_nsec -= offset
|
||||
*
|
||||
* When subtracting offset from xtime_nsec, the same amount
|
||||
* (in appropriate units) has to be added to ntp_error, in
|
||||
* order to correctly track the delta between the time
|
||||
* reported in xtime_nsec, and the intended time.
|
||||
*/
|
||||
if ((mult_adj > 0) && (tk->tkr_mono.mult + mult_adj < mult_adj)) {
|
||||
/* NTP adjustment caused clocksource mult overflow */
|
||||
@@ -2414,6 +2419,7 @@ static __always_inline void timekeeping_apply_adjustment(struct timekeeper *tk,
|
||||
tk->tkr_mono.mult += mult_adj;
|
||||
tk->xtime_interval += interval;
|
||||
tk->tkr_mono.xtime_nsec -= offset;
|
||||
tk->ntp_error += offset << tk->ntp_error_shift;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user