|
@@ -22,6 +22,7 @@
|
|
|
#include <linux/poll.h>
|
|
|
#include <linux/sched.h>
|
|
|
#include <linux/slab.h>
|
|
|
+#include <linux/timekeeping.h>
|
|
|
|
|
|
#include "ptp_private.h"
|
|
|
|
|
@@ -120,11 +121,13 @@ long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg)
|
|
|
struct ptp_clock_caps caps;
|
|
|
struct ptp_clock_request req;
|
|
|
struct ptp_sys_offset *sysoff = NULL;
|
|
|
+ struct ptp_sys_offset_precise precise_offset;
|
|
|
struct ptp_pin_desc pd;
|
|
|
struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock);
|
|
|
struct ptp_clock_info *ops = ptp->info;
|
|
|
struct ptp_clock_time *pct;
|
|
|
struct timespec64 ts;
|
|
|
+ struct system_device_crosststamp xtstamp;
|
|
|
int enable, err = 0;
|
|
|
unsigned int i, pin_index;
|
|
|
|
|
@@ -138,6 +141,7 @@ long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg)
|
|
|
caps.n_per_out = ptp->info->n_per_out;
|
|
|
caps.pps = ptp->info->pps;
|
|
|
caps.n_pins = ptp->info->n_pins;
|
|
|
+ caps.cross_timestamping = ptp->info->getcrosststamp != NULL;
|
|
|
if (copy_to_user((void __user *)arg, &caps, sizeof(caps)))
|
|
|
err = -EFAULT;
|
|
|
break;
|
|
@@ -180,6 +184,29 @@ long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg)
|
|
|
err = ops->enable(ops, &req, enable);
|
|
|
break;
|
|
|
|
|
|
+ case PTP_SYS_OFFSET_PRECISE:
|
|
|
+ if (!ptp->info->getcrosststamp) {
|
|
|
+ err = -EOPNOTSUPP;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ err = ptp->info->getcrosststamp(ptp->info, &xtstamp);
|
|
|
+ if (err)
|
|
|
+ break;
|
|
|
+
|
|
|
+ ts = ktime_to_timespec64(xtstamp.device);
|
|
|
+ precise_offset.device.sec = ts.tv_sec;
|
|
|
+ precise_offset.device.nsec = ts.tv_nsec;
|
|
|
+ ts = ktime_to_timespec64(xtstamp.sys_realtime);
|
|
|
+ precise_offset.sys_realtime.sec = ts.tv_sec;
|
|
|
+ precise_offset.sys_realtime.nsec = ts.tv_nsec;
|
|
|
+ ts = ktime_to_timespec64(xtstamp.sys_monoraw);
|
|
|
+ precise_offset.sys_monoraw.sec = ts.tv_sec;
|
|
|
+ precise_offset.sys_monoraw.nsec = ts.tv_nsec;
|
|
|
+ if (copy_to_user((void __user *)arg, &precise_offset,
|
|
|
+ sizeof(precise_offset)))
|
|
|
+ err = -EFAULT;
|
|
|
+ break;
|
|
|
+
|
|
|
case PTP_SYS_OFFSET:
|
|
|
sysoff = kmalloc(sizeof(*sysoff), GFP_KERNEL);
|
|
|
if (!sysoff) {
|