diff options
author | Christopher S M Hall <christopher.s.hall@intel.com> | 2025-03-12 05:38:57 +0000 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2025-03-13 14:11:26 +0100 |
commit | 11a247913c061c7c5553b8f98cd8a7b5642fc1ff (patch) | |
tree | 7226afd8b5c8bcfeec181cae2dc9655bbf38e315 | |
parent | c673d8d9dc567a36eb55b76feafb90a0e0a26338 (diff) | |
download | devel-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.c | 54 | ||||
-rw-r--r-- | include/uapi/linux/ptp_clock.h | 7 |
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 * |