ptp: Introduce a high resolution frequency adjustment method.
authorRichard Cochran <richardcochran@gmail.com>
Tue, 8 Nov 2016 21:49:16 +0000 (22:49 +0100)
committerDavid S. Miller <davem@davemloft.net>
Thu, 10 Nov 2016 02:19:53 +0000 (21:19 -0500)
The internal PTP Hardware Clock (PHC) interface limits the resolution for
frequency adjustments to one part per billion.  However, some hardware
devices allow finer adjustment, and making use of the increased resolution
improves synchronization measurably on such devices.

This patch adds an alternative method that allows finer frequency tuning
by passing the scaled ppm value to PHC drivers.  This value comes from
user space, and it has a resolution of about 0.015 ppb.  We also deprecate
the older method, anticipating its removal once existing drivers have been
converted over.

Signed-off-by: Richard Cochran <richardcochran@gmail.com>
Suggested-by: Ulrik De Bie <ulrik.debie-os@e2big.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/ptp/ptp_clock.c
include/linux/ptp_clock_kernel.h

index 86280b7e41f3f79db793c0545c97bb0c1e36e96e..9c13381b69662c499d0e9a679ce3eeb71c3c6d3d 100644 (file)
@@ -153,7 +153,10 @@ static int ptp_clock_adjtime(struct posix_clock *pc, struct timex *tx)
                s32 ppb = scaled_ppm_to_ppb(tx->freq);
                if (ppb > ops->max_adj || ppb < -ops->max_adj)
                        return -ERANGE;
-               err = ops->adjfreq(ops, ppb);
+               if (ops->adjfine)
+                       err = ops->adjfine(ops, tx->freq);
+               else
+                       err = ops->adjfreq(ops, ppb);
                ptp->dialed_frequency = tx->freq;
        } else if (tx->modes == 0) {
                tx->freq = ptp->dialed_frequency;
index 5ad54fc66cf0f589aa9eca3275683e56e7650107..b76d47aba564ff0936779226ec1e1b7773f90582 100644 (file)
@@ -58,7 +58,14 @@ struct system_device_crosststamp;
  *
  * clock operations
  *
+ * @adjfine:  Adjusts the frequency of the hardware clock.
+ *            parameter scaled_ppm: Desired frequency offset from
+ *            nominal frequency in parts per million, but with a
+ *            16 bit binary fractional field.
+ *
  * @adjfreq:  Adjusts the frequency of the hardware clock.
+ *            This method is deprecated.  New drivers should implement
+ *            the @adjfine method instead.
  *            parameter delta: Desired frequency offset from nominal frequency
  *            in parts per billion
  *
@@ -108,6 +115,7 @@ struct ptp_clock_info {
        int n_pins;
        int pps;
        struct ptp_pin_desc *pin_config;
+       int (*adjfine)(struct ptp_clock_info *ptp, long scaled_ppm);
        int (*adjfreq)(struct ptp_clock_info *ptp, s32 delta);
        int (*adjtime)(struct ptp_clock_info *ptp, s64 delta);
        int (*gettime64)(struct ptp_clock_info *ptp, struct timespec64 *ts);