mirror of https://gitee.com/openkylin/linux.git
stm class: p_sys-t: Add support for CLOCKSYNC packets
This adds support for CLOCKSYNC SyS-T packets, that establish correlation between the transport clock (STP timestamps) and SyS-T timestamps. These packets are sent periodically to allow the decoder to keep both time sources in sync. Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com> Tested-by: Mathieu Poirier <mathieu.poirier@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
d69d5e8311
commit
39f10239df
|
@ -72,15 +72,20 @@ enum sys_t_message_string_subtype {
|
||||||
MIPI_SYST_SEVERITY(INFO) | \
|
MIPI_SYST_SEVERITY(INFO) | \
|
||||||
MIPI_SYST_OPT_GUID)
|
MIPI_SYST_OPT_GUID)
|
||||||
|
|
||||||
|
#define CLOCK_SYNC_HEADER (MIPI_SYST_TYPES(CLOCK, TRANSPORT_SYNC) | \
|
||||||
|
MIPI_SYST_SEVERITY(MAX))
|
||||||
|
|
||||||
struct sys_t_policy_node {
|
struct sys_t_policy_node {
|
||||||
uuid_t uuid;
|
uuid_t uuid;
|
||||||
bool do_len;
|
bool do_len;
|
||||||
unsigned long ts_interval;
|
unsigned long ts_interval;
|
||||||
|
unsigned long clocksync_interval;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sys_t_output {
|
struct sys_t_output {
|
||||||
struct sys_t_policy_node node;
|
struct sys_t_policy_node node;
|
||||||
unsigned long ts_jiffies;
|
unsigned long ts_jiffies;
|
||||||
|
unsigned long clocksync_jiffies;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void sys_t_policy_node_init(void *priv)
|
static void sys_t_policy_node_init(void *priv)
|
||||||
|
@ -191,10 +196,42 @@ sys_t_policy_ts_interval_store(struct config_item *item, const char *page,
|
||||||
|
|
||||||
CONFIGFS_ATTR(sys_t_policy_, ts_interval);
|
CONFIGFS_ATTR(sys_t_policy_, ts_interval);
|
||||||
|
|
||||||
|
static ssize_t sys_t_policy_clocksync_interval_show(struct config_item *item,
|
||||||
|
char *page)
|
||||||
|
{
|
||||||
|
struct sys_t_policy_node *pn = to_pdrv_policy_node(item);
|
||||||
|
|
||||||
|
return sprintf(page, "%u\n", jiffies_to_msecs(pn->clocksync_interval));
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t
|
||||||
|
sys_t_policy_clocksync_interval_store(struct config_item *item,
|
||||||
|
const char *page, size_t count)
|
||||||
|
{
|
||||||
|
struct mutex *mutexp = &item->ci_group->cg_subsys->su_mutex;
|
||||||
|
struct sys_t_policy_node *pn = to_pdrv_policy_node(item);
|
||||||
|
unsigned int ms;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
mutex_lock(mutexp);
|
||||||
|
ret = kstrtouint(page, 10, &ms);
|
||||||
|
mutex_unlock(mutexp);
|
||||||
|
|
||||||
|
if (!ret) {
|
||||||
|
pn->clocksync_interval = msecs_to_jiffies(ms);
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
CONFIGFS_ATTR(sys_t_policy_, clocksync_interval);
|
||||||
|
|
||||||
static struct configfs_attribute *sys_t_policy_attrs[] = {
|
static struct configfs_attribute *sys_t_policy_attrs[] = {
|
||||||
&sys_t_policy_attr_uuid,
|
&sys_t_policy_attr_uuid,
|
||||||
&sys_t_policy_attr_do_len,
|
&sys_t_policy_attr_do_len,
|
||||||
&sys_t_policy_attr_ts_interval,
|
&sys_t_policy_attr_ts_interval,
|
||||||
|
&sys_t_policy_attr_clocksync_interval,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -210,6 +247,43 @@ static inline bool sys_t_need_ts(struct sys_t_output *op)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool sys_t_need_clock_sync(struct sys_t_output *op)
|
||||||
|
{
|
||||||
|
if (op->node.clocksync_interval &&
|
||||||
|
time_after(op->clocksync_jiffies + op->node.clocksync_interval,
|
||||||
|
jiffies)) {
|
||||||
|
op->clocksync_jiffies = jiffies;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t
|
||||||
|
sys_t_clock_sync(struct stm_data *data, unsigned int m, unsigned int c)
|
||||||
|
{
|
||||||
|
u32 header = CLOCK_SYNC_HEADER;
|
||||||
|
const unsigned char nil = 0;
|
||||||
|
u64 payload[2]; /* Clock value and frequency */
|
||||||
|
ssize_t sz;
|
||||||
|
|
||||||
|
sz = data->packet(data, m, c, STP_PACKET_DATA, STP_PACKET_TIMESTAMPED,
|
||||||
|
4, (u8 *)&header);
|
||||||
|
if (sz <= 0)
|
||||||
|
return sz;
|
||||||
|
|
||||||
|
payload[0] = ktime_get_real_ns();
|
||||||
|
payload[1] = NSEC_PER_SEC;
|
||||||
|
sz = stm_data_write(data, m, c, false, &payload, sizeof(payload));
|
||||||
|
if (sz <= 0)
|
||||||
|
return sz;
|
||||||
|
|
||||||
|
data->packet(data, m, c, STP_PACKET_FLAG, 0, 0, &nil);
|
||||||
|
|
||||||
|
return sizeof(header) + sizeof(payload);
|
||||||
|
}
|
||||||
|
|
||||||
static ssize_t sys_t_write(struct stm_data *data, struct stm_output *output,
|
static ssize_t sys_t_write(struct stm_data *data, struct stm_output *output,
|
||||||
unsigned int chan, const char *buf, size_t count)
|
unsigned int chan, const char *buf, size_t count)
|
||||||
{
|
{
|
||||||
|
@ -224,6 +298,12 @@ static ssize_t sys_t_write(struct stm_data *data, struct stm_output *output,
|
||||||
if (!op)
|
if (!op)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (sys_t_need_clock_sync(op)) {
|
||||||
|
sz = sys_t_clock_sync(data, m, c);
|
||||||
|
if (sz <= 0)
|
||||||
|
return sz;
|
||||||
|
}
|
||||||
|
|
||||||
if (op->node.do_len)
|
if (op->node.do_len)
|
||||||
header |= MIPI_SYST_OPT_LEN;
|
header |= MIPI_SYST_OPT_LEN;
|
||||||
if (sys_t_need_ts(op))
|
if (sys_t_need_ts(op))
|
||||||
|
|
Loading…
Reference in New Issue