License cleanup: add SPDX GPL-2.0 license identifier to files with no license
Many source files in the tree are missing licensing information, which
makes it harder for compliance tools to determine the correct license.
By default all files without license information are under the default
license of the kernel, which is GPL version 2.
Update the files which contain no license information with the 'GPL-2.0'
SPDX license identifier. The SPDX identifier is a legally binding
shorthand, which can be used instead of the full boiler plate text.
This patch is based on work done by Thomas Gleixner and Kate Stewart and
Philippe Ombredanne.
How this work was done:
Patches were generated and checked against linux-4.14-rc6 for a subset of
the use cases:
- file had no licensing information it it.
- file was a */uapi/* one with no licensing information in it,
- file was a */uapi/* one with existing licensing information,
Further patches will be generated in subsequent months to fix up cases
where non-standard license headers were used, and references to license
had to be inferred by heuristics based on keywords.
The analysis to determine which SPDX License Identifier to be applied to
a file was done in a spreadsheet of side by side results from of the
output of two independent scanners (ScanCode & Windriver) producing SPDX
tag:value files created by Philippe Ombredanne. Philippe prepared the
base worksheet, and did an initial spot review of a few 1000 files.
The 4.13 kernel was the starting point of the analysis with 60,537 files
assessed. Kate Stewart did a file by file comparison of the scanner
results in the spreadsheet to determine which SPDX license identifier(s)
to be applied to the file. She confirmed any determination that was not
immediately clear with lawyers working with the Linux Foundation.
Criteria used to select files for SPDX license identifier tagging was:
- Files considered eligible had to be source code files.
- Make and config files were included as candidates if they contained >5
lines of source
- File already had some variant of a license header in it (even if <5
lines).
All documentation files were explicitly excluded.
The following heuristics were used to determine which SPDX license
identifiers to apply.
- when both scanners couldn't find any license traces, file was
considered to have no license information in it, and the top level
COPYING file license applied.
For non */uapi/* files that summary was:
SPDX license identifier # files
---------------------------------------------------|-------
GPL-2.0 11139
and resulted in the first patch in this series.
If that file was a */uapi/* path one, it was "GPL-2.0 WITH
Linux-syscall-note" otherwise it was "GPL-2.0". Results of that was:
SPDX license identifier # files
---------------------------------------------------|-------
GPL-2.0 WITH Linux-syscall-note 930
and resulted in the second patch in this series.
- if a file had some form of licensing information in it, and was one
of the */uapi/* ones, it was denoted with the Linux-syscall-note if
any GPL family license was found in the file or had no licensing in
it (per prior point). Results summary:
SPDX license identifier # files
---------------------------------------------------|------
GPL-2.0 WITH Linux-syscall-note 270
GPL-2.0+ WITH Linux-syscall-note 169
((GPL-2.0 WITH Linux-syscall-note) OR BSD-2-Clause) 21
((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) 17
LGPL-2.1+ WITH Linux-syscall-note 15
GPL-1.0+ WITH Linux-syscall-note 14
((GPL-2.0+ WITH Linux-syscall-note) OR BSD-3-Clause) 5
LGPL-2.0+ WITH Linux-syscall-note 4
LGPL-2.1 WITH Linux-syscall-note 3
((GPL-2.0 WITH Linux-syscall-note) OR MIT) 3
((GPL-2.0 WITH Linux-syscall-note) AND MIT) 1
and that resulted in the third patch in this series.
- when the two scanners agreed on the detected license(s), that became
the concluded license(s).
- when there was disagreement between the two scanners (one detected a
license but the other didn't, or they both detected different
licenses) a manual inspection of the file occurred.
- In most cases a manual inspection of the information in the file
resulted in a clear resolution of the license that should apply (and
which scanner probably needed to revisit its heuristics).
- When it was not immediately clear, the license identifier was
confirmed with lawyers working with the Linux Foundation.
- If there was any question as to the appropriate license identifier,
the file was flagged for further research and to be revisited later
in time.
In total, over 70 hours of logged manual review was done on the
spreadsheet to determine the SPDX license identifiers to apply to the
source files by Kate, Philippe, Thomas and, in some cases, confirmation
by lawyers working with the Linux Foundation.
Kate also obtained a third independent scan of the 4.13 code base from
FOSSology, and compared selected files where the other two scanners
disagreed against that SPDX file, to see if there was new insights. The
Windriver scanner is based on an older version of FOSSology in part, so
they are related.
Thomas did random spot checks in about 500 files from the spreadsheets
for the uapi headers and agreed with SPDX license identifier in the
files he inspected. For the non-uapi files Thomas did random spot checks
in about 15000 files.
In initial set of patches against 4.14-rc6, 3 files were found to have
copy/paste license identifier errors, and have been fixed to reflect the
correct identifier.
Additionally Philippe spent 10 hours this week doing a detailed manual
inspection and review of the 12,461 patched files from the initial patch
version early this week with:
- a full scancode scan run, collecting the matched texts, detected
license ids and scores
- reviewing anything where there was a license detected (about 500+
files) to ensure that the applied SPDX license was correct
- reviewing anything where there was no detection but the patch license
was not GPL-2.0 WITH Linux-syscall-note to ensure that the applied
SPDX license was correct
This produced a worksheet with 20 files needing minor correction. This
worksheet was then exported into 3 different .csv files for the
different types of files to be modified.
These .csv files were then reviewed by Greg. Thomas wrote a script to
parse the csv files and add the proper SPDX tag to the file, in the
format that the file expected. This script was further refined by Greg
based on the output to detect more types of files automatically and to
distinguish between header and source .c files (which need different
comment types.) Finally Greg ran the script using the .csv files to
generate the patches.
Reviewed-by: Kate Stewart <kstewart@linuxfoundation.org>
Reviewed-by: Philippe Ombredanne <pombredanne@nexb.com>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2017-11-01 14:07:57 +00:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
2006-10-01 06:28:22 +00:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
2007-07-16 06:40:39 +00:00
|
|
|
#include <linux/capability.h>
|
2008-05-01 11:34:41 +00:00
|
|
|
#include <linux/clocksource.h>
|
2008-09-22 21:42:40 +00:00
|
|
|
#include <linux/workqueue.h>
|
2008-02-20 06:58:42 +00:00
|
|
|
#include <linux/hrtimer.h>
|
|
|
|
#include <linux/jiffies.h>
|
|
|
|
#include <linux/math64.h>
|
|
|
|
#include <linux/timex.h>
|
|
|
|
#include <linux/time.h>
|
|
|
|
#include <linux/mm.h>
|
2011-01-13 01:00:56 +00:00
|
|
|
#include <linux/module.h>
|
2012-12-17 21:30:53 +00:00
|
|
|
#include <linux/rtc.h>
|
2019-04-10 09:14:20 +00:00
|
|
|
#include <linux/audit.h>
|
2006-10-01 06:28:22 +00:00
|
|
|
|
2013-03-22 18:31:29 +00:00
|
|
|
#include "ntp_internal.h"
|
2015-12-13 04:24:19 +00:00
|
|
|
#include "timekeeping_internal.h"
|
|
|
|
|
2024-09-11 13:17:43 +00:00
|
|
|
/**
|
|
|
|
* struct ntp_data - Structure holding all NTP related state
|
|
|
|
* @tick_usec: USER_HZ period in microseconds
|
2024-09-11 13:17:44 +00:00
|
|
|
* @tick_length: Adjusted tick length
|
|
|
|
* @tick_length_base: Base value for @tick_length
|
2024-09-11 13:17:45 +00:00
|
|
|
* @time_state: State of the clock synchronization
|
|
|
|
* @time_status: Clock status bits
|
2024-09-11 13:17:46 +00:00
|
|
|
* @time_offset: Time adjustment in nanoseconds
|
|
|
|
* @time_constant: PLL time constant
|
2024-09-11 13:17:47 +00:00
|
|
|
* @time_maxerror: Maximum error in microseconds holding the NTP sync distance
|
|
|
|
* (NTP dispersion + delay / 2)
|
|
|
|
* @time_esterror: Estimated error in microseconds holding NTP dispersion
|
2024-09-11 13:17:48 +00:00
|
|
|
* @time_freq: Frequency offset scaled nsecs/secs
|
|
|
|
* @time_reftime: Time at last adjustment in seconds
|
2024-09-11 13:17:49 +00:00
|
|
|
* @time_adjust: Adjustment value
|
|
|
|
* @ntp_tick_adj: Constant boot-param configurable NTP tick adjustment (upscaled)
|
2024-09-11 13:17:50 +00:00
|
|
|
* @ntp_next_leap_sec: Second value of the next pending leapsecond, or TIME64_MAX if no leap
|
2013-03-22 18:52:03 +00:00
|
|
|
*
|
2024-09-11 13:17:51 +00:00
|
|
|
* @pps_valid: PPS signal watchdog counter
|
2024-09-11 13:17:52 +00:00
|
|
|
* @pps_tf: PPS phase median filter
|
2024-09-11 13:17:53 +00:00
|
|
|
* @pps_jitter: PPS current jitter in nanoseconds
|
2024-09-11 13:17:54 +00:00
|
|
|
* @pps_fbase: PPS beginning of the last freq interval
|
2024-09-11 13:17:55 +00:00
|
|
|
* @pps_shift: PPS current interval duration in seconds (shift value)
|
|
|
|
* @pps_intcnt: PPS interval counter
|
2024-09-11 13:17:56 +00:00
|
|
|
* @pps_freq: PPS frequency offset in scaled ns/s
|
|
|
|
* @pps_stabil: PPS current stability in scaled ns/s
|
2024-09-11 13:17:57 +00:00
|
|
|
* @pps_calcnt: PPS monitor: calibration intervals
|
|
|
|
* @pps_jitcnt: PPS monitor: jitter limit exceeded
|
|
|
|
* @pps_stbcnt: PPS monitor: stability limit exceeded
|
|
|
|
* @pps_errcnt: PPS monitor: calibration errors
|
2024-09-11 13:17:51 +00:00
|
|
|
*
|
2024-09-11 13:17:43 +00:00
|
|
|
* Protected by the timekeeping locks.
|
2006-10-01 06:28:22 +00:00
|
|
|
*/
|
2024-09-11 13:17:43 +00:00
|
|
|
struct ntp_data {
|
|
|
|
unsigned long tick_usec;
|
2024-09-11 13:17:44 +00:00
|
|
|
u64 tick_length;
|
|
|
|
u64 tick_length_base;
|
2024-09-11 13:17:45 +00:00
|
|
|
int time_state;
|
|
|
|
int time_status;
|
2024-09-11 13:17:46 +00:00
|
|
|
s64 time_offset;
|
|
|
|
long time_constant;
|
2024-09-11 13:17:47 +00:00
|
|
|
long time_maxerror;
|
|
|
|
long time_esterror;
|
2024-09-11 13:17:48 +00:00
|
|
|
s64 time_freq;
|
|
|
|
time64_t time_reftime;
|
2024-09-11 13:17:49 +00:00
|
|
|
long time_adjust;
|
|
|
|
s64 ntp_tick_adj;
|
2024-09-11 13:17:50 +00:00
|
|
|
time64_t ntp_next_leap_sec;
|
2024-09-11 13:17:51 +00:00
|
|
|
#ifdef CONFIG_NTP_PPS
|
|
|
|
int pps_valid;
|
2024-09-11 13:17:52 +00:00
|
|
|
long pps_tf[3];
|
2024-09-11 13:17:53 +00:00
|
|
|
long pps_jitter;
|
2024-09-11 13:17:54 +00:00
|
|
|
struct timespec64 pps_fbase;
|
2024-09-11 13:17:55 +00:00
|
|
|
int pps_shift;
|
|
|
|
int pps_intcnt;
|
2024-09-11 13:17:56 +00:00
|
|
|
s64 pps_freq;
|
|
|
|
long pps_stabil;
|
2024-09-11 13:17:57 +00:00
|
|
|
long pps_calcnt;
|
|
|
|
long pps_jitcnt;
|
|
|
|
long pps_stbcnt;
|
|
|
|
long pps_errcnt;
|
2024-09-11 13:17:51 +00:00
|
|
|
#endif
|
2024-09-11 13:17:43 +00:00
|
|
|
};
|
2006-10-01 06:28:22 +00:00
|
|
|
|
2024-09-11 13:17:43 +00:00
|
|
|
static struct ntp_data tk_ntp_data = {
|
|
|
|
.tick_usec = USER_TICK_USEC,
|
2024-09-11 13:17:45 +00:00
|
|
|
.time_state = TIME_OK,
|
|
|
|
.time_status = STA_UNSYNC,
|
2024-09-11 13:17:46 +00:00
|
|
|
.time_constant = 2,
|
2024-09-11 13:17:47 +00:00
|
|
|
.time_maxerror = NTP_PHASE_LIMIT,
|
|
|
|
.time_esterror = NTP_PHASE_LIMIT,
|
2024-09-11 13:17:50 +00:00
|
|
|
.ntp_next_leap_sec = TIME64_MAX,
|
2024-09-11 13:17:43 +00:00
|
|
|
};
|
2008-02-20 06:58:42 +00:00
|
|
|
|
2015-06-11 22:54:54 +00:00
|
|
|
#define SECS_PER_DAY 86400
|
2009-02-22 11:11:11 +00:00
|
|
|
#define MAX_TICKADJ 500LL /* usecs */
|
2008-02-20 06:58:42 +00:00
|
|
|
#define MAX_TICKADJ_SCALED \
|
2009-02-22 11:11:11 +00:00
|
|
|
(((MAX_TICKADJ * NSEC_PER_USEC) << NTP_SCALE_SHIFT) / NTP_INTERVAL_FREQ)
|
2019-06-18 15:47:13 +00:00
|
|
|
#define MAX_TAI_OFFSET 100000
|
2006-10-01 06:28:22 +00:00
|
|
|
|
2011-01-13 01:00:56 +00:00
|
|
|
#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) */
|
|
|
|
|
2024-09-11 13:17:39 +00:00
|
|
|
/*
|
|
|
|
* PPS kernel consumer compensates the whole phase error immediately.
|
2011-01-13 01:00:56 +00:00
|
|
|
* Otherwise, reduce the offset by a fixed factor times the time constant.
|
|
|
|
*/
|
2024-09-11 13:17:45 +00:00
|
|
|
static inline s64 ntp_offset_chunk(struct ntp_data *ntpdata, s64 offset)
|
2011-01-13 01:00:56 +00:00
|
|
|
{
|
2024-09-11 13:17:45 +00:00
|
|
|
if (ntpdata->time_status & STA_PPSTIME && ntpdata->time_status & STA_PPSSIGNAL)
|
2011-01-13 01:00:56 +00:00
|
|
|
return offset;
|
|
|
|
else
|
2024-09-11 13:17:46 +00:00
|
|
|
return shift_right(offset, SHIFT_PLL + ntpdata->time_constant);
|
2011-01-13 01:00:56 +00:00
|
|
|
}
|
|
|
|
|
2024-09-11 13:17:55 +00:00
|
|
|
static inline void pps_reset_freq_interval(struct ntp_data *ntpdata)
|
2011-01-13 01:00:56 +00:00
|
|
|
{
|
2024-09-11 13:17:39 +00:00
|
|
|
/* The PPS calibration interval may end surprisingly early */
|
2024-09-11 13:17:55 +00:00
|
|
|
ntpdata->pps_shift = PPS_INTMIN;
|
|
|
|
ntpdata->pps_intcnt = 0;
|
2011-01-13 01:00:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* pps_clear - Clears the PPS state variables
|
2024-09-11 13:17:52 +00:00
|
|
|
* @ntpdata: Pointer to ntp data
|
2011-01-13 01:00:56 +00:00
|
|
|
*/
|
2024-09-11 13:17:52 +00:00
|
|
|
static inline void pps_clear(struct ntp_data *ntpdata)
|
2011-01-13 01:00:56 +00:00
|
|
|
{
|
2024-09-11 13:17:55 +00:00
|
|
|
pps_reset_freq_interval(ntpdata);
|
2024-09-11 13:17:52 +00:00
|
|
|
ntpdata->pps_tf[0] = 0;
|
|
|
|
ntpdata->pps_tf[1] = 0;
|
|
|
|
ntpdata->pps_tf[2] = 0;
|
2024-09-11 13:17:54 +00:00
|
|
|
ntpdata->pps_fbase.tv_sec = ntpdata->pps_fbase.tv_nsec = 0;
|
2024-09-11 13:17:56 +00:00
|
|
|
ntpdata->pps_freq = 0;
|
2011-01-13 01:00:56 +00:00
|
|
|
}
|
|
|
|
|
2024-09-11 13:17:39 +00:00
|
|
|
/*
|
|
|
|
* 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.
|
2011-01-13 01:00:56 +00:00
|
|
|
*/
|
2024-09-11 13:17:45 +00:00
|
|
|
static inline void pps_dec_valid(struct ntp_data *ntpdata)
|
2011-01-13 01:00:56 +00:00
|
|
|
{
|
2024-09-11 13:17:51 +00:00
|
|
|
if (ntpdata->pps_valid > 0) {
|
|
|
|
ntpdata->pps_valid--;
|
|
|
|
} else {
|
2024-09-11 13:17:45 +00:00
|
|
|
ntpdata->time_status &= ~(STA_PPSSIGNAL | STA_PPSJITTER |
|
|
|
|
STA_PPSWANDER | STA_PPSERROR);
|
2024-09-11 13:17:52 +00:00
|
|
|
pps_clear(ntpdata);
|
2011-01-13 01:00:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-09-11 13:17:56 +00:00
|
|
|
static inline void pps_set_freq(struct ntp_data *ntpdata)
|
2011-01-13 01:00:56 +00:00
|
|
|
{
|
2024-09-11 13:17:56 +00:00
|
|
|
ntpdata->pps_freq = ntpdata->time_freq;
|
2011-01-13 01:00:56 +00:00
|
|
|
}
|
|
|
|
|
2024-09-11 13:17:41 +00:00
|
|
|
static inline bool is_error_status(int status)
|
2011-01-13 01:00:56 +00:00
|
|
|
{
|
2014-05-12 13:35:48 +00:00
|
|
|
return (status & (STA_UNSYNC|STA_CLOCKERR))
|
2024-09-11 13:17:39 +00:00
|
|
|
/*
|
|
|
|
* PPS signal lost when either PPS time or PPS frequency
|
|
|
|
* synchronization requested
|
2011-01-13 01:00:56 +00:00
|
|
|
*/
|
2014-05-12 13:35:48 +00:00
|
|
|
|| ((status & (STA_PPSFREQ|STA_PPSTIME))
|
|
|
|
&& !(status & STA_PPSSIGNAL))
|
2024-09-11 13:17:39 +00:00
|
|
|
/*
|
|
|
|
* PPS jitter exceeded when PPS time synchronization
|
|
|
|
* requested
|
|
|
|
*/
|
2014-05-12 13:35:48 +00:00
|
|
|
|| ((status & (STA_PPSTIME|STA_PPSJITTER))
|
2011-01-13 01:00:56 +00:00
|
|
|
== (STA_PPSTIME|STA_PPSJITTER))
|
2024-09-11 13:17:39 +00:00
|
|
|
/*
|
|
|
|
* PPS wander exceeded or calibration error when PPS
|
|
|
|
* frequency synchronization requested
|
2011-01-13 01:00:56 +00:00
|
|
|
*/
|
2014-05-12 13:35:48 +00:00
|
|
|
|| ((status & STA_PPSFREQ)
|
|
|
|
&& (status & (STA_PPSWANDER|STA_PPSERROR)));
|
2011-01-13 01:00:56 +00:00
|
|
|
}
|
|
|
|
|
2024-09-11 13:17:45 +00:00
|
|
|
static inline void pps_fill_timex(struct ntp_data *ntpdata, struct __kernel_timex *txc)
|
2011-01-13 01:00:56 +00:00
|
|
|
{
|
2024-09-11 13:17:56 +00:00
|
|
|
txc->ppsfreq = shift_right((ntpdata->pps_freq >> PPM_SCALE_INV_SHIFT) *
|
2011-01-13 01:00:56 +00:00
|
|
|
PPM_SCALE_INV, NTP_SCALE_SHIFT);
|
2024-09-11 13:17:53 +00:00
|
|
|
txc->jitter = ntpdata->pps_jitter;
|
2024-09-11 13:17:45 +00:00
|
|
|
if (!(ntpdata->time_status & STA_NANO))
|
2024-09-11 13:17:53 +00:00
|
|
|
txc->jitter = ntpdata->pps_jitter / NSEC_PER_USEC;
|
2024-09-11 13:17:55 +00:00
|
|
|
txc->shift = ntpdata->pps_shift;
|
2024-09-11 13:17:56 +00:00
|
|
|
txc->stabil = ntpdata->pps_stabil;
|
2024-09-11 13:17:57 +00:00
|
|
|
txc->jitcnt = ntpdata->pps_jitcnt;
|
|
|
|
txc->calcnt = ntpdata->pps_calcnt;
|
|
|
|
txc->errcnt = ntpdata->pps_errcnt;
|
|
|
|
txc->stbcnt = ntpdata->pps_stbcnt;
|
2011-01-13 01:00:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#else /* !CONFIG_NTP_PPS */
|
|
|
|
|
2024-09-11 13:17:46 +00:00
|
|
|
static inline s64 ntp_offset_chunk(struct ntp_data *ntpdata, s64 offset)
|
2011-01-13 01:00:56 +00:00
|
|
|
{
|
2024-09-11 13:17:46 +00:00
|
|
|
return shift_right(offset, SHIFT_PLL + ntpdata->time_constant);
|
2011-01-13 01:00:56 +00:00
|
|
|
}
|
|
|
|
|
2024-09-11 13:17:55 +00:00
|
|
|
static inline void pps_reset_freq_interval(struct ntp_data *ntpdata) {}
|
2024-09-11 13:17:52 +00:00
|
|
|
static inline void pps_clear(struct ntp_data *ntpdata) {}
|
2024-09-11 13:17:45 +00:00
|
|
|
static inline void pps_dec_valid(struct ntp_data *ntpdata) {}
|
2024-09-11 13:17:56 +00:00
|
|
|
static inline void pps_set_freq(struct ntp_data *ntpdata) {}
|
2011-01-13 01:00:56 +00:00
|
|
|
|
2024-09-11 13:17:41 +00:00
|
|
|
static inline bool is_error_status(int status)
|
2011-01-13 01:00:56 +00:00
|
|
|
{
|
|
|
|
return status & (STA_UNSYNC|STA_CLOCKERR);
|
|
|
|
}
|
|
|
|
|
2024-09-11 13:17:45 +00:00
|
|
|
static inline void pps_fill_timex(struct ntp_data *ntpdata, struct __kernel_timex *txc)
|
2011-01-13 01:00:56 +00:00
|
|
|
{
|
|
|
|
/* 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 */
|
|
|
|
|
2009-02-22 11:42:59 +00:00
|
|
|
/*
|
2024-09-11 13:17:37 +00:00
|
|
|
* Update tick_length and tick_length_base, based on tick_usec, ntp_tick_adj and
|
|
|
|
* time_freq:
|
2009-02-22 11:42:59 +00:00
|
|
|
*/
|
2024-09-11 13:17:43 +00:00
|
|
|
static void ntp_update_frequency(struct ntp_data *ntpdata)
|
2006-10-01 06:28:29 +00:00
|
|
|
{
|
2024-09-11 13:17:43 +00:00
|
|
|
u64 second_length, new_base, tick_usec = (u64)ntpdata->tick_usec;
|
2009-02-22 11:42:59 +00:00
|
|
|
|
2024-09-11 13:17:43 +00:00
|
|
|
second_length = (u64)(tick_usec * NSEC_PER_USEC * USER_HZ) << NTP_SCALE_SHIFT;
|
2009-02-22 11:42:59 +00:00
|
|
|
|
2024-09-11 13:17:49 +00:00
|
|
|
second_length += ntpdata->ntp_tick_adj;
|
2024-09-11 13:17:48 +00:00
|
|
|
second_length += ntpdata->time_freq;
|
2006-10-01 06:28:29 +00:00
|
|
|
|
2009-02-22 11:17:36 +00:00
|
|
|
new_base = div_u64(second_length, NTP_INTERVAL_FREQ);
|
2009-02-19 00:02:22 +00:00
|
|
|
|
|
|
|
/*
|
2024-09-11 13:17:39 +00:00
|
|
|
* Don't wait for the next second_overflow, apply the change to the
|
|
|
|
* tick length immediately:
|
2009-02-19 00:02:22 +00:00
|
|
|
*/
|
2024-09-11 13:17:44 +00:00
|
|
|
ntpdata->tick_length += new_base - ntpdata->tick_length_base;
|
|
|
|
ntpdata->tick_length_base = new_base;
|
2006-10-01 06:28:29 +00:00
|
|
|
}
|
|
|
|
|
2024-09-11 13:17:45 +00:00
|
|
|
static inline s64 ntp_update_offset_fll(struct ntp_data *ntpdata, s64 offset64, long secs)
|
2009-02-22 11:57:49 +00:00
|
|
|
{
|
2024-09-11 13:17:45 +00:00
|
|
|
ntpdata->time_status &= ~STA_MODE;
|
2009-02-22 11:57:49 +00:00
|
|
|
|
|
|
|
if (secs < MINSEC)
|
2009-02-22 12:22:23 +00:00
|
|
|
return 0;
|
2009-02-22 11:57:49 +00:00
|
|
|
|
2024-09-11 13:17:45 +00:00
|
|
|
if (!(ntpdata->time_status & STA_FLL) && (secs <= MAXSEC))
|
2009-02-22 12:22:23 +00:00
|
|
|
return 0;
|
2009-02-22 11:57:49 +00:00
|
|
|
|
2024-09-11 13:17:45 +00:00
|
|
|
ntpdata->time_status |= STA_MODE;
|
2009-02-22 11:57:49 +00:00
|
|
|
|
2012-03-15 16:36:14 +00:00
|
|
|
return div64_long(offset64 << (NTP_SCALE_SHIFT - SHIFT_FLL), secs);
|
2009-02-22 11:57:49 +00:00
|
|
|
}
|
|
|
|
|
2024-09-11 13:17:45 +00:00
|
|
|
static void ntp_update_offset(struct ntp_data *ntpdata, long offset)
|
2008-05-01 11:34:32 +00:00
|
|
|
{
|
2024-09-11 13:17:42 +00:00
|
|
|
s64 freq_adj, offset64;
|
|
|
|
long secs, real_secs;
|
2008-05-01 11:34:32 +00:00
|
|
|
|
2024-09-11 13:17:45 +00:00
|
|
|
if (!(ntpdata->time_status & STA_PLL))
|
2008-05-01 11:34:32 +00:00
|
|
|
return;
|
|
|
|
|
2024-09-11 13:17:45 +00:00
|
|
|
if (!(ntpdata->time_status & STA_NANO)) {
|
2015-12-03 20:46:48 +00:00
|
|
|
/* Make sure the multiplication below won't overflow */
|
|
|
|
offset = clamp(offset, -USEC_PER_SEC, USEC_PER_SEC);
|
2008-05-01 11:34:36 +00:00
|
|
|
offset *= NSEC_PER_USEC;
|
2015-12-03 20:46:48 +00:00
|
|
|
}
|
2008-05-01 11:34:32 +00:00
|
|
|
|
2024-09-11 13:17:39 +00:00
|
|
|
/* Scale the phase adjustment and clamp to the operating range. */
|
2015-12-03 20:46:48 +00:00
|
|
|
offset = clamp(offset, -MAXPHASE, MAXPHASE);
|
2008-05-01 11:34:32 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Select how the frequency is to be controlled
|
|
|
|
* and in which mode (PLL or FLL).
|
|
|
|
*/
|
2024-09-11 13:17:42 +00:00
|
|
|
real_secs = __ktime_get_real_seconds();
|
2024-09-11 13:17:48 +00:00
|
|
|
secs = (long)(real_secs - ntpdata->time_reftime);
|
2024-09-11 13:17:45 +00:00
|
|
|
if (unlikely(ntpdata->time_status & STA_FREQHOLD))
|
2009-02-22 12:29:09 +00:00
|
|
|
secs = 0;
|
|
|
|
|
2024-09-11 13:17:48 +00:00
|
|
|
ntpdata->time_reftime = real_secs;
|
2008-05-01 11:34:32 +00:00
|
|
|
|
2009-02-22 11:57:49 +00:00
|
|
|
offset64 = offset;
|
2024-09-11 13:17:45 +00:00
|
|
|
freq_adj = ntp_update_offset_fll(ntpdata, offset64, secs);
|
2009-02-22 11:57:49 +00:00
|
|
|
|
2010-09-07 14:43:46 +00:00
|
|
|
/*
|
|
|
|
* Clamp update interval to reduce PLL gain with low
|
|
|
|
* sampling rate (e.g. intermittent network connection)
|
|
|
|
* to avoid instability.
|
|
|
|
*/
|
2024-09-11 13:17:46 +00:00
|
|
|
if (unlikely(secs > 1 << (SHIFT_PLL + 1 + ntpdata->time_constant)))
|
|
|
|
secs = 1 << (SHIFT_PLL + 1 + ntpdata->time_constant);
|
2010-09-07 14:43:46 +00:00
|
|
|
|
|
|
|
freq_adj += (offset64 * secs) <<
|
2024-09-11 13:17:46 +00:00
|
|
|
(NTP_SCALE_SHIFT - 2 * (SHIFT_PLL + 2 + ntpdata->time_constant));
|
2009-02-22 11:57:49 +00:00
|
|
|
|
2024-09-11 13:17:48 +00:00
|
|
|
freq_adj = min(freq_adj + ntpdata->time_freq, MAXFREQ_SCALED);
|
2009-02-22 11:57:49 +00:00
|
|
|
|
2024-09-11 13:17:48 +00:00
|
|
|
ntpdata->time_freq = max(freq_adj, -MAXFREQ_SCALED);
|
2009-02-22 11:57:49 +00:00
|
|
|
|
2024-09-11 13:17:46 +00:00
|
|
|
ntpdata->time_offset = div_s64(offset64 << NTP_SCALE_SHIFT, NTP_INTERVAL_FREQ);
|
2008-05-01 11:34:32 +00:00
|
|
|
}
|
|
|
|
|
2024-09-11 13:17:43 +00:00
|
|
|
static void __ntp_clear(struct ntp_data *ntpdata)
|
2006-10-01 06:28:22 +00:00
|
|
|
{
|
2024-09-11 13:17:39 +00:00
|
|
|
/* Stop active adjtime() */
|
2024-09-11 13:17:49 +00:00
|
|
|
ntpdata->time_adjust = 0;
|
2024-09-11 13:17:45 +00:00
|
|
|
ntpdata->time_status |= STA_UNSYNC;
|
2024-09-11 13:17:47 +00:00
|
|
|
ntpdata->time_maxerror = NTP_PHASE_LIMIT;
|
|
|
|
ntpdata->time_esterror = NTP_PHASE_LIMIT;
|
2006-10-01 06:28:22 +00:00
|
|
|
|
2024-09-11 13:17:43 +00:00
|
|
|
ntp_update_frequency(ntpdata);
|
2006-10-01 06:28:22 +00:00
|
|
|
|
2024-09-11 13:17:44 +00:00
|
|
|
ntpdata->tick_length = ntpdata->tick_length_base;
|
2024-09-11 13:17:46 +00:00
|
|
|
ntpdata->time_offset = 0;
|
2011-01-13 01:00:56 +00:00
|
|
|
|
2024-09-11 13:17:50 +00:00
|
|
|
ntpdata->ntp_next_leap_sec = TIME64_MAX;
|
2011-01-13 01:00:56 +00:00
|
|
|
/* Clear PPS state variables */
|
2024-09-11 13:17:52 +00:00
|
|
|
pps_clear(ntpdata);
|
2006-10-01 06:28:22 +00:00
|
|
|
}
|
|
|
|
|
2024-09-11 13:17:43 +00:00
|
|
|
/**
|
|
|
|
* ntp_clear - Clears the NTP state variables
|
|
|
|
*/
|
|
|
|
void ntp_clear(void)
|
|
|
|
{
|
|
|
|
__ntp_clear(&tk_ntp_data);
|
|
|
|
}
|
|
|
|
|
2011-11-14 21:18:07 +00:00
|
|
|
|
|
|
|
u64 ntp_tick_length(void)
|
|
|
|
{
|
2024-09-11 13:17:44 +00:00
|
|
|
return tk_ntp_data.tick_length;
|
2011-11-14 21:18:07 +00:00
|
|
|
}
|
|
|
|
|
time: Prevent early expiry of hrtimers[CLOCK_REALTIME] at the leap second edge
Currently, leapsecond adjustments are done at tick time. As a result,
the leapsecond was applied at the first timer tick *after* the
leapsecond (~1-10ms late depending on HZ), rather then exactly on the
second edge.
This was in part historical from back when we were always tick based,
but correcting this since has been avoided since it adds extra
conditional checks in the gettime fastpath, which has performance
overhead.
However, it was recently pointed out that ABS_TIME CLOCK_REALTIME
timers set for right after the leapsecond could fire a second early,
since some timers may be expired before we trigger the timekeeping
timer, which then applies the leapsecond.
This isn't quite as bad as it sounds, since behaviorally it is similar
to what is possible w/ ntpd made leapsecond adjustments done w/o using
the kernel discipline. Where due to latencies, timers may fire just
prior to the settimeofday call. (Also, one should note that all
applications using CLOCK_REALTIME timers should always be careful,
since they are prone to quirks from settimeofday() disturbances.)
However, the purpose of having the kernel do the leap adjustment is to
avoid such latencies, so I think this is worth fixing.
So in order to properly keep those timers from firing a second early,
this patch modifies the ntp and timekeeping logic so that we keep
enough state so that the update_base_offsets_now accessor, which
provides the hrtimer core the current time, can check and apply the
leapsecond adjustment on the second edge. This prevents the hrtimer
core from expiring timers too early.
This patch does not modify any other time read path, so no additional
overhead is incurred. However, this also means that the leap-second
continues to be applied at tick time for all other read-paths.
Apologies to Richard Cochran, who pushed for similar changes years
ago, which I resisted due to the concerns about the performance
overhead.
While I suspect this isn't extremely critical, folks who care about
strict leap-second correctness will likely want to watch
this. Potentially a -stable candidate eventually.
Originally-suggested-by: Richard Cochran <richardcochran@gmail.com>
Reported-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Reported-by: Prarit Bhargava <prarit@redhat.com>
Signed-off-by: John Stultz <john.stultz@linaro.org>
Cc: Richard Cochran <richardcochran@gmail.com>
Cc: Jan Kara <jack@suse.cz>
Cc: Jiri Bohac <jbohac@suse.cz>
Cc: Shuah Khan <shuahkh@osg.samsung.com>
Cc: Ingo Molnar <mingo@kernel.org>
Link: http://lkml.kernel.org/r/1434063297-28657-4-git-send-email-john.stultz@linaro.org
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
2015-06-11 22:54:55 +00:00
|
|
|
/**
|
|
|
|
* 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)
|
|
|
|
{
|
2024-09-11 13:17:45 +00:00
|
|
|
struct ntp_data *ntpdata = &tk_ntp_data;
|
time: Prevent early expiry of hrtimers[CLOCK_REALTIME] at the leap second edge
Currently, leapsecond adjustments are done at tick time. As a result,
the leapsecond was applied at the first timer tick *after* the
leapsecond (~1-10ms late depending on HZ), rather then exactly on the
second edge.
This was in part historical from back when we were always tick based,
but correcting this since has been avoided since it adds extra
conditional checks in the gettime fastpath, which has performance
overhead.
However, it was recently pointed out that ABS_TIME CLOCK_REALTIME
timers set for right after the leapsecond could fire a second early,
since some timers may be expired before we trigger the timekeeping
timer, which then applies the leapsecond.
This isn't quite as bad as it sounds, since behaviorally it is similar
to what is possible w/ ntpd made leapsecond adjustments done w/o using
the kernel discipline. Where due to latencies, timers may fire just
prior to the settimeofday call. (Also, one should note that all
applications using CLOCK_REALTIME timers should always be careful,
since they are prone to quirks from settimeofday() disturbances.)
However, the purpose of having the kernel do the leap adjustment is to
avoid such latencies, so I think this is worth fixing.
So in order to properly keep those timers from firing a second early,
this patch modifies the ntp and timekeeping logic so that we keep
enough state so that the update_base_offsets_now accessor, which
provides the hrtimer core the current time, can check and apply the
leapsecond adjustment on the second edge. This prevents the hrtimer
core from expiring timers too early.
This patch does not modify any other time read path, so no additional
overhead is incurred. However, this also means that the leap-second
continues to be applied at tick time for all other read-paths.
Apologies to Richard Cochran, who pushed for similar changes years
ago, which I resisted due to the concerns about the performance
overhead.
While I suspect this isn't extremely critical, folks who care about
strict leap-second correctness will likely want to watch
this. Potentially a -stable candidate eventually.
Originally-suggested-by: Richard Cochran <richardcochran@gmail.com>
Reported-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Reported-by: Prarit Bhargava <prarit@redhat.com>
Signed-off-by: John Stultz <john.stultz@linaro.org>
Cc: Richard Cochran <richardcochran@gmail.com>
Cc: Jan Kara <jack@suse.cz>
Cc: Jiri Bohac <jbohac@suse.cz>
Cc: Shuah Khan <shuahkh@osg.samsung.com>
Cc: Ingo Molnar <mingo@kernel.org>
Link: http://lkml.kernel.org/r/1434063297-28657-4-git-send-email-john.stultz@linaro.org
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
2015-06-11 22:54:55 +00:00
|
|
|
ktime_t ret;
|
|
|
|
|
2024-09-11 13:17:45 +00:00
|
|
|
if ((ntpdata->time_state == TIME_INS) && (ntpdata->time_status & STA_INS))
|
2024-09-11 13:17:50 +00:00
|
|
|
return ktime_set(ntpdata->ntp_next_leap_sec, 0);
|
2016-12-25 10:38:40 +00:00
|
|
|
ret = KTIME_MAX;
|
time: Prevent early expiry of hrtimers[CLOCK_REALTIME] at the leap second edge
Currently, leapsecond adjustments are done at tick time. As a result,
the leapsecond was applied at the first timer tick *after* the
leapsecond (~1-10ms late depending on HZ), rather then exactly on the
second edge.
This was in part historical from back when we were always tick based,
but correcting this since has been avoided since it adds extra
conditional checks in the gettime fastpath, which has performance
overhead.
However, it was recently pointed out that ABS_TIME CLOCK_REALTIME
timers set for right after the leapsecond could fire a second early,
since some timers may be expired before we trigger the timekeeping
timer, which then applies the leapsecond.
This isn't quite as bad as it sounds, since behaviorally it is similar
to what is possible w/ ntpd made leapsecond adjustments done w/o using
the kernel discipline. Where due to latencies, timers may fire just
prior to the settimeofday call. (Also, one should note that all
applications using CLOCK_REALTIME timers should always be careful,
since they are prone to quirks from settimeofday() disturbances.)
However, the purpose of having the kernel do the leap adjustment is to
avoid such latencies, so I think this is worth fixing.
So in order to properly keep those timers from firing a second early,
this patch modifies the ntp and timekeeping logic so that we keep
enough state so that the update_base_offsets_now accessor, which
provides the hrtimer core the current time, can check and apply the
leapsecond adjustment on the second edge. This prevents the hrtimer
core from expiring timers too early.
This patch does not modify any other time read path, so no additional
overhead is incurred. However, this also means that the leap-second
continues to be applied at tick time for all other read-paths.
Apologies to Richard Cochran, who pushed for similar changes years
ago, which I resisted due to the concerns about the performance
overhead.
While I suspect this isn't extremely critical, folks who care about
strict leap-second correctness will likely want to watch
this. Potentially a -stable candidate eventually.
Originally-suggested-by: Richard Cochran <richardcochran@gmail.com>
Reported-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Reported-by: Prarit Bhargava <prarit@redhat.com>
Signed-off-by: John Stultz <john.stultz@linaro.org>
Cc: Richard Cochran <richardcochran@gmail.com>
Cc: Jan Kara <jack@suse.cz>
Cc: Jiri Bohac <jbohac@suse.cz>
Cc: Shuah Khan <shuahkh@osg.samsung.com>
Cc: Ingo Molnar <mingo@kernel.org>
Link: http://lkml.kernel.org/r/1434063297-28657-4-git-send-email-john.stultz@linaro.org
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
2015-06-11 22:54:55 +00:00
|
|
|
return ret;
|
|
|
|
}
|
2011-11-14 21:18:07 +00:00
|
|
|
|
2006-10-01 06:28:22 +00:00
|
|
|
/*
|
2024-09-11 13:17:39 +00:00
|
|
|
* This routine handles the overflow of the microsecond field
|
2012-03-15 20:04:03 +00:00
|
|
|
*
|
|
|
|
* 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
|
2006-10-01 06:28:22 +00:00
|
|
|
*/
|
2015-12-13 04:26:42 +00:00
|
|
|
int second_overflow(time64_t secs)
|
2006-10-01 06:28:22 +00:00
|
|
|
{
|
2024-09-11 13:17:44 +00:00
|
|
|
struct ntp_data *ntpdata = &tk_ntp_data;
|
2012-03-15 20:04:03 +00:00
|
|
|
s64 delta;
|
2011-11-14 21:48:36 +00:00
|
|
|
int leap = 0;
|
2015-12-13 04:26:42 +00:00
|
|
|
s32 rem;
|
2012-03-15 20:04:03 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
2024-09-11 13:17:45 +00:00
|
|
|
switch (ntpdata->time_state) {
|
2006-10-01 06:28:22 +00:00
|
|
|
case TIME_OK:
|
2024-09-11 13:17:45 +00:00
|
|
|
if (ntpdata->time_status & STA_INS) {
|
|
|
|
ntpdata->time_state = TIME_INS;
|
2015-12-13 04:26:42 +00:00
|
|
|
div_s64_rem(secs, SECS_PER_DAY, &rem);
|
2024-09-11 13:17:50 +00:00
|
|
|
ntpdata->ntp_next_leap_sec = secs + SECS_PER_DAY - rem;
|
2024-09-11 13:17:45 +00:00
|
|
|
} else if (ntpdata->time_status & STA_DEL) {
|
|
|
|
ntpdata->time_state = TIME_DEL;
|
2015-12-13 04:26:42 +00:00
|
|
|
div_s64_rem(secs + 1, SECS_PER_DAY, &rem);
|
2024-09-11 13:17:50 +00:00
|
|
|
ntpdata->ntp_next_leap_sec = secs + SECS_PER_DAY - rem;
|
time: Prevent early expiry of hrtimers[CLOCK_REALTIME] at the leap second edge
Currently, leapsecond adjustments are done at tick time. As a result,
the leapsecond was applied at the first timer tick *after* the
leapsecond (~1-10ms late depending on HZ), rather then exactly on the
second edge.
This was in part historical from back when we were always tick based,
but correcting this since has been avoided since it adds extra
conditional checks in the gettime fastpath, which has performance
overhead.
However, it was recently pointed out that ABS_TIME CLOCK_REALTIME
timers set for right after the leapsecond could fire a second early,
since some timers may be expired before we trigger the timekeeping
timer, which then applies the leapsecond.
This isn't quite as bad as it sounds, since behaviorally it is similar
to what is possible w/ ntpd made leapsecond adjustments done w/o using
the kernel discipline. Where due to latencies, timers may fire just
prior to the settimeofday call. (Also, one should note that all
applications using CLOCK_REALTIME timers should always be careful,
since they are prone to quirks from settimeofday() disturbances.)
However, the purpose of having the kernel do the leap adjustment is to
avoid such latencies, so I think this is worth fixing.
So in order to properly keep those timers from firing a second early,
this patch modifies the ntp and timekeeping logic so that we keep
enough state so that the update_base_offsets_now accessor, which
provides the hrtimer core the current time, can check and apply the
leapsecond adjustment on the second edge. This prevents the hrtimer
core from expiring timers too early.
This patch does not modify any other time read path, so no additional
overhead is incurred. However, this also means that the leap-second
continues to be applied at tick time for all other read-paths.
Apologies to Richard Cochran, who pushed for similar changes years
ago, which I resisted due to the concerns about the performance
overhead.
While I suspect this isn't extremely critical, folks who care about
strict leap-second correctness will likely want to watch
this. Potentially a -stable candidate eventually.
Originally-suggested-by: Richard Cochran <richardcochran@gmail.com>
Reported-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Reported-by: Prarit Bhargava <prarit@redhat.com>
Signed-off-by: John Stultz <john.stultz@linaro.org>
Cc: Richard Cochran <richardcochran@gmail.com>
Cc: Jan Kara <jack@suse.cz>
Cc: Jiri Bohac <jbohac@suse.cz>
Cc: Shuah Khan <shuahkh@osg.samsung.com>
Cc: Ingo Molnar <mingo@kernel.org>
Link: http://lkml.kernel.org/r/1434063297-28657-4-git-send-email-john.stultz@linaro.org
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
2015-06-11 22:54:55 +00:00
|
|
|
}
|
2006-10-01 06:28:22 +00:00
|
|
|
break;
|
|
|
|
case TIME_INS:
|
2024-09-11 13:17:45 +00:00
|
|
|
if (!(ntpdata->time_status & STA_INS)) {
|
2024-09-11 13:17:50 +00:00
|
|
|
ntpdata->ntp_next_leap_sec = TIME64_MAX;
|
2024-09-11 13:17:45 +00:00
|
|
|
ntpdata->time_state = TIME_OK;
|
2024-09-11 13:17:50 +00:00
|
|
|
} else if (secs == ntpdata->ntp_next_leap_sec) {
|
2012-03-15 20:04:03 +00:00
|
|
|
leap = -1;
|
2024-09-11 13:17:45 +00:00
|
|
|
ntpdata->time_state = TIME_OOP;
|
2024-09-11 13:17:40 +00:00
|
|
|
pr_notice("Clock: inserting leap second 23:59:60 UTC\n");
|
2012-03-15 20:04:03 +00:00
|
|
|
}
|
2006-10-01 06:28:22 +00:00
|
|
|
break;
|
|
|
|
case TIME_DEL:
|
2024-09-11 13:17:45 +00:00
|
|
|
if (!(ntpdata->time_status & STA_DEL)) {
|
2024-09-11 13:17:50 +00:00
|
|
|
ntpdata->ntp_next_leap_sec = TIME64_MAX;
|
2024-09-11 13:17:45 +00:00
|
|
|
ntpdata->time_state = TIME_OK;
|
2024-09-11 13:17:50 +00:00
|
|
|
} else if (secs == ntpdata->ntp_next_leap_sec) {
|
2012-03-15 20:04:03 +00:00
|
|
|
leap = 1;
|
2024-09-11 13:17:50 +00:00
|
|
|
ntpdata->ntp_next_leap_sec = TIME64_MAX;
|
2024-09-11 13:17:45 +00:00
|
|
|
ntpdata->time_state = TIME_WAIT;
|
2024-09-11 13:17:40 +00:00
|
|
|
pr_notice("Clock: deleting leap second 23:59:59 UTC\n");
|
2012-03-15 20:04:03 +00:00
|
|
|
}
|
2006-10-01 06:28:22 +00:00
|
|
|
break;
|
|
|
|
case TIME_OOP:
|
2024-09-11 13:17:50 +00:00
|
|
|
ntpdata->ntp_next_leap_sec = TIME64_MAX;
|
2024-09-11 13:17:45 +00:00
|
|
|
ntpdata->time_state = TIME_WAIT;
|
2012-03-15 20:04:03 +00:00
|
|
|
break;
|
2006-10-01 06:28:22 +00:00
|
|
|
case TIME_WAIT:
|
2024-09-11 13:17:45 +00:00
|
|
|
if (!(ntpdata->time_status & (STA_INS | STA_DEL)))
|
|
|
|
ntpdata->time_state = TIME_OK;
|
2008-05-01 11:34:41 +00:00
|
|
|
break;
|
|
|
|
}
|
2011-11-14 21:48:36 +00:00
|
|
|
|
2008-05-01 11:34:41 +00:00
|
|
|
/* Bump the maxerror field */
|
2024-09-11 13:17:47 +00:00
|
|
|
ntpdata->time_maxerror += MAXFREQ / NSEC_PER_USEC;
|
|
|
|
if (ntpdata->time_maxerror > NTP_PHASE_LIMIT) {
|
|
|
|
ntpdata->time_maxerror = NTP_PHASE_LIMIT;
|
2024-09-11 13:17:45 +00:00
|
|
|
ntpdata->time_status |= STA_UNSYNC;
|
2006-10-01 06:28:22 +00:00
|
|
|
}
|
|
|
|
|
2011-01-13 01:00:56 +00:00
|
|
|
/* Compute the phase adjustment for the next second */
|
2024-09-11 13:17:44 +00:00
|
|
|
ntpdata->tick_length = ntpdata->tick_length_base;
|
2009-02-22 15:06:58 +00:00
|
|
|
|
2024-09-11 13:17:46 +00:00
|
|
|
delta = ntp_offset_chunk(ntpdata, ntpdata->time_offset);
|
|
|
|
ntpdata->time_offset -= delta;
|
2024-09-11 13:17:44 +00:00
|
|
|
ntpdata->tick_length += delta;
|
2006-10-01 06:28:22 +00:00
|
|
|
|
2011-01-13 01:00:56 +00:00
|
|
|
/* Check PPS signal */
|
2024-09-11 13:17:45 +00:00
|
|
|
pps_dec_valid(ntpdata);
|
2011-01-13 01:00:56 +00:00
|
|
|
|
2024-09-11 13:17:49 +00:00
|
|
|
if (!ntpdata->time_adjust)
|
2011-11-14 21:48:36 +00:00
|
|
|
goto out;
|
2009-02-22 11:06:57 +00:00
|
|
|
|
2024-09-11 13:17:49 +00:00
|
|
|
if (ntpdata->time_adjust > MAX_TICKADJ) {
|
|
|
|
ntpdata->time_adjust -= MAX_TICKADJ;
|
2024-09-11 13:17:44 +00:00
|
|
|
ntpdata->tick_length += MAX_TICKADJ_SCALED;
|
2011-11-14 21:48:36 +00:00
|
|
|
goto out;
|
2006-10-01 06:28:22 +00:00
|
|
|
}
|
2009-02-22 11:06:57 +00:00
|
|
|
|
2024-09-11 13:17:49 +00:00
|
|
|
if (ntpdata->time_adjust < -MAX_TICKADJ) {
|
|
|
|
ntpdata->time_adjust += MAX_TICKADJ;
|
2024-09-11 13:17:44 +00:00
|
|
|
ntpdata->tick_length -= MAX_TICKADJ_SCALED;
|
2011-11-14 21:48:36 +00:00
|
|
|
goto out;
|
2009-02-22 11:06:57 +00:00
|
|
|
}
|
|
|
|
|
2024-09-11 13:17:49 +00:00
|
|
|
ntpdata->tick_length += (s64)(ntpdata->time_adjust * NSEC_PER_USEC / NTP_INTERVAL_FREQ)
|
2024-09-11 13:17:44 +00:00
|
|
|
<< NTP_SCALE_SHIFT;
|
2024-09-11 13:17:49 +00:00
|
|
|
ntpdata->time_adjust = 0;
|
2012-03-15 20:04:03 +00:00
|
|
|
|
2011-11-14 21:48:36 +00:00
|
|
|
out:
|
2012-03-15 20:04:03 +00:00
|
|
|
return leap;
|
2006-10-01 06:28:22 +00:00
|
|
|
}
|
|
|
|
|
2020-12-06 21:46:18 +00:00
|
|
|
#if defined(CONFIG_GENERIC_CMOS_UPDATE) || defined(CONFIG_RTC_SYSTOHC)
|
2017-10-13 17:54:33 +00:00
|
|
|
static void sync_hw_clock(struct work_struct *work);
|
2020-12-06 21:46:18 +00:00
|
|
|
static DECLARE_WORK(sync_work, sync_hw_clock);
|
|
|
|
static struct hrtimer sync_hrtimer;
|
2021-01-11 10:39:56 +00:00
|
|
|
#define SYNC_PERIOD_NS (11ULL * 60 * NSEC_PER_SEC)
|
2017-10-13 17:54:33 +00:00
|
|
|
|
2020-12-06 21:46:18 +00:00
|
|
|
static enum hrtimer_restart sync_timer_callback(struct hrtimer *timer)
|
2017-10-13 17:54:33 +00:00
|
|
|
{
|
2021-01-25 14:30:39 +00:00
|
|
|
queue_work(system_freezable_power_efficient_wq, &sync_work);
|
2017-10-13 17:54:33 +00:00
|
|
|
|
2020-12-06 21:46:18 +00:00
|
|
|
return HRTIMER_NORESTART;
|
|
|
|
}
|
2017-10-13 17:54:33 +00:00
|
|
|
|
2020-12-06 21:46:18 +00:00
|
|
|
static void sched_sync_hw_clock(unsigned long offset_nsec, bool retry)
|
|
|
|
{
|
|
|
|
ktime_t exp = ktime_set(ktime_get_real_seconds(), 0);
|
|
|
|
|
|
|
|
if (retry)
|
2021-01-11 10:39:56 +00:00
|
|
|
exp = ktime_add_ns(exp, 2ULL * NSEC_PER_SEC - offset_nsec);
|
2020-12-06 21:46:18 +00:00
|
|
|
else
|
|
|
|
exp = ktime_add_ns(exp, SYNC_PERIOD_NS - offset_nsec);
|
2017-10-13 17:54:33 +00:00
|
|
|
|
2020-12-06 21:46:18 +00:00
|
|
|
hrtimer_start(&sync_hrtimer, exp, HRTIMER_MODE_ABS);
|
2017-10-13 17:54:33 +00:00
|
|
|
}
|
|
|
|
|
2020-12-06 21:46:19 +00:00
|
|
|
/*
|
2020-12-06 21:46:20 +00:00
|
|
|
* Check whether @now is correct versus the required time to update the RTC
|
|
|
|
* and calculate the value which needs to be written to the RTC so that the
|
|
|
|
* next seconds increment of the RTC after the write is aligned with the next
|
|
|
|
* seconds increment of clock REALTIME.
|
2020-12-06 21:46:19 +00:00
|
|
|
*
|
2020-12-06 21:46:20 +00:00
|
|
|
* tsched t1 write(t2.tv_sec - 1sec)) t2 RTC increments seconds
|
2020-12-06 21:46:19 +00:00
|
|
|
*
|
2020-12-06 21:46:20 +00:00
|
|
|
* t2.tv_nsec == 0
|
|
|
|
* tsched = t2 - set_offset_nsec
|
|
|
|
* newval = t2 - NSEC_PER_SEC
|
|
|
|
*
|
|
|
|
* ==> neval = tsched + set_offset_nsec - NSEC_PER_SEC
|
|
|
|
*
|
|
|
|
* As the execution of this code is not guaranteed to happen exactly at
|
|
|
|
* tsched this allows it to happen within a fuzzy region:
|
|
|
|
*
|
|
|
|
* abs(now - tsched) < FUZZ
|
|
|
|
*
|
|
|
|
* If @now is not inside the allowed window the function returns false.
|
2020-12-06 21:46:19 +00:00
|
|
|
*/
|
2020-12-06 21:46:20 +00:00
|
|
|
static inline bool rtc_tv_nsec_ok(unsigned long set_offset_nsec,
|
2020-12-06 21:46:19 +00:00
|
|
|
struct timespec64 *to_set,
|
|
|
|
const struct timespec64 *now)
|
|
|
|
{
|
2021-03-22 21:39:03 +00:00
|
|
|
/* Allowed error in tv_nsec, arbitrarily set to 5 jiffies in ns. */
|
2020-12-06 21:46:19 +00:00
|
|
|
const unsigned long TIME_SET_NSEC_FUZZ = TICK_NSEC * 5;
|
2020-12-06 21:46:20 +00:00
|
|
|
struct timespec64 delay = {.tv_sec = -1,
|
2020-12-06 21:46:19 +00:00
|
|
|
.tv_nsec = set_offset_nsec};
|
|
|
|
|
|
|
|
*to_set = timespec64_add(*now, delay);
|
|
|
|
|
|
|
|
if (to_set->tv_nsec < TIME_SET_NSEC_FUZZ) {
|
|
|
|
to_set->tv_nsec = 0;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (to_set->tv_nsec > NSEC_PER_SEC - TIME_SET_NSEC_FUZZ) {
|
|
|
|
to_set->tv_sec++;
|
|
|
|
to_set->tv_nsec = 0;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-12-06 21:46:21 +00:00
|
|
|
#ifdef CONFIG_GENERIC_CMOS_UPDATE
|
|
|
|
int __weak update_persistent_clock64(struct timespec64 now64)
|
|
|
|
{
|
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
static inline int update_persistent_clock64(struct timespec64 now64)
|
|
|
|
{
|
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-12-06 21:46:19 +00:00
|
|
|
#ifdef CONFIG_RTC_SYSTOHC
|
2020-12-06 21:46:21 +00:00
|
|
|
/* Save NTP synchronized time to the RTC */
|
|
|
|
static int update_rtc(struct timespec64 *to_set, unsigned long *offset_nsec)
|
2020-12-06 21:46:19 +00:00
|
|
|
{
|
|
|
|
struct rtc_device *rtc;
|
|
|
|
struct rtc_time tm;
|
|
|
|
int err = -ENODEV;
|
|
|
|
|
|
|
|
rtc = rtc_class_open(CONFIG_RTC_SYSTOHC_DEVICE);
|
|
|
|
if (!rtc)
|
2020-12-06 21:46:21 +00:00
|
|
|
return -ENODEV;
|
2020-12-06 21:46:19 +00:00
|
|
|
|
|
|
|
if (!rtc->ops || !rtc->ops->set_time)
|
|
|
|
goto out_close;
|
|
|
|
|
2020-12-06 21:46:21 +00:00
|
|
|
/* First call might not have the correct offset */
|
|
|
|
if (*offset_nsec == rtc->set_offset_nsec) {
|
|
|
|
rtc_time64_to_tm(to_set->tv_sec, &tm);
|
|
|
|
err = rtc_set_time(rtc, &tm);
|
|
|
|
} else {
|
|
|
|
/* Store the update offset and let the caller try again */
|
|
|
|
*offset_nsec = rtc->set_offset_nsec;
|
|
|
|
err = -EAGAIN;
|
2020-12-06 21:46:19 +00:00
|
|
|
}
|
|
|
|
out_close:
|
|
|
|
rtc_class_close(rtc);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
#else
|
2020-12-06 21:46:21 +00:00
|
|
|
static inline int update_rtc(struct timespec64 *to_set, unsigned long *offset_nsec)
|
2015-04-02 03:34:23 +00:00
|
|
|
{
|
2018-08-14 12:15:23 +00:00
|
|
|
return -ENODEV;
|
2015-04-02 03:34:23 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2024-09-11 13:17:41 +00:00
|
|
|
/**
|
|
|
|
* ntp_synced - Tells whether the NTP status is not UNSYNC
|
|
|
|
* Returns: true if not UNSYNC, false otherwise
|
|
|
|
*/
|
|
|
|
static inline bool ntp_synced(void)
|
|
|
|
{
|
2024-09-11 13:17:45 +00:00
|
|
|
return !(tk_ntp_data.time_status & STA_UNSYNC);
|
2024-09-11 13:17:41 +00:00
|
|
|
}
|
|
|
|
|
2017-10-13 17:54:33 +00:00
|
|
|
/*
|
|
|
|
* If we have an externally synchronized Linux clock, then update RTC clock
|
|
|
|
* accordingly every ~11 minutes. Generally RTCs can only store second
|
|
|
|
* precision, but many RTCs will adjust the phase of their second tick to
|
|
|
|
* match the moment of update. This infrastructure arranges to call to the RTC
|
|
|
|
* set at the correct moment to phase synchronize the RTC second tick over
|
|
|
|
* with the kernel clock.
|
|
|
|
*/
|
|
|
|
static void sync_hw_clock(struct work_struct *work)
|
|
|
|
{
|
2020-12-06 21:46:21 +00:00
|
|
|
/*
|
|
|
|
* The default synchronization offset is 500ms for the deprecated
|
|
|
|
* update_persistent_clock64() under the assumption that it uses
|
|
|
|
* the infamous CMOS clock (MC146818).
|
|
|
|
*/
|
|
|
|
static unsigned long offset_nsec = NSEC_PER_SEC / 2;
|
|
|
|
struct timespec64 now, to_set;
|
|
|
|
int res = -EAGAIN;
|
|
|
|
|
2020-12-06 21:46:18 +00:00
|
|
|
/*
|
|
|
|
* Don't update if STA_UNSYNC is set and if ntp_notify_cmos_timer()
|
|
|
|
* managed to schedule the work between the timer firing and the
|
|
|
|
* work being able to rearm the timer. Wait for the timer to expire.
|
|
|
|
*/
|
|
|
|
if (!ntp_synced() || hrtimer_is_queued(&sync_hrtimer))
|
2017-10-13 17:54:33 +00:00
|
|
|
return;
|
2007-07-21 11:37:37 +00:00
|
|
|
|
2020-12-06 21:46:21 +00:00
|
|
|
ktime_get_real_ts64(&now);
|
|
|
|
/* If @now is not in the allowed window, try again */
|
|
|
|
if (!rtc_tv_nsec_ok(offset_nsec, &to_set, &now))
|
|
|
|
goto rearm;
|
|
|
|
|
|
|
|
/* Take timezone adjusted RTCs into account */
|
|
|
|
if (persistent_clock_is_local)
|
|
|
|
to_set.tv_sec -= (sys_tz.tz_minuteswest * 60);
|
|
|
|
|
|
|
|
/* Try the legacy RTC first. */
|
|
|
|
res = update_persistent_clock64(to_set);
|
|
|
|
if (res != -ENODEV)
|
|
|
|
goto rearm;
|
2017-10-13 17:54:33 +00:00
|
|
|
|
2020-12-06 21:46:21 +00:00
|
|
|
/* Try the RTC class */
|
|
|
|
res = update_rtc(&to_set, &offset_nsec);
|
|
|
|
if (res == -ENODEV)
|
|
|
|
return;
|
|
|
|
rearm:
|
|
|
|
sched_sync_hw_clock(offset_nsec, res != 0);
|
2007-07-21 11:37:37 +00:00
|
|
|
}
|
|
|
|
|
ntp: Make sure RTC is synchronized when time goes backwards
sync_hw_clock() is normally called every 11 minutes when time is
synchronized. This issue is that this periodic timer uses the REALTIME
clock, so when time moves backwards (the NTP server jumps into the past),
the timer expires late.
If the timer expires late, which can be days later, the RTC will no longer
be updated, which is an issue if the device is abruptly powered OFF during
this period. When the device will restart (when powered ON), it will have
the date prior to the ADJ_SETOFFSET call.
A normal NTP server should not jump in the past like that, but it is
possible... Another way of reproducing this issue is to use phc2sys to
synchronize the REALTIME clock with, for example, an IRIG timecode with
the source always starting at the same date (not synchronized).
Also, if the time jump in the future by less than 11 minutes, the RTC may
not be updated immediately (minor issue). Consider the following scenario:
- Time is synchronized, and sync_hw_clock() was just called (the timer
expires in 11 minutes).
- A time jump is realized in the future by a couple of minutes.
- The time is synchronized again.
- Users may expect that RTC to be updated as soon as possible, and not
after 11 minutes (for the same reason, if a power loss occurs in this
period).
Cancel periodic timer on any time jump (ADJ_SETOFFSET) greater than or
equal to 1s. The timer will be relaunched at the end of do_adjtimex() if
NTP is still considered synced. Otherwise the timer will be relaunched
later when NTP is synced. This way, when the time is synchronized again,
the RTC is updated after less than 2 seconds.
Signed-off-by: Benjamin ROBIN <dev@benjarobin.fr>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lore.kernel.org/all/20240908140836.203911-1-dev@benjarobin.fr
2024-09-08 14:08:36 +00:00
|
|
|
void ntp_notify_cmos_timer(bool offset_set)
|
2006-10-01 06:28:22 +00:00
|
|
|
{
|
ntp: Make sure RTC is synchronized when time goes backwards
sync_hw_clock() is normally called every 11 minutes when time is
synchronized. This issue is that this periodic timer uses the REALTIME
clock, so when time moves backwards (the NTP server jumps into the past),
the timer expires late.
If the timer expires late, which can be days later, the RTC will no longer
be updated, which is an issue if the device is abruptly powered OFF during
this period. When the device will restart (when powered ON), it will have
the date prior to the ADJ_SETOFFSET call.
A normal NTP server should not jump in the past like that, but it is
possible... Another way of reproducing this issue is to use phc2sys to
synchronize the REALTIME clock with, for example, an IRIG timecode with
the source always starting at the same date (not synchronized).
Also, if the time jump in the future by less than 11 minutes, the RTC may
not be updated immediately (minor issue). Consider the following scenario:
- Time is synchronized, and sync_hw_clock() was just called (the timer
expires in 11 minutes).
- A time jump is realized in the future by a couple of minutes.
- The time is synchronized again.
- Users may expect that RTC to be updated as soon as possible, and not
after 11 minutes (for the same reason, if a power loss occurs in this
period).
Cancel periodic timer on any time jump (ADJ_SETOFFSET) greater than or
equal to 1s. The timer will be relaunched at the end of do_adjtimex() if
NTP is still considered synced. Otherwise the timer will be relaunched
later when NTP is synced. This way, when the time is synchronized again,
the RTC is updated after less than 2 seconds.
Signed-off-by: Benjamin ROBIN <dev@benjarobin.fr>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lore.kernel.org/all/20240908140836.203911-1-dev@benjarobin.fr
2024-09-08 14:08:36 +00:00
|
|
|
/*
|
|
|
|
* If the time jumped (using ADJ_SETOFFSET) cancels sync timer,
|
|
|
|
* which may have been running if the time was synchronized
|
|
|
|
* prior to the ADJ_SETOFFSET call.
|
|
|
|
*/
|
|
|
|
if (offset_set)
|
|
|
|
hrtimer_cancel(&sync_hrtimer);
|
|
|
|
|
2020-12-06 21:46:18 +00:00
|
|
|
/*
|
|
|
|
* When the work is currently executed but has not yet the timer
|
|
|
|
* rearmed this queues the work immediately again. No big issue,
|
|
|
|
* just a pointless work scheduled.
|
|
|
|
*/
|
|
|
|
if (ntp_synced() && !hrtimer_is_queued(&sync_hrtimer))
|
2021-01-25 14:30:39 +00:00
|
|
|
queue_work(system_freezable_power_efficient_wq, &sync_work);
|
2020-12-06 21:46:18 +00:00
|
|
|
}
|
2007-07-21 11:37:37 +00:00
|
|
|
|
2020-12-06 21:46:18 +00:00
|
|
|
static void __init ntp_init_cmos_sync(void)
|
|
|
|
{
|
|
|
|
hrtimer_init(&sync_hrtimer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
|
|
|
|
sync_hrtimer.function = sync_timer_callback;
|
2017-10-13 17:54:33 +00:00
|
|
|
}
|
2020-12-06 21:46:18 +00:00
|
|
|
#else /* CONFIG_GENERIC_CMOS_UPDATE) || defined(CONFIG_RTC_SYSTOHC) */
|
|
|
|
static inline void __init ntp_init_cmos_sync(void) { }
|
|
|
|
#endif /* !CONFIG_GENERIC_CMOS_UPDATE) || defined(CONFIG_RTC_SYSTOHC) */
|
2009-02-22 14:15:32 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Propagate a new txc->status value into the NTP state:
|
|
|
|
*/
|
2024-09-11 13:17:45 +00:00
|
|
|
static inline void process_adj_status(struct ntp_data *ntpdata, const struct __kernel_timex *txc)
|
2009-02-22 14:15:32 +00:00
|
|
|
{
|
2024-09-11 13:17:45 +00:00
|
|
|
if ((ntpdata->time_status & STA_PLL) && !(txc->status & STA_PLL)) {
|
|
|
|
ntpdata->time_state = TIME_OK;
|
|
|
|
ntpdata->time_status = STA_UNSYNC;
|
2024-09-11 13:17:50 +00:00
|
|
|
ntpdata->ntp_next_leap_sec = TIME64_MAX;
|
2024-09-11 13:17:39 +00:00
|
|
|
/* Restart PPS frequency calibration */
|
2024-09-11 13:17:55 +00:00
|
|
|
pps_reset_freq_interval(ntpdata);
|
2009-02-22 14:15:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If we turn on PLL adjustments then reset the
|
|
|
|
* reference time to current time.
|
|
|
|
*/
|
2024-09-11 13:17:45 +00:00
|
|
|
if (!(ntpdata->time_status & STA_PLL) && (txc->status & STA_PLL))
|
2024-09-11 13:17:48 +00:00
|
|
|
ntpdata->time_reftime = __ktime_get_real_seconds();
|
2009-02-22 14:15:32 +00:00
|
|
|
|
2024-09-11 13:17:45 +00:00
|
|
|
/* only set allowed bits */
|
|
|
|
ntpdata->time_status &= STA_RONLY;
|
|
|
|
ntpdata->time_status |= txc->status & ~STA_RONLY;
|
2009-02-22 14:15:32 +00:00
|
|
|
}
|
2012-04-27 08:12:41 +00:00
|
|
|
|
2024-09-11 13:17:43 +00:00
|
|
|
static inline void process_adjtimex_modes(struct ntp_data *ntpdata, const struct __kernel_timex *txc,
|
2018-07-03 05:44:21 +00:00
|
|
|
s32 *time_tai)
|
2009-02-22 14:15:32 +00:00
|
|
|
{
|
|
|
|
if (txc->modes & ADJ_STATUS)
|
2024-09-11 13:17:45 +00:00
|
|
|
process_adj_status(ntpdata, txc);
|
2009-02-22 14:15:32 +00:00
|
|
|
|
|
|
|
if (txc->modes & ADJ_NANO)
|
2024-09-11 13:17:45 +00:00
|
|
|
ntpdata->time_status |= STA_NANO;
|
2009-02-22 14:35:18 +00:00
|
|
|
|
2009-02-22 14:15:32 +00:00
|
|
|
if (txc->modes & ADJ_MICRO)
|
2024-09-11 13:17:45 +00:00
|
|
|
ntpdata->time_status &= ~STA_NANO;
|
2009-02-22 14:15:32 +00:00
|
|
|
|
|
|
|
if (txc->modes & ADJ_FREQUENCY) {
|
2024-09-11 13:17:48 +00:00
|
|
|
ntpdata->time_freq = txc->freq * PPM_SCALE;
|
|
|
|
ntpdata->time_freq = min(ntpdata->time_freq, MAXFREQ_SCALED);
|
|
|
|
ntpdata->time_freq = max(ntpdata->time_freq, -MAXFREQ_SCALED);
|
2024-09-11 13:17:39 +00:00
|
|
|
/* Update pps_freq */
|
2024-09-11 13:17:56 +00:00
|
|
|
pps_set_freq(ntpdata);
|
2009-02-22 14:15:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (txc->modes & ADJ_MAXERROR)
|
2024-09-11 13:17:47 +00:00
|
|
|
ntpdata->time_maxerror = clamp(txc->maxerror, 0, NTP_PHASE_LIMIT);
|
2009-02-22 14:35:18 +00:00
|
|
|
|
2009-02-22 14:15:32 +00:00
|
|
|
if (txc->modes & ADJ_ESTERROR)
|
2024-09-11 13:17:47 +00:00
|
|
|
ntpdata->time_esterror = clamp(txc->esterror, 0, NTP_PHASE_LIMIT);
|
2009-02-22 14:15:32 +00:00
|
|
|
|
|
|
|
if (txc->modes & ADJ_TIMECONST) {
|
2024-09-11 13:17:46 +00:00
|
|
|
ntpdata->time_constant = clamp(txc->constant, 0, MAXTC);
|
2024-09-11 13:17:45 +00:00
|
|
|
if (!(ntpdata->time_status & STA_NANO))
|
2024-09-11 13:17:46 +00:00
|
|
|
ntpdata->time_constant += 4;
|
|
|
|
ntpdata->time_constant = clamp(ntpdata->time_constant, 0, MAXTC);
|
2009-02-22 14:15:32 +00:00
|
|
|
}
|
|
|
|
|
2024-09-11 13:17:45 +00:00
|
|
|
if (txc->modes & ADJ_TAI && txc->constant >= 0 && txc->constant <= MAX_TAI_OFFSET)
|
2012-05-03 19:30:07 +00:00
|
|
|
*time_tai = txc->constant;
|
2009-02-22 14:15:32 +00:00
|
|
|
|
|
|
|
if (txc->modes & ADJ_OFFSET)
|
2024-09-11 13:17:45 +00:00
|
|
|
ntp_update_offset(ntpdata, txc->offset);
|
2009-02-22 14:35:18 +00:00
|
|
|
|
2009-02-22 14:15:32 +00:00
|
|
|
if (txc->modes & ADJ_TICK)
|
2024-09-11 13:17:43 +00:00
|
|
|
ntpdata->tick_usec = txc->tick;
|
2009-02-22 14:15:32 +00:00
|
|
|
|
|
|
|
if (txc->modes & (ADJ_TICK|ADJ_FREQUENCY|ADJ_OFFSET))
|
2024-09-11 13:17:43 +00:00
|
|
|
ntp_update_frequency(ntpdata);
|
2009-02-22 14:15:32 +00:00
|
|
|
}
|
|
|
|
|
2013-03-22 18:59:04 +00:00
|
|
|
/*
|
2024-09-11 13:17:39 +00:00
|
|
|
* adjtimex() mainly allows reading (and writing, if superuser) of
|
2013-03-22 18:59:04 +00:00
|
|
|
* kernel time-keeping variables. used by xntpd.
|
|
|
|
*/
|
2018-07-03 05:44:21 +00:00
|
|
|
int __do_adjtimex(struct __kernel_timex *txc, const struct timespec64 *ts,
|
2019-04-10 09:14:20 +00:00
|
|
|
s32 *time_tai, struct audit_ntp_data *ad)
|
2013-03-22 18:59:04 +00:00
|
|
|
{
|
2024-09-11 13:17:43 +00:00
|
|
|
struct ntp_data *ntpdata = &tk_ntp_data;
|
2013-03-22 18:59:04 +00:00
|
|
|
int result;
|
|
|
|
|
2008-08-20 23:46:08 +00:00
|
|
|
if (txc->modes & ADJ_ADJTIME) {
|
2024-09-11 13:17:49 +00:00
|
|
|
long save_adjust = ntpdata->time_adjust;
|
2008-08-20 23:46:08 +00:00
|
|
|
|
|
|
|
if (!(txc->modes & ADJ_OFFSET_READONLY)) {
|
|
|
|
/* adjtime() is independent from ntp_adjtime() */
|
2024-09-11 13:17:49 +00:00
|
|
|
ntpdata->time_adjust = txc->offset;
|
2024-09-11 13:17:43 +00:00
|
|
|
ntp_update_frequency(ntpdata);
|
2019-04-10 09:14:20 +00:00
|
|
|
|
|
|
|
audit_ntp_set_old(ad, AUDIT_NTP_ADJUST, save_adjust);
|
2024-09-11 13:17:49 +00:00
|
|
|
audit_ntp_set_new(ad, AUDIT_NTP_ADJUST, ntpdata->time_adjust);
|
2008-08-20 23:46:08 +00:00
|
|
|
}
|
|
|
|
txc->offset = save_adjust;
|
2009-02-22 14:35:18 +00:00
|
|
|
} else {
|
|
|
|
/* If there are input parameters, then process them: */
|
2019-04-10 09:14:20 +00:00
|
|
|
if (txc->modes) {
|
2024-09-11 13:17:46 +00:00
|
|
|
audit_ntp_set_old(ad, AUDIT_NTP_OFFSET, ntpdata->time_offset);
|
2024-09-11 13:17:48 +00:00
|
|
|
audit_ntp_set_old(ad, AUDIT_NTP_FREQ, ntpdata->time_freq);
|
2024-09-11 13:17:45 +00:00
|
|
|
audit_ntp_set_old(ad, AUDIT_NTP_STATUS, ntpdata->time_status);
|
2019-04-10 09:14:20 +00:00
|
|
|
audit_ntp_set_old(ad, AUDIT_NTP_TAI, *time_tai);
|
2024-09-11 13:17:43 +00:00
|
|
|
audit_ntp_set_old(ad, AUDIT_NTP_TICK, ntpdata->tick_usec);
|
2019-04-10 09:14:20 +00:00
|
|
|
|
2024-09-11 13:17:43 +00:00
|
|
|
process_adjtimex_modes(ntpdata, txc, time_tai);
|
2008-05-01 11:34:33 +00:00
|
|
|
|
2024-09-11 13:17:46 +00:00
|
|
|
audit_ntp_set_new(ad, AUDIT_NTP_OFFSET, ntpdata->time_offset);
|
2024-09-11 13:17:48 +00:00
|
|
|
audit_ntp_set_new(ad, AUDIT_NTP_FREQ, ntpdata->time_freq);
|
2024-09-11 13:17:45 +00:00
|
|
|
audit_ntp_set_new(ad, AUDIT_NTP_STATUS, ntpdata->time_status);
|
2019-04-10 09:14:20 +00:00
|
|
|
audit_ntp_set_new(ad, AUDIT_NTP_TAI, *time_tai);
|
2024-09-11 13:17:43 +00:00
|
|
|
audit_ntp_set_new(ad, AUDIT_NTP_TICK, ntpdata->tick_usec);
|
2019-04-10 09:14:20 +00:00
|
|
|
}
|
|
|
|
|
2024-09-11 13:17:46 +00:00
|
|
|
txc->offset = shift_right(ntpdata->time_offset * NTP_INTERVAL_FREQ, NTP_SCALE_SHIFT);
|
2024-09-11 13:17:45 +00:00
|
|
|
if (!(ntpdata->time_status & STA_NANO))
|
2024-11-25 12:16:09 +00:00
|
|
|
txc->offset = div_s64(txc->offset, NSEC_PER_USEC);
|
2009-02-22 14:35:18 +00:00
|
|
|
}
|
2008-08-20 23:46:08 +00:00
|
|
|
|
2024-09-11 13:17:45 +00:00
|
|
|
result = ntpdata->time_state;
|
|
|
|
if (is_error_status(ntpdata->time_status))
|
2006-10-01 06:28:22 +00:00
|
|
|
result = TIME_ERROR;
|
|
|
|
|
2024-09-11 13:17:48 +00:00
|
|
|
txc->freq = shift_right((ntpdata->time_freq >> PPM_SCALE_INV_SHIFT) *
|
2009-02-22 14:48:43 +00:00
|
|
|
PPM_SCALE_INV, NTP_SCALE_SHIFT);
|
2024-09-11 13:17:47 +00:00
|
|
|
txc->maxerror = ntpdata->time_maxerror;
|
|
|
|
txc->esterror = ntpdata->time_esterror;
|
2024-09-11 13:17:45 +00:00
|
|
|
txc->status = ntpdata->time_status;
|
2024-09-11 13:17:46 +00:00
|
|
|
txc->constant = ntpdata->time_constant;
|
2006-10-01 06:28:29 +00:00
|
|
|
txc->precision = 1;
|
2008-05-01 11:34:34 +00:00
|
|
|
txc->tolerance = MAXFREQ_SCALED / PPM_SCALE;
|
2024-09-11 13:17:43 +00:00
|
|
|
txc->tick = ntpdata->tick_usec;
|
2013-03-22 19:28:15 +00:00
|
|
|
txc->tai = *time_tai;
|
2006-10-01 06:28:22 +00:00
|
|
|
|
2024-09-11 13:17:39 +00:00
|
|
|
/* Fill PPS status fields */
|
2024-09-11 13:17:45 +00:00
|
|
|
pps_fill_timex(ntpdata, txc);
|
2009-02-22 14:35:18 +00:00
|
|
|
|
2019-11-08 20:34:24 +00:00
|
|
|
txc->time.tv_sec = ts->tv_sec;
|
2013-03-22 19:28:15 +00:00
|
|
|
txc->time.tv_usec = ts->tv_nsec;
|
2024-09-11 13:17:45 +00:00
|
|
|
if (!(ntpdata->time_status & STA_NANO))
|
2018-07-03 05:44:21 +00:00
|
|
|
txc->time.tv_usec = ts->tv_nsec / NSEC_PER_USEC;
|
2008-05-01 11:34:32 +00:00
|
|
|
|
2015-06-11 22:54:56 +00:00
|
|
|
/* Handle leapsec adjustments */
|
2024-09-11 13:17:50 +00:00
|
|
|
if (unlikely(ts->tv_sec >= ntpdata->ntp_next_leap_sec)) {
|
2024-09-11 13:17:45 +00:00
|
|
|
if ((ntpdata->time_state == TIME_INS) && (ntpdata->time_status & STA_INS)) {
|
2015-06-11 22:54:56 +00:00
|
|
|
result = TIME_OOP;
|
|
|
|
txc->tai++;
|
|
|
|
txc->time.tv_sec--;
|
|
|
|
}
|
2024-09-11 13:17:45 +00:00
|
|
|
if ((ntpdata->time_state == TIME_DEL) && (ntpdata->time_status & STA_DEL)) {
|
2015-06-11 22:54:56 +00:00
|
|
|
result = TIME_WAIT;
|
|
|
|
txc->tai--;
|
|
|
|
txc->time.tv_sec++;
|
|
|
|
}
|
2024-09-11 13:17:50 +00:00
|
|
|
if ((ntpdata->time_state == TIME_OOP) && (ts->tv_sec == ntpdata->ntp_next_leap_sec))
|
2015-06-11 22:54:56 +00:00
|
|
|
result = TIME_WAIT;
|
|
|
|
}
|
|
|
|
|
2008-05-01 11:34:32 +00:00
|
|
|
return result;
|
2006-10-01 06:28:22 +00:00
|
|
|
}
|
time: remove obsolete CLOCK_TICK_ADJUST
The first version of the ntp_interval/tick_length inconsistent usage patch was
recently merged as bbe4d18ac2e058c56adb0cd71f49d9ed3216a405
http://git.kernel.org/gitweb.cgi?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=bbe4d18ac2e058c56adb0cd71f49d9ed3216a405
While the fix did greatly improve the situation, it was correctly pointed out
by Roman that it does have a small bug: If the users change clocksources after
the system has been running and NTP has made corrections, the correctoins made
against the old clocksource will be applied against the new clocksource,
causing error.
The second attempt, which corrects the issue in the NTP_INTERVAL_LENGTH
definition has also made it up-stream as commit
e13a2e61dd5152f5499d2003470acf9c838eab84
http://git.kernel.org/gitweb.cgi?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=e13a2e61dd5152f5499d2003470acf9c838eab84
Roman has correctly pointed out that CLOCK_TICK_ADJUST is calculated
based on the PIT's frequency, and isn't really relevant to non-PIT
driven clocksources (that is, clocksources other then jiffies and pit).
This patch reverts both of those changes, and simply removes
CLOCK_TICK_ADJUST.
This does remove the granularity error correction for users of PIT and Jiffies
clocksource users, but the granularity error but for the majority of users, it
should be within the 500ppm range NTP can accommodate for.
For systems that have granularity errors greater then 500ppm, the
"ntp_tick_adj=" boot option can be used to compensate.
[johnstul@us.ibm.com: provided changelog]
[mattilinnanvuori@yahoo.com: maek ntp_tick_adj static]
Signed-off-by: Roman Zippel <zippel@linux-m68k.org>
Acked-by: john stultz <johnstul@us.ibm.com>
Signed-off-by: Matti Linnanvuori <mattilinnanvuori@yahoo.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Cc: mingo@elte.hu
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
2008-03-04 23:14:26 +00:00
|
|
|
|
2011-01-13 01:00:56 +00:00
|
|
|
#ifdef CONFIG_NTP_PPS
|
|
|
|
|
2024-09-11 13:17:39 +00:00
|
|
|
/*
|
|
|
|
* struct pps_normtime is basically a struct timespec, but it is
|
2011-01-13 01:00:56 +00:00
|
|
|
* 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 ]
|
2024-09-11 13:17:39 +00:00
|
|
|
* while timespec.tv_nsec has a range of [0, NSEC_PER_SEC)
|
|
|
|
*/
|
2011-01-13 01:00:56 +00:00
|
|
|
struct pps_normtime {
|
2015-09-28 20:21:28 +00:00
|
|
|
s64 sec; /* seconds */
|
2011-01-13 01:00:56 +00:00
|
|
|
long nsec; /* nanoseconds */
|
|
|
|
};
|
|
|
|
|
2024-09-11 13:17:39 +00:00
|
|
|
/*
|
|
|
|
* Normalize the timestamp so that nsec is in the
|
|
|
|
* [ -NSEC_PER_SEC / 2, NSEC_PER_SEC / 2 ] interval
|
|
|
|
*/
|
2015-09-28 20:21:28 +00:00
|
|
|
static inline struct pps_normtime pps_normalize_ts(struct timespec64 ts)
|
2011-01-13 01:00:56 +00:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2024-09-11 13:17:39 +00:00
|
|
|
/* Get current phase correction and jitter */
|
2024-09-11 13:17:52 +00:00
|
|
|
static inline long pps_phase_filter_get(struct ntp_data *ntpdata, long *jitter)
|
2011-01-13 01:00:56 +00:00
|
|
|
{
|
2024-09-11 13:17:52 +00:00
|
|
|
*jitter = ntpdata->pps_tf[0] - ntpdata->pps_tf[1];
|
2011-01-13 01:00:56 +00:00
|
|
|
if (*jitter < 0)
|
|
|
|
*jitter = -*jitter;
|
|
|
|
|
|
|
|
/* TODO: test various filters */
|
2024-09-11 13:17:52 +00:00
|
|
|
return ntpdata->pps_tf[0];
|
2011-01-13 01:00:56 +00:00
|
|
|
}
|
|
|
|
|
2024-09-11 13:17:39 +00:00
|
|
|
/* Add the sample to the phase filter */
|
2024-09-11 13:17:52 +00:00
|
|
|
static inline void pps_phase_filter_add(struct ntp_data *ntpdata, long err)
|
2011-01-13 01:00:56 +00:00
|
|
|
{
|
2024-09-11 13:17:52 +00:00
|
|
|
ntpdata->pps_tf[2] = ntpdata->pps_tf[1];
|
|
|
|
ntpdata->pps_tf[1] = ntpdata->pps_tf[0];
|
|
|
|
ntpdata->pps_tf[0] = err;
|
2011-01-13 01:00:56 +00:00
|
|
|
}
|
|
|
|
|
2024-09-11 13:17:39 +00:00
|
|
|
/*
|
|
|
|
* Decrease frequency calibration interval length. It is halved after four
|
|
|
|
* consecutive unstable intervals.
|
2011-01-13 01:00:56 +00:00
|
|
|
*/
|
2024-09-11 13:17:55 +00:00
|
|
|
static inline void pps_dec_freq_interval(struct ntp_data *ntpdata)
|
2011-01-13 01:00:56 +00:00
|
|
|
{
|
2024-09-11 13:17:55 +00:00
|
|
|
if (--ntpdata->pps_intcnt <= -PPS_INTCOUNT) {
|
|
|
|
ntpdata->pps_intcnt = -PPS_INTCOUNT;
|
|
|
|
if (ntpdata->pps_shift > PPS_INTMIN) {
|
|
|
|
ntpdata->pps_shift--;
|
|
|
|
ntpdata->pps_intcnt = 0;
|
2011-01-13 01:00:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-09-11 13:17:39 +00:00
|
|
|
/*
|
|
|
|
* Increase frequency calibration interval length. It is doubled after
|
|
|
|
* four consecutive stable intervals.
|
2011-01-13 01:00:56 +00:00
|
|
|
*/
|
2024-09-11 13:17:55 +00:00
|
|
|
static inline void pps_inc_freq_interval(struct ntp_data *ntpdata)
|
2011-01-13 01:00:56 +00:00
|
|
|
{
|
2024-09-11 13:17:55 +00:00
|
|
|
if (++ntpdata->pps_intcnt >= PPS_INTCOUNT) {
|
|
|
|
ntpdata->pps_intcnt = PPS_INTCOUNT;
|
|
|
|
if (ntpdata->pps_shift < PPS_INTMAX) {
|
|
|
|
ntpdata->pps_shift++;
|
|
|
|
ntpdata->pps_intcnt = 0;
|
2011-01-13 01:00:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-09-11 13:17:39 +00:00
|
|
|
/*
|
|
|
|
* Update clock frequency based on MONOTONIC_RAW clock PPS signal
|
2011-01-13 01:00:56 +00:00
|
|
|
* 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.
|
|
|
|
*/
|
2024-09-11 13:17:43 +00:00
|
|
|
static long hardpps_update_freq(struct ntp_data *ntpdata, struct pps_normtime freq_norm)
|
2011-01-13 01:00:56 +00:00
|
|
|
{
|
|
|
|
long delta, delta_mod;
|
|
|
|
s64 ftemp;
|
|
|
|
|
2024-09-11 13:17:39 +00:00
|
|
|
/* Check if the frequency interval was too long */
|
2024-09-11 13:17:55 +00:00
|
|
|
if (freq_norm.sec > (2 << ntpdata->pps_shift)) {
|
2024-09-11 13:17:45 +00:00
|
|
|
ntpdata->time_status |= STA_PPSERROR;
|
2024-09-11 13:17:57 +00:00
|
|
|
ntpdata->pps_errcnt++;
|
2024-09-11 13:17:55 +00:00
|
|
|
pps_dec_freq_interval(ntpdata);
|
2024-09-11 13:17:40 +00:00
|
|
|
printk_deferred(KERN_ERR "hardpps: PPSERROR: interval too long - %lld s\n",
|
|
|
|
freq_norm.sec);
|
2011-01-13 01:00:56 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2024-09-11 13:17:39 +00:00
|
|
|
/*
|
|
|
|
* 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.
|
2011-01-13 01:00:56 +00:00
|
|
|
*/
|
|
|
|
ftemp = div_s64(((s64)(-freq_norm.nsec)) << NTP_SCALE_SHIFT,
|
|
|
|
freq_norm.sec);
|
2024-09-11 13:17:56 +00:00
|
|
|
delta = shift_right(ftemp - ntpdata->pps_freq, NTP_SCALE_SHIFT);
|
|
|
|
ntpdata->pps_freq = ftemp;
|
2011-01-13 01:00:56 +00:00
|
|
|
if (delta > PPS_MAXWANDER || delta < -PPS_MAXWANDER) {
|
2024-09-11 13:17:40 +00:00
|
|
|
printk_deferred(KERN_WARNING "hardpps: PPSWANDER: change=%ld\n", delta);
|
2024-09-11 13:17:45 +00:00
|
|
|
ntpdata->time_status |= STA_PPSWANDER;
|
2024-09-11 13:17:57 +00:00
|
|
|
ntpdata->pps_stbcnt++;
|
2024-09-11 13:17:55 +00:00
|
|
|
pps_dec_freq_interval(ntpdata);
|
2024-09-11 13:17:39 +00:00
|
|
|
} else {
|
|
|
|
/* Good sample */
|
2024-09-11 13:17:55 +00:00
|
|
|
pps_inc_freq_interval(ntpdata);
|
2011-01-13 01:00:56 +00:00
|
|
|
}
|
|
|
|
|
2024-09-11 13:17:39 +00:00
|
|
|
/*
|
|
|
|
* The stability metric is calculated as the average of recent
|
|
|
|
* frequency changes, but is used only for performance monitoring
|
2011-01-13 01:00:56 +00:00
|
|
|
*/
|
|
|
|
delta_mod = delta;
|
|
|
|
if (delta_mod < 0)
|
|
|
|
delta_mod = -delta_mod;
|
2024-09-11 13:17:56 +00:00
|
|
|
ntpdata->pps_stabil += (div_s64(((s64)delta_mod) << (NTP_SCALE_SHIFT - SHIFT_USEC),
|
|
|
|
NSEC_PER_USEC) - ntpdata->pps_stabil) >> PPS_INTMIN;
|
2011-01-13 01:00:56 +00:00
|
|
|
|
2024-09-11 13:17:39 +00:00
|
|
|
/* If enabled, the system clock frequency is updated */
|
2024-09-11 13:17:45 +00:00
|
|
|
if ((ntpdata->time_status & STA_PPSFREQ) && !(ntpdata->time_status & STA_FREQHOLD)) {
|
2024-09-11 13:17:56 +00:00
|
|
|
ntpdata->time_freq = ntpdata->pps_freq;
|
2024-09-11 13:17:43 +00:00
|
|
|
ntp_update_frequency(ntpdata);
|
2011-01-13 01:00:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return delta;
|
|
|
|
}
|
|
|
|
|
2024-09-11 13:17:39 +00:00
|
|
|
/* Correct REALTIME clock phase error against PPS signal */
|
2024-09-11 13:17:45 +00:00
|
|
|
static void hardpps_update_phase(struct ntp_data *ntpdata, long error)
|
2011-01-13 01:00:56 +00:00
|
|
|
{
|
|
|
|
long correction = -error;
|
|
|
|
long jitter;
|
|
|
|
|
2024-09-11 13:17:39 +00:00
|
|
|
/* Add the sample to the median filter */
|
2024-09-11 13:17:52 +00:00
|
|
|
pps_phase_filter_add(ntpdata, correction);
|
|
|
|
correction = pps_phase_filter_get(ntpdata, &jitter);
|
2011-01-13 01:00:56 +00:00
|
|
|
|
2024-09-11 13:17:39 +00:00
|
|
|
/*
|
|
|
|
* Nominal jitter is due to PPS signal noise. If it exceeds the
|
2011-01-13 01:00:56 +00:00
|
|
|
* threshold, the sample is discarded; otherwise, if so enabled,
|
|
|
|
* the time offset is updated.
|
|
|
|
*/
|
2024-09-11 13:17:53 +00:00
|
|
|
if (jitter > (ntpdata->pps_jitter << PPS_POPCORN)) {
|
2024-09-11 13:17:40 +00:00
|
|
|
printk_deferred(KERN_WARNING "hardpps: PPSJITTER: jitter=%ld, limit=%ld\n",
|
2024-09-11 13:17:53 +00:00
|
|
|
jitter, (ntpdata->pps_jitter << PPS_POPCORN));
|
2024-09-11 13:17:45 +00:00
|
|
|
ntpdata->time_status |= STA_PPSJITTER;
|
2024-09-11 13:17:57 +00:00
|
|
|
ntpdata->pps_jitcnt++;
|
2024-09-11 13:17:45 +00:00
|
|
|
} else if (ntpdata->time_status & STA_PPSTIME) {
|
2024-09-11 13:17:39 +00:00
|
|
|
/* Correct the time using the phase offset */
|
2024-09-11 13:17:46 +00:00
|
|
|
ntpdata->time_offset = div_s64(((s64)correction) << NTP_SCALE_SHIFT,
|
|
|
|
NTP_INTERVAL_FREQ);
|
2024-09-11 13:17:39 +00:00
|
|
|
/* Cancel running adjtime() */
|
2024-09-11 13:17:49 +00:00
|
|
|
ntpdata->time_adjust = 0;
|
2011-01-13 01:00:56 +00:00
|
|
|
}
|
2024-09-11 13:17:39 +00:00
|
|
|
/* Update jitter */
|
2024-09-11 13:17:53 +00:00
|
|
|
ntpdata->pps_jitter += (jitter - ntpdata->pps_jitter) >> PPS_INTMIN;
|
2011-01-13 01:00:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2013-03-22 18:31:29 +00:00
|
|
|
* __hardpps() - discipline CPU clock oscillator to external PPS signal
|
2011-01-13 01:00:56 +00:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
2015-09-28 20:21:28 +00:00
|
|
|
void __hardpps(const struct timespec64 *phase_ts, const struct timespec64 *raw_ts)
|
2011-01-13 01:00:56 +00:00
|
|
|
{
|
|
|
|
struct pps_normtime pts_norm, freq_norm;
|
2024-09-11 13:17:43 +00:00
|
|
|
struct ntp_data *ntpdata = &tk_ntp_data;
|
2011-01-13 01:00:56 +00:00
|
|
|
|
|
|
|
pts_norm = pps_normalize_ts(*phase_ts);
|
|
|
|
|
2024-09-11 13:17:39 +00:00
|
|
|
/* Clear the error bits, they will be set again if needed */
|
2024-09-11 13:17:45 +00:00
|
|
|
ntpdata->time_status &= ~(STA_PPSJITTER | STA_PPSWANDER | STA_PPSERROR);
|
2011-01-13 01:00:56 +00:00
|
|
|
|
2024-09-11 13:17:45 +00:00
|
|
|
/* indicate signal presence */
|
|
|
|
ntpdata->time_status |= STA_PPSSIGNAL;
|
2024-09-11 13:17:51 +00:00
|
|
|
ntpdata->pps_valid = PPS_VALID;
|
2011-01-13 01:00:56 +00:00
|
|
|
|
2024-09-11 13:17:39 +00:00
|
|
|
/*
|
|
|
|
* When called for the first time, just start the frequency
|
|
|
|
* interval
|
|
|
|
*/
|
2024-09-11 13:17:54 +00:00
|
|
|
if (unlikely(ntpdata->pps_fbase.tv_sec == 0)) {
|
|
|
|
ntpdata->pps_fbase = *raw_ts;
|
2011-01-13 01:00:56 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-09-11 13:17:39 +00:00
|
|
|
/* Ok, now we have a base for frequency calculation */
|
2024-09-11 13:17:54 +00:00
|
|
|
freq_norm = pps_normalize_ts(timespec64_sub(*raw_ts, ntpdata->pps_fbase));
|
2011-01-13 01:00:56 +00:00
|
|
|
|
2024-09-11 13:17:39 +00:00
|
|
|
/*
|
|
|
|
* Check that the signal is in the range
|
|
|
|
* [1s - MAXFREQ us, 1s + MAXFREQ us], otherwise reject it
|
|
|
|
*/
|
2024-09-11 13:17:40 +00:00
|
|
|
if ((freq_norm.sec == 0) || (freq_norm.nsec > MAXFREQ * freq_norm.sec) ||
|
|
|
|
(freq_norm.nsec < -MAXFREQ * freq_norm.sec)) {
|
2024-09-11 13:17:45 +00:00
|
|
|
ntpdata->time_status |= STA_PPSJITTER;
|
2024-09-11 13:17:39 +00:00
|
|
|
/* Restart the frequency calibration interval */
|
2024-09-11 13:17:54 +00:00
|
|
|
ntpdata->pps_fbase = *raw_ts;
|
2014-06-04 23:11:43 +00:00
|
|
|
printk_deferred(KERN_ERR "hardpps: PPSJITTER: bad pulse\n");
|
2011-01-13 01:00:56 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-09-11 13:17:39 +00:00
|
|
|
/* Signal is ok. Check if the current frequency interval is finished */
|
2024-09-11 13:17:55 +00:00
|
|
|
if (freq_norm.sec >= (1 << ntpdata->pps_shift)) {
|
2024-09-11 13:17:57 +00:00
|
|
|
ntpdata->pps_calcnt++;
|
2024-09-11 13:17:39 +00:00
|
|
|
/* Restart the frequency calibration interval */
|
2024-09-11 13:17:54 +00:00
|
|
|
ntpdata->pps_fbase = *raw_ts;
|
2024-09-11 13:17:43 +00:00
|
|
|
hardpps_update_freq(ntpdata, freq_norm);
|
2011-01-13 01:00:56 +00:00
|
|
|
}
|
|
|
|
|
2024-09-11 13:17:45 +00:00
|
|
|
hardpps_update_phase(ntpdata, pts_norm.nsec);
|
2011-01-13 01:00:56 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
#endif /* CONFIG_NTP_PPS */
|
|
|
|
|
time: remove obsolete CLOCK_TICK_ADJUST
The first version of the ntp_interval/tick_length inconsistent usage patch was
recently merged as bbe4d18ac2e058c56adb0cd71f49d9ed3216a405
http://git.kernel.org/gitweb.cgi?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=bbe4d18ac2e058c56adb0cd71f49d9ed3216a405
While the fix did greatly improve the situation, it was correctly pointed out
by Roman that it does have a small bug: If the users change clocksources after
the system has been running and NTP has made corrections, the correctoins made
against the old clocksource will be applied against the new clocksource,
causing error.
The second attempt, which corrects the issue in the NTP_INTERVAL_LENGTH
definition has also made it up-stream as commit
e13a2e61dd5152f5499d2003470acf9c838eab84
http://git.kernel.org/gitweb.cgi?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=e13a2e61dd5152f5499d2003470acf9c838eab84
Roman has correctly pointed out that CLOCK_TICK_ADJUST is calculated
based on the PIT's frequency, and isn't really relevant to non-PIT
driven clocksources (that is, clocksources other then jiffies and pit).
This patch reverts both of those changes, and simply removes
CLOCK_TICK_ADJUST.
This does remove the granularity error correction for users of PIT and Jiffies
clocksource users, but the granularity error but for the majority of users, it
should be within the 500ppm range NTP can accommodate for.
For systems that have granularity errors greater then 500ppm, the
"ntp_tick_adj=" boot option can be used to compensate.
[johnstul@us.ibm.com: provided changelog]
[mattilinnanvuori@yahoo.com: maek ntp_tick_adj static]
Signed-off-by: Roman Zippel <zippel@linux-m68k.org>
Acked-by: john stultz <johnstul@us.ibm.com>
Signed-off-by: Matti Linnanvuori <mattilinnanvuori@yahoo.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Cc: mingo@elte.hu
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
2008-03-04 23:14:26 +00:00
|
|
|
static int __init ntp_tick_adj_setup(char *str)
|
|
|
|
{
|
2024-09-11 13:17:49 +00:00
|
|
|
int rc = kstrtos64(str, 0, &tk_ntp_data.ntp_tick_adj);
|
2014-05-09 18:32:25 +00:00
|
|
|
if (rc)
|
|
|
|
return rc;
|
2009-02-22 15:03:37 +00:00
|
|
|
|
2024-09-11 13:17:49 +00:00
|
|
|
tk_ntp_data.ntp_tick_adj <<= NTP_SCALE_SHIFT;
|
time: remove obsolete CLOCK_TICK_ADJUST
The first version of the ntp_interval/tick_length inconsistent usage patch was
recently merged as bbe4d18ac2e058c56adb0cd71f49d9ed3216a405
http://git.kernel.org/gitweb.cgi?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=bbe4d18ac2e058c56adb0cd71f49d9ed3216a405
While the fix did greatly improve the situation, it was correctly pointed out
by Roman that it does have a small bug: If the users change clocksources after
the system has been running and NTP has made corrections, the correctoins made
against the old clocksource will be applied against the new clocksource,
causing error.
The second attempt, which corrects the issue in the NTP_INTERVAL_LENGTH
definition has also made it up-stream as commit
e13a2e61dd5152f5499d2003470acf9c838eab84
http://git.kernel.org/gitweb.cgi?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=e13a2e61dd5152f5499d2003470acf9c838eab84
Roman has correctly pointed out that CLOCK_TICK_ADJUST is calculated
based on the PIT's frequency, and isn't really relevant to non-PIT
driven clocksources (that is, clocksources other then jiffies and pit).
This patch reverts both of those changes, and simply removes
CLOCK_TICK_ADJUST.
This does remove the granularity error correction for users of PIT and Jiffies
clocksource users, but the granularity error but for the majority of users, it
should be within the 500ppm range NTP can accommodate for.
For systems that have granularity errors greater then 500ppm, the
"ntp_tick_adj=" boot option can be used to compensate.
[johnstul@us.ibm.com: provided changelog]
[mattilinnanvuori@yahoo.com: maek ntp_tick_adj static]
Signed-off-by: Roman Zippel <zippel@linux-m68k.org>
Acked-by: john stultz <johnstul@us.ibm.com>
Signed-off-by: Matti Linnanvuori <mattilinnanvuori@yahoo.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Cc: mingo@elte.hu
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
2008-03-04 23:14:26 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
__setup("ntp_tick_adj=", ntp_tick_adj_setup);
|
2008-05-01 11:34:41 +00:00
|
|
|
|
|
|
|
void __init ntp_init(void)
|
|
|
|
{
|
|
|
|
ntp_clear();
|
2020-12-06 21:46:18 +00:00
|
|
|
ntp_init_cmos_sync();
|
2008-05-01 11:34:41 +00:00
|
|
|
}
|