Skip to content

Commit 8f5de6f

Browse files
reibax-marcusdavem330
authored andcommitted
ptp: support multiple timestamp event readers
Use linked lists to create one event queue per open file. This enables simultaneous readers for timestamp event queues. Signed-off-by: Xabier Marquiegui <[email protected]> Suggested-by: Richard Cochran <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent d26ab5a commit 8f5de6f

File tree

4 files changed

+55
-29
lines changed

4 files changed

+55
-29
lines changed

drivers/ptp/ptp_chardev.c

Lines changed: 49 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,31 @@ int ptp_set_pinfunc(struct ptp_clock *ptp, unsigned int pin,
103103

104104
int ptp_open(struct posix_clock_context *pccontext, fmode_t fmode)
105105
{
106+
struct ptp_clock *ptp =
107+
container_of(pccontext->clk, struct ptp_clock, clock);
108+
struct timestamp_event_queue *queue;
109+
110+
queue = kzalloc(sizeof(*queue), GFP_KERNEL);
111+
if (!queue)
112+
return -EINVAL;
113+
spin_lock_init(&queue->lock);
114+
list_add_tail(&queue->qlist, &ptp->tsevqs);
115+
pccontext->private_clkdata = queue;
116+
return 0;
117+
}
118+
119+
int ptp_release(struct posix_clock_context *pccontext)
120+
{
121+
struct timestamp_event_queue *queue = pccontext->private_clkdata;
122+
unsigned long flags;
123+
124+
if (queue) {
125+
pccontext->private_clkdata = NULL;
126+
spin_lock_irqsave(&queue->lock, flags);
127+
list_del(&queue->qlist);
128+
spin_unlock_irqrestore(&queue->lock, flags);
129+
kfree(queue);
130+
}
106131
return 0;
107132
}
108133

@@ -441,10 +466,11 @@ __poll_t ptp_poll(struct posix_clock_context *pccontext, struct file *fp,
441466
container_of(pccontext->clk, struct ptp_clock, clock);
442467
struct timestamp_event_queue *queue;
443468

444-
poll_wait(fp, &ptp->tsev_wq, wait);
469+
queue = pccontext->private_clkdata;
470+
if (!queue)
471+
return EPOLLERR;
445472

446-
/* Extract only the first element in the queue list */
447-
queue = list_first_entry(&ptp->tsevqs, struct timestamp_event_queue, qlist);
473+
poll_wait(fp, &ptp->tsev_wq, wait);
448474

449475
return queue_cnt(queue) ? EPOLLIN : 0;
450476
}
@@ -462,36 +488,36 @@ ssize_t ptp_read(struct posix_clock_context *pccontext, uint rdflags,
462488
size_t qcnt, i;
463489
int result;
464490

465-
/* Extract only the first element in the queue list */
466-
queue = list_first_entry(&ptp->tsevqs, struct timestamp_event_queue,
467-
qlist);
491+
queue = pccontext->private_clkdata;
492+
if (!queue) {
493+
result = -EINVAL;
494+
goto exit;
495+
}
468496

469-
if (cnt % sizeof(struct ptp_extts_event) != 0)
470-
return -EINVAL;
497+
if (cnt % sizeof(struct ptp_extts_event) != 0) {
498+
result = -EINVAL;
499+
goto exit;
500+
}
471501

472502
if (cnt > EXTTS_BUFSIZE)
473503
cnt = EXTTS_BUFSIZE;
474504

475505
cnt = cnt / sizeof(struct ptp_extts_event);
476506

477-
if (mutex_lock_interruptible(&ptp->tsevq_mux))
478-
return -ERESTARTSYS;
479-
480507
if (wait_event_interruptible(ptp->tsev_wq,
481508
ptp->defunct || queue_cnt(queue))) {
482-
mutex_unlock(&ptp->tsevq_mux);
483509
return -ERESTARTSYS;
484510
}
485511

486512
if (ptp->defunct) {
487-
mutex_unlock(&ptp->tsevq_mux);
488-
return -ENODEV;
513+
result = -ENODEV;
514+
goto exit;
489515
}
490516

491517
event = kmalloc(EXTTS_BUFSIZE, GFP_KERNEL);
492518
if (!event) {
493-
mutex_unlock(&ptp->tsevq_mux);
494-
return -ENOMEM;
519+
result = -ENOMEM;
520+
goto exit;
495521
}
496522

497523
spin_lock_irqsave(&queue->lock, flags);
@@ -510,12 +536,16 @@ ssize_t ptp_read(struct posix_clock_context *pccontext, uint rdflags,
510536

511537
cnt = cnt * sizeof(struct ptp_extts_event);
512538

513-
mutex_unlock(&ptp->tsevq_mux);
514-
515539
result = cnt;
516-
if (copy_to_user(buf, event, cnt))
540+
if (copy_to_user(buf, event, cnt)) {
517541
result = -EFAULT;
542+
goto free_event;
543+
}
518544

545+
free_event:
519546
kfree(event);
547+
exit:
548+
if (result < 0)
549+
ptp_release(pccontext);
520550
return result;
521551
}

drivers/ptp/ptp_clock.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ static struct posix_clock_operations ptp_clock_ops = {
162162
.clock_settime = ptp_clock_settime,
163163
.ioctl = ptp_ioctl,
164164
.open = ptp_open,
165+
.release = ptp_release,
165166
.poll = ptp_poll,
166167
.read = ptp_read,
167168
};
@@ -174,7 +175,6 @@ static void ptp_clock_release(struct device *dev)
174175

175176
ptp_cleanup_pin_groups(ptp);
176177
kfree(ptp->vclock_index);
177-
mutex_destroy(&ptp->tsevq_mux);
178178
mutex_destroy(&ptp->pincfg_mux);
179179
mutex_destroy(&ptp->n_vclocks_mux);
180180
/* Delete first entry */
@@ -242,9 +242,8 @@ struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info,
242242
queue = kzalloc(sizeof(*queue), GFP_KERNEL);
243243
if (!queue)
244244
goto no_memory_queue;
245-
spin_lock_init(&queue->lock);
246245
list_add_tail(&queue->qlist, &ptp->tsevqs);
247-
mutex_init(&ptp->tsevq_mux);
246+
spin_lock_init(&queue->lock);
248247
mutex_init(&ptp->pincfg_mux);
249248
mutex_init(&ptp->n_vclocks_mux);
250249
init_waitqueue_head(&ptp->tsev_wq);
@@ -345,7 +344,6 @@ struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info,
345344
if (ptp->kworker)
346345
kthread_destroy_worker(ptp->kworker);
347346
kworker_err:
348-
mutex_destroy(&ptp->tsevq_mux);
349347
mutex_destroy(&ptp->pincfg_mux);
350348
mutex_destroy(&ptp->n_vclocks_mux);
351349
list_del(&queue->qlist);

drivers/ptp/ptp_private.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ struct ptp_clock {
3838
struct pps_device *pps_source;
3939
long dialed_frequency; /* remembers the frequency adjustment */
4040
struct list_head tsevqs; /* timestamp fifo list */
41-
struct mutex tsevq_mux; /* one process at a time reading the fifo */
4241
struct mutex pincfg_mux; /* protect concurrent info->pin_config access */
4342
wait_queue_head_t tsev_wq;
4443
int defunct; /* tells readers to go away when clock is being removed */

drivers/ptp/ptp_sysfs.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -81,15 +81,15 @@ static ssize_t extts_fifo_show(struct device *dev,
8181
size_t qcnt;
8282
int cnt = 0;
8383

84+
cnt = list_count_nodes(&ptp->tsevqs);
85+
if (cnt <= 0)
86+
goto out;
87+
8488
/* The sysfs fifo will always draw from the fist queue */
8589
queue = list_first_entry(&ptp->tsevqs, struct timestamp_event_queue,
8690
qlist);
8791

8892
memset(&event, 0, sizeof(event));
89-
90-
if (mutex_lock_interruptible(&ptp->tsevq_mux))
91-
return -ERESTARTSYS;
92-
9393
spin_lock_irqsave(&queue->lock, flags);
9494
qcnt = queue_cnt(queue);
9595
if (qcnt) {
@@ -104,7 +104,6 @@ static ssize_t extts_fifo_show(struct device *dev,
104104
cnt = snprintf(page, PAGE_SIZE, "%u %lld %u\n",
105105
event.index, event.t.sec, event.t.nsec);
106106
out:
107-
mutex_unlock(&ptp->tsevq_mux);
108107
return cnt;
109108
}
110109
static DEVICE_ATTR(fifo, 0444, extts_fifo_show, NULL);

0 commit comments

Comments
 (0)