From: Rob Clark <rob.clark@oss.qualcomm.com>
To: igt-dev@lists.freedesktop.org
Cc: freedreno@lists.freedesktop.org, Rob Clark <rob.clark@oss.qualcomm.com>
Subject: [PATCH 2/2] tests/msm: Add perfcntrs test
Date: Fri, 3 Jul 2026 07:39:49 -0700 [thread overview]
Message-ID: <20260703143949.280272-3-rob.clark@oss.qualcomm.com> (raw)
In-Reply-To: <20260703143949.280272-1-rob.clark@oss.qualcomm.com>
Add tests for new PERFCNTR_CONFIG ioctl.
Signed-off-by: Rob Clark <rob.clark@oss.qualcomm.com>
---
tests/msm/meson.build | 1 +
tests/msm/msm_perfcntrs.c | 194 ++++++++++++++++++++++++++++++++++++++
2 files changed, 195 insertions(+)
create mode 100644 tests/msm/msm_perfcntrs.c
diff --git a/tests/msm/meson.build b/tests/msm/meson.build
index 2ba5b4db2279..0a7f35662c03 100644
--- a/tests/msm/meson.build
+++ b/tests/msm/meson.build
@@ -1,6 +1,7 @@
msm_progs = [
'msm_bo',
'msm_mapping',
+ 'msm_perfcntrs',
'msm_recovery',
'msm_shrink',
'msm_submit',
diff --git a/tests/msm/msm_perfcntrs.c b/tests/msm/msm_perfcntrs.c
new file mode 100644
index 000000000000..7dab92b5c6bc
--- /dev/null
+++ b/tests/msm/msm_perfcntrs.c
@@ -0,0 +1,194 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#include <errno.h>
+
+#include "igt.h"
+#include "igt_core.h"
+#include "igt_msm.h"
+#include "msm_drm.h"
+
+static int
+__configure_counters(struct msm_device *dev, bool global, unsigned nr_groups,
+ const char **groups, unsigned count)
+{
+ uint32_t countables[count] = {}; /* selecting countable 0 for each counter is fine */
+ struct drm_msm_perfcntr_group group[nr_groups];
+ struct drm_msm_perfcntr_config req = {
+ .flags = global ? MSM_PERFCNTR_STREAM : 0,
+ .nr_groups = nr_groups,
+ .groups = VOID2U64(group),
+ .period = global ? NSEC_PER_SEC : 0,
+ .bufsz_shift = global ? 10 : 0,
+ .group_stride = sizeof(struct drm_msm_perfcntr_group),
+ };
+
+ memset(group, 0, sizeof(group));
+
+ for (unsigned i = 0; i < nr_groups; i++) {
+ strcpy(group[i].group_name, groups[i]);
+ group[i].nr_countables = count;
+ group[i].countables = global ? VOID2U64(countables) : 0;
+ }
+
+ return drmIoctl(dev->fd, DRM_IOCTL_MSM_PERFCNTR_CONFIG, &req);
+}
+
+static int
+configure_counters(struct msm_device *dev, bool global, unsigned count)
+{
+ /* CP group is present on all gens.. SP would be another good candidate */
+ const char *groups[] = {"CP"};
+ return __configure_counters(dev, global, 1, groups, count);
+}
+
+static unsigned
+get_available_counters(struct msm_device *dev, bool global)
+{
+ for (unsigned i = 0; ; i++) {
+ int ret = configure_counters(dev, global, i + 1);
+ igt_warn("%u: ret=%d\n", i, ret);
+ if (ret < 0)
+ return i;
+ if (global)
+ close(ret);
+ }
+}
+
+
+int igt_main()
+{
+ /* device instance for global counter collection: */
+ struct msm_device *dev_global = NULL;
+ /* device instances for local counter reservation: */
+ struct msm_device *dev_local_1 = NULL;
+ struct msm_device *dev_local_2 = NULL;
+ unsigned num_counters;
+
+ igt_fixture() {
+ dev_global = igt_msm_dev_open();
+ dev_local_1 = igt_msm_dev_open();
+ dev_local_2 = igt_msm_dev_open();
+
+ num_counters = get_available_counters(dev_global, true);
+ igt_info("num_counters=%u\n", num_counters);
+ }
+
+ igt_describe("Multiple process should be able to reserve the same "
+ "counters for local counter collection");
+ igt_subtest("perfcntrs-local-coexist") {
+ igt_require(num_counters > 0);
+
+ igt_assert_eq(0, configure_counters(dev_local_1, false, num_counters));
+ igt_assert_eq(0, configure_counters(dev_local_2, false, num_counters));
+
+ /* release the reservations: */
+ configure_counters(dev_local_1, false, 0);
+ configure_counters(dev_local_2, false, 0);
+ }
+
+ igt_describe("non-conflict global and local counters");
+ igt_subtest("perfcntrs-non-conflict-global-local") {
+ int num_local = num_counters - 2;
+ int stream_fd;
+
+ igt_require(num_counters > 2);
+
+ igt_assert_eq(0, configure_counters(dev_local_1, false, num_local));
+ igt_assert_eq(0, configure_counters(dev_local_2, false, num_local));
+
+ stream_fd = configure_counters(dev_global, true, 2);
+ igt_assert_lte(0, stream_fd);
+ close(stream_fd);
+
+ /* release the reservations: */
+ configure_counters(dev_local_1, false, 0);
+ configure_counters(dev_local_2, false, 0);
+ }
+
+ igt_describe("conflict, local first");
+ igt_subtest("conflict-local-first") {
+ int num_local = num_counters - 1;
+ int stream_fd;
+
+ igt_require(num_counters > 2);
+
+ igt_assert_eq(0, configure_counters(dev_local_1, false, num_local));
+ igt_assert_eq(0, configure_counters(dev_local_2, false, num_local));
+
+ stream_fd = configure_counters(dev_global, true, 2);
+ igt_assert_lt(stream_fd, 0);
+
+ /* release the reservation for dev_local_1: */
+ configure_counters(dev_local_1, false, 0);
+
+ /* should still fail: */
+ stream_fd = configure_counters(dev_global, true, 2);
+ igt_assert_lt(stream_fd, 0);
+
+ /* release the reservation for dev_local_2: */
+ configure_counters(dev_local_2, false, 0);
+
+ /* now should succeed: */
+ stream_fd = configure_counters(dev_global, true, 2);
+ igt_assert_lte(0, stream_fd);
+ close(stream_fd);
+ }
+
+ igt_describe("conflict, global first");
+ igt_subtest("conflict-global-first") {
+ int num_local = num_counters - 1;
+ int stream_fd;
+
+ igt_require(num_counters > 2);
+
+ stream_fd = configure_counters(dev_global, true, 2);
+ igt_assert_lte(0, stream_fd);
+
+ /* Should fail because two counters already allocated for global collection: */
+ igt_assert_neq(0, configure_counters(dev_local_1, false, num_local));
+
+ /* release global counters: */
+ close(stream_fd);
+
+ /* Now reservation should succeed: */
+ igt_assert_eq(0, configure_counters(dev_local_1, false, num_local));
+
+ /* release the reservations: */
+ configure_counters(dev_local_1, false, 0);
+ }
+
+ igt_describe("multiple groups");
+ igt_subtest("multiple-groups") {
+ const char *groups[] = {"CP", "SP"};
+
+ igt_require(num_counters > 0);
+
+ igt_assert_eq(0,
+ __configure_counters(dev_local_1, false, ARRAY_SIZE(groups), groups, 1));
+
+ /* release the reservations: */
+ configure_counters(dev_local_1, false, 0);
+ }
+
+ igt_describe("duplicate groups");
+ igt_subtest("duplicate-groups") {
+ const char *groups[] = {"CP", "CP"};
+
+ igt_require(num_counters > 0);
+
+ igt_assert_neq(0,
+ __configure_counters(dev_local_1, false, ARRAY_SIZE(groups), groups, 1));
+
+ /* release the reservations: */
+ configure_counters(dev_local_1, false, 0);
+ }
+
+ igt_fixture() {
+ igt_msm_dev_close(dev_global);
+ igt_msm_dev_close(dev_local_1);
+ igt_msm_dev_close(dev_local_2);
+ }
+}
--
2.54.0
next prev parent reply other threads:[~2026-07-03 14:44 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-03 14:39 [PATCH 0/2] tests/msm: Add PERFCNTR_CONFIG ioctl Rob Clark
2026-07-03 14:39 ` [PATCH 1/2] drm-uapi: Sync msm_drm.h Rob Clark
2026-07-03 14:39 ` Rob Clark [this message]
2026-07-06 12:23 ` [PATCH 2/2] tests/msm: Add perfcntrs test Kamil Konieczny
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260703143949.280272-3-rob.clark@oss.qualcomm.com \
--to=rob.clark@oss.qualcomm.com \
--cc=freedreno@lists.freedesktop.org \
--cc=igt-dev@lists.freedesktop.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox