long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg)
 {
        struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock);
+       struct ptp_sys_offset_extended *extoff = NULL;
        struct ptp_sys_offset_precise precise_offset;
        struct system_device_crosststamp xtstamp;
        struct ptp_clock_info *ops = ptp->info;
        struct ptp_sys_offset *sysoff = NULL;
+       struct ptp_system_timestamp sts;
        struct ptp_clock_request req;
        struct ptp_clock_caps caps;
        struct ptp_clock_time *pct;
                        err = -EFAULT;
                break;
 
+       case PTP_SYS_OFFSET_EXTENDED:
+               if (!ptp->info->gettimex64) {
+                       err = -EOPNOTSUPP;
+                       break;
+               }
+               extoff = memdup_user((void __user *)arg, sizeof(*extoff));
+               if (IS_ERR(extoff)) {
+                       err = PTR_ERR(extoff);
+                       extoff = NULL;
+                       break;
+               }
+               if (extoff->n_samples > PTP_MAX_SAMPLES) {
+                       err = -EINVAL;
+                       break;
+               }
+               for (i = 0; i < extoff->n_samples; i++) {
+                       err = ptp->info->gettimex64(ptp->info, &ts, &sts);
+                       if (err)
+                               goto out;
+                       extoff->ts[i][0].sec = sts.pre_ts.tv_sec;
+                       extoff->ts[i][0].nsec = sts.pre_ts.tv_nsec;
+                       extoff->ts[i][1].sec = ts.tv_sec;
+                       extoff->ts[i][1].nsec = ts.tv_nsec;
+                       extoff->ts[i][2].sec = sts.post_ts.tv_sec;
+                       extoff->ts[i][2].nsec = sts.post_ts.tv_nsec;
+               }
+               if (copy_to_user((void __user *)arg, extoff, sizeof(*extoff)))
+                       err = -EFAULT;
+               break;
+
        case PTP_SYS_OFFSET:
                sysoff = memdup_user((void __user *)arg, sizeof(*sysoff));
                if (IS_ERR(sysoff)) {
        }
 
 out:
+       kfree(extoff);
        kfree(sysoff);
        return err;
 }
 
 };
 
 struct system_device_crosststamp;
+
+/**
+ * struct ptp_system_timestamp - system time corresponding to a PHC timestamp
+ */
+struct ptp_system_timestamp {
+       struct timespec64 pre_ts;
+       struct timespec64 post_ts;
+};
+
 /**
  * struct ptp_clock_info - decribes a PTP hardware clock
  *
  * @gettime64:  Reads the current time from the hardware clock.
  *              parameter ts: Holds the result.
  *
+ * @gettimex64:  Reads the current time from the hardware clock and optionally
+ *               also the system clock.
+ *               parameter ts: Holds the PHC timestamp.
+ *               parameter sts: If not NULL, it holds a pair of timestamps from
+ *               the system clock. The first reading is made right before
+ *               reading the lowest bits of the PHC timestamp and the second
+ *               reading immediately follows that.
+ *
  * @getcrosststamp:  Reads the current time from the hardware clock and
  *                   system clock simultaneously.
  *                   parameter cts: Contains timestamp (device,system) pair,
        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);
+       int (*gettimex64)(struct ptp_clock_info *ptp, struct timespec64 *ts,
+                         struct ptp_system_timestamp *sts);
        int (*getcrosststamp)(struct ptp_clock_info *ptp,
                              struct system_device_crosststamp *cts);
        int (*settime64)(struct ptp_clock_info *p, const struct timespec64 *ts);
 
 #endif
 
+static inline void ptp_read_system_prets(struct ptp_system_timestamp *sts)
+{
+       if (sts)
+               ktime_get_real_ts64(&sts->pre_ts);
+}
+
+static inline void ptp_read_system_postts(struct ptp_system_timestamp *sts)
+{
+       if (sts)
+               ktime_get_real_ts64(&sts->post_ts);
+}
+
 #endif
 
        struct ptp_clock_time ts[2 * PTP_MAX_SAMPLES + 1];
 };
 
+struct ptp_sys_offset_extended {
+       unsigned int n_samples; /* Desired number of measurements. */
+       unsigned int rsv[3];    /* Reserved for future use. */
+       /*
+        * Array of [system, phc, system] time stamps. The kernel will provide
+        * 3*n_samples time stamps.
+        */
+       struct ptp_clock_time ts[PTP_MAX_SAMPLES][3];
+};
+
 struct ptp_sys_offset_precise {
        struct ptp_clock_time device;
        struct ptp_clock_time sys_realtime;
 #define PTP_PIN_SETFUNC    _IOW(PTP_CLK_MAGIC, 7, struct ptp_pin_desc)
 #define PTP_SYS_OFFSET_PRECISE \
        _IOWR(PTP_CLK_MAGIC, 8, struct ptp_sys_offset_precise)
+#define PTP_SYS_OFFSET_EXTENDED \
+       _IOW(PTP_CLK_MAGIC, 9, struct ptp_sys_offset_extended)
 
 struct ptp_extts_event {
        struct ptp_clock_time t; /* Time event occured. */