public inbox for igt-dev@lists.freedesktop.org
 help / color / mirror / Atom feed
* [PATCH v3 i-g-t 00/10] Xe SR-IOV admin scheduling helpers and test updates
@ 2026-01-28 18:08 Marcin Bernatowicz
  2026-01-28 18:08 ` [PATCH v3 i-g-t 01/10] lib/igt_sysfs_choice: Add helpers for sysfs enumerated choice attributes Marcin Bernatowicz
                   ` (11 more replies)
  0 siblings, 12 replies; 19+ messages in thread
From: Marcin Bernatowicz @ 2026-01-28 18:08 UTC (permalink / raw)
  To: igt-dev
  Cc: adam.miszczak, jakub1.kolakowski, lukasz.laguna, michal.wajdeczko,
	Marcin Bernatowicz

This v3 series introduces a generic helper for sysfs "choice" attributes
and wires Xe SR-IOV scheduling helpers and tests to the SR-IOV admin
sysfs interface.

Patches 1–2 add igt_sysfs_choice and unit tests for parsing and
formatting enumerated sysfs values such as sched_priority.
Patches 3–4 convert the existing sched_priority helpers in
xe_sriov_provisioning into thin wrappers around igt_sysfs_choice.
Patch 5 adds a small PF/VF sysfs path helper used by the SR-IOV code.
Patch 6 exposes SR-IOV admin sysfs accessors for execution quantum,
preemption timeout, scheduling priority, VF stop and restoring defaults,
following recent kernel changes:

Link: https://lore.kernel.org/intel-xe/20251030222348.186658-1-michal.wajdeczko@intel.com/

Patches 7–10 update the xe_sriov_scheduling and xe_pmu tests to prefer
the admin interface, improve cleanup, and add coverage for SR-IOV
admin sysfs scheduling attributes in xe_sriov_admin_profile.

v2 -> v3:
- Renamed the xe_sriov_admin_profile test binary to xe_sriov_admin.
- Made SR-IOV admin accessor naming consistent (__xe_sriov_admin_* /
  xe_sriov_admin_*) and updated all users.
- Expanded sched_priority negative coverage by trying all available tokens
  when validating VF write-denied behavior.
- Switched mask formatting helpers to return explicit error codes
  and adjusted callers/tests accordingly.
- Minor logging improvements and formatting fixes.

v1 -> v2:
- Added generic igt_sysfs_choice helper and unit tests.
- Reworked sched_priority helpers to use igt_sysfs_choice wrappers.
- Introduced igt_sriov_func_str() PF/VF sysfs path helper.
- Extended SR-IOV admin helpers with scheduling accessors.
- Updated xe_sriov_scheduling and xe_pmu to prefer SR-IOV admin sysfs.
- Added xe_sriov_admin_profile tests for admin sysfs scheduling
  attributes (defaults, write->readback, bulk updates).


Marcin Bernatowicz (10):
  lib/igt_sysfs_choice: Add helpers for sysfs enumerated choice
    attributes
  lib/tests/igt_sysfs_choice: Add test coverage
  lib/xe/xe_sriov_provisioning: Add string conversion helpers for
    scheduling priority
  lib/xe/xe_sriov_provisioning: Add sched priority mask to string helper
  lib/igt_sriov_device: Add helper for PF/VF sysfs path formatting
  lib/xe/xe_sriov_admin: Add SR-IOV admin sysfs accessors
  tests/intel/xe_sriov_scheduling: Avoid assert on scheduling params
    restore in cleanup
  tests/intel/xe_sriov_scheduling: Prefer SR-IOV admin sysfs accessors
  tests/intel/xe_pmu: Prefer SR-IOV admin sysfs accessors
  tests/intel/xe_sriov_admin: Add SR-IOV admin sysfs scheduling
    attributes tests

 lib/igt_sriov_device.c            |  19 +
 lib/igt_sriov_device.h            |   1 +
 lib/igt_sysfs_choice.c            | 439 +++++++++++++++++++++
 lib/igt_sysfs_choice.h            |  52 +++
 lib/meson.build                   |   2 +
 lib/tests/igt_sysfs_choice.c      | 388 +++++++++++++++++++
 lib/tests/meson.build             |   1 +
 lib/xe/xe_sriov_admin.c           | 625 ++++++++++++++++++++++++++++++
 lib/xe/xe_sriov_admin.h           |  60 +++
 lib/xe/xe_sriov_provisioning.c    | 105 +++++
 lib/xe/xe_sriov_provisioning.h    |  15 +
 tests/intel/xe_pmu.c              |  43 +-
 tests/intel/xe_sriov_admin.c      | 434 +++++++++++++++++++++
 tests/intel/xe_sriov_scheduling.c |  43 +-
 tests/meson.build                 |   1 +
 15 files changed, 2195 insertions(+), 33 deletions(-)
 create mode 100644 lib/igt_sysfs_choice.c
 create mode 100644 lib/igt_sysfs_choice.h
 create mode 100644 lib/tests/igt_sysfs_choice.c
 create mode 100644 lib/xe/xe_sriov_admin.c
 create mode 100644 lib/xe/xe_sriov_admin.h
 create mode 100644 tests/intel/xe_sriov_admin.c

-- 
2.43.0


^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH v3 i-g-t 01/10] lib/igt_sysfs_choice: Add helpers for sysfs enumerated choice attributes
  2026-01-28 18:08 [PATCH v3 i-g-t 00/10] Xe SR-IOV admin scheduling helpers and test updates Marcin Bernatowicz
@ 2026-01-28 18:08 ` Marcin Bernatowicz
  2026-01-29  8:19   ` Laguna, Lukasz
  2026-01-28 18:08 ` [PATCH v3 i-g-t 02/10] lib/tests/igt_sysfs_choice: Add test coverage Marcin Bernatowicz
                   ` (10 subsequent siblings)
  11 siblings, 1 reply; 19+ messages in thread
From: Marcin Bernatowicz @ 2026-01-28 18:08 UTC (permalink / raw)
  To: igt-dev
  Cc: adam.miszczak, jakub1.kolakowski, lukasz.laguna, michal.wajdeczko,
	Marcin Bernatowicz, Kamil Konieczny

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=y, Size: 14865 bytes --]

Introduce igt_sysfs_choice, a lightweight, fixed-size, no-malloc helper
for parsing and formatting sysfs "choice" attributes of the form:

    "low [normal] high\n"

The helper provides parsing, lookup, formatting, mask conversion, and
intersection utilities for consistent handling of enumerated sysfs values.

Suggested-by: Michal Wajdeczko <michal.wajdeczko@intel.com>
Signed-off-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
Cc: Adam Miszczak <adam.miszczak@linux.intel.com>
Cc: Jakub Kolakowski <jakub1.kolakowski@intel.com>
Cc: Kamil Konieczny <kamil.konieczny@linux.intel.com>
Cc: Lukasz Laguna <lukasz.laguna@intel.com>
Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>

---
v2:
- Corrected date
- Fix documentation formatting/description.
- Make igt_sysfs_choice_to_string() return error code instead of NULL.
- Use names_sz consistently.
- Make igt_sysfs_choice_format_mask() return error code instead of NULL.

Signed-off-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
---
 lib/igt_sysfs_choice.c | 439 +++++++++++++++++++++++++++++++++++++++++
 lib/igt_sysfs_choice.h |  52 +++++
 lib/meson.build        |   1 +
 3 files changed, 492 insertions(+)
 create mode 100644 lib/igt_sysfs_choice.c
 create mode 100644 lib/igt_sysfs_choice.h

diff --git a/lib/igt_sysfs_choice.c b/lib/igt_sysfs_choice.c
new file mode 100644
index 000000000..5ce2a2b70
--- /dev/null
+++ b/lib/igt_sysfs_choice.c
@@ -0,0 +1,439 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2026 Intel Corporation
+ */
+#include "igt_sysfs_choice.h"
+#include <ctype.h>
+#include <errno.h>
+#include "igt_core.h"
+#include "igt_sysfs.h"
+
+#define IGT_SYSFS_CHOICE_MAX_LEN 256
+#define IGT_SYSFS_CHOICE_MAX_TOKENS 16
+
+/**
+ * igt_sysfs_choice_parse() - parse sysfs enumerated choice buffer
+ * @buf: NUL-terminated buffer with sysfs contents
+ * @choice: output descriptor, must be non-NULL (can be zeroed)
+ *
+ * Parses a sysfs enumerated choice buffer, e.g.:
+ *
+ *	"low [normal] high\n"
+ *
+ * into a token list and the index of the selected token.
+ *
+ * Parsing rules:
+ *  - tokens are separated by ASCII whitespace
+ *  - exactly one token must be wrapped in '[' and ']'
+ *  - surrounding '[' and ']' are stripped from the selected token
+ *  - empty tokens are treated as malformed input
+ *
+ * On entry, any previous contents of @choice are freed.
+ *
+ * Returns:
+ *  0        on success,
+ *  -EINVAL  malformed format (no tokens, no selected token, multiple
+ *           selected tokens, unterminated '[' or ']'),
+ *  -E2BIG   on too many tokens or too small choice buffer size.
+ */
+int igt_sysfs_choice_parse(const char *buf, struct igt_sysfs_choice *choice)
+{
+	char *p, *tok_start;
+	bool selected_seen = false;
+	size_t num_tokens = 0;
+	int n, selected = -1;
+	bool is_selected;
+
+	igt_assert(buf && choice);
+
+	memset(choice, 0, sizeof(*choice));
+	n = snprintf(choice->buf, sizeof(choice->buf), "%s", buf);
+	if (igt_debug_on(n < 0))
+		return -EINVAL;
+	if (igt_debug_on((size_t)n >= sizeof(choice->buf)))
+		return -E2BIG;
+
+	choice->num_tokens = 0;
+	choice->selected = -1;
+	p = choice->buf;
+
+	while (*p) {
+		/* skip leading whitespace */
+		while (*p && isspace((unsigned char)*p))
+			p++;
+		if (!*p)
+			break;
+
+		is_selected = false;
+		tok_start = p;
+
+		if (*p == '[') {
+			is_selected = true;
+			p++;
+			tok_start = p;
+
+			if (selected_seen) {
+				igt_debug("choice-parse: multiple [selected] tokens: \"%s\"\n",
+					  choice->buf);
+				return -EINVAL;
+			}
+			selected_seen = true;
+		}
+
+		/* walk until ']' or whitespace */
+		while (*p && !isspace((unsigned char)*p) && *p != ']')
+			p++;
+
+		if (is_selected) {
+			if (*p != ']') {
+				igt_debug("choice-parse: unterminated '[' in: \"%s\"\n",
+					  choice->buf);
+				return -EINVAL;
+			}
+		}
+
+		/* terminate token */
+		if (*p) {
+			*p = '\0';
+			p++;
+		}
+
+		if (!*tok_start) {
+			igt_debug("choice-parse: empty token in: \"%s\"\n",
+				  choice->buf);
+			return -EINVAL;
+		}
+
+		if (num_tokens >= IGT_SYSFS_CHOICE_MAX_TOKENS) {
+			igt_debug("choice-parse: too many tokens (>%d) in: \"%s\"\n",
+				  IGT_SYSFS_CHOICE_MAX_TOKENS, choice->buf);
+			return -E2BIG;
+		}
+
+		choice->tokens[num_tokens] = tok_start;
+		if (is_selected)
+			selected = (int)num_tokens;
+
+		num_tokens++;
+	}
+
+	if (!num_tokens) {
+		igt_debug("choice-parse: no tokens in string: \"%s\"\n",
+			  choice->buf);
+		return -EINVAL;
+	}
+
+	if (selected < 0) {
+		igt_debug("choice-parse: missing selected token ([...]) in: \"%s\"\n",
+			  choice->buf);
+		return -EINVAL;
+	}
+
+	choice->num_tokens = num_tokens;
+	choice->selected = selected;
+
+	return 0;
+}
+
+/**
+ * igt_sysfs_choice_read() - read and parse a sysfs enumerated choice attribute
+ * @dirfd: directory file descriptor of the sysfs node
+ * @attr: attribute name relative to @dirfd
+ * @choice: output descriptor, must be non-NULL
+ *
+ * Reads the given sysfs attribute into a temporary buffer and parses it.
+ *
+ * Returns:
+ *  0 on success,
+ *  negative errno-style value on read or parse error.
+ */
+int igt_sysfs_choice_read(int dirfd, const char *attr,
+			  struct igt_sysfs_choice *choice)
+{
+	char buf[IGT_SYSFS_CHOICE_MAX_LEN];
+	int len;
+
+	len = igt_sysfs_read(dirfd, attr, buf, sizeof(buf) - 1);
+	if (len < 0)
+		return len;
+
+	buf[len] = '\0';
+
+	return igt_sysfs_choice_parse(buf, choice);
+}
+
+/**
+ * igt_sysfs_choice_selected() - Return selected token string
+ * @choice: Parsed choice
+ *
+ * Returns:
+ *   Pointer to the selected token string, or NULL if no valid selection.
+ */
+const char *igt_sysfs_choice_selected(const struct igt_sysfs_choice *choice)
+{
+	if (!choice || choice->selected < 0 ||
+	    (size_t)choice->selected >= choice->num_tokens)
+		return NULL;
+
+	return choice->tokens[choice->selected];
+}
+
+/**
+ * igt_sysfs_choice_to_string() - Render a parsed choice into string
+ * @choice:   Parsed choice (tokens[] + selected index)
+ * @buf:      Output buffer for formatted string
+ * @buf_sz:   Size of @buf in bytes
+ *
+ * Formats the given @choice into the string:
+ *
+ *	"low [normal] high"
+ *
+ * Tokens are emitted in the order stored in @choice->tokens.  The
+ * selected token (choice->selected) is wrapped in '[' and ']'.
+ *
+ * Returns:
+ *   0        on success,
+ *   -EINVAL  if arguments are invalid,
+ *   -E2BIG   if @buf_sz is too small.
+ */
+int igt_sysfs_choice_to_string(const struct igt_sysfs_choice *choice,
+			       char *buf, size_t buf_sz)
+{
+	bool first = true;
+	size_t pos = 0;
+	int n;
+
+	if (!choice || !buf || !buf_sz)
+		return -EINVAL;
+
+	buf[0] = '\0';
+
+	for (size_t i = 0; i < choice->num_tokens; i++) {
+		const char *name = choice->tokens[i];
+		bool is_selected = (choice->selected == (int)i);
+
+		if (!name)
+			continue;
+
+		n = snprintf(buf + pos, buf_sz - pos,
+			     "%s%s%s%s",
+			     first ? "" : " ",
+			     is_selected ? "[" : "",
+			     name,
+			     is_selected ? "]" : "");
+
+		if (n < 0)
+			return -EINVAL;
+		if ((size_t)n >= buf_sz - pos)
+			return -E2BIG;
+
+		pos += (size_t)n;
+		first = false;
+	}
+
+	return 0;
+}
+
+/**
+ * igt_sysfs_choice_find() - find token index by name
+ * @choice: parsed choice struct
+ * @token: token to look for (plain name, without '[' / ']')
+ *
+ * Performs a case-sensitive comparison of @token against entries in
+ * @choice->tokens.
+ *
+ * Returns:
+ *  index in [0..choice->num_tokens-1] on match,
+ *  -1 if @token is not present or @choice/@token is NULL.
+ */
+int igt_sysfs_choice_find(const struct igt_sysfs_choice *choice,
+			  const char *token)
+{
+	if (!choice || !token)
+		return -1;
+
+	for (size_t i = 0; i < choice->num_tokens; i++)
+		if (!strcmp(choice->tokens[i], token))
+			return (int)i;
+
+	return -1;
+}
+
+/**
+ * igt_sysfs_choice_to_mask() - map parsed tokens to bitmask + selection
+ * @choice: parsed choice struct
+ * @names: array of known token names
+ * @names_sz: number of elements in @names
+ * @mask: output bitmask of supported names
+ * @selected_idx: output index of selected token in @names, or -1 if selected
+ *                token is not among @names
+ *
+ * Builds a bitmask of known tokens present in @choice and identifies the
+ * selected token, if it matches one of @names.
+ *
+ * Unknown tokens do not cause an error; they are ignored and not
+ * reflected in @mask. This keeps the API "loose": tests can still
+ * validate required choices while tolerating additional values.
+ *
+ * Returns:
+ *  0        on success,
+ *  -EINVAL  on bad input parameters.
+ */
+int igt_sysfs_choice_to_mask(const struct igt_sysfs_choice *choice,
+			     const char * const *names, size_t names_sz,
+			     unsigned int *mask, int *selected_idx)
+{
+	unsigned int m = 0;
+	int sel = -1, idx;
+
+	if (!choice || !names || !mask)
+		return -EINVAL;
+
+	for (size_t i = 0; i < names_sz; i++) {
+		const char *name = names[i];
+
+		if (!name)
+			continue;
+
+		idx = igt_sysfs_choice_find(choice, name);
+		if (idx >= 0) {
+			m |= 1u << i;
+			if (idx == choice->selected)
+				sel = (int)i;
+		}
+	}
+
+	*mask = m;
+	if (selected_idx)
+		*selected_idx = sel;
+
+	return 0;
+}
+
+/**
+ * igt_sysfs_choice_format_mask() - Format a bitmask as a space-separated list of names
+ * @buf: Output buffer
+ * @buf_sz: Size of @buf in bytes
+ * @names: Array of token names indexed by bit position
+ * @names_sz: Number of elements in @names
+ * @mask: Bitmask of available tokens
+ * @selected_idx: Index to highlight with brackets, or <0 for none
+ *
+ * Builds a space-separated list of all bits set in @mask, mapping bit positions
+ * to names in @names. If @selected_idx >= 0 and that bit is set, the token is
+ * wrapped in brackets, e.g. "low [normal] high".
+ *
+ * This function is best-effort by design:
+ *  - If names[i] is NULL, it is formatted as "?".
+ *  - Bits beyond @names_sz are ignored.
+ * Empty @mask results in an empty string.
+ *
+ * Returns:
+ *  0        on success,
+ *  -EINVAL  on invalid arguments,
+ *  -E2BIG   if @buf_sz is too small.
+ */
+int igt_sysfs_choice_format_mask(char *buf, size_t buf_sz,
+				 const char *const *names,
+				 size_t names_sz,
+				 unsigned int mask,
+				 int selected_idx)
+{
+	bool first = true;
+	size_t pos = 0;
+
+	if (!buf || !buf_sz || !names || !names_sz)
+		return -EINVAL;
+
+	buf[0] = '\0';
+
+	for (size_t idx = 0; idx < names_sz && mask; idx++) {
+		int n;
+		const char *name;
+		bool highlight;
+
+		if (!(mask & 1u)) {
+			mask >>= 1;
+			continue;
+		}
+
+		name = names[idx] ?: "?";
+		highlight = ((int)idx == selected_idx);
+		n = snprintf(buf + pos, buf_sz - pos, "%s%s%s%s",
+			     first ? "" : " ",
+			     highlight ? "[" : "",
+			     name,
+			     highlight ? "]" : "");
+		if (n < 0)
+			return -EINVAL;
+		if ((size_t)n >= buf_sz - pos)
+			return -E2BIG;
+
+		pos += (size_t)n;
+		first = false;
+		mask >>= 1;
+	}
+
+	return 0;
+}
+
+/**
+ * igt_sysfs_choice_intersect() - Restrict a choice set to tokens common with another
+ * @dst:   Choice to be updated in place
+ * @other: Choice providing the allowed tokens
+ *
+ * Computes the intersection of the token sets in @dst and @other.
+ * The resulting @dst contains only tokens that appear in both choices,
+ * preserving their original order from @dst.
+ *
+ * If the previously selected token in @dst is still present after
+ * intersection, its index is updated accordingly.  If it is not present,
+ * @dst->selected is set to -1.
+ *
+ * Returns:
+ * * 0        - success
+ * * -EINVAL  - invalid arguments
+ * * -ENOENT  - no common tokens
+ */
+int igt_sysfs_choice_intersect(struct igt_sysfs_choice *dst,
+			       const struct igt_sysfs_choice *other)
+{
+	char *new_tokens[IGT_SYSFS_CHOICE_MAX_TOKENS];
+	const char *selected_name;
+	int new_selected = -1;
+	size_t new_n = 0;
+
+	if (!dst || !other)
+		return -EINVAL;
+
+	selected_name = (dst->selected >= 0 && dst->selected < dst->num_tokens) ?
+			 dst->tokens[dst->selected] : NULL;
+
+	for (size_t i = 0; i < dst->num_tokens; i++) {
+		char *tok = dst->tokens[i];
+
+		if (igt_sysfs_choice_find(other, tok) < 0)
+			continue;
+
+		new_tokens[new_n] = tok;
+
+		if (selected_name && !strcmp(tok, selected_name))
+			new_selected = (int)new_n;
+
+		new_n++;
+	}
+
+	if (!new_n) {
+		dst->num_tokens = 0;
+		dst->selected = -1;
+		return -ENOENT;
+	}
+
+	for (size_t i = 0; i < new_n; i++)
+		dst->tokens[i] = new_tokens[i];
+
+	dst->num_tokens = new_n;
+	dst->selected = new_selected;
+
+	return 0;
+}
diff --git a/lib/igt_sysfs_choice.h b/lib/igt_sysfs_choice.h
new file mode 100644
index 000000000..b354c774a
--- /dev/null
+++ b/lib/igt_sysfs_choice.h
@@ -0,0 +1,52 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2026 Intel Corporation
+ */
+#ifndef __IGT_SYSFS_CHOICE_H__
+#define __IGT_SYSFS_CHOICE_H__
+
+#include <stddef.h>
+#include <stdbool.h>
+
+#define IGT_SYSFS_CHOICE_MAX_LEN    256
+#define IGT_SYSFS_CHOICE_MAX_TOKENS 16
+
+/**
+ * struct igt_sysfs_choice - parsed sysfs enumerated choice attribute
+ * @tokens:      array of token strings
+ * @num_tokens:  number of entries in @tokens
+ * @selected:    index of the active token in @tokens, or -1 if invalid
+ *
+ * This struct represents a sysfs enumerated choice attribute, for example:
+ *
+ *	"low [normal] high\n"
+ *
+ * After parsing, @tokens point to "low", "normal", "high" and
+ * @selected will be 1 (the index of "normal").
+ */
+struct igt_sysfs_choice {
+	char    buf[IGT_SYSFS_CHOICE_MAX_LEN];
+	char   *tokens[IGT_SYSFS_CHOICE_MAX_TOKENS];
+	size_t  num_tokens;
+	int     selected; /* index into tokens[], or -1 */
+};
+
+int igt_sysfs_choice_parse(const char *buf, struct igt_sysfs_choice *choice);
+int igt_sysfs_choice_read(int dirfd, const char *attr,
+			  struct igt_sysfs_choice *choice);
+const char *igt_sysfs_choice_selected(const struct igt_sysfs_choice *choice);
+int igt_sysfs_choice_to_string(const struct igt_sysfs_choice *choice,
+			       char *buf, size_t buf_sz);
+int igt_sysfs_choice_find(const struct igt_sysfs_choice *choice,
+			  const char *token);
+int igt_sysfs_choice_to_mask(const struct igt_sysfs_choice *choice,
+			     const char *const *names, size_t names_sz,
+			     unsigned int *mask, int *selected_idx);
+int igt_sysfs_choice_format_mask(char *buf, size_t buf_sz,
+				 const char *const *names,
+				 size_t names_sz, unsigned int mask,
+				 int selected_idx);
+int igt_sysfs_choice_intersect(struct igt_sysfs_choice *dst,
+			       const struct igt_sysfs_choice *other);
+
+#endif /* __IGT_SYSFS_CHOICE_H__ */
diff --git a/lib/meson.build b/lib/meson.build
index 1a569ba52..83569e8d2 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -44,6 +44,7 @@ lib_sources = [
 	'igt_stats.c',
 	'igt_syncobj.c',
 	'igt_sysfs.c',
+	'igt_sysfs_choice.c',
 	'igt_sysrq.c',
 	'igt_taints.c',
 	'igt_thread.c',
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v3 i-g-t 02/10] lib/tests/igt_sysfs_choice: Add test coverage
  2026-01-28 18:08 [PATCH v3 i-g-t 00/10] Xe SR-IOV admin scheduling helpers and test updates Marcin Bernatowicz
  2026-01-28 18:08 ` [PATCH v3 i-g-t 01/10] lib/igt_sysfs_choice: Add helpers for sysfs enumerated choice attributes Marcin Bernatowicz
@ 2026-01-28 18:08 ` Marcin Bernatowicz
  2026-01-29  8:19   ` Laguna, Lukasz
  2026-01-28 18:08 ` [PATCH v3 i-g-t 03/10] lib/xe/xe_sriov_provisioning: Add string conversion helpers for scheduling priority Marcin Bernatowicz
                   ` (9 subsequent siblings)
  11 siblings, 1 reply; 19+ messages in thread
From: Marcin Bernatowicz @ 2026-01-28 18:08 UTC (permalink / raw)
  To: igt-dev
  Cc: adam.miszczak, jakub1.kolakowski, lukasz.laguna, michal.wajdeczko,
	Marcin Bernatowicz, Kamil Konieczny

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=y, Size: 10866 bytes --]

Add unit tests exercising parsing, selection rules, intersection,
round-trip formatting, and mask conversion for igt_sysfs_choice.

Signed-off-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
Cc: Adam Miszczak <adam.miszczak@linux.intel.com>
Cc: Jakub Kolakowski <jakub1.kolakowski@intel.com>
Cc: Kamil Konieczny <kamil.konieczny@linux.intel.com>
Cc: Lukasz Laguna <lukasz.laguna@intel.com>
Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>

---
v2:
- Align igt_simple_main() usage with upstream changes.
- Corrected date, improved assert messages.
- Use BIT() instead of (1u << n) for sysfs choice masks.
- Adjust test for igt_sysfs_choice_to_string() returning error code.
- Adjust test for igt_sysfs_choice_format_mask() returning error code.

Signed-off-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
---
 lib/tests/igt_sysfs_choice.c | 388 +++++++++++++++++++++++++++++++++++
 lib/tests/meson.build        |   1 +
 2 files changed, 389 insertions(+)
 create mode 100644 lib/tests/igt_sysfs_choice.c

diff --git a/lib/tests/igt_sysfs_choice.c b/lib/tests/igt_sysfs_choice.c
new file mode 100644
index 000000000..c573a0dff
--- /dev/null
+++ b/lib/tests/igt_sysfs_choice.c
@@ -0,0 +1,388 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2026 Intel Corporation
+ */
+#include <errno.h>
+#include "drmtest.h"
+#include "igt_core.h"
+#include "intel_chipset.h"
+#include "igt_sysfs_choice.h"
+
+static void assert_token(const struct igt_sysfs_choice *c,
+			 size_t idx, const char *expected)
+{
+	igt_assert_f(idx < c->num_tokens,
+		     "token index %zu out of range (num_tokens=%zu)\n",
+		     idx, c->num_tokens);
+	igt_assert(c->tokens[idx]);
+	igt_assert_f(!strcmp(c->tokens[idx], expected),
+		     "token[%zu] mismatch: got='%s' expected='%s'\n",
+		     idx, c->tokens[idx], expected);
+}
+
+static void parse_ok(const char *str, struct igt_sysfs_choice *choice)
+{
+	int ret;
+
+	ret = igt_sysfs_choice_parse(str, choice);
+	igt_assert_f(ret == 0, "parse(\"%s\") failed: %d\n", str, ret);
+}
+
+static void test_parse_basic_first_selected(void)
+{
+	struct igt_sysfs_choice c;
+
+	parse_ok("[low] normal high\n", &c);
+
+	igt_assert_eq(c.num_tokens, 3);
+	assert_token(&c, 0, "low");
+	assert_token(&c, 1, "normal");
+	assert_token(&c, 2, "high");
+
+	igt_assert_eq(c.selected, 0);
+}
+
+static void test_parse_middle_selected_whitespace(void)
+{
+	struct igt_sysfs_choice c;
+
+	parse_ok("  low   [normal]   high  \n", &c);
+
+	igt_assert_eq(c.num_tokens, 3);
+	assert_token(&c, 0, "low");
+	assert_token(&c, 1, "normal");
+	assert_token(&c, 2, "high");
+
+	igt_assert_eq(c.selected, 1);
+}
+
+static void test_parse_single_token(void)
+{
+	struct igt_sysfs_choice c;
+
+	parse_ok("[only]\n", &c);
+
+	igt_assert_eq(c.num_tokens, 1);
+	assert_token(&c, 0, "only");
+	igt_assert_eq(c.selected, 0);
+}
+
+static void test_parse_error_missing_selected(void)
+{
+	struct igt_sysfs_choice c;
+	int ret;
+
+	ret = igt_sysfs_choice_parse("low normal high\n", &c);
+	igt_assert_eq(ret, -EINVAL);
+}
+
+static void test_parse_error_multiple_selected(void)
+{
+	struct igt_sysfs_choice c;
+	int ret;
+
+	ret = igt_sysfs_choice_parse("[low] [normal] high\n", &c);
+	igt_assert_eq(ret, -EINVAL);
+
+	ret = igt_sysfs_choice_parse("low [normal] [high]\n", &c);
+	igt_assert_eq(ret, -EINVAL);
+}
+
+static void test_parse_error_unterminated_bracket(void)
+{
+	struct igt_sysfs_choice c;
+	int ret;
+
+	ret = igt_sysfs_choice_parse("[low normal high\n", &c);
+	igt_assert_eq(ret, -EINVAL);
+
+	ret = igt_sysfs_choice_parse("low [normal high]\n", &c);
+	igt_assert_eq(ret, -EINVAL);
+}
+
+static void test_parse_error_too_many_tokens(void)
+{
+	struct igt_sysfs_choice c;
+	char buf[512];
+	size_t i;
+	int len = 0;
+	int ret;
+
+	/*
+	 * Build a line with (IGT_SYSFS_CHOICE_MAX_TOKENS + 1) tokens:
+	 * "[t0] t1 t2 ... tN"
+	 */
+	len += snprintf(buf + len, sizeof(buf) - len, "[t0]");
+	for (i = 1; i < IGT_SYSFS_CHOICE_MAX_TOKENS + 1 && len < (int)sizeof(buf); i++)
+		len += snprintf(buf + len, sizeof(buf) - len, " t%zu", i);
+	len += snprintf(buf + len, sizeof(buf) - len, "\n");
+
+	ret = igt_sysfs_choice_parse(buf, &c);
+	igt_assert_eq(ret, -E2BIG);
+}
+
+static void test_selected_basic(void)
+{
+	struct igt_sysfs_choice c;
+	const char *sel;
+
+	/* selected at position 0 */
+	parse_ok("[low] normal high\n", &c);
+	sel = igt_sysfs_choice_selected(&c);
+	igt_assert(sel);
+	igt_assert(!strcmp(sel, "low"));
+
+	/* selected at position 1 */
+	parse_ok("low [normal] high\n", &c);
+	sel = igt_sysfs_choice_selected(&c);
+	igt_assert(sel);
+	igt_assert(!strcmp(sel, "normal"));
+
+	/* selected at position 2 */
+	parse_ok("low normal [high]\n", &c);
+	sel = igt_sysfs_choice_selected(&c);
+	igt_assert(sel);
+	igt_assert(!strcmp(sel, "high"));
+}
+
+static void test_selected_invalid_index(void)
+{
+	struct igt_sysfs_choice c;
+	const char *sel;
+
+	/* selected = -1 */
+	parse_ok("[only]\n", &c);
+	c.selected = -1;
+	sel = igt_sysfs_choice_selected(&c);
+	igt_assert(!sel);
+
+	/* selected >= num_tokens */
+	parse_ok("[only]\n", &c);
+	c.selected = 999;
+	sel = igt_sysfs_choice_selected(&c);
+	igt_assert(!sel);
+
+	/* empty choice */
+	memset(&c, 0, sizeof(c));
+	sel = igt_sysfs_choice_selected(&c);
+	igt_assert(!sel);
+}
+
+static void test_to_string_roundtrip(void)
+{
+	struct igt_sysfs_choice c1, c2;
+	char out[IGT_SYSFS_CHOICE_MAX_LEN];
+	int ret;
+
+	parse_ok(" low [normal]  high \n", &c1);
+
+	ret = igt_sysfs_choice_to_string(&c1, out, sizeof(out));
+	igt_assert_eq(ret, 0);
+
+	/*
+	 * Expect canonical format: tokens separated by single spaces,
+	 * one [selected], no trailing newline.
+	 */
+	igt_assert_f(!strcmp(out, "low [normal] high"),
+		     "choice_to_string produced '%s'\n", out);
+
+	/* Parse again and ensure we get the same structure. */
+	parse_ok(out, &c2);
+
+	igt_assert_eq(c2.num_tokens, 3);
+	assert_token(&c2, 0, "low");
+	assert_token(&c2, 1, "normal");
+	assert_token(&c2, 2, "high");
+	igt_assert_eq(c2.selected, 1);
+}
+
+static void test_find_basic(void)
+{
+	struct igt_sysfs_choice c;
+	int idx;
+
+	parse_ok("[low] normal high\n", &c);
+
+	idx = igt_sysfs_choice_find(&c, "low");
+	igt_assert_eq(idx, 0);
+
+	idx = igt_sysfs_choice_find(&c, "normal");
+	igt_assert_eq(idx, 1);
+
+	idx = igt_sysfs_choice_find(&c, "high");
+	igt_assert_eq(idx, 2);
+
+	idx = igt_sysfs_choice_find(&c, "ultra");
+	igt_assert_lt(idx, 0);
+}
+
+static const char *const prio_names[] = {
+	"low",
+	"normal",
+	"high",
+};
+
+static void test_to_mask_basic(void)
+{
+	struct igt_sysfs_choice c;
+	unsigned int mask = 0;
+	int selected_idx = -1;
+	int ret;
+
+	parse_ok("[low] normal high\n", &c);
+
+	ret = igt_sysfs_choice_to_mask(&c, prio_names, ARRAY_SIZE(prio_names),
+				       &mask, &selected_idx);
+	igt_assert_eq(ret, 0);
+
+	/* low | normal | high -> bits 0,1,2 set */
+	igt_assert_eq(mask, BIT(0) | BIT(1) | BIT(2));
+	igt_assert_eq(selected_idx, 0);
+}
+
+static void test_to_mask_ignores_unknown(void)
+{
+	struct igt_sysfs_choice c;
+	unsigned int mask = 0;
+	int selected_idx = -1;
+	int ret;
+
+	parse_ok("[low] normal extra\n", &c);
+
+	ret = igt_sysfs_choice_to_mask(&c, prio_names, ARRAY_SIZE(prio_names),
+				       &mask, &selected_idx);
+	igt_assert_eq(ret, 0);
+
+	/* "extra" is ignored, only low + normal mapped */
+	igt_assert_eq(mask, BIT(0) | BIT(1));
+	igt_assert_eq(selected_idx, 0);
+}
+
+static void test_to_mask_selected_unknown(void)
+{
+	struct igt_sysfs_choice c;
+	unsigned int mask = 0;
+	int selected_idx = 123;
+	int ret;
+
+	parse_ok("low normal [extra]\n", &c);
+
+	ret = igt_sysfs_choice_to_mask(&c, prio_names, ARRAY_SIZE(prio_names),
+				       &mask, &selected_idx);
+	igt_assert_eq(ret, 0);
+
+	igt_assert_eq(mask, BIT(0) | BIT(1)); /* low + normal */
+	igt_assert_eq(selected_idx, -1);
+}
+
+static void test_format_mask_basic(void)
+{
+	char buf[128];
+	int ret;
+
+	/* mask for low + normal + high, selected = normal (1) */
+	ret = igt_sysfs_choice_format_mask(buf, sizeof(buf),
+					   prio_names, ARRAY_SIZE(prio_names),
+					   BIT(0) | BIT(1) | BIT(2),
+					   1);
+	igt_assert_eq(ret, 0);
+	igt_assert_f(!strcmp(buf, "low [normal] high"),
+		     "choice_format_mask produced '%s'\n", buf);
+}
+
+static void test_format_mask_empty(void)
+{
+	char buf[128];
+	int ret;
+
+	ret = igt_sysfs_choice_format_mask(buf, sizeof(buf),
+					   prio_names, ARRAY_SIZE(prio_names),
+					   0, -1);
+	igt_assert_eq(ret, 0);
+	igt_assert_eq(buf[0], '\0');
+}
+
+static void test_format_mask_unknown_bit(void)
+{
+	char buf[128];
+	int ret;
+
+	ret = igt_sysfs_choice_format_mask(buf, sizeof(buf),
+					   prio_names, ARRAY_SIZE(prio_names),
+					   BIT(0) | BIT(3),
+					   0);
+	igt_assert_eq(ret, 0);
+	igt_assert_f(!strcmp(buf, "[low]"),
+		     "format_mask produced '%s'\n", buf);
+}
+
+static void test_intersect_basic(void)
+{
+	struct igt_sysfs_choice a, b;
+	int ret;
+
+	parse_ok("[low] normal high\n", &a);
+	parse_ok("low [normal] ultra\n", &b);
+
+	ret = igt_sysfs_choice_intersect(&a, &b);
+	igt_assert_eq(ret, 0);
+
+	igt_assert_eq(a.num_tokens, 2);
+	assert_token(&a, 0, "low");
+	assert_token(&a, 1, "normal");
+
+	/* semantics: selected remains the original selected token if still common */
+	igt_assert_eq(a.selected, 0);
+}
+
+static void test_intersect_single_common(void)
+{
+	struct igt_sysfs_choice a, b;
+	int ret;
+
+	parse_ok("low [normal] high\n", &a);
+	parse_ok("[normal] ultra\n", &b);
+
+	ret = igt_sysfs_choice_intersect(&a, &b);
+	igt_assert_eq(ret, 0);
+
+	igt_assert_eq(a.num_tokens, 1);
+	assert_token(&a, 0, "normal");
+	igt_assert_eq(a.selected, 0);
+}
+
+static void test_intersect_no_common(void)
+{
+	struct igt_sysfs_choice a, b;
+	int ret;
+
+	parse_ok("[low] normal\n", &a);
+	parse_ok("[high] ultra\n", &b);
+
+	ret = igt_sysfs_choice_intersect(&a, &b);
+	igt_assert_eq(ret, -ENOENT);
+}
+
+int igt_simple_main()
+{
+	test_parse_basic_first_selected();
+	test_parse_middle_selected_whitespace();
+	test_parse_single_token();
+	test_parse_error_missing_selected();
+	test_parse_error_multiple_selected();
+	test_parse_error_unterminated_bracket();
+	test_parse_error_too_many_tokens();
+	test_selected_basic();
+	test_selected_invalid_index();
+	test_to_string_roundtrip();
+	test_find_basic();
+	test_to_mask_basic();
+	test_to_mask_ignores_unknown();
+	test_to_mask_selected_unknown();
+	test_format_mask_basic();
+	test_format_mask_empty();
+	test_format_mask_unknown_bit();
+	test_intersect_basic();
+	test_intersect_single_common();
+	test_intersect_no_common();
+}
diff --git a/lib/tests/meson.build b/lib/tests/meson.build
index 1ce19f63c..124a9ecae 100644
--- a/lib/tests/meson.build
+++ b/lib/tests/meson.build
@@ -23,6 +23,7 @@ lib_tests = [
 	'igt_simulation',
 	'igt_stats',
 	'igt_subtest_group',
+	'igt_sysfs_choice',
 	'igt_thread',
 	'igt_types',
 	'i915_perf_data_alignment',
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v3 i-g-t 03/10] lib/xe/xe_sriov_provisioning: Add string conversion helpers for scheduling priority
  2026-01-28 18:08 [PATCH v3 i-g-t 00/10] Xe SR-IOV admin scheduling helpers and test updates Marcin Bernatowicz
  2026-01-28 18:08 ` [PATCH v3 i-g-t 01/10] lib/igt_sysfs_choice: Add helpers for sysfs enumerated choice attributes Marcin Bernatowicz
  2026-01-28 18:08 ` [PATCH v3 i-g-t 02/10] lib/tests/igt_sysfs_choice: Add test coverage Marcin Bernatowicz
@ 2026-01-28 18:08 ` Marcin Bernatowicz
  2026-01-28 18:08 ` [PATCH v3 i-g-t 04/10] lib/xe/xe_sriov_provisioning: Add sched priority mask to string helper Marcin Bernatowicz
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Marcin Bernatowicz @ 2026-01-28 18:08 UTC (permalink / raw)
  To: igt-dev
  Cc: adam.miszczak, jakub1.kolakowski, lukasz.laguna, michal.wajdeczko,
	Marcin Bernatowicz

Introduce helper functions to convert between xe_sriov_sched_priority
enum values and their string representations.

Signed-off-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
Reviewed-by: Lukasz Laguna <lukasz.laguna@intel.com>
Cc: Adam Miszczak <adam.miszczak@linux.intel.com>
Cc: Jakub Kolakowski <jakub1.kolakowski@intel.com>
Cc: Lukasz Laguna <lukasz.laguna@intel.com>
Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
---
 lib/xe/xe_sriov_provisioning.c | 58 ++++++++++++++++++++++++++++++++++
 lib/xe/xe_sriov_provisioning.h |  2 ++
 2 files changed, 60 insertions(+)

diff --git a/lib/xe/xe_sriov_provisioning.c b/lib/xe/xe_sriov_provisioning.c
index 116cd3255..c2a1db4bc 100644
--- a/lib/xe/xe_sriov_provisioning.c
+++ b/lib/xe/xe_sriov_provisioning.c
@@ -5,6 +5,7 @@
 
 #include <errno.h>
 
+#include "drmtest.h"
 #include "igt_core.h"
 #include "igt_debugfs.h"
 #include "igt_sriov_device.h"
@@ -599,6 +600,63 @@ void xe_sriov_set_sched_if_idle(int pf, unsigned int gt_num, bool value)
 	igt_fail_on(__xe_sriov_set_sched_if_idle(pf, gt_num, value));
 }
 
+static const char * const xe_sriov_sched_priority_str[] = {
+	[XE_SRIOV_SCHED_PRIORITY_LOW]    = "low",
+	[XE_SRIOV_SCHED_PRIORITY_NORMAL] = "normal",
+	[XE_SRIOV_SCHED_PRIORITY_HIGH]   = "high",
+};
+
+_Static_assert(ARRAY_SIZE(xe_sriov_sched_priority_str) == (XE_SRIOV_SCHED_PRIORITY_HIGH + 1),
+	       "sched priority table must cover 0..HIGH");
+
+/**
+ * xe_sriov_sched_priority_to_string - Convert scheduling priority enum to string
+ * @prio: SR-IOV scheduling priority value
+ *
+ * Converts an enumeration value of type &enum xe_sriov_sched_priority
+ * into its corresponding string representation.
+ *
+ * Return: A pointer to a constant string literal ("low", "normal", or "high"),
+ * or %NULL if the value is invalid or unrecognized.
+ */
+const char *xe_sriov_sched_priority_to_string(enum xe_sriov_sched_priority prio)
+{
+	switch (prio) {
+	case XE_SRIOV_SCHED_PRIORITY_LOW:
+	case XE_SRIOV_SCHED_PRIORITY_NORMAL:
+	case XE_SRIOV_SCHED_PRIORITY_HIGH:
+		return xe_sriov_sched_priority_str[prio];
+	}
+
+	return NULL;
+}
+
+/**
+ * xe_sriov_sched_priority_from_string - Parse scheduling priority from string
+ * @s: NUL-terminated string to parse
+ * @prio: Output pointer to store parsed enum value
+ *
+ * Parses a string representing a scheduling priority ("low", "normal", "high")
+ * into the corresponding &enum xe_sriov_sched_priority value.
+ *
+ * Return: 0 on success, -EINVAL if the string is invalid or unrecognized.
+ */
+int xe_sriov_sched_priority_from_string(const char *s,
+					enum xe_sriov_sched_priority *prio)
+{
+	igt_assert(s && prio);
+
+	for (size_t i = 0; i < ARRAY_SIZE(xe_sriov_sched_priority_str); i++) {
+		const char *name = xe_sriov_sched_priority_str[i];
+
+		if (name && !strcmp(s, name)) {
+			*prio = (enum xe_sriov_sched_priority)i;
+			return 0;
+		}
+	}
+	return -EINVAL;
+}
+
 /**
  * __xe_sriov_get_sched_priority - Get the scheduling priority for a given VF
  * @pf: PF device file descriptor
diff --git a/lib/xe/xe_sriov_provisioning.h b/lib/xe/xe_sriov_provisioning.h
index ab5347fd6..c9b321d58 100644
--- a/lib/xe/xe_sriov_provisioning.h
+++ b/lib/xe/xe_sriov_provisioning.h
@@ -136,6 +136,8 @@ int __xe_sriov_set_engine_reset(int pf, unsigned int gt_num, bool value);
 void xe_sriov_set_engine_reset(int pf, unsigned int gt_num, bool value);
 int __xe_sriov_set_sched_if_idle(int pf, unsigned int gt_num, bool value);
 void xe_sriov_set_sched_if_idle(int pf, unsigned int gt_num, bool value);
+const char *xe_sriov_sched_priority_to_string(enum xe_sriov_sched_priority value);
+int xe_sriov_sched_priority_from_string(const char *s, enum xe_sriov_sched_priority *value);
 int __xe_sriov_get_sched_priority(int pf, unsigned int vf_num,
 				  unsigned int gt_num,
 				  enum xe_sriov_sched_priority *value);
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v3 i-g-t 04/10] lib/xe/xe_sriov_provisioning: Add sched priority mask to string helper
  2026-01-28 18:08 [PATCH v3 i-g-t 00/10] Xe SR-IOV admin scheduling helpers and test updates Marcin Bernatowicz
                   ` (2 preceding siblings ...)
  2026-01-28 18:08 ` [PATCH v3 i-g-t 03/10] lib/xe/xe_sriov_provisioning: Add string conversion helpers for scheduling priority Marcin Bernatowicz
@ 2026-01-28 18:08 ` Marcin Bernatowicz
  2026-01-29  8:19   ` Laguna, Lukasz
  2026-01-28 18:08 ` [PATCH v3 i-g-t 05/10] lib/igt_sriov_device: Add helper for PF/VF sysfs path formatting Marcin Bernatowicz
                   ` (7 subsequent siblings)
  11 siblings, 1 reply; 19+ messages in thread
From: Marcin Bernatowicz @ 2026-01-28 18:08 UTC (permalink / raw)
  To: igt-dev
  Cc: adam.miszczak, jakub1.kolakowski, lukasz.laguna, michal.wajdeczko,
	Marcin Bernatowicz

Introduce xe_sriov_sched_priority_mask_to_string() to format a
scheduling priority bitmask as a space-separated list of priority names.
Introduce xe_sriov_sched_priority_choice_to_mask() to convert an
igt_sysfs_choice into a bitmask and a selected priority index.

Both helpers are thin wrappers around the generic igt_sysfs_choice
functions.

Signed-off-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
Cc: Adam Miszczak <adam.miszczak@linux.intel.com>
Cc: Jakub Kolakowski <jakub1.kolakowski@intel.com>
Cc: Lukasz Laguna <lukasz.laguna@intel.com>
Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>

---
v2:
- Make xe_sriov_sched_priority_mask_to_string() return error code
  instead of NULL.
- Add doc for xe_sriov_sched_priority_mask_to_string() and define it first

Signed-off-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
---
 lib/xe/xe_sriov_provisioning.c | 47 ++++++++++++++++++++++++++++++++++
 lib/xe/xe_sriov_provisioning.h | 13 ++++++++++
 2 files changed, 60 insertions(+)

diff --git a/lib/xe/xe_sriov_provisioning.c b/lib/xe/xe_sriov_provisioning.c
index c2a1db4bc..f8dda09fb 100644
--- a/lib/xe/xe_sriov_provisioning.c
+++ b/lib/xe/xe_sriov_provisioning.c
@@ -9,6 +9,8 @@
 #include "igt_core.h"
 #include "igt_debugfs.h"
 #include "igt_sriov_device.h"
+#include "igt_sysfs.h"
+#include "igt_sysfs_choice.h"
 #include "intel_chipset.h"
 #include "linux_scaffold.h"
 #include "xe/xe_query.h"
@@ -657,6 +659,51 @@ int xe_sriov_sched_priority_from_string(const char *s,
 	return -EINVAL;
 }
 
+/**
+ * xe_sriov_sched_priority_choice_to_mask - Map parsed sysfs choice to mask + selection
+ * @choice: Parsed choice (tokens + selected index)
+ * @mask: Output bitmask of known priorities present in @choice
+ * @selected_idx: Output selected priority index in the known-name table, or -1
+ *
+ * Converts an &struct igt_sysfs_choice representing the sched_priority sysfs
+ * attribute into a bitmask and an optional selected index.
+ *
+ * The bit positions in @mask correspond to &enum xe_sriov_sched_priority values
+ * (LOW/NORMAL/HIGH). Unknown tokens in @choice are ignored (best-effort), so
+ * tests can tolerate kernels that add extra choices.
+ *
+ * Return: 0 on success, -EINVAL on invalid arguments.
+ */
+int xe_sriov_sched_priority_choice_to_mask(const struct igt_sysfs_choice *choice,
+					   unsigned int *mask, int *selected_idx)
+{
+	return igt_sysfs_choice_to_mask(choice, xe_sriov_sched_priority_str,
+					ARRAY_SIZE(xe_sriov_sched_priority_str),
+					mask, selected_idx);
+}
+
+/**
+ * xe_sriov_sched_priority_mask_to_string - Format priority mask as text
+ * @buf: Output buffer.
+ * @buf_sz: Size of @buf.
+ * @mask: Priority bitmask.
+ * @selected_idx: Index to highlight with brackets, or <0 for none.
+ *
+ * Converts @mask to a space-separated string of priority names. If @selected_idx
+ * is >= 0 and present in @mask, that priority is wrapped in brackets, e.g.
+ * "low [normal] high". An empty @mask results in an empty string.
+ *
+ * Return: 0 on success, -EINVAL on invalid args, -E2BIG if @buf_sz is too small.
+ */
+int xe_sriov_sched_priority_mask_to_string(char *buf, size_t buf_sz,
+					   unsigned int mask, int selected_idx)
+{
+	return igt_sysfs_choice_format_mask(buf, buf_sz,
+					 xe_sriov_sched_priority_str,
+					 ARRAY_SIZE(xe_sriov_sched_priority_str),
+					 mask, selected_idx);
+}
+
 /**
  * __xe_sriov_get_sched_priority - Get the scheduling priority for a given VF
  * @pf: PF device file descriptor
diff --git a/lib/xe/xe_sriov_provisioning.h b/lib/xe/xe_sriov_provisioning.h
index c9b321d58..6661b33cc 100644
--- a/lib/xe/xe_sriov_provisioning.h
+++ b/lib/xe/xe_sriov_provisioning.h
@@ -9,6 +9,7 @@
 #include <stdint.h>
 
 struct xe_mmio;
+struct igt_sysfs_choice;
 
 /**
  * enum xe_sriov_shared_res - Shared resource types
@@ -75,6 +76,14 @@ enum xe_sriov_sched_priority {
 	XE_SRIOV_SCHED_PRIORITY_HIGH
 };
 
+#define XE_SRIOV_SCHED_PRIORITY_MASK_LOW    BIT(XE_SRIOV_SCHED_PRIORITY_LOW)
+#define XE_SRIOV_SCHED_PRIORITY_MASK_NORMAL BIT(XE_SRIOV_SCHED_PRIORITY_NORMAL)
+#define XE_SRIOV_SCHED_PRIORITY_MASK_HIGH   BIT(XE_SRIOV_SCHED_PRIORITY_HIGH)
+#define XE_SRIOV_SCHED_PRIORITY_MASK_ALL \
+	(XE_SRIOV_SCHED_PRIORITY_MASK_LOW | \
+	 XE_SRIOV_SCHED_PRIORITY_MASK_NORMAL | \
+	 XE_SRIOV_SCHED_PRIORITY_MASK_HIGH)
+
 /**
  * struct xe_sriov_provisioned_range - Provisioned range for a Virtual Function (VF)
  * @vf_id: The ID of the VF
@@ -138,6 +147,10 @@ int __xe_sriov_set_sched_if_idle(int pf, unsigned int gt_num, bool value);
 void xe_sriov_set_sched_if_idle(int pf, unsigned int gt_num, bool value);
 const char *xe_sriov_sched_priority_to_string(enum xe_sriov_sched_priority value);
 int xe_sriov_sched_priority_from_string(const char *s, enum xe_sriov_sched_priority *value);
+int xe_sriov_sched_priority_choice_to_mask(const struct igt_sysfs_choice *choice,
+					   unsigned int *mask, int *selected_idx);
+int xe_sriov_sched_priority_mask_to_string(char *buf, size_t buf_sz,
+					   unsigned int mask, int selected_idx);
 int __xe_sriov_get_sched_priority(int pf, unsigned int vf_num,
 				  unsigned int gt_num,
 				  enum xe_sriov_sched_priority *value);
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v3 i-g-t 05/10] lib/igt_sriov_device: Add helper for PF/VF sysfs path formatting
  2026-01-28 18:08 [PATCH v3 i-g-t 00/10] Xe SR-IOV admin scheduling helpers and test updates Marcin Bernatowicz
                   ` (3 preceding siblings ...)
  2026-01-28 18:08 ` [PATCH v3 i-g-t 04/10] lib/xe/xe_sriov_provisioning: Add sched priority mask to string helper Marcin Bernatowicz
@ 2026-01-28 18:08 ` Marcin Bernatowicz
  2026-01-28 18:08 ` [PATCH v3 i-g-t 06/10] lib/xe/xe_sriov_admin: Add SR-IOV admin sysfs accessors Marcin Bernatowicz
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Marcin Bernatowicz @ 2026-01-28 18:08 UTC (permalink / raw)
  To: igt-dev
  Cc: adam.miszczak, jakub1.kolakowski, lukasz.laguna, michal.wajdeczko,
	Marcin Bernatowicz

Add igt_sriov_func_str() — a small utility that returns "pf" for
function 0 and "vf%u" for any VF index. This helper allows callers
to build SR-IOV sysfs paths without duplicating PF/VF conditional
logic.

Signed-off-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
Reviewed-by: Lukasz Laguna <lukasz.laguna@intel.com>
Cc: Adam Miszczak <adam.miszczak@linux.intel.com>
Cc: Jakub Kolakowski <jakub1.kolakowski@intel.com>
Cc: Lukasz Laguna <lukasz.laguna@intel.com>
Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
---
 lib/igt_sriov_device.c | 19 +++++++++++++++++++
 lib/igt_sriov_device.h |  1 +
 2 files changed, 20 insertions(+)

diff --git a/lib/igt_sriov_device.c b/lib/igt_sriov_device.c
index ffa996d6b..788ffbfa1 100644
--- a/lib/igt_sriov_device.c
+++ b/lib/igt_sriov_device.c
@@ -42,6 +42,25 @@ bool igt_sriov_is_pf(int device)
 	return value > 0;
 }
 
+/**
+ * igt_sriov_func_str - Return "pf" or "vf%u" label for a function number
+ * @vf_num: 0 for PF, >0 for VF index
+ *
+ * Helper for constructing SR-IOV sysfs paths.
+ *
+ * Returns: "pf" for @vf_num == 0, otherwise "vf%u".
+ */
+const char *igt_sriov_func_str(unsigned int vf_num)
+{
+	static __thread char buf[16];
+
+	if (vf_num == 0)
+		return "pf";
+
+	snprintf(buf, sizeof(buf), "vf%u", vf_num);
+	return buf;
+}
+
 static bool __pf_attr_get_u32(int pf, const char *attr, uint32_t *value)
 {
 	int sysfs;
diff --git a/lib/igt_sriov_device.h b/lib/igt_sriov_device.h
index 930e97982..84d29b1bb 100644
--- a/lib/igt_sriov_device.h
+++ b/lib/igt_sriov_device.h
@@ -34,6 +34,7 @@ int igt_sriov_device_sysfs_open(int pf, unsigned int vf_num);
 bool igt_sriov_device_reset_exists(int pf, unsigned int vf_num);
 bool igt_sriov_device_reset(int pf, unsigned int vf_num);
 bool intel_is_vf_device(int device);
+const char *igt_sriov_func_str(unsigned int vf_num);
 
 /**
  * __is_valid_range - Helper to check VF range is valid
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v3 i-g-t 06/10] lib/xe/xe_sriov_admin: Add SR-IOV admin sysfs accessors
  2026-01-28 18:08 [PATCH v3 i-g-t 00/10] Xe SR-IOV admin scheduling helpers and test updates Marcin Bernatowicz
                   ` (4 preceding siblings ...)
  2026-01-28 18:08 ` [PATCH v3 i-g-t 05/10] lib/igt_sriov_device: Add helper for PF/VF sysfs path formatting Marcin Bernatowicz
@ 2026-01-28 18:08 ` Marcin Bernatowicz
  2026-01-29  8:21   ` Laguna, Lukasz
  2026-01-28 18:08 ` [PATCH v3 i-g-t 07/10] tests/intel/xe_sriov_scheduling: Avoid assert on scheduling params restore in cleanup Marcin Bernatowicz
                   ` (5 subsequent siblings)
  11 siblings, 1 reply; 19+ messages in thread
From: Marcin Bernatowicz @ 2026-01-28 18:08 UTC (permalink / raw)
  To: igt-dev
  Cc: adam.miszczak, jakub1.kolakowski, lukasz.laguna, michal.wajdeczko,
	Marcin Bernatowicz

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=y, Size: 22227 bytes --]

Reflect recent kernel changes and expose SR-IOV admin sysfs helpers for
scheduling control. Add per-VF and bulk accessors for execution quantum,
preemption timeout, scheduling priority, VF stop and restoring defaults.

Link: https://lore.kernel.org/intel-xe/20251030222348.186658-1-michal.wajdeczko@intel.com/
Signed-off-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
Cc: Adam Miszczak <adam.miszczak@linux.intel.com>
Cc: Jakub Kolakowski <jakub1.kolakowski@intel.com>
Cc: Lukasz Laguna <lukasz.laguna@intel.com>
Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>

---
v2:
- Correct __xe_sriov_profile_set_exec_quantum_ms return code
  on igt_sysfs_open() fail.
- Correct formatting.
- Rename helpers to consistent __xe_sriov_admin_*/xe_sriov_admin_*

Signed-off-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
---
 lib/meson.build         |   1 +
 lib/xe/xe_sriov_admin.c | 625 ++++++++++++++++++++++++++++++++++++++++
 lib/xe/xe_sriov_admin.h |  60 ++++
 3 files changed, 686 insertions(+)
 create mode 100644 lib/xe/xe_sriov_admin.c
 create mode 100644 lib/xe/xe_sriov_admin.h

diff --git a/lib/meson.build b/lib/meson.build
index 83569e8d2..d851029e0 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -128,6 +128,7 @@ lib_sources = [
 	'xe/xe_mmio.c',
 	'xe/xe_query.c',
 	'xe/xe_spin.c',
+	'xe/xe_sriov_admin.c',
 	'xe/xe_sriov_debugfs.c',
 	'xe/xe_sriov_provisioning.c',
 	'xe/xe_util.c',
diff --git a/lib/xe/xe_sriov_admin.c b/lib/xe/xe_sriov_admin.c
new file mode 100644
index 000000000..f3be70db8
--- /dev/null
+++ b/lib/xe/xe_sriov_admin.c
@@ -0,0 +1,625 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright(c) 2025 Intel Corporation. All rights reserved.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "igt.h"
+#include "igt_sriov_device.h"
+#include "igt_sysfs.h"
+#include "igt_sysfs_choice.h"
+#include "xe_sriov_admin.h"
+
+static const char SRIOV_ADMIN[] = "device/sriov_admin";
+
+static int fmt_profile_rel_path(char *buf, size_t sz, unsigned int vf_num,
+				const char *attr)
+{
+	igt_assert(buf && attr && sz);
+
+	return snprintf(buf, sz, "%s/%s/%s", SRIOV_ADMIN, igt_sriov_func_str(vf_num), attr);
+}
+
+static int fmt_bulk_rel_path(char *buf, size_t sz, const char *attr)
+{
+	igt_assert(buf && attr && sz);
+
+	return snprintf(buf, sz, "%s/.bulk_profile/%s", SRIOV_ADMIN, attr);
+}
+
+static int ret_from_printf(int ret)
+{
+	return ret > 0 ? 0 : ret;
+}
+
+static int ret_from_scanf_items(int ret, int want_items)
+{
+	/* igt_sysfs_scanf: returns number of assigned items, or <0 on -errno */
+	if (ret < 0)
+		return ret;
+	return (ret == want_items) ? 0 : -EIO;
+}
+
+/**
+ * xe_sriov_admin_is_present - Check if SR-IOV admin sysfs interface is available
+ * @pf_fd: PF device file descriptor.
+ *
+ * Returns: true if the PF exposes the SR-IOV admin tree, false otherwise.
+ */
+bool xe_sriov_admin_is_present(int pf_fd)
+{
+	int sysfs;
+	bool ret;
+
+	sysfs = igt_sysfs_open(pf_fd);
+	if (sysfs < 0)
+		return -1;
+
+	ret = igt_sysfs_has_attr(sysfs, SRIOV_ADMIN);
+	close(sysfs);
+	return ret;
+}
+
+/**
+ * __xe_sriov_admin_set_exec_quantum_ms - Set execution quantum for a VF
+ * @pf_fd:   PF device file descriptor.
+ * @vf_num:  VF index (0 for PF, >0 for VFs).
+ * @eq_ms:   Execution quantum in milliseconds.
+ *
+ * Writes the new execution quantum to sysfs.
+ *
+ * Returns: 0 on success or negative errno on error.
+ */
+int __xe_sriov_admin_set_exec_quantum_ms(int pf_fd, unsigned int vf_num,
+					 uint32_t eq_ms)
+{
+	char path[PATH_MAX];
+	int sysfs;
+	bool ret;
+
+	sysfs = igt_sysfs_open(pf_fd);
+	if (sysfs < 0)
+		return sysfs;
+
+	fmt_profile_rel_path(path, sizeof(path), vf_num, "profile/exec_quantum_ms");
+	ret = igt_sysfs_printf(sysfs, path, "%u", eq_ms);
+	close(sysfs);
+
+	return ret_from_printf(ret);
+}
+
+/**
+ * xe_sriov_admin_set_exec_quantum_ms - Assert wrapper for setting VF execution quantum
+ * @pf_fd:   PF device file descriptor.
+ * @vf_num:  VF index (0 for PF, >0 for VFs).
+ * @eq_ms:   Execution quantum in milliseconds.
+ *
+ * Calls __xe_sriov_admin_set_exec_quantum_ms() and asserts on error.
+ */
+void xe_sriov_admin_set_exec_quantum_ms(int pf_fd, unsigned int vf_num, uint32_t eq_ms)
+{
+	igt_assert_eq(0, __xe_sriov_admin_set_exec_quantum_ms(pf_fd, vf_num, eq_ms));
+}
+
+/**
+ * __xe_sriov_admin_get_exec_quantum_ms - Read execution quantum for a VF
+ * @pf_fd:   PF device file descriptor.
+ * @vf_num:  VF index (0 for PF, >0 for VFs).
+ * @eq_ms:   Output pointer for the execution quantum (ms).
+ *
+ * Reads current VF execution quantum from sysfs.
+ *
+ * Returns: 0 on success or negative errno on error.
+ */
+int __xe_sriov_admin_get_exec_quantum_ms(int pf_fd, unsigned int vf_num, uint32_t *eq_ms)
+{
+	char path[PATH_MAX];
+	unsigned int val = 0;
+	int sysfs, ret;
+
+	sysfs = igt_sysfs_open(pf_fd);
+	if (sysfs < 0)
+		return sysfs;
+
+	fmt_profile_rel_path(path, sizeof(path), vf_num, "profile/exec_quantum_ms");
+	ret = igt_sysfs_scanf(sysfs, path, "%u", &val);
+	close(sysfs);
+
+	ret = ret_from_scanf_items(ret, 1);
+	if (ret)
+		return ret;
+
+	*eq_ms = val;
+	return 0;
+}
+
+/**
+ * xe_sriov_admin_get_exec_quantum_ms - Assert wrapper for reading VF execution quantum
+ * @pf_fd:   PF device file descriptor.
+ * @vf_num:  VF index (0 for PF, >0 for VFs).
+ *
+ * Returns: execution quantum (ms); asserts on error.
+ */
+uint32_t xe_sriov_admin_get_exec_quantum_ms(int pf_fd, unsigned int vf_num)
+{
+	uint32_t v = 0;
+
+	igt_assert_eq(0, __xe_sriov_admin_get_exec_quantum_ms(pf_fd, vf_num, &v));
+
+	return v;
+}
+
+/**
+ * __xe_sriov_admin_set_preempt_timeout_us - Set preemption timeout for a VF
+ * @pf_fd:   PF device file descriptor.
+ * @vf_num:  VF index (0 for PF, >0 for VFs).
+ * @pt_us:   Preemption timeout in microseconds.
+ *
+ * Returns: 0 on success or negative errno on error.
+ */
+int __xe_sriov_admin_set_preempt_timeout_us(int pf_fd, unsigned int vf_num, uint32_t pt_us)
+{
+	char path[PATH_MAX];
+	int sysfs, ret;
+
+	sysfs = igt_sysfs_open(pf_fd);
+	if (sysfs < 0)
+		return sysfs;
+
+	fmt_profile_rel_path(path, sizeof(path), vf_num, "profile/preempt_timeout_us");
+	ret = igt_sysfs_printf(sysfs, path, "%u", pt_us);
+	close(sysfs);
+
+	return ret_from_printf(ret);
+}
+
+/**
+ * xe_sriov_admin_set_preempt_timeout_us - Assert wrapper for setting VF preemption timeout
+ * @pf_fd:   PF device file descriptor.
+ * @vf_num:  VF index (0 for PF, >0 for VFs).
+ * @pt_us:   Preemption timeout in microseconds.
+ */
+void xe_sriov_admin_set_preempt_timeout_us(int pf_fd, unsigned int vf_num, uint32_t pt_us)
+{
+	igt_assert_eq(0, __xe_sriov_admin_set_preempt_timeout_us(pf_fd, vf_num, pt_us));
+}
+
+/**
+ * __xe_sriov_admin_get_preempt_timeout_us - Read preemption timeout for a VF
+ * @pf_fd:   PF device file descriptor.
+ * @vf_num:  VF index (0 for PF, >0 for VFs).
+ * @pt_us:   Output pointer for preemption timeout (µs).
+ *
+ * Returns: 0 on success or negative errno on error.
+ */
+int __xe_sriov_admin_get_preempt_timeout_us(int pf_fd, unsigned int vf_num,
+					    uint32_t *pt_us)
+{
+	char path[PATH_MAX];
+	unsigned int val = 0;
+	int sysfs, ret;
+
+	sysfs = igt_sysfs_open(pf_fd);
+	if (sysfs < 0)
+		return sysfs;
+
+	fmt_profile_rel_path(path, sizeof(path), vf_num,
+			     "profile/preempt_timeout_us");
+	ret = igt_sysfs_scanf(sysfs, path, "%u", &val);
+	close(sysfs);
+
+	ret = ret_from_scanf_items(ret, 1);
+	if (ret)
+		return ret;
+	*pt_us = val;
+	return 0;
+}
+
+/**
+ * xe_sriov_admin_get_preempt_timeout_us - Assert wrapper for reading VF preemption timeout
+ * @pf_fd:   PF device file descriptor.
+ * @vf_num:  VF index (0 for PF, >0 for VFs).
+ *
+ * Returns: preemption timeout (µs); asserts on error.
+ */
+uint32_t xe_sriov_admin_get_preempt_timeout_us(int pf_fd, unsigned int vf_num)
+{
+	uint32_t v = 0;
+
+	igt_assert_eq(0, __xe_sriov_admin_get_preempt_timeout_us(pf_fd, vf_num, &v));
+	return v;
+}
+
+/**
+ * __xe_sriov_admin_set_sched_priority_string - Set VF priority from string
+ * @pf_fd:   PF device file descriptor.
+ * @vf_num:  VF index (0 for PF, >0 for VFs).
+ * @prio:    String value ("low", "normal", "high").
+ *
+ * Returns: 0 on success or negative errno on error.
+ */
+int __xe_sriov_admin_set_sched_priority_string(int pf_fd, unsigned int vf_num,
+					       const char *prio)
+{
+	char path[PATH_MAX];
+	int sysfs, ret;
+
+	if (!prio)
+		return -EINVAL;
+
+	sysfs = igt_sysfs_open(pf_fd);
+	if (sysfs < 0)
+		return sysfs;
+
+	fmt_profile_rel_path(path, sizeof(path), vf_num,
+			     "profile/sched_priority");
+	ret = igt_sysfs_printf(sysfs, path, "%s", prio);
+	close(sysfs);
+	return ret_from_printf(ret);
+}
+
+/**
+ * __xe_sriov_admin_set_sched_priority - Set VF scheduling priority
+ * @pf_fd:   PF device file descriptor.
+ * @vf_num:  VF index (0 for PF, >0 for VFs).
+ * @prio:    Priority enum value.
+ *
+ * Returns: 0 on success or negative errno on error.
+ */
+int __xe_sriov_admin_set_sched_priority(int pf_fd, unsigned int vf_num,
+					enum xe_sriov_sched_priority prio)
+{
+	const char *p = xe_sriov_sched_priority_to_string(prio);
+
+	return __xe_sriov_admin_set_sched_priority_string(pf_fd, vf_num, p);
+}
+
+/**
+ * xe_sriov_admin_set_sched_priority - Assert wrapper for setting VF priority
+ * @pf_fd:   PF device file descriptor.
+ * @vf_num:  VF index (0 for PF, >0 for VFs).
+ * @prio:    Priority enum value.
+ */
+void xe_sriov_admin_set_sched_priority(int pf_fd, unsigned int vf_num,
+				       enum xe_sriov_sched_priority prio)
+{
+	igt_assert_eq(0, __xe_sriov_admin_set_sched_priority(pf_fd, vf_num, prio));
+}
+
+/**
+ * __xe_sriov_admin_get_sched_priority_choice - Read sched_priority tokens
+ * @pf_fd:   PF device file descriptor
+ * @vf_num:  VF index (0 for PF, >0 for VFs).
+ * @choice:  Output choice structure with parsed tokens and selected index
+ *
+ * Reads the sched_priority sysfs attribute for the given PF/VF and parses it
+ * into an igt_sysfs_choice.
+ *
+ * Returns: 0 on success or a negative errno code.
+ */
+int __xe_sriov_admin_get_sched_priority_choice(int pf_fd, unsigned int vf_num,
+					       struct igt_sysfs_choice *choice)
+{
+	char path[PATH_MAX];
+	int sysfs, ret;
+
+	sysfs = igt_sysfs_open(pf_fd);
+	if (sysfs < 0)
+		return sysfs;
+
+	fmt_profile_rel_path(path, sizeof(path), vf_num, "profile/sched_priority");
+	ret = igt_sysfs_choice_read(sysfs, path, choice);
+	close(sysfs);
+
+	return ret;
+}
+
+/**
+ * __xe_sriov_admin_get_sched_priority - Read VF scheduling priority + mask
+ * @pf_fd:     PF device file descriptor.
+ * @vf_num:    VF index (0 for PF, >0 for VFs).
+ * @prio:      Output pointer for the effective priority.
+ * @prio_mask: Output mask of allowed priorities.
+ *
+ * Returns: 0 on success or negative errno on error.
+ */
+int __xe_sriov_admin_get_sched_priority(int pf_fd, unsigned int vf_num,
+					enum xe_sriov_sched_priority *prio,
+					unsigned int *prio_mask)
+{
+	struct igt_sysfs_choice prio_ch = {};
+	int ret;
+
+	ret = __xe_sriov_admin_get_sched_priority_choice(pf_fd, vf_num, &prio_ch);
+	if (ret)
+		return ret;
+
+	ret = xe_sriov_sched_priority_from_string(prio_ch.tokens[prio_ch.selected], prio);
+	if (igt_debug_on_f(ret, "unknown selected value '%s' (err=%d)\n",
+			   prio_ch.tokens[prio_ch.selected], ret))
+		return ret;
+
+	if (prio_mask) {
+		ret = xe_sriov_sched_priority_choice_to_mask(&prio_ch, prio_mask, NULL);
+		if (igt_debug_on_f(ret, "mask conversion failed (err=%d)\n", ret))
+			return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * xe_sriov_admin_get_sched_priority - Assert wrapper for reading VF priority
+ * @pf_fd:     PF device file descriptor.
+ * @vf_num:    VF index (0 for PF, >0 for VFs).
+ * @prio_mask: Output mask of supported priorities.
+ *
+ * Returns: effective priority; asserts on error.
+ */
+enum xe_sriov_sched_priority
+xe_sriov_admin_get_sched_priority(int pf_fd, unsigned int vf_num,
+				  unsigned int *prio_mask)
+{
+	enum xe_sriov_sched_priority cur_prio;
+
+	igt_assert_eq(0,
+		      __xe_sriov_admin_get_sched_priority(pf_fd, vf_num, &cur_prio, prio_mask));
+
+	return cur_prio;
+}
+
+/**
+ * __xe_sriov_admin_bulk_set_exec_quantum_ms - Set execution quantum for PF and all VFs
+ * @pf_fd: PF device file descriptor.
+ * @eq_ms: Execution quantum in milliseconds.
+ *
+ * Applies the value to PF and all VFs.
+ *
+ * Returns: 0 on success or negative errno on error.
+ */
+int __xe_sriov_admin_bulk_set_exec_quantum_ms(int pf_fd, uint32_t eq_ms)
+{
+	char path[PATH_MAX];
+	int sysfs, ret;
+
+	sysfs = igt_sysfs_open(pf_fd);
+	if (sysfs < 0)
+		return sysfs;
+
+	fmt_bulk_rel_path(path, sizeof(path), "exec_quantum_ms");
+	ret = igt_sysfs_printf(sysfs, path, "%u", eq_ms);
+	close(sysfs);
+
+	return ret_from_printf(ret);
+}
+
+/**
+ * xe_sriov_admin_bulk_set_exec_quantum_ms - Assert wrapper for bulk execution quantum update
+ * @pf_fd: PF device file descriptor.
+ * @eq_ms: Execution quantum in milliseconds.
+ */
+void xe_sriov_admin_bulk_set_exec_quantum_ms(int pf_fd, uint32_t eq_ms)
+{
+	igt_assert_eq(0, __xe_sriov_admin_bulk_set_exec_quantum_ms(pf_fd, eq_ms));
+}
+
+/**
+ * __xe_sriov_admin_bulk_set_preempt_timeout_us - Set preemption timeout for PF and all VFs
+ * @pf_fd: PF device file descriptor.
+ * @pt_us: Preemption timeout in microseconds.
+ *
+ * Applies the value to PF and all VFs.
+ *
+ * Returns: 0 on success or negative errno on error.
+ */
+int __xe_sriov_admin_bulk_set_preempt_timeout_us(int pf_fd, uint32_t pt_us)
+{
+	char path[PATH_MAX];
+	int sysfs, ret;
+
+	sysfs = igt_sysfs_open(pf_fd);
+	if (sysfs < 0)
+		return sysfs;
+
+	fmt_bulk_rel_path(path, sizeof(path), "preempt_timeout_us");
+	ret = igt_sysfs_printf(sysfs, path, "%u", pt_us);
+	close(sysfs);
+
+	return ret_from_printf(ret);
+}
+
+/**
+ * xe_sriov_admin_bulk_set_preempt_timeout_us - Assert wrapper for bulk preemption timeout update
+ * @pf_fd: PF device file descriptor.
+ * @pt_us: Preemption timeout in microseconds.
+ */
+void xe_sriov_admin_bulk_set_preempt_timeout_us(int pf_fd, uint32_t pt_us)
+{
+	igt_assert_eq(0, __xe_sriov_admin_bulk_set_preempt_timeout_us(pf_fd, pt_us));
+}
+
+/**
+ * __xe_sriov_admin_bulk_set_sched_priority_string - Set scheduling priority for PF and all VFs
+ * @pf_fd: PF device file descriptor.
+ * @prio:  String priority ("low", "normal", "high").
+ *
+ * Returns: 0 on success or negative errno on error.
+ */
+int __xe_sriov_admin_bulk_set_sched_priority_string(int pf_fd, const char *prio)
+{
+	char path[PATH_MAX];
+	int sysfs, ret;
+
+	sysfs = igt_sysfs_open(pf_fd);
+	if (sysfs < 0)
+		return sysfs;
+
+	fmt_bulk_rel_path(path, sizeof(path), "sched_priority");
+	ret = igt_sysfs_printf(sysfs, path, "%s", prio);
+	close(sysfs);
+
+	return ret_from_printf(ret);
+}
+
+/**
+ * xe_sriov_admin_bulk_set_sched_priority_string - Assert wrapper for bulk priority update
+ * @pf_fd: PF device file descriptor.
+ * @prio:  String priority.
+ */
+void xe_sriov_admin_bulk_set_sched_priority_string(int pf_fd, const char *prio)
+{
+	igt_assert_eq(0, __xe_sriov_admin_bulk_set_sched_priority_string(pf_fd, prio));
+}
+
+/**
+ * __xe_sriov_admin_bulk_set_sched_priority - Set numeric priority for PF and all VFs
+ * @pf_fd: PF device file descriptor.
+ * @prio:  Enum priority value.
+ *
+ * Returns: 0 on success or negative errno on error.
+ */
+int __xe_sriov_admin_bulk_set_sched_priority(int pf_fd,
+					     enum xe_sriov_sched_priority prio)
+{
+	const char *s = xe_sriov_sched_priority_to_string(prio);
+
+	if (!s)
+		return -EINVAL;
+	return __xe_sriov_admin_bulk_set_sched_priority_string(pf_fd, s);
+}
+
+/**
+ * xe_sriov_admin_bulk_set_sched_priority - Assert wrapper for bulk priority update
+ * @pf_fd: PF device file descriptor.
+ * @prio:  Enum priority value.
+ */
+void xe_sriov_admin_bulk_set_sched_priority(int pf_fd,
+					    enum xe_sriov_sched_priority prio)
+{
+	igt_assert_eq(0, __xe_sriov_admin_bulk_set_sched_priority(pf_fd, prio));
+}
+
+/**
+ * __xe_sriov_admin_vf_stop - Issue stop command for a VF
+ * @pf_fd:  PF device file descriptor.
+ * @vf_num: VF index.
+ *
+ * Triggers VF stop via sysfs.
+ *
+ * Returns: 0 on success or negative errno on error.
+ */
+int __xe_sriov_admin_vf_stop(int pf_fd, unsigned int vf_num)
+{
+	char path[PATH_MAX];
+	int sysfs, ret;
+
+	sysfs = igt_sysfs_open(pf_fd);
+	if (sysfs < 0)
+		return sysfs;
+
+	fmt_profile_rel_path(path, sizeof(path), vf_num, "stop");
+	ret = igt_sysfs_printf(sysfs, path, "%u", 1u);
+	close(sysfs);
+
+	return ret_from_printf(ret);
+}
+
+/**
+ * xe_sriov_admin_vf_stop - Assert wrapper for VF stop command
+ * @pf_fd:  PF device file descriptor.
+ * @vf_num: VF index.
+ */
+void xe_sriov_admin_vf_stop(int pf_fd, unsigned int vf_num)
+{
+	igt_assert_eq(0, __xe_sriov_admin_vf_stop(pf_fd, vf_num));
+}
+
+/**
+ * __xe_sriov_admin_restore_defaults - Restore scheduling defaults for a VF
+ * @pf_fd:  PF device file descriptor.
+ * @vf_num: VF index (0 for PF, >0 for VFs).
+ *
+ * Resets execution quantum, preemption timeout, and priority to driver defaults.
+ *
+ * Returns: 0 on success or negative errno on error.
+ */
+int __xe_sriov_admin_restore_defaults(int pf_fd, unsigned int vf_num)
+{
+	int ret_eq, ret_pt, ret_prio;
+	int ret = 0;
+
+	ret_eq = __xe_sriov_admin_set_exec_quantum_ms(pf_fd, vf_num, 0);
+	igt_warn_on(ret_eq);
+	if (!ret)
+		ret = ret_eq;
+
+	ret_pt = __xe_sriov_admin_set_preempt_timeout_us(pf_fd, vf_num, 0);
+	igt_warn_on(ret_pt);
+	if (!ret)
+		ret = ret_pt;
+
+	ret_prio = __xe_sriov_admin_set_sched_priority(pf_fd, vf_num,
+						       XE_SRIOV_SCHED_PRIORITY_LOW);
+	igt_warn_on(ret_prio);
+	if (!ret)
+		ret = ret_prio;
+
+	return ret;
+}
+
+/**
+ * xe_sriov_admin_restore_defaults - Assert wrapper restoring VF defaults
+ * @pf_fd:  PF device file descriptor.
+ * @vf_num: VF index (0 for PF, >0 for VFs).
+ */
+void xe_sriov_admin_restore_defaults(int pf_fd, unsigned int vf_num)
+{
+	igt_assert_eq(0, __xe_sriov_admin_restore_defaults(pf_fd, vf_num));
+}
+
+/**
+ * __xe_sriov_admin_bulk_restore_defaults - Restore scheduling defaults for PF and all VFs
+ * @pf_fd: PF device file descriptor.
+ *
+ * Resets PF and all VFs to driver default scheduling parameters.
+ *
+ * Returns: 0 on success or negative errno on error.
+ */
+int __xe_sriov_admin_bulk_restore_defaults(int pf_fd)
+{
+	int ret_eq, ret_pt, ret_prio;
+	int ret = 0;
+
+	ret_eq = __xe_sriov_admin_bulk_set_exec_quantum_ms(pf_fd, 0);
+	igt_warn_on(ret_eq);
+	if (!ret)
+		ret = ret_eq;
+
+	ret_pt = __xe_sriov_admin_bulk_set_preempt_timeout_us(pf_fd, 0);
+	igt_warn_on(ret_pt);
+	if (!ret)
+		ret = ret_pt;
+
+	ret_prio = __xe_sriov_admin_bulk_set_sched_priority(pf_fd,
+							    XE_SRIOV_SCHED_PRIORITY_LOW);
+	igt_warn_on(ret_prio);
+	if (!ret)
+		ret = ret_prio;
+
+	return ret;
+}
+
+/**
+ * xe_sriov_admin_bulk_restore_defaults - Assert wrapper for restoring defaults on PF and all VFs
+ * @pf_fd: PF device file descriptor.
+ */
+void xe_sriov_admin_bulk_restore_defaults(int pf_fd)
+{
+	igt_assert_eq(0, __xe_sriov_admin_bulk_restore_defaults(pf_fd));
+}
diff --git a/lib/xe/xe_sriov_admin.h b/lib/xe/xe_sriov_admin.h
new file mode 100644
index 000000000..607e33a86
--- /dev/null
+++ b/lib/xe/xe_sriov_admin.h
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright(c) 2025 Intel Corporation. All rights reserved.
+ */
+
+#ifndef __XE_SRIOV_ADMIN_H__
+#define __XE_SRIOV_ADMIN_H__
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stddef.h>
+#include "xe_sriov_provisioning.h" /* for enum xe_sriov_sched_priority */
+
+struct igt_sysfs_choice;
+
+bool xe_sriov_admin_is_present(int pf_fd);
+
+int  __xe_sriov_admin_set_exec_quantum_ms(int pf_fd, unsigned int vf_num, uint32_t eq_ms);
+void  xe_sriov_admin_set_exec_quantum_ms(int pf_fd, unsigned int vf_num, uint32_t eq_ms);
+int  __xe_sriov_admin_get_exec_quantum_ms(int pf_fd, unsigned int vf_num, uint32_t *eq_ms);
+uint32_t xe_sriov_admin_get_exec_quantum_ms(int pf_fd, unsigned int vf_num);
+int  __xe_sriov_admin_set_preempt_timeout_us(int pf_fd, unsigned int vf_num, uint32_t pt_us);
+void  xe_sriov_admin_set_preempt_timeout_us(int pf_fd, unsigned int vf_num, uint32_t pt_us);
+int  __xe_sriov_admin_get_preempt_timeout_us(int pf_fd, unsigned int vf_num, uint32_t *pt_us);
+uint32_t xe_sriov_admin_get_preempt_timeout_us(int pf_fd, unsigned int vf_num);
+int __xe_sriov_admin_set_sched_priority_string(int pf_fd, unsigned int vf_num,
+					       const char *prio);
+int __xe_sriov_admin_get_sched_priority_choice(int pf_fd, unsigned int vf_num,
+					       struct igt_sysfs_choice *choice);
+int __xe_sriov_admin_set_sched_priority(int pf_fd, unsigned int vf_num,
+					enum xe_sriov_sched_priority prio);
+void xe_sriov_admin_set_sched_priority(int pf_fd, unsigned int vf_num,
+				       enum xe_sriov_sched_priority prio);
+int __xe_sriov_admin_get_sched_priority(int pf_fd, unsigned int vf_num,
+					enum xe_sriov_sched_priority *prio,
+					unsigned int *prio_mask);
+enum xe_sriov_sched_priority
+xe_sriov_admin_get_sched_priority(int pf_fd, unsigned int vf_num,
+				  unsigned int *prio_mask);
+
+int  __xe_sriov_admin_bulk_set_exec_quantum_ms(int pf_fd, uint32_t eq_ms);
+void  xe_sriov_admin_bulk_set_exec_quantum_ms(int pf_fd, uint32_t eq_ms);
+int  __xe_sriov_admin_bulk_set_preempt_timeout_us(int pf_fd, uint32_t pt_us);
+void  xe_sriov_admin_bulk_set_preempt_timeout_us(int pf_fd, uint32_t pt_us);
+int  __xe_sriov_admin_bulk_set_sched_priority_string(int pf_fd, const char *prio);
+void  xe_sriov_admin_bulk_set_sched_priority_string(int pf_fd, const char *prio);
+int __xe_sriov_admin_bulk_set_sched_priority(int pf_fd,
+					     enum xe_sriov_sched_priority prio);
+void xe_sriov_admin_bulk_set_sched_priority(int pf_fd,
+					    enum xe_sriov_sched_priority prio);
+
+int  __xe_sriov_admin_vf_stop(int pf_fd, unsigned int vf_num);
+void  xe_sriov_admin_vf_stop(int pf_fd, unsigned int vf_num);
+
+int  __xe_sriov_admin_restore_defaults(int pf_fd, unsigned int vf_num);
+void  xe_sriov_admin_restore_defaults(int pf_fd, unsigned int vf_num);
+int  __xe_sriov_admin_bulk_restore_defaults(int pf_fd);
+void  xe_sriov_admin_bulk_restore_defaults(int pf_fd);
+
+#endif /* __XE_SRIOV_ADMIN_H__ */
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v3 i-g-t 07/10] tests/intel/xe_sriov_scheduling: Avoid assert on scheduling params restore in cleanup
  2026-01-28 18:08 [PATCH v3 i-g-t 00/10] Xe SR-IOV admin scheduling helpers and test updates Marcin Bernatowicz
                   ` (5 preceding siblings ...)
  2026-01-28 18:08 ` [PATCH v3 i-g-t 06/10] lib/xe/xe_sriov_admin: Add SR-IOV admin sysfs accessors Marcin Bernatowicz
@ 2026-01-28 18:08 ` Marcin Bernatowicz
  2026-01-28 18:08 ` [PATCH v3 i-g-t 08/10] tests/intel/xe_sriov_scheduling: Prefer SR-IOV admin sysfs accessors Marcin Bernatowicz
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Marcin Bernatowicz @ 2026-01-28 18:08 UTC (permalink / raw)
  To: igt-dev
  Cc: adam.miszczak, jakub1.kolakowski, lukasz.laguna, michal.wajdeczko,
	Marcin Bernatowicz

Add __set_vfs_scheduling_params() that returns error instead of asserting.
Use the non-asserting helper in cleanup paths to ensure VFs are properly
disabled before aborting.

Signed-off-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
Reviewed-by: Lukasz Laguna <lukasz.laguna@intel.com>
Cc: Adam Miszczak <adam.miszczak@linux.intel.com>
Cc: Jakub Kolakowski <jakub1.kolakowski@intel.com>
Cc: Lukasz Laguna <lukasz.laguna@intel.com>
---
 tests/intel/xe_sriov_scheduling.c | 41 ++++++++++++++++++++++++-------
 1 file changed, 32 insertions(+), 9 deletions(-)

diff --git a/tests/intel/xe_sriov_scheduling.c b/tests/intel/xe_sriov_scheduling.c
index fad3cbb04..117737d5f 100644
--- a/tests/intel/xe_sriov_scheduling.c
+++ b/tests/intel/xe_sriov_scheduling.c
@@ -371,17 +371,36 @@ struct vf_sched_params {
 	uint32_t preempt_timeout_us;
 };
 
-static void set_vfs_scheduling_params(int pf_fd, int num_vfs,
-				      const struct vf_sched_params *p)
+static int __set_vfs_scheduling_params(int pf_fd, int num_vfs,
+				       const struct vf_sched_params *p)
 {
 	unsigned int gt;
+	int vf, ret;
 
 	xe_for_each_gt(pf_fd, gt) {
-		for (int vf = 0; vf <= num_vfs; ++vf) {
-			xe_sriov_set_exec_quantum_ms(pf_fd, vf, gt, p->exec_quantum_ms);
-			xe_sriov_set_preempt_timeout_us(pf_fd, vf, gt, p->preempt_timeout_us);
+		for (vf = 0; vf <= num_vfs; ++vf) {
+			ret = __xe_sriov_set_exec_quantum_ms(pf_fd, vf, gt,
+							     p->exec_quantum_ms);
+			if (igt_warn_on_f(ret,
+					  "Failed to set exec_quantum_ms=%u (VF%d GT%u): %d\n",
+					  p->exec_quantum_ms, vf, gt, ret))
+				return ret;
+
+			ret = __xe_sriov_set_preempt_timeout_us(pf_fd, vf, gt,
+								p->preempt_timeout_us);
+			if (igt_warn_on_f(ret,
+					  "Failed to set preempt_timeout_us=%u (VF%d GT%u): %d\n",
+					  p->preempt_timeout_us, vf, gt, ret))
+				return ret;
 		}
 	}
+	return 0;
+}
+
+static void set_vfs_scheduling_params(int pf_fd, int num_vfs,
+				      const struct vf_sched_params *p)
+{
+	igt_assert_eq(0, __set_vfs_scheduling_params(pf_fd, num_vfs, p));
 }
 
 static bool check_within_epsilon(const double x, const double ref, const double tol)
@@ -729,7 +748,7 @@ static void throughput_ratio(int pf_fd, int num_vfs, const struct subm_opts *opt
 
 	/* cleanup */
 	subm_set_fini(set);
-	set_vfs_scheduling_params(pf_fd, num_vfs, &(struct vf_sched_params){});
+	__set_vfs_scheduling_params(pf_fd, num_vfs, &(struct vf_sched_params){});
 	xe_sriov_disable_vfs_restore_auto_provisioning(pf_fd);
 }
 
@@ -815,7 +834,7 @@ static void nonpreempt_engine_resets(int pf_fd, int num_vfs,
 
 	/* cleanup */
 	subm_set_fini(set);
-	set_vfs_scheduling_params(pf_fd, num_vfs, &(struct vf_sched_params){});
+	__set_vfs_scheduling_params(pf_fd, num_vfs, &(struct vf_sched_params){});
 	xe_sriov_disable_vfs_restore_auto_provisioning(pf_fd);
 }
 
@@ -923,8 +942,10 @@ int igt_main_args("", long_opts, help_str, subm_opts_handler, NULL)
 	}
 
 	igt_fixture() {
-		set_vfs_scheduling_params(pf_fd, igt_sriov_get_total_vfs(pf_fd),
-					  &(struct vf_sched_params){});
+		int ret;
+
+		ret = __set_vfs_scheduling_params(pf_fd, igt_sriov_get_total_vfs(pf_fd),
+						  &(struct vf_sched_params){});
 		xe_sriov_disable_vfs_restore_auto_provisioning(pf_fd);
 		/* abort to avoid execution of next tests with enabled VFs */
 		igt_abort_on_f(igt_sriov_get_enabled_vfs(pf_fd) > 0,
@@ -933,6 +954,8 @@ int igt_main_args("", long_opts, help_str, subm_opts_handler, NULL)
 			    igt_sriov_disable_driver_autoprobe(pf_fd);
 		igt_abort_on_f(autoprobe != igt_sriov_is_driver_autoprobe_enabled(pf_fd),
 			       "Failed to restore sriov_drivers_autoprobe value\n");
+		igt_abort_on_f(ret,
+			       "Failed to restore scheduling params\n");
 		drm_close_driver(pf_fd);
 	}
 }
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v3 i-g-t 08/10] tests/intel/xe_sriov_scheduling: Prefer SR-IOV admin sysfs accessors
  2026-01-28 18:08 [PATCH v3 i-g-t 00/10] Xe SR-IOV admin scheduling helpers and test updates Marcin Bernatowicz
                   ` (6 preceding siblings ...)
  2026-01-28 18:08 ` [PATCH v3 i-g-t 07/10] tests/intel/xe_sriov_scheduling: Avoid assert on scheduling params restore in cleanup Marcin Bernatowicz
@ 2026-01-28 18:08 ` Marcin Bernatowicz
  2026-01-28 18:08 ` [PATCH v3 i-g-t 09/10] tests/intel/xe_pmu: " Marcin Bernatowicz
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Marcin Bernatowicz @ 2026-01-28 18:08 UTC (permalink / raw)
  To: igt-dev
  Cc: adam.miszczak, jakub1.kolakowski, lukasz.laguna, michal.wajdeczko,
	Marcin Bernatowicz

Use SR-IOV admin sysfs setters for scheduling parameters,
skip if sriov_admin sysfs not available.

Signed-off-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
Reviewed-by: Lukasz Laguna <lukasz.laguna@intel.com>
Cc: Adam Miszczak <adam.miszczak@linux.intel.com>
Cc: Jakub Kolakowski <jakub1.kolakowski@intel.com>
Cc: Lukasz Laguna <lukasz.laguna@intel.com>
Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>

---
v2:
- Adjust to renamed __xe_sriov_admin_* helpers

Signed-off-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
---
 tests/intel/xe_sriov_scheduling.c | 38 ++++++++++++++-----------------
 1 file changed, 17 insertions(+), 21 deletions(-)

diff --git a/tests/intel/xe_sriov_scheduling.c b/tests/intel/xe_sriov_scheduling.c
index 117737d5f..4228eea2d 100644
--- a/tests/intel/xe_sriov_scheduling.c
+++ b/tests/intel/xe_sriov_scheduling.c
@@ -9,6 +9,7 @@
 #include "xe_drm.h"
 #include "xe/xe_ioctl.h"
 #include "xe/xe_spin.h"
+#include "xe/xe_sriov_admin.h"
 #include "xe/xe_sriov_provisioning.h"
 
 /**
@@ -374,27 +375,21 @@ struct vf_sched_params {
 static int __set_vfs_scheduling_params(int pf_fd, int num_vfs,
 				       const struct vf_sched_params *p)
 {
-	unsigned int gt;
-	int vf, ret;
-
-	xe_for_each_gt(pf_fd, gt) {
-		for (vf = 0; vf <= num_vfs; ++vf) {
-			ret = __xe_sriov_set_exec_quantum_ms(pf_fd, vf, gt,
-							     p->exec_quantum_ms);
-			if (igt_warn_on_f(ret,
-					  "Failed to set exec_quantum_ms=%u (VF%d GT%u): %d\n",
-					  p->exec_quantum_ms, vf, gt, ret))
-				return ret;
-
-			ret = __xe_sriov_set_preempt_timeout_us(pf_fd, vf, gt,
-								p->preempt_timeout_us);
-			if (igt_warn_on_f(ret,
-					  "Failed to set preempt_timeout_us=%u (VF%d GT%u): %d\n",
-					  p->preempt_timeout_us, vf, gt, ret))
-				return ret;
-		}
-	}
-	return 0;
+	int ret = 0;
+
+	ret = __xe_sriov_admin_bulk_set_exec_quantum_ms(pf_fd, p->exec_quantum_ms);
+	if (igt_warn_on_f(ret,
+			  "Failed to bulk set exec quantum=%u: %d\n",
+			  p->exec_quantum_ms, ret))
+		return ret;
+
+	ret = __xe_sriov_admin_bulk_set_preempt_timeout_us(pf_fd, p->preempt_timeout_us);
+	if (igt_warn_on_f(ret,
+			  "Failed to bulk set preempt timeout=%u: %d\n",
+			  p->preempt_timeout_us, ret))
+		return ret;
+
+	return ret;
 }
 
 static void set_vfs_scheduling_params(int pf_fd, int num_vfs,
@@ -912,6 +907,7 @@ int igt_main_args("", long_opts, help_str, subm_opts_handler, NULL)
 		pf_fd = drm_open_driver(DRIVER_XE);
 		igt_require(igt_sriov_is_pf(pf_fd));
 		igt_require(igt_sriov_get_enabled_vfs(pf_fd) == 0);
+		igt_require(xe_sriov_admin_is_present(pf_fd));
 		autoprobe = igt_sriov_is_driver_autoprobe_enabled(pf_fd);
 		xe_sriov_require_default_scheduling_attributes(pf_fd);
 	}
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v3 i-g-t 09/10] tests/intel/xe_pmu: Prefer SR-IOV admin sysfs accessors
  2026-01-28 18:08 [PATCH v3 i-g-t 00/10] Xe SR-IOV admin scheduling helpers and test updates Marcin Bernatowicz
                   ` (7 preceding siblings ...)
  2026-01-28 18:08 ` [PATCH v3 i-g-t 08/10] tests/intel/xe_sriov_scheduling: Prefer SR-IOV admin sysfs accessors Marcin Bernatowicz
@ 2026-01-28 18:08 ` Marcin Bernatowicz
  2026-01-28 18:08 ` [PATCH v3 i-g-t 10/10] tests/intel/xe_sriov_admin: Add SR-IOV admin sysfs scheduling attributes tests Marcin Bernatowicz
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Marcin Bernatowicz @ 2026-01-28 18:08 UTC (permalink / raw)
  To: igt-dev
  Cc: adam.miszczak, jakub1.kolakowski, lukasz.laguna, michal.wajdeczko,
	Marcin Bernatowicz, Jonathan Cavitt, Kamil Konieczny

Switch xe_pmu scheduling configuration to the SR-IOV admin sysfs
setters for exec_quantum_ms, preempt_timeout_us and sched_priority,
skipping the test if sriov_admin is not available.

Also adopts the “Tie preempt timeout to exec quantum” change using the
new sriov_admin interface.
Link: https://lore.kernel.org/igt-dev/20251107151251.6323-2-jonathan.cavitt@intel.com/

Signed-off-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
Reviewed-by: Lukasz Laguna <lukasz.laguna@intel.com>
Cc: Adam Miszczak <adam.miszczak@linux.intel.com>
Cc: Jakub Kolakowski <jakub1.kolakowski@intel.com>
Cc: Jonathan Cavitt <jonathan.cavitt@intel.com>
Cc: Kamil Konieczny <kamil.konieczny@linux.intel.com>
Cc: Lukasz Laguna <lukasz.laguna@intel.com>
Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>

---
v2:
- Adjust to renamed __xe_sriov_admin_* helpers

Signed-off-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
---
 tests/intel/xe_pmu.c | 43 ++++++++++++++++++++++---------------------
 1 file changed, 22 insertions(+), 21 deletions(-)

diff --git a/tests/intel/xe_pmu.c b/tests/intel/xe_pmu.c
index 33852270a..fb4b871e7 100644
--- a/tests/intel/xe_pmu.c
+++ b/tests/intel/xe_pmu.c
@@ -102,6 +102,7 @@
 #include "xe/xe_gt.h"
 #include "xe/xe_ioctl.h"
 #include "xe/xe_spin.h"
+#include "xe/xe_sriov_admin.h"
 #include "xe/xe_sriov_provisioning.h"
 
 #define SLEEP_DURATION 2 /* in seconds */
@@ -702,7 +703,7 @@ static void engine_activity_all_fn(int fd, struct drm_xe_engine_class_instance *
 }
 
 static void engine_activity_fn(int fd, struct drm_xe_engine_class_instance *eci,
-			       int function, bool sched_if_idle)
+			       int function, enum xe_sriov_sched_priority prio)
 {
 	uint64_t config, engine_active_ticks, engine_total_ticks, before[2], after[2];
 	double busy_percent, exec_quantum_ratio;
@@ -710,6 +711,9 @@ static void engine_activity_fn(int fd, struct drm_xe_engine_class_instance *eci,
 	int pmu_fd[2], fn_fd;
 	uint32_t vm;
 
+	if (prio != xe_sriov_admin_get_sched_priority(fd, 0, NULL))
+		xe_sriov_admin_bulk_set_sched_priority(fd, prio);
+
 	if (function > 0) {
 		fn_fd = igt_sriov_open_vf_drm_device(fd, function);
 		igt_assert_fd(fn_fd);
@@ -757,7 +761,7 @@ static void engine_activity_fn(int fd, struct drm_xe_engine_class_instance *eci,
 	if (function > 0)
 		close(fn_fd);
 
-	if (sched_if_idle)
+	if (prio == XE_SRIOV_SCHED_PRIORITY_NORMAL)
 		assert_within_epsilon(engine_active_ticks, engine_total_ticks, tolerance);
 	else
 		assert_within_epsilon(busy_percent, exec_quantum_ratio, tolerance);
@@ -982,10 +986,12 @@ static void test_gt_frequency(int fd, struct drm_xe_engine_class_instance *eci)
 
 static unsigned int enable_and_provision_vfs(int fd)
 {
-	unsigned int gt, num_vfs;
-	int pf_exec_quantum = 64, vf_exec_quantum = 32, vf;
+	unsigned int num_vfs, vf;
+	uint32_t pf_exec_quantum_ms = 64, vf_exec_quantum_ms = 32;
+	uint32_t pf_preempt_timeout_us = 64000, vf_preempt_timeout_us = 32000;
 
 	igt_require(igt_sriov_is_pf(fd));
+	igt_require(xe_sriov_admin_is_present(fd));
 	igt_require(igt_sriov_get_enabled_vfs(fd) == 0);
 	xe_sriov_require_default_scheduling_attributes(fd);
 	autoprobe = igt_sriov_is_driver_autoprobe_enabled(fd);
@@ -997,37 +1003,33 @@ static unsigned int enable_and_provision_vfs(int fd)
 	igt_require(num_vfs == 2);
 
 	/* Set 32ms for VF execution quantum and 64ms for PF execution quantum */
-	xe_for_each_gt(fd, gt) {
-		xe_sriov_set_sched_if_idle(fd, gt, 0);
-		for (int fn = 0; fn <= num_vfs; fn++)
-			xe_sriov_set_exec_quantum_ms(fd, fn, gt, fn ? vf_exec_quantum :
-						     pf_exec_quantum);
-	}
+	xe_sriov_admin_bulk_set_exec_quantum_ms(fd, vf_exec_quantum_ms);
+	xe_sriov_admin_bulk_set_preempt_timeout_us(fd, vf_preempt_timeout_us);
+	xe_sriov_admin_bulk_set_sched_priority(fd, XE_SRIOV_SCHED_PRIORITY_LOW);
+	xe_sriov_admin_set_exec_quantum_ms(fd, 0, pf_exec_quantum_ms);
+	xe_sriov_admin_set_preempt_timeout_us(fd, 0,
+					      pf_preempt_timeout_us);
 
 	/* probe VFs */
 	igt_sriov_enable_driver_autoprobe(fd);
 	for (vf = 1; vf <= num_vfs; vf++)
 		igt_sriov_bind_vf_drm_driver(fd, vf);
 
-	total_exec_quantum = pf_exec_quantum + (num_vfs * vf_exec_quantum);
+	total_exec_quantum = pf_exec_quantum_ms + (num_vfs * vf_exec_quantum_ms);
 
 	return num_vfs;
 }
 
 static void unprovision_and_disable_vfs(int fd)
 {
-	unsigned int gt, num_vfs = igt_sriov_get_enabled_vfs(fd);
-
-	xe_for_each_gt(fd, gt) {
-		xe_sriov_set_sched_if_idle(fd, gt, 0);
-		for (int fn = 0; fn <= num_vfs; fn++)
-			xe_sriov_set_exec_quantum_ms(fd, fn, gt, 0);
-	}
+	int ret;
 
+	ret = __xe_sriov_admin_bulk_restore_defaults(fd);
 	xe_sriov_disable_vfs_restore_auto_provisioning(fd);
 	/* abort to avoid execution of next tests with enabled VFs */
 	igt_abort_on_f(igt_sriov_get_enabled_vfs(fd) > 0,
 		       "Failed to disable VF(s)");
+	igt_abort_on_f(ret, "Failed to restore scheduling params\n");
 	autoprobe ? igt_sriov_enable_driver_autoprobe(fd) :
 		    igt_sriov_disable_driver_autoprobe(fd);
 
@@ -1197,13 +1199,12 @@ int igt_main()
 		igt_describe("Validate per-function engine activity");
 		test_each_engine("fn-engine-activity-load", fd, eci)
 			for (int fn = 0; fn < num_fns; fn++)
-				engine_activity_fn(fd, eci, fn, false);
+				engine_activity_fn(fd, eci, fn, XE_SRIOV_SCHED_PRIORITY_LOW);
 
 		igt_describe("Validate per-function engine activity when sched-if-idle is set");
 		test_each_engine("fn-engine-activity-sched-if-idle", fd, eci) {
-			xe_sriov_set_sched_if_idle(fd, eci->gt_id, 1);
 			for (int fn = 0; fn < num_fns; fn++)
-				engine_activity_fn(fd, eci, fn, true);
+				engine_activity_fn(fd, eci, fn, XE_SRIOV_SCHED_PRIORITY_NORMAL);
 		}
 
 		igt_fixture()
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v3 i-g-t 10/10] tests/intel/xe_sriov_admin: Add SR-IOV admin sysfs scheduling attributes tests
  2026-01-28 18:08 [PATCH v3 i-g-t 00/10] Xe SR-IOV admin scheduling helpers and test updates Marcin Bernatowicz
                   ` (8 preceding siblings ...)
  2026-01-28 18:08 ` [PATCH v3 i-g-t 09/10] tests/intel/xe_pmu: " Marcin Bernatowicz
@ 2026-01-28 18:08 ` Marcin Bernatowicz
  2026-01-29  8:21   ` Laguna, Lukasz
  2026-01-28 20:32 ` ✓ Xe.CI.BAT: success for Xe SR-IOV admin scheduling helpers and test updates (rev3) Patchwork
  2026-01-28 20:47 ` ✗ i915.CI.BAT: failure " Patchwork
  11 siblings, 1 reply; 19+ messages in thread
From: Marcin Bernatowicz @ 2026-01-28 18:08 UTC (permalink / raw)
  To: igt-dev
  Cc: adam.miszczak, jakub1.kolakowski, lukasz.laguna, michal.wajdeczko,
	Marcin Bernatowicz, Kamil Konieczny

Add tests that exercise SR-IOV admin sysfs attributes for PF/VF functions
with VFs disabled, covering default values, write -> readback behavior, and
bulk updates for exec_quantum_ms, preempt_timeout_us, and sched_priority.

Signed-off-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
Cc: Adam Miszczak <adam.miszczak@linux.intel.com>
Cc: Jakub Kolakowski <jakub1.kolakowski@intel.com>
Cc: Kamil Konieczny <kamil.konieczny@linux.intel.com>
Cc: Lukasz Laguna <lukasz.laguna@intel.com>
Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>

---
v2:
- Align igt_main()/igt_fixture() usage with upstream changes.
- Correct date
- Replace id with vf_id
- Iterate all VF sched_priority tokens and verify denied
  writes don’t change selection. (Lukasz)
- Rename xe_sriov_admin_profile to xe_sriov_admin (Lukasz)
- Adjust test for xe_sriov_sched_priority_mask_to_string() returning
  error code.
- Adjust to renamed __xe_sriov_admin_* helpers

Signed-off-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
---
 tests/intel/xe_sriov_admin.c | 434 +++++++++++++++++++++++++++++++++++
 tests/meson.build            |   1 +
 2 files changed, 435 insertions(+)
 create mode 100644 tests/intel/xe_sriov_admin.c

diff --git a/tests/intel/xe_sriov_admin.c b/tests/intel/xe_sriov_admin.c
new file mode 100644
index 000000000..5c7f5d621
--- /dev/null
+++ b/tests/intel/xe_sriov_admin.c
@@ -0,0 +1,434 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2026 Intel Corporation
+ */
+#include "igt.h"
+#include "igt_sriov_device.h"
+#include "igt_sysfs.h"
+#include "igt_sysfs_choice.h"
+#include "xe_drm.h"
+#include "xe/xe_sriov_admin.h"
+
+/**
+ * TEST: Tests for SR-IOV admin sysfs.
+ * Category: Core
+ * Mega feature: SR-IOV
+ * Sub-category: sysfs
+ * Functionality: SR-IOV admin sysfs
+ * Description: Verify behavior of exposed SR-IOV admin sysfs attributes.
+ */
+
+/**
+ * SUBTEST: default-sched-attributes-vfs-disabled
+ * Description:
+ *   Verify default scheduling attributes under sriov_admin
+ *   with VFs disabled.
+ */
+static void default_sched_attributes(int pf_fd, int vf_num)
+{
+	igt_dynamic_f("%s-default-exec-quantum", igt_sriov_func_str(vf_num)) {
+		igt_assert_eq(0, xe_sriov_admin_get_exec_quantum_ms(pf_fd, vf_num));
+	}
+
+	igt_dynamic_f("%s-default-preempt-timeout", igt_sriov_func_str(vf_num)) {
+		igt_assert_eq(0, xe_sriov_admin_get_preempt_timeout_us(pf_fd, vf_num));
+	}
+
+	igt_dynamic_f("%s-default-sched-priority", igt_sriov_func_str(vf_num)) {
+		enum xe_sriov_sched_priority prio;
+		unsigned int prio_mask;
+		char mask_str[64];
+		int ret;
+
+		prio = xe_sriov_admin_get_sched_priority(pf_fd, vf_num, &prio_mask);
+		ret = xe_sriov_sched_priority_mask_to_string(mask_str, sizeof(mask_str),
+							     prio_mask, prio);
+		igt_debug("sched_priority: ret=%d mask=0x%x selected_idx=%d str='%s'\n",
+			  ret, prio_mask, prio, mask_str);
+		igt_assert_eq(ret, 0);
+		igt_assert_eq(XE_SRIOV_SCHED_PRIORITY_LOW, prio);
+	}
+}
+
+/**
+ * SUBTEST: exec-quantum-write-readback-vfs-disabled
+ * Description:
+ *   Verify write -> readback of exec_quantum_ms under sriov_admin
+ *   for PF and all VFs with VFs disabled.
+ */
+static void exec_quantum_write_readback(int pf_fd, unsigned int vf_num,
+					uint32_t eq_ms)
+{
+	int ret_read, ret_restore;
+	uint32_t read_val;
+
+	igt_require(xe_sriov_admin_get_exec_quantum_ms(pf_fd, vf_num) == 0);
+
+	xe_sriov_admin_set_exec_quantum_ms(pf_fd, vf_num, eq_ms);
+
+	ret_read = __xe_sriov_admin_get_exec_quantum_ms(pf_fd, vf_num, &read_val);
+
+	ret_restore = __xe_sriov_admin_set_exec_quantum_ms(pf_fd, vf_num, 0);
+
+	igt_assert_eq(ret_read, 0);
+	igt_assert_eq(read_val, eq_ms);
+	igt_fail_on(ret_restore);
+}
+
+/**
+ * SUBTEST: preempt-timeout-write-readback-vfs-disabled
+ * Description:
+ *   Verify write -> readback of preempt_timeout_us under sriov_admin
+ *   for PF and all VFs with VFs disabled.
+ */
+static void preempt_timeout_write_readback(int pf_fd, unsigned int vf_num,
+					   uint32_t pt_us)
+{
+	int ret_read, ret_restore;
+	uint32_t read_val;
+
+	igt_require(xe_sriov_admin_get_preempt_timeout_us(pf_fd, vf_num) == 0);
+
+	xe_sriov_admin_set_preempt_timeout_us(pf_fd, vf_num, pt_us);
+
+	ret_read = __xe_sriov_admin_get_preempt_timeout_us(pf_fd, vf_num, &read_val);
+
+	ret_restore = __xe_sriov_admin_set_preempt_timeout_us(pf_fd, vf_num, 0);
+
+	igt_assert_eq(ret_read, 0);
+	igt_assert_eq(read_val, pt_us);
+	igt_fail_on(ret_restore);
+}
+
+/**
+ * SUBTEST: sched-priority-write-readback-vfs-disabled
+ * Description:
+ *   Verify write -> readback of sched_priority under sriov_admin
+ *   for PF and all VFs with VFs disabled.
+ */
+static void sched_priority_write_readback(int pf_fd, unsigned int vf_num)
+{
+	struct igt_sysfs_choice prio, now;
+	enum xe_sriov_sched_priority prio_enum;
+	int ret;
+
+	ret = __xe_sriov_admin_get_sched_priority_choice(pf_fd, vf_num, &prio);
+	igt_assert_eq(ret, 0);
+
+	for (size_t n = prio.num_tokens; n-- > 0; ) {
+		igt_warn_on_f(xe_sriov_sched_priority_from_string(prio.tokens[n],
+								  &prio_enum),
+			      "Unrecognized sched_priority value '%s'\n",
+			      prio.tokens[n]);
+		igt_debug("Setting priority string '%s'\n", prio.tokens[n]);
+		ret = __xe_sriov_admin_set_sched_priority_string(pf_fd, vf_num,
+								 prio.tokens[n]);
+
+		/* Not settable on VF */
+		if (igt_debug_on(vf_num && (ret == -EPERM || ret == -EACCES)))
+			break;
+
+		igt_assert_eq(ret, 0);
+		ret = __xe_sriov_admin_get_sched_priority_choice(pf_fd, vf_num, &now);
+		igt_assert_f(!strcmp(now.tokens[now.selected], prio.tokens[n]),
+			     "'%s' != '%s'", now.tokens[now.selected],
+			     prio.tokens[n]);
+		igt_assert_eq(now.selected, n);
+	}
+	__xe_sriov_admin_set_sched_priority_string(pf_fd, vf_num,
+						   prio.tokens[prio.selected]);
+}
+
+/**
+ * SUBTEST: bulk-exec-quantum-vfs-disabled
+ * Description:
+ *   Verify that bulk setting exec_quantum_ms under sriov_admin applies
+ *   the expected value to the PF and all VFs when VFs are disabled.
+ */
+static void bulk_set_exec_quantum(int pf_fd, unsigned int total_vfs, uint32_t eq_ms)
+{
+	uint32_t read_val;
+	unsigned int vf_id;
+	int fails = 0;
+
+	xe_sriov_admin_bulk_set_exec_quantum_ms(pf_fd, eq_ms);
+
+	for (vf_id = 0; vf_id <= total_vfs; ++vf_id) {
+		int ret = __xe_sriov_admin_get_exec_quantum_ms(pf_fd, vf_id,
+							       &read_val);
+
+		if (ret) {
+			igt_debug("%s: failed to read exec_quantum_ms, ret=%d\n",
+				  igt_sriov_func_str(vf_id), ret);
+			fails++;
+			continue;
+		}
+
+		if (read_val != eq_ms) {
+			igt_debug("%s: exec_quantum_ms=%u, expected=%u\n",
+				  igt_sriov_func_str(vf_id), read_val, eq_ms);
+			fails++;
+		}
+	}
+
+	xe_sriov_admin_bulk_set_exec_quantum_ms(pf_fd, 0);
+	igt_fail_on(fails);
+}
+
+/**
+ * SUBTEST: bulk-preempt-timeout-vfs-disabled
+ * Description:
+ *   Verify that bulk setting preempt_timeout_us under sriov_admin applies
+ *   the expected value to the PF and all VFs when VFs are disabled.
+ */
+static void bulk_set_preempt_timeout(int pf_fd, unsigned int total_vfs, uint32_t pt_us)
+{
+	uint32_t read_val;
+	unsigned int id;
+	int fails = 0;
+
+	xe_sriov_admin_bulk_set_preempt_timeout_us(pf_fd, pt_us);
+
+	for (id = 0; id <= total_vfs; ++id) {
+		int ret = __xe_sriov_admin_get_preempt_timeout_us(pf_fd, id,
+								  &read_val);
+
+		if (ret) {
+			igt_debug("%s: failed to read preempt_timeout_us, ret=%d\n",
+				  igt_sriov_func_str(id), ret);
+			fails++;
+			continue;
+		}
+
+		if (read_val != pt_us) {
+			igt_debug("%s: preempt_timeout_us=%u, expected=%u\n",
+				  igt_sriov_func_str(id), read_val, pt_us);
+			fails++;
+		}
+	}
+
+	xe_sriov_admin_bulk_set_preempt_timeout_us(pf_fd, 0);
+	igt_fail_on(fails);
+}
+
+static void build_common_sched_priority_choice(int pf_fd, int num_vfs,
+					       struct igt_sysfs_choice *common)
+{
+	int ret;
+
+	/* Start from PF */
+	ret = __xe_sriov_admin_get_sched_priority_choice(pf_fd, 0, common);
+	igt_require_f(ret == 0,
+		      "Failed to read PF sched_priority (ret=%d)\n", ret);
+
+	igt_require_f(common->num_tokens > 0,
+		      "PF sched_priority exposes no tokens\n");
+
+	/* Intersect with every VF 1..num_vfs */
+	for (int vf = 1; vf <= num_vfs; vf++) {
+		struct igt_sysfs_choice prio = {};
+
+		ret = __xe_sriov_admin_get_sched_priority_choice(pf_fd, vf, &prio);
+		igt_require_f(ret == 0,
+			      "Failed to read VF%u sched_priority (ret=%d)\n",
+			      vf, ret);
+
+		ret = igt_sysfs_choice_intersect(common, &prio);
+		igt_require_f(ret == 0,
+			      "No common sched_priority between PF and VF%u\n",
+			      vf);
+	}
+
+	igt_require_f(common->num_tokens > 0,
+		      "No common sched_priority across PF and all VFs\n");
+
+	if (common->selected < 0) {
+		igt_debug("Common sched_priority has no selected token, "
+			  "defaulting to tokens[0]=\"%s\"\n",
+			  common->tokens[0]);
+		common->selected = 0;
+	}
+}
+
+/**
+ * SUBTEST: bulk-sched-priority-vfs-disabled
+ * Description: Verify bulk sched_priority modification with VFs disabled.
+ */
+static void bulk_set_sched_priority(int pf_fd, unsigned int total_vfs, const char *prio_str)
+{
+	struct igt_sysfs_choice read_val;
+	const char *selected;
+	unsigned int id;
+	int fails = 0;
+
+	xe_sriov_admin_bulk_set_sched_priority_string(pf_fd, prio_str);
+
+	for (id = 0; id <= total_vfs; ++id) {
+		int ret = __xe_sriov_admin_get_sched_priority_choice(pf_fd, id,
+								     &read_val);
+
+		if (ret) {
+			igt_debug("%s: failed to read sched_priority, ret=%d\n",
+				  igt_sriov_func_str(id), ret);
+			fails++;
+			continue;
+		}
+
+		selected = igt_sysfs_choice_selected(&read_val);
+		if (!selected || strncmp(selected, prio_str, strlen(prio_str))) {
+			igt_debug("%s: sched_priority='%s', expected='%s'\n",
+				  igt_sriov_func_str(id), selected ?: "NULL", prio_str);
+			fails++;
+		}
+	}
+
+	igt_fail_on(fails);
+}
+
+/**
+ * SUBTEST: sched-priority-vf-write-denied
+ * Description:
+ *   Verify that sched_priority cannot be modified on a VF.
+ *   A write attempt must fail with -EPERM or -EACCES and the
+ *   current priority selection must remain unchanged.
+ */
+static void sched_priority_vf_write_denied(int pf_fd, unsigned int vf_num)
+{
+	struct igt_sysfs_choice before, after;
+	const char *new_token;
+	const char *baseline;
+	int baseline_selected;
+	bool attempted = false;
+	int ret;
+
+	igt_require(vf_num > 0);
+
+	ret = __xe_sriov_admin_get_sched_priority_choice(pf_fd, vf_num, &before);
+	igt_require(ret == 0);
+	igt_require(before.num_tokens > 0);
+	igt_require(before.selected >= 0);
+
+	baseline_selected = before.selected;
+	baseline = igt_sysfs_choice_selected(&before);
+	igt_require(baseline);
+
+	for (size_t i = 0; i < before.num_tokens; i++) {
+		if (before.num_tokens > 1 && (int)i == baseline_selected)
+			continue;
+
+		new_token = before.tokens[i];
+		attempted = true;
+
+		ret = __xe_sriov_admin_set_sched_priority_string(pf_fd, vf_num,
+								 new_token);
+		igt_assert_f(ret == -EPERM || ret == -EACCES,
+			     "Expected -EPERM/-EACCES when writing VF sched_priority "
+			     "(token='%s'), got %d\n", new_token, ret);
+
+		ret = __xe_sriov_admin_get_sched_priority_choice(pf_fd, vf_num,
+								 &after);
+		igt_assert_eq(ret, 0);
+
+		igt_assert_eq(after.selected, baseline_selected);
+		igt_assert(!strcmp(baseline, igt_sysfs_choice_selected(&after)));
+	}
+
+	igt_assert(attempted);
+}
+
+int igt_main()
+{
+	unsigned int total_vfs;
+	int pf_fd;
+
+	igt_fixture() {
+		pf_fd = drm_open_driver(DRIVER_XE);
+		igt_require(igt_sriov_is_pf(pf_fd));
+		igt_require(igt_sriov_get_enabled_vfs(pf_fd) == 0);
+		igt_require(xe_sriov_admin_is_present(pf_fd));
+		total_vfs = igt_sriov_get_total_vfs(pf_fd);
+	}
+
+	igt_subtest_with_dynamic("default-sched-attributes-vfs-disabled") {
+		for (unsigned int id = 0; id <= total_vfs; ++id)
+			default_sched_attributes(pf_fd, id);
+	}
+
+	igt_subtest_with_dynamic("exec-quantum-write-readback-vfs-disabled") {
+		uint32_t eq_ms = 10;
+
+		for (unsigned int id = 0; id <= total_vfs; ++id) {
+			igt_dynamic_f("%s-eq_ms-%u", igt_sriov_func_str(id), eq_ms) {
+				exec_quantum_write_readback(pf_fd, id, eq_ms);
+			}
+		}
+	}
+
+	igt_subtest_with_dynamic("preempt-timeout-write-readback-vfs-disabled") {
+		uint32_t pt_us = 20000;
+
+		for (unsigned int id = 0; id <= total_vfs; ++id) {
+			igt_dynamic_f("%s-pt_us-%u", igt_sriov_func_str(id), pt_us) {
+				preempt_timeout_write_readback(pf_fd, id, pt_us);
+			}
+		}
+	}
+
+	igt_subtest_with_dynamic("sched-priority-write-readback-vfs-disabled") {
+		for (unsigned int id = 0; id <= total_vfs; ++id) {
+			igt_dynamic_f("%s", igt_sriov_func_str(id)) {
+				sched_priority_write_readback(pf_fd, id);
+			}
+		}
+	}
+
+	igt_subtest_with_dynamic("sched-priority-vf-write-denied") {
+		for_each_sriov_num_vfs(pf_fd, vf_num) {
+			igt_dynamic_f("%s", igt_sriov_func_str(vf_num)) {
+				sched_priority_vf_write_denied(pf_fd, vf_num);
+			}
+		}
+	}
+
+	igt_subtest("bulk-exec-quantum-vfs-disabled") {
+		const uint32_t eq_ms = 10;
+
+		bulk_set_exec_quantum(pf_fd, total_vfs, eq_ms);
+	}
+
+	igt_subtest("bulk-preempt-timeout-vfs-disabled") {
+		uint32_t pt_us = 10000;
+
+		bulk_set_preempt_timeout(pf_fd, total_vfs, pt_us);
+	}
+
+	igt_subtest_group() {
+		struct igt_sysfs_choice prio = {};
+
+		igt_fixture() {
+			build_common_sched_priority_choice(pf_fd, total_vfs,
+							   &prio);
+		}
+
+		igt_subtest_with_dynamic_f("bulk-sched-priority-vfs-disabled") {
+			for (size_t i = prio.num_tokens; i-- > 0; ) {
+				const char *prio_str = prio.tokens[i];
+
+				igt_dynamic_f("%s", prio_str)
+					bulk_set_sched_priority(pf_fd, 0, prio_str);
+			}
+		}
+	}
+
+	igt_fixture() {
+		int ret;
+
+		ret = __xe_sriov_admin_bulk_restore_defaults(pf_fd);
+		igt_sriov_disable_vfs(pf_fd);
+		/* abort to avoid execution of next tests with enabled VFs */
+		igt_abort_on_f(igt_sriov_get_enabled_vfs(pf_fd) > 0,
+			       "Failed to disable VF(s)");
+		igt_abort_on_f(ret, "Failed to restore default profile values\n");
+		drm_close_driver(pf_fd);
+	}
+}
diff --git a/tests/meson.build b/tests/meson.build
index 0ad728b87..ef4edaa0d 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -331,6 +331,7 @@ intel_xe_progs = [
 	'xe_vm',
 	'xe_waitfence',
 	'xe_spin_batch',
+	'xe_sriov_admin',
 	'xe_sriov_auto_provisioning',
 	'xe_sriov_flr',
 	'xe_sriov_scheduling',
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* ✓ Xe.CI.BAT: success for Xe SR-IOV admin scheduling helpers and test updates (rev3)
  2026-01-28 18:08 [PATCH v3 i-g-t 00/10] Xe SR-IOV admin scheduling helpers and test updates Marcin Bernatowicz
                   ` (9 preceding siblings ...)
  2026-01-28 18:08 ` [PATCH v3 i-g-t 10/10] tests/intel/xe_sriov_admin: Add SR-IOV admin sysfs scheduling attributes tests Marcin Bernatowicz
@ 2026-01-28 20:32 ` Patchwork
  2026-01-28 20:47 ` ✗ i915.CI.BAT: failure " Patchwork
  11 siblings, 0 replies; 19+ messages in thread
From: Patchwork @ 2026-01-28 20:32 UTC (permalink / raw)
  To: Marcin Bernatowicz; +Cc: igt-dev

[-- Attachment #1: Type: text/plain, Size: 781 bytes --]

== Series Details ==

Series: Xe SR-IOV admin scheduling helpers and test updates (rev3)
URL   : https://patchwork.freedesktop.org/series/157591/
State : success

== Summary ==

CI Bug Log - changes from XEIGT_8723_BAT -> XEIGTPW_14443_BAT
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

  

Participating hosts (12 -> 11)
------------------------------

  Missing    (1): bat-bmg-3 


Changes
-------

  No changes found


Build changes
-------------

  * IGT: IGT_8723 -> IGTPW_14443

  IGTPW_14443: 14443
  IGT_8723: 8723
  xe-4465-8059f097e25f736bb3da09af6a9b283079abfd4f: 8059f097e25f736bb3da09af6a9b283079abfd4f

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14443/index.html

[-- Attachment #2: Type: text/html, Size: 1326 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* ✗ i915.CI.BAT: failure for Xe SR-IOV admin scheduling helpers and test updates (rev3)
  2026-01-28 18:08 [PATCH v3 i-g-t 00/10] Xe SR-IOV admin scheduling helpers and test updates Marcin Bernatowicz
                   ` (10 preceding siblings ...)
  2026-01-28 20:32 ` ✓ Xe.CI.BAT: success for Xe SR-IOV admin scheduling helpers and test updates (rev3) Patchwork
@ 2026-01-28 20:47 ` Patchwork
  2026-01-29 10:11   ` Bernatowicz, Marcin
  11 siblings, 1 reply; 19+ messages in thread
From: Patchwork @ 2026-01-28 20:47 UTC (permalink / raw)
  To: Marcin Bernatowicz; +Cc: igt-dev

[-- Attachment #1: Type: text/plain, Size: 6127 bytes --]

== Series Details ==

Series: Xe SR-IOV admin scheduling helpers and test updates (rev3)
URL   : https://patchwork.freedesktop.org/series/157591/
State : failure

== Summary ==

CI Bug Log - changes from IGT_8723 -> IGTPW_14443
====================================================

Summary
-------

  **FAILURE**

  Serious unknown changes coming with IGTPW_14443 absolutely need to be
  verified manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in IGTPW_14443, please notify your bug team (I915-ci-infra@lists.freedesktop.org) to allow them
  to document this new failure mode, which will reduce false positives in CI.

  External URL: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14443/index.html

Participating hosts (42 -> 41)
------------------------------

  Additional (1): bat-adls-6 
  Missing    (2): bat-dg2-13 fi-snb-2520m 

Possible new issues
-------------------

  Here are the unknown changes that may have been introduced in IGTPW_14443:

### IGT changes ###

#### Possible regressions ####

  * igt@i915_pm_rpm@module-reload:
    - bat-adlp-6:         [PASS][1] -> [DMESG-WARN][2] +78 other tests dmesg-warn
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8723/bat-adlp-6/igt@i915_pm_rpm@module-reload.html
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14443/bat-adlp-6/igt@i915_pm_rpm@module-reload.html

  
Known issues
------------

  Here are the changes found in IGTPW_14443 that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@gem_lmem_swapping@parallel-random-engines:
    - bat-adls-6:         NOTRUN -> [SKIP][3] ([i915#4613]) +3 other tests skip
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14443/bat-adls-6/igt@gem_lmem_swapping@parallel-random-engines.html

  * igt@gem_tiled_pread_basic:
    - bat-adls-6:         NOTRUN -> [SKIP][4] ([i915#3282])
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14443/bat-adls-6/igt@gem_tiled_pread_basic.html

  * igt@i915_selftest@live:
    - bat-twl-1:          [PASS][5] -> [DMESG-WARN][6] ([i915#14872]) +1 other test dmesg-warn
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8723/bat-twl-1/igt@i915_selftest@live.html
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14443/bat-twl-1/igt@i915_selftest@live.html

  * igt@intel_hwmon@hwmon-read:
    - bat-adls-6:         NOTRUN -> [SKIP][7] ([i915#7707]) +1 other test skip
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14443/bat-adls-6/igt@intel_hwmon@hwmon-read.html

  * igt@kms_cursor_legacy@basic-busy-flip-before-cursor-legacy:
    - bat-adls-6:         NOTRUN -> [SKIP][8] ([i915#4103]) +1 other test skip
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14443/bat-adls-6/igt@kms_cursor_legacy@basic-busy-flip-before-cursor-legacy.html

  * igt@kms_dsc@dsc-basic:
    - bat-adls-6:         NOTRUN -> [SKIP][9] ([i915#3555] / [i915#3840])
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14443/bat-adls-6/igt@kms_dsc@dsc-basic.html

  * igt@kms_force_connector_basic@force-load-detect:
    - bat-adls-6:         NOTRUN -> [SKIP][10]
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14443/bat-adls-6/igt@kms_force_connector_basic@force-load-detect.html

  * igt@kms_pm_backlight@basic-brightness:
    - bat-adls-6:         NOTRUN -> [SKIP][11] ([i915#5354])
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14443/bat-adls-6/igt@kms_pm_backlight@basic-brightness.html

  * igt@kms_psr@psr-primary-mmap-gtt:
    - bat-adls-6:         NOTRUN -> [SKIP][12] ([i915#1072] / [i915#9732]) +3 other tests skip
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14443/bat-adls-6/igt@kms_psr@psr-primary-mmap-gtt.html

  * igt@kms_setmode@basic-clone-single-crtc:
    - bat-adls-6:         NOTRUN -> [SKIP][13] ([i915#3555])
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14443/bat-adls-6/igt@kms_setmode@basic-clone-single-crtc.html

  * igt@prime_vgem@basic-fence-read:
    - bat-adls-6:         NOTRUN -> [SKIP][14] ([i915#3291]) +2 other tests skip
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14443/bat-adls-6/igt@prime_vgem@basic-fence-read.html

  
#### Possible fixes ####

  * igt@i915_selftest@live:
    - bat-mtlp-8:         [DMESG-FAIL][15] ([i915#12061]) -> [PASS][16] +1 other test pass
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8723/bat-mtlp-8/igt@i915_selftest@live.html
   [16]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14443/bat-mtlp-8/igt@i915_selftest@live.html

  * igt@i915_selftest@live@workarounds:
    - bat-arls-6:         [DMESG-FAIL][17] ([i915#12061]) -> [PASS][18] +1 other test pass
   [17]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8723/bat-arls-6/igt@i915_selftest@live@workarounds.html
   [18]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14443/bat-arls-6/igt@i915_selftest@live@workarounds.html

  
  [i915#1072]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/1072
  [i915#12061]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/12061
  [i915#14872]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14872
  [i915#3282]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3282
  [i915#3291]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3291
  [i915#3555]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3555
  [i915#3840]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3840
  [i915#4103]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4103
  [i915#4613]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4613
  [i915#5354]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/5354
  [i915#7707]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/7707
  [i915#9732]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9732


Build changes
-------------

  * CI: CI-20190529 -> None
  * IGT: IGT_8723 -> IGTPW_14443

  CI-20190529: 20190529
  CI_DRM_17900: 8059f097e25f736bb3da09af6a9b283079abfd4f @ git://anongit.freedesktop.org/gfx-ci/linux
  IGTPW_14443: 14443
  IGT_8723: 8723

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14443/index.html

[-- Attachment #2: Type: text/html, Size: 7244 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v3 i-g-t 01/10] lib/igt_sysfs_choice: Add helpers for sysfs enumerated choice attributes
  2026-01-28 18:08 ` [PATCH v3 i-g-t 01/10] lib/igt_sysfs_choice: Add helpers for sysfs enumerated choice attributes Marcin Bernatowicz
@ 2026-01-29  8:19   ` Laguna, Lukasz
  0 siblings, 0 replies; 19+ messages in thread
From: Laguna, Lukasz @ 2026-01-29  8:19 UTC (permalink / raw)
  To: Marcin Bernatowicz, igt-dev
  Cc: adam.miszczak, jakub1.kolakowski, michal.wajdeczko,
	Kamil Konieczny


On 1/28/2026 19:08, Marcin Bernatowicz wrote:
> Introduce igt_sysfs_choice, a lightweight, fixed-size, no-malloc helper
> for parsing and formatting sysfs "choice" attributes of the form:
>
>      "low [normal] high\n"
>
> The helper provides parsing, lookup, formatting, mask conversion, and
> intersection utilities for consistent handling of enumerated sysfs values.
>
> Suggested-by: Michal Wajdeczko <michal.wajdeczko@intel.com>
> Signed-off-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
> Cc: Adam Miszczak <adam.miszczak@linux.intel.com>
> Cc: Jakub Kolakowski <jakub1.kolakowski@intel.com>
> Cc: Kamil Konieczny <kamil.konieczny@linux.intel.com>
> Cc: Lukasz Laguna <lukasz.laguna@intel.com>

Reviewed-by: Lukasz Laguna <lukasz.laguna@intel.com>

> Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
>
> ---
> v2:
> - Corrected date
> - Fix documentation formatting/description.
> - Make igt_sysfs_choice_to_string() return error code instead of NULL.
> - Use names_sz consistently.
> - Make igt_sysfs_choice_format_mask() return error code instead of NULL.
>
> Signed-off-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
> ---
>   lib/igt_sysfs_choice.c | 439 +++++++++++++++++++++++++++++++++++++++++
>   lib/igt_sysfs_choice.h |  52 +++++
>   lib/meson.build        |   1 +
>   3 files changed, 492 insertions(+)
>   create mode 100644 lib/igt_sysfs_choice.c
>   create mode 100644 lib/igt_sysfs_choice.h
>
> diff --git a/lib/igt_sysfs_choice.c b/lib/igt_sysfs_choice.c
> new file mode 100644
> index 000000000..5ce2a2b70
> --- /dev/null
> +++ b/lib/igt_sysfs_choice.c
> @@ -0,0 +1,439 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2026 Intel Corporation
> + */
> +#include "igt_sysfs_choice.h"
> +#include <ctype.h>
> +#include <errno.h>
> +#include "igt_core.h"
> +#include "igt_sysfs.h"
> +
> +#define IGT_SYSFS_CHOICE_MAX_LEN 256
> +#define IGT_SYSFS_CHOICE_MAX_TOKENS 16
> +
> +/**
> + * igt_sysfs_choice_parse() - parse sysfs enumerated choice buffer
> + * @buf: NUL-terminated buffer with sysfs contents
> + * @choice: output descriptor, must be non-NULL (can be zeroed)
> + *
> + * Parses a sysfs enumerated choice buffer, e.g.:
> + *
> + *	"low [normal] high\n"
> + *
> + * into a token list and the index of the selected token.
> + *
> + * Parsing rules:
> + *  - tokens are separated by ASCII whitespace
> + *  - exactly one token must be wrapped in '[' and ']'
> + *  - surrounding '[' and ']' are stripped from the selected token
> + *  - empty tokens are treated as malformed input
> + *
> + * On entry, any previous contents of @choice are freed.
> + *
> + * Returns:
> + *  0        on success,
> + *  -EINVAL  malformed format (no tokens, no selected token, multiple
> + *           selected tokens, unterminated '[' or ']'),
> + *  -E2BIG   on too many tokens or too small choice buffer size.
> + */
> +int igt_sysfs_choice_parse(const char *buf, struct igt_sysfs_choice *choice)
> +{
> +	char *p, *tok_start;
> +	bool selected_seen = false;
> +	size_t num_tokens = 0;
> +	int n, selected = -1;
> +	bool is_selected;
> +
> +	igt_assert(buf && choice);
> +
> +	memset(choice, 0, sizeof(*choice));
> +	n = snprintf(choice->buf, sizeof(choice->buf), "%s", buf);
> +	if (igt_debug_on(n < 0))
> +		return -EINVAL;
> +	if (igt_debug_on((size_t)n >= sizeof(choice->buf)))
> +		return -E2BIG;
> +
> +	choice->num_tokens = 0;
> +	choice->selected = -1;
> +	p = choice->buf;
> +
> +	while (*p) {
> +		/* skip leading whitespace */
> +		while (*p && isspace((unsigned char)*p))
> +			p++;
> +		if (!*p)
> +			break;
> +
> +		is_selected = false;
> +		tok_start = p;
> +
> +		if (*p == '[') {
> +			is_selected = true;
> +			p++;
> +			tok_start = p;
> +
> +			if (selected_seen) {
> +				igt_debug("choice-parse: multiple [selected] tokens: \"%s\"\n",
> +					  choice->buf);
> +				return -EINVAL;
> +			}
> +			selected_seen = true;
> +		}
> +
> +		/* walk until ']' or whitespace */
> +		while (*p && !isspace((unsigned char)*p) && *p != ']')
> +			p++;
> +
> +		if (is_selected) {
> +			if (*p != ']') {
> +				igt_debug("choice-parse: unterminated '[' in: \"%s\"\n",
> +					  choice->buf);
> +				return -EINVAL;
> +			}
> +		}
> +
> +		/* terminate token */
> +		if (*p) {
> +			*p = '\0';
> +			p++;
> +		}
> +
> +		if (!*tok_start) {
> +			igt_debug("choice-parse: empty token in: \"%s\"\n",
> +				  choice->buf);
> +			return -EINVAL;
> +		}
> +
> +		if (num_tokens >= IGT_SYSFS_CHOICE_MAX_TOKENS) {
> +			igt_debug("choice-parse: too many tokens (>%d) in: \"%s\"\n",
> +				  IGT_SYSFS_CHOICE_MAX_TOKENS, choice->buf);
> +			return -E2BIG;
> +		}
> +
> +		choice->tokens[num_tokens] = tok_start;
> +		if (is_selected)
> +			selected = (int)num_tokens;
> +
> +		num_tokens++;
> +	}
> +
> +	if (!num_tokens) {
> +		igt_debug("choice-parse: no tokens in string: \"%s\"\n",
> +			  choice->buf);
> +		return -EINVAL;
> +	}
> +
> +	if (selected < 0) {
> +		igt_debug("choice-parse: missing selected token ([...]) in: \"%s\"\n",
> +			  choice->buf);
> +		return -EINVAL;
> +	}
> +
> +	choice->num_tokens = num_tokens;
> +	choice->selected = selected;
> +
> +	return 0;
> +}
> +
> +/**
> + * igt_sysfs_choice_read() - read and parse a sysfs enumerated choice attribute
> + * @dirfd: directory file descriptor of the sysfs node
> + * @attr: attribute name relative to @dirfd
> + * @choice: output descriptor, must be non-NULL
> + *
> + * Reads the given sysfs attribute into a temporary buffer and parses it.
> + *
> + * Returns:
> + *  0 on success,
> + *  negative errno-style value on read or parse error.
> + */
> +int igt_sysfs_choice_read(int dirfd, const char *attr,
> +			  struct igt_sysfs_choice *choice)
> +{
> +	char buf[IGT_SYSFS_CHOICE_MAX_LEN];
> +	int len;
> +
> +	len = igt_sysfs_read(dirfd, attr, buf, sizeof(buf) - 1);
> +	if (len < 0)
> +		return len;
> +
> +	buf[len] = '\0';
> +
> +	return igt_sysfs_choice_parse(buf, choice);
> +}
> +
> +/**
> + * igt_sysfs_choice_selected() - Return selected token string
> + * @choice: Parsed choice
> + *
> + * Returns:
> + *   Pointer to the selected token string, or NULL if no valid selection.
> + */
> +const char *igt_sysfs_choice_selected(const struct igt_sysfs_choice *choice)
> +{
> +	if (!choice || choice->selected < 0 ||
> +	    (size_t)choice->selected >= choice->num_tokens)
> +		return NULL;
> +
> +	return choice->tokens[choice->selected];
> +}
> +
> +/**
> + * igt_sysfs_choice_to_string() - Render a parsed choice into string
> + * @choice:   Parsed choice (tokens[] + selected index)
> + * @buf:      Output buffer for formatted string
> + * @buf_sz:   Size of @buf in bytes
> + *
> + * Formats the given @choice into the string:
> + *
> + *	"low [normal] high"
> + *
> + * Tokens are emitted in the order stored in @choice->tokens.  The
> + * selected token (choice->selected) is wrapped in '[' and ']'.
> + *
> + * Returns:
> + *   0        on success,
> + *   -EINVAL  if arguments are invalid,
> + *   -E2BIG   if @buf_sz is too small.
> + */
> +int igt_sysfs_choice_to_string(const struct igt_sysfs_choice *choice,
> +			       char *buf, size_t buf_sz)
> +{
> +	bool first = true;
> +	size_t pos = 0;
> +	int n;
> +
> +	if (!choice || !buf || !buf_sz)
> +		return -EINVAL;
> +
> +	buf[0] = '\0';
> +
> +	for (size_t i = 0; i < choice->num_tokens; i++) {
> +		const char *name = choice->tokens[i];
> +		bool is_selected = (choice->selected == (int)i);
> +
> +		if (!name)
> +			continue;
> +
> +		n = snprintf(buf + pos, buf_sz - pos,
> +			     "%s%s%s%s",
> +			     first ? "" : " ",
> +			     is_selected ? "[" : "",
> +			     name,
> +			     is_selected ? "]" : "");
> +
> +		if (n < 0)
> +			return -EINVAL;
> +		if ((size_t)n >= buf_sz - pos)
> +			return -E2BIG;
> +
> +		pos += (size_t)n;
> +		first = false;
> +	}
> +
> +	return 0;
> +}
> +
> +/**
> + * igt_sysfs_choice_find() - find token index by name
> + * @choice: parsed choice struct
> + * @token: token to look for (plain name, without '[' / ']')
> + *
> + * Performs a case-sensitive comparison of @token against entries in
> + * @choice->tokens.
> + *
> + * Returns:
> + *  index in [0..choice->num_tokens-1] on match,
> + *  -1 if @token is not present or @choice/@token is NULL.
> + */
> +int igt_sysfs_choice_find(const struct igt_sysfs_choice *choice,
> +			  const char *token)
> +{
> +	if (!choice || !token)
> +		return -1;
> +
> +	for (size_t i = 0; i < choice->num_tokens; i++)
> +		if (!strcmp(choice->tokens[i], token))
> +			return (int)i;
> +
> +	return -1;
> +}
> +
> +/**
> + * igt_sysfs_choice_to_mask() - map parsed tokens to bitmask + selection
> + * @choice: parsed choice struct
> + * @names: array of known token names
> + * @names_sz: number of elements in @names
> + * @mask: output bitmask of supported names
> + * @selected_idx: output index of selected token in @names, or -1 if selected
> + *                token is not among @names
> + *
> + * Builds a bitmask of known tokens present in @choice and identifies the
> + * selected token, if it matches one of @names.
> + *
> + * Unknown tokens do not cause an error; they are ignored and not
> + * reflected in @mask. This keeps the API "loose": tests can still
> + * validate required choices while tolerating additional values.
> + *
> + * Returns:
> + *  0        on success,
> + *  -EINVAL  on bad input parameters.
> + */
> +int igt_sysfs_choice_to_mask(const struct igt_sysfs_choice *choice,
> +			     const char * const *names, size_t names_sz,
> +			     unsigned int *mask, int *selected_idx)
> +{
> +	unsigned int m = 0;
> +	int sel = -1, idx;
> +
> +	if (!choice || !names || !mask)
> +		return -EINVAL;
> +
> +	for (size_t i = 0; i < names_sz; i++) {
> +		const char *name = names[i];
> +
> +		if (!name)
> +			continue;
> +
> +		idx = igt_sysfs_choice_find(choice, name);
> +		if (idx >= 0) {
> +			m |= 1u << i;
> +			if (idx == choice->selected)
> +				sel = (int)i;
> +		}
> +	}
> +
> +	*mask = m;
> +	if (selected_idx)
> +		*selected_idx = sel;
> +
> +	return 0;
> +}
> +
> +/**
> + * igt_sysfs_choice_format_mask() - Format a bitmask as a space-separated list of names
> + * @buf: Output buffer
> + * @buf_sz: Size of @buf in bytes
> + * @names: Array of token names indexed by bit position
> + * @names_sz: Number of elements in @names
> + * @mask: Bitmask of available tokens
> + * @selected_idx: Index to highlight with brackets, or <0 for none
> + *
> + * Builds a space-separated list of all bits set in @mask, mapping bit positions
> + * to names in @names. If @selected_idx >= 0 and that bit is set, the token is
> + * wrapped in brackets, e.g. "low [normal] high".
> + *
> + * This function is best-effort by design:
> + *  - If names[i] is NULL, it is formatted as "?".
> + *  - Bits beyond @names_sz are ignored.
> + * Empty @mask results in an empty string.
> + *
> + * Returns:
> + *  0        on success,
> + *  -EINVAL  on invalid arguments,
> + *  -E2BIG   if @buf_sz is too small.
> + */
> +int igt_sysfs_choice_format_mask(char *buf, size_t buf_sz,
> +				 const char *const *names,
> +				 size_t names_sz,
> +				 unsigned int mask,
> +				 int selected_idx)
> +{
> +	bool first = true;
> +	size_t pos = 0;
> +
> +	if (!buf || !buf_sz || !names || !names_sz)
> +		return -EINVAL;
> +
> +	buf[0] = '\0';
> +
> +	for (size_t idx = 0; idx < names_sz && mask; idx++) {
> +		int n;
> +		const char *name;
> +		bool highlight;
> +
> +		if (!(mask & 1u)) {
> +			mask >>= 1;
> +			continue;
> +		}
> +
> +		name = names[idx] ?: "?";
> +		highlight = ((int)idx == selected_idx);
> +		n = snprintf(buf + pos, buf_sz - pos, "%s%s%s%s",
> +			     first ? "" : " ",
> +			     highlight ? "[" : "",
> +			     name,
> +			     highlight ? "]" : "");
> +		if (n < 0)
> +			return -EINVAL;
> +		if ((size_t)n >= buf_sz - pos)
> +			return -E2BIG;
> +
> +		pos += (size_t)n;
> +		first = false;
> +		mask >>= 1;
> +	}
> +
> +	return 0;
> +}
> +
> +/**
> + * igt_sysfs_choice_intersect() - Restrict a choice set to tokens common with another
> + * @dst:   Choice to be updated in place
> + * @other: Choice providing the allowed tokens
> + *
> + * Computes the intersection of the token sets in @dst and @other.
> + * The resulting @dst contains only tokens that appear in both choices,
> + * preserving their original order from @dst.
> + *
> + * If the previously selected token in @dst is still present after
> + * intersection, its index is updated accordingly.  If it is not present,
> + * @dst->selected is set to -1.
> + *
> + * Returns:
> + * * 0        - success
> + * * -EINVAL  - invalid arguments
> + * * -ENOENT  - no common tokens
> + */
> +int igt_sysfs_choice_intersect(struct igt_sysfs_choice *dst,
> +			       const struct igt_sysfs_choice *other)
> +{
> +	char *new_tokens[IGT_SYSFS_CHOICE_MAX_TOKENS];
> +	const char *selected_name;
> +	int new_selected = -1;
> +	size_t new_n = 0;
> +
> +	if (!dst || !other)
> +		return -EINVAL;
> +
> +	selected_name = (dst->selected >= 0 && dst->selected < dst->num_tokens) ?
> +			 dst->tokens[dst->selected] : NULL;
> +
> +	for (size_t i = 0; i < dst->num_tokens; i++) {
> +		char *tok = dst->tokens[i];
> +
> +		if (igt_sysfs_choice_find(other, tok) < 0)
> +			continue;
> +
> +		new_tokens[new_n] = tok;
> +
> +		if (selected_name && !strcmp(tok, selected_name))
> +			new_selected = (int)new_n;
> +
> +		new_n++;
> +	}
> +
> +	if (!new_n) {
> +		dst->num_tokens = 0;
> +		dst->selected = -1;
> +		return -ENOENT;
> +	}
> +
> +	for (size_t i = 0; i < new_n; i++)
> +		dst->tokens[i] = new_tokens[i];
> +
> +	dst->num_tokens = new_n;
> +	dst->selected = new_selected;
> +
> +	return 0;
> +}
> diff --git a/lib/igt_sysfs_choice.h b/lib/igt_sysfs_choice.h
> new file mode 100644
> index 000000000..b354c774a
> --- /dev/null
> +++ b/lib/igt_sysfs_choice.h
> @@ -0,0 +1,52 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright © 2026 Intel Corporation
> + */
> +#ifndef __IGT_SYSFS_CHOICE_H__
> +#define __IGT_SYSFS_CHOICE_H__
> +
> +#include <stddef.h>
> +#include <stdbool.h>
> +
> +#define IGT_SYSFS_CHOICE_MAX_LEN    256
> +#define IGT_SYSFS_CHOICE_MAX_TOKENS 16
> +
> +/**
> + * struct igt_sysfs_choice - parsed sysfs enumerated choice attribute
> + * @tokens:      array of token strings
> + * @num_tokens:  number of entries in @tokens
> + * @selected:    index of the active token in @tokens, or -1 if invalid
> + *
> + * This struct represents a sysfs enumerated choice attribute, for example:
> + *
> + *	"low [normal] high\n"
> + *
> + * After parsing, @tokens point to "low", "normal", "high" and
> + * @selected will be 1 (the index of "normal").
> + */
> +struct igt_sysfs_choice {
> +	char    buf[IGT_SYSFS_CHOICE_MAX_LEN];
> +	char   *tokens[IGT_SYSFS_CHOICE_MAX_TOKENS];
> +	size_t  num_tokens;
> +	int     selected; /* index into tokens[], or -1 */
> +};
> +
> +int igt_sysfs_choice_parse(const char *buf, struct igt_sysfs_choice *choice);
> +int igt_sysfs_choice_read(int dirfd, const char *attr,
> +			  struct igt_sysfs_choice *choice);
> +const char *igt_sysfs_choice_selected(const struct igt_sysfs_choice *choice);
> +int igt_sysfs_choice_to_string(const struct igt_sysfs_choice *choice,
> +			       char *buf, size_t buf_sz);
> +int igt_sysfs_choice_find(const struct igt_sysfs_choice *choice,
> +			  const char *token);
> +int igt_sysfs_choice_to_mask(const struct igt_sysfs_choice *choice,
> +			     const char *const *names, size_t names_sz,
> +			     unsigned int *mask, int *selected_idx);
> +int igt_sysfs_choice_format_mask(char *buf, size_t buf_sz,
> +				 const char *const *names,
> +				 size_t names_sz, unsigned int mask,
> +				 int selected_idx);
> +int igt_sysfs_choice_intersect(struct igt_sysfs_choice *dst,
> +			       const struct igt_sysfs_choice *other);
> +
> +#endif /* __IGT_SYSFS_CHOICE_H__ */
> diff --git a/lib/meson.build b/lib/meson.build
> index 1a569ba52..83569e8d2 100644
> --- a/lib/meson.build
> +++ b/lib/meson.build
> @@ -44,6 +44,7 @@ lib_sources = [
>   	'igt_stats.c',
>   	'igt_syncobj.c',
>   	'igt_sysfs.c',
> +	'igt_sysfs_choice.c',
>   	'igt_sysrq.c',
>   	'igt_taints.c',
>   	'igt_thread.c',

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v3 i-g-t 02/10] lib/tests/igt_sysfs_choice: Add test coverage
  2026-01-28 18:08 ` [PATCH v3 i-g-t 02/10] lib/tests/igt_sysfs_choice: Add test coverage Marcin Bernatowicz
@ 2026-01-29  8:19   ` Laguna, Lukasz
  0 siblings, 0 replies; 19+ messages in thread
From: Laguna, Lukasz @ 2026-01-29  8:19 UTC (permalink / raw)
  To: Marcin Bernatowicz, igt-dev
  Cc: adam.miszczak, jakub1.kolakowski, michal.wajdeczko,
	Kamil Konieczny


On 1/28/2026 19:08, Marcin Bernatowicz wrote:
> Add unit tests exercising parsing, selection rules, intersection,
> round-trip formatting, and mask conversion for igt_sysfs_choice.
>
> Signed-off-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
> Cc: Adam Miszczak <adam.miszczak@linux.intel.com>
> Cc: Jakub Kolakowski <jakub1.kolakowski@intel.com>
> Cc: Kamil Konieczny <kamil.konieczny@linux.intel.com>
> Cc: Lukasz Laguna <lukasz.laguna@intel.com>

Reviewed-by: Lukasz Laguna <lukasz.laguna@intel.com>

> Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
>
> ---
> v2:
> - Align igt_simple_main() usage with upstream changes.
> - Corrected date, improved assert messages.
> - Use BIT() instead of (1u << n) for sysfs choice masks.
> - Adjust test for igt_sysfs_choice_to_string() returning error code.
> - Adjust test for igt_sysfs_choice_format_mask() returning error code.
>
> Signed-off-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
> ---
>   lib/tests/igt_sysfs_choice.c | 388 +++++++++++++++++++++++++++++++++++
>   lib/tests/meson.build        |   1 +
>   2 files changed, 389 insertions(+)
>   create mode 100644 lib/tests/igt_sysfs_choice.c
>
> diff --git a/lib/tests/igt_sysfs_choice.c b/lib/tests/igt_sysfs_choice.c
> new file mode 100644
> index 000000000..c573a0dff
> --- /dev/null
> +++ b/lib/tests/igt_sysfs_choice.c
> @@ -0,0 +1,388 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2026 Intel Corporation
> + */
> +#include <errno.h>
> +#include "drmtest.h"
> +#include "igt_core.h"
> +#include "intel_chipset.h"
> +#include "igt_sysfs_choice.h"
> +
> +static void assert_token(const struct igt_sysfs_choice *c,
> +			 size_t idx, const char *expected)
> +{
> +	igt_assert_f(idx < c->num_tokens,
> +		     "token index %zu out of range (num_tokens=%zu)\n",
> +		     idx, c->num_tokens);
> +	igt_assert(c->tokens[idx]);
> +	igt_assert_f(!strcmp(c->tokens[idx], expected),
> +		     "token[%zu] mismatch: got='%s' expected='%s'\n",
> +		     idx, c->tokens[idx], expected);
> +}
> +
> +static void parse_ok(const char *str, struct igt_sysfs_choice *choice)
> +{
> +	int ret;
> +
> +	ret = igt_sysfs_choice_parse(str, choice);
> +	igt_assert_f(ret == 0, "parse(\"%s\") failed: %d\n", str, ret);
> +}
> +
> +static void test_parse_basic_first_selected(void)
> +{
> +	struct igt_sysfs_choice c;
> +
> +	parse_ok("[low] normal high\n", &c);
> +
> +	igt_assert_eq(c.num_tokens, 3);
> +	assert_token(&c, 0, "low");
> +	assert_token(&c, 1, "normal");
> +	assert_token(&c, 2, "high");
> +
> +	igt_assert_eq(c.selected, 0);
> +}
> +
> +static void test_parse_middle_selected_whitespace(void)
> +{
> +	struct igt_sysfs_choice c;
> +
> +	parse_ok("  low   [normal]   high  \n", &c);
> +
> +	igt_assert_eq(c.num_tokens, 3);
> +	assert_token(&c, 0, "low");
> +	assert_token(&c, 1, "normal");
> +	assert_token(&c, 2, "high");
> +
> +	igt_assert_eq(c.selected, 1);
> +}
> +
> +static void test_parse_single_token(void)
> +{
> +	struct igt_sysfs_choice c;
> +
> +	parse_ok("[only]\n", &c);
> +
> +	igt_assert_eq(c.num_tokens, 1);
> +	assert_token(&c, 0, "only");
> +	igt_assert_eq(c.selected, 0);
> +}
> +
> +static void test_parse_error_missing_selected(void)
> +{
> +	struct igt_sysfs_choice c;
> +	int ret;
> +
> +	ret = igt_sysfs_choice_parse("low normal high\n", &c);
> +	igt_assert_eq(ret, -EINVAL);
> +}
> +
> +static void test_parse_error_multiple_selected(void)
> +{
> +	struct igt_sysfs_choice c;
> +	int ret;
> +
> +	ret = igt_sysfs_choice_parse("[low] [normal] high\n", &c);
> +	igt_assert_eq(ret, -EINVAL);
> +
> +	ret = igt_sysfs_choice_parse("low [normal] [high]\n", &c);
> +	igt_assert_eq(ret, -EINVAL);
> +}
> +
> +static void test_parse_error_unterminated_bracket(void)
> +{
> +	struct igt_sysfs_choice c;
> +	int ret;
> +
> +	ret = igt_sysfs_choice_parse("[low normal high\n", &c);
> +	igt_assert_eq(ret, -EINVAL);
> +
> +	ret = igt_sysfs_choice_parse("low [normal high]\n", &c);
> +	igt_assert_eq(ret, -EINVAL);
> +}
> +
> +static void test_parse_error_too_many_tokens(void)
> +{
> +	struct igt_sysfs_choice c;
> +	char buf[512];
> +	size_t i;
> +	int len = 0;
> +	int ret;
> +
> +	/*
> +	 * Build a line with (IGT_SYSFS_CHOICE_MAX_TOKENS + 1) tokens:
> +	 * "[t0] t1 t2 ... tN"
> +	 */
> +	len += snprintf(buf + len, sizeof(buf) - len, "[t0]");
> +	for (i = 1; i < IGT_SYSFS_CHOICE_MAX_TOKENS + 1 && len < (int)sizeof(buf); i++)
> +		len += snprintf(buf + len, sizeof(buf) - len, " t%zu", i);
> +	len += snprintf(buf + len, sizeof(buf) - len, "\n");
> +
> +	ret = igt_sysfs_choice_parse(buf, &c);
> +	igt_assert_eq(ret, -E2BIG);
> +}
> +
> +static void test_selected_basic(void)
> +{
> +	struct igt_sysfs_choice c;
> +	const char *sel;
> +
> +	/* selected at position 0 */
> +	parse_ok("[low] normal high\n", &c);
> +	sel = igt_sysfs_choice_selected(&c);
> +	igt_assert(sel);
> +	igt_assert(!strcmp(sel, "low"));
> +
> +	/* selected at position 1 */
> +	parse_ok("low [normal] high\n", &c);
> +	sel = igt_sysfs_choice_selected(&c);
> +	igt_assert(sel);
> +	igt_assert(!strcmp(sel, "normal"));
> +
> +	/* selected at position 2 */
> +	parse_ok("low normal [high]\n", &c);
> +	sel = igt_sysfs_choice_selected(&c);
> +	igt_assert(sel);
> +	igt_assert(!strcmp(sel, "high"));
> +}
> +
> +static void test_selected_invalid_index(void)
> +{
> +	struct igt_sysfs_choice c;
> +	const char *sel;
> +
> +	/* selected = -1 */
> +	parse_ok("[only]\n", &c);
> +	c.selected = -1;
> +	sel = igt_sysfs_choice_selected(&c);
> +	igt_assert(!sel);
> +
> +	/* selected >= num_tokens */
> +	parse_ok("[only]\n", &c);
> +	c.selected = 999;
> +	sel = igt_sysfs_choice_selected(&c);
> +	igt_assert(!sel);
> +
> +	/* empty choice */
> +	memset(&c, 0, sizeof(c));
> +	sel = igt_sysfs_choice_selected(&c);
> +	igt_assert(!sel);
> +}
> +
> +static void test_to_string_roundtrip(void)
> +{
> +	struct igt_sysfs_choice c1, c2;
> +	char out[IGT_SYSFS_CHOICE_MAX_LEN];
> +	int ret;
> +
> +	parse_ok(" low [normal]  high \n", &c1);
> +
> +	ret = igt_sysfs_choice_to_string(&c1, out, sizeof(out));
> +	igt_assert_eq(ret, 0);
> +
> +	/*
> +	 * Expect canonical format: tokens separated by single spaces,
> +	 * one [selected], no trailing newline.
> +	 */
> +	igt_assert_f(!strcmp(out, "low [normal] high"),
> +		     "choice_to_string produced '%s'\n", out);
> +
> +	/* Parse again and ensure we get the same structure. */
> +	parse_ok(out, &c2);
> +
> +	igt_assert_eq(c2.num_tokens, 3);
> +	assert_token(&c2, 0, "low");
> +	assert_token(&c2, 1, "normal");
> +	assert_token(&c2, 2, "high");
> +	igt_assert_eq(c2.selected, 1);
> +}
> +
> +static void test_find_basic(void)
> +{
> +	struct igt_sysfs_choice c;
> +	int idx;
> +
> +	parse_ok("[low] normal high\n", &c);
> +
> +	idx = igt_sysfs_choice_find(&c, "low");
> +	igt_assert_eq(idx, 0);
> +
> +	idx = igt_sysfs_choice_find(&c, "normal");
> +	igt_assert_eq(idx, 1);
> +
> +	idx = igt_sysfs_choice_find(&c, "high");
> +	igt_assert_eq(idx, 2);
> +
> +	idx = igt_sysfs_choice_find(&c, "ultra");
> +	igt_assert_lt(idx, 0);
> +}
> +
> +static const char *const prio_names[] = {
> +	"low",
> +	"normal",
> +	"high",
> +};
> +
> +static void test_to_mask_basic(void)
> +{
> +	struct igt_sysfs_choice c;
> +	unsigned int mask = 0;
> +	int selected_idx = -1;
> +	int ret;
> +
> +	parse_ok("[low] normal high\n", &c);
> +
> +	ret = igt_sysfs_choice_to_mask(&c, prio_names, ARRAY_SIZE(prio_names),
> +				       &mask, &selected_idx);
> +	igt_assert_eq(ret, 0);
> +
> +	/* low | normal | high -> bits 0,1,2 set */
> +	igt_assert_eq(mask, BIT(0) | BIT(1) | BIT(2));
> +	igt_assert_eq(selected_idx, 0);
> +}
> +
> +static void test_to_mask_ignores_unknown(void)
> +{
> +	struct igt_sysfs_choice c;
> +	unsigned int mask = 0;
> +	int selected_idx = -1;
> +	int ret;
> +
> +	parse_ok("[low] normal extra\n", &c);
> +
> +	ret = igt_sysfs_choice_to_mask(&c, prio_names, ARRAY_SIZE(prio_names),
> +				       &mask, &selected_idx);
> +	igt_assert_eq(ret, 0);
> +
> +	/* "extra" is ignored, only low + normal mapped */
> +	igt_assert_eq(mask, BIT(0) | BIT(1));
> +	igt_assert_eq(selected_idx, 0);
> +}
> +
> +static void test_to_mask_selected_unknown(void)
> +{
> +	struct igt_sysfs_choice c;
> +	unsigned int mask = 0;
> +	int selected_idx = 123;
> +	int ret;
> +
> +	parse_ok("low normal [extra]\n", &c);
> +
> +	ret = igt_sysfs_choice_to_mask(&c, prio_names, ARRAY_SIZE(prio_names),
> +				       &mask, &selected_idx);
> +	igt_assert_eq(ret, 0);
> +
> +	igt_assert_eq(mask, BIT(0) | BIT(1)); /* low + normal */
> +	igt_assert_eq(selected_idx, -1);
> +}
> +
> +static void test_format_mask_basic(void)
> +{
> +	char buf[128];
> +	int ret;
> +
> +	/* mask for low + normal + high, selected = normal (1) */
> +	ret = igt_sysfs_choice_format_mask(buf, sizeof(buf),
> +					   prio_names, ARRAY_SIZE(prio_names),
> +					   BIT(0) | BIT(1) | BIT(2),
> +					   1);
> +	igt_assert_eq(ret, 0);
> +	igt_assert_f(!strcmp(buf, "low [normal] high"),
> +		     "choice_format_mask produced '%s'\n", buf);
> +}
> +
> +static void test_format_mask_empty(void)
> +{
> +	char buf[128];
> +	int ret;
> +
> +	ret = igt_sysfs_choice_format_mask(buf, sizeof(buf),
> +					   prio_names, ARRAY_SIZE(prio_names),
> +					   0, -1);
> +	igt_assert_eq(ret, 0);
> +	igt_assert_eq(buf[0], '\0');
> +}
> +
> +static void test_format_mask_unknown_bit(void)
> +{
> +	char buf[128];
> +	int ret;
> +
> +	ret = igt_sysfs_choice_format_mask(buf, sizeof(buf),
> +					   prio_names, ARRAY_SIZE(prio_names),
> +					   BIT(0) | BIT(3),
> +					   0);
> +	igt_assert_eq(ret, 0);
> +	igt_assert_f(!strcmp(buf, "[low]"),
> +		     "format_mask produced '%s'\n", buf);
> +}
> +
> +static void test_intersect_basic(void)
> +{
> +	struct igt_sysfs_choice a, b;
> +	int ret;
> +
> +	parse_ok("[low] normal high\n", &a);
> +	parse_ok("low [normal] ultra\n", &b);
> +
> +	ret = igt_sysfs_choice_intersect(&a, &b);
> +	igt_assert_eq(ret, 0);
> +
> +	igt_assert_eq(a.num_tokens, 2);
> +	assert_token(&a, 0, "low");
> +	assert_token(&a, 1, "normal");
> +
> +	/* semantics: selected remains the original selected token if still common */
> +	igt_assert_eq(a.selected, 0);
> +}
> +
> +static void test_intersect_single_common(void)
> +{
> +	struct igt_sysfs_choice a, b;
> +	int ret;
> +
> +	parse_ok("low [normal] high\n", &a);
> +	parse_ok("[normal] ultra\n", &b);
> +
> +	ret = igt_sysfs_choice_intersect(&a, &b);
> +	igt_assert_eq(ret, 0);
> +
> +	igt_assert_eq(a.num_tokens, 1);
> +	assert_token(&a, 0, "normal");
> +	igt_assert_eq(a.selected, 0);
> +}
> +
> +static void test_intersect_no_common(void)
> +{
> +	struct igt_sysfs_choice a, b;
> +	int ret;
> +
> +	parse_ok("[low] normal\n", &a);
> +	parse_ok("[high] ultra\n", &b);
> +
> +	ret = igt_sysfs_choice_intersect(&a, &b);
> +	igt_assert_eq(ret, -ENOENT);
> +}
> +
> +int igt_simple_main()
> +{
> +	test_parse_basic_first_selected();
> +	test_parse_middle_selected_whitespace();
> +	test_parse_single_token();
> +	test_parse_error_missing_selected();
> +	test_parse_error_multiple_selected();
> +	test_parse_error_unterminated_bracket();
> +	test_parse_error_too_many_tokens();
> +	test_selected_basic();
> +	test_selected_invalid_index();
> +	test_to_string_roundtrip();
> +	test_find_basic();
> +	test_to_mask_basic();
> +	test_to_mask_ignores_unknown();
> +	test_to_mask_selected_unknown();
> +	test_format_mask_basic();
> +	test_format_mask_empty();
> +	test_format_mask_unknown_bit();
> +	test_intersect_basic();
> +	test_intersect_single_common();
> +	test_intersect_no_common();
> +}
> diff --git a/lib/tests/meson.build b/lib/tests/meson.build
> index 1ce19f63c..124a9ecae 100644
> --- a/lib/tests/meson.build
> +++ b/lib/tests/meson.build
> @@ -23,6 +23,7 @@ lib_tests = [
>   	'igt_simulation',
>   	'igt_stats',
>   	'igt_subtest_group',
> +	'igt_sysfs_choice',
>   	'igt_thread',
>   	'igt_types',
>   	'i915_perf_data_alignment',

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v3 i-g-t 04/10] lib/xe/xe_sriov_provisioning: Add sched priority mask to string helper
  2026-01-28 18:08 ` [PATCH v3 i-g-t 04/10] lib/xe/xe_sriov_provisioning: Add sched priority mask to string helper Marcin Bernatowicz
@ 2026-01-29  8:19   ` Laguna, Lukasz
  0 siblings, 0 replies; 19+ messages in thread
From: Laguna, Lukasz @ 2026-01-29  8:19 UTC (permalink / raw)
  To: Marcin Bernatowicz, igt-dev
  Cc: adam.miszczak, jakub1.kolakowski, michal.wajdeczko


On 1/28/2026 19:08, Marcin Bernatowicz wrote:
> Introduce xe_sriov_sched_priority_mask_to_string() to format a
> scheduling priority bitmask as a space-separated list of priority names.
> Introduce xe_sriov_sched_priority_choice_to_mask() to convert an
> igt_sysfs_choice into a bitmask and a selected priority index.
>
> Both helpers are thin wrappers around the generic igt_sysfs_choice
> functions.
>
> Signed-off-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
> Cc: Adam Miszczak <adam.miszczak@linux.intel.com>
> Cc: Jakub Kolakowski <jakub1.kolakowski@intel.com>
> Cc: Lukasz Laguna <lukasz.laguna@intel.com>

Reviewed-by: Lukasz Laguna <lukasz.laguna@intel.com>

> Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
>
> ---
> v2:
> - Make xe_sriov_sched_priority_mask_to_string() return error code
>    instead of NULL.
> - Add doc for xe_sriov_sched_priority_mask_to_string() and define it first
>
> Signed-off-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
> ---
>   lib/xe/xe_sriov_provisioning.c | 47 ++++++++++++++++++++++++++++++++++
>   lib/xe/xe_sriov_provisioning.h | 13 ++++++++++
>   2 files changed, 60 insertions(+)
>
> diff --git a/lib/xe/xe_sriov_provisioning.c b/lib/xe/xe_sriov_provisioning.c
> index c2a1db4bc..f8dda09fb 100644
> --- a/lib/xe/xe_sriov_provisioning.c
> +++ b/lib/xe/xe_sriov_provisioning.c
> @@ -9,6 +9,8 @@
>   #include "igt_core.h"
>   #include "igt_debugfs.h"
>   #include "igt_sriov_device.h"
> +#include "igt_sysfs.h"
> +#include "igt_sysfs_choice.h"
>   #include "intel_chipset.h"
>   #include "linux_scaffold.h"
>   #include "xe/xe_query.h"
> @@ -657,6 +659,51 @@ int xe_sriov_sched_priority_from_string(const char *s,
>   	return -EINVAL;
>   }
>   
> +/**
> + * xe_sriov_sched_priority_choice_to_mask - Map parsed sysfs choice to mask + selection
> + * @choice: Parsed choice (tokens + selected index)
> + * @mask: Output bitmask of known priorities present in @choice
> + * @selected_idx: Output selected priority index in the known-name table, or -1
> + *
> + * Converts an &struct igt_sysfs_choice representing the sched_priority sysfs
> + * attribute into a bitmask and an optional selected index.
> + *
> + * The bit positions in @mask correspond to &enum xe_sriov_sched_priority values
> + * (LOW/NORMAL/HIGH). Unknown tokens in @choice are ignored (best-effort), so
> + * tests can tolerate kernels that add extra choices.
> + *
> + * Return: 0 on success, -EINVAL on invalid arguments.
> + */
> +int xe_sriov_sched_priority_choice_to_mask(const struct igt_sysfs_choice *choice,
> +					   unsigned int *mask, int *selected_idx)
> +{
> +	return igt_sysfs_choice_to_mask(choice, xe_sriov_sched_priority_str,
> +					ARRAY_SIZE(xe_sriov_sched_priority_str),
> +					mask, selected_idx);
> +}
> +
> +/**
> + * xe_sriov_sched_priority_mask_to_string - Format priority mask as text
> + * @buf: Output buffer.
> + * @buf_sz: Size of @buf.
> + * @mask: Priority bitmask.
> + * @selected_idx: Index to highlight with brackets, or <0 for none.
> + *
> + * Converts @mask to a space-separated string of priority names. If @selected_idx
> + * is >= 0 and present in @mask, that priority is wrapped in brackets, e.g.
> + * "low [normal] high". An empty @mask results in an empty string.
> + *
> + * Return: 0 on success, -EINVAL on invalid args, -E2BIG if @buf_sz is too small.
> + */
> +int xe_sriov_sched_priority_mask_to_string(char *buf, size_t buf_sz,
> +					   unsigned int mask, int selected_idx)
> +{
> +	return igt_sysfs_choice_format_mask(buf, buf_sz,
> +					 xe_sriov_sched_priority_str,
> +					 ARRAY_SIZE(xe_sriov_sched_priority_str),
> +					 mask, selected_idx);
> +}
> +
>   /**
>    * __xe_sriov_get_sched_priority - Get the scheduling priority for a given VF
>    * @pf: PF device file descriptor
> diff --git a/lib/xe/xe_sriov_provisioning.h b/lib/xe/xe_sriov_provisioning.h
> index c9b321d58..6661b33cc 100644
> --- a/lib/xe/xe_sriov_provisioning.h
> +++ b/lib/xe/xe_sriov_provisioning.h
> @@ -9,6 +9,7 @@
>   #include <stdint.h>
>   
>   struct xe_mmio;
> +struct igt_sysfs_choice;
>   
>   /**
>    * enum xe_sriov_shared_res - Shared resource types
> @@ -75,6 +76,14 @@ enum xe_sriov_sched_priority {
>   	XE_SRIOV_SCHED_PRIORITY_HIGH
>   };
>   
> +#define XE_SRIOV_SCHED_PRIORITY_MASK_LOW    BIT(XE_SRIOV_SCHED_PRIORITY_LOW)
> +#define XE_SRIOV_SCHED_PRIORITY_MASK_NORMAL BIT(XE_SRIOV_SCHED_PRIORITY_NORMAL)
> +#define XE_SRIOV_SCHED_PRIORITY_MASK_HIGH   BIT(XE_SRIOV_SCHED_PRIORITY_HIGH)
> +#define XE_SRIOV_SCHED_PRIORITY_MASK_ALL \
> +	(XE_SRIOV_SCHED_PRIORITY_MASK_LOW | \
> +	 XE_SRIOV_SCHED_PRIORITY_MASK_NORMAL | \
> +	 XE_SRIOV_SCHED_PRIORITY_MASK_HIGH)
> +
>   /**
>    * struct xe_sriov_provisioned_range - Provisioned range for a Virtual Function (VF)
>    * @vf_id: The ID of the VF
> @@ -138,6 +147,10 @@ int __xe_sriov_set_sched_if_idle(int pf, unsigned int gt_num, bool value);
>   void xe_sriov_set_sched_if_idle(int pf, unsigned int gt_num, bool value);
>   const char *xe_sriov_sched_priority_to_string(enum xe_sriov_sched_priority value);
>   int xe_sriov_sched_priority_from_string(const char *s, enum xe_sriov_sched_priority *value);
> +int xe_sriov_sched_priority_choice_to_mask(const struct igt_sysfs_choice *choice,
> +					   unsigned int *mask, int *selected_idx);
> +int xe_sriov_sched_priority_mask_to_string(char *buf, size_t buf_sz,
> +					   unsigned int mask, int selected_idx);
>   int __xe_sriov_get_sched_priority(int pf, unsigned int vf_num,
>   				  unsigned int gt_num,
>   				  enum xe_sriov_sched_priority *value);

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v3 i-g-t 06/10] lib/xe/xe_sriov_admin: Add SR-IOV admin sysfs accessors
  2026-01-28 18:08 ` [PATCH v3 i-g-t 06/10] lib/xe/xe_sriov_admin: Add SR-IOV admin sysfs accessors Marcin Bernatowicz
@ 2026-01-29  8:21   ` Laguna, Lukasz
  0 siblings, 0 replies; 19+ messages in thread
From: Laguna, Lukasz @ 2026-01-29  8:21 UTC (permalink / raw)
  To: Marcin Bernatowicz, igt-dev
  Cc: adam.miszczak, jakub1.kolakowski, michal.wajdeczko


On 1/28/2026 19:08, Marcin Bernatowicz wrote:
> Reflect recent kernel changes and expose SR-IOV admin sysfs helpers for
> scheduling control. Add per-VF and bulk accessors for execution quantum,
> preemption timeout, scheduling priority, VF stop and restoring defaults.
>
> Link: https://lore.kernel.org/intel-xe/20251030222348.186658-1-michal.wajdeczko@intel.com/
> Signed-off-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
> Cc: Adam Miszczak <adam.miszczak@linux.intel.com>
> Cc: Jakub Kolakowski <jakub1.kolakowski@intel.com>
> Cc: Lukasz Laguna <lukasz.laguna@intel.com>

Reviewed-by: Lukasz Laguna <lukasz.laguna@intel.com>

> Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
>
> ---
> v2:
> - Correct __xe_sriov_profile_set_exec_quantum_ms return code
>    on igt_sysfs_open() fail.
> - Correct formatting.
> - Rename helpers to consistent __xe_sriov_admin_*/xe_sriov_admin_*
>
> Signed-off-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
> ---
>   lib/meson.build         |   1 +
>   lib/xe/xe_sriov_admin.c | 625 ++++++++++++++++++++++++++++++++++++++++
>   lib/xe/xe_sriov_admin.h |  60 ++++
>   3 files changed, 686 insertions(+)
>   create mode 100644 lib/xe/xe_sriov_admin.c
>   create mode 100644 lib/xe/xe_sriov_admin.h
>
> diff --git a/lib/meson.build b/lib/meson.build
> index 83569e8d2..d851029e0 100644
> --- a/lib/meson.build
> +++ b/lib/meson.build
> @@ -128,6 +128,7 @@ lib_sources = [
>   	'xe/xe_mmio.c',
>   	'xe/xe_query.c',
>   	'xe/xe_spin.c',
> +	'xe/xe_sriov_admin.c',
>   	'xe/xe_sriov_debugfs.c',
>   	'xe/xe_sriov_provisioning.c',
>   	'xe/xe_util.c',
> diff --git a/lib/xe/xe_sriov_admin.c b/lib/xe/xe_sriov_admin.c
> new file mode 100644
> index 000000000..f3be70db8
> --- /dev/null
> +++ b/lib/xe/xe_sriov_admin.c
> @@ -0,0 +1,625 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright(c) 2025 Intel Corporation. All rights reserved.
> + */
> +
> +#include <errno.h>
> +#include <fcntl.h>
> +#include <limits.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <unistd.h>
> +#include "igt.h"
> +#include "igt_sriov_device.h"
> +#include "igt_sysfs.h"
> +#include "igt_sysfs_choice.h"
> +#include "xe_sriov_admin.h"
> +
> +static const char SRIOV_ADMIN[] = "device/sriov_admin";
> +
> +static int fmt_profile_rel_path(char *buf, size_t sz, unsigned int vf_num,
> +				const char *attr)
> +{
> +	igt_assert(buf && attr && sz);
> +
> +	return snprintf(buf, sz, "%s/%s/%s", SRIOV_ADMIN, igt_sriov_func_str(vf_num), attr);
> +}
> +
> +static int fmt_bulk_rel_path(char *buf, size_t sz, const char *attr)
> +{
> +	igt_assert(buf && attr && sz);
> +
> +	return snprintf(buf, sz, "%s/.bulk_profile/%s", SRIOV_ADMIN, attr);
> +}
> +
> +static int ret_from_printf(int ret)
> +{
> +	return ret > 0 ? 0 : ret;
> +}
> +
> +static int ret_from_scanf_items(int ret, int want_items)
> +{
> +	/* igt_sysfs_scanf: returns number of assigned items, or <0 on -errno */
> +	if (ret < 0)
> +		return ret;
> +	return (ret == want_items) ? 0 : -EIO;
> +}
> +
> +/**
> + * xe_sriov_admin_is_present - Check if SR-IOV admin sysfs interface is available
> + * @pf_fd: PF device file descriptor.
> + *
> + * Returns: true if the PF exposes the SR-IOV admin tree, false otherwise.
> + */
> +bool xe_sriov_admin_is_present(int pf_fd)
> +{
> +	int sysfs;
> +	bool ret;
> +
> +	sysfs = igt_sysfs_open(pf_fd);
> +	if (sysfs < 0)
> +		return -1;
> +
> +	ret = igt_sysfs_has_attr(sysfs, SRIOV_ADMIN);
> +	close(sysfs);
> +	return ret;
> +}
> +
> +/**
> + * __xe_sriov_admin_set_exec_quantum_ms - Set execution quantum for a VF
> + * @pf_fd:   PF device file descriptor.
> + * @vf_num:  VF index (0 for PF, >0 for VFs).
> + * @eq_ms:   Execution quantum in milliseconds.
> + *
> + * Writes the new execution quantum to sysfs.
> + *
> + * Returns: 0 on success or negative errno on error.
> + */
> +int __xe_sriov_admin_set_exec_quantum_ms(int pf_fd, unsigned int vf_num,
> +					 uint32_t eq_ms)
> +{
> +	char path[PATH_MAX];
> +	int sysfs;
> +	bool ret;
> +
> +	sysfs = igt_sysfs_open(pf_fd);
> +	if (sysfs < 0)
> +		return sysfs;
> +
> +	fmt_profile_rel_path(path, sizeof(path), vf_num, "profile/exec_quantum_ms");
> +	ret = igt_sysfs_printf(sysfs, path, "%u", eq_ms);
> +	close(sysfs);
> +
> +	return ret_from_printf(ret);
> +}
> +
> +/**
> + * xe_sriov_admin_set_exec_quantum_ms - Assert wrapper for setting VF execution quantum
> + * @pf_fd:   PF device file descriptor.
> + * @vf_num:  VF index (0 for PF, >0 for VFs).
> + * @eq_ms:   Execution quantum in milliseconds.
> + *
> + * Calls __xe_sriov_admin_set_exec_quantum_ms() and asserts on error.
> + */
> +void xe_sriov_admin_set_exec_quantum_ms(int pf_fd, unsigned int vf_num, uint32_t eq_ms)
> +{
> +	igt_assert_eq(0, __xe_sriov_admin_set_exec_quantum_ms(pf_fd, vf_num, eq_ms));
> +}
> +
> +/**
> + * __xe_sriov_admin_get_exec_quantum_ms - Read execution quantum for a VF
> + * @pf_fd:   PF device file descriptor.
> + * @vf_num:  VF index (0 for PF, >0 for VFs).
> + * @eq_ms:   Output pointer for the execution quantum (ms).
> + *
> + * Reads current VF execution quantum from sysfs.
> + *
> + * Returns: 0 on success or negative errno on error.
> + */
> +int __xe_sriov_admin_get_exec_quantum_ms(int pf_fd, unsigned int vf_num, uint32_t *eq_ms)
> +{
> +	char path[PATH_MAX];
> +	unsigned int val = 0;
> +	int sysfs, ret;
> +
> +	sysfs = igt_sysfs_open(pf_fd);
> +	if (sysfs < 0)
> +		return sysfs;
> +
> +	fmt_profile_rel_path(path, sizeof(path), vf_num, "profile/exec_quantum_ms");
> +	ret = igt_sysfs_scanf(sysfs, path, "%u", &val);
> +	close(sysfs);
> +
> +	ret = ret_from_scanf_items(ret, 1);
> +	if (ret)
> +		return ret;
> +
> +	*eq_ms = val;
> +	return 0;
> +}
> +
> +/**
> + * xe_sriov_admin_get_exec_quantum_ms - Assert wrapper for reading VF execution quantum
> + * @pf_fd:   PF device file descriptor.
> + * @vf_num:  VF index (0 for PF, >0 for VFs).
> + *
> + * Returns: execution quantum (ms); asserts on error.
> + */
> +uint32_t xe_sriov_admin_get_exec_quantum_ms(int pf_fd, unsigned int vf_num)
> +{
> +	uint32_t v = 0;
> +
> +	igt_assert_eq(0, __xe_sriov_admin_get_exec_quantum_ms(pf_fd, vf_num, &v));
> +
> +	return v;
> +}
> +
> +/**
> + * __xe_sriov_admin_set_preempt_timeout_us - Set preemption timeout for a VF
> + * @pf_fd:   PF device file descriptor.
> + * @vf_num:  VF index (0 for PF, >0 for VFs).
> + * @pt_us:   Preemption timeout in microseconds.
> + *
> + * Returns: 0 on success or negative errno on error.
> + */
> +int __xe_sriov_admin_set_preempt_timeout_us(int pf_fd, unsigned int vf_num, uint32_t pt_us)
> +{
> +	char path[PATH_MAX];
> +	int sysfs, ret;
> +
> +	sysfs = igt_sysfs_open(pf_fd);
> +	if (sysfs < 0)
> +		return sysfs;
> +
> +	fmt_profile_rel_path(path, sizeof(path), vf_num, "profile/preempt_timeout_us");
> +	ret = igt_sysfs_printf(sysfs, path, "%u", pt_us);
> +	close(sysfs);
> +
> +	return ret_from_printf(ret);
> +}
> +
> +/**
> + * xe_sriov_admin_set_preempt_timeout_us - Assert wrapper for setting VF preemption timeout
> + * @pf_fd:   PF device file descriptor.
> + * @vf_num:  VF index (0 for PF, >0 for VFs).
> + * @pt_us:   Preemption timeout in microseconds.
> + */
> +void xe_sriov_admin_set_preempt_timeout_us(int pf_fd, unsigned int vf_num, uint32_t pt_us)
> +{
> +	igt_assert_eq(0, __xe_sriov_admin_set_preempt_timeout_us(pf_fd, vf_num, pt_us));
> +}
> +
> +/**
> + * __xe_sriov_admin_get_preempt_timeout_us - Read preemption timeout for a VF
> + * @pf_fd:   PF device file descriptor.
> + * @vf_num:  VF index (0 for PF, >0 for VFs).
> + * @pt_us:   Output pointer for preemption timeout (µs).
> + *
> + * Returns: 0 on success or negative errno on error.
> + */
> +int __xe_sriov_admin_get_preempt_timeout_us(int pf_fd, unsigned int vf_num,
> +					    uint32_t *pt_us)
> +{
> +	char path[PATH_MAX];
> +	unsigned int val = 0;
> +	int sysfs, ret;
> +
> +	sysfs = igt_sysfs_open(pf_fd);
> +	if (sysfs < 0)
> +		return sysfs;
> +
> +	fmt_profile_rel_path(path, sizeof(path), vf_num,
> +			     "profile/preempt_timeout_us");
> +	ret = igt_sysfs_scanf(sysfs, path, "%u", &val);
> +	close(sysfs);
> +
> +	ret = ret_from_scanf_items(ret, 1);
> +	if (ret)
> +		return ret;
> +	*pt_us = val;
> +	return 0;
> +}
> +
> +/**
> + * xe_sriov_admin_get_preempt_timeout_us - Assert wrapper for reading VF preemption timeout
> + * @pf_fd:   PF device file descriptor.
> + * @vf_num:  VF index (0 for PF, >0 for VFs).
> + *
> + * Returns: preemption timeout (µs); asserts on error.
> + */
> +uint32_t xe_sriov_admin_get_preempt_timeout_us(int pf_fd, unsigned int vf_num)
> +{
> +	uint32_t v = 0;
> +
> +	igt_assert_eq(0, __xe_sriov_admin_get_preempt_timeout_us(pf_fd, vf_num, &v));
> +	return v;
> +}
> +
> +/**
> + * __xe_sriov_admin_set_sched_priority_string - Set VF priority from string
> + * @pf_fd:   PF device file descriptor.
> + * @vf_num:  VF index (0 for PF, >0 for VFs).
> + * @prio:    String value ("low", "normal", "high").
> + *
> + * Returns: 0 on success or negative errno on error.
> + */
> +int __xe_sriov_admin_set_sched_priority_string(int pf_fd, unsigned int vf_num,
> +					       const char *prio)
> +{
> +	char path[PATH_MAX];
> +	int sysfs, ret;
> +
> +	if (!prio)
> +		return -EINVAL;
> +
> +	sysfs = igt_sysfs_open(pf_fd);
> +	if (sysfs < 0)
> +		return sysfs;
> +
> +	fmt_profile_rel_path(path, sizeof(path), vf_num,
> +			     "profile/sched_priority");
> +	ret = igt_sysfs_printf(sysfs, path, "%s", prio);
> +	close(sysfs);
> +	return ret_from_printf(ret);
> +}
> +
> +/**
> + * __xe_sriov_admin_set_sched_priority - Set VF scheduling priority
> + * @pf_fd:   PF device file descriptor.
> + * @vf_num:  VF index (0 for PF, >0 for VFs).
> + * @prio:    Priority enum value.
> + *
> + * Returns: 0 on success or negative errno on error.
> + */
> +int __xe_sriov_admin_set_sched_priority(int pf_fd, unsigned int vf_num,
> +					enum xe_sriov_sched_priority prio)
> +{
> +	const char *p = xe_sriov_sched_priority_to_string(prio);
> +
> +	return __xe_sriov_admin_set_sched_priority_string(pf_fd, vf_num, p);
> +}
> +
> +/**
> + * xe_sriov_admin_set_sched_priority - Assert wrapper for setting VF priority
> + * @pf_fd:   PF device file descriptor.
> + * @vf_num:  VF index (0 for PF, >0 for VFs).
> + * @prio:    Priority enum value.
> + */
> +void xe_sriov_admin_set_sched_priority(int pf_fd, unsigned int vf_num,
> +				       enum xe_sriov_sched_priority prio)
> +{
> +	igt_assert_eq(0, __xe_sriov_admin_set_sched_priority(pf_fd, vf_num, prio));
> +}
> +
> +/**
> + * __xe_sriov_admin_get_sched_priority_choice - Read sched_priority tokens
> + * @pf_fd:   PF device file descriptor
> + * @vf_num:  VF index (0 for PF, >0 for VFs).
> + * @choice:  Output choice structure with parsed tokens and selected index
> + *
> + * Reads the sched_priority sysfs attribute for the given PF/VF and parses it
> + * into an igt_sysfs_choice.
> + *
> + * Returns: 0 on success or a negative errno code.
> + */
> +int __xe_sriov_admin_get_sched_priority_choice(int pf_fd, unsigned int vf_num,
> +					       struct igt_sysfs_choice *choice)
> +{
> +	char path[PATH_MAX];
> +	int sysfs, ret;
> +
> +	sysfs = igt_sysfs_open(pf_fd);
> +	if (sysfs < 0)
> +		return sysfs;
> +
> +	fmt_profile_rel_path(path, sizeof(path), vf_num, "profile/sched_priority");
> +	ret = igt_sysfs_choice_read(sysfs, path, choice);
> +	close(sysfs);
> +
> +	return ret;
> +}
> +
> +/**
> + * __xe_sriov_admin_get_sched_priority - Read VF scheduling priority + mask
> + * @pf_fd:     PF device file descriptor.
> + * @vf_num:    VF index (0 for PF, >0 for VFs).
> + * @prio:      Output pointer for the effective priority.
> + * @prio_mask: Output mask of allowed priorities.
> + *
> + * Returns: 0 on success or negative errno on error.
> + */
> +int __xe_sriov_admin_get_sched_priority(int pf_fd, unsigned int vf_num,
> +					enum xe_sriov_sched_priority *prio,
> +					unsigned int *prio_mask)
> +{
> +	struct igt_sysfs_choice prio_ch = {};
> +	int ret;
> +
> +	ret = __xe_sriov_admin_get_sched_priority_choice(pf_fd, vf_num, &prio_ch);
> +	if (ret)
> +		return ret;
> +
> +	ret = xe_sriov_sched_priority_from_string(prio_ch.tokens[prio_ch.selected], prio);
> +	if (igt_debug_on_f(ret, "unknown selected value '%s' (err=%d)\n",
> +			   prio_ch.tokens[prio_ch.selected], ret))
> +		return ret;
> +
> +	if (prio_mask) {
> +		ret = xe_sriov_sched_priority_choice_to_mask(&prio_ch, prio_mask, NULL);
> +		if (igt_debug_on_f(ret, "mask conversion failed (err=%d)\n", ret))
> +			return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +/**
> + * xe_sriov_admin_get_sched_priority - Assert wrapper for reading VF priority
> + * @pf_fd:     PF device file descriptor.
> + * @vf_num:    VF index (0 for PF, >0 for VFs).
> + * @prio_mask: Output mask of supported priorities.
> + *
> + * Returns: effective priority; asserts on error.
> + */
> +enum xe_sriov_sched_priority
> +xe_sriov_admin_get_sched_priority(int pf_fd, unsigned int vf_num,
> +				  unsigned int *prio_mask)
> +{
> +	enum xe_sriov_sched_priority cur_prio;
> +
> +	igt_assert_eq(0,
> +		      __xe_sriov_admin_get_sched_priority(pf_fd, vf_num, &cur_prio, prio_mask));
> +
> +	return cur_prio;
> +}
> +
> +/**
> + * __xe_sriov_admin_bulk_set_exec_quantum_ms - Set execution quantum for PF and all VFs
> + * @pf_fd: PF device file descriptor.
> + * @eq_ms: Execution quantum in milliseconds.
> + *
> + * Applies the value to PF and all VFs.
> + *
> + * Returns: 0 on success or negative errno on error.
> + */
> +int __xe_sriov_admin_bulk_set_exec_quantum_ms(int pf_fd, uint32_t eq_ms)
> +{
> +	char path[PATH_MAX];
> +	int sysfs, ret;
> +
> +	sysfs = igt_sysfs_open(pf_fd);
> +	if (sysfs < 0)
> +		return sysfs;
> +
> +	fmt_bulk_rel_path(path, sizeof(path), "exec_quantum_ms");
> +	ret = igt_sysfs_printf(sysfs, path, "%u", eq_ms);
> +	close(sysfs);
> +
> +	return ret_from_printf(ret);
> +}
> +
> +/**
> + * xe_sriov_admin_bulk_set_exec_quantum_ms - Assert wrapper for bulk execution quantum update
> + * @pf_fd: PF device file descriptor.
> + * @eq_ms: Execution quantum in milliseconds.
> + */
> +void xe_sriov_admin_bulk_set_exec_quantum_ms(int pf_fd, uint32_t eq_ms)
> +{
> +	igt_assert_eq(0, __xe_sriov_admin_bulk_set_exec_quantum_ms(pf_fd, eq_ms));
> +}
> +
> +/**
> + * __xe_sriov_admin_bulk_set_preempt_timeout_us - Set preemption timeout for PF and all VFs
> + * @pf_fd: PF device file descriptor.
> + * @pt_us: Preemption timeout in microseconds.
> + *
> + * Applies the value to PF and all VFs.
> + *
> + * Returns: 0 on success or negative errno on error.
> + */
> +int __xe_sriov_admin_bulk_set_preempt_timeout_us(int pf_fd, uint32_t pt_us)
> +{
> +	char path[PATH_MAX];
> +	int sysfs, ret;
> +
> +	sysfs = igt_sysfs_open(pf_fd);
> +	if (sysfs < 0)
> +		return sysfs;
> +
> +	fmt_bulk_rel_path(path, sizeof(path), "preempt_timeout_us");
> +	ret = igt_sysfs_printf(sysfs, path, "%u", pt_us);
> +	close(sysfs);
> +
> +	return ret_from_printf(ret);
> +}
> +
> +/**
> + * xe_sriov_admin_bulk_set_preempt_timeout_us - Assert wrapper for bulk preemption timeout update
> + * @pf_fd: PF device file descriptor.
> + * @pt_us: Preemption timeout in microseconds.
> + */
> +void xe_sriov_admin_bulk_set_preempt_timeout_us(int pf_fd, uint32_t pt_us)
> +{
> +	igt_assert_eq(0, __xe_sriov_admin_bulk_set_preempt_timeout_us(pf_fd, pt_us));
> +}
> +
> +/**
> + * __xe_sriov_admin_bulk_set_sched_priority_string - Set scheduling priority for PF and all VFs
> + * @pf_fd: PF device file descriptor.
> + * @prio:  String priority ("low", "normal", "high").
> + *
> + * Returns: 0 on success or negative errno on error.
> + */
> +int __xe_sriov_admin_bulk_set_sched_priority_string(int pf_fd, const char *prio)
> +{
> +	char path[PATH_MAX];
> +	int sysfs, ret;
> +
> +	sysfs = igt_sysfs_open(pf_fd);
> +	if (sysfs < 0)
> +		return sysfs;
> +
> +	fmt_bulk_rel_path(path, sizeof(path), "sched_priority");
> +	ret = igt_sysfs_printf(sysfs, path, "%s", prio);
> +	close(sysfs);
> +
> +	return ret_from_printf(ret);
> +}
> +
> +/**
> + * xe_sriov_admin_bulk_set_sched_priority_string - Assert wrapper for bulk priority update
> + * @pf_fd: PF device file descriptor.
> + * @prio:  String priority.
> + */
> +void xe_sriov_admin_bulk_set_sched_priority_string(int pf_fd, const char *prio)
> +{
> +	igt_assert_eq(0, __xe_sriov_admin_bulk_set_sched_priority_string(pf_fd, prio));
> +}
> +
> +/**
> + * __xe_sriov_admin_bulk_set_sched_priority - Set numeric priority for PF and all VFs
> + * @pf_fd: PF device file descriptor.
> + * @prio:  Enum priority value.
> + *
> + * Returns: 0 on success or negative errno on error.
> + */
> +int __xe_sriov_admin_bulk_set_sched_priority(int pf_fd,
> +					     enum xe_sriov_sched_priority prio)
> +{
> +	const char *s = xe_sriov_sched_priority_to_string(prio);
> +
> +	if (!s)
> +		return -EINVAL;
> +	return __xe_sriov_admin_bulk_set_sched_priority_string(pf_fd, s);
> +}
> +
> +/**
> + * xe_sriov_admin_bulk_set_sched_priority - Assert wrapper for bulk priority update
> + * @pf_fd: PF device file descriptor.
> + * @prio:  Enum priority value.
> + */
> +void xe_sriov_admin_bulk_set_sched_priority(int pf_fd,
> +					    enum xe_sriov_sched_priority prio)
> +{
> +	igt_assert_eq(0, __xe_sriov_admin_bulk_set_sched_priority(pf_fd, prio));
> +}
> +
> +/**
> + * __xe_sriov_admin_vf_stop - Issue stop command for a VF
> + * @pf_fd:  PF device file descriptor.
> + * @vf_num: VF index.
> + *
> + * Triggers VF stop via sysfs.
> + *
> + * Returns: 0 on success or negative errno on error.
> + */
> +int __xe_sriov_admin_vf_stop(int pf_fd, unsigned int vf_num)
> +{
> +	char path[PATH_MAX];
> +	int sysfs, ret;
> +
> +	sysfs = igt_sysfs_open(pf_fd);
> +	if (sysfs < 0)
> +		return sysfs;
> +
> +	fmt_profile_rel_path(path, sizeof(path), vf_num, "stop");
> +	ret = igt_sysfs_printf(sysfs, path, "%u", 1u);
> +	close(sysfs);
> +
> +	return ret_from_printf(ret);
> +}
> +
> +/**
> + * xe_sriov_admin_vf_stop - Assert wrapper for VF stop command
> + * @pf_fd:  PF device file descriptor.
> + * @vf_num: VF index.
> + */
> +void xe_sriov_admin_vf_stop(int pf_fd, unsigned int vf_num)
> +{
> +	igt_assert_eq(0, __xe_sriov_admin_vf_stop(pf_fd, vf_num));
> +}
> +
> +/**
> + * __xe_sriov_admin_restore_defaults - Restore scheduling defaults for a VF
> + * @pf_fd:  PF device file descriptor.
> + * @vf_num: VF index (0 for PF, >0 for VFs).
> + *
> + * Resets execution quantum, preemption timeout, and priority to driver defaults.
> + *
> + * Returns: 0 on success or negative errno on error.
> + */
> +int __xe_sriov_admin_restore_defaults(int pf_fd, unsigned int vf_num)
> +{
> +	int ret_eq, ret_pt, ret_prio;
> +	int ret = 0;
> +
> +	ret_eq = __xe_sriov_admin_set_exec_quantum_ms(pf_fd, vf_num, 0);
> +	igt_warn_on(ret_eq);
> +	if (!ret)
> +		ret = ret_eq;
> +
> +	ret_pt = __xe_sriov_admin_set_preempt_timeout_us(pf_fd, vf_num, 0);
> +	igt_warn_on(ret_pt);
> +	if (!ret)
> +		ret = ret_pt;
> +
> +	ret_prio = __xe_sriov_admin_set_sched_priority(pf_fd, vf_num,
> +						       XE_SRIOV_SCHED_PRIORITY_LOW);
> +	igt_warn_on(ret_prio);
> +	if (!ret)
> +		ret = ret_prio;
> +
> +	return ret;
> +}
> +
> +/**
> + * xe_sriov_admin_restore_defaults - Assert wrapper restoring VF defaults
> + * @pf_fd:  PF device file descriptor.
> + * @vf_num: VF index (0 for PF, >0 for VFs).
> + */
> +void xe_sriov_admin_restore_defaults(int pf_fd, unsigned int vf_num)
> +{
> +	igt_assert_eq(0, __xe_sriov_admin_restore_defaults(pf_fd, vf_num));
> +}
> +
> +/**
> + * __xe_sriov_admin_bulk_restore_defaults - Restore scheduling defaults for PF and all VFs
> + * @pf_fd: PF device file descriptor.
> + *
> + * Resets PF and all VFs to driver default scheduling parameters.
> + *
> + * Returns: 0 on success or negative errno on error.
> + */
> +int __xe_sriov_admin_bulk_restore_defaults(int pf_fd)
> +{
> +	int ret_eq, ret_pt, ret_prio;
> +	int ret = 0;
> +
> +	ret_eq = __xe_sriov_admin_bulk_set_exec_quantum_ms(pf_fd, 0);
> +	igt_warn_on(ret_eq);
> +	if (!ret)
> +		ret = ret_eq;
> +
> +	ret_pt = __xe_sriov_admin_bulk_set_preempt_timeout_us(pf_fd, 0);
> +	igt_warn_on(ret_pt);
> +	if (!ret)
> +		ret = ret_pt;
> +
> +	ret_prio = __xe_sriov_admin_bulk_set_sched_priority(pf_fd,
> +							    XE_SRIOV_SCHED_PRIORITY_LOW);
> +	igt_warn_on(ret_prio);
> +	if (!ret)
> +		ret = ret_prio;
> +
> +	return ret;
> +}
> +
> +/**
> + * xe_sriov_admin_bulk_restore_defaults - Assert wrapper for restoring defaults on PF and all VFs
> + * @pf_fd: PF device file descriptor.
> + */
> +void xe_sriov_admin_bulk_restore_defaults(int pf_fd)
> +{
> +	igt_assert_eq(0, __xe_sriov_admin_bulk_restore_defaults(pf_fd));
> +}
> diff --git a/lib/xe/xe_sriov_admin.h b/lib/xe/xe_sriov_admin.h
> new file mode 100644
> index 000000000..607e33a86
> --- /dev/null
> +++ b/lib/xe/xe_sriov_admin.h
> @@ -0,0 +1,60 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright(c) 2025 Intel Corporation. All rights reserved.
> + */
> +
> +#ifndef __XE_SRIOV_ADMIN_H__
> +#define __XE_SRIOV_ADMIN_H__
> +
> +#include <stdbool.h>
> +#include <stdint.h>
> +#include <stddef.h>
> +#include "xe_sriov_provisioning.h" /* for enum xe_sriov_sched_priority */
> +
> +struct igt_sysfs_choice;
> +
> +bool xe_sriov_admin_is_present(int pf_fd);
> +
> +int  __xe_sriov_admin_set_exec_quantum_ms(int pf_fd, unsigned int vf_num, uint32_t eq_ms);
> +void  xe_sriov_admin_set_exec_quantum_ms(int pf_fd, unsigned int vf_num, uint32_t eq_ms);
> +int  __xe_sriov_admin_get_exec_quantum_ms(int pf_fd, unsigned int vf_num, uint32_t *eq_ms);
> +uint32_t xe_sriov_admin_get_exec_quantum_ms(int pf_fd, unsigned int vf_num);
> +int  __xe_sriov_admin_set_preempt_timeout_us(int pf_fd, unsigned int vf_num, uint32_t pt_us);
> +void  xe_sriov_admin_set_preempt_timeout_us(int pf_fd, unsigned int vf_num, uint32_t pt_us);
> +int  __xe_sriov_admin_get_preempt_timeout_us(int pf_fd, unsigned int vf_num, uint32_t *pt_us);
> +uint32_t xe_sriov_admin_get_preempt_timeout_us(int pf_fd, unsigned int vf_num);
> +int __xe_sriov_admin_set_sched_priority_string(int pf_fd, unsigned int vf_num,
> +					       const char *prio);
> +int __xe_sriov_admin_get_sched_priority_choice(int pf_fd, unsigned int vf_num,
> +					       struct igt_sysfs_choice *choice);
> +int __xe_sriov_admin_set_sched_priority(int pf_fd, unsigned int vf_num,
> +					enum xe_sriov_sched_priority prio);
> +void xe_sriov_admin_set_sched_priority(int pf_fd, unsigned int vf_num,
> +				       enum xe_sriov_sched_priority prio);
> +int __xe_sriov_admin_get_sched_priority(int pf_fd, unsigned int vf_num,
> +					enum xe_sriov_sched_priority *prio,
> +					unsigned int *prio_mask);
> +enum xe_sriov_sched_priority
> +xe_sriov_admin_get_sched_priority(int pf_fd, unsigned int vf_num,
> +				  unsigned int *prio_mask);
> +
> +int  __xe_sriov_admin_bulk_set_exec_quantum_ms(int pf_fd, uint32_t eq_ms);
> +void  xe_sriov_admin_bulk_set_exec_quantum_ms(int pf_fd, uint32_t eq_ms);
> +int  __xe_sriov_admin_bulk_set_preempt_timeout_us(int pf_fd, uint32_t pt_us);
> +void  xe_sriov_admin_bulk_set_preempt_timeout_us(int pf_fd, uint32_t pt_us);
> +int  __xe_sriov_admin_bulk_set_sched_priority_string(int pf_fd, const char *prio);
> +void  xe_sriov_admin_bulk_set_sched_priority_string(int pf_fd, const char *prio);
> +int __xe_sriov_admin_bulk_set_sched_priority(int pf_fd,
> +					     enum xe_sriov_sched_priority prio);
> +void xe_sriov_admin_bulk_set_sched_priority(int pf_fd,
> +					    enum xe_sriov_sched_priority prio);
> +
> +int  __xe_sriov_admin_vf_stop(int pf_fd, unsigned int vf_num);
> +void  xe_sriov_admin_vf_stop(int pf_fd, unsigned int vf_num);
> +
> +int  __xe_sriov_admin_restore_defaults(int pf_fd, unsigned int vf_num);
> +void  xe_sriov_admin_restore_defaults(int pf_fd, unsigned int vf_num);
> +int  __xe_sriov_admin_bulk_restore_defaults(int pf_fd);
> +void  xe_sriov_admin_bulk_restore_defaults(int pf_fd);
> +
> +#endif /* __XE_SRIOV_ADMIN_H__ */

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v3 i-g-t 10/10] tests/intel/xe_sriov_admin: Add SR-IOV admin sysfs scheduling attributes tests
  2026-01-28 18:08 ` [PATCH v3 i-g-t 10/10] tests/intel/xe_sriov_admin: Add SR-IOV admin sysfs scheduling attributes tests Marcin Bernatowicz
@ 2026-01-29  8:21   ` Laguna, Lukasz
  0 siblings, 0 replies; 19+ messages in thread
From: Laguna, Lukasz @ 2026-01-29  8:21 UTC (permalink / raw)
  To: Marcin Bernatowicz, igt-dev
  Cc: adam.miszczak, jakub1.kolakowski, michal.wajdeczko,
	Kamil Konieczny


On 1/28/2026 19:08, Marcin Bernatowicz wrote:
> Add tests that exercise SR-IOV admin sysfs attributes for PF/VF functions
> with VFs disabled, covering default values, write -> readback behavior, and
> bulk updates for exec_quantum_ms, preempt_timeout_us, and sched_priority.
>
> Signed-off-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
> Cc: Adam Miszczak <adam.miszczak@linux.intel.com>
> Cc: Jakub Kolakowski <jakub1.kolakowski@intel.com>
> Cc: Kamil Konieczny <kamil.konieczny@linux.intel.com>
> Cc: Lukasz Laguna <lukasz.laguna@intel.com>

Reviewed-by: Lukasz Laguna <lukasz.laguna@intel.com>

> Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
>
> ---
> v2:
> - Align igt_main()/igt_fixture() usage with upstream changes.
> - Correct date
> - Replace id with vf_id
> - Iterate all VF sched_priority tokens and verify denied
>    writes don’t change selection. (Lukasz)
> - Rename xe_sriov_admin_profile to xe_sriov_admin (Lukasz)
> - Adjust test for xe_sriov_sched_priority_mask_to_string() returning
>    error code.
> - Adjust to renamed __xe_sriov_admin_* helpers
>
> Signed-off-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
> ---
>   tests/intel/xe_sriov_admin.c | 434 +++++++++++++++++++++++++++++++++++
>   tests/meson.build            |   1 +
>   2 files changed, 435 insertions(+)
>   create mode 100644 tests/intel/xe_sriov_admin.c
>
> diff --git a/tests/intel/xe_sriov_admin.c b/tests/intel/xe_sriov_admin.c
> new file mode 100644
> index 000000000..5c7f5d621
> --- /dev/null
> +++ b/tests/intel/xe_sriov_admin.c
> @@ -0,0 +1,434 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2026 Intel Corporation
> + */
> +#include "igt.h"
> +#include "igt_sriov_device.h"
> +#include "igt_sysfs.h"
> +#include "igt_sysfs_choice.h"
> +#include "xe_drm.h"
> +#include "xe/xe_sriov_admin.h"
> +
> +/**
> + * TEST: Tests for SR-IOV admin sysfs.
> + * Category: Core
> + * Mega feature: SR-IOV
> + * Sub-category: sysfs
> + * Functionality: SR-IOV admin sysfs
> + * Description: Verify behavior of exposed SR-IOV admin sysfs attributes.
> + */
> +
> +/**
> + * SUBTEST: default-sched-attributes-vfs-disabled
> + * Description:
> + *   Verify default scheduling attributes under sriov_admin
> + *   with VFs disabled.
> + */
> +static void default_sched_attributes(int pf_fd, int vf_num)
> +{
> +	igt_dynamic_f("%s-default-exec-quantum", igt_sriov_func_str(vf_num)) {
> +		igt_assert_eq(0, xe_sriov_admin_get_exec_quantum_ms(pf_fd, vf_num));
> +	}
> +
> +	igt_dynamic_f("%s-default-preempt-timeout", igt_sriov_func_str(vf_num)) {
> +		igt_assert_eq(0, xe_sriov_admin_get_preempt_timeout_us(pf_fd, vf_num));
> +	}
> +
> +	igt_dynamic_f("%s-default-sched-priority", igt_sriov_func_str(vf_num)) {
> +		enum xe_sriov_sched_priority prio;
> +		unsigned int prio_mask;
> +		char mask_str[64];
> +		int ret;
> +
> +		prio = xe_sriov_admin_get_sched_priority(pf_fd, vf_num, &prio_mask);
> +		ret = xe_sriov_sched_priority_mask_to_string(mask_str, sizeof(mask_str),
> +							     prio_mask, prio);
> +		igt_debug("sched_priority: ret=%d mask=0x%x selected_idx=%d str='%s'\n",
> +			  ret, prio_mask, prio, mask_str);
> +		igt_assert_eq(ret, 0);
> +		igt_assert_eq(XE_SRIOV_SCHED_PRIORITY_LOW, prio);
> +	}
> +}
> +
> +/**
> + * SUBTEST: exec-quantum-write-readback-vfs-disabled
> + * Description:
> + *   Verify write -> readback of exec_quantum_ms under sriov_admin
> + *   for PF and all VFs with VFs disabled.
> + */
> +static void exec_quantum_write_readback(int pf_fd, unsigned int vf_num,
> +					uint32_t eq_ms)
> +{
> +	int ret_read, ret_restore;
> +	uint32_t read_val;
> +
> +	igt_require(xe_sriov_admin_get_exec_quantum_ms(pf_fd, vf_num) == 0);
> +
> +	xe_sriov_admin_set_exec_quantum_ms(pf_fd, vf_num, eq_ms);
> +
> +	ret_read = __xe_sriov_admin_get_exec_quantum_ms(pf_fd, vf_num, &read_val);
> +
> +	ret_restore = __xe_sriov_admin_set_exec_quantum_ms(pf_fd, vf_num, 0);
> +
> +	igt_assert_eq(ret_read, 0);
> +	igt_assert_eq(read_val, eq_ms);
> +	igt_fail_on(ret_restore);
> +}
> +
> +/**
> + * SUBTEST: preempt-timeout-write-readback-vfs-disabled
> + * Description:
> + *   Verify write -> readback of preempt_timeout_us under sriov_admin
> + *   for PF and all VFs with VFs disabled.
> + */
> +static void preempt_timeout_write_readback(int pf_fd, unsigned int vf_num,
> +					   uint32_t pt_us)
> +{
> +	int ret_read, ret_restore;
> +	uint32_t read_val;
> +
> +	igt_require(xe_sriov_admin_get_preempt_timeout_us(pf_fd, vf_num) == 0);
> +
> +	xe_sriov_admin_set_preempt_timeout_us(pf_fd, vf_num, pt_us);
> +
> +	ret_read = __xe_sriov_admin_get_preempt_timeout_us(pf_fd, vf_num, &read_val);
> +
> +	ret_restore = __xe_sriov_admin_set_preempt_timeout_us(pf_fd, vf_num, 0);
> +
> +	igt_assert_eq(ret_read, 0);
> +	igt_assert_eq(read_val, pt_us);
> +	igt_fail_on(ret_restore);
> +}
> +
> +/**
> + * SUBTEST: sched-priority-write-readback-vfs-disabled
> + * Description:
> + *   Verify write -> readback of sched_priority under sriov_admin
> + *   for PF and all VFs with VFs disabled.
> + */
> +static void sched_priority_write_readback(int pf_fd, unsigned int vf_num)
> +{
> +	struct igt_sysfs_choice prio, now;
> +	enum xe_sriov_sched_priority prio_enum;
> +	int ret;
> +
> +	ret = __xe_sriov_admin_get_sched_priority_choice(pf_fd, vf_num, &prio);
> +	igt_assert_eq(ret, 0);
> +
> +	for (size_t n = prio.num_tokens; n-- > 0; ) {
> +		igt_warn_on_f(xe_sriov_sched_priority_from_string(prio.tokens[n],
> +								  &prio_enum),
> +			      "Unrecognized sched_priority value '%s'\n",
> +			      prio.tokens[n]);
> +		igt_debug("Setting priority string '%s'\n", prio.tokens[n]);
> +		ret = __xe_sriov_admin_set_sched_priority_string(pf_fd, vf_num,
> +								 prio.tokens[n]);
> +
> +		/* Not settable on VF */
> +		if (igt_debug_on(vf_num && (ret == -EPERM || ret == -EACCES)))
> +			break;
> +
> +		igt_assert_eq(ret, 0);
> +		ret = __xe_sriov_admin_get_sched_priority_choice(pf_fd, vf_num, &now);
> +		igt_assert_f(!strcmp(now.tokens[now.selected], prio.tokens[n]),
> +			     "'%s' != '%s'", now.tokens[now.selected],
> +			     prio.tokens[n]);
> +		igt_assert_eq(now.selected, n);
> +	}
> +	__xe_sriov_admin_set_sched_priority_string(pf_fd, vf_num,
> +						   prio.tokens[prio.selected]);
> +}
> +
> +/**
> + * SUBTEST: bulk-exec-quantum-vfs-disabled
> + * Description:
> + *   Verify that bulk setting exec_quantum_ms under sriov_admin applies
> + *   the expected value to the PF and all VFs when VFs are disabled.
> + */
> +static void bulk_set_exec_quantum(int pf_fd, unsigned int total_vfs, uint32_t eq_ms)
> +{
> +	uint32_t read_val;
> +	unsigned int vf_id;
> +	int fails = 0;
> +
> +	xe_sriov_admin_bulk_set_exec_quantum_ms(pf_fd, eq_ms);
> +
> +	for (vf_id = 0; vf_id <= total_vfs; ++vf_id) {
> +		int ret = __xe_sriov_admin_get_exec_quantum_ms(pf_fd, vf_id,
> +							       &read_val);
> +
> +		if (ret) {
> +			igt_debug("%s: failed to read exec_quantum_ms, ret=%d\n",
> +				  igt_sriov_func_str(vf_id), ret);
> +			fails++;
> +			continue;
> +		}
> +
> +		if (read_val != eq_ms) {
> +			igt_debug("%s: exec_quantum_ms=%u, expected=%u\n",
> +				  igt_sriov_func_str(vf_id), read_val, eq_ms);
> +			fails++;
> +		}
> +	}
> +
> +	xe_sriov_admin_bulk_set_exec_quantum_ms(pf_fd, 0);
> +	igt_fail_on(fails);
> +}
> +
> +/**
> + * SUBTEST: bulk-preempt-timeout-vfs-disabled
> + * Description:
> + *   Verify that bulk setting preempt_timeout_us under sriov_admin applies
> + *   the expected value to the PF and all VFs when VFs are disabled.
> + */
> +static void bulk_set_preempt_timeout(int pf_fd, unsigned int total_vfs, uint32_t pt_us)
> +{
> +	uint32_t read_val;
> +	unsigned int id;
> +	int fails = 0;
> +
> +	xe_sriov_admin_bulk_set_preempt_timeout_us(pf_fd, pt_us);
> +
> +	for (id = 0; id <= total_vfs; ++id) {
> +		int ret = __xe_sriov_admin_get_preempt_timeout_us(pf_fd, id,
> +								  &read_val);
> +
> +		if (ret) {
> +			igt_debug("%s: failed to read preempt_timeout_us, ret=%d\n",
> +				  igt_sriov_func_str(id), ret);
> +			fails++;
> +			continue;
> +		}
> +
> +		if (read_val != pt_us) {
> +			igt_debug("%s: preempt_timeout_us=%u, expected=%u\n",
> +				  igt_sriov_func_str(id), read_val, pt_us);
> +			fails++;
> +		}
> +	}
> +
> +	xe_sriov_admin_bulk_set_preempt_timeout_us(pf_fd, 0);
> +	igt_fail_on(fails);
> +}
> +
> +static void build_common_sched_priority_choice(int pf_fd, int num_vfs,
> +					       struct igt_sysfs_choice *common)
> +{
> +	int ret;
> +
> +	/* Start from PF */
> +	ret = __xe_sriov_admin_get_sched_priority_choice(pf_fd, 0, common);
> +	igt_require_f(ret == 0,
> +		      "Failed to read PF sched_priority (ret=%d)\n", ret);
> +
> +	igt_require_f(common->num_tokens > 0,
> +		      "PF sched_priority exposes no tokens\n");
> +
> +	/* Intersect with every VF 1..num_vfs */
> +	for (int vf = 1; vf <= num_vfs; vf++) {
> +		struct igt_sysfs_choice prio = {};
> +
> +		ret = __xe_sriov_admin_get_sched_priority_choice(pf_fd, vf, &prio);
> +		igt_require_f(ret == 0,
> +			      "Failed to read VF%u sched_priority (ret=%d)\n",
> +			      vf, ret);
> +
> +		ret = igt_sysfs_choice_intersect(common, &prio);
> +		igt_require_f(ret == 0,
> +			      "No common sched_priority between PF and VF%u\n",
> +			      vf);
> +	}
> +
> +	igt_require_f(common->num_tokens > 0,
> +		      "No common sched_priority across PF and all VFs\n");
> +
> +	if (common->selected < 0) {
> +		igt_debug("Common sched_priority has no selected token, "
> +			  "defaulting to tokens[0]=\"%s\"\n",
> +			  common->tokens[0]);
> +		common->selected = 0;
> +	}
> +}
> +
> +/**
> + * SUBTEST: bulk-sched-priority-vfs-disabled
> + * Description: Verify bulk sched_priority modification with VFs disabled.
> + */
> +static void bulk_set_sched_priority(int pf_fd, unsigned int total_vfs, const char *prio_str)
> +{
> +	struct igt_sysfs_choice read_val;
> +	const char *selected;
> +	unsigned int id;
> +	int fails = 0;
> +
> +	xe_sriov_admin_bulk_set_sched_priority_string(pf_fd, prio_str);
> +
> +	for (id = 0; id <= total_vfs; ++id) {
> +		int ret = __xe_sriov_admin_get_sched_priority_choice(pf_fd, id,
> +								     &read_val);
> +
> +		if (ret) {
> +			igt_debug("%s: failed to read sched_priority, ret=%d\n",
> +				  igt_sriov_func_str(id), ret);
> +			fails++;
> +			continue;
> +		}
> +
> +		selected = igt_sysfs_choice_selected(&read_val);
> +		if (!selected || strncmp(selected, prio_str, strlen(prio_str))) {
> +			igt_debug("%s: sched_priority='%s', expected='%s'\n",
> +				  igt_sriov_func_str(id), selected ?: "NULL", prio_str);
> +			fails++;
> +		}
> +	}
> +
> +	igt_fail_on(fails);
> +}
> +
> +/**
> + * SUBTEST: sched-priority-vf-write-denied
> + * Description:
> + *   Verify that sched_priority cannot be modified on a VF.
> + *   A write attempt must fail with -EPERM or -EACCES and the
> + *   current priority selection must remain unchanged.
> + */
> +static void sched_priority_vf_write_denied(int pf_fd, unsigned int vf_num)
> +{
> +	struct igt_sysfs_choice before, after;
> +	const char *new_token;
> +	const char *baseline;
> +	int baseline_selected;
> +	bool attempted = false;
> +	int ret;
> +
> +	igt_require(vf_num > 0);
> +
> +	ret = __xe_sriov_admin_get_sched_priority_choice(pf_fd, vf_num, &before);
> +	igt_require(ret == 0);
> +	igt_require(before.num_tokens > 0);
> +	igt_require(before.selected >= 0);
> +
> +	baseline_selected = before.selected;
> +	baseline = igt_sysfs_choice_selected(&before);
> +	igt_require(baseline);
> +
> +	for (size_t i = 0; i < before.num_tokens; i++) {
> +		if (before.num_tokens > 1 && (int)i == baseline_selected)
> +			continue;
> +
> +		new_token = before.tokens[i];
> +		attempted = true;
> +
> +		ret = __xe_sriov_admin_set_sched_priority_string(pf_fd, vf_num,
> +								 new_token);
> +		igt_assert_f(ret == -EPERM || ret == -EACCES,
> +			     "Expected -EPERM/-EACCES when writing VF sched_priority "
> +			     "(token='%s'), got %d\n", new_token, ret);
> +
> +		ret = __xe_sriov_admin_get_sched_priority_choice(pf_fd, vf_num,
> +								 &after);
> +		igt_assert_eq(ret, 0);
> +
> +		igt_assert_eq(after.selected, baseline_selected);
> +		igt_assert(!strcmp(baseline, igt_sysfs_choice_selected(&after)));
> +	}
> +
> +	igt_assert(attempted);
> +}
> +
> +int igt_main()
> +{
> +	unsigned int total_vfs;
> +	int pf_fd;
> +
> +	igt_fixture() {
> +		pf_fd = drm_open_driver(DRIVER_XE);
> +		igt_require(igt_sriov_is_pf(pf_fd));
> +		igt_require(igt_sriov_get_enabled_vfs(pf_fd) == 0);
> +		igt_require(xe_sriov_admin_is_present(pf_fd));
> +		total_vfs = igt_sriov_get_total_vfs(pf_fd);
> +	}
> +
> +	igt_subtest_with_dynamic("default-sched-attributes-vfs-disabled") {
> +		for (unsigned int id = 0; id <= total_vfs; ++id)
> +			default_sched_attributes(pf_fd, id);
> +	}
> +
> +	igt_subtest_with_dynamic("exec-quantum-write-readback-vfs-disabled") {
> +		uint32_t eq_ms = 10;
> +
> +		for (unsigned int id = 0; id <= total_vfs; ++id) {
> +			igt_dynamic_f("%s-eq_ms-%u", igt_sriov_func_str(id), eq_ms) {
> +				exec_quantum_write_readback(pf_fd, id, eq_ms);
> +			}
> +		}
> +	}
> +
> +	igt_subtest_with_dynamic("preempt-timeout-write-readback-vfs-disabled") {
> +		uint32_t pt_us = 20000;
> +
> +		for (unsigned int id = 0; id <= total_vfs; ++id) {
> +			igt_dynamic_f("%s-pt_us-%u", igt_sriov_func_str(id), pt_us) {
> +				preempt_timeout_write_readback(pf_fd, id, pt_us);
> +			}
> +		}
> +	}
> +
> +	igt_subtest_with_dynamic("sched-priority-write-readback-vfs-disabled") {
> +		for (unsigned int id = 0; id <= total_vfs; ++id) {
> +			igt_dynamic_f("%s", igt_sriov_func_str(id)) {
> +				sched_priority_write_readback(pf_fd, id);
> +			}
> +		}
> +	}
> +
> +	igt_subtest_with_dynamic("sched-priority-vf-write-denied") {
> +		for_each_sriov_num_vfs(pf_fd, vf_num) {
> +			igt_dynamic_f("%s", igt_sriov_func_str(vf_num)) {
> +				sched_priority_vf_write_denied(pf_fd, vf_num);
> +			}
> +		}
> +	}
> +
> +	igt_subtest("bulk-exec-quantum-vfs-disabled") {
> +		const uint32_t eq_ms = 10;
> +
> +		bulk_set_exec_quantum(pf_fd, total_vfs, eq_ms);
> +	}
> +
> +	igt_subtest("bulk-preempt-timeout-vfs-disabled") {
> +		uint32_t pt_us = 10000;
> +
> +		bulk_set_preempt_timeout(pf_fd, total_vfs, pt_us);
> +	}
> +
> +	igt_subtest_group() {
> +		struct igt_sysfs_choice prio = {};
> +
> +		igt_fixture() {
> +			build_common_sched_priority_choice(pf_fd, total_vfs,
> +							   &prio);
> +		}
> +
> +		igt_subtest_with_dynamic_f("bulk-sched-priority-vfs-disabled") {
> +			for (size_t i = prio.num_tokens; i-- > 0; ) {
> +				const char *prio_str = prio.tokens[i];
> +
> +				igt_dynamic_f("%s", prio_str)
> +					bulk_set_sched_priority(pf_fd, 0, prio_str);
> +			}
> +		}
> +	}
> +
> +	igt_fixture() {
> +		int ret;
> +
> +		ret = __xe_sriov_admin_bulk_restore_defaults(pf_fd);
> +		igt_sriov_disable_vfs(pf_fd);
> +		/* abort to avoid execution of next tests with enabled VFs */
> +		igt_abort_on_f(igt_sriov_get_enabled_vfs(pf_fd) > 0,
> +			       "Failed to disable VF(s)");
> +		igt_abort_on_f(ret, "Failed to restore default profile values\n");
> +		drm_close_driver(pf_fd);
> +	}
> +}
> diff --git a/tests/meson.build b/tests/meson.build
> index 0ad728b87..ef4edaa0d 100644
> --- a/tests/meson.build
> +++ b/tests/meson.build
> @@ -331,6 +331,7 @@ intel_xe_progs = [
>   	'xe_vm',
>   	'xe_waitfence',
>   	'xe_spin_batch',
> +	'xe_sriov_admin',
>   	'xe_sriov_auto_provisioning',
>   	'xe_sriov_flr',
>   	'xe_sriov_scheduling',

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: ✗ i915.CI.BAT: failure for Xe SR-IOV admin scheduling helpers and test updates (rev3)
  2026-01-28 20:47 ` ✗ i915.CI.BAT: failure " Patchwork
@ 2026-01-29 10:11   ` Bernatowicz, Marcin
  0 siblings, 0 replies; 19+ messages in thread
From: Bernatowicz, Marcin @ 2026-01-29 10:11 UTC (permalink / raw)
  To: igt-dev, lgci.bug.filing


On 1/28/2026 9:47 PM, Patchwork wrote:
> == Series Details ==
>
> Series: Xe SR-IOV admin scheduling helpers and test updates (rev3)
> URL   : https://patchwork.freedesktop.org/series/157591/
> State : failure
>
> == Summary ==
>
> CI Bug Log - changes from IGT_8723 -> IGTPW_14443
> ====================================================
>
> Summary
> -------
>
>    **FAILURE**
>
>    Serious unknown changes coming with IGTPW_14443 absolutely need to be
>    verified manually.
>    
>    If you think the reported changes have nothing to do with the changes
>    introduced in IGTPW_14443, please notify your bug team (I915-ci-infra@lists.freedesktop.org) to allow them
>    to document this new failure mode, which will reduce false positives in CI.
>
>    External URL: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14443/index.html
>
> Participating hosts (42 -> 41)
> ------------------------------
>
>    Additional (1): bat-adls-6
>    Missing    (2): bat-dg2-13 fi-snb-2520m
>
> Possible new issues
> -------------------
>
>    Here are the unknown changes that may have been introduced in IGTPW_14443:
>
> ### IGT changes ###
>
> #### Possible regressions ####
>
>    * igt@i915_pm_rpm@module-reload:
>      - bat-adlp-6:         [PASS][1] -> [DMESG-WARN][2] +78 other tests dmesg-warn
>     [1]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8723/bat-adlp-6/igt@i915_pm_rpm@module-reload.html
>     [2]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14443/bat-adlp-6/igt@i915_pm_rpm@module-reload.html

Not related to the series.

--

marcin

>
>    
> Known issues
> ------------
>
>    Here are the changes found in IGTPW_14443 that come from known issues:
>
> ### IGT changes ###
>
> #### Issues hit ####
>
>    * igt@gem_lmem_swapping@parallel-random-engines:
>      - bat-adls-6:         NOTRUN -> [SKIP][3] ([i915#4613]) +3 other tests skip
>     [3]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14443/bat-adls-6/igt@gem_lmem_swapping@parallel-random-engines.html
>
>    * igt@gem_tiled_pread_basic:
>      - bat-adls-6:         NOTRUN -> [SKIP][4] ([i915#3282])
>     [4]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14443/bat-adls-6/igt@gem_tiled_pread_basic.html
>
>    * igt@i915_selftest@live:
>      - bat-twl-1:          [PASS][5] -> [DMESG-WARN][6] ([i915#14872]) +1 other test dmesg-warn
>     [5]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8723/bat-twl-1/igt@i915_selftest@live.html
>     [6]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14443/bat-twl-1/igt@i915_selftest@live.html
>
>    * igt@intel_hwmon@hwmon-read:
>      - bat-adls-6:         NOTRUN -> [SKIP][7] ([i915#7707]) +1 other test skip
>     [7]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14443/bat-adls-6/igt@intel_hwmon@hwmon-read.html
>
>    * igt@kms_cursor_legacy@basic-busy-flip-before-cursor-legacy:
>      - bat-adls-6:         NOTRUN -> [SKIP][8] ([i915#4103]) +1 other test skip
>     [8]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14443/bat-adls-6/igt@kms_cursor_legacy@basic-busy-flip-before-cursor-legacy.html
>
>    * igt@kms_dsc@dsc-basic:
>      - bat-adls-6:         NOTRUN -> [SKIP][9] ([i915#3555] / [i915#3840])
>     [9]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14443/bat-adls-6/igt@kms_dsc@dsc-basic.html
>
>    * igt@kms_force_connector_basic@force-load-detect:
>      - bat-adls-6:         NOTRUN -> [SKIP][10]
>     [10]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14443/bat-adls-6/igt@kms_force_connector_basic@force-load-detect.html
>
>    * igt@kms_pm_backlight@basic-brightness:
>      - bat-adls-6:         NOTRUN -> [SKIP][11] ([i915#5354])
>     [11]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14443/bat-adls-6/igt@kms_pm_backlight@basic-brightness.html
>
>    * igt@kms_psr@psr-primary-mmap-gtt:
>      - bat-adls-6:         NOTRUN -> [SKIP][12] ([i915#1072] / [i915#9732]) +3 other tests skip
>     [12]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14443/bat-adls-6/igt@kms_psr@psr-primary-mmap-gtt.html
>
>    * igt@kms_setmode@basic-clone-single-crtc:
>      - bat-adls-6:         NOTRUN -> [SKIP][13] ([i915#3555])
>     [13]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14443/bat-adls-6/igt@kms_setmode@basic-clone-single-crtc.html
>
>    * igt@prime_vgem@basic-fence-read:
>      - bat-adls-6:         NOTRUN -> [SKIP][14] ([i915#3291]) +2 other tests skip
>     [14]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14443/bat-adls-6/igt@prime_vgem@basic-fence-read.html
>
>    
> #### Possible fixes ####
>
>    * igt@i915_selftest@live:
>      - bat-mtlp-8:         [DMESG-FAIL][15] ([i915#12061]) -> [PASS][16] +1 other test pass
>     [15]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8723/bat-mtlp-8/igt@i915_selftest@live.html
>     [16]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14443/bat-mtlp-8/igt@i915_selftest@live.html
>
>    * igt@i915_selftest@live@workarounds:
>      - bat-arls-6:         [DMESG-FAIL][17] ([i915#12061]) -> [PASS][18] +1 other test pass
>     [17]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8723/bat-arls-6/igt@i915_selftest@live@workarounds.html
>     [18]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14443/bat-arls-6/igt@i915_selftest@live@workarounds.html
>
>    
>    [i915#1072]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/1072
>    [i915#12061]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/12061
>    [i915#14872]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14872
>    [i915#3282]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3282
>    [i915#3291]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3291
>    [i915#3555]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3555
>    [i915#3840]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3840
>    [i915#4103]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4103
>    [i915#4613]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4613
>    [i915#5354]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/5354
>    [i915#7707]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/7707
>    [i915#9732]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9732
>
>
> Build changes
> -------------
>
>    * CI: CI-20190529 -> None
>    * IGT: IGT_8723 -> IGTPW_14443
>
>    CI-20190529: 20190529
>    CI_DRM_17900: 8059f097e25f736bb3da09af6a9b283079abfd4f @ git://anongit.freedesktop.org/gfx-ci/linux
>    IGTPW_14443: 14443
>    IGT_8723: 8723
>
> == Logs ==
>
> For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14443/index.html
>

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2026-01-29 10:11 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-28 18:08 [PATCH v3 i-g-t 00/10] Xe SR-IOV admin scheduling helpers and test updates Marcin Bernatowicz
2026-01-28 18:08 ` [PATCH v3 i-g-t 01/10] lib/igt_sysfs_choice: Add helpers for sysfs enumerated choice attributes Marcin Bernatowicz
2026-01-29  8:19   ` Laguna, Lukasz
2026-01-28 18:08 ` [PATCH v3 i-g-t 02/10] lib/tests/igt_sysfs_choice: Add test coverage Marcin Bernatowicz
2026-01-29  8:19   ` Laguna, Lukasz
2026-01-28 18:08 ` [PATCH v3 i-g-t 03/10] lib/xe/xe_sriov_provisioning: Add string conversion helpers for scheduling priority Marcin Bernatowicz
2026-01-28 18:08 ` [PATCH v3 i-g-t 04/10] lib/xe/xe_sriov_provisioning: Add sched priority mask to string helper Marcin Bernatowicz
2026-01-29  8:19   ` Laguna, Lukasz
2026-01-28 18:08 ` [PATCH v3 i-g-t 05/10] lib/igt_sriov_device: Add helper for PF/VF sysfs path formatting Marcin Bernatowicz
2026-01-28 18:08 ` [PATCH v3 i-g-t 06/10] lib/xe/xe_sriov_admin: Add SR-IOV admin sysfs accessors Marcin Bernatowicz
2026-01-29  8:21   ` Laguna, Lukasz
2026-01-28 18:08 ` [PATCH v3 i-g-t 07/10] tests/intel/xe_sriov_scheduling: Avoid assert on scheduling params restore in cleanup Marcin Bernatowicz
2026-01-28 18:08 ` [PATCH v3 i-g-t 08/10] tests/intel/xe_sriov_scheduling: Prefer SR-IOV admin sysfs accessors Marcin Bernatowicz
2026-01-28 18:08 ` [PATCH v3 i-g-t 09/10] tests/intel/xe_pmu: " Marcin Bernatowicz
2026-01-28 18:08 ` [PATCH v3 i-g-t 10/10] tests/intel/xe_sriov_admin: Add SR-IOV admin sysfs scheduling attributes tests Marcin Bernatowicz
2026-01-29  8:21   ` Laguna, Lukasz
2026-01-28 20:32 ` ✓ Xe.CI.BAT: success for Xe SR-IOV admin scheduling helpers and test updates (rev3) Patchwork
2026-01-28 20:47 ` ✗ i915.CI.BAT: failure " Patchwork
2026-01-29 10:11   ` Bernatowicz, Marcin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox