Hi Rob,
On 2026-07-08 at 09:12:24 -0700, Rob Clark wrote:
> Add tests for new PERFCNTR_CONFIG ioctl.
> 
> Signed-off-by: Rob Clark <[email protected]>
> ---
>  tests/msm/meson.build     |   1 +
>  tests/msm/msm_perfcntrs.c | 196 ++++++++++++++++++++++++++++++++++++++
>  2 files changed, 197 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..42f77456939e
> --- /dev/null
> +++ b/tests/msm/msm_perfcntrs.c
> @@ -0,0 +1,196 @@
> +// 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];
> +     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));
> +     /* selecting countable 0 for each counter is fine: */
> +     memset(countables, 0, sizeof(countables));
> +
> +     for (unsigned i = 0; i < nr_groups; i++) {

checkpatch suggest using 'unsigned int'.

> +             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);

Why warn here? It will make your test fail, imho you should use
igt_info() instead.

> +             if (ret < 0)
> +                     return i;

and this imho:
                if (ret < 0) {
                        igt_warn("Unexpected error\n");
                        return i;
                }

> +             if (global)
> +                     close(ret);
> +     }
> +}
> +
> +

One newline is enough.

I will merge this as is with whitespace/style fixes with the help
of checkpatch.pl --fix-inplace. If you want improve test with
above s/warn/info/ please send a fix.

LGTM
Acked-by: Kamil Konieczny <[email protected]>

Regards,
Kamil

> +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.55.0
> 

Reply via email to