diff mbox series

[net-next,1/2] ptp: Add .getfine function to support reporting frequency offset from hardware

Message ID 20221202201528.26634-2-rrameshbabu@nvidia.com (mailing list archive)
State Rejected
Delegated to: Netdev Maintainers
Headers show
Series ptp: Introduce .getfine callback to ptp_clock_info | expand

Checks

Context Check Description
netdev/tree_selection success Clearly marked for net-next
netdev/fixes_present success Fixes tag not required for -next series
netdev/subject_prefix success Link
netdev/cover_letter success Series has a cover letter
netdev/patch_count success Link
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 197 this patch: 197
netdev/cc_maintainers success CCed 2 of 2 maintainers
netdev/build_clang success Errors and warnings before: 15 this patch: 15
netdev/module_param success Was 0 now: 0
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 228 this patch: 228
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 48 lines checked
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Rahul Rameshbabu Dec. 2, 2022, 8:15 p.m. UTC
Query the hardware for the operational frequency (represented in 16-bit
fractional parts-per-million) instead of caching the value last set by the
last adjfine command. Prevent inconsistencies between the ptp driver and
the hardware.

For drivers that do not implement the .getfine callback, the cached value
is used.

The linuxptp community has seen cases where the cached value for frequency
is incorrect due to concurrent ptp4l processes adjusting frequency but each
using a stale cache value for frequency. The .getfine callback remedies
that by letting implementers provide a method for querying the frequency.

Signed-off-by: Rahul Rameshbabu <rrameshbabu@nvidia.com>
Reviewed-by: Gal Pressman <gal@nvidia.com>
Cc: Richard Cochran <richardcochran@gmail.com>
---
 drivers/ptp/ptp_clock.c          | 18 +++++++++++++++++-
 include/linux/ptp_clock_kernel.h |  6 ++++++
 2 files changed, 23 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/drivers/ptp/ptp_clock.c b/drivers/ptp/ptp_clock.c
index 62d4d29e7c05..1655381ae731 100644
--- a/drivers/ptp/ptp_clock.c
+++ b/drivers/ptp/ptp_clock.c
@@ -66,6 +66,22 @@  static void enqueue_external_timestamp(struct timestamp_event_queue *queue,
 
 /* posix clock implementation */
 
+static long ptp_get_fine(struct ptp_clock *ptp)
+{
+	struct ptp_clock_info *ops = ptp->info;
+
+	if (ops->getfine) {
+		long fine;
+
+		if (ops->getfine(ops, &fine))
+			return ptp->dialed_frequency;
+
+		return fine;
+	}
+
+	return ptp->dialed_frequency;
+}
+
 static int ptp_clock_getres(struct posix_clock *pc, struct timespec64 *tp)
 {
 	tp->tv_sec = 0;
@@ -143,7 +159,7 @@  static int ptp_clock_adjtime(struct posix_clock *pc, struct __kernel_timex *tx)
 			err = ops->adjphase(ops, offset);
 		}
 	} else if (tx->modes == 0) {
-		tx->freq = ptp->dialed_frequency;
+		tx->freq = ptp_get_fine(ptp);
 		err = 0;
 	}
 
diff --git a/include/linux/ptp_clock_kernel.h b/include/linux/ptp_clock_kernel.h
index fdffa6a98d79..f17097de349e 100644
--- a/include/linux/ptp_clock_kernel.h
+++ b/include/linux/ptp_clock_kernel.h
@@ -77,6 +77,11 @@  struct ptp_system_timestamp {
  *            nominal frequency in parts per million, but with a
  *            16 bit binary fractional field.
  *
+ * @getfine:  Reads the current frequency offset from the hardware clock.
+ *            parameter scaled_ppm: Requested frequency offset from
+ *            nominal frequency in parts per million, but with a
+ *            16 bit binary fractional field.
+ *
  * @adjphase:  Adjusts the phase offset of the hardware clock.
  *             parameter delta: Desired change in nanoseconds.
  *
@@ -168,6 +173,7 @@  struct ptp_clock_info {
 	int pps;
 	struct ptp_pin_desc *pin_config;
 	int (*adjfine)(struct ptp_clock_info *ptp, long scaled_ppm);
+	int (*getfine)(struct ptp_clock_info *ptp, long *scaled_ppm);
 	int (*adjphase)(struct ptp_clock_info *ptp, s32 phase);
 	int (*adjtime)(struct ptp_clock_info *ptp, s64 delta);
 	int (*gettime64)(struct ptp_clock_info *ptp, struct timespec64 *ts);