netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [net-next, v2, 0/7] ptp: support virtual clocks for multiple
@ 2021-05-21  4:36 Yangbo Lu
  2021-05-21  4:36 ` [net-next, v2, 1/7] ptp: add ptp virtual clock driver framework Yangbo Lu
                   ` (6 more replies)
  0 siblings, 7 replies; 23+ messages in thread
From: Yangbo Lu @ 2021-05-21  4:36 UTC (permalink / raw)
  To: netdev
  Cc: Yangbo Lu, David S . Miller, Richard Cochran, Claudiu Manoil,
	Jakub Kicinski

Current PTP driver exposes one PTP device to user which binds network
interface/interfaces to provide timestamping. Actually we have a way
utilizing timecounter/cyclecounter to virtualize any number of PTP
clocks based on a same free running physical clock for using.
The purpose of having multiple PTP virtual clocks is for user space
to directly/easily use them for multiple domains synchronization.

               +------------------------------+
MAC driver:    |      rx/tx PTP packet        |
               +------------------------------+
                               ^
                               | Match vclock via domain value
                               | Convert HW timestamp to domain time
                               v
         +--------------+--------------+--------------+
vclock:  | ptp1 domain1 | ptp2 domain2 | ptpN domainN |
         +--------------+--------------+--------------+
pclock:  |             ptp0 free running              |
         +--------------------------------------------+

The block diagram may explain how it works. Besides the PTP virtual
clocks, the PTP packet HW timestamp converting to domain time is also
done in kernel.

An example to use it:

  Run two ptp4l jobs on each of two boards for domain 1 and 2 synchronziation.

  Board1:
    # echo 2 > /sys/class/ptp/ptp0/num_vclocks
    [  282.230432] ptp ptp0: new virtual clock ptp2
    [  282.235211] ptp ptp0: new virtual clock ptp3
    [  282.240354] ptp ptp0: guarantee physical clock free running
    # echo 1 > /sys/class/ptp/ptp2/domain
    # echo 2 > /sys/class/ptp/ptp3/domain
    #
    # ptp4l -i eno0 -p/dev/ptp2 -m --domainNumber=1 --priority1=127 > domain1-master.log 2>&1 &
    # ptp4l -i eno0 -p/dev/ptp3 -m --domainNumber=2 --priority1=128 > domain2-slave.log 2>&1 &

  Board2:
    # echo 2 > /sys/class/ptp/ptp0/num_vclocks
    [  259.619382] ptp ptp0: new virtual clock ptp2
    [  259.624140] ptp ptp0: new virtual clock ptp3
    [  259.629315] ptp ptp0: guarantee physical clock free running
    # echo 1 > /sys/class/ptp/ptp2/domain
    # echo 2 > /sys/class/ptp/ptp3/domain
    #
    # ptp4l -i eno0 -p/dev/ptp2 -m --domainNumber=1 --priority1=128 > domain1-slave.log 2>&1 &
    # ptp4l -i eno0 -p/dev/ptp3 -m --domainNumber=2 --priority1=127 > domain2-master.log 2>&1 &

  Physical clock is guaranteed to stay free running when virtual clocks
  are created. To back use physical clock,

    # echo 0 > /sys/class/ptp/ptp0/num_vclocks
    [  531.249944] ptp ptp0: delete virtual clock ptp3
    [  531.254971] ptp ptp0: delete virtual clock ptp2
    [  531.259976] ptp ptp0: only physical clock in use now

How the patch-set affect current ptp drivers/function:

  - For current drivers, no impact on all existing function.

  - For drivers adapted to use it in the future, no impact on all
    existing function unless configuring value to num_vclocks in
    sysfs to convert to using virtual clocks.

  - For drivers adapted to use it with virtual clocks in using
    - Manual configurations are required for domain value in sysfs.
    - Manual configurations are required for application to specify
      right ptp device for domain on which the application will run.
    Note,
    - Physical clock is guaranteed to stay free running. Operation on it
      returns error.
    - If domain value of application has no PTP clock matched, the
      original HW timestamp will be used.

How to adapt drivers to use the feature:

  - During normally registering PTP clock for physical clock with
    ptp_clock_info, just fill the new member vclock_cc which contains
    cyclecounter info for virtual clock.

  - Timestamp conversion to domain time need to be done in MAC driver.
    When get HW timestamp, parse PTP packet domain value and convert
    timestamp to domain time by calling API ptp_clock_domain_tstamp(),
    before submitting to upper stack.

TODO:

  - PTP physical clock and its timestamping capabilities is still
    binding to network interface/interfaces through ethtool_ts_info.
    New way is needed to support querying all PTP virtual clocks
    and their timestamping capabilities. Making application to use
    PTP virtual clocks dynamically is a direction.

  - PTP packet parsing for domain value and one-step sync (not related
    to this patch-set) is common used. Make such functions common.

Changes for v2:
	- Converted to num_vclocks for creating virtual clocks.
	- Guranteed physical clock free running when using virtual
	  clocks.
	- Fixed build warning.
	- Updated copyright.

Yangbo Lu (7):
  ptp: add ptp virtual clock driver framework
  ptp: support ptp physical/virtual clocks conversion
  ptp: support domains and timestamp conversion
  ptp_qoriq: export ptp clock reading function for cyclecounter
  enetc_ptp: support ptp virtual clock
  enetc: store ptp device pointer
  enetc: support PTP domain timestamp conversion

 Documentation/ABI/testing/sysfs-ptp           |  25 +++
 MAINTAINERS                                   |   6 +
 drivers/net/ethernet/freescale/enetc/enetc.c  |  39 +++-
 drivers/net/ethernet/freescale/enetc/enetc.h  |   3 +-
 .../net/ethernet/freescale/enetc/enetc_pf.c   |  14 +-
 .../net/ethernet/freescale/enetc/enetc_ptp.c  |  13 +-
 .../net/ethernet/freescale/enetc/enetc_vf.c   |  14 +-
 drivers/ptp/Makefile                          |   2 +-
 drivers/ptp/ptp_clock.c                       |  12 ++
 drivers/ptp/ptp_private.h                     |  42 +++++
 drivers/ptp/ptp_qoriq.c                       |  16 ++
 drivers/ptp/ptp_sysfs.c                       | 134 +++++++++++++
 drivers/ptp/ptp_vclock.c                      | 176 ++++++++++++++++++
 include/linux/fsl/ptp_qoriq.h                 |   3 +-
 include/linux/ptp_clock_kernel.h              |  57 +++++-
 15 files changed, 545 insertions(+), 11 deletions(-)
 create mode 100644 drivers/ptp/ptp_vclock.c


base-commit: 86544c3de6a2185409c5a3d02f674ea223a14217
-- 
2.25.1


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [net-next, v2, 1/7] ptp: add ptp virtual clock driver framework
  2021-05-21  4:36 [net-next, v2, 0/7] ptp: support virtual clocks for multiple Yangbo Lu
@ 2021-05-21  4:36 ` Yangbo Lu
  2021-05-23 21:24   ` Richard Cochran
  2021-05-21  4:36 ` [net-next, v2, 2/7] ptp: support ptp physical/virtual clocks conversion Yangbo Lu
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 23+ messages in thread
From: Yangbo Lu @ 2021-05-21  4:36 UTC (permalink / raw)
  To: netdev
  Cc: Yangbo Lu, David S . Miller, Richard Cochran, Claudiu Manoil,
	Jakub Kicinski

This patch is to add ptp virtual clock driver framework
which just exports essential APIs.

A new member is added for ptp_clock_info structure. Device driver
can provide initial cyclecounter info for ptp virtual clock via
this member, before normally registering ptp clock.

- struct ptp_vclock_cc *vclock_cc;

PTP vclock register/unregister APIs are private for PTP driver.
They can be called after normal ptp clock registering.

- ptp_vclock_register()
- ptp_vclock_unregister()

And below API added is for device driver to get ptp_clock_info of
registered physical clock through cyclecounter pointer of ptp virtual
clock. This is needed for cyclecounter .read callback to read
physical clock cycles.

- ptp_get_pclock_info()

Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
---
Changes for v2:
	- Split from v1 patch #1.
	- Fixed build warning.
	- Updated copyright.
---
 MAINTAINERS                      |   6 ++
 drivers/ptp/Makefile             |   2 +-
 drivers/ptp/ptp_private.h        |  23 +++++
 drivers/ptp/ptp_vclock.c         | 142 +++++++++++++++++++++++++++++++
 include/linux/ptp_clock_kernel.h |  43 +++++++++-
 5 files changed, 214 insertions(+), 2 deletions(-)
 create mode 100644 drivers/ptp/ptp_vclock.c

diff --git a/MAINTAINERS b/MAINTAINERS
index bd7aff0c120f..13ef366e4ab4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14818,6 +14818,12 @@ F:	drivers/net/phy/dp83640*
 F:	drivers/ptp/*
 F:	include/linux/ptp_cl*
 
+PTP VIRTUAL CLOCK SUPPORT
+M:	Yangbo Lu <yangbo.lu@nxp.com>
+L:	netdev@vger.kernel.org
+S:	Maintained
+F:	drivers/ptp/ptp_vclock.c
+
 PTRACE SUPPORT
 M:	Oleg Nesterov <oleg@redhat.com>
 S:	Maintained
diff --git a/drivers/ptp/Makefile b/drivers/ptp/Makefile
index 8673d1743faa..3c6a905760e2 100644
--- a/drivers/ptp/Makefile
+++ b/drivers/ptp/Makefile
@@ -3,7 +3,7 @@
 # Makefile for PTP 1588 clock support.
 #
 
-ptp-y					:= ptp_clock.o ptp_chardev.o ptp_sysfs.o
+ptp-y					:= ptp_clock.o ptp_vclock.o ptp_chardev.o ptp_sysfs.o
 ptp_kvm-$(CONFIG_X86)			:= ptp_kvm_x86.o ptp_kvm_common.o
 ptp_kvm-$(CONFIG_HAVE_ARM_SMCCC)	:= ptp_kvm_arm.o ptp_kvm_common.o
 obj-$(CONFIG_PTP_1588_CLOCK)		+= ptp.o
diff --git a/drivers/ptp/ptp_private.h b/drivers/ptp/ptp_private.h
index 6b97155148f1..870e54506781 100644
--- a/drivers/ptp/ptp_private.h
+++ b/drivers/ptp/ptp_private.h
@@ -3,6 +3,7 @@
  * PTP 1588 clock support - private declarations for the core module.
  *
  * Copyright (C) 2010 OMICRON electronics GmbH
+ * Copyright 2021 NXP
  */
 #ifndef _PTP_PRIVATE_H_
 #define _PTP_PRIVATE_H_
@@ -48,6 +49,26 @@ struct ptp_clock {
 	struct kthread_delayed_work aux_work;
 };
 
+#define info_to_vclock(d) container_of((d), struct ptp_vclock, info)
+#define cc_to_vclock(d) container_of((d), struct ptp_vclock, cc)
+#define dw_to_vclock(d) container_of((d), struct ptp_vclock, refresh_work)
+
+struct ptp_vclock {
+	struct ptp_clock *pclock;
+	struct ptp_clock_info info;
+	struct ptp_clock *clock;
+
+	/* timecounter/cyclecounter definitions */
+	struct cyclecounter cc;
+	struct timecounter tc;
+	spinlock_t lock;	/* protects tc/cc */
+	struct delayed_work refresh_work;
+	unsigned long refresh_interval;
+	u32 mult;
+	u32 mult_factor;
+	u32 div_factor;
+};
+
 /*
  * The function queue_cnt() is safe for readers to call without
  * holding q->lock. Readers use this function to verify that the queue
@@ -89,4 +110,6 @@ extern const struct attribute_group *ptp_groups[];
 int ptp_populate_pin_groups(struct ptp_clock *ptp);
 void ptp_cleanup_pin_groups(struct ptp_clock *ptp);
 
+struct ptp_vclock *ptp_vclock_register(struct ptp_clock *pclock);
+void ptp_vclock_unregister(struct ptp_vclock *vclock);
 #endif
diff --git a/drivers/ptp/ptp_vclock.c b/drivers/ptp/ptp_vclock.c
new file mode 100644
index 000000000000..70aae8696003
--- /dev/null
+++ b/drivers/ptp/ptp_vclock.c
@@ -0,0 +1,142 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * PTP virtual clock driver
+ *
+ * Copyright 2021 NXP
+ */
+#include <linux/slab.h>
+#include "ptp_private.h"
+
+static int ptp_vclock_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
+{
+	struct ptp_vclock *vclock = info_to_vclock(ptp);
+	unsigned long flags;
+	s64 adj;
+
+	adj = (s64)scaled_ppm * vclock->mult_factor;
+	adj = div_s64(adj, vclock->div_factor);
+
+	spin_lock_irqsave(&vclock->lock, flags);
+	timecounter_read(&vclock->tc);
+	vclock->cc.mult = vclock->mult + adj;
+	spin_unlock_irqrestore(&vclock->lock, flags);
+
+	return 0;
+}
+
+static int ptp_vclock_adjtime(struct ptp_clock_info *ptp, s64 delta)
+{
+	struct ptp_vclock *vclock = info_to_vclock(ptp);
+	unsigned long flags;
+
+	spin_lock_irqsave(&vclock->lock, flags);
+	timecounter_adjtime(&vclock->tc, delta);
+	spin_unlock_irqrestore(&vclock->lock, flags);
+
+	return 0;
+}
+
+static int ptp_vclock_gettime(struct ptp_clock_info *ptp,
+			      struct timespec64 *ts)
+{
+	struct ptp_vclock *vclock = info_to_vclock(ptp);
+	unsigned long flags;
+	u64 ns;
+
+	spin_lock_irqsave(&vclock->lock, flags);
+	ns = timecounter_read(&vclock->tc);
+	spin_unlock_irqrestore(&vclock->lock, flags);
+	*ts = ns_to_timespec64(ns);
+
+	return 0;
+}
+
+static int ptp_vclock_settime(struct ptp_clock_info *ptp,
+			      const struct timespec64 *ts)
+{
+	struct ptp_vclock *vclock = info_to_vclock(ptp);
+	u64 ns = timespec64_to_ns(ts);
+	unsigned long flags;
+
+	spin_lock_irqsave(&vclock->lock, flags);
+	timecounter_init(&vclock->tc, &vclock->cc, ns);
+	spin_unlock_irqrestore(&vclock->lock, flags);
+
+	return 0;
+}
+
+static const struct ptp_clock_info ptp_vclock_info = {
+	.owner		= THIS_MODULE,
+	.name		= "ptp virtual clock",
+	/* The maximum ppb value that long scaled_ppm can support */
+	.max_adj	= 32767999,
+	.adjfine	= ptp_vclock_adjfine,
+	.adjtime	= ptp_vclock_adjtime,
+	.gettime64	= ptp_vclock_gettime,
+	.settime64	= ptp_vclock_settime,
+};
+
+static void ptp_vclock_refresh(struct work_struct *work)
+{
+	struct delayed_work *dw = to_delayed_work(work);
+	struct ptp_vclock *vclock = dw_to_vclock(dw);
+	struct timespec64 ts;
+
+	ptp_vclock_gettime(&vclock->info, &ts);
+	schedule_delayed_work(&vclock->refresh_work, vclock->refresh_interval);
+}
+
+struct ptp_clock_info *ptp_get_pclock_info(const struct cyclecounter *cc)
+{
+	struct ptp_vclock *vclock = cc_to_vclock(cc);
+
+	return vclock->pclock->info;
+}
+EXPORT_SYMBOL(ptp_get_pclock_info);
+
+struct ptp_vclock *ptp_vclock_register(struct ptp_clock *pclock)
+{
+	struct ptp_vclock_cc *vclock_cc = pclock->info->vclock_cc;
+	struct ptp_vclock *vclock;
+
+	vclock = kzalloc(sizeof(*vclock), GFP_KERNEL);
+	if (!vclock)
+		return NULL;
+
+	vclock->pclock = pclock;
+
+	vclock->info = ptp_vclock_info;
+	vclock->info.vclock_cc = vclock_cc;
+	snprintf(vclock->info.name, PTP_CLOCK_NAME_LEN,
+		 "virtual clock on ptp%d", pclock->index);
+
+	/* Copy members initial values of ptp_vclock_cc to ptp_vclock */
+	vclock->cc = vclock_cc->cc;
+	vclock->mult = vclock_cc->cc.mult;
+	vclock->refresh_interval = vclock_cc->refresh_interval;
+	vclock->mult_factor = vclock_cc->mult_factor;
+	vclock->div_factor = vclock_cc->div_factor;
+
+	spin_lock_init(&vclock->lock);
+
+	vclock->clock = ptp_clock_register(&vclock->info, pclock->dev.parent);
+	if (IS_ERR_OR_NULL(vclock->clock)) {
+		kfree(vclock);
+		return NULL;
+	}
+
+	timecounter_init(&vclock->tc, &vclock->cc,
+			 ktime_to_ns(ktime_get_real()));
+
+	INIT_DELAYED_WORK(&vclock->refresh_work, ptp_vclock_refresh);
+	schedule_delayed_work(&vclock->refresh_work, vclock->refresh_interval);
+
+	return vclock;
+}
+
+void ptp_vclock_unregister(struct ptp_vclock *vclock)
+{
+	cancel_delayed_work_sync(&vclock->refresh_work);
+	ptp_clock_unregister(vclock->clock);
+	kfree(vclock);
+}
diff --git a/include/linux/ptp_clock_kernel.h b/include/linux/ptp_clock_kernel.h
index a311bddd9e85..e4c1c6411e7d 100644
--- a/include/linux/ptp_clock_kernel.h
+++ b/include/linux/ptp_clock_kernel.h
@@ -3,6 +3,7 @@
  * PTP 1588 clock support
  *
  * Copyright (C) 2010 OMICRON electronics GmbH
+ * Copyright 2021 NXP
  */
 
 #ifndef _PTP_CLOCK_KERNEL_H_
@@ -11,7 +12,9 @@
 #include <linux/device.h>
 #include <linux/pps_kernel.h>
 #include <linux/ptp_clock.h>
+#include <linux/timecounter.h>
 
+#define PTP_CLOCK_NAME_LEN	32
 /**
  * struct ptp_clock_request - request PTP clock event
  *
@@ -48,6 +51,32 @@ struct ptp_system_timestamp {
 	struct timespec64 post_ts;
 };
 
+/**
+ * struct ptp_vclock_cc - ptp virtual clock cycle counter info
+ *
+ * @cc:               cyclecounter structure
+ * @refresh_interval: time interval to refresh time counter, to avoid 64-bit
+ *                    overflow during delta conversion. For example, with
+ *                    cc.mult value 2^28,  there are 36 bits left of cycle
+ *                    counter. With 1 ns counter resolution, the overflow time
+ *                    is 2^36 ns which is 68.7 s. The refresh_interval may be
+ *                    (60 * HZ) less than 68.7 s.
+ * @mult_factor:      parameter for cc.mult adjustment calculation, see below
+ * @div_factor:       parameter for cc.mult adjustment calculation, see below
+ *
+ * scaled_ppm to adjustment of cc.mult
+ *
+ * adj = mult * (ppb / 10^9)
+ *     = mult * (scaled_ppm * 1000 / 2^16) / 10^9
+ *     = scaled_ppm * mult_factor / div_factor
+ */
+struct ptp_vclock_cc {
+	struct cyclecounter cc;
+	unsigned long refresh_interval;
+	u32 mult_factor;
+	u32 div_factor;
+};
+
 /**
  * struct ptp_clock_info - describes a PTP hardware clock
  *
@@ -64,6 +93,8 @@ struct ptp_system_timestamp {
  * @pin_config: Array of length 'n_pins'. If the number of
  *              programmable pins is nonzero, then drivers must
  *              allocate and initialize this array.
+ * @vclock_cc: ptp_vclock_cc structure pointer. Provide initial cyclecounter
+ *             info for ptp virtual clock. This is optional.
  *
  * clock operations
  *
@@ -134,7 +165,7 @@ struct ptp_system_timestamp {
 
 struct ptp_clock_info {
 	struct module *owner;
-	char name[16];
+	char name[PTP_CLOCK_NAME_LEN];
 	s32 max_adj;
 	int n_alarm;
 	int n_ext_ts;
@@ -142,6 +173,7 @@ struct ptp_clock_info {
 	int n_pins;
 	int pps;
 	struct ptp_pin_desc *pin_config;
+	struct ptp_vclock_cc *vclock_cc;
 	int (*adjfine)(struct ptp_clock_info *ptp, long scaled_ppm);
 	int (*adjfreq)(struct ptp_clock_info *ptp, s32 delta);
 	int (*adjphase)(struct ptp_clock_info *ptp, s32 phase);
@@ -304,6 +336,12 @@ int ptp_schedule_worker(struct ptp_clock *ptp, unsigned long delay);
  */
 void ptp_cancel_worker_sync(struct ptp_clock *ptp);
 
+/**
+ * ptp_get_pclock_info() - get ptp_clock_info pointer of physical clock
+ *
+ * @cc:     cyclecounter pointer of ptp virtual clock.
+ */
+struct ptp_clock_info *ptp_get_pclock_info(const struct cyclecounter *cc);
 #else
 static inline struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info,
 						   struct device *parent)
@@ -324,6 +362,9 @@ static inline int ptp_schedule_worker(struct ptp_clock *ptp,
 static inline void ptp_cancel_worker_sync(struct ptp_clock *ptp)
 { }
 
+static inline struct ptp_clock_info *ptp_get_pclock_info(
+	const struct cyclecounter *cc)
+{ return NULL; }
 #endif
 
 static inline void ptp_read_system_prets(struct ptp_system_timestamp *sts)
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [net-next, v2, 2/7] ptp: support ptp physical/virtual clocks conversion
  2021-05-21  4:36 [net-next, v2, 0/7] ptp: support virtual clocks for multiple Yangbo Lu
  2021-05-21  4:36 ` [net-next, v2, 1/7] ptp: add ptp virtual clock driver framework Yangbo Lu
@ 2021-05-21  4:36 ` Yangbo Lu
  2021-05-25 11:33   ` Richard Cochran
  2021-05-25 12:28   ` Richard Cochran
  2021-05-21  4:36 ` [net-next, v2, 3/7] ptp: support domains and timestamp conversion Yangbo Lu
                   ` (4 subsequent siblings)
  6 siblings, 2 replies; 23+ messages in thread
From: Yangbo Lu @ 2021-05-21  4:36 UTC (permalink / raw)
  To: netdev
  Cc: Yangbo Lu, David S . Miller, Richard Cochran, Claudiu Manoil,
	Jakub Kicinski

Support ptp physical/virtual clocks conversion via sysfs.
There will be a new attribute num_vclocks under ptp physical
clock sysfs.

- In default, the value is 0 meaning only ptp physical clock
  is in use.
- Setting the value can create corresponding number of ptp
  virtual clocks to use. But current physical clock is guaranteed
  to stay free running.
- Setting the value back to 0 can delete virtual clocks and back
  use physical clock again.

Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
---
Changes for v2:
	- Split from v1 patch #2.
	- Converted to num_vclocks for creating virtual clocks.
	- Guranteed physical clock free running when using virtual
	  clocks.
	- Fixed build warning.
	- Updated copyright.
---
 Documentation/ABI/testing/sysfs-ptp | 13 +++++
 drivers/ptp/ptp_clock.c             | 11 ++++
 drivers/ptp/ptp_private.h           | 13 +++++
 drivers/ptp/ptp_sysfs.c             | 79 +++++++++++++++++++++++++++++
 drivers/ptp/ptp_vclock.c            |  1 +
 include/linux/ptp_clock_kernel.h    |  1 +
 6 files changed, 118 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-ptp b/Documentation/ABI/testing/sysfs-ptp
index 2363ad810ddb..6403e746eeb4 100644
--- a/Documentation/ABI/testing/sysfs-ptp
+++ b/Documentation/ABI/testing/sysfs-ptp
@@ -61,6 +61,19 @@ Description:
 		This file contains the number of programmable pins
 		offered by the PTP hardware clock.
 
+What:		/sys/class/ptp/ptpN/num_vclocks
+Date:		May 2021
+Contact:	Yangbo Lu <yangbo.lu@nxp.com>
+Description:
+		This file contains the ptp virtual clocks number in use,
+		based on current ptp physical clock. In default, the
+		value is 0 meaning only ptp physical clock is in use.
+		Setting the value can create corresponding number of ptp
+		virtual clocks to use. But current ptp physical clock is
+		guaranteed to stay free running. Setting the value back
+		to 0 can delete ptp virtual clocks and back use ptp
+		physical clock again.
+
 What:		/sys/class/ptp/ptpN/pins
 Date:		March 2014
 Contact:	Richard Cochran <richardcochran@gmail.com>
diff --git a/drivers/ptp/ptp_clock.c b/drivers/ptp/ptp_clock.c
index a780435331c8..9b8ab1e6625f 100644
--- a/drivers/ptp/ptp_clock.c
+++ b/drivers/ptp/ptp_clock.c
@@ -3,6 +3,7 @@
  * PTP 1588 clock support
  *
  * Copyright (C) 2010 OMICRON electronics GmbH
+ * Copyright 2021 NXP
  */
 #include <linux/idr.h>
 #include <linux/device.h>
@@ -76,6 +77,11 @@ static int ptp_clock_settime(struct posix_clock *pc, const struct timespec64 *tp
 {
 	struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock);
 
+	if (ptp_guarantee_pclock(ptp)) {
+		pr_err("ptp: virtual clock in use, guarantee physical clock free running\n");
+		return -EBUSY;
+	}
+
 	return  ptp->info->settime64(ptp->info, tp);
 }
 
@@ -97,6 +103,11 @@ static int ptp_clock_adjtime(struct posix_clock *pc, struct __kernel_timex *tx)
 	struct ptp_clock_info *ops;
 	int err = -EOPNOTSUPP;
 
+	if (ptp_guarantee_pclock(ptp)) {
+		pr_err("ptp: virtual clock in use, guarantee physical clock free running\n");
+		return -EBUSY;
+	}
+
 	ops = ptp->info;
 
 	if (tx->modes & ADJ_SETOFFSET) {
diff --git a/drivers/ptp/ptp_private.h b/drivers/ptp/ptp_private.h
index 870e54506781..da24d0c83799 100644
--- a/drivers/ptp/ptp_private.h
+++ b/drivers/ptp/ptp_private.h
@@ -47,6 +47,7 @@ struct ptp_clock {
 	const struct attribute_group *pin_attr_groups[2];
 	struct kthread_worker *kworker;
 	struct kthread_delayed_work aux_work;
+	u8 num_vclocks;
 };
 
 #define info_to_vclock(d) container_of((d), struct ptp_vclock, info)
@@ -82,6 +83,18 @@ static inline int queue_cnt(struct timestamp_event_queue *q)
 	return cnt < 0 ? PTP_MAX_TIMESTAMPS + cnt : cnt;
 }
 
+/*
+ * Guarantee physical clock to stay free running, if ptp virtual clocks
+ * on it are in use.
+ */
+static inline bool ptp_guarantee_pclock(struct ptp_clock *ptp)
+{
+	if (!ptp->info->vclock_flag && ptp->num_vclocks)
+		return true;
+
+	return false;
+}
+
 /*
  * see ptp_chardev.c
  */
diff --git a/drivers/ptp/ptp_sysfs.c b/drivers/ptp/ptp_sysfs.c
index be076a91e20e..5e1b5947dbff 100644
--- a/drivers/ptp/ptp_sysfs.c
+++ b/drivers/ptp/ptp_sysfs.c
@@ -3,6 +3,7 @@
  * PTP 1588 clock support - sysfs interface.
  *
  * Copyright (C) 2010 OMICRON electronics GmbH
+ * Copyright 2021 NXP
  */
 #include <linux/capability.h>
 #include <linux/slab.h>
@@ -148,6 +149,80 @@ static ssize_t pps_enable_store(struct device *dev,
 }
 static DEVICE_ATTR(pps_enable, 0220, NULL, pps_enable_store);
 
+static int unregister_vclock(struct device *dev, void *data)
+{
+	struct ptp_clock *ptp = dev_get_drvdata(dev);
+	struct ptp_clock_info *info = ptp->info;
+	struct ptp_vclock *vclock;
+	u8 *num = data;
+
+	if (info->vclock_flag) {
+		vclock = info_to_vclock(info);
+		dev_info(&vclock->pclock->dev, "delete virtual clock ptp%d\n",
+			 vclock->clock->index);
+		ptp_vclock_unregister(vclock);
+		(*num)--;
+	}
+
+	/* For break. Not error. */
+	if (*num == 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+static ssize_t num_vclocks_show(struct device *dev,
+				struct device_attribute *attr, char *page)
+{
+	struct ptp_clock *ptp = dev_get_drvdata(dev);
+
+	return snprintf(page, PAGE_SIZE-1, "%d\n", ptp->num_vclocks);
+}
+
+static ssize_t num_vclocks_store(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf, size_t count)
+{
+	struct ptp_clock *ptp = dev_get_drvdata(dev);
+	struct ptp_vclock *vclock;
+	int err = -EINVAL;
+	u8 num, i;
+
+	if (kstrtou8(buf, 0, &num))
+		goto out;
+
+	/* Need to create more vclocks */
+	if (num > ptp->num_vclocks) {
+		for (i = 0; i < num - ptp->num_vclocks; i++) {
+			vclock = ptp_vclock_register(ptp);
+			if (!vclock)
+				goto out;
+
+			dev_info(dev, "new virtual clock ptp%d\n",
+				 vclock->clock->index);
+		}
+	}
+
+	/* Need to delete vclocks */
+	if (num < ptp->num_vclocks) {
+		i = ptp->num_vclocks - num;
+		device_for_each_child_reverse(dev->parent, &i,
+					      unregister_vclock);
+	}
+
+	if (num == 0)
+		dev_info(dev, "only physical clock in use now\n");
+	else
+		dev_info(dev, "guarantee physical clock free running\n");
+
+	ptp->num_vclocks = num;
+
+	return count;
+out:
+	return err;
+}
+static DEVICE_ATTR_RW(num_vclocks);
+
 static struct attribute *ptp_attrs[] = {
 	&dev_attr_clock_name.attr,
 
@@ -162,6 +237,7 @@ static struct attribute *ptp_attrs[] = {
 	&dev_attr_fifo.attr,
 	&dev_attr_period.attr,
 	&dev_attr_pps_enable.attr,
+	&dev_attr_num_vclocks.attr,
 	NULL
 };
 
@@ -183,6 +259,9 @@ static umode_t ptp_is_attribute_visible(struct kobject *kobj,
 	} else if (attr == &dev_attr_pps_enable.attr) {
 		if (!info->pps)
 			mode = 0;
+	} else if (attr == &dev_attr_num_vclocks.attr) {
+		if (info->vclock_flag || !info->vclock_cc)
+			mode = 0;
 	}
 
 	return mode;
diff --git a/drivers/ptp/ptp_vclock.c b/drivers/ptp/ptp_vclock.c
index 70aae8696003..fce09f10ae69 100644
--- a/drivers/ptp/ptp_vclock.c
+++ b/drivers/ptp/ptp_vclock.c
@@ -68,6 +68,7 @@ static int ptp_vclock_settime(struct ptp_clock_info *ptp,
 static const struct ptp_clock_info ptp_vclock_info = {
 	.owner		= THIS_MODULE,
 	.name		= "ptp virtual clock",
+	.vclock_flag	= true,
 	/* The maximum ppb value that long scaled_ppm can support */
 	.max_adj	= 32767999,
 	.adjfine	= ptp_vclock_adjfine,
diff --git a/include/linux/ptp_clock_kernel.h b/include/linux/ptp_clock_kernel.h
index e4c1c6411e7d..8f34f192f2cf 100644
--- a/include/linux/ptp_clock_kernel.h
+++ b/include/linux/ptp_clock_kernel.h
@@ -174,6 +174,7 @@ struct ptp_clock_info {
 	int pps;
 	struct ptp_pin_desc *pin_config;
 	struct ptp_vclock_cc *vclock_cc;
+	bool vclock_flag;
 	int (*adjfine)(struct ptp_clock_info *ptp, long scaled_ppm);
 	int (*adjfreq)(struct ptp_clock_info *ptp, s32 delta);
 	int (*adjphase)(struct ptp_clock_info *ptp, s32 phase);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [net-next, v2, 3/7] ptp: support domains and timestamp conversion
  2021-05-21  4:36 [net-next, v2, 0/7] ptp: support virtual clocks for multiple Yangbo Lu
  2021-05-21  4:36 ` [net-next, v2, 1/7] ptp: add ptp virtual clock driver framework Yangbo Lu
  2021-05-21  4:36 ` [net-next, v2, 2/7] ptp: support ptp physical/virtual clocks conversion Yangbo Lu
@ 2021-05-21  4:36 ` Yangbo Lu
  2021-05-21  4:36 ` [net-next, v2, 4/7] ptp_qoriq: export ptp clock reading function for cyclecounter Yangbo Lu
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 23+ messages in thread
From: Yangbo Lu @ 2021-05-21  4:36 UTC (permalink / raw)
  To: netdev
  Cc: Yangbo Lu, David S . Miller, Richard Cochran, Claudiu Manoil,
	Jakub Kicinski

PTP virtual clocks support is actually for multiple domains
synchronization.

This patch is to support configuring domain value for PTP
virtual clock via sysfs and to support hardware timestamp
conversion to domain time. The idea is driver identifying
PTP message domain number, matching with PTP virtual clock
which has same domain number configured, and then converting
to the PTP virtual clock time. The identifying could be in
MAC driver, the matching and converting is through the API
this patch added which can be called by MAC driver,

- ptp_clock_domain_tstamp()

Different domain values should be configured for multiple ptp
virtual clocks based on same one free running ptp physical clock.
If ptp message domain value has no PTP clock matched, the
original hardware timestamp will be used.

Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
---
Changes for v2:
	- Split from v1 patch #1 and #2.
	- Fixed build warning.
---
 Documentation/ABI/testing/sysfs-ptp | 12 +++++++
 drivers/ptp/ptp_clock.c             |  1 +
 drivers/ptp/ptp_private.h           |  6 ++++
 drivers/ptp/ptp_sysfs.c             | 55 +++++++++++++++++++++++++++++
 drivers/ptp/ptp_vclock.c            | 33 +++++++++++++++++
 include/linux/ptp_clock_kernel.h    | 13 +++++++
 6 files changed, 120 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-ptp b/Documentation/ABI/testing/sysfs-ptp
index 6403e746eeb4..7a518185cb11 100644
--- a/Documentation/ABI/testing/sysfs-ptp
+++ b/Documentation/ABI/testing/sysfs-ptp
@@ -25,6 +25,18 @@ Description:
 		MAC based ones. The string does not necessarily have
 		to be any kind of unique id.
 
+What:		/sys/class/ptp/ptpN/domain
+Date:		May 2021
+Contact:	Yangbo Lu <yangbo.lu@nxp.com>
+Description:
+		This file contains the domain value that the PTP virtual
+		clock serves. PTP virtual clock will provide timestamp
+		to PTP messages which have same domain matched.
+		Write value 0 ~ 255 into this file to change the domain.
+		Writing -1 means serving no domain. If PTP message domain
+		value does not have a PTP virtual clock matched, the
+		original hardware time stamp will be used.
+
 What:		/sys/class/ptp/ptpN/max_adjustment
 Date:		September 2010
 Contact:	Richard Cochran <richardcochran@gmail.com>
diff --git a/drivers/ptp/ptp_clock.c b/drivers/ptp/ptp_clock.c
index 9b8ab1e6625f..4ad20b2aae57 100644
--- a/drivers/ptp/ptp_clock.c
+++ b/drivers/ptp/ptp_clock.c
@@ -216,6 +216,7 @@ struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info,
 	ptp->info = info;
 	ptp->devid = MKDEV(major, index);
 	ptp->index = index;
+	ptp->domain = -1;	/* No domain set */
 	spin_lock_init(&ptp->tsevq.lock);
 	mutex_init(&ptp->tsevq_mux);
 	mutex_init(&ptp->pincfg_mux);
diff --git a/drivers/ptp/ptp_private.h b/drivers/ptp/ptp_private.h
index da24d0c83799..fe8f976b7b75 100644
--- a/drivers/ptp/ptp_private.h
+++ b/drivers/ptp/ptp_private.h
@@ -48,6 +48,7 @@ struct ptp_clock {
 	struct kthread_worker *kworker;
 	struct kthread_delayed_work aux_work;
 	u8 num_vclocks;
+	int16_t domain;
 };
 
 #define info_to_vclock(d) container_of((d), struct ptp_vclock, info)
@@ -70,6 +71,11 @@ struct ptp_vclock {
 	u32 div_factor;
 };
 
+struct domain_tstamp {
+	u64 tstamp;
+	u8 domain;
+};
+
 /*
  * The function queue_cnt() is safe for readers to call without
  * holding q->lock. Readers use this function to verify that the queue
diff --git a/drivers/ptp/ptp_sysfs.c b/drivers/ptp/ptp_sysfs.c
index 5e1b5947dbff..b854661aadeb 100644
--- a/drivers/ptp/ptp_sysfs.c
+++ b/drivers/ptp/ptp_sysfs.c
@@ -223,6 +223,57 @@ static ssize_t num_vclocks_store(struct device *dev,
 }
 static DEVICE_ATTR_RW(num_vclocks);
 
+static int check_domain_avail(struct device *dev, void *data)
+{
+	struct ptp_clock *ptp = dev_get_drvdata(dev);
+	int16_t *domain = data;
+
+	if (ptp->domain == *domain)
+		return -EINVAL;
+
+	return 0;
+}
+
+static ssize_t domain_show(struct device *dev,
+			   struct device_attribute *attr, char *page)
+{
+	struct ptp_clock *ptp = dev_get_drvdata(dev);
+
+	return snprintf(page, PAGE_SIZE-1, "%d\n", ptp->domain);
+}
+
+static ssize_t domain_store(struct device *dev,
+			    struct device_attribute *attr,
+			    const char *buf, size_t count)
+{
+	struct ptp_clock *ptp = dev_get_drvdata(dev);
+	int err = -EINVAL;
+	int16_t domain;
+
+	if (kstrtos16(buf, 0, &domain))
+		goto out;
+
+	if (domain > 255 || domain < -1)
+		goto out;
+
+	if (domain == -1) {
+		ptp->domain = -1;
+		return count;
+	}
+
+	if (device_for_each_child(dev->parent, &domain, check_domain_avail)) {
+		dev_err(dev, "the domain value already in used\n");
+		goto out;
+	}
+
+	ptp->domain = domain;
+
+	return count;
+out:
+	return err;
+}
+static DEVICE_ATTR_RW(domain);
+
 static struct attribute *ptp_attrs[] = {
 	&dev_attr_clock_name.attr,
 
@@ -238,6 +289,7 @@ static struct attribute *ptp_attrs[] = {
 	&dev_attr_period.attr,
 	&dev_attr_pps_enable.attr,
 	&dev_attr_num_vclocks.attr,
+	&dev_attr_domain.attr,
 	NULL
 };
 
@@ -262,6 +314,9 @@ static umode_t ptp_is_attribute_visible(struct kobject *kobj,
 	} else if (attr == &dev_attr_num_vclocks.attr) {
 		if (info->vclock_flag || !info->vclock_cc)
 			mode = 0;
+	} else if (attr == &dev_attr_domain.attr) {
+		if (!info->vclock_flag)
+			mode = 0;
 	}
 
 	return mode;
diff --git a/drivers/ptp/ptp_vclock.c b/drivers/ptp/ptp_vclock.c
index fce09f10ae69..6e7d1403d024 100644
--- a/drivers/ptp/ptp_vclock.c
+++ b/drivers/ptp/ptp_vclock.c
@@ -87,6 +87,39 @@ static void ptp_vclock_refresh(struct work_struct *work)
 	schedule_delayed_work(&vclock->refresh_work, vclock->refresh_interval);
 }
 
+static int ptp_convert_domain_tstamp(struct device *dev, void *data)
+{
+	struct ptp_clock *ptp = dev_get_drvdata(dev);
+	struct ptp_clock_info *info = ptp->info;
+	struct domain_tstamp *domain_ts = data;
+	struct ptp_vclock *vclock;
+	unsigned long flags;
+
+	/* Convert to domain tstamp if there is a domain matched */
+	if (ptp->domain == domain_ts->domain) {
+		vclock = info_to_vclock(info);
+		spin_lock_irqsave(&vclock->lock, flags);
+		domain_ts->tstamp = timecounter_cyc2time(&vclock->tc,
+							 domain_ts->tstamp);
+		spin_unlock_irqrestore(&vclock->lock, flags);
+		return -EINVAL;	/* For break. Not error. */
+	}
+
+	return 0;
+}
+
+void ptp_clock_domain_tstamp(struct device *ptp_dev, u64 *tstamp, u8 domain)
+{
+	struct domain_tstamp domain_ts;
+
+	domain_ts.tstamp = *tstamp;
+	domain_ts.domain = domain;
+
+	device_for_each_child(ptp_dev, &domain_ts, ptp_convert_domain_tstamp);
+	*tstamp = domain_ts.tstamp;
+}
+EXPORT_SYMBOL(ptp_clock_domain_tstamp);
+
 struct ptp_clock_info *ptp_get_pclock_info(const struct cyclecounter *cc)
 {
 	struct ptp_vclock *vclock = cc_to_vclock(cc);
diff --git a/include/linux/ptp_clock_kernel.h b/include/linux/ptp_clock_kernel.h
index 8f34f192f2cf..edc816cdfb2c 100644
--- a/include/linux/ptp_clock_kernel.h
+++ b/include/linux/ptp_clock_kernel.h
@@ -343,6 +343,15 @@ void ptp_cancel_worker_sync(struct ptp_clock *ptp);
  * @cc:     cyclecounter pointer of ptp virtual clock.
  */
 struct ptp_clock_info *ptp_get_pclock_info(const struct cyclecounter *cc);
+
+/**
+ * ptp_clock_domain_tstamp() - convert to domain timestamp
+ *
+ * @ptp_dev: device pointer of current ptp clock.
+ * @tstamp:  time stamp pointer to hardware time stamp
+ * @domain:  domain number to convert
+ */
+void ptp_clock_domain_tstamp(struct device *ptp_dev, u64 *tstamp, u8 domain);
 #else
 static inline struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info,
 						   struct device *parent)
@@ -366,6 +375,10 @@ static inline void ptp_cancel_worker_sync(struct ptp_clock *ptp)
 static inline struct ptp_clock_info *ptp_get_pclock_info(
 	const struct cyclecounter *cc)
 { return NULL; }
+
+static inline void ptp_clock_domain_tstamp(struct device *dev, u64 *tstamp,
+					   u8 domain)
+{ }
 #endif
 
 static inline void ptp_read_system_prets(struct ptp_system_timestamp *sts)
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [net-next, v2, 4/7] ptp_qoriq: export ptp clock reading function for cyclecounter
  2021-05-21  4:36 [net-next, v2, 0/7] ptp: support virtual clocks for multiple Yangbo Lu
                   ` (2 preceding siblings ...)
  2021-05-21  4:36 ` [net-next, v2, 3/7] ptp: support domains and timestamp conversion Yangbo Lu
@ 2021-05-21  4:36 ` Yangbo Lu
  2021-05-21  4:36 ` [net-next, v2, 5/7] enetc_ptp: support ptp virtual clock Yangbo Lu
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 23+ messages in thread
From: Yangbo Lu @ 2021-05-21  4:36 UTC (permalink / raw)
  To: netdev
  Cc: Yangbo Lu, David S . Miller, Richard Cochran, Claudiu Manoil,
	Jakub Kicinski

Export ptp clock reading function for cyclecounter to read cycles.

Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
---
Changes for v2:
	- Updated copyright.
---
 drivers/ptp/ptp_qoriq.c       | 16 ++++++++++++++++
 include/linux/fsl/ptp_qoriq.h |  3 ++-
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/drivers/ptp/ptp_qoriq.c b/drivers/ptp/ptp_qoriq.c
index 08f4cf0ad9e3..2bcbe9da2a29 100644
--- a/drivers/ptp/ptp_qoriq.c
+++ b/drivers/ptp/ptp_qoriq.c
@@ -3,6 +3,7 @@
  * PTP 1588 clock for Freescale QorIQ 1588 timer
  *
  * Copyright (C) 2010 OMICRON electronics GmbH
+ * Copyright 2021 NXP
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -311,6 +312,21 @@ int ptp_qoriq_enable(struct ptp_clock_info *ptp,
 }
 EXPORT_SYMBOL_GPL(ptp_qoriq_enable);
 
+u64 ptp_qoriq_clock_read(const struct cyclecounter *cc)
+{
+	struct ptp_clock_info *ptp = ptp_get_pclock_info(cc);
+	struct ptp_qoriq *ptp_qoriq = container_of(ptp, struct ptp_qoriq, caps);
+	unsigned long flags;
+	u64 ns;
+
+	spin_lock_irqsave(&ptp_qoriq->lock, flags);
+	ns = tmr_cnt_read(ptp_qoriq);
+	spin_unlock_irqrestore(&ptp_qoriq->lock, flags);
+
+	return ns;
+}
+EXPORT_SYMBOL_GPL(ptp_qoriq_clock_read);
+
 static const struct ptp_clock_info ptp_qoriq_caps = {
 	.owner		= THIS_MODULE,
 	.name		= "qoriq ptp clock",
diff --git a/include/linux/fsl/ptp_qoriq.h b/include/linux/fsl/ptp_qoriq.h
index 01acebe37fab..4590e70f1afb 100644
--- a/include/linux/fsl/ptp_qoriq.h
+++ b/include/linux/fsl/ptp_qoriq.h
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2010 OMICRON electronics GmbH
- * Copyright 2018 NXP
+ * Copyright 2018-2021 NXP
  */
 #ifndef __PTP_QORIQ_H__
 #define __PTP_QORIQ_H__
@@ -193,6 +193,7 @@ int ptp_qoriq_settime(struct ptp_clock_info *ptp,
 		      const struct timespec64 *ts);
 int ptp_qoriq_enable(struct ptp_clock_info *ptp,
 		     struct ptp_clock_request *rq, int on);
+u64 ptp_qoriq_clock_read(const struct cyclecounter *cc);
 int extts_clean_up(struct ptp_qoriq *ptp_qoriq, int index, bool update_event);
 #ifdef CONFIG_DEBUG_FS
 void ptp_qoriq_create_debugfs(struct ptp_qoriq *ptp_qoriq);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [net-next, v2, 5/7] enetc_ptp: support ptp virtual clock
  2021-05-21  4:36 [net-next, v2, 0/7] ptp: support virtual clocks for multiple Yangbo Lu
                   ` (3 preceding siblings ...)
  2021-05-21  4:36 ` [net-next, v2, 4/7] ptp_qoriq: export ptp clock reading function for cyclecounter Yangbo Lu
@ 2021-05-21  4:36 ` Yangbo Lu
  2021-05-21  4:36 ` [net-next, v2, 6/7] enetc: store ptp device pointer Yangbo Lu
  2021-05-21  4:36 ` [net-next, v2, 7/7] enetc: support PTP domain timestamp conversion Yangbo Lu
  6 siblings, 0 replies; 23+ messages in thread
From: Yangbo Lu @ 2021-05-21  4:36 UTC (permalink / raw)
  To: netdev
  Cc: Yangbo Lu, David S . Miller, Richard Cochran, Claudiu Manoil,
	Jakub Kicinski

Add support for ptp virtual clock.

Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
---
Changes for v2:
	- Made ptp_qoriq_vclock_cc static.
	- Updated copyright.
---
 drivers/net/ethernet/freescale/enetc/enetc_ptp.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ptp.c b/drivers/net/ethernet/freescale/enetc/enetc_ptp.c
index bc594892507a..dabcdaf972a9 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_ptp.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_ptp.c
@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
-/* Copyright 2019 NXP */
+/* Copyright 2019-2021 NXP */
 
 #include <linux/module.h>
 #include <linux/of.h>
@@ -10,6 +10,16 @@
 int enetc_phc_index = -1;
 EXPORT_SYMBOL(enetc_phc_index);
 
+static struct ptp_vclock_cc ptp_qoriq_vclock_cc = {
+	.cc.read		= ptp_qoriq_clock_read,
+	.cc.mask		= CYCLECOUNTER_MASK(64),
+	.cc.shift		= 28,
+	.cc.mult		= (1 << 28),
+	.refresh_interval	= (HZ * 60),
+	.mult_factor		= (1 << 6),
+	.div_factor		= 15625,
+};
+
 static struct ptp_clock_info enetc_ptp_caps = {
 	.owner		= THIS_MODULE,
 	.name		= "ENETC PTP clock",
@@ -24,6 +34,7 @@ static struct ptp_clock_info enetc_ptp_caps = {
 	.gettime64	= ptp_qoriq_gettime,
 	.settime64	= ptp_qoriq_settime,
 	.enable		= ptp_qoriq_enable,
+	.vclock_cc	= &ptp_qoriq_vclock_cc,
 };
 
 static int enetc_ptp_probe(struct pci_dev *pdev,
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [net-next, v2, 6/7] enetc: store ptp device pointer
  2021-05-21  4:36 [net-next, v2, 0/7] ptp: support virtual clocks for multiple Yangbo Lu
                   ` (4 preceding siblings ...)
  2021-05-21  4:36 ` [net-next, v2, 5/7] enetc_ptp: support ptp virtual clock Yangbo Lu
@ 2021-05-21  4:36 ` Yangbo Lu
  2021-05-21  4:36 ` [net-next, v2, 7/7] enetc: support PTP domain timestamp conversion Yangbo Lu
  6 siblings, 0 replies; 23+ messages in thread
From: Yangbo Lu @ 2021-05-21  4:36 UTC (permalink / raw)
  To: netdev
  Cc: Yangbo Lu, David S . Miller, Richard Cochran, Claudiu Manoil,
	Jakub Kicinski

Store ptp device pointer which will be used for ptp domain
timestamp conversion.

Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
---
Changes for v2:
	- Made sure ptp device was got.
	- Update copyright.
---
 drivers/net/ethernet/freescale/enetc/enetc.h    |  3 ++-
 drivers/net/ethernet/freescale/enetc/enetc_pf.c | 14 +++++++++++++-
 drivers/net/ethernet/freescale/enetc/enetc_vf.c | 14 +++++++++++++-
 3 files changed, 28 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h
index 08b283347d9c..925f2a96e375 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
-/* Copyright 2017-2019 NXP */
+/* Copyright 2017-2021 NXP */
 
 #include <linux/timer.h>
 #include <linux/pci.h>
@@ -351,6 +351,7 @@ struct enetc_ndev_priv {
 
 	struct work_struct	tx_onestep_tstamp;
 	struct sk_buff_head	tx_skbs;
+	struct device *ptp_dev;
 };
 
 /* Messaging */
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index 31274325159a..994a4d3b715e 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
-/* Copyright 2017-2019 NXP */
+/* Copyright 2017-2021 NXP */
 
 #include <linux/mdio.h>
 #include <linux/module.h>
@@ -1201,6 +1201,7 @@ static int enetc_pf_probe(struct pci_dev *pdev,
 {
 	struct device_node *node = pdev->dev.of_node;
 	struct enetc_ndev_priv *priv;
+	struct pci_dev *ptp_pdev;
 	struct net_device *ndev;
 	struct enetc_si *si;
 	struct enetc_pf *pf;
@@ -1293,6 +1294,16 @@ static int enetc_pf_probe(struct pci_dev *pdev,
 		goto err_alloc_msix;
 	}
 
+	ptp_pdev = pci_get_device(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID_PTP,
+				  NULL);
+	if (!ptp_pdev) {
+		dev_err(&pdev->dev, "no PTP device found\n");
+		err = -ENODEV;
+		goto err_get_ptp;
+	}
+
+	priv->ptp_dev = &ptp_pdev->dev;
+
 	if (!of_get_phy_mode(node, &pf->if_mode)) {
 		err = enetc_mdiobus_create(pf, node);
 		if (err)
@@ -1310,6 +1321,7 @@ static int enetc_pf_probe(struct pci_dev *pdev,
 	return 0;
 
 err_reg_netdev:
+err_get_ptp:
 	enetc_phylink_destroy(priv);
 err_phylink_create:
 	enetc_mdiobus_destroy(pf);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_vf.c b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
index 03090ba7e226..ca1deb7d4dcb 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_vf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
-/* Copyright 2017-2019 NXP */
+/* Copyright 2017-2021 NXP */
 
 #include <linux/module.h>
 #include "enetc.h"
@@ -138,6 +138,7 @@ static int enetc_vf_probe(struct pci_dev *pdev,
 			  const struct pci_device_id *ent)
 {
 	struct enetc_ndev_priv *priv;
+	struct pci_dev *ptp_pdev;
 	struct net_device *ndev;
 	struct enetc_si *si;
 	int err;
@@ -188,6 +189,16 @@ static int enetc_vf_probe(struct pci_dev *pdev,
 		goto err_alloc_msix;
 	}
 
+	ptp_pdev = pci_get_device(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID_PTP,
+				  NULL);
+	if (!ptp_pdev) {
+		dev_err(&pdev->dev, "no PTP device found\n");
+		err = -ENODEV;
+		goto err_get_ptp;
+	}
+
+	priv->ptp_dev = &ptp_pdev->dev;
+
 	err = register_netdev(ndev);
 	if (err)
 		goto err_reg_netdev;
@@ -197,6 +208,7 @@ static int enetc_vf_probe(struct pci_dev *pdev,
 	return 0;
 
 err_reg_netdev:
+err_get_ptp:
 	enetc_free_msix(priv);
 err_config_si:
 err_alloc_msix:
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [net-next, v2, 7/7] enetc: support PTP domain timestamp conversion
  2021-05-21  4:36 [net-next, v2, 0/7] ptp: support virtual clocks for multiple Yangbo Lu
                   ` (5 preceding siblings ...)
  2021-05-21  4:36 ` [net-next, v2, 6/7] enetc: store ptp device pointer Yangbo Lu
@ 2021-05-21  4:36 ` Yangbo Lu
  2021-05-22 20:46   ` Claudiu Manoil
  2021-05-25 12:37   ` Richard Cochran
  6 siblings, 2 replies; 23+ messages in thread
From: Yangbo Lu @ 2021-05-21  4:36 UTC (permalink / raw)
  To: netdev
  Cc: Yangbo Lu, David S . Miller, Richard Cochran, Claudiu Manoil,
	Jakub Kicinski

Support timestamp conversion to specified PTP domain in PTP packet.

Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
---
Changes for v2:
	- Fixed build waring.
	- Updated copyright.
---
 drivers/net/ethernet/freescale/enetc/enetc.c | 39 ++++++++++++++++++--
 1 file changed, 35 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
index 3ca93adb9662..cd0429c73999 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
-/* Copyright 2017-2019 NXP */
+/* Copyright 2017-2021 NXP */
 
 #include "enetc.h"
 #include <linux/bpf_trace.h>
@@ -7,6 +7,7 @@
 #include <linux/udp.h>
 #include <linux/vmalloc.h>
 #include <linux/ptp_classify.h>
+#include <linux/ptp_clock_kernel.h>
 #include <net/pkt_sched.h>
 
 static int enetc_num_stack_tx_queues(struct enetc_ndev_priv *priv)
@@ -472,13 +473,36 @@ static void enetc_get_tx_tstamp(struct enetc_hw *hw, union enetc_tx_bd *txbd,
 	*tstamp = (u64)hi << 32 | tstamp_lo;
 }
 
-static void enetc_tstamp_tx(struct sk_buff *skb, u64 tstamp)
+static int enetc_ptp_parse_domain(struct sk_buff *skb, u8 *domain)
+{
+	unsigned int ptp_class;
+	struct ptp_header *hdr;
+
+	ptp_class = ptp_classify_raw(skb);
+	if (ptp_class == PTP_CLASS_NONE)
+		return -EINVAL;
+
+	hdr = ptp_parse_header(skb, ptp_class);
+	if (!hdr)
+		return -EINVAL;
+
+	*domain = hdr->domain_number;
+	return 0;
+}
+
+static void enetc_tstamp_tx(struct enetc_ndev_priv *priv, struct sk_buff *skb,
+			    u64 tstamp)
 {
 	struct skb_shared_hwtstamps shhwtstamps;
+	u64 ts = tstamp;
+	u8 domain;
 
 	if (skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS) {
+		if (!enetc_ptp_parse_domain(skb, &domain))
+			ptp_clock_domain_tstamp(priv->ptp_dev, &ts, domain);
+
 		memset(&shhwtstamps, 0, sizeof(shhwtstamps));
-		shhwtstamps.hwtstamp = ns_to_ktime(tstamp);
+		shhwtstamps.hwtstamp = ns_to_ktime(ts);
 		skb_txtime_consumed(skb);
 		skb_tstamp_tx(skb, &shhwtstamps);
 	}
@@ -575,7 +599,7 @@ static bool enetc_clean_tx_ring(struct enetc_bdr *tx_ring, int napi_budget)
 				 */
 				schedule_work(&priv->tx_onestep_tstamp);
 			} else if (unlikely(do_twostep_tstamp)) {
-				enetc_tstamp_tx(skb, tstamp);
+				enetc_tstamp_tx(priv, skb, tstamp);
 				do_twostep_tstamp = false;
 			}
 			napi_consume_skb(skb, napi_budget);
@@ -698,6 +722,7 @@ static void enetc_get_rx_tstamp(struct net_device *ndev,
 	struct enetc_hw *hw = &priv->si->hw;
 	u32 lo, hi, tstamp_lo;
 	u64 tstamp;
+	u8 domain;
 
 	if (le16_to_cpu(rxbd->r.flags) & ENETC_RXBD_FLAG_TSTMP) {
 		lo = enetc_rd_reg_hot(hw->reg + ENETC_SICTR0);
@@ -708,6 +733,12 @@ static void enetc_get_rx_tstamp(struct net_device *ndev,
 			hi -= 1;
 
 		tstamp = (u64)hi << 32 | tstamp_lo;
+
+		skb_reset_mac_header(skb);
+
+		if (!enetc_ptp_parse_domain(skb, &domain))
+			ptp_clock_domain_tstamp(priv->ptp_dev, &tstamp, domain);
+
 		memset(shhwtstamps, 0, sizeof(*shhwtstamps));
 		shhwtstamps->hwtstamp = ns_to_ktime(tstamp);
 	}
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [net-next, v2, 7/7] enetc: support PTP domain timestamp conversion
  2021-05-21  4:36 ` [net-next, v2, 7/7] enetc: support PTP domain timestamp conversion Yangbo Lu
@ 2021-05-22 20:46   ` Claudiu Manoil
  2021-05-25 12:37   ` Richard Cochran
  1 sibling, 0 replies; 23+ messages in thread
From: Claudiu Manoil @ 2021-05-22 20:46 UTC (permalink / raw)
  To: Yangbo Lu, netdev
  Cc: David S . Miller, Richard Cochran, Claudiu Manoil, Jakub Kicinski

hi Yangbo,

On 21.05.2021 07:36, Yangbo Lu wrote:
> Support timestamp conversion to specified PTP domain in PTP packet.
> 
> Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
> ---
> Changes for v2:
> 	- Fixed build waring.
> 	- Updated copyright.
> ---
>   drivers/net/ethernet/freescale/enetc/enetc.c | 39 ++++++++++++++++++--
>   1 file changed, 35 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
> index 3ca93adb9662..cd0429c73999 100644
> --- a/drivers/net/ethernet/freescale/enetc/enetc.c
> +++ b/drivers/net/ethernet/freescale/enetc/enetc.c
> @@ -1,5 +1,5 @@
>   // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
> -/* Copyright 2017-2019 NXP */
> +/* Copyright 2017-2021 NXP */
>   
>   #include "enetc.h"
>   #include <linux/bpf_trace.h>
> @@ -7,6 +7,7 @@
>   #include <linux/udp.h>
>   #include <linux/vmalloc.h>
>   #include <linux/ptp_classify.h>
> +#include <linux/ptp_clock_kernel.h>
>   #include <net/pkt_sched.h>
>   
>   static int enetc_num_stack_tx_queues(struct enetc_ndev_priv *priv)
> @@ -472,13 +473,36 @@ static void enetc_get_tx_tstamp(struct enetc_hw *hw, union enetc_tx_bd *txbd,
>   	*tstamp = (u64)hi << 32 | tstamp_lo;
>   }
>   
> -static void enetc_tstamp_tx(struct sk_buff *skb, u64 tstamp)
> +static int enetc_ptp_parse_domain(struct sk_buff *skb, u8 *domain)
> +{
> +	unsigned int ptp_class;
> +	struct ptp_header *hdr;
> +
> +	ptp_class = ptp_classify_raw(skb);
> +	if (ptp_class == PTP_CLASS_NONE)
> +		return -EINVAL;
> +
> +	hdr = ptp_parse_header(skb, ptp_class);
> +	if (!hdr)
> +		return -EINVAL;
> +
> +	*domain = hdr->domain_number;
> +	return 0;
> +}
> +

Why is this function defined inside the enetc driver? I don't see 
anything enetc specific to it, but it looks like another generic ptp 
procedure, similar to ptp_parse_header() or ptp_clock_domain_tstamp().

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [net-next, v2, 1/7] ptp: add ptp virtual clock driver framework
  2021-05-21  4:36 ` [net-next, v2, 1/7] ptp: add ptp virtual clock driver framework Yangbo Lu
@ 2021-05-23 21:24   ` Richard Cochran
  2021-05-31 10:38     ` Y.b. Lu
  0 siblings, 1 reply; 23+ messages in thread
From: Richard Cochran @ 2021-05-23 21:24 UTC (permalink / raw)
  To: Yangbo Lu; +Cc: netdev, David S . Miller, Claudiu Manoil, Jakub Kicinski

On Fri, May 21, 2021 at 12:36:13PM +0800, Yangbo Lu wrote:
> This patch is to add ptp virtual clock driver framework
> which just exports essential APIs.
> 
> A new member is added for ptp_clock_info structure. Device driver
> can provide initial cyclecounter info for ptp virtual clock via
> this member, before normally registering ptp clock.

Why not provide this in the PHC class layer, and make it work for
every driver without alteration?

> +/**
> + * struct ptp_vclock_cc - ptp virtual clock cycle counter info
> + *
> + * @cc:               cyclecounter structure
> + * @refresh_interval: time interval to refresh time counter, to avoid 64-bit
> + *                    overflow during delta conversion. For example, with
> + *                    cc.mult value 2^28,  there are 36 bits left of cycle
> + *                    counter. With 1 ns counter resolution, the overflow time
> + *                    is 2^36 ns which is 68.7 s. The refresh_interval may be
> + *                    (60 * HZ) less than 68.7 s.
> + * @mult_factor:      parameter for cc.mult adjustment calculation, see below
> + * @div_factor:       parameter for cc.mult adjustment calculation, see below

Just use  mult = 2147483648 = 0x80000000 and div = 31.

Read the real PHC using .gettime() and then mask off the high 32 bits.

Arrange a kthread to read once every 4 (better 2) seconds to keep the
time value correct.

See?

Thanks,
Richard


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [net-next, v2, 2/7] ptp: support ptp physical/virtual clocks conversion
  2021-05-21  4:36 ` [net-next, v2, 2/7] ptp: support ptp physical/virtual clocks conversion Yangbo Lu
@ 2021-05-25 11:33   ` Richard Cochran
  2021-05-31 10:39     ` Y.b. Lu
  2021-05-25 12:28   ` Richard Cochran
  1 sibling, 1 reply; 23+ messages in thread
From: Richard Cochran @ 2021-05-25 11:33 UTC (permalink / raw)
  To: Yangbo Lu; +Cc: netdev, David S . Miller, Claudiu Manoil, Jakub Kicinski

On Fri, May 21, 2021 at 12:36:14PM +0800, Yangbo Lu wrote:

> diff --git a/Documentation/ABI/testing/sysfs-ptp b/Documentation/ABI/testing/sysfs-ptp
> index 2363ad810ddb..6403e746eeb4 100644
> --- a/Documentation/ABI/testing/sysfs-ptp
> +++ b/Documentation/ABI/testing/sysfs-ptp
> @@ -61,6 +61,19 @@ Description:
>  		This file contains the number of programmable pins
>  		offered by the PTP hardware clock.
>  
> +What:		/sys/class/ptp/ptpN/num_vclocks

How about "n_vclocks" to be consistent with n_external_timestamps, etc...

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [net-next, v2, 2/7] ptp: support ptp physical/virtual clocks conversion
  2021-05-21  4:36 ` [net-next, v2, 2/7] ptp: support ptp physical/virtual clocks conversion Yangbo Lu
  2021-05-25 11:33   ` Richard Cochran
@ 2021-05-25 12:28   ` Richard Cochran
  2021-05-31 10:40     ` Y.b. Lu
  1 sibling, 1 reply; 23+ messages in thread
From: Richard Cochran @ 2021-05-25 12:28 UTC (permalink / raw)
  To: Yangbo Lu; +Cc: netdev, David S . Miller, Claudiu Manoil, Jakub Kicinski

On Fri, May 21, 2021 at 12:36:14PM +0800, Yangbo Lu wrote:

> @@ -76,6 +77,11 @@ static int ptp_clock_settime(struct posix_clock *pc, const struct timespec64 *tp
>  {
>  	struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock);
>  
> +	if (ptp_guarantee_pclock(ptp)) {

Going to need to protect against concurrency WRT ptp->num_vclocks.

> +		pr_err("ptp: virtual clock in use, guarantee physical clock free running\n");
> +		return -EBUSY;
> +	}
> +
>  	return  ptp->info->settime64(ptp->info, tp);
>  }

Thanks,
Richard

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [net-next, v2, 7/7] enetc: support PTP domain timestamp conversion
  2021-05-21  4:36 ` [net-next, v2, 7/7] enetc: support PTP domain timestamp conversion Yangbo Lu
  2021-05-22 20:46   ` Claudiu Manoil
@ 2021-05-25 12:37   ` Richard Cochran
  2021-05-25 12:48     ` Richard Cochran
  2021-05-31 10:51     ` Y.b. Lu
  1 sibling, 2 replies; 23+ messages in thread
From: Richard Cochran @ 2021-05-25 12:37 UTC (permalink / raw)
  To: Yangbo Lu; +Cc: netdev, David S . Miller, Claudiu Manoil, Jakub Kicinski

On Fri, May 21, 2021 at 12:36:19PM +0800, Yangbo Lu wrote:

> @@ -472,13 +473,36 @@ static void enetc_get_tx_tstamp(struct enetc_hw *hw, union enetc_tx_bd *txbd,
>  	*tstamp = (u64)hi << 32 | tstamp_lo;
>  }
>  
> -static void enetc_tstamp_tx(struct sk_buff *skb, u64 tstamp)
> +static int enetc_ptp_parse_domain(struct sk_buff *skb, u8 *domain)
> +{
> +	unsigned int ptp_class;
> +	struct ptp_header *hdr;
> +
> +	ptp_class = ptp_classify_raw(skb);
> +	if (ptp_class == PTP_CLASS_NONE)
> +		return -EINVAL;
> +
> +	hdr = ptp_parse_header(skb, ptp_class);
> +	if (!hdr)
> +		return -EINVAL;
> +
> +	*domain = hdr->domain_number;

This is really clunky.  We do NOT want to have drivers starting to
handle the PTP.  That is the job of the user space stack.

Instead, the conversion from raw time stamp to vclock time stamp
should happen in the core infrastructure.  That way, no driver hacks
will be needed, and it will "just work" everywhere.

We need a way to associate a given socket with a particular vclock.
Perhaps we can extend the SO_TIMESTAMPING API to allow that.

> +	return 0;
> +}

Thanks,
Richard

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [net-next, v2, 7/7] enetc: support PTP domain timestamp conversion
  2021-05-25 12:37   ` Richard Cochran
@ 2021-05-25 12:48     ` Richard Cochran
  2021-05-31 11:26       ` Y.b. Lu
  2021-05-31 10:51     ` Y.b. Lu
  1 sibling, 1 reply; 23+ messages in thread
From: Richard Cochran @ 2021-05-25 12:48 UTC (permalink / raw)
  To: Yangbo Lu; +Cc: netdev, David S . Miller, Claudiu Manoil, Jakub Kicinski

On Tue, May 25, 2021 at 05:37:11AM -0700, Richard Cochran wrote:
> Instead, the conversion from raw time stamp to vclock time stamp
> should happen in the core infrastructure.  That way, no driver hacks
> will be needed, and it will "just work" everywhere.

For transmit time stamps, we have skb_complete_tx_timestamp().

For receive, most drivers use the following cliche:

	shwt = skb_hwtstamps(skb);
	memset(shwt, 0, sizeof(*shwt));
	shwt->hwtstamp = ns_to_ktime(ns);

So the first step will be to introduce a helper function for that, and
then re-factor the drivers to use the helper.

Thanks,
Richard

 

^ permalink raw reply	[flat|nested] 23+ messages in thread

* RE: [net-next, v2, 1/7] ptp: add ptp virtual clock driver framework
  2021-05-23 21:24   ` Richard Cochran
@ 2021-05-31 10:38     ` Y.b. Lu
  0 siblings, 0 replies; 23+ messages in thread
From: Y.b. Lu @ 2021-05-31 10:38 UTC (permalink / raw)
  To: Richard Cochran; +Cc: netdev, David S . Miller, Claudiu Manoil, Jakub Kicinski

> -----Original Message-----
> From: Richard Cochran <richardcochran@gmail.com>
> Sent: 2021年5月24日 5:24
> To: Y.b. Lu <yangbo.lu@nxp.com>
> Cc: netdev@vger.kernel.org; David S . Miller <davem@davemloft.net>; Claudiu
> Manoil <claudiu.manoil@nxp.com>; Jakub Kicinski <kuba@kernel.org>
> Subject: Re: [net-next, v2, 1/7] ptp: add ptp virtual clock driver framework
> 
> On Fri, May 21, 2021 at 12:36:13PM +0800, Yangbo Lu wrote:
> > This patch is to add ptp virtual clock driver framework which just
> > exports essential APIs.
> >
> > A new member is added for ptp_clock_info structure. Device driver can
> > provide initial cyclecounter info for ptp virtual clock via this
> > member, before normally registering ptp clock.
> 
> Why not provide this in the PHC class layer, and make it work for every driver
> without alteration?

That's better. Will implement in v3.

> 
> > +/**
> > + * struct ptp_vclock_cc - ptp virtual clock cycle counter info
> > + *
> > + * @cc:               cyclecounter structure
> > + * @refresh_interval: time interval to refresh time counter, to avoid 64-bit
> > + *                    overflow during delta conversion. For example,
> with
> > + *                    cc.mult value 2^28,  there are 36 bits left of cycle
> > + *                    counter. With 1 ns counter resolution, the
> overflow time
> > + *                    is 2^36 ns which is 68.7 s. The refresh_interval
> may be
> > + *                    (60 * HZ) less than 68.7 s.
> > + * @mult_factor:      parameter for cc.mult adjustment calculation, see
> below
> > + * @div_factor:       parameter for cc.mult adjustment calculation, see
> below
> 
> Just use  mult = 2147483648 = 0x80000000 and div = 31.
> 
> Read the real PHC using .gettime() and then mask off the high 32 bits.
> 
> Arrange a kthread to read once every 4 (better 2) seconds to keep the time
> value correct.
> 
> See?

I see. I think you meant using below definitions for cyclecounter,

#define PTP_VCLOCK_CC_MULT             (1 << 31)
#define PTP_VCLOCK_CC_SHIFT            31
#define PTP_VCLOCK_CC_MULT_NUM         (1 << 9)
#define PTP_VCLOCK_CC_MULT_DEM         15625ULL
#define PTP_VCLOCK_CC_REFRESH_INTERVAL (HZ * 2)


> 
> Thanks,
> Richard


^ permalink raw reply	[flat|nested] 23+ messages in thread

* RE: [net-next, v2, 2/7] ptp: support ptp physical/virtual clocks conversion
  2021-05-25 11:33   ` Richard Cochran
@ 2021-05-31 10:39     ` Y.b. Lu
  0 siblings, 0 replies; 23+ messages in thread
From: Y.b. Lu @ 2021-05-31 10:39 UTC (permalink / raw)
  To: Richard Cochran; +Cc: netdev, David S . Miller, Claudiu Manoil, Jakub Kicinski

> -----Original Message-----
> From: Richard Cochran <richardcochran@gmail.com>
> Sent: 2021年5月25日 19:33
> To: Y.b. Lu <yangbo.lu@nxp.com>
> Cc: netdev@vger.kernel.org; David S . Miller <davem@davemloft.net>; Claudiu
> Manoil <claudiu.manoil@nxp.com>; Jakub Kicinski <kuba@kernel.org>
> Subject: Re: [net-next, v2, 2/7] ptp: support ptp physical/virtual clocks
> conversion
> 
> On Fri, May 21, 2021 at 12:36:14PM +0800, Yangbo Lu wrote:
> 
> > diff --git a/Documentation/ABI/testing/sysfs-ptp
> b/Documentation/ABI/testing/sysfs-ptp
> > index 2363ad810ddb..6403e746eeb4 100644
> > --- a/Documentation/ABI/testing/sysfs-ptp
> > +++ b/Documentation/ABI/testing/sysfs-ptp
> > @@ -61,6 +61,19 @@ Description:
> >  		This file contains the number of programmable pins
> >  		offered by the PTP hardware clock.
> >
> > +What:		/sys/class/ptp/ptpN/num_vclocks
> 
> How about "n_vclocks" to be consistent with n_external_timestamps, etc...

Ok. Will keep consistent.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* RE: [net-next, v2, 2/7] ptp: support ptp physical/virtual clocks conversion
  2021-05-25 12:28   ` Richard Cochran
@ 2021-05-31 10:40     ` Y.b. Lu
  0 siblings, 0 replies; 23+ messages in thread
From: Y.b. Lu @ 2021-05-31 10:40 UTC (permalink / raw)
  To: Richard Cochran; +Cc: netdev, David S . Miller, Claudiu Manoil, Jakub Kicinski

> -----Original Message-----
> From: Richard Cochran <richardcochran@gmail.com>
> Sent: 2021年5月25日 20:28
> To: Y.b. Lu <yangbo.lu@nxp.com>
> Cc: netdev@vger.kernel.org; David S . Miller <davem@davemloft.net>; Claudiu
> Manoil <claudiu.manoil@nxp.com>; Jakub Kicinski <kuba@kernel.org>
> Subject: Re: [net-next, v2, 2/7] ptp: support ptp physical/virtual clocks
> conversion
> 
> On Fri, May 21, 2021 at 12:36:14PM +0800, Yangbo Lu wrote:
> 
> > @@ -76,6 +77,11 @@ static int ptp_clock_settime(struct posix_clock
> > *pc, const struct timespec64 *tp  {
> >  	struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock);
> >
> > +	if (ptp_guarantee_pclock(ptp)) {
> 
> Going to need to protect against concurrency WRT ptp->num_vclocks.

Will protect n_vclocks.
Thanks.

> 
> > +		pr_err("ptp: virtual clock in use, guarantee physical clock free
> running\n");
> > +		return -EBUSY;
> > +	}
> > +
> >  	return  ptp->info->settime64(ptp->info, tp);  }
> 
> Thanks,
> Richard

^ permalink raw reply	[flat|nested] 23+ messages in thread

* RE: [net-next, v2, 7/7] enetc: support PTP domain timestamp conversion
  2021-05-25 12:37   ` Richard Cochran
  2021-05-25 12:48     ` Richard Cochran
@ 2021-05-31 10:51     ` Y.b. Lu
  2021-05-31 11:31       ` Y.b. Lu
  1 sibling, 1 reply; 23+ messages in thread
From: Y.b. Lu @ 2021-05-31 10:51 UTC (permalink / raw)
  To: Richard Cochran, Claudiu Manoil; +Cc: netdev, David S . Miller, Jakub Kicinski

Hi Claudiu and Richard,

> -----Original Message-----
> From: Richard Cochran <richardcochran@gmail.com>
> Sent: 2021年5月25日 20:37
> To: Y.b. Lu <yangbo.lu@nxp.com>
> Cc: netdev@vger.kernel.org; David S . Miller <davem@davemloft.net>; Claudiu
> Manoil <claudiu.manoil@nxp.com>; Jakub Kicinski <kuba@kernel.org>
> Subject: Re: [net-next, v2, 7/7] enetc: support PTP domain timestamp
> conversion
> 
> On Fri, May 21, 2021 at 12:36:19PM +0800, Yangbo Lu wrote:
> 
> > @@ -472,13 +473,36 @@ static void enetc_get_tx_tstamp(struct enetc_hw
> *hw, union enetc_tx_bd *txbd,
> >  	*tstamp = (u64)hi << 32 | tstamp_lo;  }
> >
> > -static void enetc_tstamp_tx(struct sk_buff *skb, u64 tstamp)
> > +static int enetc_ptp_parse_domain(struct sk_buff *skb, u8 *domain) {
> > +	unsigned int ptp_class;
> > +	struct ptp_header *hdr;
> > +
> > +	ptp_class = ptp_classify_raw(skb);
> > +	if (ptp_class == PTP_CLASS_NONE)
> > +		return -EINVAL;
> > +
> > +	hdr = ptp_parse_header(skb, ptp_class);
> > +	if (!hdr)
> > +		return -EINVAL;
> > +
> > +	*domain = hdr->domain_number;
> 
> This is really clunky.  We do NOT want to have drivers starting to handle the
> PTP.  That is the job of the user space stack.
> 
> Instead, the conversion from raw time stamp to vclock time stamp should
> happen in the core infrastructure.  That way, no driver hacks will be needed,
> and it will "just work" everywhere.

That's perfect way.

> 
> We need a way to associate a given socket with a particular vclock.
> Perhaps we can extend the SO_TIMESTAMPING API to allow that.

How about adding a flag SOF_TIMESTAMPING_BIND_PHC, and redefining the data passing by setsockopt like,

struct timestamping {
       int flags;
       u8 hwtstamp_phc; /*phc index */
};

The sock could have a new member sk_hwtstamp_phc to record it.

> 
> > +	return 0;
> > +}
> 
> Thanks,
> Richard

^ permalink raw reply	[flat|nested] 23+ messages in thread

* RE: [net-next, v2, 7/7] enetc: support PTP domain timestamp conversion
  2021-05-25 12:48     ` Richard Cochran
@ 2021-05-31 11:26       ` Y.b. Lu
  2021-05-31 13:49         ` Richard Cochran
  0 siblings, 1 reply; 23+ messages in thread
From: Y.b. Lu @ 2021-05-31 11:26 UTC (permalink / raw)
  To: Richard Cochran; +Cc: netdev, David S . Miller, Claudiu Manoil, Jakub Kicinski

> -----Original Message-----
> From: Richard Cochran <richardcochran@gmail.com>
> Sent: 2021年5月25日 20:49
> To: Y.b. Lu <yangbo.lu@nxp.com>
> Cc: netdev@vger.kernel.org; David S . Miller <davem@davemloft.net>; Claudiu
> Manoil <claudiu.manoil@nxp.com>; Jakub Kicinski <kuba@kernel.org>
> Subject: Re: [net-next, v2, 7/7] enetc: support PTP domain timestamp
> conversion
> 
> On Tue, May 25, 2021 at 05:37:11AM -0700, Richard Cochran wrote:
> > Instead, the conversion from raw time stamp to vclock time stamp
> > should happen in the core infrastructure.  That way, no driver hacks
> > will be needed, and it will "just work" everywhere.
> 
> For transmit time stamps, we have skb_complete_tx_timestamp().
> 
> For receive, most drivers use the following cliche:
> 
> 	shwt = skb_hwtstamps(skb);
> 	memset(shwt, 0, sizeof(*shwt));
> 	shwt->hwtstamp = ns_to_ktime(ns);
> 
> So the first step will be to introduce a helper function for that, and then
> re-factor the drivers to use the helper.

So, the timestamp conversion could be in skbuff.c.
That's good to do this. But there are quite a lot of drivers using timestamping.
Should we convert all drivers to use the helper, or let others do this when they need?
Thanks.


> 
> Thanks,
> Richard
> 
> 

^ permalink raw reply	[flat|nested] 23+ messages in thread

* RE: [net-next, v2, 7/7] enetc: support PTP domain timestamp conversion
  2021-05-31 10:51     ` Y.b. Lu
@ 2021-05-31 11:31       ` Y.b. Lu
  2021-05-31 13:54         ` Richard Cochran
  0 siblings, 1 reply; 23+ messages in thread
From: Y.b. Lu @ 2021-05-31 11:31 UTC (permalink / raw)
  To: Richard Cochran; +Cc: netdev, David S . Miller, Jakub Kicinski, Claudiu Manoil

> -----Original Message-----
> From: Y.b. Lu <yangbo.lu@nxp.com>
> Sent: 2021年5月31日 18:52
> To: Richard Cochran <richardcochran@gmail.com>; Claudiu Manoil
> <claudiu.manoil@nxp.com>
> Cc: netdev@vger.kernel.org; David S . Miller <davem@davemloft.net>; Jakub
> Kicinski <kuba@kernel.org>
> Subject: RE: [net-next, v2, 7/7] enetc: support PTP domain timestamp
> conversion
> 
> Hi Claudiu and Richard,
> 
> > -----Original Message-----
> > From: Richard Cochran <richardcochran@gmail.com>
> > Sent: 2021年5月25日 20:37
> > To: Y.b. Lu <yangbo.lu@nxp.com>
> > Cc: netdev@vger.kernel.org; David S . Miller <davem@davemloft.net>;
> > Claudiu Manoil <claudiu.manoil@nxp.com>; Jakub Kicinski
> > <kuba@kernel.org>
> > Subject: Re: [net-next, v2, 7/7] enetc: support PTP domain timestamp
> > conversion
> >
> > On Fri, May 21, 2021 at 12:36:19PM +0800, Yangbo Lu wrote:
> >
> > > @@ -472,13 +473,36 @@ static void enetc_get_tx_tstamp(struct
> > > enetc_hw
> > *hw, union enetc_tx_bd *txbd,
> > >  	*tstamp = (u64)hi << 32 | tstamp_lo;  }
> > >
> > > -static void enetc_tstamp_tx(struct sk_buff *skb, u64 tstamp)
> > > +static int enetc_ptp_parse_domain(struct sk_buff *skb, u8 *domain) {
> > > +	unsigned int ptp_class;
> > > +	struct ptp_header *hdr;
> > > +
> > > +	ptp_class = ptp_classify_raw(skb);
> > > +	if (ptp_class == PTP_CLASS_NONE)
> > > +		return -EINVAL;
> > > +
> > > +	hdr = ptp_parse_header(skb, ptp_class);
> > > +	if (!hdr)
> > > +		return -EINVAL;
> > > +
> > > +	*domain = hdr->domain_number;
> >
> > This is really clunky.  We do NOT want to have drivers starting to
> > handle the PTP.  That is the job of the user space stack.
> >
> > Instead, the conversion from raw time stamp to vclock time stamp
> > should happen in the core infrastructure.  That way, no driver hacks
> > will be needed, and it will "just work" everywhere.
> 
> That's perfect way.
> 
> >
> > We need a way to associate a given socket with a particular vclock.
> > Perhaps we can extend the SO_TIMESTAMPING API to allow that.
> 
> How about adding a flag SOF_TIMESTAMPING_BIND_PHC, and redefining the
> data passing by setsockopt like,
> 
> struct timestamping {
>        int flags;
>        u8 hwtstamp_phc; /*phc index */
> };
> 
> The sock could have a new member sk_hwtstamp_phc to record it.

But one problem is how to check the phc availability for current network interface.
If user can make sure it's using right phc device for current network interface, that's no problem.
Otherwise, timestamp will be token on wrong phc...

> 
> >
> > > +	return 0;
> > > +}
> >
> > Thanks,
> > Richard

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [net-next, v2, 7/7] enetc: support PTP domain timestamp conversion
  2021-05-31 11:26       ` Y.b. Lu
@ 2021-05-31 13:49         ` Richard Cochran
  2021-06-15  9:44           ` Y.b. Lu
  0 siblings, 1 reply; 23+ messages in thread
From: Richard Cochran @ 2021-05-31 13:49 UTC (permalink / raw)
  To: Y.b. Lu; +Cc: netdev, David S . Miller, Claudiu Manoil, Jakub Kicinski

On Mon, May 31, 2021 at 11:26:18AM +0000, Y.b. Lu wrote:
> So, the timestamp conversion could be in skbuff.c.
> That's good to do this. But there are quite a lot of drivers using timestamping.
> Should we convert all drivers to use the helper, or let others do this when they need?

I think we should convert them all.  Yes, it is work, but I will help.
I really like the vclock idea, especially because it will work with
every clock.  Also, adding the helper will be a nice refactoring all
by itself.

Thanks,
Richard

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [net-next, v2, 7/7] enetc: support PTP domain timestamp conversion
  2021-05-31 11:31       ` Y.b. Lu
@ 2021-05-31 13:54         ` Richard Cochran
  0 siblings, 0 replies; 23+ messages in thread
From: Richard Cochran @ 2021-05-31 13:54 UTC (permalink / raw)
  To: Y.b. Lu; +Cc: netdev, David S . Miller, Jakub Kicinski, Claudiu Manoil

> But one problem is how to check the phc availability for current network interface.
> If user can make sure it's using right phc device for current network interface, that's no problem.
> Otherwise, timestamp will be token on wrong phc...

Right, when user space requests the option, the kernel needs to check:
sock -> dev -> physical phc_index -> vclocks.

Today we have ethtool get_ts_info.  We could add get_vclock_info for
example.

Thanks,
Richard




^ permalink raw reply	[flat|nested] 23+ messages in thread

* RE: [net-next, v2, 7/7] enetc: support PTP domain timestamp conversion
  2021-05-31 13:49         ` Richard Cochran
@ 2021-06-15  9:44           ` Y.b. Lu
  0 siblings, 0 replies; 23+ messages in thread
From: Y.b. Lu @ 2021-06-15  9:44 UTC (permalink / raw)
  To: Richard Cochran; +Cc: netdev, David S . Miller, Claudiu Manoil, Jakub Kicinski

Hi Richard,

> -----Original Message-----
> From: Richard Cochran <richardcochran@gmail.com>
> Sent: 2021年5月31日 21:49
> To: Y.b. Lu <yangbo.lu@nxp.com>
> Cc: netdev@vger.kernel.org; David S . Miller <davem@davemloft.net>; Claudiu
> Manoil <claudiu.manoil@nxp.com>; Jakub Kicinski <kuba@kernel.org>
> Subject: Re: [net-next, v2, 7/7] enetc: support PTP domain timestamp
> conversion
> 
> On Mon, May 31, 2021 at 11:26:18AM +0000, Y.b. Lu wrote:
> > So, the timestamp conversion could be in skbuff.c.
> > That's good to do this. But there are quite a lot of drivers using
> timestamping.
> > Should we convert all drivers to use the helper, or let others do this when
> they need?
> 
> I think we should convert them all.  Yes, it is work, but I will help.
> I really like the vclock idea, especially because it will work with every clock.
> Also, adding the helper will be a nice refactoring all by itself.

It seems socket.c __sock_recv_timestamp may be the better place.
HW timestamps are handled in it before going to user space.
I sent out a v3 patch for your reviewing. Maybe we don’t have to convert all drivers to a helper.
Thank you very much.

> 
> Thanks,
> Richard

^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2021-06-15  9:44 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-21  4:36 [net-next, v2, 0/7] ptp: support virtual clocks for multiple Yangbo Lu
2021-05-21  4:36 ` [net-next, v2, 1/7] ptp: add ptp virtual clock driver framework Yangbo Lu
2021-05-23 21:24   ` Richard Cochran
2021-05-31 10:38     ` Y.b. Lu
2021-05-21  4:36 ` [net-next, v2, 2/7] ptp: support ptp physical/virtual clocks conversion Yangbo Lu
2021-05-25 11:33   ` Richard Cochran
2021-05-31 10:39     ` Y.b. Lu
2021-05-25 12:28   ` Richard Cochran
2021-05-31 10:40     ` Y.b. Lu
2021-05-21  4:36 ` [net-next, v2, 3/7] ptp: support domains and timestamp conversion Yangbo Lu
2021-05-21  4:36 ` [net-next, v2, 4/7] ptp_qoriq: export ptp clock reading function for cyclecounter Yangbo Lu
2021-05-21  4:36 ` [net-next, v2, 5/7] enetc_ptp: support ptp virtual clock Yangbo Lu
2021-05-21  4:36 ` [net-next, v2, 6/7] enetc: store ptp device pointer Yangbo Lu
2021-05-21  4:36 ` [net-next, v2, 7/7] enetc: support PTP domain timestamp conversion Yangbo Lu
2021-05-22 20:46   ` Claudiu Manoil
2021-05-25 12:37   ` Richard Cochran
2021-05-25 12:48     ` Richard Cochran
2021-05-31 11:26       ` Y.b. Lu
2021-05-31 13:49         ` Richard Cochran
2021-06-15  9:44           ` Y.b. Lu
2021-05-31 10:51     ` Y.b. Lu
2021-05-31 11:31       ` Y.b. Lu
2021-05-31 13:54         ` Richard Cochran

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).