Re: [PATCH v15 33/35] Documentation: Add SCMI System Telemetry documentation
From: Jonathan Cameron
Date: Tue Nov 10 2026 - 18:55:30 EST
On Mon, 9 Nov 2026 09:12:19 +0000
Cristian Marussi <cristian.marussi@xxxxxxx> wrote:
> Document ARM SCMI Telemetry IOCTLs interface.
>
> Co-developed-by: Philip Radford <philip.radford@xxxxxxx>
> Signed-off-by: Philip Radford <philip.radford@xxxxxxx>
Various trivial things inline. For example code it is always
a balance between writing production quality stuff that
has lots of info that doesn't matter for docs, and over simplifying
to the point of ending with random broken code.
Here there is enough error handling to expect it to work but
there are cases where it doesn't. So tidy those up for consistency.
Jonathan
> ---
> Documentation/userspace-api/index.rst | 1 +
> Documentation/userspace-api/stlm.rst | 590 ++++++++++++++++++++++++++
> 2 files changed, 591 insertions(+)
> create mode 100644 Documentation/userspace-api/stlm.rst
>
> diff --git a/Documentation/userspace-api/index.rst b/Documentation/userspace-api/index.rst
> index a68b1bea57a8..22daa7ebf78e 100644
> --- a/Documentation/userspace-api/index.rst
> +++ b/Documentation/userspace-api/index.rst
> @@ -54,6 +54,7 @@ Devices and I/O
> dcdbas
> vduse
> isapnp
> + stlm
>
> Everything else
> ===============
> diff --git a/Documentation/userspace-api/stlm.rst b/Documentation/userspace-api/stlm.rst
> new file mode 100644
> index 000000000000..ea05a10d314f
> --- /dev/null
> +++ b/Documentation/userspace-api/stlm.rst
> @@ -0,0 +1,590 @@
> +.. SPDX-License-Identifier: GPL-2.0
> +
> +=======================================
> +STLM - ARM SCMI Telemetry Userspace API
> +=======================================
> +
> +.. contents::
> +
> +Overview
> +========
> +
> +ARM SCMI is a System and Configuration Management protocol, based on a
Wrap docs to 80 chars.
> +client-server model, that defines a number of messages that allows a
> +client/agent like Linux to discover, configure and make use of services
> +provided by the server/platform firmware.
> +
> +Enumerating DataEvents
> +======================
> +
> +SCMI_TLM_GET_DE_LIST returns the DataEvent descriptors exposed by the
> +Telemetery instance. Users can size the request from
> +SCMI_TLM_GET_ABI_INFO.num_des or by issuing a zero-sized batch query.
> +
> +Example
> +-------
> +
> +.. code-block:: c
> +
> + int main(int argc, char **argv)
> + {
> + struct scmi_tlm_abi_info abi = {};
> + struct scmi_tlm_batch batch = {};
> + struct scmi_tlm_de_info *des;
> + int fd, ret, i;
> +
> + fd = open("/dev/scmi/tlm_0", O_RDONLY | O_CLOEXEC);
> + if (fd < 0)
> + return fd;
> +
> + abi.size = sizeof(abi);
> + ret = ioctl(fd, SCMI_TLM_GET_ABI_INFO, &abi);
> + if (ret) {
> + close(fd);
> + return ret;
> + }
> +
> + if (!abi.num_des) {
> + close(fd);
> + return ret;
returns success. Make that explicit with return 0;
> + }
> +
> + des = calloc(abi.num_des, sizeof(*des));
> + if (!des) {
> + close(fd);
> + return -ENOMEM;
> + }
> +
> + batch.num_items = abi.num_des;
> + batch.item_sz = sizeof(*des);
> + batch.items = (unsigned long)des;
> +
> + ret = ioctl(fd, SCMI_TLM_GET_DE_LIST, &batch);
> + if (ret) {
> + free(des);
> + close(fd);
> + return ret;
> + }
> +
> + for (i = 0; i < batch.num_items; i++) {
> + printf("0x%08x: %.*s size:%u type:%u unit:%u", des[i].id, 16,
> + des[i].name, des[i].data_sz, des[i].type, des[i].unit);
> +
> + if (des[i].flags & SCMI_TLM_DEINFO_GROUP)
> + printf("group:%u", des[i].grp_id);
> +
> + printf("\n");
> + }
> +
> + return 0;
> + }
> +
> +Enumerating Groups
> +==================
> +
> +SCMI_TLM_GET_GRP_LIST returns the groups exposed by the Telemetry Instance.
> +Group descriptors report; the group ID, the number of DEs in the group, and
> +the number of update intervals supported by the group.
> +
> +SCMI_TLM_GET_GRP_DESC can then be used to retrieve the DE IDs of a specific
> +group.
> +
> +Example
> +-------
> +
> +.. code-block:: c
> +
> + int main(int argc, char **argv)
> + {
> + struct scmi_tlm_abi_info abi = {};
> + struct scmi_tlm_batch batch = {};
> + struct scmi_tlm_grp_info *groups;
> + int fd, ret, i;
> +
> + fd = open("/dev/scmi/tlm_0", O_RDONLY | O_CLOEXEC);
> + if (fd < 0)
> + return fd;
> +
> + abi.size = sizeof(abi);
> + ret = ioctl(fd, SCMI_TLM_GET_ABI_INFO, &abi);
> +
> + if (ret){
> + free(groups);
> + close(fd);
> + return ret;
> + }
> +
> + if (!abi.num_groups) {
> + ret = 0;
> + free(groups);
> + close(fd);
> + return ret;
return 0;
rather than setting ret.
> + }
> +
> + groups = calloc(abi.num_groups, sizeof(*groups));
> + if (!groups) {
> + ret = -ENOMEM;
> + free(groups);
> + close(fd);
return an error rather than carrying on.
> + }
> +
> + batch.num_items = abi.num_groups;
> + batch.item_sz = sizeof(*groups);
> + batch.items = (unsigned long)groups;
> +
> + ret = ioctl(fd, SCMI_TLM_GET_GRP_LIST, &batch);
> + if (ret) {
> + free(groups);
> + close(fd);
> + return ret;
> + }
> +
> + for (i = 0; i < batch.num_items; i++) {
> + struct scmi_tlm_grp_desc desc = {};
> + __u32 *de_ids;
> + int j;
> +
> + printf("group:%u des:%u intervals:%u\n", groups[i].grp_id,
> + groups[i].num_des, groups[i].num_intervals);
> +
> + if (!groups[i].num_des)
> + continue;
> +
> + de_ids = calloc(groups[i].num_des, sizeof(*de_ids));
> + if (!de_ids) {
> + ret = -ENOMEM;
> + free(groups);
> + close(fd);
> + return de_ids;
return -ENOMEM;
I'm curious if sashiko noticed your docs and spotted this stuff?
I guess it might be conservative as often such examples in docs
skip error handling.
> + }
> +
> + desc.grp_id = groups[i].grp_id;
> + desc.num_des = groups[i].num_des;
> + desc.composing_des = (unsigned long)de_ids;
> +
> + ret = ioctl(fd, SCMI_TLM_GET_GRP_DESC, &desc);
> + if (ret) {
> + free(de_ids);
> + free(groups);
> + close(fd);
> + return ret;
> + }
> +
> + printf("DataEvents:");
> + for (j = 0; j < desc.num_des; j++)
> + printf(" 0x%08x", de_ids[j]);
> + printf("\n");
> +
> + free(de_ids);
> + }
> +
> + free(groups);
> + close(fd);
> + return 0;
> + }
...