aboutsummaryrefslogtreecommitdiffstats
diff options
authorChristopher S M Hall <christopher.s.hall@intel.com>2025-03-12 05:38:57 +0000
committerThomas Gleixner <tglx@linutronix.de>2025-03-13 14:11:26 +0100
commit11a247913c061c7c5553b8f98cd8a7b5642fc1ff (patch)
tree7226afd8b5c8bcfeec181cae2dc9655bbf38e315
parentc673d8d9dc567a36eb55b76feafb90a0e0a26338 (diff)
downloaddevel-timers/ptp/tkntp.tar.gz
ptp: Support PTP POSIX clock IDstimers/ptp/tkntp
<INSERT sensible changelog /> Not-Signed-off-by: Christopher S M Hall <christopher.s.hall@intel.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--drivers/ptp/ptp_clock.c54
-rw-r--r--include/uapi/linux/ptp_clock.h7
2 files changed, 56 insertions, 5 deletions
diff --git a/drivers/ptp/ptp_clock.c b/drivers/ptp/ptp_clock.c
index 2451722d5add8b..669ba764f6cfe0 100644
--- a/drivers/ptp/ptp_clock.c
+++ b/drivers/ptp/ptp_clock.c
@@ -15,6 +15,7 @@
#include <linux/syscalls.h>
#include <linux/uaccess.h>
#include <linux/debugfs.h>
+#include <linux/refcount.h>
#include <linux/xarray.h>
#include <uapi/linux/sched/types.h>
@@ -34,6 +35,7 @@ const struct class ptp_class = {
static dev_t ptp_devt;
+static DEFINE_MUTEX(ptp_clock_mutex);
static DEFINE_XARRAY_ALLOC(ptp_clocks_map);
/* time stamp event queue operations */
@@ -205,7 +207,11 @@ static void ptp_clock_release(struct device *dev)
bitmap_free(tsevq->mask);
kfree(tsevq);
debugfs_remove(ptp->debugfs_root);
- xa_erase(&ptp_clocks_map, ptp->index);
+ scoped_guard (mutex, &ptp_clock_mutex) {
+ xa_erase(&ptp_clocks_map, ptp->index);
+ if (ptp_valid_clockid(ptp->ptp_clockid))
+ timekeeping_put_ptp_clock(ptp->ptp_clockid);
+ }
kfree(ptp);
}
@@ -251,8 +257,12 @@ struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info,
goto no_memory;
}
- err = xa_alloc(&ptp_clocks_map, &index, ptp, xa_limit_31b,
- GFP_KERNEL);
+ scoped_guard(mutex, &ptp_clock_mutex) {
+ /* Initialize first so a lookup in ptp_manage_clockid() fails */
+ ptp->ptp_clockid = PTP_CLOCK_NONE;
+ err = xa_alloc(&ptp_clocks_map, &index, ptp, xa_limit_31b,
+ GFP_KERNEL);
+ }
if (err)
goto no_slot;
@@ -260,7 +270,6 @@ struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info,
ptp->info = info;
ptp->devid = MKDEV(major, index);
ptp->index = index;
- ptp->ptp_clockid = PTP_CLOCK_NONE;
INIT_LIST_HEAD(&ptp->tsevqs);
queue = kzalloc(sizeof(*queue), GFP_KERNEL);
if (!queue) {
@@ -516,7 +525,42 @@ EXPORT_SYMBOL(ptp_cancel_worker_sync);
int ptp_manage_clockid(struct ptp_clock *ptp, unsigned int index)
{
- return -ENOTSUPP;
+ struct ptp_clock *peer;
+
+ guard(mutex)(&ptp_clock_mutex);
+
+ if (index == PTP_INDEX_CLOCKID_NONE) {
+ if (!ptp_valid_clockid(ptp->ptp_clockid))
+ return -EINVAL;
+ timekeeping_put_ptp_clock(ptp->ptp_clockid);
+ return 0;
+ }
+
+ if (index == PTP_INDEX_CLOCKID_NEW) {
+ int id = timekeeping_assign_ptp_clock(0);
+
+ if (id < 0)
+ return id;
+ ptp->ptp_clockid = id;
+ return 0;
+ }
+
+ /*
+ * Try to look up the peer clock by @index to share the clock ID
+ * with it.
+ */
+ peer = xa_load(&ptp_clocks_map, index);
+ if (!peer)
+ return -ENODEV;
+
+ if (!ptp_valid_clockid(peer->ptp_clockid))
+ return -EINVAL;
+
+ if (!timekeeping_get_ptp_clock(peer->ptp_clockid))
+ return -EINVAL;
+
+ ptp->ptp_clockid = peer->ptp_clockid;
+ return 0;
}
/* module operations */
diff --git a/include/uapi/linux/ptp_clock.h b/include/uapi/linux/ptp_clock.h
index 18eefa6d93d62f..c889a49692fa77 100644
--- a/include/uapi/linux/ptp_clock.h
+++ b/include/uapi/linux/ptp_clock.h
@@ -25,6 +25,10 @@
#include <linux/ioctl.h>
#include <linux/types.h>
+#ifndef __KERNEL__
+#include <limits.h>
+#endif
+
/*
* Bits of the ptp_extts_request.flags field:
*/
@@ -76,6 +80,9 @@
*/
#define PTP_PEROUT_V1_VALID_FLAGS (0)
+#define PTP_INDEX_CLOCKID_NONE UINT_MAX
+#define PTP_INDEX_CLOCKID_NEW (UINT_MAX - 1)
+
/*
* struct ptp_clock_time - represents a time value
*