ptp: track available ptp vclocks information
authorYangbo Lu <yangbo.lu@nxp.com>
Wed, 30 Jun 2021 08:11:54 +0000 (16:11 +0800)
committerDavid S. Miller <davem@davemloft.net>
Thu, 1 Jul 2021 20:08:18 +0000 (13:08 -0700)
Track available ptp vclocks information. Record index values
of available ptp vclocks during registering and unregistering.

This is preparation for supporting ptp vclocks info query
through ethtool.

Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/ptp/ptp_clock.c
drivers/ptp/ptp_private.h
drivers/ptp/ptp_sysfs.c

index 7334f47..9205a93 100644 (file)
@@ -196,6 +196,7 @@ struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info,
 {
        struct ptp_clock *ptp;
        int err = 0, index, major = MAJOR(ptp_devt);
+       size_t size;
 
        if (info->n_alarm > PTP_MAX_ALARMS)
                return ERR_PTR(-EINVAL);
@@ -238,9 +239,17 @@ struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info,
            strcmp(parent->class->name, "ptp") == 0)
                ptp->is_virtual_clock = true;
 
-       if (!ptp->is_virtual_clock)
+       if (!ptp->is_virtual_clock) {
                ptp->max_vclocks = PTP_DEFAULT_MAX_VCLOCKS;
 
+               size = sizeof(int) * ptp->max_vclocks;
+               ptp->vclock_index = kzalloc(size, GFP_KERNEL);
+               if (!ptp->vclock_index) {
+                       err = -ENOMEM;
+                       goto no_mem_for_vclocks;
+               }
+       }
+
        err = ptp_populate_pin_groups(ptp);
        if (err)
                goto no_pin_groups;
@@ -285,6 +294,8 @@ no_clock:
 no_pps:
        ptp_cleanup_pin_groups(ptp);
 no_pin_groups:
+       kfree(ptp->vclock_index);
+no_mem_for_vclocks:
        if (ptp->kworker)
                kthread_destroy_worker(ptp->kworker);
 kworker_err:
@@ -309,6 +320,8 @@ int ptp_clock_unregister(struct ptp_clock *ptp)
        ptp->defunct = 1;
        wake_up_interruptible(&ptp->tsev_wq);
 
+       kfree(ptp->vclock_index);
+
        if (ptp->kworker) {
                kthread_cancel_delayed_work_sync(&ptp->aux_work);
                kthread_destroy_worker(ptp->kworker);
index 87cb559..f75fadd 100644 (file)
@@ -49,6 +49,7 @@ struct ptp_clock {
        struct kthread_delayed_work aux_work;
        unsigned int max_vclocks;
        unsigned int n_vclocks;
+       int *vclock_index;
        struct mutex n_vclocks_mux; /* protect concurrent n_vclocks access */
        bool is_virtual_clock;
 };
index 0b05041..6a36590 100644 (file)
@@ -213,6 +213,9 @@ static ssize_t n_vclocks_store(struct device *dev,
                        if (!vclock)
                                goto out;
 
+                       *(ptp->vclock_index + ptp->n_vclocks + i) =
+                               vclock->clock->index;
+
                        dev_info(dev, "new virtual clock ptp%d\n",
                                 vclock->clock->index);
                }
@@ -223,6 +226,9 @@ static ssize_t n_vclocks_store(struct device *dev,
                i = ptp->n_vclocks - num;
                device_for_each_child_reverse(dev, &i,
                                              unregister_vclock);
+
+               for (i = 1; i <= ptp->n_vclocks - num; i++)
+                       *(ptp->vclock_index + ptp->n_vclocks - i) = -1;
        }
 
        if (num == 0)
@@ -256,6 +262,9 @@ static ssize_t max_vclocks_store(struct device *dev,
                                 const char *buf, size_t count)
 {
        struct ptp_clock *ptp = dev_get_drvdata(dev);
+       unsigned int *vclock_index;
+       int err = -EINVAL;
+       size_t size;
        u32 max;
 
        if (kstrtou32(buf, 0, &max) || max == 0)
@@ -267,16 +276,29 @@ static ssize_t max_vclocks_store(struct device *dev,
        if (mutex_lock_interruptible(&ptp->n_vclocks_mux))
                return -ERESTARTSYS;
 
-       if (max < ptp->n_vclocks) {
-               mutex_unlock(&ptp->n_vclocks_mux);
-               return -EINVAL;
+       if (max < ptp->n_vclocks)
+               goto out;
+
+       size = sizeof(int) * max;
+       vclock_index = kzalloc(size, GFP_KERNEL);
+       if (!vclock_index) {
+               err = -ENOMEM;
+               goto out;
        }
 
+       size = sizeof(int) * ptp->n_vclocks;
+       memcpy(vclock_index, ptp->vclock_index, size);
+
+       kfree(ptp->vclock_index);
+       ptp->vclock_index = vclock_index;
        ptp->max_vclocks = max;
 
        mutex_unlock(&ptp->n_vclocks_mux);
 
        return count;
+out:
+       mutex_unlock(&ptp->n_vclocks_mux);
+       return err;
 }
 static DEVICE_ATTR_RW(max_vclocks);