mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 14:11:52 +00:00
ptp: Replace timestamp event queue with linked list
Introduce linked lists to access the timestamp event queue. Signed-off-by: Xabier Marquiegui <reibax@gmail.com> Suggested-by: Richard Cochran <richardcochran@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
60c6946675
commit
d26ab5a35a
@ -439,10 +439,14 @@ __poll_t ptp_poll(struct posix_clock_context *pccontext, struct file *fp,
|
||||
{
|
||||
struct ptp_clock *ptp =
|
||||
container_of(pccontext->clk, struct ptp_clock, clock);
|
||||
struct timestamp_event_queue *queue;
|
||||
|
||||
poll_wait(fp, &ptp->tsev_wq, wait);
|
||||
|
||||
return queue_cnt(&ptp->tsevq) ? EPOLLIN : 0;
|
||||
/* Extract only the first element in the queue list */
|
||||
queue = list_first_entry(&ptp->tsevqs, struct timestamp_event_queue, qlist);
|
||||
|
||||
return queue_cnt(queue) ? EPOLLIN : 0;
|
||||
}
|
||||
|
||||
#define EXTTS_BUFSIZE (PTP_BUF_TIMESTAMPS * sizeof(struct ptp_extts_event))
|
||||
@ -452,12 +456,16 @@ ssize_t ptp_read(struct posix_clock_context *pccontext, uint rdflags,
|
||||
{
|
||||
struct ptp_clock *ptp =
|
||||
container_of(pccontext->clk, struct ptp_clock, clock);
|
||||
struct timestamp_event_queue *queue = &ptp->tsevq;
|
||||
struct timestamp_event_queue *queue;
|
||||
struct ptp_extts_event *event;
|
||||
unsigned long flags;
|
||||
size_t qcnt, i;
|
||||
int result;
|
||||
|
||||
/* Extract only the first element in the queue list */
|
||||
queue = list_first_entry(&ptp->tsevqs, struct timestamp_event_queue,
|
||||
qlist);
|
||||
|
||||
if (cnt % sizeof(struct ptp_extts_event) != 0)
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -169,12 +169,21 @@ static struct posix_clock_operations ptp_clock_ops = {
|
||||
static void ptp_clock_release(struct device *dev)
|
||||
{
|
||||
struct ptp_clock *ptp = container_of(dev, struct ptp_clock, dev);
|
||||
struct timestamp_event_queue *tsevq;
|
||||
unsigned long flags;
|
||||
|
||||
ptp_cleanup_pin_groups(ptp);
|
||||
kfree(ptp->vclock_index);
|
||||
mutex_destroy(&ptp->tsevq_mux);
|
||||
mutex_destroy(&ptp->pincfg_mux);
|
||||
mutex_destroy(&ptp->n_vclocks_mux);
|
||||
/* Delete first entry */
|
||||
tsevq = list_first_entry(&ptp->tsevqs, struct timestamp_event_queue,
|
||||
qlist);
|
||||
spin_lock_irqsave(&tsevq->lock, flags);
|
||||
list_del(&tsevq->qlist);
|
||||
spin_unlock_irqrestore(&tsevq->lock, flags);
|
||||
kfree(tsevq);
|
||||
ida_free(&ptp_clocks_map, ptp->index);
|
||||
kfree(ptp);
|
||||
}
|
||||
@ -206,6 +215,7 @@ struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info,
|
||||
struct device *parent)
|
||||
{
|
||||
struct ptp_clock *ptp;
|
||||
struct timestamp_event_queue *queue = NULL;
|
||||
int err = 0, index, major = MAJOR(ptp_devt);
|
||||
size_t size;
|
||||
|
||||
@ -228,7 +238,12 @@ struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info,
|
||||
ptp->info = info;
|
||||
ptp->devid = MKDEV(major, index);
|
||||
ptp->index = index;
|
||||
spin_lock_init(&ptp->tsevq.lock);
|
||||
INIT_LIST_HEAD(&ptp->tsevqs);
|
||||
queue = kzalloc(sizeof(*queue), GFP_KERNEL);
|
||||
if (!queue)
|
||||
goto no_memory_queue;
|
||||
spin_lock_init(&queue->lock);
|
||||
list_add_tail(&queue->qlist, &ptp->tsevqs);
|
||||
mutex_init(&ptp->tsevq_mux);
|
||||
mutex_init(&ptp->pincfg_mux);
|
||||
mutex_init(&ptp->n_vclocks_mux);
|
||||
@ -333,6 +348,9 @@ kworker_err:
|
||||
mutex_destroy(&ptp->tsevq_mux);
|
||||
mutex_destroy(&ptp->pincfg_mux);
|
||||
mutex_destroy(&ptp->n_vclocks_mux);
|
||||
list_del(&queue->qlist);
|
||||
kfree(queue);
|
||||
no_memory_queue:
|
||||
ida_free(&ptp_clocks_map, index);
|
||||
no_slot:
|
||||
kfree(ptp);
|
||||
@ -375,6 +393,7 @@ EXPORT_SYMBOL(ptp_clock_unregister);
|
||||
|
||||
void ptp_clock_event(struct ptp_clock *ptp, struct ptp_clock_event *event)
|
||||
{
|
||||
struct timestamp_event_queue *tsevq;
|
||||
struct pps_event_time evt;
|
||||
|
||||
switch (event->type) {
|
||||
@ -383,7 +402,10 @@ void ptp_clock_event(struct ptp_clock *ptp, struct ptp_clock_event *event)
|
||||
break;
|
||||
|
||||
case PTP_CLOCK_EXTTS:
|
||||
enqueue_external_timestamp(&ptp->tsevq, event);
|
||||
/* Enqueue timestamp on all queues */
|
||||
list_for_each_entry(tsevq, &ptp->tsevqs, qlist) {
|
||||
enqueue_external_timestamp(tsevq, event);
|
||||
}
|
||||
wake_up_interruptible(&ptp->tsev_wq);
|
||||
break;
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <linux/ptp_clock.h>
|
||||
#include <linux/ptp_clock_kernel.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/list.h>
|
||||
|
||||
#define PTP_MAX_TIMESTAMPS 128
|
||||
#define PTP_BUF_TIMESTAMPS 30
|
||||
@ -25,6 +26,7 @@ struct timestamp_event_queue {
|
||||
int head;
|
||||
int tail;
|
||||
spinlock_t lock;
|
||||
struct list_head qlist;
|
||||
};
|
||||
|
||||
struct ptp_clock {
|
||||
@ -35,7 +37,7 @@ struct ptp_clock {
|
||||
int index; /* index into clocks.map */
|
||||
struct pps_device *pps_source;
|
||||
long dialed_frequency; /* remembers the frequency adjustment */
|
||||
struct timestamp_event_queue tsevq; /* simple fifo for time stamps */
|
||||
struct list_head tsevqs; /* timestamp fifo list */
|
||||
struct mutex tsevq_mux; /* one process at a time reading the fifo */
|
||||
struct mutex pincfg_mux; /* protect concurrent info->pin_config access */
|
||||
wait_queue_head_t tsev_wq;
|
||||
|
@ -75,12 +75,16 @@ static ssize_t extts_fifo_show(struct device *dev,
|
||||
struct device_attribute *attr, char *page)
|
||||
{
|
||||
struct ptp_clock *ptp = dev_get_drvdata(dev);
|
||||
struct timestamp_event_queue *queue = &ptp->tsevq;
|
||||
struct timestamp_event_queue *queue;
|
||||
struct ptp_extts_event event;
|
||||
unsigned long flags;
|
||||
size_t qcnt;
|
||||
int cnt = 0;
|
||||
|
||||
/* The sysfs fifo will always draw from the fist queue */
|
||||
queue = list_first_entry(&ptp->tsevqs, struct timestamp_event_queue,
|
||||
qlist);
|
||||
|
||||
memset(&event, 0, sizeof(event));
|
||||
|
||||
if (mutex_lock_interruptible(&ptp->tsevq_mux))
|
||||
|
Loading…
Reference in New Issue
Block a user