aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwtracing
diff options
context:
space:
mode:
authorAlexander Shishkin <alexander.shishkin@linux.intel.com>2018-10-05 08:42:59 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2018-10-11 06:12:54 -0400
commit39f10239df751e4ec5190ef851a3e71c052c2539 (patch)
treeb97464d29cfec08375dd697491b034d145224ea3 /drivers/hwtracing
parentd69d5e83110fedd15ff463ed2d5320ab3dec75f1 (diff)
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>
Diffstat (limited to 'drivers/hwtracing')
-rw-r--r--drivers/hwtracing/stm/p_sys-t.c80
1 files changed, 80 insertions, 0 deletions
diff --git a/drivers/hwtracing/stm/p_sys-t.c b/drivers/hwtracing/stm/p_sys-t.c
index ffeb057b777c..b178a5495b67 100644
--- a/drivers/hwtracing/stm/p_sys-t.c
+++ b/drivers/hwtracing/stm/p_sys-t.c
@@ -72,15 +72,20 @@ enum sys_t_message_string_subtype {
72 MIPI_SYST_SEVERITY(INFO) | \ 72 MIPI_SYST_SEVERITY(INFO) | \
73 MIPI_SYST_OPT_GUID) 73 MIPI_SYST_OPT_GUID)
74 74
75#define CLOCK_SYNC_HEADER (MIPI_SYST_TYPES(CLOCK, TRANSPORT_SYNC) | \
76 MIPI_SYST_SEVERITY(MAX))
77
75struct sys_t_policy_node { 78struct sys_t_policy_node {
76 uuid_t uuid; 79 uuid_t uuid;
77 bool do_len; 80 bool do_len;
78 unsigned long ts_interval; 81 unsigned long ts_interval;
82 unsigned long clocksync_interval;
79}; 83};
80 84
81struct sys_t_output { 85struct sys_t_output {
82 struct sys_t_policy_node node; 86 struct sys_t_policy_node node;
83 unsigned long ts_jiffies; 87 unsigned long ts_jiffies;
88 unsigned long clocksync_jiffies;
84}; 89};
85 90
86static void sys_t_policy_node_init(void *priv) 91static 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,
191 196
192CONFIGFS_ATTR(sys_t_policy_, ts_interval); 197CONFIGFS_ATTR(sys_t_policy_, ts_interval);
193 198
199static ssize_t sys_t_policy_clocksync_interval_show(struct config_item *item,
200 char *page)
201{
202 struct sys_t_policy_node *pn = to_pdrv_policy_node(item);
203
204 return sprintf(page, "%u\n", jiffies_to_msecs(pn->clocksync_interval));
205}
206
207static ssize_t
208sys_t_policy_clocksync_interval_store(struct config_item *item,
209 const char *page, size_t count)
210{
211 struct mutex *mutexp = &item->ci_group->cg_subsys->su_mutex;
212 struct sys_t_policy_node *pn = to_pdrv_policy_node(item);
213 unsigned int ms;
214 int ret;
215
216 mutex_lock(mutexp);
217 ret = kstrtouint(page, 10, &ms);
218 mutex_unlock(mutexp);
219
220 if (!ret) {
221 pn->clocksync_interval = msecs_to_jiffies(ms);
222 return count;
223 }
224
225 return ret;
226}
227
228CONFIGFS_ATTR(sys_t_policy_, clocksync_interval);
229
194static struct configfs_attribute *sys_t_policy_attrs[] = { 230static struct configfs_attribute *sys_t_policy_attrs[] = {
195 &sys_t_policy_attr_uuid, 231 &sys_t_policy_attr_uuid,
196 &sys_t_policy_attr_do_len, 232 &sys_t_policy_attr_do_len,
197 &sys_t_policy_attr_ts_interval, 233 &sys_t_policy_attr_ts_interval,
234 &sys_t_policy_attr_clocksync_interval,
198 NULL, 235 NULL,
199}; 236};
200 237
@@ -210,6 +247,43 @@ static inline bool sys_t_need_ts(struct sys_t_output *op)
210 return false; 247 return false;
211} 248}
212 249
250static bool sys_t_need_clock_sync(struct sys_t_output *op)
251{
252 if (op->node.clocksync_interval &&
253 time_after(op->clocksync_jiffies + op->node.clocksync_interval,
254 jiffies)) {
255 op->clocksync_jiffies = jiffies;
256
257 return true;
258 }
259
260 return false;
261}
262
263static ssize_t
264sys_t_clock_sync(struct stm_data *data, unsigned int m, unsigned int c)
265{
266 u32 header = CLOCK_SYNC_HEADER;
267 const unsigned char nil = 0;
268 u64 payload[2]; /* Clock value and frequency */
269 ssize_t sz;
270
271 sz = data->packet(data, m, c, STP_PACKET_DATA, STP_PACKET_TIMESTAMPED,
272 4, (u8 *)&header);
273 if (sz <= 0)
274 return sz;
275
276 payload[0] = ktime_get_real_ns();
277 payload[1] = NSEC_PER_SEC;
278 sz = stm_data_write(data, m, c, false, &payload, sizeof(payload));
279 if (sz <= 0)
280 return sz;
281
282 data->packet(data, m, c, STP_PACKET_FLAG, 0, 0, &nil);
283
284 return sizeof(header) + sizeof(payload);
285}
286
213static ssize_t sys_t_write(struct stm_data *data, struct stm_output *output, 287static ssize_t sys_t_write(struct stm_data *data, struct stm_output *output,
214 unsigned int chan, const char *buf, size_t count) 288 unsigned int chan, const char *buf, size_t count)
215{ 289{
@@ -224,6 +298,12 @@ static ssize_t sys_t_write(struct stm_data *data, struct stm_output *output,
224 if (!op) 298 if (!op)
225 return -EINVAL; 299 return -EINVAL;
226 300
301 if (sys_t_need_clock_sync(op)) {
302 sz = sys_t_clock_sync(data, m, c);
303 if (sz <= 0)
304 return sz;
305 }
306
227 if (op->node.do_len) 307 if (op->node.do_len)
228 header |= MIPI_SYST_OPT_LEN; 308 header |= MIPI_SYST_OPT_LEN;
229 if (sys_t_need_ts(op)) 309 if (sys_t_need_ts(op))