Blame view

kernel/time/ntp.c 25.6 KB
4c7ee8de9   John Stultz   [PATCH] NTP: Move...
1
  /*
4c7ee8de9   John Stultz   [PATCH] NTP: Move...
2
3
4
5
6
7
   * NTP state machine interfaces and logic.
   *
   * This code was mainly moved from kernel/timer.c and kernel/time.c
   * Please see those files for relevant copyright info and historical
   * changelogs.
   */
aa0ac3651   Alexey Dobriyan   Remove capability...
8
  #include <linux/capability.h>
7dffa3c67   Roman Zippel   ntp: handle leap ...
9
  #include <linux/clocksource.h>
eb3f938fd   Maciej W. Rozycki   ntp: let update_p...
10
  #include <linux/workqueue.h>
53bbfa9e9   Ingo Molnar   time: ntp: clean ...
11
12
13
14
15
16
  #include <linux/hrtimer.h>
  #include <linux/jiffies.h>
  #include <linux/math64.h>
  #include <linux/timex.h>
  #include <linux/time.h>
  #include <linux/mm.h>
025b40abe   Alexander Gordeev   ntp: add hardpps ...
17
  #include <linux/module.h>
023f333a9   Jason Gunthorpe   NTP: Add a CONFIG...
18
  #include <linux/rtc.h>
c79634877   DengChao   ntp: Fix second_o...
19
  #include <linux/math64.h>
4c7ee8de9   John Stultz   [PATCH] NTP: Move...
20

aa6f9c595   John Stultz   ntp: Move do_adjt...
21
  #include "ntp_internal.h"
0af864651   DengChao   ntp: Change time_...
22
  #include "timekeeping_internal.h"
e2830b5c1   Torben Hohn   time: Make do_tim...
23

b0ee75561   Roman Zippel   [PATCH] ntp: add ...
24
  /*
53bbfa9e9   Ingo Molnar   time: ntp: clean ...
25
   * NTP timekeeping variables:
a076b2146   John Stultz   ntp: Remove ntp_l...
26
27
   *
   * Note: All of the NTP state is protected by the timekeeping locks.
b0ee75561   Roman Zippel   [PATCH] ntp: add ...
28
   */
b0ee75561   Roman Zippel   [PATCH] ntp: add ...
29

bd3312681   John Stultz   ntp: Add ntp_lock...
30

53bbfa9e9   Ingo Molnar   time: ntp: clean ...
31
32
  /* USER_HZ period (usecs): */
  unsigned long			tick_usec = TICK_USEC;
02ab20ae3   John Stultz   time/jiffies: Ren...
33
  /* SHIFTED_HZ period (nsecs): */
53bbfa9e9   Ingo Molnar   time: ntp: clean ...
34
  unsigned long			tick_nsec;
7dffa3c67   Roman Zippel   ntp: handle leap ...
35

ea7cf49a7   John Stultz   ntp: Access tick_...
36
  static u64			tick_length;
53bbfa9e9   Ingo Molnar   time: ntp: clean ...
37
  static u64			tick_length_base;
90bf361ce   John Stultz   ntp: Introduce an...
38
  #define SECS_PER_DAY		86400
bbd126769   Ingo Molnar   time: ntp: simpli...
39
  #define MAX_TICKADJ		500LL		/* usecs */
53bbfa9e9   Ingo Molnar   time: ntp: clean ...
40
  #define MAX_TICKADJ_SCALED \
bbd126769   Ingo Molnar   time: ntp: simpli...
41
  	(((MAX_TICKADJ * NSEC_PER_USEC) << NTP_SCALE_SHIFT) / NTP_INTERVAL_FREQ)
4c7ee8de9   John Stultz   [PATCH] NTP: Move...
42
43
44
45
  
  /*
   * phase-lock loop variables
   */
53bbfa9e9   Ingo Molnar   time: ntp: clean ...
46
47
48
49
50
51
52
53
54
  
  /*
   * clock synchronization status
   *
   * (TIME_ERROR prevents overwriting the CMOS clock)
   */
  static int			time_state = TIME_OK;
  
  /* clock status bits:							*/
8357929e6   John Stultz   ntp: Cleanup timex.h
55
  static int			time_status = STA_UNSYNC;
53bbfa9e9   Ingo Molnar   time: ntp: clean ...
56

53bbfa9e9   Ingo Molnar   time: ntp: clean ...
57
58
59
60
61
62
63
  /* time adjustment (nsecs):						*/
  static s64			time_offset;
  
  /* pll time constant:							*/
  static long			time_constant = 2;
  
  /* maximum error (usecs):						*/
1f5b8f8a2   John Stultz   ntp: Make time_es...
64
  static long			time_maxerror = NTP_PHASE_LIMIT;
53bbfa9e9   Ingo Molnar   time: ntp: clean ...
65
66
  
  /* estimated error (usecs):						*/
1f5b8f8a2   John Stultz   ntp: Make time_es...
67
  static long			time_esterror = NTP_PHASE_LIMIT;
53bbfa9e9   Ingo Molnar   time: ntp: clean ...
68
69
70
71
72
  
  /* frequency offset (scaled nsecs/secs):				*/
  static s64			time_freq;
  
  /* time at last adjustment (secs):					*/
0af864651   DengChao   ntp: Change time_...
73
  static time64_t		time_reftime;
53bbfa9e9   Ingo Molnar   time: ntp: clean ...
74

e1292ba16   John Stultz   ntp: Make time_ad...
75
  static long			time_adjust;
53bbfa9e9   Ingo Molnar   time: ntp: clean ...
76

069569e02   Ingo Molnar   time: ntp: simpli...
77
78
  /* constant (boot-param configurable) NTP tick adjustment (upscaled)	*/
  static s64			ntp_tick_adj;
53bbfa9e9   Ingo Molnar   time: ntp: clean ...
79

833f32d76   John Stultz   time: Prevent ear...
80
81
  /* second value of the next pending leapsecond, or TIME64_MAX if no leap */
  static time64_t			ntp_next_leap_sec = TIME64_MAX;
025b40abe   Alexander Gordeev   ntp: add hardpps ...
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
  #ifdef CONFIG_NTP_PPS
  
  /*
   * The following variables are used when a pulse-per-second (PPS) signal
   * is available. They establish the engineering parameters of the clock
   * discipline loop when controlled by the PPS signal.
   */
  #define PPS_VALID	10	/* PPS signal watchdog max (s) */
  #define PPS_POPCORN	4	/* popcorn spike threshold (shift) */
  #define PPS_INTMIN	2	/* min freq interval (s) (shift) */
  #define PPS_INTMAX	8	/* max freq interval (s) (shift) */
  #define PPS_INTCOUNT	4	/* number of consecutive good intervals to
  				   increase pps_shift or consecutive bad
  				   intervals to decrease it */
  #define PPS_MAXWANDER	100000	/* max PPS freq wander (ns/s) */
  
  static int pps_valid;		/* signal watchdog counter */
  static long pps_tf[3];		/* phase median filter */
  static long pps_jitter;		/* current jitter (ns) */
7ec88e4be   Arnd Bergmann   ntp/pps: use time...
101
  static struct timespec64 pps_fbase; /* beginning of the last freq interval */
025b40abe   Alexander Gordeev   ntp: add hardpps ...
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
  static int pps_shift;		/* current interval duration (s) (shift) */
  static int pps_intcnt;		/* interval counter */
  static s64 pps_freq;		/* frequency offset (scaled ns/s) */
  static long pps_stabil;		/* current stability (scaled ns/s) */
  
  /*
   * PPS signal quality monitors
   */
  static long pps_calcnt;		/* calibration intervals */
  static long pps_jitcnt;		/* jitter limit exceeded */
  static long pps_stbcnt;		/* stability limit exceeded */
  static long pps_errcnt;		/* calibration errors */
  
  
  /* PPS kernel consumer compensates the whole phase error immediately.
   * Otherwise, reduce the offset by a fixed factor times the time constant.
   */
  static inline s64 ntp_offset_chunk(s64 offset)
  {
  	if (time_status & STA_PPSTIME && time_status & STA_PPSSIGNAL)
  		return offset;
  	else
  		return shift_right(offset, SHIFT_PLL + time_constant);
  }
  
  static inline void pps_reset_freq_interval(void)
  {
  	/* the PPS calibration interval may end
  	   surprisingly early */
  	pps_shift = PPS_INTMIN;
  	pps_intcnt = 0;
  }
  
  /**
   * pps_clear - Clears the PPS state variables
025b40abe   Alexander Gordeev   ntp: add hardpps ...
137
138
139
140
141
142
143
144
145
146
147
148
149
150
   */
  static inline void pps_clear(void)
  {
  	pps_reset_freq_interval();
  	pps_tf[0] = 0;
  	pps_tf[1] = 0;
  	pps_tf[2] = 0;
  	pps_fbase.tv_sec = pps_fbase.tv_nsec = 0;
  	pps_freq = 0;
  }
  
  /* Decrease pps_valid to indicate that another second has passed since
   * the last PPS signal. When it reaches 0, indicate that PPS signal is
   * missing.
025b40abe   Alexander Gordeev   ntp: add hardpps ...
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
   */
  static inline void pps_dec_valid(void)
  {
  	if (pps_valid > 0)
  		pps_valid--;
  	else {
  		time_status &= ~(STA_PPSSIGNAL | STA_PPSJITTER |
  				 STA_PPSWANDER | STA_PPSERROR);
  		pps_clear();
  	}
  }
  
  static inline void pps_set_freq(s64 freq)
  {
  	pps_freq = freq;
  }
  
  static inline int is_error_status(int status)
  {
ea54bca3a   George Spelvin   ntp: Make is_erro...
170
  	return (status & (STA_UNSYNC|STA_CLOCKERR))
025b40abe   Alexander Gordeev   ntp: add hardpps ...
171
172
173
  		/* PPS signal lost when either PPS time or
  		 * PPS frequency synchronization requested
  		 */
ea54bca3a   George Spelvin   ntp: Make is_erro...
174
175
  		|| ((status & (STA_PPSFREQ|STA_PPSTIME))
  			&& !(status & STA_PPSSIGNAL))
025b40abe   Alexander Gordeev   ntp: add hardpps ...
176
177
  		/* PPS jitter exceeded when
  		 * PPS time synchronization requested */
ea54bca3a   George Spelvin   ntp: Make is_erro...
178
  		|| ((status & (STA_PPSTIME|STA_PPSJITTER))
025b40abe   Alexander Gordeev   ntp: add hardpps ...
179
180
181
182
  			== (STA_PPSTIME|STA_PPSJITTER))
  		/* PPS wander exceeded or calibration error when
  		 * PPS frequency synchronization requested
  		 */
ea54bca3a   George Spelvin   ntp: Make is_erro...
183
184
  		|| ((status & STA_PPSFREQ)
  			&& (status & (STA_PPSWANDER|STA_PPSERROR)));
025b40abe   Alexander Gordeev   ntp: add hardpps ...
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
  }
  
  static inline void pps_fill_timex(struct timex *txc)
  {
  	txc->ppsfreq	   = shift_right((pps_freq >> PPM_SCALE_INV_SHIFT) *
  					 PPM_SCALE_INV, NTP_SCALE_SHIFT);
  	txc->jitter	   = pps_jitter;
  	if (!(time_status & STA_NANO))
  		txc->jitter /= NSEC_PER_USEC;
  	txc->shift	   = pps_shift;
  	txc->stabil	   = pps_stabil;
  	txc->jitcnt	   = pps_jitcnt;
  	txc->calcnt	   = pps_calcnt;
  	txc->errcnt	   = pps_errcnt;
  	txc->stbcnt	   = pps_stbcnt;
  }
  
  #else /* !CONFIG_NTP_PPS */
  
  static inline s64 ntp_offset_chunk(s64 offset)
  {
  	return shift_right(offset, SHIFT_PLL + time_constant);
  }
  
  static inline void pps_reset_freq_interval(void) {}
  static inline void pps_clear(void) {}
  static inline void pps_dec_valid(void) {}
  static inline void pps_set_freq(s64 freq) {}
  
  static inline int is_error_status(int status)
  {
  	return status & (STA_UNSYNC|STA_CLOCKERR);
  }
  
  static inline void pps_fill_timex(struct timex *txc)
  {
  	/* PPS is not implemented, so these are zero */
  	txc->ppsfreq	   = 0;
  	txc->jitter	   = 0;
  	txc->shift	   = 0;
  	txc->stabil	   = 0;
  	txc->jitcnt	   = 0;
  	txc->calcnt	   = 0;
  	txc->errcnt	   = 0;
  	txc->stbcnt	   = 0;
  }
  
  #endif /* CONFIG_NTP_PPS */
8357929e6   John Stultz   ntp: Cleanup timex.h
233
234
235
236
237
238
239
240
241
  
  /**
   * ntp_synced - Returns 1 if the NTP status is not UNSYNC
   *
   */
  static inline int ntp_synced(void)
  {
  	return !(time_status & STA_UNSYNC);
  }
53bbfa9e9   Ingo Molnar   time: ntp: clean ...
242
243
244
  /*
   * NTP methods:
   */
4c7ee8de9   John Stultz   [PATCH] NTP: Move...
245

9ce616aae   Ingo Molnar   time: ntp: clean ...
246
247
248
249
  /*
   * Update (tick_length, tick_length_base, tick_nsec), based
   * on (tick_usec, ntp_tick_adj, time_freq):
   */
70bc42f90   Adrian Bunk   [PATCH] kernel/ti...
250
251
  static void ntp_update_frequency(void)
  {
9ce616aae   Ingo Molnar   time: ntp: clean ...
252
  	u64 second_length;
bc26c31d4   Ingo Molnar   time: ntp: refact...
253
  	u64 new_base;
9ce616aae   Ingo Molnar   time: ntp: clean ...
254
255
256
  
  	second_length		 = (u64)(tick_usec * NSEC_PER_USEC * USER_HZ)
  						<< NTP_SCALE_SHIFT;
069569e02   Ingo Molnar   time: ntp: simpli...
257
  	second_length		+= ntp_tick_adj;
9ce616aae   Ingo Molnar   time: ntp: clean ...
258
  	second_length		+= time_freq;
70bc42f90   Adrian Bunk   [PATCH] kernel/ti...
259

9ce616aae   Ingo Molnar   time: ntp: clean ...
260
  	tick_nsec		 = div_u64(second_length, HZ) >> NTP_SCALE_SHIFT;
bc26c31d4   Ingo Molnar   time: ntp: refact...
261
  	new_base		 = div_u64(second_length, NTP_INTERVAL_FREQ);
fdcedf7b7   John Stultz   time: apply NTP f...
262
263
264
  
  	/*
  	 * Don't wait for the next second_overflow, apply
bc26c31d4   Ingo Molnar   time: ntp: refact...
265
  	 * the change to the tick length immediately:
fdcedf7b7   John Stultz   time: apply NTP f...
266
  	 */
bc26c31d4   Ingo Molnar   time: ntp: refact...
267
268
  	tick_length		+= new_base - tick_length_base;
  	tick_length_base	 = new_base;
70bc42f90   Adrian Bunk   [PATCH] kernel/ti...
269
  }
478b7aab1   Ingo Molnar   time: ntp: simpli...
270
  static inline s64 ntp_update_offset_fll(s64 offset64, long secs)
f939890b6   Ingo Molnar   time: ntp: refact...
271
272
273
274
  {
  	time_status &= ~STA_MODE;
  
  	if (secs < MINSEC)
478b7aab1   Ingo Molnar   time: ntp: simpli...
275
  		return 0;
f939890b6   Ingo Molnar   time: ntp: refact...
276
277
  
  	if (!(time_status & STA_FLL) && (secs <= MAXSEC))
478b7aab1   Ingo Molnar   time: ntp: simpli...
278
  		return 0;
f939890b6   Ingo Molnar   time: ntp: refact...
279

f939890b6   Ingo Molnar   time: ntp: refact...
280
  	time_status |= STA_MODE;
a078c6d0e   Sasha Levin   ntp: Fix integer ...
281
  	return div64_long(offset64 << (NTP_SCALE_SHIFT - SHIFT_FLL), secs);
f939890b6   Ingo Molnar   time: ntp: refact...
282
  }
ee9851b21   Roman Zippel   ntp: cleanup ntp.c
283
284
  static void ntp_update_offset(long offset)
  {
ee9851b21   Roman Zippel   ntp: cleanup ntp.c
285
  	s64 freq_adj;
f939890b6   Ingo Molnar   time: ntp: refact...
286
287
  	s64 offset64;
  	long secs;
ee9851b21   Roman Zippel   ntp: cleanup ntp.c
288
289
290
  
  	if (!(time_status & STA_PLL))
  		return;
52d189f1b   Sasha Levin   ntp: Verify offse...
291
292
293
  	if (!(time_status & STA_NANO)) {
  		/* Make sure the multiplication below won't overflow */
  		offset = clamp(offset, -USEC_PER_SEC, USEC_PER_SEC);
9f14f669d   Roman Zippel   ntp: increase tim...
294
  		offset *= NSEC_PER_USEC;
52d189f1b   Sasha Levin   ntp: Verify offse...
295
  	}
ee9851b21   Roman Zippel   ntp: cleanup ntp.c
296
297
298
299
300
  
  	/*
  	 * Scale the phase adjustment and
  	 * clamp to the operating range.
  	 */
52d189f1b   Sasha Levin   ntp: Verify offse...
301
  	offset = clamp(offset, -MAXPHASE, MAXPHASE);
ee9851b21   Roman Zippel   ntp: cleanup ntp.c
302
303
304
305
306
  
  	/*
  	 * Select how the frequency is to be controlled
  	 * and in which mode (PLL or FLL).
  	 */
0af864651   DengChao   ntp: Change time_...
307
  	secs = (long)(__ktime_get_real_seconds() - time_reftime);
10dd31a7a   Ingo Molnar   time: ntp: fix bu...
308
  	if (unlikely(time_status & STA_FREQHOLD))
c7986acba   Ingo Molnar   time: ntp: micro-...
309
  		secs = 0;
0af864651   DengChao   ntp: Change time_...
310
  	time_reftime = __ktime_get_real_seconds();
ee9851b21   Roman Zippel   ntp: cleanup ntp.c
311

f939890b6   Ingo Molnar   time: ntp: refact...
312
  	offset64    = offset;
8af3c153b   Miroslav Lichvar   ntp: Clamp PLL up...
313
  	freq_adj    = ntp_update_offset_fll(offset64, secs);
f939890b6   Ingo Molnar   time: ntp: refact...
314

8af3c153b   Miroslav Lichvar   ntp: Clamp PLL up...
315
316
317
318
319
320
321
322
323
324
  	/*
  	 * Clamp update interval to reduce PLL gain with low
  	 * sampling rate (e.g. intermittent network connection)
  	 * to avoid instability.
  	 */
  	if (unlikely(secs > 1 << (SHIFT_PLL + 1 + time_constant)))
  		secs = 1 << (SHIFT_PLL + 1 + time_constant);
  
  	freq_adj    += (offset64 * secs) <<
  			(NTP_SCALE_SHIFT - 2 * (SHIFT_PLL + 2 + time_constant));
f939890b6   Ingo Molnar   time: ntp: refact...
325
326
327
328
329
330
  
  	freq_adj    = min(freq_adj + time_freq, MAXFREQ_SCALED);
  
  	time_freq   = max(freq_adj, -MAXFREQ_SCALED);
  
  	time_offset = div_s64(offset64 << NTP_SCALE_SHIFT, NTP_INTERVAL_FREQ);
ee9851b21   Roman Zippel   ntp: cleanup ntp.c
331
  }
b0ee75561   Roman Zippel   [PATCH] ntp: add ...
332
333
  /**
   * ntp_clear - Clears the NTP state variables
b0ee75561   Roman Zippel   [PATCH] ntp: add ...
334
335
336
   */
  void ntp_clear(void)
  {
53bbfa9e9   Ingo Molnar   time: ntp: clean ...
337
338
339
340
  	time_adjust	= 0;		/* stop active adjtime() */
  	time_status	|= STA_UNSYNC;
  	time_maxerror	= NTP_PHASE_LIMIT;
  	time_esterror	= NTP_PHASE_LIMIT;
b0ee75561   Roman Zippel   [PATCH] ntp: add ...
341
342
  
  	ntp_update_frequency();
53bbfa9e9   Ingo Molnar   time: ntp: clean ...
343
344
  	tick_length	= tick_length_base;
  	time_offset	= 0;
025b40abe   Alexander Gordeev   ntp: add hardpps ...
345

833f32d76   John Stultz   time: Prevent ear...
346
  	ntp_next_leap_sec = TIME64_MAX;
025b40abe   Alexander Gordeev   ntp: add hardpps ...
347
348
  	/* Clear PPS state variables */
  	pps_clear();
b0ee75561   Roman Zippel   [PATCH] ntp: add ...
349
  }
ea7cf49a7   John Stultz   ntp: Access tick_...
350
351
352
  
  u64 ntp_tick_length(void)
  {
a076b2146   John Stultz   ntp: Remove ntp_l...
353
  	return tick_length;
ea7cf49a7   John Stultz   ntp: Access tick_...
354
  }
833f32d76   John Stultz   time: Prevent ear...
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
  /**
   * ntp_get_next_leap - Returns the next leapsecond in CLOCK_REALTIME ktime_t
   *
   * Provides the time of the next leapsecond against CLOCK_REALTIME in
   * a ktime_t format. Returns KTIME_MAX if no leapsecond is pending.
   */
  ktime_t ntp_get_next_leap(void)
  {
  	ktime_t ret;
  
  	if ((time_state == TIME_INS) && (time_status & STA_INS))
  		return ktime_set(ntp_next_leap_sec, 0);
  	ret.tv64 = KTIME_MAX;
  	return ret;
  }
ea7cf49a7   John Stultz   ntp: Access tick_...
370

4c7ee8de9   John Stultz   [PATCH] NTP: Move...
371
  /*
6b43ae8a6   John Stultz   ntp: Fix leap-sec...
372
373
374
375
376
377
378
379
   * this routine handles the overflow of the microsecond field
   *
   * The tricky bits of code to handle the accurate clock support
   * were provided by Dave Mills (Mills@UDEL.EDU) of NTP fame.
   * They were originally developed for SUN and DEC kernels.
   * All the kudos should go to Dave for this stuff.
   *
   * Also handles leap second processing, and returns leap offset
4c7ee8de9   John Stultz   [PATCH] NTP: Move...
380
   */
c79634877   DengChao   ntp: Fix second_o...
381
  int second_overflow(time64_t secs)
4c7ee8de9   John Stultz   [PATCH] NTP: Move...
382
  {
6b43ae8a6   John Stultz   ntp: Fix leap-sec...
383
  	s64 delta;
bd3312681   John Stultz   ntp: Add ntp_lock...
384
  	int leap = 0;
c79634877   DengChao   ntp: Fix second_o...
385
  	s32 rem;
6b43ae8a6   John Stultz   ntp: Fix leap-sec...
386
387
388
389
390
391
  
  	/*
  	 * Leap second processing. If in leap-insert state at the end of the
  	 * day, the system clock is set back one second; if in leap-delete
  	 * state, the system clock is set ahead one second.
  	 */
4c7ee8de9   John Stultz   [PATCH] NTP: Move...
392
393
  	switch (time_state) {
  	case TIME_OK:
833f32d76   John Stultz   time: Prevent ear...
394
  		if (time_status & STA_INS) {
6b43ae8a6   John Stultz   ntp: Fix leap-sec...
395
  			time_state = TIME_INS;
c79634877   DengChao   ntp: Fix second_o...
396
397
  			div_s64_rem(secs, SECS_PER_DAY, &rem);
  			ntp_next_leap_sec = secs + SECS_PER_DAY - rem;
833f32d76   John Stultz   time: Prevent ear...
398
  		} else if (time_status & STA_DEL) {
6b43ae8a6   John Stultz   ntp: Fix leap-sec...
399
  			time_state = TIME_DEL;
c79634877   DengChao   ntp: Fix second_o...
400
401
  			div_s64_rem(secs + 1, SECS_PER_DAY, &rem);
  			ntp_next_leap_sec = secs + SECS_PER_DAY - rem;
833f32d76   John Stultz   time: Prevent ear...
402
  		}
4c7ee8de9   John Stultz   [PATCH] NTP: Move...
403
404
  		break;
  	case TIME_INS:
833f32d76   John Stultz   time: Prevent ear...
405
406
  		if (!(time_status & STA_INS)) {
  			ntp_next_leap_sec = TIME64_MAX;
6b1859dba   John Stultz   ntp: Fix STA_INS/...
407
  			time_state = TIME_OK;
c79634877   DengChao   ntp: Fix second_o...
408
  		} else if (secs == ntp_next_leap_sec) {
6b43ae8a6   John Stultz   ntp: Fix leap-sec...
409
410
411
412
413
414
  			leap = -1;
  			time_state = TIME_OOP;
  			printk(KERN_NOTICE
  				"Clock: inserting leap second 23:59:60 UTC
  ");
  		}
4c7ee8de9   John Stultz   [PATCH] NTP: Move...
415
416
  		break;
  	case TIME_DEL:
833f32d76   John Stultz   time: Prevent ear...
417
418
  		if (!(time_status & STA_DEL)) {
  			ntp_next_leap_sec = TIME64_MAX;
6b1859dba   John Stultz   ntp: Fix STA_INS/...
419
  			time_state = TIME_OK;
c79634877   DengChao   ntp: Fix second_o...
420
  		} else if (secs == ntp_next_leap_sec) {
6b43ae8a6   John Stultz   ntp: Fix leap-sec...
421
  			leap = 1;
833f32d76   John Stultz   time: Prevent ear...
422
  			ntp_next_leap_sec = TIME64_MAX;
6b43ae8a6   John Stultz   ntp: Fix leap-sec...
423
424
425
426
427
  			time_state = TIME_WAIT;
  			printk(KERN_NOTICE
  				"Clock: deleting leap second 23:59:59 UTC
  ");
  		}
4c7ee8de9   John Stultz   [PATCH] NTP: Move...
428
429
  		break;
  	case TIME_OOP:
833f32d76   John Stultz   time: Prevent ear...
430
  		ntp_next_leap_sec = TIME64_MAX;
4c7ee8de9   John Stultz   [PATCH] NTP: Move...
431
  		time_state = TIME_WAIT;
6b43ae8a6   John Stultz   ntp: Fix leap-sec...
432
  		break;
4c7ee8de9   John Stultz   [PATCH] NTP: Move...
433
434
  	case TIME_WAIT:
  		if (!(time_status & (STA_INS | STA_DEL)))
ee9851b21   Roman Zippel   ntp: cleanup ntp.c
435
  			time_state = TIME_OK;
7dffa3c67   Roman Zippel   ntp: handle leap ...
436
437
  		break;
  	}
bd3312681   John Stultz   ntp: Add ntp_lock...
438

7dffa3c67   Roman Zippel   ntp: handle leap ...
439
440
441
442
443
444
  
  	/* Bump the maxerror field */
  	time_maxerror += MAXFREQ / NSEC_PER_USEC;
  	if (time_maxerror > NTP_PHASE_LIMIT) {
  		time_maxerror = NTP_PHASE_LIMIT;
  		time_status |= STA_UNSYNC;
4c7ee8de9   John Stultz   [PATCH] NTP: Move...
445
  	}
025b40abe   Alexander Gordeev   ntp: add hardpps ...
446
  	/* Compute the phase adjustment for the next second */
39854fe8c   Ingo Molnar   time: ntp: clean ...
447
  	tick_length	 = tick_length_base;
025b40abe   Alexander Gordeev   ntp: add hardpps ...
448
  	delta		 = ntp_offset_chunk(time_offset);
39854fe8c   Ingo Molnar   time: ntp: clean ...
449
450
  	time_offset	-= delta;
  	tick_length	+= delta;
4c7ee8de9   John Stultz   [PATCH] NTP: Move...
451

025b40abe   Alexander Gordeev   ntp: add hardpps ...
452
453
  	/* Check PPS signal */
  	pps_dec_valid();
3c972c244   Ingo Molnar   time: ntp: simpli...
454
  	if (!time_adjust)
bd3312681   John Stultz   ntp: Add ntp_lock...
455
  		goto out;
3c972c244   Ingo Molnar   time: ntp: simpli...
456
457
458
459
  
  	if (time_adjust > MAX_TICKADJ) {
  		time_adjust -= MAX_TICKADJ;
  		tick_length += MAX_TICKADJ_SCALED;
bd3312681   John Stultz   ntp: Add ntp_lock...
460
  		goto out;
4c7ee8de9   John Stultz   [PATCH] NTP: Move...
461
  	}
3c972c244   Ingo Molnar   time: ntp: simpli...
462
463
464
465
  
  	if (time_adjust < -MAX_TICKADJ) {
  		time_adjust += MAX_TICKADJ;
  		tick_length -= MAX_TICKADJ_SCALED;
bd3312681   John Stultz   ntp: Add ntp_lock...
466
  		goto out;
3c972c244   Ingo Molnar   time: ntp: simpli...
467
468
469
470
471
  	}
  
  	tick_length += (s64)(time_adjust * NSEC_PER_USEC / NTP_INTERVAL_FREQ)
  							 << NTP_SCALE_SHIFT;
  	time_adjust = 0;
6b43ae8a6   John Stultz   ntp: Fix leap-sec...
472

bd3312681   John Stultz   ntp: Add ntp_lock...
473
  out:
6b43ae8a6   John Stultz   ntp: Fix leap-sec...
474
  	return leap;
4c7ee8de9   John Stultz   [PATCH] NTP: Move...
475
  }
3c00a1fe8   Xunlei Pang   time: Add y2038 s...
476
  #ifdef CONFIG_GENERIC_CMOS_UPDATE
7494e9eed   Xunlei Pang   time: Add the com...
477
478
479
480
  int __weak update_persistent_clock(struct timespec now)
  {
  	return -ENODEV;
  }
3c00a1fe8   Xunlei Pang   time: Add y2038 s...
481
482
483
484
485
486
487
488
  int __weak update_persistent_clock64(struct timespec64 now64)
  {
  	struct timespec now;
  
  	now = timespec64_to_timespec(now64);
  	return update_persistent_clock(now);
  }
  #endif
023f333a9   Jason Gunthorpe   NTP: Add a CONFIG...
489
  #if defined(CONFIG_GENERIC_CMOS_UPDATE) || defined(CONFIG_RTC_SYSTOHC)
eb3f938fd   Maciej W. Rozycki   ntp: let update_p...
490
  static void sync_cmos_clock(struct work_struct *work);
82644459c   Thomas Gleixner   NTP: move the cmo...
491

eb3f938fd   Maciej W. Rozycki   ntp: let update_p...
492
  static DECLARE_DELAYED_WORK(sync_cmos_work, sync_cmos_clock);
82644459c   Thomas Gleixner   NTP: move the cmo...
493

eb3f938fd   Maciej W. Rozycki   ntp: let update_p...
494
  static void sync_cmos_clock(struct work_struct *work)
82644459c   Thomas Gleixner   NTP: move the cmo...
495
  {
d6d29896c   Thomas Gleixner   timekeeping: Prov...
496
  	struct timespec64 now;
5fd96c421   Arnd Bergmann   ntp: use timespec...
497
  	struct timespec64 next;
82644459c   Thomas Gleixner   NTP: move the cmo...
498
499
500
501
502
503
504
505
  	int fail = 1;
  
  	/*
  	 * If we have an externally synchronized Linux clock, then update
  	 * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
  	 * called as close as possible to 500 ms before the new second starts.
  	 * This code is run on a timer.  If the clock is set, that timer
  	 * may not expire at the correct time.  Thus, we adjust...
a97ad0c4b   Miroslav Lichvar   ntp: Make periodi...
506
  	 * We want the clock to be within a couple of ticks from the target.
82644459c   Thomas Gleixner   NTP: move the cmo...
507
  	 */
53bbfa9e9   Ingo Molnar   time: ntp: clean ...
508
  	if (!ntp_synced()) {
82644459c   Thomas Gleixner   NTP: move the cmo...
509
510
511
512
513
  		/*
  		 * Not synced, exit, do not restart a timer (if one is
  		 * running, let it run out).
  		 */
  		return;
53bbfa9e9   Ingo Molnar   time: ntp: clean ...
514
  	}
82644459c   Thomas Gleixner   NTP: move the cmo...
515

d6d29896c   Thomas Gleixner   timekeeping: Prov...
516
  	getnstimeofday64(&now);
a97ad0c4b   Miroslav Lichvar   ntp: Make periodi...
517
  	if (abs(now.tv_nsec - (NSEC_PER_SEC / 2)) <= tick_nsec * 5) {
9a4a445e3   Xunlei Pang   rtc: Convert rtc_...
518
  		struct timespec64 adjust = now;
84e345e4e   Prarit Bhargava   time, Fix setting...
519

023f333a9   Jason Gunthorpe   NTP: Add a CONFIG...
520
  		fail = -ENODEV;
84e345e4e   Prarit Bhargava   time, Fix setting...
521
522
  		if (persistent_clock_is_local)
  			adjust.tv_sec -= (sys_tz.tz_minuteswest * 60);
023f333a9   Jason Gunthorpe   NTP: Add a CONFIG...
523
  #ifdef CONFIG_GENERIC_CMOS_UPDATE
3c00a1fe8   Xunlei Pang   time: Add y2038 s...
524
  		fail = update_persistent_clock64(adjust);
023f333a9   Jason Gunthorpe   NTP: Add a CONFIG...
525
  #endif
3c00a1fe8   Xunlei Pang   time: Add y2038 s...
526

023f333a9   Jason Gunthorpe   NTP: Add a CONFIG...
527
528
  #ifdef CONFIG_RTC_SYSTOHC
  		if (fail == -ENODEV)
84e345e4e   Prarit Bhargava   time, Fix setting...
529
  			fail = rtc_set_ntp_time(adjust);
023f333a9   Jason Gunthorpe   NTP: Add a CONFIG...
530
531
  #endif
  	}
82644459c   Thomas Gleixner   NTP: move the cmo...
532

4ff4b9e19   Maciej W. Rozycki   ntp: fix calculat...
533
  	next.tv_nsec = (NSEC_PER_SEC / 2) - now.tv_nsec - (TICK_NSEC / 2);
82644459c   Thomas Gleixner   NTP: move the cmo...
534
535
  	if (next.tv_nsec <= 0)
  		next.tv_nsec += NSEC_PER_SEC;
023f333a9   Jason Gunthorpe   NTP: Add a CONFIG...
536
  	if (!fail || fail == -ENODEV)
82644459c   Thomas Gleixner   NTP: move the cmo...
537
538
539
540
541
542
543
544
  		next.tv_sec = 659;
  	else
  		next.tv_sec = 0;
  
  	if (next.tv_nsec >= NSEC_PER_SEC) {
  		next.tv_sec++;
  		next.tv_nsec -= NSEC_PER_SEC;
  	}
e8b175946   Shaibal Dutta   timekeeping: Move...
545
  	queue_delayed_work(system_power_efficient_wq,
5fd96c421   Arnd Bergmann   ntp: use timespec...
546
  			   &sync_cmos_work, timespec64_to_jiffies(&next));
82644459c   Thomas Gleixner   NTP: move the cmo...
547
  }
7bd360144   John Stultz   timekeeping: Fix ...
548
  void ntp_notify_cmos_timer(void)
4c7ee8de9   John Stultz   [PATCH] NTP: Move...
549
  {
e8b175946   Shaibal Dutta   timekeeping: Move...
550
  	queue_delayed_work(system_power_efficient_wq, &sync_cmos_work, 0);
4c7ee8de9   John Stultz   [PATCH] NTP: Move...
551
  }
82644459c   Thomas Gleixner   NTP: move the cmo...
552
  #else
7bd360144   John Stultz   timekeeping: Fix ...
553
  void ntp_notify_cmos_timer(void) { }
82644459c   Thomas Gleixner   NTP: move the cmo...
554
  #endif
80f225711   Ingo Molnar   time: ntp: refact...
555
556
557
558
  
  /*
   * Propagate a new txc->status value into the NTP state:
   */
7d489d15c   John Stultz   timekeeping: Conv...
559
  static inline void process_adj_status(struct timex *txc, struct timespec64 *ts)
80f225711   Ingo Molnar   time: ntp: refact...
560
  {
80f225711   Ingo Molnar   time: ntp: refact...
561
562
563
  	if ((time_status & STA_PLL) && !(txc->status & STA_PLL)) {
  		time_state = TIME_OK;
  		time_status = STA_UNSYNC;
833f32d76   John Stultz   time: Prevent ear...
564
  		ntp_next_leap_sec = TIME64_MAX;
025b40abe   Alexander Gordeev   ntp: add hardpps ...
565
566
  		/* restart PPS frequency calibration */
  		pps_reset_freq_interval();
80f225711   Ingo Molnar   time: ntp: refact...
567
  	}
80f225711   Ingo Molnar   time: ntp: refact...
568
569
570
571
572
573
  
  	/*
  	 * If we turn on PLL adjustments then reset the
  	 * reference time to current time.
  	 */
  	if (!(time_status & STA_PLL) && (txc->status & STA_PLL))
0af864651   DengChao   ntp: Change time_...
574
  		time_reftime = __ktime_get_real_seconds();
80f225711   Ingo Molnar   time: ntp: refact...
575

a2a5ac865   John Stultz   time: ntp: fix bu...
576
577
  	/* only set allowed bits */
  	time_status &= STA_RONLY;
80f225711   Ingo Molnar   time: ntp: refact...
578
  	time_status |= txc->status & ~STA_RONLY;
80f225711   Ingo Molnar   time: ntp: refact...
579
  }
cd5398bed   Richard Cochran   ntp: Fix a stale ...
580

a076b2146   John Stultz   ntp: Remove ntp_l...
581

cc244ddae   John Stultz   timekeeping: Move...
582
  static inline void process_adjtimex_modes(struct timex *txc,
7d489d15c   John Stultz   timekeeping: Conv...
583
  						struct timespec64 *ts,
cc244ddae   John Stultz   timekeeping: Move...
584
  						s32 *time_tai)
80f225711   Ingo Molnar   time: ntp: refact...
585
586
587
588
589
590
  {
  	if (txc->modes & ADJ_STATUS)
  		process_adj_status(txc, ts);
  
  	if (txc->modes & ADJ_NANO)
  		time_status |= STA_NANO;
e96291653   Ingo Molnar   time: ntp: refact...
591

80f225711   Ingo Molnar   time: ntp: refact...
592
593
594
595
  	if (txc->modes & ADJ_MICRO)
  		time_status &= ~STA_NANO;
  
  	if (txc->modes & ADJ_FREQUENCY) {
2b9d1496e   Ingo Molnar   time: ntp: make 6...
596
  		time_freq = txc->freq * PPM_SCALE;
80f225711   Ingo Molnar   time: ntp: refact...
597
598
  		time_freq = min(time_freq, MAXFREQ_SCALED);
  		time_freq = max(time_freq, -MAXFREQ_SCALED);
025b40abe   Alexander Gordeev   ntp: add hardpps ...
599
600
  		/* update pps_freq */
  		pps_set_freq(time_freq);
80f225711   Ingo Molnar   time: ntp: refact...
601
602
603
604
  	}
  
  	if (txc->modes & ADJ_MAXERROR)
  		time_maxerror = txc->maxerror;
e96291653   Ingo Molnar   time: ntp: refact...
605

80f225711   Ingo Molnar   time: ntp: refact...
606
607
608
609
610
611
612
613
614
615
616
617
  	if (txc->modes & ADJ_ESTERROR)
  		time_esterror = txc->esterror;
  
  	if (txc->modes & ADJ_TIMECONST) {
  		time_constant = txc->constant;
  		if (!(time_status & STA_NANO))
  			time_constant += 4;
  		time_constant = min(time_constant, (long)MAXTC);
  		time_constant = max(time_constant, 0l);
  	}
  
  	if (txc->modes & ADJ_TAI && txc->constant > 0)
cc244ddae   John Stultz   timekeeping: Move...
618
  		*time_tai = txc->constant;
80f225711   Ingo Molnar   time: ntp: refact...
619
620
621
  
  	if (txc->modes & ADJ_OFFSET)
  		ntp_update_offset(txc->offset);
e96291653   Ingo Molnar   time: ntp: refact...
622

80f225711   Ingo Molnar   time: ntp: refact...
623
624
625
626
627
628
  	if (txc->modes & ADJ_TICK)
  		tick_usec = txc->tick;
  
  	if (txc->modes & (ADJ_TICK|ADJ_FREQUENCY|ADJ_OFFSET))
  		ntp_update_frequency();
  }
ad460967a   John Stultz   ntp: Split out ti...
629
630
631
632
  
  
  /**
   * ntp_validate_timex - Ensures the timex is ok for use in do_adjtimex
4c7ee8de9   John Stultz   [PATCH] NTP: Move...
633
   */
ad460967a   John Stultz   ntp: Split out ti...
634
  int ntp_validate_timex(struct timex *txc)
4c7ee8de9   John Stultz   [PATCH] NTP: Move...
635
  {
916c7a855   Roman Zippel   ntp: fix ADJ_OFFS...
636
  	if (txc->modes & ADJ_ADJTIME) {
eea83d896   Roman Zippel   ntp: NTP4 user sp...
637
  		/* singleshot must not be used with any other mode bits */
916c7a855   Roman Zippel   ntp: fix ADJ_OFFS...
638
  		if (!(txc->modes & ADJ_OFFSET_SINGLESHOT))
4c7ee8de9   John Stultz   [PATCH] NTP: Move...
639
  			return -EINVAL;
916c7a855   Roman Zippel   ntp: fix ADJ_OFFS...
640
641
642
643
644
645
646
  		if (!(txc->modes & ADJ_OFFSET_READONLY) &&
  		    !capable(CAP_SYS_TIME))
  			return -EPERM;
  	} else {
  		/* In order to modify anything, you gotta be super-user! */
  		 if (txc->modes && !capable(CAP_SYS_TIME))
  			return -EPERM;
53bbfa9e9   Ingo Molnar   time: ntp: clean ...
647
648
649
650
  		/*
  		 * if the quartz is off by more than 10% then
  		 * something is VERY wrong!
  		 */
916c7a855   Roman Zippel   ntp: fix ADJ_OFFS...
651
652
653
  		if (txc->modes & ADJ_TICK &&
  		    (txc->tick <  900000/USER_HZ ||
  		     txc->tick > 1100000/USER_HZ))
e96291653   Ingo Molnar   time: ntp: refact...
654
  			return -EINVAL;
52bfb3605   John Stultz   time: add ADJ_OFF...
655
  	}
4c7ee8de9   John Stultz   [PATCH] NTP: Move...
656

37cf4dc33   John Stultz   time: Verify time...
657
658
659
660
  	if (txc->modes & ADJ_SETOFFSET) {
  		/* In order to inject time, you gotta be super-user! */
  		if (!capable(CAP_SYS_TIME))
  			return -EPERM;
dd4e17ab7   John Stultz   ntp: Fix ADJ_SETO...
661
662
663
664
665
666
667
668
669
670
671
672
  		if (txc->modes & ADJ_NANO) {
  			struct timespec ts;
  
  			ts.tv_sec = txc->time.tv_sec;
  			ts.tv_nsec = txc->time.tv_usec;
  			if (!timespec_inject_offset_valid(&ts))
  				return -EINVAL;
  
  		} else {
  			if (!timeval_inject_offset_valid(&txc->time))
  				return -EINVAL;
  		}
37cf4dc33   John Stultz   time: Verify time...
673
  	}
ad460967a   John Stultz   ntp: Split out ti...
674

29183a70b   John Stultz   ntp: Fixup adjtim...
675
676
677
678
679
680
  	/*
  	 * Check for potential multiplication overflows that can
  	 * only happen on 64-bit systems:
  	 */
  	if ((txc->modes & ADJ_FREQUENCY) && (BITS_PER_LONG == 64)) {
  		if (LLONG_MIN / PPM_SCALE > txc->freq)
5e5aeb436   Sasha Levin   time: adjtimex: V...
681
  			return -EINVAL;
29183a70b   John Stultz   ntp: Fixup adjtim...
682
  		if (LLONG_MAX / PPM_SCALE < txc->freq)
5e5aeb436   Sasha Levin   time: adjtimex: V...
683
684
  			return -EINVAL;
  	}
ad460967a   John Stultz   ntp: Split out ti...
685
686
687
688
689
690
691
692
  	return 0;
  }
  
  
  /*
   * adjtimex mainly allows reading (and writing, if superuser) of
   * kernel time-keeping variables. used by xntpd.
   */
7d489d15c   John Stultz   timekeeping: Conv...
693
  int __do_adjtimex(struct timex *txc, struct timespec64 *ts, s32 *time_tai)
ad460967a   John Stultz   ntp: Split out ti...
694
  {
ad460967a   John Stultz   ntp: Split out ti...
695
  	int result;
916c7a855   Roman Zippel   ntp: fix ADJ_OFFS...
696
697
698
699
700
701
702
703
704
  	if (txc->modes & ADJ_ADJTIME) {
  		long save_adjust = time_adjust;
  
  		if (!(txc->modes & ADJ_OFFSET_READONLY)) {
  			/* adjtime() is independent from ntp_adjtime() */
  			time_adjust = txc->offset;
  			ntp_update_frequency();
  		}
  		txc->offset = save_adjust;
e96291653   Ingo Molnar   time: ntp: refact...
705
  	} else {
ee9851b21   Roman Zippel   ntp: cleanup ntp.c
706

e96291653   Ingo Molnar   time: ntp: refact...
707
708
  		/* If there are input parameters, then process them: */
  		if (txc->modes)
87ace39b7   John Stultz   ntp: Rework do_ad...
709
  			process_adjtimex_modes(txc, ts, time_tai);
eea83d896   Roman Zippel   ntp: NTP4 user sp...
710

e96291653   Ingo Molnar   time: ntp: refact...
711
  		txc->offset = shift_right(time_offset * NTP_INTERVAL_FREQ,
916c7a855   Roman Zippel   ntp: fix ADJ_OFFS...
712
  				  NTP_SCALE_SHIFT);
e96291653   Ingo Molnar   time: ntp: refact...
713
714
715
  		if (!(time_status & STA_NANO))
  			txc->offset /= NSEC_PER_USEC;
  	}
916c7a855   Roman Zippel   ntp: fix ADJ_OFFS...
716

eea83d896   Roman Zippel   ntp: NTP4 user sp...
717
  	result = time_state;	/* mostly `TIME_OK' */
025b40abe   Alexander Gordeev   ntp: add hardpps ...
718
719
  	/* check for errors */
  	if (is_error_status(time_status))
4c7ee8de9   John Stultz   [PATCH] NTP: Move...
720
  		result = TIME_ERROR;
d40e944c2   Roman Zippel   ntp: improve adjt...
721
  	txc->freq	   = shift_right((time_freq >> PPM_SCALE_INV_SHIFT) *
2b9d1496e   Ingo Molnar   time: ntp: make 6...
722
  					 PPM_SCALE_INV, NTP_SCALE_SHIFT);
4c7ee8de9   John Stultz   [PATCH] NTP: Move...
723
724
725
726
  	txc->maxerror	   = time_maxerror;
  	txc->esterror	   = time_esterror;
  	txc->status	   = time_status;
  	txc->constant	   = time_constant;
70bc42f90   Adrian Bunk   [PATCH] kernel/ti...
727
  	txc->precision	   = 1;
074b3b879   Roman Zippel   ntp: increase tim...
728
  	txc->tolerance	   = MAXFREQ_SCALED / PPM_SCALE;
4c7ee8de9   John Stultz   [PATCH] NTP: Move...
729
  	txc->tick	   = tick_usec;
87ace39b7   John Stultz   ntp: Rework do_ad...
730
  	txc->tai	   = *time_tai;
4c7ee8de9   John Stultz   [PATCH] NTP: Move...
731

025b40abe   Alexander Gordeev   ntp: add hardpps ...
732
733
  	/* fill PPS status fields */
  	pps_fill_timex(txc);
e96291653   Ingo Molnar   time: ntp: refact...
734

7d489d15c   John Stultz   timekeeping: Conv...
735
  	txc->time.tv_sec = (time_t)ts->tv_sec;
87ace39b7   John Stultz   ntp: Rework do_ad...
736
  	txc->time.tv_usec = ts->tv_nsec;
eea83d896   Roman Zippel   ntp: NTP4 user sp...
737
738
  	if (!(time_status & STA_NANO))
  		txc->time.tv_usec /= NSEC_PER_USEC;
ee9851b21   Roman Zippel   ntp: cleanup ntp.c
739

96efdcf2d   John Stultz   ntp: Do leapsecon...
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
  	/* Handle leapsec adjustments */
  	if (unlikely(ts->tv_sec >= ntp_next_leap_sec)) {
  		if ((time_state == TIME_INS) && (time_status & STA_INS)) {
  			result = TIME_OOP;
  			txc->tai++;
  			txc->time.tv_sec--;
  		}
  		if ((time_state == TIME_DEL) && (time_status & STA_DEL)) {
  			result = TIME_WAIT;
  			txc->tai--;
  			txc->time.tv_sec++;
  		}
  		if ((time_state == TIME_OOP) &&
  					(ts->tv_sec == ntp_next_leap_sec)) {
  			result = TIME_WAIT;
  		}
  	}
ee9851b21   Roman Zippel   ntp: cleanup ntp.c
757
  	return result;
4c7ee8de9   John Stultz   [PATCH] NTP: Move...
758
  }
10a398d04   Roman Zippel   time: remove obso...
759

025b40abe   Alexander Gordeev   ntp: add hardpps ...
760
761
762
763
764
765
766
  #ifdef	CONFIG_NTP_PPS
  
  /* actually struct pps_normtime is good old struct timespec, but it is
   * semantically different (and it is the reason why it was invented):
   * pps_normtime.nsec has a range of ( -NSEC_PER_SEC / 2, NSEC_PER_SEC / 2 ]
   * while timespec.tv_nsec has a range of [0, NSEC_PER_SEC) */
  struct pps_normtime {
7ec88e4be   Arnd Bergmann   ntp/pps: use time...
767
  	s64		sec;	/* seconds */
025b40abe   Alexander Gordeev   ntp: add hardpps ...
768
769
770
771
772
  	long		nsec;	/* nanoseconds */
  };
  
  /* normalize the timestamp so that nsec is in the
     ( -NSEC_PER_SEC / 2, NSEC_PER_SEC / 2 ] interval */
7ec88e4be   Arnd Bergmann   ntp/pps: use time...
773
  static inline struct pps_normtime pps_normalize_ts(struct timespec64 ts)
025b40abe   Alexander Gordeev   ntp: add hardpps ...
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
  {
  	struct pps_normtime norm = {
  		.sec = ts.tv_sec,
  		.nsec = ts.tv_nsec
  	};
  
  	if (norm.nsec > (NSEC_PER_SEC >> 1)) {
  		norm.nsec -= NSEC_PER_SEC;
  		norm.sec++;
  	}
  
  	return norm;
  }
  
  /* get current phase correction and jitter */
  static inline long pps_phase_filter_get(long *jitter)
  {
  	*jitter = pps_tf[0] - pps_tf[1];
  	if (*jitter < 0)
  		*jitter = -*jitter;
  
  	/* TODO: test various filters */
  	return pps_tf[0];
  }
  
  /* add the sample to the phase filter */
  static inline void pps_phase_filter_add(long err)
  {
  	pps_tf[2] = pps_tf[1];
  	pps_tf[1] = pps_tf[0];
  	pps_tf[0] = err;
  }
  
  /* decrease frequency calibration interval length.
   * It is halved after four consecutive unstable intervals.
   */
  static inline void pps_dec_freq_interval(void)
  {
  	if (--pps_intcnt <= -PPS_INTCOUNT) {
  		pps_intcnt = -PPS_INTCOUNT;
  		if (pps_shift > PPS_INTMIN) {
  			pps_shift--;
  			pps_intcnt = 0;
  		}
  	}
  }
  
  /* increase frequency calibration interval length.
   * It is doubled after four consecutive stable intervals.
   */
  static inline void pps_inc_freq_interval(void)
  {
  	if (++pps_intcnt >= PPS_INTCOUNT) {
  		pps_intcnt = PPS_INTCOUNT;
  		if (pps_shift < PPS_INTMAX) {
  			pps_shift++;
  			pps_intcnt = 0;
  		}
  	}
  }
  
  /* update clock frequency based on MONOTONIC_RAW clock PPS signal
   * timestamps
   *
   * At the end of the calibration interval the difference between the
   * first and last MONOTONIC_RAW clock timestamps divided by the length
   * of the interval becomes the frequency update. If the interval was
   * too long, the data are discarded.
   * Returns the difference between old and new frequency values.
   */
  static long hardpps_update_freq(struct pps_normtime freq_norm)
  {
  	long delta, delta_mod;
  	s64 ftemp;
  
  	/* check if the frequency interval was too long */
  	if (freq_norm.sec > (2 << pps_shift)) {
  		time_status |= STA_PPSERROR;
  		pps_errcnt++;
  		pps_dec_freq_interval();
6d9bcb621   John Stultz   timekeeping: use ...
854
  		printk_deferred(KERN_ERR
7ec88e4be   Arnd Bergmann   ntp/pps: use time...
855
856
  			"hardpps: PPSERROR: interval too long - %lld s
  ",
6d9bcb621   John Stultz   timekeeping: use ...
857
  			freq_norm.sec);
025b40abe   Alexander Gordeev   ntp: add hardpps ...
858
859
860
861
862
863
864
865
866
867
868
869
  		return 0;
  	}
  
  	/* here the raw frequency offset and wander (stability) is
  	 * calculated. If the wander is less than the wander threshold
  	 * the interval is increased; otherwise it is decreased.
  	 */
  	ftemp = div_s64(((s64)(-freq_norm.nsec)) << NTP_SCALE_SHIFT,
  			freq_norm.sec);
  	delta = shift_right(ftemp - pps_freq, NTP_SCALE_SHIFT);
  	pps_freq = ftemp;
  	if (delta > PPS_MAXWANDER || delta < -PPS_MAXWANDER) {
6d9bcb621   John Stultz   timekeeping: use ...
870
871
872
  		printk_deferred(KERN_WARNING
  				"hardpps: PPSWANDER: change=%ld
  ", delta);
025b40abe   Alexander Gordeev   ntp: add hardpps ...
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
  		time_status |= STA_PPSWANDER;
  		pps_stbcnt++;
  		pps_dec_freq_interval();
  	} else {	/* good sample */
  		pps_inc_freq_interval();
  	}
  
  	/* the stability metric is calculated as the average of recent
  	 * frequency changes, but is used only for performance
  	 * monitoring
  	 */
  	delta_mod = delta;
  	if (delta_mod < 0)
  		delta_mod = -delta_mod;
  	pps_stabil += (div_s64(((s64)delta_mod) <<
  				(NTP_SCALE_SHIFT - SHIFT_USEC),
  				NSEC_PER_USEC) - pps_stabil) >> PPS_INTMIN;
  
  	/* if enabled, the system clock frequency is updated */
  	if ((time_status & STA_PPSFREQ) != 0 &&
  	    (time_status & STA_FREQHOLD) == 0) {
  		time_freq = pps_freq;
  		ntp_update_frequency();
  	}
  
  	return delta;
  }
  
  /* correct REALTIME clock phase error against PPS signal */
  static void hardpps_update_phase(long error)
  {
  	long correction = -error;
  	long jitter;
  
  	/* add the sample to the median filter */
  	pps_phase_filter_add(correction);
  	correction = pps_phase_filter_get(&jitter);
  
  	/* Nominal jitter is due to PPS signal noise. If it exceeds the
  	 * threshold, the sample is discarded; otherwise, if so enabled,
  	 * the time offset is updated.
  	 */
  	if (jitter > (pps_jitter << PPS_POPCORN)) {
6d9bcb621   John Stultz   timekeeping: use ...
916
917
918
919
  		printk_deferred(KERN_WARNING
  				"hardpps: PPSJITTER: jitter=%ld, limit=%ld
  ",
  				jitter, (pps_jitter << PPS_POPCORN));
025b40abe   Alexander Gordeev   ntp: add hardpps ...
920
921
922
923
924
925
926
927
928
929
930
931
932
933
  		time_status |= STA_PPSJITTER;
  		pps_jitcnt++;
  	} else if (time_status & STA_PPSTIME) {
  		/* correct the time using the phase offset */
  		time_offset = div_s64(((s64)correction) << NTP_SCALE_SHIFT,
  				NTP_INTERVAL_FREQ);
  		/* cancel running adjtime() */
  		time_adjust = 0;
  	}
  	/* update jitter */
  	pps_jitter += (jitter - pps_jitter) >> PPS_INTMIN;
  }
  
  /*
aa6f9c595   John Stultz   ntp: Move do_adjt...
934
   * __hardpps() - discipline CPU clock oscillator to external PPS signal
025b40abe   Alexander Gordeev   ntp: add hardpps ...
935
936
937
938
939
940
941
942
943
944
   *
   * This routine is called at each PPS signal arrival in order to
   * discipline the CPU clock oscillator to the PPS signal. It takes two
   * parameters: REALTIME and MONOTONIC_RAW clock timestamps. The former
   * is used to correct clock phase error and the latter is used to
   * correct the frequency.
   *
   * This code is based on David Mills's reference nanokernel
   * implementation. It was mostly rewritten but keeps the same idea.
   */
7ec88e4be   Arnd Bergmann   ntp/pps: use time...
945
  void __hardpps(const struct timespec64 *phase_ts, const struct timespec64 *raw_ts)
025b40abe   Alexander Gordeev   ntp: add hardpps ...
946
947
  {
  	struct pps_normtime pts_norm, freq_norm;
025b40abe   Alexander Gordeev   ntp: add hardpps ...
948
949
  
  	pts_norm = pps_normalize_ts(*phase_ts);
025b40abe   Alexander Gordeev   ntp: add hardpps ...
950
951
952
953
954
955
956
957
958
959
960
  	/* clear the error bits, they will be set again if needed */
  	time_status &= ~(STA_PPSJITTER | STA_PPSWANDER | STA_PPSERROR);
  
  	/* indicate signal presence */
  	time_status |= STA_PPSSIGNAL;
  	pps_valid = PPS_VALID;
  
  	/* when called for the first time,
  	 * just start the frequency interval */
  	if (unlikely(pps_fbase.tv_sec == 0)) {
  		pps_fbase = *raw_ts;
025b40abe   Alexander Gordeev   ntp: add hardpps ...
961
962
963
964
  		return;
  	}
  
  	/* ok, now we have a base for frequency calculation */
7ec88e4be   Arnd Bergmann   ntp/pps: use time...
965
  	freq_norm = pps_normalize_ts(timespec64_sub(*raw_ts, pps_fbase));
025b40abe   Alexander Gordeev   ntp: add hardpps ...
966
967
968
969
970
971
972
973
974
  
  	/* check that the signal is in the range
  	 * [1s - MAXFREQ us, 1s + MAXFREQ us], otherwise reject it */
  	if ((freq_norm.sec == 0) ||
  			(freq_norm.nsec > MAXFREQ * freq_norm.sec) ||
  			(freq_norm.nsec < -MAXFREQ * freq_norm.sec)) {
  		time_status |= STA_PPSJITTER;
  		/* restart the frequency calibration interval */
  		pps_fbase = *raw_ts;
6d9bcb621   John Stultz   timekeeping: use ...
975
976
  		printk_deferred(KERN_ERR "hardpps: PPSJITTER: bad pulse
  ");
025b40abe   Alexander Gordeev   ntp: add hardpps ...
977
978
979
980
981
982
983
984
985
986
987
988
989
990
  		return;
  	}
  
  	/* signal is ok */
  
  	/* check if the current frequency interval is finished */
  	if (freq_norm.sec >= (1 << pps_shift)) {
  		pps_calcnt++;
  		/* restart the frequency calibration interval */
  		pps_fbase = *raw_ts;
  		hardpps_update_freq(freq_norm);
  	}
  
  	hardpps_update_phase(pts_norm.nsec);
025b40abe   Alexander Gordeev   ntp: add hardpps ...
991
  }
025b40abe   Alexander Gordeev   ntp: add hardpps ...
992
  #endif	/* CONFIG_NTP_PPS */
10a398d04   Roman Zippel   time: remove obso...
993
994
  static int __init ntp_tick_adj_setup(char *str)
  {
cdafb93fe   Fabian Frederick   ntp: Convert simp...
995
996
997
998
  	int rc = kstrtol(str, 0, (long *)&ntp_tick_adj);
  
  	if (rc)
  		return rc;
069569e02   Ingo Molnar   time: ntp: simpli...
999
  	ntp_tick_adj <<= NTP_SCALE_SHIFT;
10a398d04   Roman Zippel   time: remove obso...
1000
1001
1002
1003
  	return 1;
  }
  
  __setup("ntp_tick_adj=", ntp_tick_adj_setup);
7dffa3c67   Roman Zippel   ntp: handle leap ...
1004
1005
1006
1007
  
  void __init ntp_init(void)
  {
  	ntp_clear();
7dffa3c67   Roman Zippel   ntp: handle leap ...
1008
  }