1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
24c7ee8deSjohn stultz /*
34c7ee8deSjohn stultz * NTP state machine interfaces and logic.
44c7ee8deSjohn stultz *
54c7ee8deSjohn stultz * This code was mainly moved from kernel/timer.c and kernel/time.c
64c7ee8deSjohn stultz * Please see those files for relevant copyright info and historical
74c7ee8deSjohn stultz * changelogs.
84c7ee8deSjohn stultz */
9aa0ac365SAlexey Dobriyan #include <linux/capability.h>
107dffa3c6SRoman Zippel #include <linux/clocksource.h>
11eb3f938fSMaciej W. Rozycki #include <linux/workqueue.h>
1253bbfa9eSIngo Molnar #include <linux/hrtimer.h>
1353bbfa9eSIngo Molnar #include <linux/jiffies.h>
1453bbfa9eSIngo Molnar #include <linux/math64.h>
1553bbfa9eSIngo Molnar #include <linux/timex.h>
1653bbfa9eSIngo Molnar #include <linux/time.h>
1753bbfa9eSIngo Molnar #include <linux/mm.h>
18025b40abSAlexander Gordeev #include <linux/module.h>
19023f333aSJason Gunthorpe #include <linux/rtc.h>
207e8eda73SOndrej Mosnacek #include <linux/audit.h>
214c7ee8deSjohn stultz
22aa6f9c59SJohn Stultz #include "ntp_internal.h"
230af86465SDengChao #include "timekeeping_internal.h"
240af86465SDengChao
2568f66f97SThomas Gleixner /**
2668f66f97SThomas Gleixner * struct ntp_data - Structure holding all NTP related state
2768f66f97SThomas Gleixner * @tick_usec: USER_HZ period in microseconds
28ec93ec22SThomas Gleixner * @tick_length: Adjusted tick length
29ec93ec22SThomas Gleixner * @tick_length_base: Base value for @tick_length
30bee18a23SThomas Gleixner * @time_state: State of the clock synchronization
31bee18a23SThomas Gleixner * @time_status: Clock status bits
32d5143554SThomas Gleixner * @time_offset: Time adjustment in nanoseconds
33d5143554SThomas Gleixner * @time_constant: PLL time constant
347891cf29SThomas Gleixner * @time_maxerror: Maximum error in microseconds holding the NTP sync distance
357891cf29SThomas Gleixner * (NTP dispersion + delay / 2)
367891cf29SThomas Gleixner * @time_esterror: Estimated error in microseconds holding NTP dispersion
37161b8ec2SThomas Gleixner * @time_freq: Frequency offset scaled nsecs/secs
38161b8ec2SThomas Gleixner * @time_reftime: Time at last adjustment in seconds
39bb6400a2SThomas Gleixner * @time_adjust: Adjustment value
40bb6400a2SThomas Gleixner * @ntp_tick_adj: Constant boot-param configurable NTP tick adjustment (upscaled)
4175d956b9SThomas Gleixner * @ntp_next_leap_sec: Second value of the next pending leapsecond, or TIME64_MAX if no leap
42a076b214SJohn Stultz *
43931a177fSThomas Gleixner * @pps_valid: PPS signal watchdog counter
445cc953b8SThomas Gleixner * @pps_tf: PPS phase median filter
459d7130dfSThomas Gleixner * @pps_jitter: PPS current jitter in nanoseconds
46db45e9bcSThomas Gleixner * @pps_fbase: PPS beginning of the last freq interval
47b1c89a76SThomas Gleixner * @pps_shift: PPS current interval duration in seconds (shift value)
48b1c89a76SThomas Gleixner * @pps_intcnt: PPS interval counter
4912850b46SThomas Gleixner * @pps_freq: PPS frequency offset in scaled ns/s
5012850b46SThomas Gleixner * @pps_stabil: PPS current stability in scaled ns/s
516fadb4a6SThomas Gleixner * @pps_calcnt: PPS monitor: calibration intervals
526fadb4a6SThomas Gleixner * @pps_jitcnt: PPS monitor: jitter limit exceeded
536fadb4a6SThomas Gleixner * @pps_stbcnt: PPS monitor: stability limit exceeded
546fadb4a6SThomas Gleixner * @pps_errcnt: PPS monitor: calibration errors
55931a177fSThomas Gleixner *
5668f66f97SThomas Gleixner * Protected by the timekeeping locks.
57b0ee7556SRoman Zippel */
5868f66f97SThomas Gleixner struct ntp_data {
5968f66f97SThomas Gleixner unsigned long tick_usec;
60ec93ec22SThomas Gleixner u64 tick_length;
61ec93ec22SThomas Gleixner u64 tick_length_base;
62bee18a23SThomas Gleixner int time_state;
63bee18a23SThomas Gleixner int time_status;
64d5143554SThomas Gleixner s64 time_offset;
65d5143554SThomas Gleixner long time_constant;
667891cf29SThomas Gleixner long time_maxerror;
677891cf29SThomas Gleixner long time_esterror;
68161b8ec2SThomas Gleixner s64 time_freq;
69161b8ec2SThomas Gleixner time64_t time_reftime;
70bb6400a2SThomas Gleixner long time_adjust;
71bb6400a2SThomas Gleixner s64 ntp_tick_adj;
7275d956b9SThomas Gleixner time64_t ntp_next_leap_sec;
73931a177fSThomas Gleixner #ifdef CONFIG_NTP_PPS
74931a177fSThomas Gleixner int pps_valid;
755cc953b8SThomas Gleixner long pps_tf[3];
769d7130dfSThomas Gleixner long pps_jitter;
77db45e9bcSThomas Gleixner struct timespec64 pps_fbase;
78b1c89a76SThomas Gleixner int pps_shift;
79b1c89a76SThomas Gleixner int pps_intcnt;
8012850b46SThomas Gleixner s64 pps_freq;
8112850b46SThomas Gleixner long pps_stabil;
826fadb4a6SThomas Gleixner long pps_calcnt;
836fadb4a6SThomas Gleixner long pps_jitcnt;
846fadb4a6SThomas Gleixner long pps_stbcnt;
856fadb4a6SThomas Gleixner long pps_errcnt;
86931a177fSThomas Gleixner #endif
8768f66f97SThomas Gleixner };
8853bbfa9eSIngo Molnar
8968f66f97SThomas Gleixner static struct ntp_data tk_ntp_data = {
9068f66f97SThomas Gleixner .tick_usec = USER_TICK_USEC,
91bee18a23SThomas Gleixner .time_state = TIME_OK,
92bee18a23SThomas Gleixner .time_status = STA_UNSYNC,
93d5143554SThomas Gleixner .time_constant = 2,
947891cf29SThomas Gleixner .time_maxerror = NTP_PHASE_LIMIT,
957891cf29SThomas Gleixner .time_esterror = NTP_PHASE_LIMIT,
9675d956b9SThomas Gleixner .ntp_next_leap_sec = TIME64_MAX,
9768f66f97SThomas Gleixner };
9853bbfa9eSIngo Molnar
9990bf361cSJohn Stultz #define SECS_PER_DAY 86400
100bbd12676SIngo Molnar #define MAX_TICKADJ 500LL /* usecs */
10153bbfa9eSIngo Molnar #define MAX_TICKADJ_SCALED \
102bbd12676SIngo Molnar (((MAX_TICKADJ * NSEC_PER_USEC) << NTP_SCALE_SHIFT) / NTP_INTERVAL_FREQ)
103d897a4abSMiroslav Lichvar #define MAX_TAI_OFFSET 100000
1044c7ee8deSjohn stultz
105025b40abSAlexander Gordeev #ifdef CONFIG_NTP_PPS
106025b40abSAlexander Gordeev
107025b40abSAlexander Gordeev /*
108025b40abSAlexander Gordeev * The following variables are used when a pulse-per-second (PPS) signal
109025b40abSAlexander Gordeev * is available. They establish the engineering parameters of the clock
110025b40abSAlexander Gordeev * discipline loop when controlled by the PPS signal.
111025b40abSAlexander Gordeev */
112025b40abSAlexander Gordeev #define PPS_VALID 10 /* PPS signal watchdog max (s) */
113025b40abSAlexander Gordeev #define PPS_POPCORN 4 /* popcorn spike threshold (shift) */
114025b40abSAlexander Gordeev #define PPS_INTMIN 2 /* min freq interval (s) (shift) */
115025b40abSAlexander Gordeev #define PPS_INTMAX 8 /* max freq interval (s) (shift) */
116025b40abSAlexander Gordeev #define PPS_INTCOUNT 4 /* number of consecutive good intervals to
117025b40abSAlexander Gordeev increase pps_shift or consecutive bad
118025b40abSAlexander Gordeev intervals to decrease it */
119025b40abSAlexander Gordeev #define PPS_MAXWANDER 100000 /* max PPS freq wander (ns/s) */
120025b40abSAlexander Gordeev
121025b40abSAlexander Gordeev /*
122a0581cdbSThomas Gleixner * PPS kernel consumer compensates the whole phase error immediately.
123025b40abSAlexander Gordeev * Otherwise, reduce the offset by a fixed factor times the time constant.
124025b40abSAlexander Gordeev */
ntp_offset_chunk(struct ntp_data * ntpdata,s64 offset)125bee18a23SThomas Gleixner static inline s64 ntp_offset_chunk(struct ntp_data *ntpdata, s64 offset)
126025b40abSAlexander Gordeev {
127bee18a23SThomas Gleixner if (ntpdata->time_status & STA_PPSTIME && ntpdata->time_status & STA_PPSSIGNAL)
128025b40abSAlexander Gordeev return offset;
129025b40abSAlexander Gordeev else
130d5143554SThomas Gleixner return shift_right(offset, SHIFT_PLL + ntpdata->time_constant);
131025b40abSAlexander Gordeev }
132025b40abSAlexander Gordeev
pps_reset_freq_interval(struct ntp_data * ntpdata)133b1c89a76SThomas Gleixner static inline void pps_reset_freq_interval(struct ntp_data *ntpdata)
134025b40abSAlexander Gordeev {
135a0581cdbSThomas Gleixner /* The PPS calibration interval may end surprisingly early */
136b1c89a76SThomas Gleixner ntpdata->pps_shift = PPS_INTMIN;
137b1c89a76SThomas Gleixner ntpdata->pps_intcnt = 0;
138025b40abSAlexander Gordeev }
139025b40abSAlexander Gordeev
140025b40abSAlexander Gordeev /**
141025b40abSAlexander Gordeev * pps_clear - Clears the PPS state variables
1425cc953b8SThomas Gleixner * @ntpdata: Pointer to ntp data
143025b40abSAlexander Gordeev */
pps_clear(struct ntp_data * ntpdata)1445cc953b8SThomas Gleixner static inline void pps_clear(struct ntp_data *ntpdata)
145025b40abSAlexander Gordeev {
146b1c89a76SThomas Gleixner pps_reset_freq_interval(ntpdata);
1475cc953b8SThomas Gleixner ntpdata->pps_tf[0] = 0;
1485cc953b8SThomas Gleixner ntpdata->pps_tf[1] = 0;
1495cc953b8SThomas Gleixner ntpdata->pps_tf[2] = 0;
150db45e9bcSThomas Gleixner ntpdata->pps_fbase.tv_sec = ntpdata->pps_fbase.tv_nsec = 0;
15112850b46SThomas Gleixner ntpdata->pps_freq = 0;
152025b40abSAlexander Gordeev }
153025b40abSAlexander Gordeev
154a0581cdbSThomas Gleixner /*
155a0581cdbSThomas Gleixner * Decrease pps_valid to indicate that another second has passed since the
156a0581cdbSThomas Gleixner * last PPS signal. When it reaches 0, indicate that PPS signal is missing.
157025b40abSAlexander Gordeev */
pps_dec_valid(struct ntp_data * ntpdata)158bee18a23SThomas Gleixner static inline void pps_dec_valid(struct ntp_data *ntpdata)
159025b40abSAlexander Gordeev {
160931a177fSThomas Gleixner if (ntpdata->pps_valid > 0) {
161931a177fSThomas Gleixner ntpdata->pps_valid--;
162931a177fSThomas Gleixner } else {
163bee18a23SThomas Gleixner ntpdata->time_status &= ~(STA_PPSSIGNAL | STA_PPSJITTER |
164025b40abSAlexander Gordeev STA_PPSWANDER | STA_PPSERROR);
1655cc953b8SThomas Gleixner pps_clear(ntpdata);
166025b40abSAlexander Gordeev }
167025b40abSAlexander Gordeev }
168025b40abSAlexander Gordeev
pps_set_freq(struct ntp_data * ntpdata)16912850b46SThomas Gleixner static inline void pps_set_freq(struct ntp_data *ntpdata)
170025b40abSAlexander Gordeev {
17112850b46SThomas Gleixner ntpdata->pps_freq = ntpdata->time_freq;
172025b40abSAlexander Gordeev }
173025b40abSAlexander Gordeev
is_error_status(int status)17448c3c65fSThomas Gleixner static inline bool is_error_status(int status)
175025b40abSAlexander Gordeev {
176ea54bca3SGeorge Spelvin return (status & (STA_UNSYNC|STA_CLOCKERR))
177a0581cdbSThomas Gleixner /*
178a0581cdbSThomas Gleixner * PPS signal lost when either PPS time or PPS frequency
179a0581cdbSThomas Gleixner * synchronization requested
180025b40abSAlexander Gordeev */
181ea54bca3SGeorge Spelvin || ((status & (STA_PPSFREQ|STA_PPSTIME))
182ea54bca3SGeorge Spelvin && !(status & STA_PPSSIGNAL))
183a0581cdbSThomas Gleixner /*
184a0581cdbSThomas Gleixner * PPS jitter exceeded when PPS time synchronization
185a0581cdbSThomas Gleixner * requested
186a0581cdbSThomas Gleixner */
187ea54bca3SGeorge Spelvin || ((status & (STA_PPSTIME|STA_PPSJITTER))
188025b40abSAlexander Gordeev == (STA_PPSTIME|STA_PPSJITTER))
189a0581cdbSThomas Gleixner /*
190a0581cdbSThomas Gleixner * PPS wander exceeded or calibration error when PPS
191a0581cdbSThomas Gleixner * frequency synchronization requested
192025b40abSAlexander Gordeev */
193ea54bca3SGeorge Spelvin || ((status & STA_PPSFREQ)
194ea54bca3SGeorge Spelvin && (status & (STA_PPSWANDER|STA_PPSERROR)));
195025b40abSAlexander Gordeev }
196025b40abSAlexander Gordeev
pps_fill_timex(struct ntp_data * ntpdata,struct __kernel_timex * txc)197bee18a23SThomas Gleixner static inline void pps_fill_timex(struct ntp_data *ntpdata, struct __kernel_timex *txc)
198025b40abSAlexander Gordeev {
19912850b46SThomas Gleixner txc->ppsfreq = shift_right((ntpdata->pps_freq >> PPM_SCALE_INV_SHIFT) *
200025b40abSAlexander Gordeev PPM_SCALE_INV, NTP_SCALE_SHIFT);
2019d7130dfSThomas Gleixner txc->jitter = ntpdata->pps_jitter;
202bee18a23SThomas Gleixner if (!(ntpdata->time_status & STA_NANO))
2039d7130dfSThomas Gleixner txc->jitter = ntpdata->pps_jitter / NSEC_PER_USEC;
204b1c89a76SThomas Gleixner txc->shift = ntpdata->pps_shift;
20512850b46SThomas Gleixner txc->stabil = ntpdata->pps_stabil;
2066fadb4a6SThomas Gleixner txc->jitcnt = ntpdata->pps_jitcnt;
2076fadb4a6SThomas Gleixner txc->calcnt = ntpdata->pps_calcnt;
2086fadb4a6SThomas Gleixner txc->errcnt = ntpdata->pps_errcnt;
2096fadb4a6SThomas Gleixner txc->stbcnt = ntpdata->pps_stbcnt;
210025b40abSAlexander Gordeev }
211025b40abSAlexander Gordeev
212025b40abSAlexander Gordeev #else /* !CONFIG_NTP_PPS */
213025b40abSAlexander Gordeev
ntp_offset_chunk(struct ntp_data * ntpdata,s64 offset)214d5143554SThomas Gleixner static inline s64 ntp_offset_chunk(struct ntp_data *ntpdata, s64 offset)
215025b40abSAlexander Gordeev {
216d5143554SThomas Gleixner return shift_right(offset, SHIFT_PLL + ntpdata->time_constant);
217025b40abSAlexander Gordeev }
218025b40abSAlexander Gordeev
pps_reset_freq_interval(struct ntp_data * ntpdata)219b1c89a76SThomas Gleixner static inline void pps_reset_freq_interval(struct ntp_data *ntpdata) {}
pps_clear(struct ntp_data * ntpdata)2205cc953b8SThomas Gleixner static inline void pps_clear(struct ntp_data *ntpdata) {}
pps_dec_valid(struct ntp_data * ntpdata)221bee18a23SThomas Gleixner static inline void pps_dec_valid(struct ntp_data *ntpdata) {}
pps_set_freq(struct ntp_data * ntpdata)22212850b46SThomas Gleixner static inline void pps_set_freq(struct ntp_data *ntpdata) {}
223025b40abSAlexander Gordeev
is_error_status(int status)22448c3c65fSThomas Gleixner static inline bool is_error_status(int status)
225025b40abSAlexander Gordeev {
226025b40abSAlexander Gordeev return status & (STA_UNSYNC|STA_CLOCKERR);
227025b40abSAlexander Gordeev }
228025b40abSAlexander Gordeev
pps_fill_timex(struct ntp_data * ntpdata,struct __kernel_timex * txc)229bee18a23SThomas Gleixner static inline void pps_fill_timex(struct ntp_data *ntpdata, struct __kernel_timex *txc)
230025b40abSAlexander Gordeev {
231025b40abSAlexander Gordeev /* PPS is not implemented, so these are zero */
232025b40abSAlexander Gordeev txc->ppsfreq = 0;
233025b40abSAlexander Gordeev txc->jitter = 0;
234025b40abSAlexander Gordeev txc->shift = 0;
235025b40abSAlexander Gordeev txc->stabil = 0;
236025b40abSAlexander Gordeev txc->jitcnt = 0;
237025b40abSAlexander Gordeev txc->calcnt = 0;
238025b40abSAlexander Gordeev txc->errcnt = 0;
239025b40abSAlexander Gordeev txc->stbcnt = 0;
240025b40abSAlexander Gordeev }
241025b40abSAlexander Gordeev
242025b40abSAlexander Gordeev #endif /* CONFIG_NTP_PPS */
243025b40abSAlexander Gordeev
2449ce616aaSIngo Molnar /*
245a849a027SThomas Gleixner * Update tick_length and tick_length_base, based on tick_usec, ntp_tick_adj and
246a849a027SThomas Gleixner * time_freq:
2479ce616aaSIngo Molnar */
ntp_update_frequency(struct ntp_data * ntpdata)24868f66f97SThomas Gleixner static void ntp_update_frequency(struct ntp_data *ntpdata)
24970bc42f9SAdrian Bunk {
25068f66f97SThomas Gleixner u64 second_length, new_base, tick_usec = (u64)ntpdata->tick_usec;
2519ce616aaSIngo Molnar
25268f66f97SThomas Gleixner second_length = (u64)(tick_usec * NSEC_PER_USEC * USER_HZ) << NTP_SCALE_SHIFT;
2539ce616aaSIngo Molnar
254bb6400a2SThomas Gleixner second_length += ntpdata->ntp_tick_adj;
255161b8ec2SThomas Gleixner second_length += ntpdata->time_freq;
25670bc42f9SAdrian Bunk
257bc26c31dSIngo Molnar new_base = div_u64(second_length, NTP_INTERVAL_FREQ);
258fdcedf7bSjohn stultz
259fdcedf7bSjohn stultz /*
260a0581cdbSThomas Gleixner * Don't wait for the next second_overflow, apply the change to the
261a0581cdbSThomas Gleixner * tick length immediately:
262fdcedf7bSjohn stultz */
263ec93ec22SThomas Gleixner ntpdata->tick_length += new_base - ntpdata->tick_length_base;
264ec93ec22SThomas Gleixner ntpdata->tick_length_base = new_base;
26570bc42f9SAdrian Bunk }
26670bc42f9SAdrian Bunk
ntp_update_offset_fll(struct ntp_data * ntpdata,s64 offset64,long secs)267bee18a23SThomas Gleixner static inline s64 ntp_update_offset_fll(struct ntp_data *ntpdata, s64 offset64, long secs)
268f939890bSIngo Molnar {
269bee18a23SThomas Gleixner ntpdata->time_status &= ~STA_MODE;
270f939890bSIngo Molnar
271f939890bSIngo Molnar if (secs < MINSEC)
272478b7aabSIngo Molnar return 0;
273f939890bSIngo Molnar
274bee18a23SThomas Gleixner if (!(ntpdata->time_status & STA_FLL) && (secs <= MAXSEC))
275478b7aabSIngo Molnar return 0;
276f939890bSIngo Molnar
277bee18a23SThomas Gleixner ntpdata->time_status |= STA_MODE;
278f939890bSIngo Molnar
279a078c6d0SSasha Levin return div64_long(offset64 << (NTP_SCALE_SHIFT - SHIFT_FLL), secs);
280f939890bSIngo Molnar }
281f939890bSIngo Molnar
ntp_update_offset(struct ntp_data * ntpdata,long offset)282bee18a23SThomas Gleixner static void ntp_update_offset(struct ntp_data *ntpdata, long offset)
283ee9851b2SRoman Zippel {
284136bccbcSThomas Gleixner s64 freq_adj, offset64;
285136bccbcSThomas Gleixner long secs, real_secs;
286ee9851b2SRoman Zippel
287bee18a23SThomas Gleixner if (!(ntpdata->time_status & STA_PLL))
288ee9851b2SRoman Zippel return;
289ee9851b2SRoman Zippel
290bee18a23SThomas Gleixner if (!(ntpdata->time_status & STA_NANO)) {
29152d189f1SSasha Levin /* Make sure the multiplication below won't overflow */
29252d189f1SSasha Levin offset = clamp(offset, -USEC_PER_SEC, USEC_PER_SEC);
2939f14f669SRoman Zippel offset *= NSEC_PER_USEC;
29452d189f1SSasha Levin }
295ee9851b2SRoman Zippel
296a0581cdbSThomas Gleixner /* Scale the phase adjustment and clamp to the operating range. */
29752d189f1SSasha Levin offset = clamp(offset, -MAXPHASE, MAXPHASE);
298ee9851b2SRoman Zippel
299ee9851b2SRoman Zippel /*
300ee9851b2SRoman Zippel * Select how the frequency is to be controlled
301ee9851b2SRoman Zippel * and in which mode (PLL or FLL).
302ee9851b2SRoman Zippel */
303136bccbcSThomas Gleixner real_secs = __ktime_get_real_seconds();
304161b8ec2SThomas Gleixner secs = (long)(real_secs - ntpdata->time_reftime);
305bee18a23SThomas Gleixner if (unlikely(ntpdata->time_status & STA_FREQHOLD))
306c7986acbSIngo Molnar secs = 0;
307c7986acbSIngo Molnar
308161b8ec2SThomas Gleixner ntpdata->time_reftime = real_secs;
309ee9851b2SRoman Zippel
310f939890bSIngo Molnar offset64 = offset;
311bee18a23SThomas Gleixner freq_adj = ntp_update_offset_fll(ntpdata, offset64, secs);
312f939890bSIngo Molnar
3138af3c153SMiroslav Lichvar /*
3148af3c153SMiroslav Lichvar * Clamp update interval to reduce PLL gain with low
3158af3c153SMiroslav Lichvar * sampling rate (e.g. intermittent network connection)
3168af3c153SMiroslav Lichvar * to avoid instability.
3178af3c153SMiroslav Lichvar */
318d5143554SThomas Gleixner if (unlikely(secs > 1 << (SHIFT_PLL + 1 + ntpdata->time_constant)))
319d5143554SThomas Gleixner secs = 1 << (SHIFT_PLL + 1 + ntpdata->time_constant);
3208af3c153SMiroslav Lichvar
3218af3c153SMiroslav Lichvar freq_adj += (offset64 * secs) <<
322d5143554SThomas Gleixner (NTP_SCALE_SHIFT - 2 * (SHIFT_PLL + 2 + ntpdata->time_constant));
323f939890bSIngo Molnar
324161b8ec2SThomas Gleixner freq_adj = min(freq_adj + ntpdata->time_freq, MAXFREQ_SCALED);
325f939890bSIngo Molnar
326161b8ec2SThomas Gleixner ntpdata->time_freq = max(freq_adj, -MAXFREQ_SCALED);
3279f14f669SRoman Zippel
328d5143554SThomas Gleixner ntpdata->time_offset = div_s64(offset64 << NTP_SCALE_SHIFT, NTP_INTERVAL_FREQ);
329ee9851b2SRoman Zippel }
330ee9851b2SRoman Zippel
__ntp_clear(struct ntp_data * ntpdata)33168f66f97SThomas Gleixner static void __ntp_clear(struct ntp_data *ntpdata)
332b0ee7556SRoman Zippel {
333a0581cdbSThomas Gleixner /* Stop active adjtime() */
334bb6400a2SThomas Gleixner ntpdata->time_adjust = 0;
335bee18a23SThomas Gleixner ntpdata->time_status |= STA_UNSYNC;
3367891cf29SThomas Gleixner ntpdata->time_maxerror = NTP_PHASE_LIMIT;
3377891cf29SThomas Gleixner ntpdata->time_esterror = NTP_PHASE_LIMIT;
338b0ee7556SRoman Zippel
33968f66f97SThomas Gleixner ntp_update_frequency(ntpdata);
340b0ee7556SRoman Zippel
341ec93ec22SThomas Gleixner ntpdata->tick_length = ntpdata->tick_length_base;
342d5143554SThomas Gleixner ntpdata->time_offset = 0;
343025b40abSAlexander Gordeev
34475d956b9SThomas Gleixner ntpdata->ntp_next_leap_sec = TIME64_MAX;
345025b40abSAlexander Gordeev /* Clear PPS state variables */
3465cc953b8SThomas Gleixner pps_clear(ntpdata);
347b0ee7556SRoman Zippel }
348b0ee7556SRoman Zippel
34968f66f97SThomas Gleixner /**
35068f66f97SThomas Gleixner * ntp_clear - Clears the NTP state variables
35168f66f97SThomas Gleixner */
ntp_clear(void)35268f66f97SThomas Gleixner void ntp_clear(void)
35368f66f97SThomas Gleixner {
35468f66f97SThomas Gleixner __ntp_clear(&tk_ntp_data);
35568f66f97SThomas Gleixner }
35668f66f97SThomas Gleixner
357ea7cf49aSJohn Stultz
ntp_tick_length(void)358ea7cf49aSJohn Stultz u64 ntp_tick_length(void)
359ea7cf49aSJohn Stultz {
360ec93ec22SThomas Gleixner return tk_ntp_data.tick_length;
361ea7cf49aSJohn Stultz }
362ea7cf49aSJohn Stultz
363833f32d7SJohn Stultz /**
364833f32d7SJohn Stultz * ntp_get_next_leap - Returns the next leapsecond in CLOCK_REALTIME ktime_t
365833f32d7SJohn Stultz *
366833f32d7SJohn Stultz * Provides the time of the next leapsecond against CLOCK_REALTIME in
367833f32d7SJohn Stultz * a ktime_t format. Returns KTIME_MAX if no leapsecond is pending.
368833f32d7SJohn Stultz */
ntp_get_next_leap(void)369833f32d7SJohn Stultz ktime_t ntp_get_next_leap(void)
370833f32d7SJohn Stultz {
371bee18a23SThomas Gleixner struct ntp_data *ntpdata = &tk_ntp_data;
372833f32d7SJohn Stultz ktime_t ret;
373833f32d7SJohn Stultz
374bee18a23SThomas Gleixner if ((ntpdata->time_state == TIME_INS) && (ntpdata->time_status & STA_INS))
37575d956b9SThomas Gleixner return ktime_set(ntpdata->ntp_next_leap_sec, 0);
3762456e855SThomas Gleixner ret = KTIME_MAX;
377833f32d7SJohn Stultz return ret;
378833f32d7SJohn Stultz }
379ea7cf49aSJohn Stultz
3804c7ee8deSjohn stultz /*
381a0581cdbSThomas Gleixner * This routine handles the overflow of the microsecond field
3824c7ee8deSjohn stultz *
3834c7ee8deSjohn stultz * The tricky bits of code to handle the accurate clock support
3844c7ee8deSjohn stultz * were provided by Dave Mills ([email protected]) of NTP fame.
3854c7ee8deSjohn stultz * They were originally developed for SUN and DEC kernels.
3864c7ee8deSjohn stultz * All the kudos should go to Dave for this stuff.
3876b43ae8aSJohn Stultz *
3886b43ae8aSJohn Stultz * Also handles leap second processing, and returns leap offset
3894c7ee8deSjohn stultz */
second_overflow(time64_t secs)390c7963487SDengChao int second_overflow(time64_t secs)
3914c7ee8deSjohn stultz {
392ec93ec22SThomas Gleixner struct ntp_data *ntpdata = &tk_ntp_data;
39339854fe8SIngo Molnar s64 delta;
3946b43ae8aSJohn Stultz int leap = 0;
395c7963487SDengChao s32 rem;
3964c7ee8deSjohn stultz
3976b43ae8aSJohn Stultz /*
3986b43ae8aSJohn Stultz * Leap second processing. If in leap-insert state at the end of the
3996b43ae8aSJohn Stultz * day, the system clock is set back one second; if in leap-delete
4006b43ae8aSJohn Stultz * state, the system clock is set ahead one second.
4016b43ae8aSJohn Stultz */
402bee18a23SThomas Gleixner switch (ntpdata->time_state) {
4036b43ae8aSJohn Stultz case TIME_OK:
404bee18a23SThomas Gleixner if (ntpdata->time_status & STA_INS) {
405bee18a23SThomas Gleixner ntpdata->time_state = TIME_INS;
406c7963487SDengChao div_s64_rem(secs, SECS_PER_DAY, &rem);
40775d956b9SThomas Gleixner ntpdata->ntp_next_leap_sec = secs + SECS_PER_DAY - rem;
408bee18a23SThomas Gleixner } else if (ntpdata->time_status & STA_DEL) {
409bee18a23SThomas Gleixner ntpdata->time_state = TIME_DEL;
410c7963487SDengChao div_s64_rem(secs + 1, SECS_PER_DAY, &rem);
41175d956b9SThomas Gleixner ntpdata->ntp_next_leap_sec = secs + SECS_PER_DAY - rem;
412833f32d7SJohn Stultz }
4136b43ae8aSJohn Stultz break;
4146b43ae8aSJohn Stultz case TIME_INS:
415bee18a23SThomas Gleixner if (!(ntpdata->time_status & STA_INS)) {
41675d956b9SThomas Gleixner ntpdata->ntp_next_leap_sec = TIME64_MAX;
417bee18a23SThomas Gleixner ntpdata->time_state = TIME_OK;
41875d956b9SThomas Gleixner } else if (secs == ntpdata->ntp_next_leap_sec) {
4196b43ae8aSJohn Stultz leap = -1;
420bee18a23SThomas Gleixner ntpdata->time_state = TIME_OOP;
42138007dc0SAnna-Maria Behnsen pr_notice("Clock: inserting leap second 23:59:60 UTC\n");
4226b43ae8aSJohn Stultz }
4236b43ae8aSJohn Stultz break;
4246b43ae8aSJohn Stultz case TIME_DEL:
425bee18a23SThomas Gleixner if (!(ntpdata->time_status & STA_DEL)) {
42675d956b9SThomas Gleixner ntpdata->ntp_next_leap_sec = TIME64_MAX;
427bee18a23SThomas Gleixner ntpdata->time_state = TIME_OK;
42875d956b9SThomas Gleixner } else if (secs == ntpdata->ntp_next_leap_sec) {
4296b43ae8aSJohn Stultz leap = 1;
43075d956b9SThomas Gleixner ntpdata->ntp_next_leap_sec = TIME64_MAX;
431bee18a23SThomas Gleixner ntpdata->time_state = TIME_WAIT;
43238007dc0SAnna-Maria Behnsen pr_notice("Clock: deleting leap second 23:59:59 UTC\n");
4336b43ae8aSJohn Stultz }
4346b43ae8aSJohn Stultz break;
4356b43ae8aSJohn Stultz case TIME_OOP:
43675d956b9SThomas Gleixner ntpdata->ntp_next_leap_sec = TIME64_MAX;
437bee18a23SThomas Gleixner ntpdata->time_state = TIME_WAIT;
4386b43ae8aSJohn Stultz break;
4396b43ae8aSJohn Stultz case TIME_WAIT:
440bee18a23SThomas Gleixner if (!(ntpdata->time_status & (STA_INS | STA_DEL)))
441bee18a23SThomas Gleixner ntpdata->time_state = TIME_OK;
4426b43ae8aSJohn Stultz break;
4436b43ae8aSJohn Stultz }
4446b43ae8aSJohn Stultz
4454c7ee8deSjohn stultz /* Bump the maxerror field */
4467891cf29SThomas Gleixner ntpdata->time_maxerror += MAXFREQ / NSEC_PER_USEC;
4477891cf29SThomas Gleixner if (ntpdata->time_maxerror > NTP_PHASE_LIMIT) {
4487891cf29SThomas Gleixner ntpdata->time_maxerror = NTP_PHASE_LIMIT;
449bee18a23SThomas Gleixner ntpdata->time_status |= STA_UNSYNC;
4504c7ee8deSjohn stultz }
4514c7ee8deSjohn stultz
452025b40abSAlexander Gordeev /* Compute the phase adjustment for the next second */
453ec93ec22SThomas Gleixner ntpdata->tick_length = ntpdata->tick_length_base;
45439854fe8SIngo Molnar
455d5143554SThomas Gleixner delta = ntp_offset_chunk(ntpdata, ntpdata->time_offset);
456d5143554SThomas Gleixner ntpdata->time_offset -= delta;
457ec93ec22SThomas Gleixner ntpdata->tick_length += delta;
4588f807f8dSRoman Zippel
459025b40abSAlexander Gordeev /* Check PPS signal */
460bee18a23SThomas Gleixner pps_dec_valid(ntpdata);
461025b40abSAlexander Gordeev
462bb6400a2SThomas Gleixner if (!ntpdata->time_adjust)
463bd331268SJohn Stultz goto out;
4643c972c24SIngo Molnar
465bb6400a2SThomas Gleixner if (ntpdata->time_adjust > MAX_TICKADJ) {
466bb6400a2SThomas Gleixner ntpdata->time_adjust -= MAX_TICKADJ;
467ec93ec22SThomas Gleixner ntpdata->tick_length += MAX_TICKADJ_SCALED;
468bd331268SJohn Stultz goto out;
4693c972c24SIngo Molnar }
4703c972c24SIngo Molnar
471bb6400a2SThomas Gleixner if (ntpdata->time_adjust < -MAX_TICKADJ) {
472bb6400a2SThomas Gleixner ntpdata->time_adjust += MAX_TICKADJ;
473ec93ec22SThomas Gleixner ntpdata->tick_length -= MAX_TICKADJ_SCALED;
474bd331268SJohn Stultz goto out;
4753c972c24SIngo Molnar }
4763c972c24SIngo Molnar
477bb6400a2SThomas Gleixner ntpdata->tick_length += (s64)(ntpdata->time_adjust * NSEC_PER_USEC / NTP_INTERVAL_FREQ)
4783c972c24SIngo Molnar << NTP_SCALE_SHIFT;
479bb6400a2SThomas Gleixner ntpdata->time_adjust = 0;
4806b43ae8aSJohn Stultz
481bd331268SJohn Stultz out:
4826b43ae8aSJohn Stultz return leap;
4834c7ee8deSjohn stultz }
4844c7ee8deSjohn stultz
485c9e6189fSThomas Gleixner #if defined(CONFIG_GENERIC_CMOS_UPDATE) || defined(CONFIG_RTC_SYSTOHC)
4860f295b06SJason Gunthorpe static void sync_hw_clock(struct work_struct *work);
487c9e6189fSThomas Gleixner static DECLARE_WORK(sync_work, sync_hw_clock);
488c9e6189fSThomas Gleixner static struct hrtimer sync_hrtimer;
489e3fab2f3SGeert Uytterhoeven #define SYNC_PERIOD_NS (11ULL * 60 * NSEC_PER_SEC)
4900f295b06SJason Gunthorpe
sync_timer_callback(struct hrtimer * timer)491c9e6189fSThomas Gleixner static enum hrtimer_restart sync_timer_callback(struct hrtimer *timer)
4920f295b06SJason Gunthorpe {
49324c242ecSGeert Uytterhoeven queue_work(system_freezable_power_efficient_wq, &sync_work);
4940f295b06SJason Gunthorpe
495c9e6189fSThomas Gleixner return HRTIMER_NORESTART;
4960f295b06SJason Gunthorpe }
4970f295b06SJason Gunthorpe
sched_sync_hw_clock(unsigned long offset_nsec,bool retry)498c9e6189fSThomas Gleixner static void sched_sync_hw_clock(unsigned long offset_nsec, bool retry)
499c9e6189fSThomas Gleixner {
500c9e6189fSThomas Gleixner ktime_t exp = ktime_set(ktime_get_real_seconds(), 0);
5010f295b06SJason Gunthorpe
502c9e6189fSThomas Gleixner if (retry)
503e3fab2f3SGeert Uytterhoeven exp = ktime_add_ns(exp, 2ULL * NSEC_PER_SEC - offset_nsec);
504c9e6189fSThomas Gleixner else
505c9e6189fSThomas Gleixner exp = ktime_add_ns(exp, SYNC_PERIOD_NS - offset_nsec);
506c9e6189fSThomas Gleixner
507c9e6189fSThomas Gleixner hrtimer_start(&sync_hrtimer, exp, HRTIMER_MODE_ABS);
5080f295b06SJason Gunthorpe }
5090f295b06SJason Gunthorpe
51033e62e83SThomas Gleixner /*
51169eca258SThomas Gleixner * Check whether @now is correct versus the required time to update the RTC
51269eca258SThomas Gleixner * and calculate the value which needs to be written to the RTC so that the
51369eca258SThomas Gleixner * next seconds increment of the RTC after the write is aligned with the next
51469eca258SThomas Gleixner * seconds increment of clock REALTIME.
51533e62e83SThomas Gleixner *
51669eca258SThomas Gleixner * tsched t1 write(t2.tv_sec - 1sec)) t2 RTC increments seconds
51733e62e83SThomas Gleixner *
51869eca258SThomas Gleixner * t2.tv_nsec == 0
51969eca258SThomas Gleixner * tsched = t2 - set_offset_nsec
52069eca258SThomas Gleixner * newval = t2 - NSEC_PER_SEC
52169eca258SThomas Gleixner *
52269eca258SThomas Gleixner * ==> neval = tsched + set_offset_nsec - NSEC_PER_SEC
52369eca258SThomas Gleixner *
52469eca258SThomas Gleixner * As the execution of this code is not guaranteed to happen exactly at
52569eca258SThomas Gleixner * tsched this allows it to happen within a fuzzy region:
52669eca258SThomas Gleixner *
52769eca258SThomas Gleixner * abs(now - tsched) < FUZZ
52869eca258SThomas Gleixner *
52969eca258SThomas Gleixner * If @now is not inside the allowed window the function returns false.
53033e62e83SThomas Gleixner */
rtc_tv_nsec_ok(unsigned long set_offset_nsec,struct timespec64 * to_set,const struct timespec64 * now)53169eca258SThomas Gleixner static inline bool rtc_tv_nsec_ok(unsigned long set_offset_nsec,
53233e62e83SThomas Gleixner struct timespec64 *to_set,
53333e62e83SThomas Gleixner const struct timespec64 *now)
53433e62e83SThomas Gleixner {
5354bf07f65SIngo Molnar /* Allowed error in tv_nsec, arbitrarily set to 5 jiffies in ns. */
53633e62e83SThomas Gleixner const unsigned long TIME_SET_NSEC_FUZZ = TICK_NSEC * 5;
53769eca258SThomas Gleixner struct timespec64 delay = {.tv_sec = -1,
53833e62e83SThomas Gleixner .tv_nsec = set_offset_nsec};
53933e62e83SThomas Gleixner
54033e62e83SThomas Gleixner *to_set = timespec64_add(*now, delay);
54133e62e83SThomas Gleixner
54233e62e83SThomas Gleixner if (to_set->tv_nsec < TIME_SET_NSEC_FUZZ) {
54333e62e83SThomas Gleixner to_set->tv_nsec = 0;
54433e62e83SThomas Gleixner return true;
54533e62e83SThomas Gleixner }
54633e62e83SThomas Gleixner
54733e62e83SThomas Gleixner if (to_set->tv_nsec > NSEC_PER_SEC - TIME_SET_NSEC_FUZZ) {
54833e62e83SThomas Gleixner to_set->tv_sec++;
54933e62e83SThomas Gleixner to_set->tv_nsec = 0;
55033e62e83SThomas Gleixner return true;
55133e62e83SThomas Gleixner }
55233e62e83SThomas Gleixner return false;
55333e62e83SThomas Gleixner }
55433e62e83SThomas Gleixner
5553c00a1feSXunlei Pang #ifdef CONFIG_GENERIC_CMOS_UPDATE
update_persistent_clock64(struct timespec64 now64)5563c00a1feSXunlei Pang int __weak update_persistent_clock64(struct timespec64 now64)
5573c00a1feSXunlei Pang {
55892661788SArnd Bergmann return -ENODEV;
5593c00a1feSXunlei Pang }
56076e87d96SThomas Gleixner #else
update_persistent_clock64(struct timespec64 now64)56176e87d96SThomas Gleixner static inline int update_persistent_clock64(struct timespec64 now64)
56276e87d96SThomas Gleixner {
56376e87d96SThomas Gleixner return -ENODEV;
56476e87d96SThomas Gleixner }
5653c00a1feSXunlei Pang #endif
5663c00a1feSXunlei Pang
56776e87d96SThomas Gleixner #ifdef CONFIG_RTC_SYSTOHC
56876e87d96SThomas Gleixner /* Save NTP synchronized time to the RTC */
update_rtc(struct timespec64 * to_set,unsigned long * offset_nsec)56976e87d96SThomas Gleixner static int update_rtc(struct timespec64 *to_set, unsigned long *offset_nsec)
5704c7ee8deSjohn stultz {
57176e87d96SThomas Gleixner struct rtc_device *rtc;
57276e87d96SThomas Gleixner struct rtc_time tm;
57376e87d96SThomas Gleixner int err = -ENODEV;
5740f295b06SJason Gunthorpe
57576e87d96SThomas Gleixner rtc = rtc_class_open(CONFIG_RTC_SYSTOHC_DEVICE);
57676e87d96SThomas Gleixner if (!rtc)
57776e87d96SThomas Gleixner return -ENODEV;
5780f295b06SJason Gunthorpe
57976e87d96SThomas Gleixner if (!rtc->ops || !rtc->ops->set_time)
58076e87d96SThomas Gleixner goto out_close;
58182644459SThomas Gleixner
58276e87d96SThomas Gleixner /* First call might not have the correct offset */
58376e87d96SThomas Gleixner if (*offset_nsec == rtc->set_offset_nsec) {
58476e87d96SThomas Gleixner rtc_time64_to_tm(to_set->tv_sec, &tm);
58576e87d96SThomas Gleixner err = rtc_set_time(rtc, &tm);
58676e87d96SThomas Gleixner } else {
58776e87d96SThomas Gleixner /* Store the update offset and let the caller try again */
58876e87d96SThomas Gleixner *offset_nsec = rtc->set_offset_nsec;
58976e87d96SThomas Gleixner err = -EAGAIN;
5900f295b06SJason Gunthorpe }
59176e87d96SThomas Gleixner out_close:
59276e87d96SThomas Gleixner rtc_class_close(rtc);
59376e87d96SThomas Gleixner return err;
594023f333aSJason Gunthorpe }
59576e87d96SThomas Gleixner #else
update_rtc(struct timespec64 * to_set,unsigned long * offset_nsec)59676e87d96SThomas Gleixner static inline int update_rtc(struct timespec64 *to_set, unsigned long *offset_nsec)
59776e87d96SThomas Gleixner {
59876e87d96SThomas Gleixner return -ENODEV;
5994c7ee8deSjohn stultz }
60076e87d96SThomas Gleixner #endif
6010f295b06SJason Gunthorpe
60248c3c65fSThomas Gleixner /**
60348c3c65fSThomas Gleixner * ntp_synced - Tells whether the NTP status is not UNSYNC
60448c3c65fSThomas Gleixner * Returns: true if not UNSYNC, false otherwise
60548c3c65fSThomas Gleixner */
ntp_synced(void)60648c3c65fSThomas Gleixner static inline bool ntp_synced(void)
60748c3c65fSThomas Gleixner {
608bee18a23SThomas Gleixner return !(tk_ntp_data.time_status & STA_UNSYNC);
60948c3c65fSThomas Gleixner }
61048c3c65fSThomas Gleixner
6110f295b06SJason Gunthorpe /*
6120f295b06SJason Gunthorpe * If we have an externally synchronized Linux clock, then update RTC clock
6130f295b06SJason Gunthorpe * accordingly every ~11 minutes. Generally RTCs can only store second
6140f295b06SJason Gunthorpe * precision, but many RTCs will adjust the phase of their second tick to
6150f295b06SJason Gunthorpe * match the moment of update. This infrastructure arranges to call to the RTC
6160f295b06SJason Gunthorpe * set at the correct moment to phase synchronize the RTC second tick over
6170f295b06SJason Gunthorpe * with the kernel clock.
6180f295b06SJason Gunthorpe */
sync_hw_clock(struct work_struct * work)6190f295b06SJason Gunthorpe static void sync_hw_clock(struct work_struct *work)
6200f295b06SJason Gunthorpe {
621c9e6189fSThomas Gleixner /*
62276e87d96SThomas Gleixner * The default synchronization offset is 500ms for the deprecated
62376e87d96SThomas Gleixner * update_persistent_clock64() under the assumption that it uses
62476e87d96SThomas Gleixner * the infamous CMOS clock (MC146818).
62576e87d96SThomas Gleixner */
62676e87d96SThomas Gleixner static unsigned long offset_nsec = NSEC_PER_SEC / 2;
62776e87d96SThomas Gleixner struct timespec64 now, to_set;
62876e87d96SThomas Gleixner int res = -EAGAIN;
62976e87d96SThomas Gleixner
63076e87d96SThomas Gleixner /*
631c9e6189fSThomas Gleixner * Don't update if STA_UNSYNC is set and if ntp_notify_cmos_timer()
632c9e6189fSThomas Gleixner * managed to schedule the work between the timer firing and the
633c9e6189fSThomas Gleixner * work being able to rearm the timer. Wait for the timer to expire.
634c9e6189fSThomas Gleixner */
635c9e6189fSThomas Gleixner if (!ntp_synced() || hrtimer_is_queued(&sync_hrtimer))
6360f295b06SJason Gunthorpe return;
6370f295b06SJason Gunthorpe
63876e87d96SThomas Gleixner ktime_get_real_ts64(&now);
63976e87d96SThomas Gleixner /* If @now is not in the allowed window, try again */
64076e87d96SThomas Gleixner if (!rtc_tv_nsec_ok(offset_nsec, &to_set, &now))
64176e87d96SThomas Gleixner goto rearm;
6420f295b06SJason Gunthorpe
64376e87d96SThomas Gleixner /* Take timezone adjusted RTCs into account */
64476e87d96SThomas Gleixner if (persistent_clock_is_local)
64576e87d96SThomas Gleixner to_set.tv_sec -= (sys_tz.tz_minuteswest * 60);
64676e87d96SThomas Gleixner
64776e87d96SThomas Gleixner /* Try the legacy RTC first. */
64876e87d96SThomas Gleixner res = update_persistent_clock64(to_set);
64976e87d96SThomas Gleixner if (res != -ENODEV)
65076e87d96SThomas Gleixner goto rearm;
65176e87d96SThomas Gleixner
65276e87d96SThomas Gleixner /* Try the RTC class */
65376e87d96SThomas Gleixner res = update_rtc(&to_set, &offset_nsec);
65476e87d96SThomas Gleixner if (res == -ENODEV)
65576e87d96SThomas Gleixner return;
65676e87d96SThomas Gleixner rearm:
65776e87d96SThomas Gleixner sched_sync_hw_clock(offset_nsec, res != 0);
65882644459SThomas Gleixner }
65982644459SThomas Gleixner
ntp_notify_cmos_timer(bool offset_set)66035b603f8SBenjamin ROBIN void ntp_notify_cmos_timer(bool offset_set)
66182644459SThomas Gleixner {
662c9e6189fSThomas Gleixner /*
66335b603f8SBenjamin ROBIN * If the time jumped (using ADJ_SETOFFSET) cancels sync timer,
66435b603f8SBenjamin ROBIN * which may have been running if the time was synchronized
66535b603f8SBenjamin ROBIN * prior to the ADJ_SETOFFSET call.
66635b603f8SBenjamin ROBIN */
66735b603f8SBenjamin ROBIN if (offset_set)
66835b603f8SBenjamin ROBIN hrtimer_cancel(&sync_hrtimer);
66935b603f8SBenjamin ROBIN
67035b603f8SBenjamin ROBIN /*
671c9e6189fSThomas Gleixner * When the work is currently executed but has not yet the timer
672c9e6189fSThomas Gleixner * rearmed this queues the work immediately again. No big issue,
673c9e6189fSThomas Gleixner * just a pointless work scheduled.
674c9e6189fSThomas Gleixner */
675c9e6189fSThomas Gleixner if (ntp_synced() && !hrtimer_is_queued(&sync_hrtimer))
67624c242ecSGeert Uytterhoeven queue_work(system_freezable_power_efficient_wq, &sync_work);
67782644459SThomas Gleixner }
67882644459SThomas Gleixner
ntp_init_cmos_sync(void)679c9e6189fSThomas Gleixner static void __init ntp_init_cmos_sync(void)
680c9e6189fSThomas Gleixner {
681*f66b0acfSNam Cao hrtimer_setup(&sync_hrtimer, sync_timer_callback, CLOCK_REALTIME, HRTIMER_MODE_ABS);
682c9e6189fSThomas Gleixner }
683c9e6189fSThomas Gleixner #else /* CONFIG_GENERIC_CMOS_UPDATE) || defined(CONFIG_RTC_SYSTOHC) */
ntp_init_cmos_sync(void)684c9e6189fSThomas Gleixner static inline void __init ntp_init_cmos_sync(void) { }
685c9e6189fSThomas Gleixner #endif /* !CONFIG_GENERIC_CMOS_UPDATE) || defined(CONFIG_RTC_SYSTOHC) */
686c9e6189fSThomas Gleixner
68780f22571SIngo Molnar /*
68880f22571SIngo Molnar * Propagate a new txc->status value into the NTP state:
68980f22571SIngo Molnar */
process_adj_status(struct ntp_data * ntpdata,const struct __kernel_timex * txc)690bee18a23SThomas Gleixner static inline void process_adj_status(struct ntp_data *ntpdata, const struct __kernel_timex *txc)
69180f22571SIngo Molnar {
692bee18a23SThomas Gleixner if ((ntpdata->time_status & STA_PLL) && !(txc->status & STA_PLL)) {
693bee18a23SThomas Gleixner ntpdata->time_state = TIME_OK;
694bee18a23SThomas Gleixner ntpdata->time_status = STA_UNSYNC;
69575d956b9SThomas Gleixner ntpdata->ntp_next_leap_sec = TIME64_MAX;
696a0581cdbSThomas Gleixner /* Restart PPS frequency calibration */
697b1c89a76SThomas Gleixner pps_reset_freq_interval(ntpdata);
69880f22571SIngo Molnar }
69980f22571SIngo Molnar
70080f22571SIngo Molnar /*
70180f22571SIngo Molnar * If we turn on PLL adjustments then reset the
70280f22571SIngo Molnar * reference time to current time.
70380f22571SIngo Molnar */
704bee18a23SThomas Gleixner if (!(ntpdata->time_status & STA_PLL) && (txc->status & STA_PLL))
705161b8ec2SThomas Gleixner ntpdata->time_reftime = __ktime_get_real_seconds();
70680f22571SIngo Molnar
707bee18a23SThomas Gleixner /* only set allowed bits */
708bee18a23SThomas Gleixner ntpdata->time_status &= STA_RONLY;
709bee18a23SThomas Gleixner ntpdata->time_status |= txc->status & ~STA_RONLY;
71080f22571SIngo Molnar }
711cd5398beSRichard Cochran
process_adjtimex_modes(struct ntp_data * ntpdata,const struct __kernel_timex * txc,s32 * time_tai)71268f66f97SThomas Gleixner static inline void process_adjtimex_modes(struct ntp_data *ntpdata, const struct __kernel_timex *txc,
713ead25417SDeepa Dinamani s32 *time_tai)
71480f22571SIngo Molnar {
71580f22571SIngo Molnar if (txc->modes & ADJ_STATUS)
716bee18a23SThomas Gleixner process_adj_status(ntpdata, txc);
71780f22571SIngo Molnar
71880f22571SIngo Molnar if (txc->modes & ADJ_NANO)
719bee18a23SThomas Gleixner ntpdata->time_status |= STA_NANO;
720e9629165SIngo Molnar
72180f22571SIngo Molnar if (txc->modes & ADJ_MICRO)
722bee18a23SThomas Gleixner ntpdata->time_status &= ~STA_NANO;
72380f22571SIngo Molnar
72480f22571SIngo Molnar if (txc->modes & ADJ_FREQUENCY) {
725161b8ec2SThomas Gleixner ntpdata->time_freq = txc->freq * PPM_SCALE;
726161b8ec2SThomas Gleixner ntpdata->time_freq = min(ntpdata->time_freq, MAXFREQ_SCALED);
727161b8ec2SThomas Gleixner ntpdata->time_freq = max(ntpdata->time_freq, -MAXFREQ_SCALED);
728a0581cdbSThomas Gleixner /* Update pps_freq */
72912850b46SThomas Gleixner pps_set_freq(ntpdata);
73080f22571SIngo Molnar }
73180f22571SIngo Molnar
73280f22571SIngo Molnar if (txc->modes & ADJ_MAXERROR)
7337891cf29SThomas Gleixner ntpdata->time_maxerror = clamp(txc->maxerror, 0, NTP_PHASE_LIMIT);
734e9629165SIngo Molnar
73580f22571SIngo Molnar if (txc->modes & ADJ_ESTERROR)
7367891cf29SThomas Gleixner ntpdata->time_esterror = clamp(txc->esterror, 0, NTP_PHASE_LIMIT);
73780f22571SIngo Molnar
73880f22571SIngo Molnar if (txc->modes & ADJ_TIMECONST) {
739d5143554SThomas Gleixner ntpdata->time_constant = clamp(txc->constant, 0, MAXTC);
740bee18a23SThomas Gleixner if (!(ntpdata->time_status & STA_NANO))
741d5143554SThomas Gleixner ntpdata->time_constant += 4;
742d5143554SThomas Gleixner ntpdata->time_constant = clamp(ntpdata->time_constant, 0, MAXTC);
74380f22571SIngo Molnar }
74480f22571SIngo Molnar
745bee18a23SThomas Gleixner if (txc->modes & ADJ_TAI && txc->constant >= 0 && txc->constant <= MAX_TAI_OFFSET)
746cc244ddaSJohn Stultz *time_tai = txc->constant;
74780f22571SIngo Molnar
74880f22571SIngo Molnar if (txc->modes & ADJ_OFFSET)
749bee18a23SThomas Gleixner ntp_update_offset(ntpdata, txc->offset);
750e9629165SIngo Molnar
75180f22571SIngo Molnar if (txc->modes & ADJ_TICK)
75268f66f97SThomas Gleixner ntpdata->tick_usec = txc->tick;
75380f22571SIngo Molnar
75480f22571SIngo Molnar if (txc->modes & (ADJ_TICK|ADJ_FREQUENCY|ADJ_OFFSET))
75568f66f97SThomas Gleixner ntp_update_frequency(ntpdata);
75680f22571SIngo Molnar }
75780f22571SIngo Molnar
758ad460967SJohn Stultz /*
759a0581cdbSThomas Gleixner * adjtimex() mainly allows reading (and writing, if superuser) of
760ad460967SJohn Stultz * kernel time-keeping variables. used by xntpd.
761ad460967SJohn Stultz */
__do_adjtimex(struct __kernel_timex * txc,const struct timespec64 * ts,s32 * time_tai,struct audit_ntp_data * ad)762ead25417SDeepa Dinamani int __do_adjtimex(struct __kernel_timex *txc, const struct timespec64 *ts,
7637e8eda73SOndrej Mosnacek s32 *time_tai, struct audit_ntp_data *ad)
764ad460967SJohn Stultz {
76568f66f97SThomas Gleixner struct ntp_data *ntpdata = &tk_ntp_data;
766ad460967SJohn Stultz int result;
767ad460967SJohn Stultz
768916c7a85SRoman Zippel if (txc->modes & ADJ_ADJTIME) {
769bb6400a2SThomas Gleixner long save_adjust = ntpdata->time_adjust;
770916c7a85SRoman Zippel
771916c7a85SRoman Zippel if (!(txc->modes & ADJ_OFFSET_READONLY)) {
772916c7a85SRoman Zippel /* adjtime() is independent from ntp_adjtime() */
773bb6400a2SThomas Gleixner ntpdata->time_adjust = txc->offset;
77468f66f97SThomas Gleixner ntp_update_frequency(ntpdata);
7757e8eda73SOndrej Mosnacek
7767e8eda73SOndrej Mosnacek audit_ntp_set_old(ad, AUDIT_NTP_ADJUST, save_adjust);
777bb6400a2SThomas Gleixner audit_ntp_set_new(ad, AUDIT_NTP_ADJUST, ntpdata->time_adjust);
778916c7a85SRoman Zippel }
779916c7a85SRoman Zippel txc->offset = save_adjust;
780e9629165SIngo Molnar } else {
78180f22571SIngo Molnar /* If there are input parameters, then process them: */
7827e8eda73SOndrej Mosnacek if (txc->modes) {
783d5143554SThomas Gleixner audit_ntp_set_old(ad, AUDIT_NTP_OFFSET, ntpdata->time_offset);
784161b8ec2SThomas Gleixner audit_ntp_set_old(ad, AUDIT_NTP_FREQ, ntpdata->time_freq);
785bee18a23SThomas Gleixner audit_ntp_set_old(ad, AUDIT_NTP_STATUS, ntpdata->time_status);
7867e8eda73SOndrej Mosnacek audit_ntp_set_old(ad, AUDIT_NTP_TAI, *time_tai);
78768f66f97SThomas Gleixner audit_ntp_set_old(ad, AUDIT_NTP_TICK, ntpdata->tick_usec);
7887e8eda73SOndrej Mosnacek
78968f66f97SThomas Gleixner process_adjtimex_modes(ntpdata, txc, time_tai);
790eea83d89SRoman Zippel
791d5143554SThomas Gleixner audit_ntp_set_new(ad, AUDIT_NTP_OFFSET, ntpdata->time_offset);
792161b8ec2SThomas Gleixner audit_ntp_set_new(ad, AUDIT_NTP_FREQ, ntpdata->time_freq);
793bee18a23SThomas Gleixner audit_ntp_set_new(ad, AUDIT_NTP_STATUS, ntpdata->time_status);
7947e8eda73SOndrej Mosnacek audit_ntp_set_new(ad, AUDIT_NTP_TAI, *time_tai);
79568f66f97SThomas Gleixner audit_ntp_set_new(ad, AUDIT_NTP_TICK, ntpdata->tick_usec);
7967e8eda73SOndrej Mosnacek }
7977e8eda73SOndrej Mosnacek
798d5143554SThomas Gleixner txc->offset = shift_right(ntpdata->time_offset * NTP_INTERVAL_FREQ, NTP_SCALE_SHIFT);
799bee18a23SThomas Gleixner if (!(ntpdata->time_status & STA_NANO))
800f5807b06SMarcelo Dalmas txc->offset = div_s64(txc->offset, NSEC_PER_USEC);
801e9629165SIngo Molnar }
802916c7a85SRoman Zippel
803bee18a23SThomas Gleixner result = ntpdata->time_state;
804bee18a23SThomas Gleixner if (is_error_status(ntpdata->time_status))
805916c7a85SRoman Zippel result = TIME_ERROR;
806916c7a85SRoman Zippel
807161b8ec2SThomas Gleixner txc->freq = shift_right((ntpdata->time_freq >> PPM_SCALE_INV_SHIFT) *
8082b9d1496SIngo Molnar PPM_SCALE_INV, NTP_SCALE_SHIFT);
8097891cf29SThomas Gleixner txc->maxerror = ntpdata->time_maxerror;
8107891cf29SThomas Gleixner txc->esterror = ntpdata->time_esterror;
811bee18a23SThomas Gleixner txc->status = ntpdata->time_status;
812d5143554SThomas Gleixner txc->constant = ntpdata->time_constant;
81370bc42f9SAdrian Bunk txc->precision = 1;
814074b3b87SRoman Zippel txc->tolerance = MAXFREQ_SCALED / PPM_SCALE;
81568f66f97SThomas Gleixner txc->tick = ntpdata->tick_usec;
81687ace39bSJohn Stultz txc->tai = *time_tai;
8174c7ee8deSjohn stultz
818a0581cdbSThomas Gleixner /* Fill PPS status fields */
819bee18a23SThomas Gleixner pps_fill_timex(ntpdata, txc);
820e9629165SIngo Molnar
8212f584134SArnd Bergmann txc->time.tv_sec = ts->tv_sec;
82287ace39bSJohn Stultz txc->time.tv_usec = ts->tv_nsec;
823bee18a23SThomas Gleixner if (!(ntpdata->time_status & STA_NANO))
824ead25417SDeepa Dinamani txc->time.tv_usec = ts->tv_nsec / NSEC_PER_USEC;
825ee9851b2SRoman Zippel
82696efdcf2SJohn Stultz /* Handle leapsec adjustments */
82775d956b9SThomas Gleixner if (unlikely(ts->tv_sec >= ntpdata->ntp_next_leap_sec)) {
828bee18a23SThomas Gleixner if ((ntpdata->time_state == TIME_INS) && (ntpdata->time_status & STA_INS)) {
82996efdcf2SJohn Stultz result = TIME_OOP;
83096efdcf2SJohn Stultz txc->tai++;
83196efdcf2SJohn Stultz txc->time.tv_sec--;
83296efdcf2SJohn Stultz }
833bee18a23SThomas Gleixner if ((ntpdata->time_state == TIME_DEL) && (ntpdata->time_status & STA_DEL)) {
83496efdcf2SJohn Stultz result = TIME_WAIT;
83596efdcf2SJohn Stultz txc->tai--;
83696efdcf2SJohn Stultz txc->time.tv_sec++;
83796efdcf2SJohn Stultz }
83875d956b9SThomas Gleixner if ((ntpdata->time_state == TIME_OOP) && (ts->tv_sec == ntpdata->ntp_next_leap_sec))
83996efdcf2SJohn Stultz result = TIME_WAIT;
84096efdcf2SJohn Stultz }
84196efdcf2SJohn Stultz
842ee9851b2SRoman Zippel return result;
8434c7ee8deSjohn stultz }
84410a398d0SRoman Zippel
845025b40abSAlexander Gordeev #ifdef CONFIG_NTP_PPS
846025b40abSAlexander Gordeev
847a0581cdbSThomas Gleixner /*
848a0581cdbSThomas Gleixner * struct pps_normtime is basically a struct timespec, but it is
849025b40abSAlexander Gordeev * semantically different (and it is the reason why it was invented):
850025b40abSAlexander Gordeev * pps_normtime.nsec has a range of ( -NSEC_PER_SEC / 2, NSEC_PER_SEC / 2 ]
851a0581cdbSThomas Gleixner * while timespec.tv_nsec has a range of [0, NSEC_PER_SEC)
852a0581cdbSThomas Gleixner */
853025b40abSAlexander Gordeev struct pps_normtime {
8547ec88e4bSArnd Bergmann s64 sec; /* seconds */
855025b40abSAlexander Gordeev long nsec; /* nanoseconds */
856025b40abSAlexander Gordeev };
857025b40abSAlexander Gordeev
858a0581cdbSThomas Gleixner /*
859a0581cdbSThomas Gleixner * Normalize the timestamp so that nsec is in the
860a0581cdbSThomas Gleixner * [ -NSEC_PER_SEC / 2, NSEC_PER_SEC / 2 ] interval
861a0581cdbSThomas Gleixner */
pps_normalize_ts(struct timespec64 ts)8627ec88e4bSArnd Bergmann static inline struct pps_normtime pps_normalize_ts(struct timespec64 ts)
863025b40abSAlexander Gordeev {
864025b40abSAlexander Gordeev struct pps_normtime norm = {
865025b40abSAlexander Gordeev .sec = ts.tv_sec,
866025b40abSAlexander Gordeev .nsec = ts.tv_nsec
867025b40abSAlexander Gordeev };
868025b40abSAlexander Gordeev
869025b40abSAlexander Gordeev if (norm.nsec > (NSEC_PER_SEC >> 1)) {
870025b40abSAlexander Gordeev norm.nsec -= NSEC_PER_SEC;
871025b40abSAlexander Gordeev norm.sec++;
872025b40abSAlexander Gordeev }
873025b40abSAlexander Gordeev
874025b40abSAlexander Gordeev return norm;
875025b40abSAlexander Gordeev }
876025b40abSAlexander Gordeev
877a0581cdbSThomas Gleixner /* Get current phase correction and jitter */
pps_phase_filter_get(struct ntp_data * ntpdata,long * jitter)8785cc953b8SThomas Gleixner static inline long pps_phase_filter_get(struct ntp_data *ntpdata, long *jitter)
879025b40abSAlexander Gordeev {
8805cc953b8SThomas Gleixner *jitter = ntpdata->pps_tf[0] - ntpdata->pps_tf[1];
881025b40abSAlexander Gordeev if (*jitter < 0)
882025b40abSAlexander Gordeev *jitter = -*jitter;
883025b40abSAlexander Gordeev
884025b40abSAlexander Gordeev /* TODO: test various filters */
8855cc953b8SThomas Gleixner return ntpdata->pps_tf[0];
886025b40abSAlexander Gordeev }
887025b40abSAlexander Gordeev
888a0581cdbSThomas Gleixner /* Add the sample to the phase filter */
pps_phase_filter_add(struct ntp_data * ntpdata,long err)8895cc953b8SThomas Gleixner static inline void pps_phase_filter_add(struct ntp_data *ntpdata, long err)
890025b40abSAlexander Gordeev {
8915cc953b8SThomas Gleixner ntpdata->pps_tf[2] = ntpdata->pps_tf[1];
8925cc953b8SThomas Gleixner ntpdata->pps_tf[1] = ntpdata->pps_tf[0];
8935cc953b8SThomas Gleixner ntpdata->pps_tf[0] = err;
894025b40abSAlexander Gordeev }
895025b40abSAlexander Gordeev
896a0581cdbSThomas Gleixner /*
897a0581cdbSThomas Gleixner * Decrease frequency calibration interval length. It is halved after four
898a0581cdbSThomas Gleixner * consecutive unstable intervals.
899025b40abSAlexander Gordeev */
pps_dec_freq_interval(struct ntp_data * ntpdata)900b1c89a76SThomas Gleixner static inline void pps_dec_freq_interval(struct ntp_data *ntpdata)
901025b40abSAlexander Gordeev {
902b1c89a76SThomas Gleixner if (--ntpdata->pps_intcnt <= -PPS_INTCOUNT) {
903b1c89a76SThomas Gleixner ntpdata->pps_intcnt = -PPS_INTCOUNT;
904b1c89a76SThomas Gleixner if (ntpdata->pps_shift > PPS_INTMIN) {
905b1c89a76SThomas Gleixner ntpdata->pps_shift--;
906b1c89a76SThomas Gleixner ntpdata->pps_intcnt = 0;
907025b40abSAlexander Gordeev }
908025b40abSAlexander Gordeev }
909025b40abSAlexander Gordeev }
910025b40abSAlexander Gordeev
911a0581cdbSThomas Gleixner /*
912a0581cdbSThomas Gleixner * Increase frequency calibration interval length. It is doubled after
913a0581cdbSThomas Gleixner * four consecutive stable intervals.
914025b40abSAlexander Gordeev */
pps_inc_freq_interval(struct ntp_data * ntpdata)915b1c89a76SThomas Gleixner static inline void pps_inc_freq_interval(struct ntp_data *ntpdata)
916025b40abSAlexander Gordeev {
917b1c89a76SThomas Gleixner if (++ntpdata->pps_intcnt >= PPS_INTCOUNT) {
918b1c89a76SThomas Gleixner ntpdata->pps_intcnt = PPS_INTCOUNT;
919b1c89a76SThomas Gleixner if (ntpdata->pps_shift < PPS_INTMAX) {
920b1c89a76SThomas Gleixner ntpdata->pps_shift++;
921b1c89a76SThomas Gleixner ntpdata->pps_intcnt = 0;
922025b40abSAlexander Gordeev }
923025b40abSAlexander Gordeev }
924025b40abSAlexander Gordeev }
925025b40abSAlexander Gordeev
926a0581cdbSThomas Gleixner /*
927a0581cdbSThomas Gleixner * Update clock frequency based on MONOTONIC_RAW clock PPS signal
928025b40abSAlexander Gordeev * timestamps
929025b40abSAlexander Gordeev *
930025b40abSAlexander Gordeev * At the end of the calibration interval the difference between the
931025b40abSAlexander Gordeev * first and last MONOTONIC_RAW clock timestamps divided by the length
932025b40abSAlexander Gordeev * of the interval becomes the frequency update. If the interval was
933025b40abSAlexander Gordeev * too long, the data are discarded.
934025b40abSAlexander Gordeev * Returns the difference between old and new frequency values.
935025b40abSAlexander Gordeev */
hardpps_update_freq(struct ntp_data * ntpdata,struct pps_normtime freq_norm)93668f66f97SThomas Gleixner static long hardpps_update_freq(struct ntp_data *ntpdata, struct pps_normtime freq_norm)
937025b40abSAlexander Gordeev {
938025b40abSAlexander Gordeev long delta, delta_mod;
939025b40abSAlexander Gordeev s64 ftemp;
940025b40abSAlexander Gordeev
941a0581cdbSThomas Gleixner /* Check if the frequency interval was too long */
942b1c89a76SThomas Gleixner if (freq_norm.sec > (2 << ntpdata->pps_shift)) {
943bee18a23SThomas Gleixner ntpdata->time_status |= STA_PPSERROR;
9446fadb4a6SThomas Gleixner ntpdata->pps_errcnt++;
945b1c89a76SThomas Gleixner pps_dec_freq_interval(ntpdata);
94638007dc0SAnna-Maria Behnsen printk_deferred(KERN_ERR "hardpps: PPSERROR: interval too long - %lld s\n",
947025b40abSAlexander Gordeev freq_norm.sec);
948025b40abSAlexander Gordeev return 0;
949025b40abSAlexander Gordeev }
950025b40abSAlexander Gordeev
951a0581cdbSThomas Gleixner /*
952a0581cdbSThomas Gleixner * Here the raw frequency offset and wander (stability) is
953a0581cdbSThomas Gleixner * calculated. If the wander is less than the wander threshold the
954a0581cdbSThomas Gleixner * interval is increased; otherwise it is decreased.
955025b40abSAlexander Gordeev */
956025b40abSAlexander Gordeev ftemp = div_s64(((s64)(-freq_norm.nsec)) << NTP_SCALE_SHIFT,
957025b40abSAlexander Gordeev freq_norm.sec);
95812850b46SThomas Gleixner delta = shift_right(ftemp - ntpdata->pps_freq, NTP_SCALE_SHIFT);
95912850b46SThomas Gleixner ntpdata->pps_freq = ftemp;
960025b40abSAlexander Gordeev if (delta > PPS_MAXWANDER || delta < -PPS_MAXWANDER) {
96138007dc0SAnna-Maria Behnsen printk_deferred(KERN_WARNING "hardpps: PPSWANDER: change=%ld\n", delta);
962bee18a23SThomas Gleixner ntpdata->time_status |= STA_PPSWANDER;
9636fadb4a6SThomas Gleixner ntpdata->pps_stbcnt++;
964b1c89a76SThomas Gleixner pps_dec_freq_interval(ntpdata);
965a0581cdbSThomas Gleixner } else {
966a0581cdbSThomas Gleixner /* Good sample */
967b1c89a76SThomas Gleixner pps_inc_freq_interval(ntpdata);
968025b40abSAlexander Gordeev }
969025b40abSAlexander Gordeev
970a0581cdbSThomas Gleixner /*
971a0581cdbSThomas Gleixner * The stability metric is calculated as the average of recent
972a0581cdbSThomas Gleixner * frequency changes, but is used only for performance monitoring
973025b40abSAlexander Gordeev */
974025b40abSAlexander Gordeev delta_mod = delta;
975025b40abSAlexander Gordeev if (delta_mod < 0)
976025b40abSAlexander Gordeev delta_mod = -delta_mod;
97712850b46SThomas Gleixner ntpdata->pps_stabil += (div_s64(((s64)delta_mod) << (NTP_SCALE_SHIFT - SHIFT_USEC),
97812850b46SThomas Gleixner NSEC_PER_USEC) - ntpdata->pps_stabil) >> PPS_INTMIN;
979025b40abSAlexander Gordeev
980a0581cdbSThomas Gleixner /* If enabled, the system clock frequency is updated */
981bee18a23SThomas Gleixner if ((ntpdata->time_status & STA_PPSFREQ) && !(ntpdata->time_status & STA_FREQHOLD)) {
98212850b46SThomas Gleixner ntpdata->time_freq = ntpdata->pps_freq;
98368f66f97SThomas Gleixner ntp_update_frequency(ntpdata);
984025b40abSAlexander Gordeev }
985025b40abSAlexander Gordeev
986025b40abSAlexander Gordeev return delta;
987025b40abSAlexander Gordeev }
988025b40abSAlexander Gordeev
989a0581cdbSThomas Gleixner /* Correct REALTIME clock phase error against PPS signal */
hardpps_update_phase(struct ntp_data * ntpdata,long error)990bee18a23SThomas Gleixner static void hardpps_update_phase(struct ntp_data *ntpdata, long error)
991025b40abSAlexander Gordeev {
992025b40abSAlexander Gordeev long correction = -error;
993025b40abSAlexander Gordeev long jitter;
994025b40abSAlexander Gordeev
995a0581cdbSThomas Gleixner /* Add the sample to the median filter */
9965cc953b8SThomas Gleixner pps_phase_filter_add(ntpdata, correction);
9975cc953b8SThomas Gleixner correction = pps_phase_filter_get(ntpdata, &jitter);
998025b40abSAlexander Gordeev
999a0581cdbSThomas Gleixner /*
1000a0581cdbSThomas Gleixner * Nominal jitter is due to PPS signal noise. If it exceeds the
1001025b40abSAlexander Gordeev * threshold, the sample is discarded; otherwise, if so enabled,
1002025b40abSAlexander Gordeev * the time offset is updated.
1003025b40abSAlexander Gordeev */
10049d7130dfSThomas Gleixner if (jitter > (ntpdata->pps_jitter << PPS_POPCORN)) {
100538007dc0SAnna-Maria Behnsen printk_deferred(KERN_WARNING "hardpps: PPSJITTER: jitter=%ld, limit=%ld\n",
10069d7130dfSThomas Gleixner jitter, (ntpdata->pps_jitter << PPS_POPCORN));
1007bee18a23SThomas Gleixner ntpdata->time_status |= STA_PPSJITTER;
10086fadb4a6SThomas Gleixner ntpdata->pps_jitcnt++;
1009bee18a23SThomas Gleixner } else if (ntpdata->time_status & STA_PPSTIME) {
1010a0581cdbSThomas Gleixner /* Correct the time using the phase offset */
1011d5143554SThomas Gleixner ntpdata->time_offset = div_s64(((s64)correction) << NTP_SCALE_SHIFT,
1012d5143554SThomas Gleixner NTP_INTERVAL_FREQ);
1013a0581cdbSThomas Gleixner /* Cancel running adjtime() */
1014bb6400a2SThomas Gleixner ntpdata->time_adjust = 0;
1015025b40abSAlexander Gordeev }
1016a0581cdbSThomas Gleixner /* Update jitter */
10179d7130dfSThomas Gleixner ntpdata->pps_jitter += (jitter - ntpdata->pps_jitter) >> PPS_INTMIN;
1018025b40abSAlexander Gordeev }
1019025b40abSAlexander Gordeev
1020025b40abSAlexander Gordeev /*
1021aa6f9c59SJohn Stultz * __hardpps() - discipline CPU clock oscillator to external PPS signal
1022025b40abSAlexander Gordeev *
1023025b40abSAlexander Gordeev * This routine is called at each PPS signal arrival in order to
1024025b40abSAlexander Gordeev * discipline the CPU clock oscillator to the PPS signal. It takes two
1025025b40abSAlexander Gordeev * parameters: REALTIME and MONOTONIC_RAW clock timestamps. The former
1026025b40abSAlexander Gordeev * is used to correct clock phase error and the latter is used to
1027025b40abSAlexander Gordeev * correct the frequency.
1028025b40abSAlexander Gordeev *
1029025b40abSAlexander Gordeev * This code is based on David Mills's reference nanokernel
1030025b40abSAlexander Gordeev * implementation. It was mostly rewritten but keeps the same idea.
1031025b40abSAlexander Gordeev */
__hardpps(const struct timespec64 * phase_ts,const struct timespec64 * raw_ts)10327ec88e4bSArnd Bergmann void __hardpps(const struct timespec64 *phase_ts, const struct timespec64 *raw_ts)
1033025b40abSAlexander Gordeev {
1034025b40abSAlexander Gordeev struct pps_normtime pts_norm, freq_norm;
103568f66f97SThomas Gleixner struct ntp_data *ntpdata = &tk_ntp_data;
1036025b40abSAlexander Gordeev
1037025b40abSAlexander Gordeev pts_norm = pps_normalize_ts(*phase_ts);
1038025b40abSAlexander Gordeev
1039a0581cdbSThomas Gleixner /* Clear the error bits, they will be set again if needed */
1040bee18a23SThomas Gleixner ntpdata->time_status &= ~(STA_PPSJITTER | STA_PPSWANDER | STA_PPSERROR);
1041025b40abSAlexander Gordeev
1042bee18a23SThomas Gleixner /* indicate signal presence */
1043bee18a23SThomas Gleixner ntpdata->time_status |= STA_PPSSIGNAL;
1044931a177fSThomas Gleixner ntpdata->pps_valid = PPS_VALID;
1045025b40abSAlexander Gordeev
1046a0581cdbSThomas Gleixner /*
1047a0581cdbSThomas Gleixner * When called for the first time, just start the frequency
1048a0581cdbSThomas Gleixner * interval
1049a0581cdbSThomas Gleixner */
1050db45e9bcSThomas Gleixner if (unlikely(ntpdata->pps_fbase.tv_sec == 0)) {
1051db45e9bcSThomas Gleixner ntpdata->pps_fbase = *raw_ts;
1052025b40abSAlexander Gordeev return;
1053025b40abSAlexander Gordeev }
1054025b40abSAlexander Gordeev
1055a0581cdbSThomas Gleixner /* Ok, now we have a base for frequency calculation */
1056db45e9bcSThomas Gleixner freq_norm = pps_normalize_ts(timespec64_sub(*raw_ts, ntpdata->pps_fbase));
1057025b40abSAlexander Gordeev
1058a0581cdbSThomas Gleixner /*
1059a0581cdbSThomas Gleixner * Check that the signal is in the range
1060a0581cdbSThomas Gleixner * [1s - MAXFREQ us, 1s + MAXFREQ us], otherwise reject it
1061a0581cdbSThomas Gleixner */
106238007dc0SAnna-Maria Behnsen if ((freq_norm.sec == 0) || (freq_norm.nsec > MAXFREQ * freq_norm.sec) ||
1063025b40abSAlexander Gordeev (freq_norm.nsec < -MAXFREQ * freq_norm.sec)) {
1064bee18a23SThomas Gleixner ntpdata->time_status |= STA_PPSJITTER;
1065a0581cdbSThomas Gleixner /* Restart the frequency calibration interval */
1066db45e9bcSThomas Gleixner ntpdata->pps_fbase = *raw_ts;
10676d9bcb62SJohn Stultz printk_deferred(KERN_ERR "hardpps: PPSJITTER: bad pulse\n");
1068025b40abSAlexander Gordeev return;
1069025b40abSAlexander Gordeev }
1070025b40abSAlexander Gordeev
1071a0581cdbSThomas Gleixner /* Signal is ok. Check if the current frequency interval is finished */
1072b1c89a76SThomas Gleixner if (freq_norm.sec >= (1 << ntpdata->pps_shift)) {
10736fadb4a6SThomas Gleixner ntpdata->pps_calcnt++;
1074a0581cdbSThomas Gleixner /* Restart the frequency calibration interval */
1075db45e9bcSThomas Gleixner ntpdata->pps_fbase = *raw_ts;
107668f66f97SThomas Gleixner hardpps_update_freq(ntpdata, freq_norm);
1077025b40abSAlexander Gordeev }
1078025b40abSAlexander Gordeev
1079bee18a23SThomas Gleixner hardpps_update_phase(ntpdata, pts_norm.nsec);
1080025b40abSAlexander Gordeev
1081025b40abSAlexander Gordeev }
1082025b40abSAlexander Gordeev #endif /* CONFIG_NTP_PPS */
1083025b40abSAlexander Gordeev
ntp_tick_adj_setup(char * str)108410a398d0SRoman Zippel static int __init ntp_tick_adj_setup(char *str)
108510a398d0SRoman Zippel {
1086bb6400a2SThomas Gleixner int rc = kstrtos64(str, 0, &tk_ntp_data.ntp_tick_adj);
1087cdafb93fSFabian Frederick if (rc)
1088cdafb93fSFabian Frederick return rc;
1089069569e0SIngo Molnar
1090bb6400a2SThomas Gleixner tk_ntp_data.ntp_tick_adj <<= NTP_SCALE_SHIFT;
109110a398d0SRoman Zippel return 1;
109210a398d0SRoman Zippel }
109310a398d0SRoman Zippel
109410a398d0SRoman Zippel __setup("ntp_tick_adj=", ntp_tick_adj_setup);
10957dffa3c6SRoman Zippel
ntp_init(void)10967dffa3c6SRoman Zippel void __init ntp_init(void)
10977dffa3c6SRoman Zippel {
10987dffa3c6SRoman Zippel ntp_clear();
1099c9e6189fSThomas Gleixner ntp_init_cmos_sync();
11007dffa3c6SRoman Zippel }
1101