Thread (28 messages) 28 messages, 6 authors, 2021-06-25

RE: [net-next, v3, 02/10] ptp: support ptp physical/virtual clocks conversion

flat view

From: "Y.b. Lu" <yangbo.lu@nxp.com>
Date: 2021-06-22 10:39:37
Also in: linux-kselftest, lkml, mptcp

Hi Richard,
-----Original Message-----
From: Richard Cochran <richardcochran@gmail.com>
Sent: 2021年6月19日 12:06
To: Y.b. Lu <yangbo.lu@nxp.com>
Cc: netdev@vger.kernel.org; linux-kernel@vger.kernel.org;
linux-kselftest@vger.kernel.org; mptcp@lists.linux.dev; David S . Miller
[off-list ref]; Jakub Kicinski [off-list ref]; Mat Martineau
[off-list ref]; Matthieu Baerts
[off-list ref]; Shuah Khan [off-list ref]; Michal
Kubecek [off-list ref]; Florian Fainelli [off-list ref];
Andrew Lunn [off-list ref]; Rui Sousa [off-list ref]; Sebastien
Laveze [off-list ref]
Subject: Re: [net-next, v3, 02/10] ptp: support ptp physical/virtual clocks
conversion

On Tue, Jun 15, 2021 at 05:45:09PM +0800, Yangbo Lu wrote:
quoted
diff --git a/drivers/ptp/ptp_clock.c b/drivers/ptp/ptp_clock.c index
a780435331c8..78414b3e16dd 100644
--- a/drivers/ptp/ptp_clock.c
+++ b/drivers/ptp/ptp_clock.c
@@ -76,6 +76,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_guaranteed_pclock(ptp)) {
Can we please invent a more descriptive name for this method?
The word "guaranteed" suggests much more.
quoted
+		pr_err("ptp: virtual clock in use, guarantee physical clock free
+running\n");
This is good:           ^^^^^^^^^^^^^^^^^^^^^^^^^
You can drop this part:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

So, please rename ptp_guaranteed_pclock() to ptp_vclock_in_use();
Thank you. Will convert to that.
quoted
+		return -EBUSY;
+	}
+
 	return  ptp->info->settime64(ptp->info, tp);  }
quoted
diff --git a/drivers/ptp/ptp_private.h b/drivers/ptp/ptp_private.h
index 3f388d63904c..6949afc9d733 100644
--- a/drivers/ptp/ptp_private.h
+++ b/drivers/ptp/ptp_private.h
@@ -46,6 +46,9 @@ struct ptp_clock {
 	const struct attribute_group *pin_attr_groups[2];
 	struct kthread_worker *kworker;
 	struct kthread_delayed_work aux_work;
+	u8 n_vclocks;
Why not use "unsigned int" type?  I don't see a need to set an artificial limit.
Please see my explain in another email thread. Thanks.
quoted
+	struct mutex n_vclocks_mux; /* protect concurrent n_vclocks access */
+	bool vclock_flag;
"flag" is vague.  How about "is_virtual_clock" instead?
That's better. Will use it. Thank you.
quoted
 };

 #define info_to_vclock(d) container_of((d), struct ptp_vclock, info)
@@ -75,6 +78,18 @@ static inline int queue_cnt(struct
timestamp_event_queue *q)
quoted
 	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_guaranteed_pclock(struct ptp_clock *ptp) {
+	if (!ptp->vclock_flag && ptp->n_vclocks)
Need to take mutex for n_vclocks to prevent load tearing.
quoted
+		return true;
+
+	return false;
+}
+
 /*
  * see ptp_chardev.c
  */
quoted
@@ -148,6 +149,90 @@ 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;
+
+	vclock = info_to_vclock(info);
+	dev_info(dev->parent, "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 n_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->n_vclocks);
Take mutex.
Will take mutex everywhere to access it.
quoted
+}
+
+static ssize_t n_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;
+
+	if (num > PTP_MAX_VCLOCKS) {
+		dev_err(dev, "max value is %d\n", PTP_MAX_VCLOCKS);
+		goto out;
+	}
+
+	if (mutex_lock_interruptible(&ptp->n_vclocks_mux))
+		return -ERESTARTSYS;
+
+	/* Need to create more vclocks */
+	if (num > ptp->n_vclocks) {
+		for (i = 0; i < num - ptp->n_vclocks; i++) {
+			vclock = ptp_vclock_register(ptp);
+			if (!vclock) {
+				mutex_unlock(&ptp->n_vclocks_mux);
+				goto out;
+			}
+
+			dev_info(dev, "new virtual clock ptp%d\n",
+				 vclock->clock->index);
+		}
+	}
+
+	/* Need to delete vclocks */
+	if (num < ptp->n_vclocks) {
+		i = ptp->n_vclocks - num;
+		device_for_each_child_reverse(dev, &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->n_vclocks = num;
+	mutex_unlock(&ptp->n_vclocks_mux);
+
+	return count;
+out:
+	return err;
+}
+static DEVICE_ATTR_RW(n_vclocks);
+
 static struct attribute *ptp_attrs[] = {
 	&dev_attr_clock_name.attr,
quoted
diff --git a/include/uapi/linux/ptp_clock.h
b/include/uapi/linux/ptp_clock.h index 1d108d597f66..4b933dc1b81b
100644
--- a/include/uapi/linux/ptp_clock.h
+++ b/include/uapi/linux/ptp_clock.h
@@ -69,6 +69,11 @@
  */
 #define PTP_PEROUT_V1_VALID_FLAGS	(0)

+/*
+ * Max number of PTP virtual clocks per PTP physical clock  */
+#define PTP_MAX_VCLOCKS			20
Why limit this to twenty clocks?
Please see my explain in another email thread. Thanks.
Thanks,
Richard
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help