In commit cb33217b1b25 ("time: Avoid accumulating time drift in
suspend/resume") logic was added to timekeeping_suspend() to compensate for
read_persistent_clock() having only single-second precision. However, if
the implementation is capable of returning fractional seconds then it is
better to disable this compensation because of its interaction with NTP.This patch checks the tv_nsec field from read_persistent_clock(). If it ever returns a non-zero value, then the compensation is disabled. Signed-off-by: Gabriel M. Beddingfield <[email protected]> --- kernel/time/timekeeping.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 2cafb49aa65e..19bf462d4ce7 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -1479,6 +1479,8 @@ static bool sleeptime_injected; /* Flag for if there is a persistent clock on this platform */ static bool persistent_clock_exists; +/* Flag for if the persistent clock supports fractional seconds */ +static bool persistent_clock_has_fractional_seconds; /* * timekeeping_init - Initializes the clocksource and common timekeeping values @@ -1703,16 +1705,24 @@ int timekeeping_suspend(void) * On some systems the persistent_clock can not be detected at * timekeeping_init by its return value, so if we see a valid * value returned, update the persistent_clock_exists flag. + * + * Likewise, some systems provide only whole (truncated) seconds + * for the time. If we ever see a non-zero tv_nsec, then we + * disable the "delta_delta" compensation. */ - if (timekeeping_suspend_time.tv_sec || timekeeping_suspend_time.tv_nsec) + if (timekeeping_suspend_time.tv_nsec) { + persistent_clock_exists = true; + persistent_clock_has_fractional_seconds = true; + } else if (timekeeping_suspend_time.tv_sec) { persistent_clock_exists = true; + } raw_spin_lock_irqsave(&timekeeper_lock, flags); write_seqcount_begin(&tk_core.seq); timekeeping_forward_now(tk); timekeeping_suspended = 1; - if (persistent_clock_exists) { + if (persistent_clock_exists && !persistent_clock_has_fractional_seconds) { /* * To avoid drift caused by repeated suspend/resumes, * which each can add ~1 second drift error, -- 2.14.2.920.gcf0c67979c-goog

