[PATCH net-next] ptp: add vclock timestamp conversion IOCTL
From: Sebastien Laveze
Date: Mon Sep 27 2021 - 05:33:27 EST
From: Seb Laveze <sebastien.laveze@xxxxxxx>
Add an IOCTL to perform per-timestamp conversion, as an extension of the
ptp virtual framework introduced in commit 5d43f951b1ac ("ptp: add ptp
virtual clock driver framework").
The original implementation allows binding a socket to a given virtual
clock to perform the timestamps conversions. Commit 5d43f951b1ac ("ptp:
add ptp virtual clock driver framework").
This binding works well if the application requires all timestamps in the
same domain but is not convenient when multiple domains need to be
supported using a single socket.
Typically, IEEE 802.1AS-2020 can be implemented using a single socket,
the CMLDS layer using raw PHC timestamps and the domain specific
timestamps converted in the appropriate gPTP domain using this IOCTL.
Signed-off-by: Seb Laveze <sebastien.laveze@xxxxxxx>
---
drivers/ptp/ptp_chardev.c | 24 ++++++++++++++++++++++++
include/uapi/linux/ptp_clock.h | 1 +
2 files changed, 25 insertions(+)
diff --git a/drivers/ptp/ptp_chardev.c b/drivers/ptp/ptp_chardev.c
index af3bc65c4595..28c13098fcba 100644
--- a/drivers/ptp/ptp_chardev.c
+++ b/drivers/ptp/ptp_chardev.c
@@ -118,10 +118,13 @@ long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg)
struct ptp_clock_request req;
struct ptp_clock_caps caps;
struct ptp_clock_time *pct;
+ struct ptp_vclock *vclock;
unsigned int i, pin_index;
struct ptp_pin_desc pd;
struct timespec64 ts;
+ unsigned long flags;
int enable, err = 0;
+ s64 ns;
switch (cmd) {
@@ -418,6 +421,27 @@ long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg)
mutex_unlock(&ptp->pincfg_mux);
break;
+ case PTP_VCLOCK_CONV_TS:
+ if (!ptp->is_virtual_clock)
+ return -EINVAL;
+
+ vclock = info_to_vclock(ptp->info);
+
+ if (get_timespec64(&ts, (void __user *)arg))
+ return -EFAULT;
+
+ ns = timespec64_to_ns(&ts);
+
+ spin_lock_irqsave(&vclock->lock, flags);
+ ns = timecounter_cyc2time(&vclock->tc, ns);
+ spin_unlock_irqrestore(&vclock->lock, flags);
+
+ ts = ns_to_timespec64(ns);
+
+ if (put_timespec64(&ts, (void __user *)arg))
+ return -EFAULT;
+ break;
+
default:
err = -ENOTTY;
break;
diff --git a/include/uapi/linux/ptp_clock.h b/include/uapi/linux/ptp_clock.h
index 1d108d597f66..13147d454aa8 100644
--- a/include/uapi/linux/ptp_clock.h
+++ b/include/uapi/linux/ptp_clock.h
@@ -223,6 +223,7 @@ struct ptp_pin_desc {
_IOWR(PTP_CLK_MAGIC, 17, struct ptp_sys_offset_precise)
#define PTP_SYS_OFFSET_EXTENDED2 \
_IOWR(PTP_CLK_MAGIC, 18, struct ptp_sys_offset_extended)
+#define PTP_VCLOCK_CONV_TS _IOWR(PTP_CLK_MAGIC, 19, struct __kernel_timespec)
struct ptp_extts_event {
struct ptp_clock_time t; /* Time event occured. */
--
2.25.1