[3/4] ptp: add ioctl interface for ptp_gettimex64any()

Message ID 20230929023743.1611460-1-maheshb@google.com
State New
Headers
Series [1/4] time: add ktime_get_cycles64() api |

Commit Message

  add an ioctl op PTP_SYS_OFFSET_ANY2 to support ptp_gettimex64any() method

Signed-off-by: Mahesh Bandewar <maheshb@google.com>
CC: Richard Cochran <richardcochran@gmail.com>
CC: Rahul Rameshbabu <rrameshbabu@nvidia.com>
CC: "David S. Miller" <davem@davemloft.net>
CC: netdev@vger.kernel.org
---
 drivers/ptp/ptp_chardev.c      | 34 ++++++++++++++++++++++++++++++++++
 include/uapi/linux/ptp_clock.h | 14 ++++++++++++++
 2 files changed, 48 insertions(+)
  

Comments

Richard Cochran Sept. 30, 2023, 9:21 p.m. UTC | #1
On Thu, Sep 28, 2023 at 07:37:43PM -0700, Mahesh Bandewar wrote:

> diff --git a/include/uapi/linux/ptp_clock.h b/include/uapi/linux/ptp_clock.h
> index 1f1e98966cff..73bd17055a37 100644
> --- a/include/uapi/linux/ptp_clock.h
> +++ b/include/uapi/linux/ptp_clock.h
> @@ -166,6 +166,18 @@ struct ptp_sys_offset_extended {
>  	struct ptp_clock_time ts[PTP_MAX_SAMPLES][3];
>  };
>  
> +struct ptp_sys_offset_any {
> +	unsigned int n_samples;		/* Desired number of measurements. */
> +	enum ptp_ts_types ts_type;	/* One of the TS types */

clockid_t other_clock;

Hm?

> +	unsigned int rsv[2];		/* Reserved for future use. */
> +	/*
> +	 * Array of [TS, phc, TS] time stamps. The kernel will provide
> +	 * 3*n_samples time stamps.
> +	 * TS is any of the ts_type requested.
> +	 */
> +	struct ptp_clock_time ts[PTP_MAX_SAMPLES][3];
> +};

Thanks,
Richard
  
Richard Cochran Sept. 30, 2023, 9:25 p.m. UTC | #2
On Thu, Sep 28, 2023 at 07:37:43PM -0700, Mahesh Bandewar wrote:
> add an ioctl op PTP_SYS_OFFSET_ANY2 to support ptp_gettimex64any() method

This is a useful idea.

But how about a new system call instead?

    clock_compare(clockid_t a, clockid_t b);

It would accept any two clock IDs.

I've been wanting this for a long time, but never found time to
implement it.

Thanks,
Richard
  
Richard Cochran Sept. 30, 2023, 11:07 p.m. UTC | #3
On Sat, Sep 30, 2023 at 02:25:23PM -0700, Richard Cochran wrote:
> But how about a new system call instead?
> 
>     clock_compare(clockid_t a, clockid_t b);

It could have a third argument, n_samples, that would only be used for
"slow" clocks like PCIe MACs.  The system call would return the offset
from the shortest measurement (which is really what user space needs).

Thanks,
Richard
  
Mahesh Bandewar (महेश बंडेवार) Oct. 3, 2023, 12:29 a.m. UTC | #4
On Sat, Sep 30, 2023 at 2:25 PM Richard Cochran
<richardcochran@gmail.com> wrote:
>
> On Thu, Sep 28, 2023 at 07:37:43PM -0700, Mahesh Bandewar wrote:
> > add an ioctl op PTP_SYS_OFFSET_ANY2 to support ptp_gettimex64any() method
>
> This is a useful idea.
>
> But how about a new system call instead?
>
>     clock_compare(clockid_t a, clockid_t b);
>
The purpose of this API is not to compare clocks but to get the width
of reading the MTS value (offered by NICs) in terms of the timebase
that is selected to essentially improve the accuracy.

> It would accept any two clock IDs.
>
> I've been wanting this for a long time, but never found time to
> implement it.
>
> Thanks,
> Richard
  
Richard Cochran Oct. 4, 2023, 4:23 a.m. UTC | #5
On Mon, Oct 02, 2023 at 05:29:58PM -0700, Mahesh Bandewar (महेश बंडेवार) wrote:

> The purpose of this API is not to compare clocks but to get the width
> of reading the MTS value (offered by NICs) in terms of the timebase
> that is selected to essentially improve the accuracy.

What is MTS ?
  

Patch

diff --git a/drivers/ptp/ptp_chardev.c b/drivers/ptp/ptp_chardev.c
index 362bf756e6b7..fef1c7e7e6e6 100644
--- a/drivers/ptp/ptp_chardev.c
+++ b/drivers/ptp/ptp_chardev.c
@@ -110,6 +110,7 @@  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_any *anyoff = NULL;
 	struct ptp_sys_offset_precise precise_offset;
 	struct system_device_crosststamp xtstamp;
 	struct ptp_clock_info *ops = ptp->info;
@@ -324,6 +325,39 @@  long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg)
 			err = -EFAULT;
 		break;
 
+	case PTP_SYS_OFFSET_ANY2:
+		if (!ptp->info->gettimex64any) {
+			err = -EOPNOTSUPP;
+			break;
+		}
+		anyoff = memdup_user((void __user *)arg, sizeof(*anyoff));
+		if (IS_ERR(anyoff)) {
+			err = PTR_ERR(anyoff);
+			anyoff = NULL;
+			break;
+		}
+		if (anyoff->n_samples > PTP_MAX_SAMPLES
+		    || anyoff->ts_type >= PTP_TS_MAX
+		    || anyoff->rsv[0] || anyoff->rsv[1]) {
+			err = -EINVAL;
+			break;
+		}
+		for (i = 0; i < anyoff->n_samples; i++) {
+			err = ptp->info->gettimex64any(ptp->info, &ts, &sts,
+						       anyoff->ts_type);
+			if (err)
+				goto out;
+			anyoff->ts[i][0].sec = sts.pre_ts.tv_sec;
+			anyoff->ts[i][0].nsec = sts.pre_ts.tv_nsec;
+			anyoff->ts[i][1].sec = ts.tv_sec;
+			anyoff->ts[i][1].nsec = ts.tv_nsec;
+			anyoff->ts[i][2].sec = sts.post_ts.tv_sec;
+			anyoff->ts[i][2].nsec = sts.post_ts.tv_nsec;
+		}
+		if (copy_to_user((void __user *)arg, anyoff, sizeof(*anyoff)))
+			err = -EFAULT;
+		break;
+
 	case PTP_SYS_OFFSET:
 	case PTP_SYS_OFFSET2:
 		sysoff = memdup_user((void __user *)arg, sizeof(*sysoff));
diff --git a/include/uapi/linux/ptp_clock.h b/include/uapi/linux/ptp_clock.h
index 1f1e98966cff..73bd17055a37 100644
--- a/include/uapi/linux/ptp_clock.h
+++ b/include/uapi/linux/ptp_clock.h
@@ -166,6 +166,18 @@  struct ptp_sys_offset_extended {
 	struct ptp_clock_time ts[PTP_MAX_SAMPLES][3];
 };
 
+struct ptp_sys_offset_any {
+	unsigned int n_samples;		/* Desired number of measurements. */
+	enum ptp_ts_types ts_type;	/* One of the TS types */
+	unsigned int rsv[2];		/* Reserved for future use. */
+	/*
+	 * Array of [TS, phc, TS] time stamps. The kernel will provide
+	 * 3*n_samples time stamps.
+	 * TS is any of the ts_type requested.
+	 */
+	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;
@@ -232,6 +244,8 @@  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_SYS_OFFSET_ANY2 \
+	_IOWR(PTP_CLK_MAGIC, 19, struct ptp_sys_offset_any)
 
 struct ptp_extts_event {
 	struct ptp_clock_time t; /* Time event occured. */