diff options
author | Alexander Shishkin <alexander.shishkin@linux.intel.com> | 2018-10-05 08:42:59 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2018-10-11 06:12:54 -0400 |
commit | 39f10239df751e4ec5190ef851a3e71c052c2539 (patch) | |
tree | b97464d29cfec08375dd697491b034d145224ea3 /drivers/hwtracing | |
parent | d69d5e83110fedd15ff463ed2d5320ab3dec75f1 (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.c | 80 |
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 | |||
75 | struct sys_t_policy_node { | 78 | struct 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 | ||
81 | struct sys_t_output { | 85 | struct 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 | ||
86 | static void sys_t_policy_node_init(void *priv) | 91 | 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, | |||
191 | 196 | ||
192 | CONFIGFS_ATTR(sys_t_policy_, ts_interval); | 197 | CONFIGFS_ATTR(sys_t_policy_, ts_interval); |
193 | 198 | ||
199 | static 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 | |||
207 | static ssize_t | ||
208 | sys_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 | |||
228 | CONFIGFS_ATTR(sys_t_policy_, clocksync_interval); | ||
229 | |||
194 | static struct configfs_attribute *sys_t_policy_attrs[] = { | 230 | static 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 | ||
250 | static 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 | |||
263 | static ssize_t | ||
264 | sys_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 | |||
213 | static ssize_t sys_t_write(struct stm_data *data, struct stm_output *output, | 287 | static 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)) |