2019-05-20 15:19:02 +08:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
2011-04-22 18:03:08 +08:00
|
|
|
/*
|
|
|
|
* PTP 1588 clock support - private declarations for the core module.
|
|
|
|
*
|
|
|
|
* Copyright (C) 2010 OMICRON electronics GmbH
|
|
|
|
*/
|
|
|
|
#ifndef _PTP_PRIVATE_H_
|
|
|
|
#define _PTP_PRIVATE_H_
|
|
|
|
|
|
|
|
#include <linux/cdev.h>
|
|
|
|
#include <linux/device.h>
|
ptp: introduce ptp auxiliary worker
Many PTP drivers required to perform some asynchronous or periodic work,
like periodically handling PHC counter overflow or handle delayed timestamp
for RX/TX network packets. In most of the cases, such work is implemented
using workqueues. Unfortunately, Kernel workqueues might introduce
significant delay in work scheduling under high system load and on -RT,
which could cause misbehavior of PTP drivers due to internal counter
overflow, for example, and there is no way to tune its execution policy and
priority manuallly.
Hence, The kthread_worker can be used insted of workqueues, as it create
separte named kthread for each worker and its its execution policy and
priority can be configured using chrt tool.
This prblem was reported for two drivers TI CPSW CPTS and dp83640, so
instead of modifying each of these driver it was proposed to add PTP
auxiliary worker to the PHC subsystem.
The patch adds PTP auxiliary worker in PHC subsystem using kthread_worker
and kthread_delayed_work and introduces two new PHC subsystem APIs:
- long (*do_aux_work)(struct ptp_clock_info *ptp) callback in
ptp_clock_info structure, which driver should assign if it require to
perform asynchronous or periodic work. Driver should return the delay of
the PTP next auxiliary work scheduling time (>=0) or negative value in case
further scheduling is not required.
- int ptp_schedule_worker(struct ptp_clock *ptp, unsigned long delay) which
allows schedule PTP auxiliary work.
The name of kthread_worker thread corresponds PTP PHC device name "ptp%d".
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-07-29 06:30:02 +08:00
|
|
|
#include <linux/kthread.h>
|
2011-04-22 18:03:08 +08:00
|
|
|
#include <linux/mutex.h>
|
|
|
|
#include <linux/posix-clock.h>
|
|
|
|
#include <linux/ptp_clock.h>
|
|
|
|
#include <linux/ptp_clock_kernel.h>
|
|
|
|
#include <linux/time.h>
|
|
|
|
|
|
|
|
#define PTP_MAX_TIMESTAMPS 128
|
|
|
|
#define PTP_BUF_TIMESTAMPS 30
|
|
|
|
|
|
|
|
struct timestamp_event_queue {
|
|
|
|
struct ptp_extts_event buf[PTP_MAX_TIMESTAMPS];
|
|
|
|
int head;
|
|
|
|
int tail;
|
|
|
|
spinlock_t lock;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ptp_clock {
|
|
|
|
struct posix_clock clock;
|
|
|
|
struct device *dev;
|
|
|
|
struct ptp_clock_info *info;
|
|
|
|
dev_t devid;
|
|
|
|
int index; /* index into clocks.map */
|
|
|
|
struct pps_device *pps_source;
|
2012-09-22 15:02:01 +08:00
|
|
|
long dialed_frequency; /* remembers the frequency adjustment */
|
2011-04-22 18:03:08 +08:00
|
|
|
struct timestamp_event_queue tsevq; /* simple fifo for time stamps */
|
|
|
|
struct mutex tsevq_mux; /* one process at a time reading the fifo */
|
2014-03-21 05:21:52 +08:00
|
|
|
struct mutex pincfg_mux; /* protect concurrent info->pin_config access */
|
2011-04-22 18:03:08 +08:00
|
|
|
wait_queue_head_t tsev_wq;
|
|
|
|
int defunct; /* tells readers to go away when clock is being removed */
|
2014-03-21 05:21:54 +08:00
|
|
|
struct device_attribute *pin_dev_attr;
|
|
|
|
struct attribute **pin_attr;
|
|
|
|
struct attribute_group pin_attr_group;
|
2017-02-15 02:23:34 +08:00
|
|
|
/* 1st entry is a pointer to the real group, 2nd is NULL terminator */
|
|
|
|
const struct attribute_group *pin_attr_groups[2];
|
ptp: introduce ptp auxiliary worker
Many PTP drivers required to perform some asynchronous or periodic work,
like periodically handling PHC counter overflow or handle delayed timestamp
for RX/TX network packets. In most of the cases, such work is implemented
using workqueues. Unfortunately, Kernel workqueues might introduce
significant delay in work scheduling under high system load and on -RT,
which could cause misbehavior of PTP drivers due to internal counter
overflow, for example, and there is no way to tune its execution policy and
priority manuallly.
Hence, The kthread_worker can be used insted of workqueues, as it create
separte named kthread for each worker and its its execution policy and
priority can be configured using chrt tool.
This prblem was reported for two drivers TI CPSW CPTS and dp83640, so
instead of modifying each of these driver it was proposed to add PTP
auxiliary worker to the PHC subsystem.
The patch adds PTP auxiliary worker in PHC subsystem using kthread_worker
and kthread_delayed_work and introduces two new PHC subsystem APIs:
- long (*do_aux_work)(struct ptp_clock_info *ptp) callback in
ptp_clock_info structure, which driver should assign if it require to
perform asynchronous or periodic work. Driver should return the delay of
the PTP next auxiliary work scheduling time (>=0) or negative value in case
further scheduling is not required.
- int ptp_schedule_worker(struct ptp_clock *ptp, unsigned long delay) which
allows schedule PTP auxiliary work.
The name of kthread_worker thread corresponds PTP PHC device name "ptp%d".
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-07-29 06:30:02 +08:00
|
|
|
struct kthread_worker *kworker;
|
|
|
|
struct kthread_delayed_work aux_work;
|
2011-04-22 18:03:08 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The function queue_cnt() is safe for readers to call without
|
|
|
|
* holding q->lock. Readers use this function to verify that the queue
|
|
|
|
* is nonempty before proceeding with a dequeue operation. The fact
|
|
|
|
* that a writer might concurrently increment the tail does not
|
|
|
|
* matter, since the queue remains nonempty nonetheless.
|
|
|
|
*/
|
|
|
|
static inline int queue_cnt(struct timestamp_event_queue *q)
|
|
|
|
{
|
|
|
|
int cnt = q->tail - q->head;
|
|
|
|
return cnt < 0 ? PTP_MAX_TIMESTAMPS + cnt : cnt;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* see ptp_chardev.c
|
|
|
|
*/
|
|
|
|
|
2014-03-21 05:21:52 +08:00
|
|
|
/* caller must hold pincfg_mux */
|
|
|
|
int ptp_set_pinfunc(struct ptp_clock *ptp, unsigned int pin,
|
|
|
|
enum ptp_pin_function func, unsigned int chan);
|
|
|
|
|
2011-04-22 18:03:08 +08:00
|
|
|
long ptp_ioctl(struct posix_clock *pc,
|
|
|
|
unsigned int cmd, unsigned long arg);
|
|
|
|
|
|
|
|
int ptp_open(struct posix_clock *pc, fmode_t fmode);
|
|
|
|
|
|
|
|
ssize_t ptp_read(struct posix_clock *pc,
|
|
|
|
uint flags, char __user *buf, size_t cnt);
|
|
|
|
|
2017-07-03 18:39:46 +08:00
|
|
|
__poll_t ptp_poll(struct posix_clock *pc,
|
2011-04-22 18:03:08 +08:00
|
|
|
struct file *fp, poll_table *wait);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* see ptp_sysfs.c
|
|
|
|
*/
|
|
|
|
|
2013-07-25 06:05:20 +08:00
|
|
|
extern const struct attribute_group *ptp_groups[];
|
2011-04-22 18:03:08 +08:00
|
|
|
|
2017-02-15 02:23:34 +08:00
|
|
|
int ptp_populate_pin_groups(struct ptp_clock *ptp);
|
|
|
|
void ptp_cleanup_pin_groups(struct ptp_clock *ptp);
|
2011-04-22 18:03:08 +08:00
|
|
|
|
|
|
|
#endif
|