On Tue, Jun 15, 2021 at 05:45:09PM +0800, Yangbo Lu wrote:
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.
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();
return -EBUSY;
- }
- return ptp->info->settime64(ptp->info, tp);
}
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.
- struct mutex n_vclocks_mux; /* protect concurrent n_vclocks access */
- bool vclock_flag;
"flag" is vague. How about "is_virtual_clock" instead?
}; #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) 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.
return true;
- return false;
+}
/*
- see ptp_chardev.c
*/
@@ -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.
+}
+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,
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?
Thanks, Richard