[PATCH v12 25/25] [RFC] kselftest/arm64: Add SCMI Telemetry UAPI compliance testcases

Cristian Marussi cristian.marussi at arm.com
Sun Sep 20 02:19:28 PDT 2026


From: Philip Radford <philip.radford at arm.com>

Add support to test SCMI Telemetry UAPI compliance testcases.

Co-developed-by: Cristian Marussi <cristian.marussi at arm.com>
Signed-off-by: Philip Radford <philip.radford at arm.com>
Signed-off-by: Cristian Marussi <cristian.marussi at arm.com>
---
 tools/testing/selftests/arm64/Makefile        |    2 +-
 tools/testing/selftests/arm64/scmi/Makefile   |   12 +
 tools/testing/selftests/arm64/scmi/config     |    2 +
 .../arm64/scmi/test_scmi_telemetry_uapi.c     | 1040 +++++++++++++++++
 4 files changed, 1055 insertions(+), 1 deletion(-)
 create mode 100644 tools/testing/selftests/arm64/scmi/Makefile
 create mode 100644 tools/testing/selftests/arm64/scmi/config
 create mode 100644 tools/testing/selftests/arm64/scmi/test_scmi_telemetry_uapi.c

diff --git a/tools/testing/selftests/arm64/Makefile b/tools/testing/selftests/arm64/Makefile
index e456f3b62fa1..f3beae2ae164 100644
--- a/tools/testing/selftests/arm64/Makefile
+++ b/tools/testing/selftests/arm64/Makefile
@@ -4,7 +4,7 @@
 ARCH ?= $(shell uname -m 2>/dev/null || echo not)
 
 ifneq (,$(filter $(ARCH),aarch64 arm64))
-ARM64_SUBTARGETS ?= tags signal pauth fp mte bti abi gcs
+ARM64_SUBTARGETS ?= tags signal pauth fp mte bti abi gcs scmi
 else
 ARM64_SUBTARGETS :=
 endif
diff --git a/tools/testing/selftests/arm64/scmi/Makefile b/tools/testing/selftests/arm64/scmi/Makefile
new file mode 100644
index 000000000000..3d9576c7a3e8
--- /dev/null
+++ b/tools/testing/selftests/arm64/scmi/Makefile
@@ -0,0 +1,12 @@
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (C) 2026 ARM Limited
+
+# Additional include paths needed by kselftest.h and local headers
+CFLAGS += -std=gnu99 -I.
+LDFLAGS += -static
+
+# Generated binaries to be installed by top KSFT script
+TEST_GEN_PROGS := test_scmi_telemetry_uapi
+
+# Include KSFT lib.mk.
+include ../../lib.mk
diff --git a/tools/testing/selftests/arm64/scmi/config b/tools/testing/selftests/arm64/scmi/config
new file mode 100644
index 000000000000..63cd7e67ab55
--- /dev/null
+++ b/tools/testing/selftests/arm64/scmi/config
@@ -0,0 +1,2 @@
+CONFIG_ARM_SCMI_SYSTEM_TELEMETRY=y
+
diff --git a/tools/testing/selftests/arm64/scmi/test_scmi_telemetry_uapi.c b/tools/testing/selftests/arm64/scmi/test_scmi_telemetry_uapi.c
new file mode 100644
index 000000000000..87f4d0c1e98f
--- /dev/null
+++ b/tools/testing/selftests/arm64/scmi/test_scmi_telemetry_uapi.c
@@ -0,0 +1,1040 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2026 ARM Limited
+
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ioctl.h>
+
+#include "kselftest_harness.h"
+
+#include <../../../../../include/uapi/linux/scmi.h>
+
+#define TLM_0	"tlm_0"
+
+struct scmi_ksft_session {
+	bool initialized;
+	struct scmi_tlm_abi_info info;
+	struct scmi_tlm_config *original_cfg;
+	struct scmi_tlm_intervals available;
+	struct scmi_tlm_update_interval *intervals;
+	struct scmi_tlm_de_info *de_list;
+	unsigned int num_des;
+
+} ksft_session;
+
+static int scmi_tlm_batch_init(struct scmi_tlm_batch *batch,
+			       unsigned int num_items,
+			       size_t item_sz,
+			       bool with_states)
+{
+	void *items = NULL;
+	int *states = NULL;
+
+	bzero(batch, sizeof(*batch));
+
+	if (num_items) {
+		items = malloc(item_sz * num_items);
+		if (!items)
+			return -1;
+
+		bzero(items, item_sz * num_items);
+	}
+
+	if (with_states && num_items) {
+		states = malloc(sizeof(*states) * num_items);
+		if (!states) {
+			free(items);
+			return -1;
+		}
+
+		bzero(states, sizeof(*states) * num_items);
+	}
+
+	batch->num_items = num_items;
+	batch->item_sz = item_sz;
+	batch->items = (__u64)items;
+	batch->states = (__u64)states;
+
+	return 0;
+}
+
+static void scmi_tlm_batch_free(struct scmi_tlm_batch *batch)
+{
+	free((void *)batch->items);
+	free((void *)batch->states);
+	bzero(batch, sizeof(*batch));
+}
+
+static __attribute__((constructor)) void scmi_tlm_initialize(void)
+{
+	struct scmi_tlm_batch batch = {};
+	int fd, ret;
+
+	fd = open("/dev/scmi/" TLM_0, O_RDWR);
+	if (fd < 0) {
+		fprintf(stderr, "INIT: device not available\n");
+		return;
+	}
+
+	ksft_session.info.size = sizeof(struct scmi_tlm_abi_info);
+	ret = ioctl(fd, SCMI_TLM_GET_ABI_INFO, &ksft_session.info);
+	if (ret) {
+		fprintf(stderr, "INIT: failed to get ABI info\n");
+		goto out;
+	}
+
+	if (ksft_session.info.abi_version != SCMI_TLM_ABI_VERSION_V1) {
+		fprintf(stderr, "INIT: ABI Version %u NOT supported",
+			ksft_session.info.abi_version);
+		goto out;
+	}
+
+	if (ksft_session.info.num_des) {
+		ret = scmi_tlm_batch_init(&batch, ksft_session.info.num_des,
+					  sizeof(*ksft_session.de_list), false);
+		if (!ret) {
+			ret = ioctl(fd, SCMI_TLM_GET_DE_LIST, &batch);
+			if (!ret) {
+				ksft_session.de_list = (struct scmi_tlm_de_info *)batch.items;
+				ksft_session.num_des = batch.num_items;
+			} else {
+				scmi_tlm_batch_free(&batch);
+			}
+		}
+	}
+
+	if (ksft_session.info.num_intervals) {
+		int num_intervals = ksft_session.info.num_intervals;
+		struct scmi_tlm_update_interval *intervals;
+
+		intervals = malloc(sizeof(*intervals) * num_intervals);
+		if (!intervals) {
+			fprintf(stderr, "INIT: Failed to allocate intervals");
+			goto out;
+		}
+
+		bzero(intervals, sizeof(*intervals) * num_intervals);
+
+		ksft_session.intervals = intervals;
+		ksft_session.available.intervals = (__u64)intervals;
+		ksft_session.available.num_intervals = num_intervals;
+
+		ret = ioctl(fd, SCMI_TLM_GET_INTRVS, &ksft_session.available);
+		if (ret) {
+			fprintf(stderr, "INIT: Failed to retrieve intervals");
+			free(intervals);
+			goto out;
+		}
+	}
+
+	fprintf(stdout, "INIT: Found ABI version %u\n",
+		ksft_session.info.abi_version);
+	fprintf(stdout, "INIT: Discovered %u global update intervals\n",
+		ksft_session.available.num_intervals);
+
+	ksft_session.original_cfg = malloc(sizeof(*ksft_session.original_cfg));
+	if (ksft_session.original_cfg) {
+		bzero(ksft_session.original_cfg, sizeof(*ksft_session.original_cfg));
+
+		ret = ioctl(fd, SCMI_TLM_GET_CFG, ksft_session.original_cfg);
+		if (ret) {
+			free(ksft_session.original_cfg);
+			ksft_session.original_cfg = NULL;
+		}
+	}
+
+	ksft_session.initialized = true;
+
+out:
+	close(fd);
+}
+
+TEST(scmi_tlm_config_struct_layout) {
+	ASSERT_EQ(24, sizeof(struct scmi_tlm_config));
+	ASSERT_EQ(0,  offsetof(struct scmi_tlm_config, enable));
+	ASSERT_EQ(1, offsetof(struct scmi_tlm_config, t_enable));
+	ASSERT_EQ(2, offsetof(struct scmi_tlm_config, flags));
+	ASSERT_EQ(3, offsetof(struct scmi_tlm_config, pad));
+	ASSERT_EQ(4, offsetof(struct scmi_tlm_config, grp_id));
+	ASSERT_EQ(8, offsetof(struct scmi_tlm_config, active));
+	ASSERT_EQ(16, offsetof(struct scmi_tlm_config, reserved));
+}
+
+TEST(scmi_tlm_abi_info_struct_layout) {
+	ASSERT_EQ(56, sizeof(struct scmi_tlm_abi_info));
+	ASSERT_EQ(0, offsetof(struct scmi_tlm_abi_info, size));
+	ASSERT_EQ(4, offsetof(struct scmi_tlm_abi_info, abi_version));
+	ASSERT_EQ(8, offsetof(struct scmi_tlm_abi_info, abi_features));
+	ASSERT_EQ(12, offsetof(struct scmi_tlm_abi_info, primary_de_impl_version));
+	ASSERT_EQ(28, offsetof(struct scmi_tlm_abi_info, num_des));
+	ASSERT_EQ(32, offsetof(struct scmi_tlm_abi_info, num_groups));
+	ASSERT_EQ(36, offsetof(struct scmi_tlm_abi_info, num_intervals));
+	ASSERT_EQ(40, offsetof(struct scmi_tlm_abi_info, num_shmtis));
+	ASSERT_EQ(44, offsetof(struct scmi_tlm_abi_info, features));
+	ASSERT_EQ(48, offsetof(struct scmi_tlm_abi_info, reserved));
+}
+
+TEST(scmi_tlm_update_interval_struct_layout) {
+	ASSERT_EQ(8, sizeof(struct scmi_tlm_update_interval));
+	ASSERT_EQ(0, offsetof(struct scmi_tlm_update_interval, secs));
+	ASSERT_EQ(4, offsetof(struct scmi_tlm_update_interval, exp));
+}
+
+TEST(scmi_tlm_intervals_struct_layout) {
+	ASSERT_EQ(32, sizeof(struct scmi_tlm_intervals));
+	ASSERT_EQ(0, offsetof(struct scmi_tlm_intervals, grp_id));
+	ASSERT_EQ(4, offsetof(struct scmi_tlm_intervals, flags));
+	ASSERT_EQ(5, offsetof(struct scmi_tlm_intervals, pad));
+	ASSERT_EQ(8, offsetof(struct scmi_tlm_intervals, num_intervals));
+	ASSERT_EQ(12, offsetof(struct scmi_tlm_intervals, pad2));
+	ASSERT_EQ(16, offsetof(struct scmi_tlm_intervals, reserved));
+	ASSERT_EQ(24, offsetof(struct scmi_tlm_intervals, intervals));
+}
+
+TEST(scmi_tlm_de_config_struct_layout) {
+	ASSERT_EQ(48, sizeof(struct scmi_tlm_de_config));
+	ASSERT_EQ(0, offsetof(struct scmi_tlm_de_config, id));
+	ASSERT_EQ(4, offsetof(struct scmi_tlm_de_config, enable));
+	ASSERT_EQ(8, offsetof(struct scmi_tlm_de_config, t_enable));
+	ASSERT_EQ(12, offsetof(struct scmi_tlm_de_config, sid));
+	ASSERT_EQ(16, offsetof(struct scmi_tlm_de_config, offset));
+	ASSERT_EQ(20, offsetof(struct scmi_tlm_de_config, pad));
+	ASSERT_EQ(24, offsetof(struct scmi_tlm_de_config, uuid));
+	ASSERT_EQ(40, offsetof(struct scmi_tlm_de_config, reserved));
+}
+
+TEST(scmi_tlm_de_info_struct_layout) {
+	ASSERT_EQ(72, sizeof(struct scmi_tlm_de_info));
+	ASSERT_EQ(0, offsetof(struct scmi_tlm_de_info, id));
+	ASSERT_EQ(4, offsetof(struct scmi_tlm_de_info, grp_id));
+	ASSERT_EQ(8, offsetof(struct scmi_tlm_de_info, data_sz));
+	ASSERT_EQ(12, offsetof(struct scmi_tlm_de_info, type));
+	ASSERT_EQ(16, offsetof(struct scmi_tlm_de_info, unit));
+	ASSERT_EQ(20, offsetof(struct scmi_tlm_de_info, unit_exp));
+	ASSERT_EQ(24, offsetof(struct scmi_tlm_de_info, ts_rate));
+	ASSERT_EQ(28, offsetof(struct scmi_tlm_de_info, instance_id));
+	ASSERT_EQ(32, offsetof(struct scmi_tlm_de_info, compo_instance_id));
+	ASSERT_EQ(36, offsetof(struct scmi_tlm_de_info, compo_type));
+	ASSERT_EQ(40, offsetof(struct scmi_tlm_de_info, persistent));
+	ASSERT_EQ(41, offsetof(struct scmi_tlm_de_info, flags));
+	ASSERT_EQ(42, offsetof(struct scmi_tlm_de_info, pad));
+	ASSERT_EQ(44, offsetof(struct scmi_tlm_de_info, pad2));
+	ASSERT_EQ(48, offsetof(struct scmi_tlm_de_info, name));
+	ASSERT_EQ(64, offsetof(struct scmi_tlm_de_info, reserved));
+}
+
+TEST(scmi_tlm_de_sample_struct_layout) {
+	ASSERT_EQ(24, sizeof(struct scmi_tlm_de_sample));
+	ASSERT_EQ(0, offsetof(struct scmi_tlm_de_sample, id));
+	ASSERT_EQ(4, offsetof(struct scmi_tlm_de_sample, pad));
+	ASSERT_EQ(8, offsetof(struct scmi_tlm_de_sample, tstamp));
+	ASSERT_EQ(16, offsetof(struct scmi_tlm_de_sample, val));
+}
+
+TEST(scmi_tlm_data_read_struct_layout) {
+	ASSERT_EQ(24, sizeof(struct scmi_tlm_data_read));
+	ASSERT_EQ(0, offsetof(struct scmi_tlm_data_read, grp_id));
+	ASSERT_EQ(4, offsetof(struct scmi_tlm_data_read, flags));
+	ASSERT_EQ(5, offsetof(struct scmi_tlm_data_read, pad));
+	ASSERT_EQ(8, offsetof(struct scmi_tlm_data_read, pad2));
+	ASSERT_EQ(12, offsetof(struct scmi_tlm_data_read, num_samples));
+	ASSERT_EQ(16, offsetof(struct scmi_tlm_data_read, samples));
+}
+
+TEST(scmi_tlm_batch_struct_layout) {
+	ASSERT_EQ(32, sizeof(struct scmi_tlm_batch));
+	ASSERT_EQ(0, offsetof(struct scmi_tlm_batch, num_items));
+	ASSERT_EQ(4, offsetof(struct scmi_tlm_batch, item_sz));
+	ASSERT_EQ(8, offsetof(struct scmi_tlm_batch, reserved));
+	ASSERT_EQ(16, offsetof(struct scmi_tlm_batch, states));
+	ASSERT_EQ(24, offsetof(struct scmi_tlm_batch, items));
+}
+
+TEST(scmi_tlm_grp_info_struct_layout) {
+	ASSERT_EQ(24, sizeof(struct scmi_tlm_grp_info));
+	ASSERT_EQ(0, offsetof(struct scmi_tlm_grp_info, grp_id));
+	ASSERT_EQ(4, offsetof(struct scmi_tlm_grp_info, num_des));
+	ASSERT_EQ(8, offsetof(struct scmi_tlm_grp_info, num_intervals));
+	ASSERT_EQ(12, offsetof(struct scmi_tlm_grp_info, pad));
+	ASSERT_EQ(16, offsetof(struct scmi_tlm_grp_info, reserved));
+}
+
+TEST(scmi_tlm_grp_desc_struct_layout) {
+	ASSERT_EQ(24, sizeof(struct scmi_tlm_grp_desc));
+	ASSERT_EQ(0, offsetof(struct scmi_tlm_grp_desc, grp_id));
+	ASSERT_EQ(4, offsetof(struct scmi_tlm_grp_desc, num_des));
+	ASSERT_EQ(8, offsetof(struct scmi_tlm_grp_desc, composing_des));
+}
+
+TEST(scmi_tlm_shmti_info_struct_layout) {
+	ASSERT_EQ(24, sizeof(struct scmi_tlm_shmti_info));
+	ASSERT_EQ(0, offsetof(struct scmi_tlm_shmti_info, sid));
+	ASSERT_EQ(4, offsetof(struct scmi_tlm_shmti_info, fd));
+	ASSERT_EQ(8, offsetof(struct scmi_tlm_shmti_info, len));
+	ASSERT_EQ(12, offsetof(struct scmi_tlm_shmti_info, offset));
+	ASSERT_EQ(16, offsetof(struct scmi_tlm_shmti_info, reserved));
+}
+
+TEST(scmi_tlm_uuid_struct_layout) {
+	ASSERT_EQ(16, sizeof(struct scmi_tlm_uuid));
+	ASSERT_EQ(0, offsetof(struct scmi_tlm_uuid, bytes));
+}
+
+TEST(scmi_tlm_event_struct_layout) {
+	ASSERT_EQ(24, sizeof(struct scmi_tlm_event));
+	ASSERT_EQ(0, offsetof(struct scmi_tlm_event, type));
+	ASSERT_EQ(4, offsetof(struct scmi_tlm_event, efd));
+	ASSERT_EQ(8, offsetof(struct scmi_tlm_event, cookie));
+	ASSERT_EQ(12, offsetof(struct scmi_tlm_event, pad));
+	ASSERT_EQ(16, offsetof(struct scmi_tlm_event, reserved));
+}
+
+FIXTURE(stlm) {
+	int fd;
+};
+
+FIXTURE_SETUP(stlm) {
+	if (!ksft_session.initialized)
+		SKIP(return, "initialization failed");
+
+	self->fd = open("/dev/scmi/" TLM_0, O_RDWR);
+	if (self->fd < 0)
+		SKIP(return, "device not available");
+
+	TH_LOG("Testing ABI Version %u on device %s",
+	       ksft_session.info.abi_version, TLM_0);
+}
+
+FIXTURE_TEARDOWN(stlm) {
+	close(self->fd);
+}
+
+TEST_F(stlm, tlm_get_cfg) {
+	struct scmi_tlm_config cfg = {};
+
+	ASSERT_EQ(0, ioctl(self->fd, SCMI_TLM_GET_CFG, &cfg));
+	ASSERT_EQ(0, cfg.pad);
+	ASSERT_EQ(0, cfg.reserved);
+	ASSERT_EQ(0, cfg.flags & ~SCMI_TLM_CONFIG_FLAGS);
+
+	TH_LOG("SCMI_TLM_GET_CFG - ena:%u  t_ena:%u  secs:%u  exp:%d",
+	       cfg.enable, cfg.t_enable, cfg.active.secs, cfg.active.exp);
+
+	for (int i = 0; i < ksft_session.info.num_groups; i++) {
+		cfg.flags = SCMI_TLM_CONFIG_GROUP;
+		cfg.grp_id = i;
+
+		ASSERT_EQ(0, ioctl(self->fd, SCMI_TLM_GET_CFG, &cfg));
+		ASSERT_EQ(0, cfg.pad);
+		ASSERT_EQ(0, cfg.reserved);
+		ASSERT_EQ(SCMI_TLM_CONFIG_GROUP, cfg.flags & SCMI_TLM_CONFIG_FLAGS);
+		ASSERT_EQ(i, cfg.grp_id);
+
+		TH_LOG("SCMI_TLM_GET_CFG - ena:%u  t_ena:%u  grp_id:%u  secs:%u  exp:%d",
+		       cfg.enable, cfg.t_enable, cfg.grp_id, cfg.active.secs, cfg.active.exp);
+	}
+
+	/* Invalid GRP ID should be ignored when proper flags missing */
+	cfg.grp_id = ksft_session.info.num_groups;
+	cfg.flags = 0x0;
+
+	ASSERT_EQ(0, ioctl(self->fd, SCMI_TLM_GET_CFG, &cfg));
+	ASSERT_EQ(0, cfg.pad);
+	ASSERT_EQ(0, cfg.reserved);
+}
+
+TEST_F(stlm, tlm_get_cfg_bad_group) {
+	struct scmi_tlm_config cfg = {};
+
+	cfg.flags = SCMI_TLM_CONFIG_GROUP;
+	cfg.grp_id = ksft_session.info.num_groups;
+
+	ASSERT_EQ(-1, ioctl(self->fd, SCMI_TLM_GET_CFG, &cfg));
+	ASSERT_EQ(0, cfg.pad);
+	ASSERT_EQ(0, cfg.reserved);
+	ASSERT_EQ(0, cfg.flags & ~SCMI_TLM_CONFIG_FLAGS);
+}
+
+TEST_F(stlm, tlm_get_cfg_null_ptr_rejected) {
+	ASSERT_EQ(-1, ioctl(self->fd, SCMI_TLM_GET_CFG, NULL));
+	EXPECT_EQ(EFAULT, errno);
+}
+
+TEST_F(stlm, tlm_get_cfg_invalid_request) {
+	struct scmi_tlm_config cfg = { };
+
+	cfg.pad = 0x1;
+	ASSERT_EQ(-1, ioctl(self->fd, SCMI_TLM_GET_CFG, &cfg));
+	EXPECT_EQ(EINVAL, errno);
+
+	cfg.pad = 0x0;
+	cfg.reserved = 0x1;
+	ASSERT_EQ(-1, ioctl(self->fd, SCMI_TLM_GET_CFG, &cfg));
+	EXPECT_EQ(EINVAL, errno);
+
+	cfg.reserved = 0x0;
+	cfg.flags = ~SCMI_TLM_CONFIG_FLAGS;
+	ASSERT_EQ(-1, ioctl(self->fd, SCMI_TLM_GET_CFG, &cfg));
+	EXPECT_EQ(EINVAL, errno);
+}
+
+TEST_F(stlm, tlm_set_cfg) {
+	struct scmi_tlm_config old_cfg = {};
+	struct scmi_tlm_config new_cfg = {};
+	struct scmi_tlm_config check_cfg = {};
+
+	if (!ksft_session.original_cfg)
+		SKIP(return, "original config not available");
+
+	old_cfg = *ksft_session.original_cfg;
+
+	new_cfg = old_cfg;
+	new_cfg.enable = !old_cfg.enable;
+
+	if (ksft_session.info.num_intervals > 1) {
+		int num_intervals = ksft_session.info.num_intervals;
+		struct scmi_tlm_update_interval *intervals;
+
+		intervals = (struct scmi_tlm_update_interval *)ksft_session.available.intervals;
+		for (int i = 0; i < num_intervals; i++) {
+			if (intervals[i].secs == old_cfg.active.secs &&
+			    intervals[i].exp == old_cfg.active.exp)
+				continue;
+
+			/* pick another valid interval */
+			new_cfg.active.secs = intervals[i].secs;
+			new_cfg.active.exp = intervals[i].exp;
+			break;
+		}
+	}
+
+	TH_LOG("SCMI_TLM_SET_CFG - ena:%u  t_ena:%u  secs:%u  exp:%d",
+	       new_cfg.enable, new_cfg.t_enable, new_cfg.active.secs, new_cfg.active.exp);
+
+	ASSERT_EQ(0, ioctl(self->fd, SCMI_TLM_SET_CFG, &new_cfg));
+	ASSERT_EQ(0, ioctl(self->fd, SCMI_TLM_GET_CFG, &check_cfg));
+	ASSERT_EQ(0, ioctl(self->fd, SCMI_TLM_SET_CFG, &old_cfg));
+
+	ASSERT_EQ(new_cfg.enable, check_cfg.enable);
+	ASSERT_EQ(new_cfg.active.secs, check_cfg.active.secs);
+	ASSERT_EQ(new_cfg.active.exp, check_cfg.active.exp);
+	ASSERT_EQ(0, check_cfg.pad);
+	ASSERT_EQ(0, check_cfg.reserved);
+
+}
+
+TEST_F(stlm, tlm_get_intrvs) {
+	struct scmi_tlm_update_interval *intervals;
+	struct scmi_tlm_intervals ivs = {};
+	int num_intervals = ksft_session.info.num_intervals;
+
+	if (!num_intervals)
+		SKIP(return, "No update intervals available");
+
+	intervals = malloc(sizeof(*intervals) * num_intervals);
+	ASSERT_NE(NULL, intervals);
+	bzero(intervals, sizeof(*intervals) * num_intervals);
+
+	ivs.num_intervals = num_intervals;
+	ivs.intervals = (__u64)intervals;
+
+	ASSERT_EQ(0, ioctl(self->fd, SCMI_TLM_GET_INTRVS, &ivs));
+
+	ASSERT_EQ(num_intervals, ivs.num_intervals);
+	ASSERT_EQ(0, ivs.pad[0]);
+	ASSERT_EQ(0, ivs.pad[1]);
+	ASSERT_EQ(0, ivs.pad[2]);
+	ASSERT_EQ(0, ivs.pad2);
+	ASSERT_EQ(0, ivs.reserved);
+	ASSERT_EQ(0, ivs.flags & ~SCMI_TLM_INTERV_FLAGS);
+
+	for (int i = 0; i < num_intervals; i++) {
+		TH_LOG("SCMI_TLM_GET_INTRVS - [%d] secs:%u exp:%d", i,
+		       intervals[i].secs, intervals[i].exp);
+	}
+
+	free(intervals);
+}
+
+TEST_F(stlm, tlm_get_intrvs_invalid_request) {
+	struct scmi_tlm_update_interval interval = {};
+	struct scmi_tlm_intervals ivs = {};
+
+	ivs.num_intervals = 1;
+	ivs.intervals = (__u64)&interval;
+	ivs.pad[0] = 1;
+	ASSERT_EQ(-1, ioctl(self->fd, SCMI_TLM_GET_INTRVS, &ivs));
+	EXPECT_EQ(EINVAL, errno);
+
+	bzero(&ivs, sizeof(ivs));
+	ivs.num_intervals = 1;
+	ivs.intervals = (__u64)&interval;
+	ivs.pad2 = 1;
+	ASSERT_EQ(-1, ioctl(self->fd, SCMI_TLM_GET_INTRVS, &ivs));
+	EXPECT_EQ(EINVAL, errno);
+
+	bzero(&ivs, sizeof(ivs));
+	ivs.num_intervals = 1;
+	ivs.intervals = (__u64)&interval;
+	ivs.reserved = 1;
+	ASSERT_EQ(-1, ioctl(self->fd, SCMI_TLM_GET_INTRVS, &ivs));
+	EXPECT_EQ(EINVAL, errno);
+
+	bzero(&ivs, sizeof(ivs));
+	ivs.num_intervals = 1;
+	ivs.intervals = (__u64)&interval;
+	ivs.flags = ~SCMI_TLM_INTERV_FLAGS;
+	ASSERT_EQ(-1, ioctl(self->fd, SCMI_TLM_GET_INTRVS, &ivs));
+}
+
+TEST_F(stlm, tlm_get_intrvs_oversized) {
+	struct scmi_tlm_update_interval interval = {};
+	struct scmi_tlm_intervals ivs = {};
+
+	ivs.num_intervals = ksft_session.info.num_intervals + 1;
+	ivs.intervals = (__u64)&interval;
+
+	ASSERT_EQ(-1, ioctl(self->fd, SCMI_TLM_GET_INTRVS, &ivs));
+	EXPECT_EQ(ENOSPC, errno);
+}
+
+TEST_F(stlm, tlm_get_de_list)
+{
+	struct scmi_tlm_de_info *des;
+	struct scmi_tlm_batch batch = {};
+
+	if (!ksft_session.info.num_des)
+		SKIP(return, "no DEs available");
+
+	ASSERT_EQ(0, scmi_tlm_batch_init(&batch, ksft_session.info.num_des,
+		  sizeof(*des), false));
+
+	des = (struct scmi_tlm_de_info *)batch.items;
+
+	ASSERT_EQ(0, ioctl(self->fd, SCMI_TLM_GET_DE_LIST, &batch));
+
+	ASSERT_LE(batch.num_items, ksft_session.info.num_des);
+
+	for (int i = 0; i < batch.num_items; i++) {
+		ASSERT_EQ(0, des[i].reserved);
+		ASSERT_EQ(0, des[i].pad[0]);
+		ASSERT_EQ(0, des[i].pad[1]);
+		ASSERT_EQ(0, des[i].pad2);
+		ASSERT_EQ(0, des[i].flags & ~SCMI_TLM_DEINFO_FLAGS);
+
+		TH_LOG("SCMI_TLM_GET_DE_LIST - [%d] id:0x%x name:%s", i, des[i].id,
+		       des[i].name);
+	}
+
+	scmi_tlm_batch_free(&batch);
+}
+
+TEST_F(stlm, tlm_get_de_list_zero_size_query)
+{
+	struct scmi_tlm_batch batch = {};
+
+	batch.num_items = 0;
+	batch.item_sz = sizeof(struct scmi_tlm_de_info);
+
+	ASSERT_EQ(0, ioctl(self->fd, SCMI_TLM_GET_DE_LIST, &batch));
+	ASSERT_EQ(ksft_session.info.num_des, batch.num_items);
+	ASSERT_EQ(sizeof(struct scmi_tlm_de_info), batch.item_sz);
+	ASSERT_EQ(0, batch.reserved);
+	ASSERT_EQ(0, batch.items);
+}
+
+TEST_F(stlm, tlm_get_de_list_zero_size_query_bad_item_sz)
+{
+	struct scmi_tlm_batch batch = {};
+
+	batch.num_items = 0;
+	batch.item_sz = sizeof(struct scmi_tlm_de_info) + 1;
+	ASSERT_EQ(-1, ioctl(self->fd, SCMI_TLM_GET_DE_LIST, &batch));
+	EXPECT_EQ(EINVAL, errno);
+}
+
+TEST_F(stlm, tlm_get_de_list_invalid_request)
+{
+	struct scmi_tlm_batch batch = {};
+	struct scmi_tlm_de_info de = {};
+
+	batch.num_items = 1;
+	batch.item_sz = sizeof(de) + 1;
+	batch.items = (__u64)&de;
+
+	ASSERT_EQ(-1, ioctl(self->fd, SCMI_TLM_GET_DE_LIST, &batch));
+	EXPECT_EQ(EINVAL, errno);
+
+	bzero(&batch, sizeof(batch));
+	batch.num_items = 1;
+	batch.item_sz = sizeof(de);
+	batch.reserved = 1;
+	batch.items = (__u64)&de;
+
+	ASSERT_EQ(-1, ioctl(self->fd, SCMI_TLM_GET_DE_LIST, &batch));
+	EXPECT_EQ(EINVAL, errno);
+
+	bzero(&batch, sizeof(batch));
+	batch.num_items = ksft_session.info.num_des + 1;
+	batch.item_sz = sizeof(de);
+	batch.items = (__u64)&de;
+
+	ASSERT_EQ(-1, ioctl(self->fd, SCMI_TLM_GET_DE_LIST, &batch));
+	EXPECT_EQ(EINVAL, errno);
+}
+
+TEST_F(stlm, tlm_get_de_info)
+{
+	struct scmi_tlm_de_info info = {};
+
+	if (!ksft_session.de_list || !ksft_session.num_des)
+		SKIP(return, "no DE list available");
+
+	info.id = ksft_session.de_list[0].id;
+
+	ASSERT_EQ(0, ioctl(self->fd, SCMI_TLM_GET_DE_INFO, &info));
+	ASSERT_EQ(0, info.reserved);
+	ASSERT_EQ(0, info.pad[0]);
+	ASSERT_EQ(0, info.pad[1]);
+	ASSERT_EQ(0, info.pad2);
+	ASSERT_EQ(0, info.flags & ~SCMI_TLM_DEINFO_FLAGS);
+
+	TH_LOG("SCMI_TLM_GET_DE_INFO - id:0x%x name:%s data_sz:%u",
+	       info.id, info.name, info.data_sz);
+}
+
+TEST_F(stlm, tlm_get_de_info_invalid_request)
+{
+	struct scmi_tlm_de_info info = {};
+
+	if (!ksft_session.de_list || !ksft_session.num_des)
+		SKIP(return, "no DE list available");
+
+	info.id = ksft_session.de_list[0].id;
+	info.flags = 1;
+	ASSERT_EQ(-1, ioctl(self->fd, SCMI_TLM_GET_DE_INFO, &info));
+	EXPECT_EQ(EINVAL, errno);
+
+	bzero(&info, sizeof(info));
+	info.id = ksft_session.de_list[0].id;
+	info.pad[0] = 1;
+	ASSERT_EQ(-1, ioctl(self->fd, SCMI_TLM_GET_DE_INFO, &info));
+	EXPECT_EQ(EINVAL, errno);
+
+	bzero(&info, sizeof(info));
+	info.id = ksft_session.de_list[0].id;
+	info.reserved = 1;
+	ASSERT_EQ(-1, ioctl(self->fd, SCMI_TLM_GET_DE_INFO, &info));
+	EXPECT_EQ(EINVAL, errno);
+}
+
+TEST_F(stlm, tlm_get_de_info_bad_id)
+{
+	struct scmi_tlm_de_info info = {};
+
+	info.id = 0xffffffff;
+
+	ASSERT_EQ(-1, ioctl(self->fd, SCMI_TLM_GET_DE_INFO, &info));
+	EXPECT_EQ(EINVAL, errno);
+}
+
+TEST_F(stlm, tlm_get_de_cfg)
+{
+	struct scmi_tlm_batch batch = {};
+	struct scmi_tlm_de_config *cfg;
+
+	if (!ksft_session.de_list || !ksft_session.num_des)
+		SKIP(return, "no DE list available");
+
+	ASSERT_EQ(0, scmi_tlm_batch_init(&batch, 1, sizeof(*cfg), false));
+
+	cfg = (struct scmi_tlm_de_config *)batch.items;
+	cfg[0].id = ksft_session.de_list[0].id;
+
+	ASSERT_EQ(0, ioctl(self->fd, SCMI_TLM_GET_DE_CFG, &batch));
+	ASSERT_EQ(1, batch.num_items);
+	ASSERT_EQ(ksft_session.de_list[0].id, cfg[0].id);
+	ASSERT_EQ(0, cfg[0].reserved);
+
+	TH_LOG("SCMI_TLM_GET_DE_CFG - id:0x%x ena:%u sid:%u offset:%u",
+			cfg[0].id, cfg[0].enable, cfg[0].sid,
+			cfg[0].offset);
+
+	scmi_tlm_batch_free(&batch);
+}
+
+TEST_F(stlm, tlm_get_de_cfg_invalid_request)
+{
+	struct scmi_tlm_batch batch = {};
+	struct scmi_tlm_de_config cfg = {};
+
+	batch.num_items = 1;
+	batch.item_sz = sizeof(cfg) + 1;
+	batch.items = (__u64)&cfg;
+
+	ASSERT_EQ(-1, ioctl(self->fd, SCMI_TLM_GET_DE_CFG, &batch));
+	EXPECT_EQ(EINVAL, errno);
+
+	bzero(&batch, sizeof(batch));
+	batch.num_items = ksft_session.info.num_des + 1;
+	batch.item_sz = sizeof(cfg);
+	batch.items = (__u64)&cfg;
+
+	ASSERT_EQ(-1, ioctl(self->fd, SCMI_TLM_GET_DE_CFG, &batch));
+	EXPECT_EQ(EINVAL, errno);
+
+	bzero(&batch, sizeof(batch));
+	batch.num_items = 1;
+	batch.item_sz = sizeof(cfg);
+	batch.items = 0;
+
+	ASSERT_EQ(-1, ioctl(self->fd, SCMI_TLM_GET_DE_CFG, &batch));
+	EXPECT_EQ(EFAULT, errno);
+}
+
+TEST_F(stlm, tlm_get_de_cfg_bad_id)
+{
+	struct scmi_tlm_batch batch = {};
+	struct scmi_tlm_de_config *cfg;
+
+	ASSERT_EQ(0, scmi_tlm_batch_init(&batch, 1, sizeof(*cfg), false));
+
+	cfg = (struct scmi_tlm_de_config *)batch.items;
+	cfg[0].id = 0xffffffff;
+
+	ASSERT_EQ(-1, ioctl(self->fd, SCMI_TLM_GET_DE_CFG, &batch));
+	EXPECT_EQ(ENODEV, errno);
+
+	scmi_tlm_batch_free(&batch);
+}
+
+TEST_F(stlm, tlm_get_de_cfg_bad_id_with_states)
+{
+	struct scmi_tlm_batch batch = {};
+	struct scmi_tlm_de_config *cfg;
+	int *states;
+
+	ASSERT_EQ(0, scmi_tlm_batch_init(&batch, 1, sizeof(*cfg), true));
+
+	cfg = (struct scmi_tlm_de_config *)batch.items;
+	states = (int *)batch.states;
+
+	cfg[0].id = 0xffffffff;
+
+	ASSERT_EQ(0, ioctl(self->fd, SCMI_TLM_GET_DE_CFG, &batch));
+	ASSERT_LT(states[0], 0);
+
+	scmi_tlm_batch_free(&batch);
+}
+
+TEST_F(stlm, tlm_de_read)
+{
+	struct scmi_tlm_de_sample sample = {};
+	__u32 de_id;
+
+	if (!ksft_session.de_list || !ksft_session.num_des)
+		SKIP(return, "no DE list availalbe");
+
+	de_id = ksft_session.de_list[0].id;
+	sample.id = de_id;
+
+	ASSERT_EQ(0, ioctl(self->fd, SCMI_TLM_DE_READ, &sample));
+	ASSERT_EQ(de_id, sample.id);
+	ASSERT_EQ(0, sample.pad);
+
+	TH_LOG("SCMI_TLM_DE_READ - id:0x%x tstamp:%llu val:%llu", sample.id,
+	       sample.tstamp, sample.val);
+}
+
+TEST_F(stlm, tlm_de_read_invalid_request)
+{
+	struct scmi_tlm_de_sample sample = {};
+
+	if (!ksft_session.de_list || !ksft_session.num_des)
+		SKIP(return, "no DE list available");
+
+	sample.id = ksft_session.de_list[0].id;
+	sample.pad = 1;
+
+	ASSERT_EQ(-1, ioctl(self->fd, SCMI_TLM_DE_READ, &sample));
+	EXPECT_EQ(EINVAL, errno);
+}
+
+TEST_F(stlm, tlm_de_read_null_ptr_rejected)
+{
+	ASSERT_EQ(-1, ioctl(self->fd, SCMI_TLM_DE_READ, NULL));
+	EXPECT_EQ(EFAULT, errno);
+}
+
+TEST_F(stlm, tlm_de_read_bad_id)
+{
+	struct scmi_tlm_de_sample sample = {};
+
+	sample.id = 0xffffffff;
+
+	ASSERT_EQ(-1, ioctl(self->fd, SCMI_TLM_DE_READ, &sample));
+	EXPECT_EQ(ENOENT, errno);
+}
+
+TEST_F(stlm, tlm_single_read)
+{
+	struct scmi_tlm_de_sample *samples;
+	struct scmi_tlm_data_read read = {};
+	int num_samples = ksft_session.num_des;
+
+	if (!ksft_session.de_list || !ksft_session.num_des)
+		SKIP(return, "no DE list available");
+
+	samples = malloc(sizeof(*samples) * num_samples);
+	ASSERT_NE(NULL, samples);
+	bzero(samples, sizeof(*samples) * num_samples);
+
+	read.num_samples = num_samples;
+	read.samples = (__u64)samples;
+
+	ASSERT_EQ(0, ioctl(self->fd, SCMI_TLM_SINGLE_READ, &read));
+	ASSERT_LE(read.num_samples, num_samples);
+	ASSERT_EQ(0, read.pad[0]);
+	ASSERT_EQ(0, read.pad[1]);
+	ASSERT_EQ(0, read.pad[2]);
+	ASSERT_EQ(0, read.pad2);
+	ASSERT_EQ(0, read.flags & ~SCMI_TLM_READ_FLAGS);
+
+	for (int i = 0; i < read.num_samples; i++) {
+		ASSERT_EQ(0, samples[i].pad);
+
+		TH_LOG("SCMI_TLM_SINGE_READ = [%d] id:0x%x tstamp:%llu val:%llu", i,
+		       samples[i].id, samples[i].tstamp, samples[i].val);
+	}
+
+	free(samples);
+}
+
+TEST_F(stlm, tlm_single_read_invalid_request)
+{
+	struct scmi_tlm_de_sample sample = {};
+	struct scmi_tlm_data_read read = {};
+
+	read.num_samples = 1;
+	read.samples = (__u64)&sample;
+	read.pad[0] = 1;
+	ASSERT_EQ(-1, ioctl(self->fd, SCMI_TLM_SINGLE_READ, &read));
+	EXPECT_EQ(EINVAL, errno);
+
+	bzero(&read, sizeof(read));
+	read.num_samples = 1;
+	read.samples = (__u64)&sample;
+	read.pad2 = 1;
+	ASSERT_EQ(-1, ioctl(self->fd, SCMI_TLM_SINGLE_READ, &read));
+	EXPECT_EQ(EINVAL, errno);
+
+	bzero(&read, sizeof(read));
+	read.num_samples = 1;
+	read.samples = (__u64)&sample;
+	read.flags = ~SCMI_TLM_READ_FLAGS;
+	ASSERT_EQ(-1, ioctl(self->fd, SCMI_TLM_SINGLE_READ, &read));
+	EXPECT_EQ(EINVAL, errno);
+}
+
+TEST_F(stlm, tlm_single_read_oversized)
+{
+	struct scmi_tlm_de_sample sample = {};
+	struct scmi_tlm_data_read read = {};
+
+	read.num_samples = ksft_session.info.num_des + 1;
+	read.samples = (__u64)&sample;
+	ASSERT_EQ(-1, ioctl(self->fd, SCMI_TLM_SINGLE_READ, &read));
+	EXPECT_EQ(E2BIG, errno);
+}
+
+TEST_F(stlm, tlm_single_read_null_ptr_rejected)
+{
+	ASSERT_EQ(-1, ioctl(self->fd, SCMI_TLM_SINGLE_READ, NULL));
+	EXPECT_EQ(EFAULT, errno);
+}
+
+TEST_F(stlm, tlm_bulk_read)
+{
+	struct scmi_tlm_de_sample *samples;
+	struct scmi_tlm_data_read read = {};
+	int num_samples = ksft_session.num_des;
+	int i;
+
+	if (!ksft_session.de_list || !ksft_session.num_des)
+		SKIP(return, "no DE list available");
+
+	samples = malloc(sizeof(*samples) * num_samples);
+	ASSERT_NE(NULL, samples);
+	bzero(samples, sizeof(*samples) * num_samples);
+
+	read.num_samples = num_samples;
+	read.samples = (__u64)samples;
+
+	ASSERT_EQ(0, ioctl(self->fd, SCMI_TLM_BULK_READ, &read));
+	ASSERT_LE(read.num_samples, num_samples);
+	ASSERT_EQ(0, read.pad[0]);
+	ASSERT_EQ(0, read.pad[1]);
+	ASSERT_EQ(0, read.pad[2]);
+	ASSERT_EQ(0, read.pad2);
+	ASSERT_EQ(0, read.flags & ~SCMI_TLM_READ_FLAGS);
+
+	for (i = 0; i < read.num_samples; i++) {
+		ASSERT_EQ(0, samples[i].pad);
+
+		TH_LOG("SCMI_TLM_BULK_READ - [%d] id:0x%x tstamp:%llu val:%llu", i,
+		       samples[i].id, samples[i].tstamp, samples[i].val);
+	}
+
+	free(samples);
+}
+
+TEST_F(stlm, tlm_bulk_read_invalid_request)
+{
+	struct scmi_tlm_de_sample sample = {};
+	struct scmi_tlm_data_read read = {};
+
+	read.num_samples = 1;
+	read.samples = (__u64)&sample;
+	read.pad[0] = 1;
+	ASSERT_EQ(-1, ioctl(self->fd, SCMI_TLM_BULK_READ, &read));
+	EXPECT_EQ(EINVAL, errno);
+
+	bzero(&read, sizeof(read));
+	read.num_samples = 1;
+	read.samples = (__u64)&sample;
+	read.pad2 = 1;
+	ASSERT_EQ(-1, ioctl(self->fd, SCMI_TLM_BULK_READ, &read));
+	EXPECT_EQ(EINVAL, errno);
+
+	bzero(&read, sizeof(read));
+	read.num_samples = 1;
+	read.samples = (__u64)&sample;
+	read.flags = ~SCMI_TLM_READ_FLAGS;
+	ASSERT_EQ(-1, ioctl(self->fd, SCMI_TLM_BULK_READ, &read));
+	EXPECT_EQ(EINVAL, errno);
+}
+
+TEST_F(stlm, tlm_bulk_read_oversized)
+{
+	struct scmi_tlm_de_sample sample = {};
+	struct scmi_tlm_data_read read = {};
+
+	read.num_samples = ksft_session.info.num_des + 1;
+	read.samples = (__u64)&sample;
+
+	ASSERT_EQ(-1, ioctl(self->fd, SCMI_TLM_BULK_READ, &read));
+	EXPECT_EQ(E2BIG, errno);
+}
+
+TEST_F(stlm, tlm_bulk_read_null_ptr_rejected)
+{
+	ASSERT_EQ(-1, ioctl(self->fd, SCMI_TLM_BULK_READ, NULL));
+	EXPECT_EQ(EFAULT, errno);
+}
+
+TEST_F(stlm, tlm_batch_read)
+{
+	struct scmi_tlm_batch batch = {};
+	struct scmi_tlm_de_sample *samples;
+
+	if (!ksft_session.de_list || !ksft_session.num_des)
+		SKIP(return, "no DE list available");
+
+	ASSERT_EQ(0, scmi_tlm_batch_init(&batch, 1, sizeof(*samples),
+		  false));
+
+	samples = (struct scmi_tlm_de_sample *)batch.items;
+	samples[0].id = ksft_session.de_list[0].id;
+
+	ASSERT_EQ(0, ioctl(self->fd, SCMI_TLM_BATCH_READ, &batch));
+
+	ASSERT_EQ(1, batch.num_items);
+	ASSERT_EQ(ksft_session.de_list[0].id, samples[0].id);
+	ASSERT_EQ(0, samples[0].pad);
+
+	TH_LOG("SCMI_TLM_BATCH_READ - id:0x%x tstamp:%llu val:%llu", samples[0].id,
+	       samples[0].tstamp, samples[0].val);
+
+	scmi_tlm_batch_free(&batch);
+}
+
+TEST_F(stlm, tlm_batch_read_invalid_request)
+{
+	struct scmi_tlm_batch batch = {};
+	struct scmi_tlm_de_sample sample = {};
+
+	batch.num_items = 1;
+	batch.item_sz = sizeof(sample) + 1;
+	batch.items = (__u64)&sample;
+
+	ASSERT_EQ(-1, ioctl(self->fd, SCMI_TLM_BATCH_READ, &batch));
+	EXPECT_EQ(EINVAL, errno);
+
+	bzero(&batch, sizeof(batch));
+	batch.num_items = 1;
+	batch.item_sz = sizeof(sample);
+	batch.reserved = 1;
+	batch.items = (__u64)&sample;
+
+	ASSERT_EQ(-1, ioctl(self->fd, SCMI_TLM_BATCH_READ, &batch));
+	EXPECT_EQ(EINVAL, errno);
+
+	bzero(&batch, sizeof(batch));
+	batch.num_items = ksft_session.info.num_des + 1;
+	batch.item_sz = sizeof(sample);
+	batch.items = (__u64)&sample;
+
+	ASSERT_EQ(-1, ioctl(self->fd, SCMI_TLM_BATCH_READ, &batch));
+	EXPECT_EQ(EINVAL, errno);
+}
+
+TEST_F(stlm, tlm_batch_read_bad_items_ptr)
+{
+	struct scmi_tlm_batch batch = {};
+
+	batch.num_items = 1;
+	batch.item_sz = sizeof(struct scmi_tlm_de_sample);
+	batch.items = 0;
+
+	ASSERT_EQ(-1, ioctl(self->fd, SCMI_TLM_BATCH_READ, &batch));
+	EXPECT_EQ(EFAULT, errno);
+}
+
+TEST_F(stlm, tlm_batch_read_bad_id)
+{
+	struct scmi_tlm_batch batch = {};
+	struct scmi_tlm_de_sample *samples;
+
+	ASSERT_EQ(0, scmi_tlm_batch_init(&batch, 1, sizeof(*samples), false));
+
+	samples = (struct scmi_tlm_de_sample *)batch.items;
+	samples[0].id = 0xffffffff;
+
+	ASSERT_EQ(-1, ioctl(self->fd, SCMI_TLM_BATCH_READ, &batch));
+	EXPECT_EQ(ENOENT, errno);
+
+	scmi_tlm_batch_free(&batch);
+}
+
+TEST_F(stlm, tlm_batch_read_bad_id_with_states)
+{
+	struct scmi_tlm_batch batch = {};
+	struct scmi_tlm_de_sample *samples;
+	int *states;
+
+	ASSERT_EQ(0, scmi_tlm_batch_init(&batch, 1, sizeof(*samples), true));
+
+	samples = (struct scmi_tlm_de_sample *)batch.items;
+	states = (int *)batch.states;
+
+	samples[0].id = 0xffffffff;
+
+	ASSERT_EQ(0, ioctl(self->fd, SCMI_TLM_BATCH_READ, &batch));
+	ASSERT_EQ(-ENOENT, states[0]);
+
+	scmi_tlm_batch_free(&batch);
+}
+
+TEST_HARNESS_MAIN   /* generates main() */
-- 
2.54.0




More information about the linux-arm-kernel mailing list