Messages in this thread |  | | Date | Thu, 27 Sep 2018 11:08:31 -0600 | From | Mathieu Poirier <> | Subject | Re: [QUEUED v20180920 08/16] stm class: Add MIPI SyS-T protocol support |
| |
On Thu, Sep 20, 2018 at 03:45:45PM +0300, Alexander Shishkin wrote: > This adds support for MIPI SyS-T protocol as specified in an open > standard [1]. In additional to marking message boundaries, it also
s/additional/addition
> supports tagging messages with the source UUID, to provide better > distinction between trace sources, including payload length and > timestamp in the message's metadata. > > This driver adds attributes to STP policy nodes to control/configure > these metadata features. > > [1] https://www.mipi.org/specifications/sys-t > > Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com> > --- > drivers/hwtracing/stm/Kconfig | 14 ++ > drivers/hwtracing/stm/Makefile | 2 + > drivers/hwtracing/stm/p_sys-t.c | 301 ++++++++++++++++++++++++++++++++ > 3 files changed, 317 insertions(+) > create mode 100644 drivers/hwtracing/stm/p_sys-t.c > > diff --git a/drivers/hwtracing/stm/Kconfig b/drivers/hwtracing/stm/Kconfig > index 262e7891fb97..752dd66742bf 100644 > --- a/drivers/hwtracing/stm/Kconfig > +++ b/drivers/hwtracing/stm/Kconfig > @@ -26,6 +26,20 @@ config STM_PROTO_BASIC > If you want to be able to use the basic protocol or want the > backwards compatibility for your existing setup, say Y. > > +config STM_PROTO_SYS_T > + tristate "MIPI SyS-T STM framing protocol driver" > + default CONFIG_STM > + help > + This is an implementation of MIPI SyS-T protocol to be used > + over the STP transport. In addition to the data payload, it > + also carries additional metadata for time correlation, better > + means of trace source identification, etc. > + > + The receiving side must be able to decode this protocol in > + addition to the MIPI STP, in order to extract the data. > + > + If you don't know what this is, say N. > + > config STM_DUMMY > tristate "Dummy STM driver" > help > diff --git a/drivers/hwtracing/stm/Makefile b/drivers/hwtracing/stm/Makefile > index 1571de66eca4..1692fcd29277 100644 > --- a/drivers/hwtracing/stm/Makefile > +++ b/drivers/hwtracing/stm/Makefile > @@ -4,8 +4,10 @@ obj-$(CONFIG_STM) += stm_core.o > stm_core-y := core.o policy.o > > obj-$(CONFIG_STM_PROTO_BASIC) += stm_p_basic.o > +obj-$(CONFIG_STM_PROTO_SYS_T) += stm_p_sys-t.o > > stm_p_basic-y := p_basic.o > +stm_p_sys-t-y := p_sys-t.o > > obj-$(CONFIG_STM_DUMMY) += dummy_stm.o > > diff --git a/drivers/hwtracing/stm/p_sys-t.c b/drivers/hwtracing/stm/p_sys-t.c > new file mode 100644 > index 000000000000..8f3066ff1b7b > --- /dev/null > +++ b/drivers/hwtracing/stm/p_sys-t.c > @@ -0,0 +1,301 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * MIPI SyS-T framing protocol for STM devices. > + * Copyright (c) 2018, Intel Corporation. > + */ > + > +#include <linux/configfs.h> > +#include <linux/module.h> > +#include <linux/device.h> > +#include <linux/slab.h> > +#include <linux/uuid.h> > +#include <linux/stm.h> > +#include "stm.h" > + > +enum sys_t_message_type { > + MIPI_SYST_TYPE_BUILD = 0, > + MIPI_SYST_TYPE_SHORT32, > + MIPI_SYST_TYPE_STRING, > + MIPI_SYST_TYPE_CATALOG, > + MIPI_SYST_TYPE_RAW = 6, > + MIPI_SYST_TYPE_SHORT64, > + MIPI_SYST_TYPE_CLOCK, > +}; > + > +enum sys_t_message_severity { > + MIPI_SYST_SEVERITY_MAX = 0, > + MIPI_SYST_SEVERITY_FATAL, > + MIPI_SYST_SEVERITY_ERROR, > + MIPI_SYST_SEVERITY_WARNING, > + MIPI_SYST_SEVERITY_INFO, > + MIPI_SYST_SEVERITY_USER1, > + MIPI_SYST_SEVERITY_USER2, > + MIPI_SYST_SEVERITY_DEBUG, > +}; > + > +enum sys_t_message_build_subtype { > + MIPI_SYST_BUILD_ID_COMPACT32 = 0, > + MIPI_SYST_BUILD_ID_COMPACT64, > + MIPI_SYST_BUILD_ID_LONG, > +}; > + > +enum sys_t_message_clock_subtype { > + MIPI_SYST_CLOCK_TRANSPORT_SYNC = 1, > +}; > + > +enum sys_t_message_string_subtype { > + MIPI_SYST_STRING_GENERIC = 1, > + MIPI_SYST_STRING_FUNCTIONENTER, > + MIPI_SYST_STRING_FUNCTIONEXIT, > + MIPI_SYST_STRING_INVALIDPARAM = 5, > + MIPI_SYST_STRING_ASSERT = 7, > + MIPI_SYST_STRING_PRINTF_32 = 11, > + MIPI_SYST_STRING_PRINTF_64 = 12, > +}; > + > +#define MIPI_SYST_TYPE(t) ((u32)(MIPI_SYST_TYPE_ ## t)) > +#define MIPI_SYST_SEVERITY(s) ((u32)(MIPI_SYST_SEVERITY_ ## s) << 4) > +#define MIPI_SYST_OPT_LOC BIT(8) > +#define MIPI_SYST_OPT_LEN BIT(9) > +#define MIPI_SYST_OPT_CHK BIT(10) > +#define MIPI_SYST_OPT_TS BIT(11) > +#define MIPI_SYST_UNIT(u) ((u32)(u) << 12) > +#define MIPI_SYST_ORIGIN(o) ((u32)(o) << 16) > +#define MIPI_SYST_OPT_GUID BIT(23) > +#define MIPI_SYST_SUBTYPE(s) ((u32)(MIPI_SYST_ ## s) << 24) > +#define MIPI_SYST_UNITLARGE(u) (MIPI_SYST_UNIT(u & 0xf) | \ > + MIPI_SYST_ORIGIN(u >> 4)) > +#define MIPI_SYST_TYPES(t, s) (MIPI_SYST_TYPE(t) | \ > + MIPI_SYST_SUBTYPE(t ## _ ## s)) > + > +#define DATA_HEADER (MIPI_SYST_TYPES(STRING, GENERIC) | \ > + MIPI_SYST_SEVERITY(INFO) | \ > + MIPI_SYST_OPT_GUID) > + > +struct sys_t_policy_node { > + uuid_t uuid; > + bool do_len; > + unsigned long ts_interval; > +}; > + > +struct sys_t_output { > + struct sys_t_policy_node node; > + unsigned long ts_jiffies; > +}; > + > +static void sys_t_policy_node_init(void *priv) > +{ > + struct sys_t_policy_node *pn = priv; > + > + generate_random_uuid(pn->uuid.b); > +} > + > +static int sys_t_output_open(void *priv, struct stm_output *output) > +{ > + struct sys_t_policy_node *pn = priv; > + struct sys_t_output *opriv; > + > + opriv = kzalloc(sizeof(*opriv), GFP_ATOMIC); > + if (!opriv) > + return -ENOMEM; > + > + memcpy(&opriv->node, pn, sizeof(opriv->node)); > + output->pdrv_private = opriv; > + > + return 0; > +} > + > +static void sys_t_output_close(struct stm_output *output) > +{ > + kfree(output->pdrv_private); > +} > + > +static ssize_t sys_t_policy_uuid_show(struct config_item *item, > + char *page) > +{ > + struct sys_t_policy_node *pn = to_pdrv_policy_node(item); > + > + return sprintf(page, "%pU\n", &pn->uuid); > +} > + > +static ssize_t > +sys_t_policy_uuid_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); > + int ret; > + > + mutex_lock(mutexp); > + ret = uuid_parse(page, &pn->uuid); > + mutex_unlock(mutexp); > + > + return ret < 0 ? ret : count; > +} > + > +CONFIGFS_ATTR(sys_t_policy_, uuid); > + > +static ssize_t sys_t_policy_do_len_show(struct config_item *item, > + char *page) > +{ > + struct sys_t_policy_node *pn = to_pdrv_policy_node(item); > + > + return sprintf(page, "%d\n", pn->do_len); > +} > + > +static ssize_t > +sys_t_policy_do_len_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); > + int ret; > + > + mutex_lock(mutexp); > + ret = kstrtobool(page, &pn->do_len); > + mutex_unlock(mutexp); > + > + return ret ? ret : count; > +} > + > +CONFIGFS_ATTR(sys_t_policy_, do_len); > + > +static ssize_t sys_t_policy_ts_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->ts_interval)); > +} > + > +static ssize_t > +sys_t_policy_ts_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->ts_interval = msecs_to_jiffies(ms); > + return count; > + } > + > + return ret; > +} > + > +CONFIGFS_ATTR(sys_t_policy_, ts_interval); > + > +static struct configfs_attribute *sys_t_policy_attrs[] = { > + &sys_t_policy_attr_uuid, > + &sys_t_policy_attr_do_len, > + &sys_t_policy_attr_ts_interval, > + NULL, > +}; > + > +static inline bool sys_t_need_ts(struct sys_t_output *op) > +{ > + if (op->node.ts_interval && > + time_after(op->ts_jiffies + op->node.ts_interval, jiffies)) { > + op->ts_jiffies = jiffies; > + > + return true; > + } > + > + return false; > +} > + > +static ssize_t sys_t_write(struct stm_data *data, struct stm_output *output, > + unsigned int chan, const char *buf, size_t count) > +{ > + struct sys_t_output *op = output->pdrv_private; > + unsigned int c = output->channel + chan; > + unsigned int m = output->master; > + u32 header = DATA_HEADER; > + ssize_t sz; > + > + /* We require an existing policy node to proceed */ > + if (!op) > + return -EINVAL; > + > + if (op->node.do_len) > + header |= MIPI_SYST_OPT_LEN; > + if (sys_t_need_ts(op)) > + header |= MIPI_SYST_OPT_TS; > + > + /* > + * STP framing rules for SyS-T frames: > + * * the first packet of the SyS-T frame is timestamped; > + * * the last packet is a FLAG. > + */ > + /* Message layout: HEADER / GUID / [LENGTH /][TIMESTAMP /] DATA */ > + /* HEADER */ > + sz = data->packet(data, m, c, STP_PACKET_DATA, STP_PACKET_TIMESTAMPED, > + 4, (u8 *)&header); > + if (sz <= 0) > + return sz; > + > + /* GUID */ > + sz = stm_data_write(data, m, c, false, op->node.uuid.b, UUID_SIZE); > + if (sz <= 0) > + return sz; > + > + /* [LENGTH] */ > + if (op->node.do_len) { > + u16 length = count; > + > + sz = data->packet(data, m, c, STP_PACKET_DATA, 0, 2, > + (u8 *)&length); > + if (sz <= 0) > + return sz; > + } > + > + /* [TIMESTAMP] */ > + if (header & MIPI_SYST_OPT_TS) { > + u64 ts = ktime_get_real_ns(); > + > + sz = stm_data_write(data, m, c, false, &ts, sizeof(ts)); > + if (sz <= 0) > + return sz; > + } > + > + /* DATA */ > + sz = stm_data_write(data, m, c, false, buf, count); > + if (sz > 0) > + data->packet(data, m, c, STP_PACKET_FLAG, 0, 0, buf); > + > + return sz; > +} > + > +static const struct stm_protocol_driver sys_t_pdrv = { > + .owner = THIS_MODULE, > + .name = "p_sys-t", > + .priv_sz = sizeof(struct sys_t_policy_node), > + .write = sys_t_write, > + .policy_attr = sys_t_policy_attrs, > + .policy_node_init = sys_t_policy_node_init, > + .output_open = sys_t_output_open, > + .output_close = sys_t_output_close, > +}; > + > +static int sys_t_stm_init(void) > +{ > + return stm_register_protocol(&sys_t_pdrv); > +} > + > +static void sys_t_stm_exit(void) > +{ > + stm_unregister_protocol(&sys_t_pdrv); > +} > + > +module_init(sys_t_stm_init); > +module_exit(sys_t_stm_exit); > + > +MODULE_LICENSE("GPL v2"); > +MODULE_DESCRIPTION("MIPI SyS-T STM framing protocol driver"); > +MODULE_AUTHOR("Alexander Shishkin <alexander.shishkin@linux.intel.com>"); > -- > 2.18.0 >
|  |