|
|
04e706 |
commit 513c7457865dba262a43e03fbe9178f4b08ba319
|
|
|
04e706 |
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
|
|
04e706 |
Date: Mon Oct 24 15:25:30 2022 +0200
|
|
|
04e706 |
|
|
|
04e706 |
Drop support for old kernels returning zero frequency.
|
|
|
04e706 |
|
|
|
04e706 |
Kernels before 3.10 had a bug in reading of the system clock frequency,
|
|
|
04e706 |
which was worked around by commit da347d7a36f2 ("ptp4l: Set clock
|
|
|
04e706 |
frequency on start").
|
|
|
04e706 |
|
|
|
04e706 |
Drop this workaround and support for the old kernels to make
|
|
|
04e706 |
clockadj_get_freq() useful.
|
|
|
04e706 |
|
|
|
04e706 |
(Rebased to 3.1.1)
|
|
|
04e706 |
|
|
|
04e706 |
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
|
|
|
04e706 |
|
|
|
04e706 |
diff --git a/clock.c b/clock.c
|
|
|
04e706 |
index f3df220..9079428 100644
|
|
|
04e706 |
--- a/clock.c
|
|
|
04e706 |
+++ b/clock.c
|
|
|
04e706 |
@@ -1147,11 +1147,6 @@ struct clock *clock_create(enum clock_type type, struct config *config,
|
|
|
04e706 |
|
|
|
04e706 |
if (c->clkid != CLOCK_INVALID) {
|
|
|
04e706 |
fadj = (int) clockadj_get_freq(c->clkid);
|
|
|
04e706 |
- /* Due to a bug in older kernels, the reading may silently fail
|
|
|
04e706 |
- and return 0. Set the frequency back to make sure fadj is
|
|
|
04e706 |
- the actual frequency of the clock. */
|
|
|
04e706 |
- clockadj_set_freq(c->clkid, fadj);
|
|
|
04e706 |
-
|
|
|
04e706 |
/* Disable write phase mode if not implemented by driver */
|
|
|
04e706 |
if (c->write_phase_mode && !phc_has_writephase(c->clkid)) {
|
|
|
04e706 |
pr_err("clock does not support write phase mode");
|
|
|
04e706 |
@@ -1746,7 +1741,6 @@ int clock_switch_phc(struct clock *c, int phc_index)
|
|
|
04e706 |
return -1;
|
|
|
04e706 |
}
|
|
|
04e706 |
fadj = (int) clockadj_get_freq(clkid);
|
|
|
04e706 |
- clockadj_set_freq(clkid, fadj);
|
|
|
04e706 |
servo = servo_create(c->config, c->servo_type, -fadj, max_adj, 0);
|
|
|
04e706 |
if (!servo) {
|
|
|
04e706 |
pr_err("Switching PHC, failed to create clock servo");
|
|
|
04e706 |
diff --git a/phc2sys.c b/phc2sys.c
|
|
|
04e706 |
index 5f6fbaa..af948eb 100644
|
|
|
04e706 |
--- a/phc2sys.c
|
|
|
04e706 |
+++ b/phc2sys.c
|
|
|
04e706 |
@@ -147,9 +147,6 @@ static struct servo *servo_add(struct phc2sys_private *priv,
|
|
|
04e706 |
|
|
|
04e706 |
clockadj_init(clock->clkid);
|
|
|
04e706 |
ppb = clockadj_get_freq(clock->clkid);
|
|
|
04e706 |
- /* The reading may silently fail and return 0, reset the frequency to
|
|
|
04e706 |
- make sure ppb is the actual frequency of the clock. */
|
|
|
04e706 |
- clockadj_set_freq(clock->clkid, ppb);
|
|
|
04e706 |
if (clock->clkid == CLOCK_REALTIME) {
|
|
|
04e706 |
sysclk_set_leap(0);
|
|
|
04e706 |
max_ppb = sysclk_max_freq();
|
|
|
04e706 |
diff --git a/ts2phc_slave.c b/ts2phc_slave.c
|
|
|
04e706 |
index 749efe5..5541d91 100644
|
|
|
04e706 |
--- a/ts2phc_slave.c
|
|
|
04e706 |
+++ b/ts2phc_slave.c
|
|
|
04e706 |
@@ -183,10 +183,6 @@ static struct ts2phc_slave *ts2phc_slave_create(struct config *cfg, const char *
|
|
|
04e706 |
pr_debug("PHC slave %s has ptp index %d", device, junk);
|
|
|
04e706 |
|
|
|
04e706 |
fadj = (int) clockadj_get_freq(slave->clk);
|
|
|
04e706 |
- /* Due to a bug in older kernels, the reading may silently fail
|
|
|
04e706 |
- and return 0. Set the frequency back to make sure fadj is
|
|
|
04e706 |
- the actual frequency of the clock. */
|
|
|
04e706 |
- clockadj_set_freq(slave->clk, fadj);
|
|
|
04e706 |
|
|
|
04e706 |
max_adj = phc_max_adj(slave->clk);
|
|
|
04e706 |
|
|
|
04e706 |
|
|
|
04e706 |
commit 80d6875b0072c7ea636a5631e590fa72d169c351
|
|
|
04e706 |
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
|
|
04e706 |
Date: Mon Oct 24 15:25:31 2022 +0200
|
|
|
04e706 |
|
|
|
04e706 |
Don't accept errors in clockadj_get_freq().
|
|
|
04e706 |
|
|
|
04e706 |
Exit if an error is returned from the clock_adjtime() call in
|
|
|
04e706 |
clockadj_get_freq(). No recoverable errors are expected.
|
|
|
04e706 |
|
|
|
04e706 |
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
|
|
|
04e706 |
|
|
|
04e706 |
diff --git a/clockadj.c b/clockadj.c
|
|
|
04e706 |
index 957dc57..4c920b9 100644
|
|
|
04e706 |
--- a/clockadj.c
|
|
|
04e706 |
+++ b/clockadj.c
|
|
|
04e706 |
@@ -19,6 +19,7 @@
|
|
|
04e706 |
|
|
|
04e706 |
#include <errno.h>
|
|
|
04e706 |
#include <math.h>
|
|
|
04e706 |
+#include <stdlib.h>
|
|
|
04e706 |
#include <string.h>
|
|
|
04e706 |
#include <unistd.h>
|
|
|
04e706 |
|
|
|
04e706 |
@@ -72,6 +73,7 @@ double clockadj_get_freq(clockid_t clkid)
|
|
|
04e706 |
memset(&tx, 0, sizeof(tx));
|
|
|
04e706 |
if (clock_adjtime(clkid, &tx) < 0) {
|
|
|
04e706 |
pr_err("failed to read out the clock frequency adjustment: %m");
|
|
|
04e706 |
+ exit(1);
|
|
|
04e706 |
} else {
|
|
|
04e706 |
f = tx.freq / 65.536;
|
|
|
04e706 |
if (clkid == CLOCK_REALTIME && realtime_nominal_tick && tx.tick)
|
|
|
04e706 |
|
|
|
04e706 |
commit 211cbfe810ef4082d1af8e9b50f65d4f6fd7246a
|
|
|
04e706 |
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
|
|
04e706 |
Date: Mon Oct 24 15:25:32 2022 +0200
|
|
|
04e706 |
|
|
|
04e706 |
Extend clockcheck to check for changes in frequency.
|
|
|
04e706 |
|
|
|
04e706 |
Before setting the new frequency offset on a clock update, compare the
|
|
|
04e706 |
current frequency returned by the kernel with the value saved from the
|
|
|
04e706 |
previous update. Print a warning message if the difference is larger
|
|
|
04e706 |
than 1 ppb, allowing for rounding errors in conversion to and from
|
|
|
04e706 |
double. The kernel caches the value set by clock_adjtime() in shifted
|
|
|
04e706 |
ppm, it doesn't request it from the driver, which can have a lower
|
|
|
04e706 |
resulution.
|
|
|
04e706 |
|
|
|
04e706 |
This should detect misconfigurations where multiple processes are trying
|
|
|
04e706 |
to control the clock (e.g. another ptp4l/phc2sys instance or an NTP
|
|
|
04e706 |
client), even when they don't step the clock.
|
|
|
04e706 |
|
|
|
04e706 |
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
|
|
|
04e706 |
|
|
|
04e706 |
diff --git a/clock.c b/clock.c
|
|
|
04e706 |
index 9079428..eea7983 100644
|
|
|
04e706 |
--- a/clock.c
|
|
|
04e706 |
+++ b/clock.c
|
|
|
04e706 |
@@ -1760,6 +1760,9 @@ int clock_switch_phc(struct clock *c, int phc_index)
|
|
|
04e706 |
|
|
|
04e706 |
static void clock_synchronize_locked(struct clock *c, double adj)
|
|
|
04e706 |
{
|
|
|
04e706 |
+ if (c->sanity_check) {
|
|
|
04e706 |
+ clockcheck_freq(c->sanity_check, clockadj_get_freq(c->clkid));
|
|
|
04e706 |
+ }
|
|
|
04e706 |
clockadj_set_freq(c->clkid, -adj);
|
|
|
04e706 |
if (c->clkid == CLOCK_REALTIME) {
|
|
|
04e706 |
sysclk_set_sync();
|
|
|
04e706 |
diff --git a/clockcheck.c b/clockcheck.c
|
|
|
04e706 |
index f0141be..b5a69cc 100644
|
|
|
04e706 |
--- a/clockcheck.c
|
|
|
04e706 |
+++ b/clockcheck.c
|
|
|
04e706 |
@@ -123,6 +123,16 @@ void clockcheck_set_freq(struct clockcheck *cc, int freq)
|
|
|
04e706 |
cc->freq_known = 1;
|
|
|
04e706 |
}
|
|
|
04e706 |
|
|
|
04e706 |
+int clockcheck_freq(struct clockcheck *cc, int freq)
|
|
|
04e706 |
+{
|
|
|
04e706 |
+ /* Allow difference of 1 ppb due to conversion to/from double */
|
|
|
04e706 |
+ if (cc->freq_known && abs(cc->current_freq - freq) > 1) {
|
|
|
04e706 |
+ pr_warning("clockcheck: clock frequency changed unexpectedly!");
|
|
|
04e706 |
+ return 1;
|
|
|
04e706 |
+ }
|
|
|
04e706 |
+ return 0;
|
|
|
04e706 |
+}
|
|
|
04e706 |
+
|
|
|
04e706 |
void clockcheck_step(struct clockcheck *cc, int64_t step)
|
|
|
04e706 |
{
|
|
|
04e706 |
if (cc->last_ts)
|
|
|
04e706 |
diff --git a/clockcheck.h b/clockcheck.h
|
|
|
04e706 |
index 1ff86eb..4b09b98 100644
|
|
|
04e706 |
--- a/clockcheck.h
|
|
|
04e706 |
+++ b/clockcheck.h
|
|
|
04e706 |
@@ -54,6 +54,14 @@ int clockcheck_sample(struct clockcheck *cc, uint64_t ts);
|
|
|
04e706 |
*/
|
|
|
04e706 |
void clockcheck_set_freq(struct clockcheck *cc, int freq);
|
|
|
04e706 |
|
|
|
04e706 |
+/**
|
|
|
04e706 |
+ * Check whether the frequency correction did not change unexpectedly.
|
|
|
04e706 |
+ * @param cc Pointer to a clock check obtained via @ref clockcheck_create().
|
|
|
04e706 |
+ * @param freq Current reading of the frequency correction in ppb.
|
|
|
04e706 |
+ * @return Zero if the frequency did not change, non-zero otherwise.
|
|
|
04e706 |
+ */
|
|
|
04e706 |
+int clockcheck_freq(struct clockcheck *cc, int freq);
|
|
|
04e706 |
+
|
|
|
04e706 |
/**
|
|
|
04e706 |
* Inform clock check that the clock was stepped.
|
|
|
04e706 |
* @param cc Pointer to a clock check obtained via @ref clockcheck_create().
|
|
|
04e706 |
diff --git a/phc2sys.c b/phc2sys.c
|
|
|
04e706 |
index af948eb..4daa1bf 100644
|
|
|
04e706 |
--- a/phc2sys.c
|
|
|
04e706 |
+++ b/phc2sys.c
|
|
|
04e706 |
@@ -566,6 +566,9 @@ static void update_clock(struct phc2sys_private *priv, struct clock *clock,
|
|
|
04e706 |
/* Fall through. */
|
|
|
04e706 |
case SERVO_LOCKED:
|
|
|
04e706 |
case SERVO_LOCKED_STABLE:
|
|
|
04e706 |
+ if (clock->sanity_check)
|
|
|
04e706 |
+ clockcheck_freq(clock->sanity_check,
|
|
|
04e706 |
+ clockadj_get_freq(clock->clkid));
|
|
|
04e706 |
clockadj_set_freq(clock->clkid, -ppb);
|
|
|
04e706 |
if (clock->clkid == CLOCK_REALTIME)
|
|
|
04e706 |
sysclk_set_sync();
|
|
|
04e706 |
diff --git a/ptp4l.8 b/ptp4l.8
|
|
|
04e706 |
index 4917240..f760e2b 100644
|
|
|
04e706 |
--- a/ptp4l.8
|
|
|
04e706 |
+++ b/ptp4l.8
|
|
|
04e706 |
@@ -605,8 +605,10 @@ This option used to be called
|
|
|
04e706 |
The maximum allowed frequency offset between uncorrected clock and the system
|
|
|
04e706 |
monotonic clock in parts per billion (ppb). This is used as a sanity check of
|
|
|
04e706 |
the synchronized clock. When a larger offset is measured, a warning message
|
|
|
04e706 |
-will be printed and the servo will be reset. When set to 0, the sanity check is
|
|
|
04e706 |
-disabled. The default is 200000000 (20%).
|
|
|
04e706 |
+will be printed and the servo will be reset. If the frequency correction set by
|
|
|
04e706 |
+ptp4l changes unexpectedly between updates of the clock (e.g. due to another
|
|
|
04e706 |
+process trying to control the clock), a warning message will be printed. When
|
|
|
04e706 |
+set to 0, the sanity check is disabled. The default is 200000000 (20%).
|
|
|
04e706 |
.TP
|
|
|
04e706 |
.B initial_delay
|
|
|
04e706 |
The initial path delay of the clock in nanoseconds used for synchronization of
|