Skip to content

Commit 719f1aa

Browse files
christopher-s-halljohnstultz-work
authored andcommitted
ptp: Add PTP_SYS_OFFSET_PRECISE for driver crosstimestamping
Currently, network /system cross-timestamping is performed in the PTP_SYS_OFFSET ioctl. The PTP clock driver reads gettimeofday() and the gettime64() callback provided by the driver. The cross-timestamp is best effort where the latency between the capture of system time (getnstimeofday()) and the device time (driver callback) may be significant. The getcrosststamp() callback and corresponding PTP_SYS_OFFSET_PRECISE ioctl allows the driver to perform this device/system correlation when for example cross timestamp hardware is available. Modern Intel systems can do this for onboard Ethernet controllers using the ART counter. There is virtually zero latency between captures of the ART and network device clock. The capabilities ioctl (PTP_CLOCK_GETCAPS), is augmented allowing applications to query whether or not drivers implement the getcrosststamp callback, providing more precise cross timestamping. Cc: Prarit Bhargava <prarit@redhat.com> Cc: Richard Cochran <richardcochran@gmail.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Ingo Molnar <mingo@kernel.org> Cc: Andy Lutomirski <luto@amacapital.net> Cc: kevin.b.stanton@intel.com Cc: kevin.j.clarke@intel.com Cc: hpa@zytor.com Cc: jeffrey.t.kirsher@intel.com Cc: netdev@vger.kernel.org Acked-by: Richard Cochran <richardcochran@gmail.com> Signed-off-by: Christopher S. Hall <christopher.s.hall@intel.com> [jstultz: Commit subject tweaks] Signed-off-by: John Stultz <john.stultz@linaro.org>
1 parent f9677e0 commit 719f1aa

File tree

4 files changed

+51
-3
lines changed

4 files changed

+51
-3
lines changed

Documentation/ptp/testptp.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -277,13 +277,15 @@ int main(int argc, char *argv[])
277277
" %d external time stamp channels\n"
278278
" %d programmable periodic signals\n"
279279
" %d pulse per second\n"
280-
" %d programmable pins\n",
280+
" %d programmable pins\n"
281+
" %d cross timestamping\n",
281282
caps.max_adj,
282283
caps.n_alarm,
283284
caps.n_ext_ts,
284285
caps.n_per_out,
285286
caps.pps,
286-
caps.n_pins);
287+
caps.n_pins,
288+
caps.cross_timestamping);
287289
}
288290
}
289291

drivers/ptp/ptp_chardev.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <linux/poll.h>
2323
#include <linux/sched.h>
2424
#include <linux/slab.h>
25+
#include <linux/timekeeping.h>
2526

2627
#include "ptp_private.h"
2728

@@ -120,11 +121,13 @@ long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg)
120121
struct ptp_clock_caps caps;
121122
struct ptp_clock_request req;
122123
struct ptp_sys_offset *sysoff = NULL;
124+
struct ptp_sys_offset_precise precise_offset;
123125
struct ptp_pin_desc pd;
124126
struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock);
125127
struct ptp_clock_info *ops = ptp->info;
126128
struct ptp_clock_time *pct;
127129
struct timespec64 ts;
130+
struct system_device_crosststamp xtstamp;
128131
int enable, err = 0;
129132
unsigned int i, pin_index;
130133

@@ -138,6 +141,7 @@ long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg)
138141
caps.n_per_out = ptp->info->n_per_out;
139142
caps.pps = ptp->info->pps;
140143
caps.n_pins = ptp->info->n_pins;
144+
caps.cross_timestamping = ptp->info->getcrosststamp != NULL;
141145
if (copy_to_user((void __user *)arg, &caps, sizeof(caps)))
142146
err = -EFAULT;
143147
break;
@@ -180,6 +184,29 @@ long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg)
180184
err = ops->enable(ops, &req, enable);
181185
break;
182186

187+
case PTP_SYS_OFFSET_PRECISE:
188+
if (!ptp->info->getcrosststamp) {
189+
err = -EOPNOTSUPP;
190+
break;
191+
}
192+
err = ptp->info->getcrosststamp(ptp->info, &xtstamp);
193+
if (err)
194+
break;
195+
196+
ts = ktime_to_timespec64(xtstamp.device);
197+
precise_offset.device.sec = ts.tv_sec;
198+
precise_offset.device.nsec = ts.tv_nsec;
199+
ts = ktime_to_timespec64(xtstamp.sys_realtime);
200+
precise_offset.sys_realtime.sec = ts.tv_sec;
201+
precise_offset.sys_realtime.nsec = ts.tv_nsec;
202+
ts = ktime_to_timespec64(xtstamp.sys_monoraw);
203+
precise_offset.sys_monoraw.sec = ts.tv_sec;
204+
precise_offset.sys_monoraw.nsec = ts.tv_nsec;
205+
if (copy_to_user((void __user *)arg, &precise_offset,
206+
sizeof(precise_offset)))
207+
err = -EFAULT;
208+
break;
209+
183210
case PTP_SYS_OFFSET:
184211
sysoff = kmalloc(sizeof(*sysoff), GFP_KERNEL);
185212
if (!sysoff) {

include/linux/ptp_clock_kernel.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ struct ptp_clock_request {
3838
};
3939
};
4040

41+
struct system_device_crosststamp;
4142
/**
4243
* struct ptp_clock_info - decribes a PTP hardware clock
4344
*
@@ -67,6 +68,11 @@ struct ptp_clock_request {
6768
* @gettime64: Reads the current time from the hardware clock.
6869
* parameter ts: Holds the result.
6970
*
71+
* @getcrosststamp: Reads the current time from the hardware clock and
72+
* system clock simultaneously.
73+
* parameter cts: Contains timestamp (device,system) pair,
74+
* where system time is realtime and monotonic.
75+
*
7076
* @settime64: Set the current time on the hardware clock.
7177
* parameter ts: Time value to set.
7278
*
@@ -105,6 +111,8 @@ struct ptp_clock_info {
105111
int (*adjfreq)(struct ptp_clock_info *ptp, s32 delta);
106112
int (*adjtime)(struct ptp_clock_info *ptp, s64 delta);
107113
int (*gettime64)(struct ptp_clock_info *ptp, struct timespec64 *ts);
114+
int (*getcrosststamp)(struct ptp_clock_info *ptp,
115+
struct system_device_crosststamp *cts);
108116
int (*settime64)(struct ptp_clock_info *p, const struct timespec64 *ts);
109117
int (*enable)(struct ptp_clock_info *ptp,
110118
struct ptp_clock_request *request, int on);

include/uapi/linux/ptp_clock.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,9 @@ struct ptp_clock_caps {
5151
int n_per_out; /* Number of programmable periodic signals. */
5252
int pps; /* Whether the clock supports a PPS callback. */
5353
int n_pins; /* Number of input/output pins. */
54-
int rsv[14]; /* Reserved for future use. */
54+
/* Whether the clock supports precise system-device cross timestamps */
55+
int cross_timestamping;
56+
int rsv[13]; /* Reserved for future use. */
5557
};
5658

5759
struct ptp_extts_request {
@@ -81,6 +83,13 @@ struct ptp_sys_offset {
8183
struct ptp_clock_time ts[2 * PTP_MAX_SAMPLES + 1];
8284
};
8385

86+
struct ptp_sys_offset_precise {
87+
struct ptp_clock_time device;
88+
struct ptp_clock_time sys_realtime;
89+
struct ptp_clock_time sys_monoraw;
90+
unsigned int rsv[4]; /* Reserved for future use. */
91+
};
92+
8493
enum ptp_pin_function {
8594
PTP_PF_NONE,
8695
PTP_PF_EXTTS,
@@ -124,6 +133,8 @@ struct ptp_pin_desc {
124133
#define PTP_SYS_OFFSET _IOW(PTP_CLK_MAGIC, 5, struct ptp_sys_offset)
125134
#define PTP_PIN_GETFUNC _IOWR(PTP_CLK_MAGIC, 6, struct ptp_pin_desc)
126135
#define PTP_PIN_SETFUNC _IOW(PTP_CLK_MAGIC, 7, struct ptp_pin_desc)
136+
#define PTP_SYS_OFFSET_PRECISE \
137+
_IOWR(PTP_CLK_MAGIC, 8, struct ptp_sys_offset_precise)
127138

128139
struct ptp_extts_event {
129140
struct ptp_clock_time t; /* Time event occured. */

0 commit comments

Comments
 (0)