From: "Piotr Piórkowski" <piotr.piorkowski@intel.com>
To: Sobin Thomas <sobin.thomas@intel.com>
Cc: <igt-dev@lists.freedesktop.org>, <kamil.konieczny@intel.com>
Subject: Re: [PATCH i-g-t v2] tests/xe_debugfs: Add debugfs entry read/write validation in root-dir
Date: Mon, 15 Jun 2026 12:39:27 +0200 [thread overview]
Message-ID: <20260615103927.sdp7dhfswcjsshnt@intel.com> (raw)
In-Reply-To: <20260615043050.603026-1-sobin.thomas@intel.com>
Sobin Thomas <sobin.thomas@intel.com> wrote on pon [2026-cze-15 04:30:50 +0000]:
> Extend the root-dir subtest to validate additional optional Xe debugfs
> entries. Optional entries are those that may not be present on all
> platforms or configurations — their absence is not treated as a failure.
>
> - dgfx_pkg_residencies: Validate counter reads (non-empty)
> - dgfx_pcie_link_residencies: Validate PCIE LINK string content
> - sriov_info: Validate entry is non-empty
> - workarounds: Validate entry is non-empty
> - atomic_svm_timeslice_ms: Validate integer read/write
> - poor_man_system_atomic_support: Validate boolean read/write
> - disable_late_binding: Validate boolean read/write
>
> v2: Fixed the optional file check and added fail count.
> Replaced igt_debug with igt_info in few places (kamil)
>
> Signed-off-by: Sobin Thomas <sobin.thomas@intel.com>
> ---
> tests/intel/xe_debugfs.c | 198 ++++++++++++++++++++++++++++++++++++---
> 1 file changed, 184 insertions(+), 14 deletions(-)
>
> diff --git a/tests/intel/xe_debugfs.c b/tests/intel/xe_debugfs.c
> index 587e3e785..d92e07092 100644
> --- a/tests/intel/xe_debugfs.c
> +++ b/tests/intel/xe_debugfs.c
> @@ -39,11 +39,24 @@ IGT_TEST_DESCRIPTION("Validate Xe debugfs devnodes and their contents");
> __m && ((__i) = __builtin_ctz(__m), 1); \
> __m &= __m - 1)
>
> +/* Validation types for debugfs read tests */
> +enum debugfs_validate_type {
> + VALIDATE_NONE, /* Just check file exists */
> + VALIDATE_NON_EMPTY, /* Just check buffer is not empty */
> + VALIDATE_CONTAINS_STR, /* Check buffer contains expected string */
> + VALIDATE_INT_GE_ZERO, /* Parse as integer, verify >= 0 */
> + VALIDATE_BOOL, /* Check bool value (0 or 1) */
> +};
> +
> struct check_entry {
> const char *name_fmt;
> int mode;
> - bool (*condition)(struct xe_device *xe_dev);
> + bool optional;
> + bool (*condition)(struct xe_device *xe_dev, void *params);
I don't see any reason to add parameters to the condition at this point, because we don't use
them anywhere in a useful way
> + void *cond_params;
> unsigned int (*iter_mask)(struct xe_device *xe_dev);
> + enum debugfs_validate_type validate;
> + const char *expected_str;
> };
>
> static unsigned int gt_iter_mask(struct xe_device *xe_dev)
> @@ -56,7 +69,7 @@ static unsigned int tile_iter_mask(struct xe_device *xe_dev)
> return xe_dev->tile_mask;
> }
>
> -static bool has_vram(struct xe_device *xe_dev)
> +static bool has_vram_region(struct xe_device *xe_dev, void *params)
> {
> return xe_dev->has_vram;
> }
> @@ -131,6 +144,108 @@ static bool find_not_tested_files(int dir_fd, struct igt_list_head *hit_entries)
> return found_not_tested;
> }
>
> +/* Validate that debugfs buffer is non-empty or contains expected string */
> +static bool validate_string(int dirfd, const char *file_name, const char *expected_str)
> +{
> + char buf[4096];
> + int ret = 0;
> +
> + ret = igt_sysfs_read(dirfd, file_name, buf, sizeof(buf) - 1);
> + if (ret < 0)
> + return false;
> + buf[ret] = '\0';
> +
> + /* Check for empty buffer */
> + if (strlen(buf) == 0) {
> + igt_warn("Empty output from %s\n", file_name);
> + return false;
> + }
> +
> + /* If expecting specific string, verify it's present */
> + if (expected_str && !strstr(buf, expected_str)) {
> + igt_warn("Expected '%s' not found in %s\n", expected_str, file_name);
> + return false;
> + }
> +
> + if (expected_str)
> + igt_debug("Successfully read %s: found '%s'\n", file_name, expected_str);
> + else
> + igt_debug("Successfully read %s: %zd bytes\n%s\n", file_name, strlen(buf), buf);
> +
I understand you were supposed to change igt_debug to igt_info
Thanks,
Piotr
> + return true;
> +}
> +
> +static const char *mode_to_str(int mode)
> +{
> + switch (mode & O_ACCMODE) {
> + case O_RDONLY: return "RO";
> + case O_WRONLY: return "WO";
> + case O_RDWR: return "RW";
> + default: return "UNKNOWN";
> + }
> +}
> +
> +static bool validate_bool_file(int dirfd, const char *file_name, int mode)
> +{
> + int orig_val = 0, read_val = 0, test_val = 0;
> +
> + if (igt_sysfs_scanf(dirfd, file_name, "%d", &orig_val) != 1 ||
> + (orig_val != 0 && orig_val != 1))
> + return false;
> +
> + if (mode == O_RDWR) {
> + test_val = (orig_val == 0) ? 1 : 0;
> +
> + if (igt_sysfs_printf(dirfd, file_name, "%d", test_val) < 0)
> + return false;
> +
> + if (igt_sysfs_scanf(dirfd, file_name, "%d", &read_val) != 1 || read_val != test_val)
> + return false;
> +
> + /* Restore original value */
> + if (igt_sysfs_printf(dirfd, file_name, "%d", orig_val) < 0) {
> + igt_warn("Failed to restore original value for %s\n", file_name);
> + return false;
> + }
> + }
> +
> + igt_info("Successfully validated %s bool %s\n", mode_to_str(mode), file_name);
> + return true;
> +}
> +
> +static bool validate_int_file(int dirfd, const char *file_name, int mode)
> +{
> + long orig_val = 0, new_val = 0, read_val = 0;
> +
> + if (igt_sysfs_scanf(dirfd, file_name, "%ld", &orig_val) != 1)
> + return false;
> +
> + if (orig_val < 0)
> + return false;
> +
> + if (mode == O_RDWR) {
> + new_val = orig_val + 1;
> + if (igt_sysfs_printf(dirfd, file_name, "%ld", new_val) < 0)
> + return false;
> + if (igt_sysfs_scanf(dirfd, file_name, "%ld", &read_val) != 1)
> + return false;
> + if (read_val != new_val)
> + return false;
> + /* Restore original value */
> + if (igt_sysfs_printf(dirfd, file_name, "%ld", orig_val) < 0) {
> + igt_warn("Failed to restore original value for %s\n", file_name);
> + return false;
> + }
> +
> + igt_info("Successfully validated %s int %s: %ld -> %ld -> %ld\n",
> + mode_to_str(mode), file_name, orig_val, new_val, orig_val);
> + } else {
> + igt_info("Successfully validated %s int %s: %ld\n",
> + mode_to_str(mode), file_name, orig_val);
> + }
> + return true;
> +}
> +
> static bool file_in_dir_exists(int dirfd, const char *file_name, int mode)
> {
> int fd = openat(dirfd, file_name, mode);
> @@ -139,10 +254,39 @@ static bool file_in_dir_exists(int dirfd, const char *file_name, int mode)
> close(fd);
> return true;
> }
> -
> return false;
> }
>
> +static bool validate_debugfs_file(int dirfd, const char *file_name, int mode,
> + enum debugfs_validate_type validate, const char *expected_str)
> +{
> + bool result = true;
> +
> + if (validate == VALIDATE_NONE)
> + return true;
> +
> + switch (validate) {
> + case VALIDATE_NON_EMPTY:
> + result = validate_string(dirfd, file_name, NULL);
> + break;
> + case VALIDATE_CONTAINS_STR:
> + result = validate_string(dirfd, file_name, expected_str);
> + break;
> + case VALIDATE_INT_GE_ZERO:
> + result = validate_int_file(dirfd, file_name, mode);
> + break;
> + case VALIDATE_BOOL:
> + result = validate_bool_file(dirfd, file_name, mode);
> + break;
> + default:
> + igt_warn("Unknown validate type %d for %s\n", validate, file_name);
> + result = false;
> + break;
> + }
> +
> + return result;
> +}
> +
> /*
> * Return: negative error code on failure, or number of missing files
> */
> @@ -151,6 +295,7 @@ static int debugfs_validate_entries(struct xe_device *xe_dev, int dir_fd,
> {
> struct igt_list_head hit_entries;
> int missing_count = 0;
> + int fail_count = 0;
> int err = 0;
>
> IGT_INIT_LIST_HEAD(&hit_entries);
> @@ -160,7 +305,7 @@ static int debugfs_validate_entries(struct xe_device *xe_dev, int dir_fd,
> unsigned int mask;
> unsigned int j;
>
> - if (check->condition && !check->condition(xe_dev))
> + if (check->condition && !check->condition(xe_dev, check->cond_params))
> continue;
>
> if (!check->iter_mask)
> @@ -210,9 +355,20 @@ static int debugfs_validate_entries(struct xe_device *xe_dev, int dir_fd,
> }
>
> if (!file_in_dir_exists(dir_fd, entry->name, check->mode)) {
> - igt_warn("Missing debugfs file: %s\n", entry->name);
> - missing_count++;
> + if (check->optional) {
> + igt_info("Optional entry %s not found (skipped)\n",
> + entry->name);
> + } else {
> + igt_info("Missing debugfs file: %s\n",
> + entry->name);
> + missing_count++;
> + }
> + } else {
> + if (!validate_debugfs_file(dir_fd, entry->name, check->mode,
> + check->validate, check->expected_str))
> + fail_count++;
> }
> +
> }
> }
>
> @@ -229,7 +385,10 @@ out:
> }
> }
>
> - return (err < 0) ? err : missing_count;
> + if (fail_count || missing_count)
> + igt_warn("Fails: %d missing debugfs file(s): %d\n", fail_count, missing_count);
> +
> + return (err < 0) ? err : (missing_count + fail_count);
> }
>
> /**
> @@ -239,14 +398,25 @@ out:
> static void test_root_dir(struct xe_device *xe_dev)
> {
> const struct check_entry expected_files[] = {
> - { "clients", O_RDONLY },
> + { "clients", O_RDONLY, .validate = VALIDATE_NON_EMPTY },
> + { "disable_late_binding", O_RDWR, .optional = true, .validate = VALIDATE_BOOL },
> { "forcewake_all", O_WRONLY },
> { "gem_names", O_RDONLY },
> - { "gt%u", O_RDONLY, NULL, gt_iter_mask }, /* gt0, gt1, ... */
> - { "gtt_mm", O_RDONLY },
> - { "info", O_RDONLY },
> - { "name", O_RDONLY },
> - { "tile%u", O_RDONLY, NULL, tile_iter_mask }, /* tile0, tile1, ... */
> + { "gt%u", O_RDONLY, .iter_mask = gt_iter_mask },
> + { "gtt_mm", O_RDONLY, },
> + { "info", O_RDONLY, .validate = VALIDATE_NON_EMPTY },
> + { "name", O_RDONLY, .validate = VALIDATE_NON_EMPTY },
> + { "poor_man_system_atomic_support", O_RDWR, .optional = true,
> + .validate = VALIDATE_BOOL },
> + { "dgfx_pkg_residencies", O_RDONLY, .optional = true,
> + .validate = VALIDATE_NON_EMPTY },
> + { "dgfx_pcie_link_residencies", O_RDONLY, .optional = true,
> + .validate = VALIDATE_CONTAINS_STR, .expected_str = "PCIE LINK" },
> + { "sriov_info", O_RDONLY, .optional = true, .validate = VALIDATE_NON_EMPTY },
> + { "workarounds", O_RDONLY, .optional = true, .validate = VALIDATE_NON_EMPTY },
> + { "atomic_svm_timeslice_ms", O_RDWR, .optional = true,
> + .validate = VALIDATE_INT_GE_ZERO },
> + { "tile%u", O_RDONLY, .iter_mask = tile_iter_mask },
> };
> int debugfs_fd = igt_debugfs_dir(xe_dev->fd);
> int missing_count;
> @@ -276,7 +446,7 @@ static void test_tile_dir(struct xe_device *xe_dev, uint8_t tile)
> const struct check_entry expected_files[] = {
> { "ggtt", O_RDONLY },
> { "sa_info", O_RDONLY },
> - { "vram_mm", O_RDONLY, has_vram },
> + { "vram_mm", O_RDONLY, .condition = has_vram_region, .cond_params = (void *)&tile },
> };
> int debugfs_fd = igt_debugfs_tile_dir(xe_dev->fd, tile);
> int missing_count;
> --
> 2.52.0
>
--
next prev parent reply other threads:[~2026-06-15 10:39 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-15 4:30 [PATCH i-g-t v2] tests/xe_debugfs: Add debugfs entry read/write validation in root-dir Sobin Thomas
2026-06-15 5:33 ` ✓ Xe.CI.BAT: success for tests/xe_debugfs: Add debugfs entry read/write validation in root-dir (rev3) Patchwork
2026-06-15 5:48 ` ✓ i915.CI.BAT: " Patchwork
2026-06-15 6:32 ` ✓ Xe.CI.FULL: " Patchwork
2026-06-15 7:43 ` ✓ i915.CI.Full: " Patchwork
2026-06-15 10:39 ` Piotr Piórkowski [this message]
2026-06-15 11:10 ` [PATCH i-g-t v2] tests/xe_debugfs: Add debugfs entry read/write validation in root-dir Jani Nikula
2026-06-15 12:02 ` Kamil Konieczny
2026-06-15 12:58 ` Jani Nikula
2026-06-15 13:25 ` Kamil Konieczny
2026-06-15 15:01 ` Jani Nikula
2026-06-15 11:16 ` 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=20260615103927.sdp7dhfswcjsshnt@intel.com \
--to=piotr.piorkowski@intel.com \
--cc=igt-dev@lists.freedesktop.org \
--cc=kamil.konieczny@intel.com \
--cc=sobin.thomas@intel.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.