]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
sys_linux: add support for PTP_SYS_OFFSET_PRECISE
authorMiroslav Lichvar <mlichvar@redhat.com>
Thu, 19 Jan 2017 15:05:49 +0000 (16:05 +0100)
committerMiroslav Lichvar <mlichvar@redhat.com>
Mon, 23 Jan 2017 14:58:55 +0000 (15:58 +0100)
This is for hardware that can precisely cross timestamp the PHC with the
system clock.

ntp_io_linux.c
refclock_phc.c
sys_linux.c
sys_linux.h

index 9e5c354a7e7ad18be09e050a7a43f16e3e11f4cd..686d175ccbb6b2f9cfa5a7219e700f00960299df 100644 (file)
@@ -368,7 +368,7 @@ process_hw_timestamp(struct Interface *iface, struct timespec *hw_ts,
   int l2_length;
 
   if (HCL_NeedsNewSample(iface->clock, &local_ts->ts)) {
-    if (!SYS_Linux_GetPHCSample(iface->phc_fd, iface->precision, &iface->phc_mode,
+    if (!SYS_Linux_GetPHCSample(iface->phc_fd, 0, iface->precision, &iface->phc_mode,
                                 &sample_phc_ts, &sample_sys_ts, &err))
       return;
 
index 31859201f112d48a14b67f199c6147763f8c4627..2bbed3dd5b15c9d1222a671d1e10b10a2528d954 100644 (file)
@@ -83,7 +83,7 @@ static int phc_poll(RCL_Instance instance)
 
   phc = (struct phc_instance *)RCL_GetDriverData(instance);
 
-  if (!SYS_Linux_GetPHCSample(phc->fd, RCL_GetPrecision(instance), &phc->mode,
+  if (!SYS_Linux_GetPHCSample(phc->fd, 0, RCL_GetPrecision(instance), &phc->mode,
                               &phc_ts, &sys_ts, &err))
     return 0;
 
index d4233624255e1b2d408e47eb604cd445f00a1e4e..b121ee817a054e5a03bdcd77bb860962fbb96c2f 100644 (file)
@@ -517,6 +517,9 @@ SYS_Linux_EnableSystemCallFilter(int level)
     FIONREAD, TCGETS,
 #if defined(FEAT_PHC) || defined(HAVE_LINUX_TIMESTAMPING)
     PTP_SYS_OFFSET,
+#ifdef PTP_SYS_OFFSET_PRECISE
+    PTP_SYS_OFFSET_PRECISE,
+#endif
 #endif
 #ifdef FEAT_PPS
     PPS_FETCH,
@@ -729,6 +732,35 @@ get_phc_sample(int phc_fd, double precision, struct timespec *phc_ts,
 
   return 1;
 }
+/* ================================================== */
+
+static int
+get_precise_phc_sample(int phc_fd, double precision, struct timespec *phc_ts,
+                      struct timespec *sys_ts, double *err)
+{
+#ifdef PTP_SYS_OFFSET_PRECISE
+  struct ptp_sys_offset_precise sys_off;
+
+  /* Silence valgrind */
+  memset(&sys_off, 0, sizeof (sys_off));
+
+  if (ioctl(phc_fd, PTP_SYS_OFFSET_PRECISE, &sys_off)) {
+    DEBUG_LOG(LOGF_SysLinux, "ioctl(%s) failed : %s", "PTP_SYS_OFFSET_PRECISE",
+              strerror(errno));
+    return 0;
+  }
+
+  phc_ts->tv_sec = sys_off.device.sec;
+  phc_ts->tv_nsec = sys_off.device.nsec;
+  sys_ts->tv_sec = sys_off.sys_realtime.sec;
+  sys_ts->tv_nsec = sys_off.sys_realtime.nsec;
+  *err = MAX(LCL_GetSysPrecisionAsQuantum(), precision);
+
+  return 1;
+#else
+  return 0;
+#endif
+}
 
 /* ================================================== */
 
@@ -766,10 +798,14 @@ SYS_Linux_OpenPHC(const char *path, int phc_index)
 /* ================================================== */
 
 int
-SYS_Linux_GetPHCSample(int fd, double precision, int *reading_mode,
+SYS_Linux_GetPHCSample(int fd, int nocrossts, double precision, int *reading_mode,
                        struct timespec *phc_ts, struct timespec *sys_ts, double *err)
 {
-  if ((*reading_mode == 1 || !*reading_mode) &&
+  if ((*reading_mode == 2 || !*reading_mode) && !nocrossts &&
+      get_precise_phc_sample(fd, precision, phc_ts, sys_ts, err)) {
+    *reading_mode = 2;
+    return 1;
+  } else if ((*reading_mode == 1 || !*reading_mode) &&
       get_phc_sample(fd, precision, phc_ts, sys_ts, err)) {
     *reading_mode = 1;
     return 1;
index 5e9f1d100a14749353c7e2925b7f5b4aa6926c2a..4108401ad8439cc8a5ab902d2ed7e560dfd99a9d 100644 (file)
@@ -43,7 +43,7 @@ extern int SYS_Linux_CheckKernelVersion(int req_major, int req_minor);
 
 extern int SYS_Linux_OpenPHC(const char *path, int phc_index);
 
-extern int SYS_Linux_GetPHCSample(int fd, double precision, int *reading_mode,
+extern int SYS_Linux_GetPHCSample(int fd, int nocrossts, double precision, int *reading_mode,
                                   struct timespec *phc_ts, struct timespec *sys_ts, double *err);
 
 #endif  /* GOT_SYS_LINUX_H */