Skip to content

Commit c5a445b

Browse files
reibax-marcusdavem330
authored andcommitted
ptp: support event queue reader channel masks
On systems with multiple timestamp event channels, some readers might want to receive only a subset of those channels. Add the necessary modifications to support timestamp event channel filtering, including two IOCTL operations: - Clear all channels - Enable one channel The mask modification operations will be applied exclusively on the event queue assigned to the file descriptor used on the IOCTL operation, so the typical procedure to have a reader receiving only a subset of the enabled channels would be: - Open device file - ioctl: clear all channels - ioctl: enable one channel - start reading Calling the enable one channel ioctl more than once will result in multiple enabled channels. Signed-off-by: Xabier Marquiegui <[email protected]> Suggested-by: Richard Cochran <[email protected]> Suggested-by: Vinicius Costa Gomes <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 8f5de6f commit c5a445b

File tree

4 files changed

+41
-2
lines changed

4 files changed

+41
-2
lines changed

drivers/ptp/ptp_chardev.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,12 @@ int ptp_open(struct posix_clock_context *pccontext, fmode_t fmode)
110110
queue = kzalloc(sizeof(*queue), GFP_KERNEL);
111111
if (!queue)
112112
return -EINVAL;
113+
queue->mask = bitmap_alloc(PTP_MAX_CHANNELS, GFP_KERNEL);
114+
if (!queue->mask) {
115+
kfree(queue);
116+
return -EINVAL;
117+
}
118+
bitmap_set(queue->mask, 0, PTP_MAX_CHANNELS);
113119
spin_lock_init(&queue->lock);
114120
list_add_tail(&queue->qlist, &ptp->tsevqs);
115121
pccontext->private_clkdata = queue;
@@ -126,6 +132,7 @@ int ptp_release(struct posix_clock_context *pccontext)
126132
spin_lock_irqsave(&queue->lock, flags);
127133
list_del(&queue->qlist);
128134
spin_unlock_irqrestore(&queue->lock, flags);
135+
bitmap_free(queue->mask);
129136
kfree(queue);
130137
}
131138
return 0;
@@ -141,6 +148,7 @@ long ptp_ioctl(struct posix_clock_context *pccontext, unsigned int cmd,
141148
struct system_device_crosststamp xtstamp;
142149
struct ptp_clock_info *ops = ptp->info;
143150
struct ptp_sys_offset *sysoff = NULL;
151+
struct timestamp_event_queue *tsevq;
144152
struct ptp_system_timestamp sts;
145153
struct ptp_clock_request req;
146154
struct ptp_clock_caps caps;
@@ -150,6 +158,8 @@ long ptp_ioctl(struct posix_clock_context *pccontext, unsigned int cmd,
150158
struct timespec64 ts;
151159
int enable, err = 0;
152160

161+
tsevq = pccontext->private_clkdata;
162+
153163
switch (cmd) {
154164

155165
case PTP_CLOCK_GETCAPS:
@@ -448,6 +458,22 @@ long ptp_ioctl(struct posix_clock_context *pccontext, unsigned int cmd,
448458
mutex_unlock(&ptp->pincfg_mux);
449459
break;
450460

461+
case PTP_MASK_CLEAR_ALL:
462+
bitmap_clear(tsevq->mask, 0, PTP_MAX_CHANNELS);
463+
break;
464+
465+
case PTP_MASK_EN_SINGLE:
466+
if (copy_from_user(&i, (void __user *)arg, sizeof(i))) {
467+
err = -EFAULT;
468+
break;
469+
}
470+
if (i >= PTP_MAX_CHANNELS) {
471+
err = -EFAULT;
472+
break;
473+
}
474+
set_bit(i, tsevq->mask);
475+
break;
476+
451477
default:
452478
err = -ENOTTY;
453479
break;

drivers/ptp/ptp_clock.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ static void ptp_clock_release(struct device *dev)
183183
spin_lock_irqsave(&tsevq->lock, flags);
184184
list_del(&tsevq->qlist);
185185
spin_unlock_irqrestore(&tsevq->lock, flags);
186+
bitmap_free(tsevq->mask);
186187
kfree(tsevq);
187188
ida_free(&ptp_clocks_map, ptp->index);
188189
kfree(ptp);
@@ -243,6 +244,10 @@ struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info,
243244
if (!queue)
244245
goto no_memory_queue;
245246
list_add_tail(&queue->qlist, &ptp->tsevqs);
247+
queue->mask = bitmap_alloc(PTP_MAX_CHANNELS, GFP_KERNEL);
248+
if (!queue->mask)
249+
goto no_memory_bitmap;
250+
bitmap_set(queue->mask, 0, PTP_MAX_CHANNELS);
246251
spin_lock_init(&queue->lock);
247252
mutex_init(&ptp->pincfg_mux);
248253
mutex_init(&ptp->n_vclocks_mux);
@@ -346,6 +351,8 @@ struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info,
346351
kworker_err:
347352
mutex_destroy(&ptp->pincfg_mux);
348353
mutex_destroy(&ptp->n_vclocks_mux);
354+
bitmap_free(queue->mask);
355+
no_memory_bitmap:
349356
list_del(&queue->qlist);
350357
kfree(queue);
351358
no_memory_queue:
@@ -400,9 +407,10 @@ void ptp_clock_event(struct ptp_clock *ptp, struct ptp_clock_event *event)
400407
break;
401408

402409
case PTP_CLOCK_EXTTS:
403-
/* Enqueue timestamp on all queues */
410+
/* Enqueue timestamp on selected queues */
404411
list_for_each_entry(tsevq, &ptp->tsevqs, qlist) {
405-
enqueue_external_timestamp(tsevq, event);
412+
if (test_bit((unsigned int)event->index, tsevq->mask))
413+
enqueue_external_timestamp(tsevq, event);
406414
}
407415
wake_up_interruptible(&ptp->tsev_wq);
408416
break;

drivers/ptp/ptp_private.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,20 @@
1616
#include <linux/ptp_clock_kernel.h>
1717
#include <linux/time.h>
1818
#include <linux/list.h>
19+
#include <linux/bitmap.h>
1920

2021
#define PTP_MAX_TIMESTAMPS 128
2122
#define PTP_BUF_TIMESTAMPS 30
2223
#define PTP_DEFAULT_MAX_VCLOCKS 20
24+
#define PTP_MAX_CHANNELS 2048
2325

2426
struct timestamp_event_queue {
2527
struct ptp_extts_event buf[PTP_MAX_TIMESTAMPS];
2628
int head;
2729
int tail;
2830
spinlock_t lock;
2931
struct list_head qlist;
32+
unsigned long *mask;
3033
};
3134

3235
struct ptp_clock {

include/uapi/linux/ptp_clock.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,8 @@ struct ptp_pin_desc {
224224
_IOWR(PTP_CLK_MAGIC, 17, struct ptp_sys_offset_precise)
225225
#define PTP_SYS_OFFSET_EXTENDED2 \
226226
_IOWR(PTP_CLK_MAGIC, 18, struct ptp_sys_offset_extended)
227+
#define PTP_MASK_CLEAR_ALL _IO(PTP_CLK_MAGIC, 19)
228+
#define PTP_MASK_EN_SINGLE _IOW(PTP_CLK_MAGIC, 20, unsigned int)
227229

228230
struct ptp_extts_event {
229231
struct ptp_clock_time t; /* Time event occured. */

0 commit comments

Comments
 (0)