public inbox for igt-dev@lists.freedesktop.org
 help / color / mirror / Atom feed
* [PATCH i-g-t 1/6] lib/igt_edid: add EDID serial extraction helpers
  2026-02-25 19:42 [PATCH i-g-t 0/6] add test to validate dock/undock and switch Kunal Joshi
@ 2026-02-25 19:42 ` Kunal Joshi
  0 siblings, 0 replies; 25+ messages in thread
From: Kunal Joshi @ 2026-02-25 19:42 UTC (permalink / raw)
  To: igt-dev; +Cc: Kunal Joshi

Add helpers to extract serial identification from EDID data.

 - edid_get_serial_string(): extract ASCII serial from descriptor 0xFF
 - edid_get_serial_number(): extract 32-bit serial from EDID header
 - edid_get_any_serial(): convenience helper that tries ASCII serial
   first, then falls back to 32-bit header serial formatted as hex

These are needed by the connector helper and USB4 switch test suite
for EDID-based display verification after dock/undock events.

Signed-off-by: Kunal Joshi <kunal1.joshi@intel.com>
---
 lib/igt_edid.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/igt_edid.h |  5 +++
 2 files changed, 96 insertions(+)

diff --git a/lib/igt_edid.c b/lib/igt_edid.c
index c68ccf671..0298ae599 100644
--- a/lib/igt_edid.c
+++ b/lib/igt_edid.c
@@ -249,6 +249,97 @@ void edid_get_monitor_name(const struct edid *edid, char *name, size_t name_size
 	name[0] = '\0';
 }
 
+/**
+ * edid_get_serial_string:
+ * @edid: EDID structure
+ * @serial: buffer to write serial string
+ * @serial_size: size of serial buffer; must be > 1
+ *
+ * Extract the serial string from EDID descriptor block type 0xFF.
+ * The descriptor payload is a 13-byte fixed-width field; trailing
+ * whitespace is stripped and the result is NUL-terminated.
+ * @serial is left empty when no 0xFF descriptor is found.
+ */
+void edid_get_serial_string(const struct edid *edid,
+			    char *serial, size_t serial_size)
+{
+	size_t copy_len, i, n;
+
+	igt_assert(edid);
+	igt_assert(serial);
+	igt_assert(serial_size > 1);
+	serial[0] = '\0';
+
+	for (i = 0; i < DETAILED_TIMINGS_LEN; i++) {
+		const uint8_t *d = (const uint8_t *)&edid->detailed_timings[i];
+
+		if (d[0] != 0x00 || d[1] != 0x00 || d[2] != 0x00)
+			continue;
+
+		if (d[3] != EDID_DETAIL_MONITOR_SERIAL || d[4] != 0x00)
+			continue;
+
+		/* Descriptor string payload is 13 bytes starting at d[5] */
+		copy_len = 13 < serial_size - 1 ? 13 : serial_size - 1;
+		memcpy(serial, &d[5], copy_len);
+		serial[copy_len] = '\0';
+
+		for (n = strlen(serial);
+		     n > 0 && isspace((unsigned char)serial[n - 1]); n--)
+			serial[n - 1] = '\0';
+
+		return;
+	}
+}
+
+/**
+ * edid_get_serial_number:
+ * @edid: EDID structure
+ *
+ * Extract the 32-bit serial number from the EDID base block header
+ * (bytes 12–15, the manufacturer/product section).  This is different
+ * from the ASCII serial string in descriptor block 0xFF.
+ *
+ * Returns: 32-bit serial number (little-endian), 0 if absent.
+ */
+uint32_t edid_get_serial_number(const struct edid *edid)
+{
+	return (uint32_t)edid->serial[0] |
+	       ((uint32_t)edid->serial[1] << 8) |
+	       ((uint32_t)edid->serial[2] << 16) |
+	       ((uint32_t)edid->serial[3] << 24);
+}
+
+/**
+ * edid_get_any_serial:
+ * @edid: EDID structure
+ * @serial: buffer to write serial string
+ * @serial_size: size of serial buffer; must be > 1
+ *
+ * Convenience helper that tries to extract a serial identifier from EDID.
+ * First tries the ASCII serial string descriptor (0xFF). If that is empty,
+ * falls back to the 32-bit header serial number formatted as 8-char hex.
+ * If neither source provides a usable serial (no 0xFF descriptor and the
+ * header serial is 0), @serial is left empty.
+ */
+void edid_get_any_serial(const struct edid *edid,
+			 char *serial, size_t serial_size)
+{
+	uint32_t serial_num;
+
+	igt_assert(edid);
+	igt_assert(serial);
+	igt_assert(serial_size > 1);
+
+	edid_get_serial_string(edid, serial, serial_size);
+	if (serial[0])
+		return;
+
+	serial_num = edid_get_serial_number(edid);
+	if (serial_num != 0)
+		snprintf(serial, serial_size, "%08X", serial_num);
+}
+
 static void edid_set_mfg(struct edid *edid, const char mfg[static 3])
 {
 	edid->mfg_id[0] = (mfg[0] - '@') << 2 | (mfg[1] - '@') >> 3;
diff --git a/lib/igt_edid.h b/lib/igt_edid.h
index be0ccf529..d9e396065 100644
--- a/lib/igt_edid.h
+++ b/lib/igt_edid.h
@@ -457,5 +457,10 @@ void *dispid_block_tiled(void *ptr,
 			 int hsize, int vsize,
 			 const char *topology_id);
 void edid_get_monitor_name(const struct edid *edid, char *name, size_t name_size);
+void edid_get_serial_string(const struct edid *edid,
+			    char *serial, size_t serial_size);
+uint32_t edid_get_serial_number(const struct edid *edid);
+void edid_get_any_serial(const struct edid *edid,
+			 char *serial, size_t serial_size);
 
 #endif
-- 
2.25.1


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

* [PATCH i-g-t 0/6] add test to validate dock/undock and switch
@ 2026-02-25 21:28 Kunal Joshi
  2026-02-25 21:28 ` [PATCH i-g-t 1/6] lib/igt_edid: add EDID serial extraction helpers Kunal Joshi
                   ` (9 more replies)
  0 siblings, 10 replies; 25+ messages in thread
From: Kunal Joshi @ 2026-02-25 21:28 UTC (permalink / raw)
  To: igt-dev; +Cc: Kunal Joshi

Add test to validate docking/undocking scenarios on TBT Hub
and switching from TBT/DP-ALT to DP-ALT/TBT mode.

Relies on Microsoft USB4 switch 3141 for the same
Below is link to documentation for Microsoft USB4 switch 3141
https://mcci.com/wp-content/uploads/2021/09/950001601a_Model-3141-USB4%E2%84%A2-Switch-User-Manual.pdf

Kunal Joshi (6):
  lib/igt_edid: add EDID serial extraction helpers
  lib/igt_connector_helper: Add generic connector helpers
  lib/igt_serial: add generic serial communication helper
  lib/igt_usb4_switch: add helper library for USB4 Switch 3141
  tests/kms_feature_discovery: add basic usb4 switch discovery
  tests/intel/kms_usb4_switch: Add USB4 switch test suite

 lib/igt_connector_helper.c    |  299 ++++++++
 lib/igt_connector_helper.h    |   27 +
 lib/igt_edid.c                |   91 +++
 lib/igt_edid.h                |    5 +
 lib/igt_serial.c              |  435 ++++++++++++
 lib/igt_serial.h              |   32 +
 lib/igt_usb4_switch.c         | 1055 +++++++++++++++++++++++++++
 lib/igt_usb4_switch.h         |  157 +++++
 lib/meson.build               |    3 +
 tests/intel/kms_usb4_switch.c | 1254 +++++++++++++++++++++++++++++++++
 tests/kms_feature_discovery.c |   23 +
 tests/meson.build             |    2 +
 12 files changed, 3383 insertions(+)
 create mode 100644 lib/igt_connector_helper.c
 create mode 100644 lib/igt_connector_helper.h
 create mode 100644 lib/igt_serial.c
 create mode 100644 lib/igt_serial.h
 create mode 100644 lib/igt_usb4_switch.c
 create mode 100644 lib/igt_usb4_switch.h
 create mode 100644 tests/intel/kms_usb4_switch.c

-- 
2.25.1


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

* [PATCH i-g-t 1/6] lib/igt_edid: add EDID serial extraction helpers
  2026-02-25 21:28 [PATCH i-g-t 0/6] add test to validate dock/undock and switch Kunal Joshi
@ 2026-02-25 21:28 ` Kunal Joshi
  2026-03-09  9:30   ` [i-g-t,1/6] " Murthy, Arun R
  2026-02-25 21:28 ` [PATCH i-g-t 2/6] lib/igt_connector_helper: Add generic connector helpers Kunal Joshi
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 25+ messages in thread
From: Kunal Joshi @ 2026-02-25 21:28 UTC (permalink / raw)
  To: igt-dev; +Cc: Kunal Joshi

Add helpers to extract serial identification from EDID data.

 - edid_get_serial_string(): extract ASCII serial from descriptor 0xFF
 - edid_get_serial_number(): extract 32-bit serial from EDID header
 - edid_get_any_serial(): convenience helper that tries ASCII serial
   first, then falls back to 32-bit header serial formatted as hex

These are needed by the connector helper and USB4 switch test suite
for EDID-based display verification after dock/undock events.

Signed-off-by: Kunal Joshi <kunal1.joshi@intel.com>
---
 lib/igt_edid.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/igt_edid.h |  5 +++
 2 files changed, 96 insertions(+)

diff --git a/lib/igt_edid.c b/lib/igt_edid.c
index c68ccf671..e7fcbf0b9 100644
--- a/lib/igt_edid.c
+++ b/lib/igt_edid.c
@@ -249,6 +249,97 @@ void edid_get_monitor_name(const struct edid *edid, char *name, size_t name_size
 	name[0] = '\0';
 }
 
+/**
+ * edid_get_serial_string:
+ * @edid: EDID structure
+ * @serial: buffer to write serial string
+ * @serial_size: size of serial buffer; must be > 1
+ *
+ * Extract the serial string from EDID descriptor block type 0xFF.
+ * The descriptor payload is a 13-byte fixed-width field; trailing
+ * whitespace is stripped and the result is NUL-terminated.
+ * @serial is left empty when no 0xFF descriptor is found.
+ */
+void edid_get_serial_string(const struct edid *edid,
+			    char *serial, size_t serial_size)
+{
+	size_t copy_len, i, n;
+
+	igt_assert(edid);
+	igt_assert(serial);
+	igt_assert(serial_size > 1);
+	serial[0] = '\0';
+
+	for (i = 0; i < DETAILED_TIMINGS_LEN; i++) {
+		const uint8_t *d = (const uint8_t *)&edid->detailed_timings[i];
+
+		if (d[0] != 0x00 || d[1] != 0x00 || d[2] != 0x00)
+			continue;
+
+		if (d[3] != EDID_DETAIL_MONITOR_SERIAL || d[4] != 0x00)
+			continue;
+
+		/* Descriptor string payload is 13 bytes starting at d[5] */
+		copy_len = serial_size - 1 < 13 ? serial_size - 1 : 13;
+		memcpy(serial, &d[5], copy_len);
+		serial[copy_len] = '\0';
+
+		for (n = strlen(serial);
+		     n > 0 && isspace((unsigned char)serial[n - 1]); n--)
+			serial[n - 1] = '\0';
+
+		return;
+	}
+}
+
+/**
+ * edid_get_serial_number:
+ * @edid: EDID structure
+ *
+ * Extract the 32-bit serial number from the EDID base block header
+ * (bytes 12–15, the manufacturer/product section).  This is different
+ * from the ASCII serial string in descriptor block 0xFF.
+ *
+ * Returns: 32-bit serial number (little-endian), 0 if absent.
+ */
+uint32_t edid_get_serial_number(const struct edid *edid)
+{
+	return (uint32_t)edid->serial[0] |
+	       ((uint32_t)edid->serial[1] << 8) |
+	       ((uint32_t)edid->serial[2] << 16) |
+	       ((uint32_t)edid->serial[3] << 24);
+}
+
+/**
+ * edid_get_any_serial:
+ * @edid: EDID structure
+ * @serial: buffer to write serial string
+ * @serial_size: size of serial buffer; must be > 1
+ *
+ * Convenience helper that tries to extract a serial identifier from EDID.
+ * First tries the ASCII serial string descriptor (0xFF). If that is empty,
+ * falls back to the 32-bit header serial number formatted as 8-char hex.
+ * If neither source provides a usable serial (no 0xFF descriptor and the
+ * header serial is 0), @serial is left empty.
+ */
+void edid_get_any_serial(const struct edid *edid,
+			 char *serial, size_t serial_size)
+{
+	uint32_t serial_num;
+
+	igt_assert(edid);
+	igt_assert(serial);
+	igt_assert(serial_size > 1);
+
+	edid_get_serial_string(edid, serial, serial_size);
+	if (serial[0])
+		return;
+
+	serial_num = edid_get_serial_number(edid);
+	if (serial_num != 0)
+		snprintf(serial, serial_size, "%08X", serial_num);
+}
+
 static void edid_set_mfg(struct edid *edid, const char mfg[static 3])
 {
 	edid->mfg_id[0] = (mfg[0] - '@') << 2 | (mfg[1] - '@') >> 3;
diff --git a/lib/igt_edid.h b/lib/igt_edid.h
index be0ccf529..d9e396065 100644
--- a/lib/igt_edid.h
+++ b/lib/igt_edid.h
@@ -457,5 +457,10 @@ void *dispid_block_tiled(void *ptr,
 			 int hsize, int vsize,
 			 const char *topology_id);
 void edid_get_monitor_name(const struct edid *edid, char *name, size_t name_size);
+void edid_get_serial_string(const struct edid *edid,
+			    char *serial, size_t serial_size);
+uint32_t edid_get_serial_number(const struct edid *edid);
+void edid_get_any_serial(const struct edid *edid,
+			 char *serial, size_t serial_size);
 
 #endif
-- 
2.25.1


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

* [PATCH i-g-t 2/6] lib/igt_connector_helper: Add generic connector helpers
  2026-02-25 21:28 [PATCH i-g-t 0/6] add test to validate dock/undock and switch Kunal Joshi
  2026-02-25 21:28 ` [PATCH i-g-t 1/6] lib/igt_edid: add EDID serial extraction helpers Kunal Joshi
@ 2026-02-25 21:28 ` Kunal Joshi
  2026-03-09  9:38   ` [i-g-t,2/6] " Murthy, Arun R
  2026-02-25 21:28 ` [PATCH i-g-t 3/6] lib/igt_serial: add generic serial communication helper Kunal Joshi
                   ` (7 subsequent siblings)
  9 siblings, 1 reply; 25+ messages in thread
From: Kunal Joshi @ 2026-02-25 21:28 UTC (permalink / raw)
  To: igt-dev; +Cc: Kunal Joshi

Add a lightweight helper library for DRM connector operations used
by USB4 switch and other dock/undock tests:

 - igt_connector_get_connected(): enumerate connected connectors
 - igt_connector_get_info(): query name, EDID serial, and MST path
 - igt_connector_find_by_path(): PATH-based connector lookup (MST)
 - igt_connector_find_by_name(): name-based connector lookup
 - igt_connector_reprobe_all(): force reprobe all connectors by
   iterating each connector to trigger DRM core re-detection

These helpers abstract common DRM connector patterns that are needed
by multiple test suites for display enumeration and verification.

Signed-off-by: Kunal Joshi <kunal1.joshi@intel.com>
---
 lib/igt_connector_helper.c | 299 +++++++++++++++++++++++++++++++++++++
 lib/igt_connector_helper.h |  27 ++++
 lib/meson.build            |   1 +
 3 files changed, 327 insertions(+)
 create mode 100644 lib/igt_connector_helper.c
 create mode 100644 lib/igt_connector_helper.h

diff --git a/lib/igt_connector_helper.c b/lib/igt_connector_helper.c
new file mode 100644
index 000000000..6be849b7a
--- /dev/null
+++ b/lib/igt_connector_helper.c
@@ -0,0 +1,299 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2026 Intel Corporation
+ */
+
+/**
+ * SECTION:igt_connector_helper
+ * @short_description: Generic connector helper functions for DRM/KMS
+ * @title: Connector Helper
+ * @include: igt_connector_helper.h
+ *
+ * Helper functions for DRM connector operations including enumeration,
+ * lookup by name/path, and EDID serial extraction.
+ */
+
+#include <string.h>
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+
+#include "igt_core.h"
+#include "igt_edid.h"
+#include "igt_kms.h"
+#include "igt_connector_helper.h"
+
+/**
+ * igt_connector_get_connected:
+ * @drm_fd: DRM file descriptor
+ * @connectors: array to store connector IDs; must be valid if @max_connectors > 0
+ * @max_connectors: maximum number of connectors to store
+ *
+ * Walks all DRM connectors and stores the IDs of those currently connected.
+ * Scanning stops once @max_connectors IDs have been collected; later
+ * connectors are not examined.
+ *
+ * Returns: number of connector IDs written to @connectors, capped by
+ * @max_connectors.
+ */
+int igt_connector_get_connected(int drm_fd, uint32_t *connectors,
+				int max_connectors)
+{
+	drmModeRes *res;
+	drmModeConnector *conn;
+	int count = 0;
+	int i;
+
+	igt_assert(max_connectors >= 0);
+	if (max_connectors > 0)
+		igt_assert(connectors);
+
+	res = drmModeGetResources(drm_fd);
+	if (!res)
+		return 0;
+
+	for (i = 0; i < res->count_connectors && count < max_connectors; i++) {
+		conn = drmModeGetConnector(drm_fd, res->connectors[i]);
+		if (!conn)
+			continue;
+
+		if (conn->connection == DRM_MODE_CONNECTED)
+			connectors[count++] = conn->connector_id;
+
+		drmModeFreeConnector(conn);
+	}
+
+	drmModeFreeResources(res);
+	return count;
+}
+
+/**
+ * igt_connector_get_info:
+ * @drm_fd: DRM file descriptor
+ * @connector_id: connector ID
+ * @name: buffer for connector name (mandatory)
+ * @name_size: size of @name; must be > 0
+ * @serial: buffer for EDID-derived serial (mandatory)
+ * @serial_size: size of @serial; must be > 1
+ * @path: buffer for MST PATH property (optional, may be NULL)
+ * @path_size: size of @path buffer
+ *
+ * Fills connector name, MST PATH, and EDID-derived serial for a connector.
+ * @name is always filled when the connector is found. @serial is filled from
+ * the ASCII serial string descriptor (0xFF) if present, else from the 32-bit
+ * header serial number; left empty if no EDID is available. @path is filled
+ * only if requested and the PATH property exists.
+ *
+ * Success means the connector object was found and @name was filled.
+ * @serial and @path are best-effort and may still be empty on success.
+ *
+ * Returns: true if the connector was found, false otherwise.
+ */
+bool igt_connector_get_info(int drm_fd, uint32_t connector_id,
+			    char *name, size_t name_size,
+			    char *serial, size_t serial_size,
+			    char *path, size_t path_size)
+{
+	drmModeConnector *conn;
+	drmModePropertyBlobPtr edid_blob = NULL;
+	uint64_t blob_id = 0;
+	drmModePropertyPtr prop;
+	const struct edid *edid;
+	int i;
+
+	igt_assert(name && name_size > 0);
+	igt_assert(serial && serial_size > 1);
+	igt_assert(!path || path_size > 0);
+
+	name[0] = '\0';
+	serial[0] = '\0';
+	if (path)
+		path[0] = '\0';
+
+	conn = drmModeGetConnector(drm_fd, connector_id);
+	if (!conn)
+		return false;
+
+	snprintf(name, name_size, "%s-%d",
+		 kmstest_connector_type_str(conn->connector_type),
+		 conn->connector_type_id);
+
+	for (i = 0; i < conn->count_props; i++) {
+		prop = drmModeGetProperty(drm_fd, conn->props[i]);
+		if (!prop)
+			continue;
+
+		if (strcmp(prop->name, "EDID") == 0)
+			blob_id = conn->prop_values[i];
+
+		drmModeFreeProperty(prop);
+		if (blob_id)
+			break;
+	}
+
+	/* Extract MST PATH if requested */
+	if (path) {
+		drmModePropertyBlobPtr path_blob;
+
+		/* PATH blob payload is a NUL-terminated string */
+		path_blob = kmstest_get_path_blob(drm_fd, connector_id);
+		if (path_blob) {
+			snprintf(path, path_size, "%s",
+				 (const char *)path_blob->data);
+			drmModeFreePropertyBlob(path_blob);
+		}
+	}
+
+	drmModeFreeConnector(conn);
+
+	if (blob_id) {
+		edid_blob = drmModeGetPropertyBlob(drm_fd, blob_id);
+		if (edid_blob) {
+			if (edid_blob->length >= sizeof(struct edid)) {
+				edid = edid_blob->data;
+				edid_get_any_serial(edid, serial, serial_size);
+			}
+			drmModeFreePropertyBlob(edid_blob);
+		}
+	}
+
+	return true;
+}
+
+/**
+ * igt_connector_find_by_path:
+ * @drm_fd: DRM file descriptor
+ * @path: MST PATH property value to match
+ * @connector_id: output for connector ID (filled on success)
+ *
+ * Finds the currently connected connector whose PATH property matches @path
+ * (exact string comparison).  PATH is the preferred stable identity for MST
+ * connectors; connector IDs may change across hotplug events.
+ *
+ * Returns: true if a matching connected connector was found.
+ */
+bool igt_connector_find_by_path(int drm_fd, const char *path,
+				uint32_t *connector_id)
+{
+	drmModeRes *res;
+	drmModeConnector *conn;
+	drmModePropertyBlobPtr path_blob;
+	bool found = false;
+	int i;
+
+	if (!path || !connector_id)
+		return false;
+
+	res = drmModeGetResources(drm_fd);
+	if (!res)
+		return false;
+
+	for (i = 0; i < res->count_connectors && !found; i++) {
+		conn = drmModeGetConnector(drm_fd, res->connectors[i]);
+		if (!conn)
+			continue;
+
+		if (conn->connection == DRM_MODE_CONNECTED) {
+			path_blob = kmstest_get_path_blob(drm_fd,
+							  conn->connector_id);
+			if (path_blob) {
+				if (strcmp(path_blob->data, path) == 0) {
+					*connector_id = conn->connector_id;
+					found = true;
+				}
+				drmModeFreePropertyBlob(path_blob);
+			}
+		}
+
+		drmModeFreeConnector(conn);
+	}
+
+	drmModeFreeResources(res);
+
+	if (found)
+		igt_debug("igt_connector: Found connector %u for path '%s'\n",
+			  *connector_id, path);
+
+	return found;
+}
+
+/**
+ * igt_connector_find_by_name:
+ * @drm_fd: DRM file descriptor
+ * @name: connector name to match (e.g., "DP-6")
+ * @connector_id: output for connector ID (filled on success)
+ *
+ * Name-based lookup helper.  Prefer igt_connector_find_by_path() for MST
+ * connectors, since connector names and IDs may change across hotplug events.
+ *
+ * Returns: true if a matching connected connector was found.
+ */
+bool igt_connector_find_by_name(int drm_fd, const char *name,
+				uint32_t *connector_id)
+{
+	drmModeRes *res;
+	drmModeConnector *conn;
+	char conn_name[IGT_CONNECTOR_NAME_MAX];
+	bool found = false;
+	int i;
+
+	if (!name || !connector_id)
+		return false;
+
+	res = drmModeGetResources(drm_fd);
+	if (!res)
+		return false;
+
+	for (i = 0; i < res->count_connectors && !found; i++) {
+		conn = drmModeGetConnector(drm_fd, res->connectors[i]);
+		if (!conn)
+			continue;
+
+		snprintf(conn_name, sizeof(conn_name), "%s-%d",
+			 kmstest_connector_type_str(conn->connector_type),
+			 conn->connector_type_id);
+
+		if (strcmp(conn_name, name) == 0 &&
+		    conn->connection == DRM_MODE_CONNECTED) {
+			*connector_id = conn->connector_id;
+			found = true;
+		}
+
+		drmModeFreeConnector(conn);
+	}
+
+	drmModeFreeResources(res);
+
+	if (found)
+		igt_debug("igt_connector: Found connector %u for name '%s'\n",
+			  *connector_id, name);
+
+	return found;
+}
+
+/**
+ * igt_connector_reprobe_all:
+ * @drm_fd: DRM file descriptor
+ *
+ * Issues a GETCONNECTOR ioctl for every connector, requesting fresh state
+ * from the kernel. This is often sufficient to refresh connector status and
+ * MST topology visibility after hotplug events, but does not guarantee a
+ * full hardware reprobe in all driver paths.
+ */
+void igt_connector_reprobe_all(int drm_fd)
+{
+	drmModeRes *res;
+	drmModeConnector *conn;
+	int i;
+
+	res = drmModeGetResources(drm_fd);
+	if (!res)
+		return;
+
+	for (i = 0; i < res->count_connectors; i++) {
+		conn = drmModeGetConnector(drm_fd, res->connectors[i]);
+		if (conn)
+			drmModeFreeConnector(conn);
+	}
+
+	drmModeFreeResources(res);
+}
diff --git a/lib/igt_connector_helper.h b/lib/igt_connector_helper.h
new file mode 100644
index 000000000..fffb2661b
--- /dev/null
+++ b/lib/igt_connector_helper.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2026 Intel Corporation
+ */
+
+#ifndef IGT_CONNECTOR_HELPER_H
+#define IGT_CONNECTOR_HELPER_H
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#define IGT_CONNECTOR_NAME_MAX 32
+
+int igt_connector_get_connected(int drm_fd, uint32_t *connectors,
+				int max_connectors);
+bool igt_connector_get_info(int drm_fd, uint32_t connector_id,
+			    char *name, size_t name_size,
+			    char *serial, size_t serial_size,
+			    char *path, size_t path_size);
+bool igt_connector_find_by_path(int drm_fd, const char *path,
+				uint32_t *connector_id);
+bool igt_connector_find_by_name(int drm_fd, const char *name,
+				uint32_t *connector_id);
+void igt_connector_reprobe_all(int drm_fd);
+
+#endif /* IGT_CONNECTOR_HELPER_H */
diff --git a/lib/meson.build b/lib/meson.build
index ea721ecf7..074b21fdf 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -113,6 +113,7 @@ lib_sources = [
 	'igt_vmwgfx.c',
 	'igt_psr.c',
 	'igt_amd.c',
+	'igt_connector_helper.c',
 	'igt_edid.c',
 	'igt_eld.c',
 	'igt_infoframe.c',
-- 
2.25.1


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

* [PATCH i-g-t 3/6] lib/igt_serial: add generic serial communication helper
  2026-02-25 21:28 [PATCH i-g-t 0/6] add test to validate dock/undock and switch Kunal Joshi
  2026-02-25 21:28 ` [PATCH i-g-t 1/6] lib/igt_edid: add EDID serial extraction helpers Kunal Joshi
  2026-02-25 21:28 ` [PATCH i-g-t 2/6] lib/igt_connector_helper: Add generic connector helpers Kunal Joshi
@ 2026-02-25 21:28 ` Kunal Joshi
  2026-03-16  5:40   ` [i-g-t,3/6] " Murthy, Arun R
  2026-02-25 21:28 ` [PATCH i-g-t 4/6] lib/igt_usb4_switch: add helper library for USB4 Switch 3141 Kunal Joshi
                   ` (6 subsequent siblings)
  9 siblings, 1 reply; 25+ messages in thread
From: Kunal Joshi @ 2026-02-25 21:28 UTC (permalink / raw)
  To: igt-dev; +Cc: Kunal Joshi

Add a reusable serial communication library for host-to-device

 - igt_serial_open()/close(): lifecycle with configurable baud rate
 - igt_serial_send()/read(): raw data transfer
 - igt_serial_command(): send command and capture response
 - igt_serial_flush(): drain stale data from receive buffer
 - igt_serial_set_timeout(): adjust per-operation VTIME timeouts

Used by lib/igt_usb4_switch to communicate with the Microsoft USB4
Switch 3141 over its serial/USB interface.

Signed-off-by: Kunal Joshi <kunal1.joshi@intel.com>
---
 lib/igt_serial.c | 435 +++++++++++++++++++++++++++++++++++++++++++++++
 lib/igt_serial.h |  32 ++++
 lib/meson.build  |   1 +
 3 files changed, 468 insertions(+)
 create mode 100644 lib/igt_serial.c
 create mode 100644 lib/igt_serial.h

diff --git a/lib/igt_serial.c b/lib/igt_serial.c
new file mode 100644
index 000000000..35fbadd7c
--- /dev/null
+++ b/lib/igt_serial.c
@@ -0,0 +1,435 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2026 Intel Corporation
+ */
+
+/**
+ * SECTION:igt_serial
+ * @short_description: Generic serial port communication library
+ * @title: Serial Communication
+ * @include: igt_serial.h
+ *
+ * This library provides a clean API for serial port communication,
+ * useful for test equipment that uses serial/USB-CDC interfaces.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "igt_core.h"
+#include "igt_serial.h"
+
+struct igt_serial {
+	int fd;
+	char *device;
+	struct termios orig_termios;
+	bool termios_saved;
+	int read_timeout_ds;
+};
+
+static speed_t baud_to_speed(int baud)
+{
+	switch (baud) {
+	case 9600:   return B9600;
+	case 19200:  return B19200;
+	case 38400:  return B38400;
+	case 57600:  return B57600;
+	case 115200: return B115200;
+	case 230400: return B230400;
+	case 460800: return B460800;
+	case 921600: return B921600;
+	default:
+		return 0;
+	}
+}
+
+/**
+ * igt_serial_open:
+ * @device: path to the serial device (e.g., "/dev/ttyACM0")
+ * @baud_rate: baud rate (e.g., 115200)
+ *
+ * Opens a serial port with the specified baud rate.
+ * Uses 8N1 configuration (8 data bits, no parity, 1 stop bit).
+ *
+ * Returns: A serial handle on success, NULL on failure.
+ */
+struct igt_serial *igt_serial_open(const char *device, int baud_rate)
+{
+	struct igt_serial *s;
+	struct termios tty;
+	speed_t speed;
+
+	if (!device) {
+		igt_debug("Serial: NULL device path\n");
+		return NULL;
+	}
+
+	s = calloc(1, sizeof(*s));
+	if (!s) {
+		igt_debug("Serial: Failed to allocate memory\n");
+		return NULL;
+	}
+
+	s->fd = -1;
+
+	s->device = strdup(device);
+	if (!s->device)
+		goto err_free;
+
+	/* Default timeout: 1 second (10 deciseconds) */
+	s->read_timeout_ds = 10;
+	s->fd = open(device, O_RDWR | O_NOCTTY);
+
+	if (s->fd < 0) {
+		igt_debug("Serial: Failed to open %s: %s\n",
+			  device, strerror(errno));
+		goto err_free_device;
+	}
+
+	if (tcgetattr(s->fd, &tty) != 0) {
+		igt_debug("Serial: tcgetattr failed: %s\n", strerror(errno));
+		goto err_close;
+	}
+
+	s->orig_termios = tty;
+	s->termios_saved = true;
+	speed = baud_to_speed(baud_rate);
+
+	if (!speed) {
+		igt_debug("Serial: Unsupported baud rate %d\n", baud_rate);
+		goto err_close;
+	}
+
+	cfsetospeed(&tty, speed);
+	cfsetispeed(&tty, speed);
+
+	/* 8N1: 8 data bits, no parity, 1 stop bit */
+	tty.c_cflag &= ~PARENB;
+	tty.c_cflag &= ~CSTOPB;
+	tty.c_cflag &= ~CSIZE;
+	tty.c_cflag |= CS8;
+	tty.c_cflag &= ~CRTSCTS;
+	tty.c_cflag |= CREAD | CLOCAL;
+
+	/* Disable canonical mode, echo, and signals */
+	tty.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
+
+	/* Disable output post-processing */
+	tty.c_oflag &= ~OPOST;
+
+	/* Disable software flow control and input translations */
+	tty.c_iflag &= ~(IXON | IXOFF | IXANY);
+	tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP |
+			  INLCR | IGNCR | ICRNL);
+
+	/*
+	 * Blocking read with timeout.
+	 * VMIN=0, VTIME>0: return after timeout or when data available.
+	 */
+	tty.c_cc[VMIN] = 0;
+	tty.c_cc[VTIME] = s->read_timeout_ds;
+
+	if (tcsetattr(s->fd, TCSANOW, &tty) != 0) {
+		igt_debug("Serial: tcsetattr failed: %s\n", strerror(errno));
+		goto err_close;
+	}
+
+	/* Flush any stale input */
+	if (tcflush(s->fd, TCIFLUSH) != 0)
+		igt_debug("Serial: tcflush failed: %s\n", strerror(errno));
+
+	igt_debug("Serial: Opened %s at %d baud (timeout=%dms)\n",
+		  s->device, baud_rate, s->read_timeout_ds * 100);
+	return s;
+
+err_close:
+	close(s->fd);
+err_free_device:
+	free(s->device);
+err_free:
+	free(s);
+	return NULL;
+}
+
+/**
+ * igt_serial_close:
+ * @s: serial handle
+ *
+ * Closes the serial port and frees resources.
+ */
+void igt_serial_close(struct igt_serial *s)
+{
+	if (!s)
+		return;
+
+	if (s->termios_saved) {
+		if (tcsetattr(s->fd, TCSANOW, &s->orig_termios) != 0)
+			igt_debug("Serial: tcsetattr restore failed: %s\n",
+				  strerror(errno));
+	}
+
+	if (s->fd >= 0)
+		close(s->fd);
+	igt_debug("Serial: Closed %s\n", s->device ? s->device : "(unknown)");
+	free(s->device);
+	free(s);
+}
+
+/**
+ * igt_serial_set_timeout:
+ * @s: serial handle
+ * @timeout_ms: timeout in milliseconds (0 enables polling mode)
+ *
+ * Sets the read timeout for the serial port. VTIME has a granularity
+ * of 100 ms (deciseconds); non-zero values are rounded up. Setting
+ * @timeout_ms to 0 configures polling mode where reads return
+ * immediately if no data is available.
+ *
+ * Returns: true on success, false on failure.
+ */
+bool igt_serial_set_timeout(struct igt_serial *s, int timeout_ms)
+{
+	struct termios tty;
+	int new_timeout_ds;
+
+	if (!s || timeout_ms < 0)
+		return false;
+
+	if (tcgetattr(s->fd, &tty) != 0) {
+		igt_debug("Serial: tcgetattr failed: %s\n", strerror(errno));
+		return false;
+	}
+
+	/* Convert ms to deciseconds (0.1s units), clamp to cc_t max (255) */
+	new_timeout_ds = (timeout_ms + 99) / 100;
+	if (new_timeout_ds > 255)
+		new_timeout_ds = 255;
+
+	tty.c_cc[VTIME] = new_timeout_ds;
+
+	if (tcsetattr(s->fd, TCSANOW, &tty) != 0) {
+		igt_debug("Serial: tcsetattr failed: %s\n", strerror(errno));
+		return false;
+	}
+	s->read_timeout_ds = new_timeout_ds;
+	igt_debug("Serial: Timeout set to %dms (applied %dms)\n",
+		  timeout_ms, s->read_timeout_ds * 100);
+	return true;
+}
+
+/**
+ * igt_serial_send:
+ * @s: serial handle
+ * @cmd: command string to send
+ *
+ * Sends a command string to the serial port exactly as provided.
+ * The caller is responsible for adding any required line endings.
+ * Handles short writes that may occur on USB-CDC devices under load.
+ *
+ * Returns: true on success, false on failure.
+ */
+bool igt_serial_send(struct igt_serial *s, const char *cmd)
+{
+	size_t len, total = 0;
+	ssize_t written;
+
+	if (!s || !cmd)
+		return false;
+
+	len = strlen(cmd);
+	if (len == 0)
+		return true;
+
+	while (total < len) {
+		written = write(s->fd, cmd + total, len - total);
+		if (written <= 0) {
+			if (written < 0 && errno == EINTR)
+				continue;
+			igt_debug("Serial: Write failed: %s\n",
+				  written < 0 ? strerror(errno) : "zero bytes written");
+			return false;
+		}
+		total += written;
+	}
+
+	if (tcdrain(s->fd) != 0) {
+		igt_debug("Serial: tcdrain failed: %s\n", strerror(errno));
+		return false;
+	}
+
+	igt_debug("Serial: Sent '%s'\n", cmd);
+	return true;
+}
+
+/*
+ * igt_serial_readline - Read a line from serial port (until newline or timeout).
+ *
+ * Returns number of bytes in buf (0 means timeout/no data), or -1 on error.
+ */
+static ssize_t igt_serial_readline(struct igt_serial *s, char *buf, size_t size)
+{
+	size_t total = 0;
+	ssize_t n;
+
+	if (!s || !buf || size == 0)
+		return -1;
+
+	/*
+	 * Read one byte at a time until newline or timeout.
+	 * VTIME timeout ensures read() returns 0 on timeout.
+	 */
+	while (total < size - 1) {
+		n = read(s->fd, buf + total, 1);
+		if (n < 0) {
+			if (errno == EINTR)
+				continue;
+			igt_debug("Serial: Read error: %s\n", strerror(errno));
+			return -1;
+		}
+		if (n == 0)
+			break;
+
+		total++;
+
+		if (buf[total - 1] == '\n')
+			break;
+	}
+
+	buf[total] = '\0';
+	return (ssize_t)total;
+}
+
+/**
+ * igt_serial_read:
+ * @s: serial handle
+ * @buf: buffer to read into
+ * @size: size of buffer
+ *
+ * Reads one line (up to newline or timeout) from the serial port.
+ * This is a line-oriented read, not an arbitrary byte read — it stops
+ * at the first newline character or when the VTIME timeout expires.
+ * Use igt_serial_set_timeout() to adjust the timeout before calling.
+ *
+ * Returns: Number of bytes read, 0 on timeout/no data, or -1 on error.
+ */
+ssize_t igt_serial_read(struct igt_serial *s, char *buf, size_t size)
+{
+	ssize_t n;
+
+	n = igt_serial_readline(s, buf, size);
+
+	igt_debug("Serial: Read %zd bytes: '%s'\n", n, n > 0 ? buf : "");
+	return n;
+}
+
+/**
+ * igt_serial_command:
+ * @s: serial handle
+ * @cmd: command string to send
+ * @response: buffer for response
+ * @resp_size: size of response buffer
+ *
+ * Convenience function to send a command and read the response.
+ * Flushes stale input before sending, sends the command, then reads
+ * one response line. If @response is non-NULL, at least one byte must
+ * be received before the configured VTIME timeout for success.
+ *
+ * Returns: true if the send succeeded and, when @response is given,
+ * at least one response byte was received; false otherwise.
+ */
+bool igt_serial_command(struct igt_serial *s, const char *cmd,
+			char *response, size_t resp_size)
+{
+	ssize_t n;
+
+	if (!s || !cmd)
+		return false;
+
+	igt_serial_flush(s);
+
+	if (!igt_serial_send(s, cmd))
+		return false;
+
+	if (response && resp_size > 0) {
+		n = igt_serial_readline(s, response, resp_size);
+		if (n <= 0) {
+			igt_debug("Serial: No response received\n");
+			return false;
+		}
+		igt_debug("Serial: Response: '%s'\n", response);
+	}
+
+	return true;
+}
+
+/**
+ * igt_serial_flush:
+ * @s: serial handle
+ *
+ * Discards stale input. Does not touch pending output.
+ * Calls TCIFLUSH to drop kernel-queued input, then temporarily sets
+ * O_NONBLOCK and drains any bytes already readable to reduce races
+ * with in-flight input. Assumes single-threaded access.
+ */
+void igt_serial_flush(struct igt_serial *s)
+{
+	char discard[256];
+	ssize_t n;
+	int flags;
+
+	if (!s)
+		return;
+
+	/* Discard kernel-queued input; never touch pending output */
+	if (tcflush(s->fd, TCIFLUSH) != 0)
+		igt_debug("Serial: tcflush failed: %s\n", strerror(errno));
+
+	/* Drain bytes already readable to reduce races with in-flight input */
+	flags = fcntl(s->fd, F_GETFL);
+	if (flags < 0) {
+		igt_debug("Serial: fcntl(F_GETFL) failed: %s\n", strerror(errno));
+		return;
+	}
+
+	if (fcntl(s->fd, F_SETFL, flags | O_NONBLOCK) < 0) {
+		igt_debug("Serial: fcntl(F_SETFL) failed: %s\n", strerror(errno));
+		return;
+	}
+
+	for (;;) {
+		n = read(s->fd, discard, sizeof(discard));
+		if (n > 0)
+			continue;
+		if (n == 0)
+			break;
+		/* n < 0 */
+		if (errno == EINTR)
+			continue;
+		if (errno != EAGAIN)
+			igt_debug("Serial: unexpected read error in flush: %s\n",
+				  strerror(errno));
+		break;
+	}
+
+	if (fcntl(s->fd, F_SETFL, flags) < 0)
+		igt_debug("Serial: fcntl(F_SETFL) restore failed: %s\n", strerror(errno));
+
+	igt_debug("Serial: Flushed\n");
+}
+
+/**
+ * igt_serial_get_fd:
+ * @s: serial handle
+ *
+ * Gets the underlying file descriptor for advanced operations.
+ *
+ * Returns: File descriptor, or -1 if handle is NULL.
+ */
+int igt_serial_get_fd(struct igt_serial *s)
+{
+	return s ? s->fd : -1;
+}
diff --git a/lib/igt_serial.h b/lib/igt_serial.h
new file mode 100644
index 000000000..b460fbf16
--- /dev/null
+++ b/lib/igt_serial.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2026 Intel Corporation
+ */
+
+#ifndef IGT_SERIAL_H
+#define IGT_SERIAL_H
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <sys/types.h>
+
+/**
+ * IGT_SERIAL_DEFAULT_TIMEOUT_MS:
+ *
+ * Default timeout for serial read operations in milliseconds.
+ */
+#define IGT_SERIAL_DEFAULT_TIMEOUT_MS 1000
+
+struct igt_serial;
+
+struct igt_serial *igt_serial_open(const char *device, int baud_rate);
+void igt_serial_close(struct igt_serial *s);
+bool igt_serial_set_timeout(struct igt_serial *s, int timeout_ms);
+bool igt_serial_send(struct igt_serial *s, const char *cmd);
+ssize_t igt_serial_read(struct igt_serial *s, char *buf, size_t size);
+bool igt_serial_command(struct igt_serial *s, const char *cmd,
+			char *response, size_t resp_size);
+void igt_serial_flush(struct igt_serial *s);
+int igt_serial_get_fd(struct igt_serial *s);
+
+#endif /* IGT_SERIAL_H */
diff --git a/lib/meson.build b/lib/meson.build
index 074b21fdf..67b57533c 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -123,6 +123,7 @@ lib_sources = [
 	'igt_msm.c',
 	'igt_dsc.c',
 	'igt_hook.c',
+	'igt_serial.c',
 	'xe/xe_gt.c',
 	'xe/xe_ioctl.c',
 	'xe/xe_legacy.c',
-- 
2.25.1


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

* [PATCH i-g-t 4/6] lib/igt_usb4_switch: add helper library for USB4 Switch 3141
  2026-02-25 21:28 [PATCH i-g-t 0/6] add test to validate dock/undock and switch Kunal Joshi
                   ` (2 preceding siblings ...)
  2026-02-25 21:28 ` [PATCH i-g-t 3/6] lib/igt_serial: add generic serial communication helper Kunal Joshi
@ 2026-02-25 21:28 ` Kunal Joshi
  2026-03-16  8:45   ` [i-g-t,4/6] " Murthy, Arun R
  2026-02-25 21:28 ` [PATCH i-g-t 5/6] tests/kms_feature_discovery: add basic usb4 switch discovery Kunal Joshi
                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 25+ messages in thread
From: Kunal Joshi @ 2026-02-25 21:28 UTC (permalink / raw)
  To: igt-dev; +Cc: Kunal Joshi

Add a control library for the Microsft USB4 Switch 3141 test equipment,
used for automated USB4/Thunderbolt dock/undock testing:

 - usb4switch_init()/deinit(): lifecycle with
   .igtrc config or autodiscovery
 - usb4switch_port_enable()/disable(): port control with optional HW delay
 - usb4switch_get_active_port(): query current port state
 - usb4switch_get_voltage_mv()/get_current_ma(): VBUS monitoring
 - usb4switch_get_orientation(): USB-C cable orientation

Signed-off-by: Kunal Joshi <kunal1.joshi@intel.com>
---
 lib/igt_usb4_switch.c | 1055 +++++++++++++++++++++++++++++++++++++++++
 lib/igt_usb4_switch.h |  157 ++++++
 lib/meson.build       |    1 +
 3 files changed, 1213 insertions(+)
 create mode 100644 lib/igt_usb4_switch.c
 create mode 100644 lib/igt_usb4_switch.h

diff --git a/lib/igt_usb4_switch.c b/lib/igt_usb4_switch.c
new file mode 100644
index 000000000..5cede4d60
--- /dev/null
+++ b/lib/igt_usb4_switch.c
@@ -0,0 +1,1055 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2026 Intel Corporation
+ */
+
+/**
+ * SECTION:igt_usb4_switch
+ * @short_description: USB4 Switch 3141 control library
+ * @title: USB4 Switch
+ * @include: igt_usb4_switch.h
+ *
+ * This library provides control and status functions for the Microsoft
+ * USB4 Switch 3141 test equipment, used for automated USB4/Thunderbolt
+ * dock/undock testing.
+ *
+ * The library handles serial communication, port control, and
+ * configuration parsing.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "igt_core.h"
+#include "igt_rc.h"
+#include "igt_serial.h"
+#include "igt_usb4_switch.h"
+#include "igt_connector_helper.h"
+
+struct usb4switch {
+	struct igt_serial *serial;
+
+	/* Configuration */
+	char *device_path;
+	int hotplug_timeout_s;
+	int iterations;
+	int min_switch_interval_ms;
+
+	/* Timestamp of last port change for minimum interval enforcement */
+	struct timespec last_port_change;
+
+	/* Port configuration */
+	struct usb4switch_port ports[USB4_SWITCH_MAX_PORTS];
+	int port_count;
+};
+
+/* .igtrc section and key names */
+#define USB4_SWITCH_SECTION "USB4Switch"
+#define USB4_SWITCH_KEY_DEVICE "Device"
+#define USB4_SWITCH_KEY_HOTPLUG_TIMEOUT "HotplugTimeout"
+#define USB4_SWITCH_KEY_ITERATIONS "DockUndockIterations"
+#define USB4_SWITCH_KEY_MIN_INTERVAL "MinSwitchInterval"
+
+/*
+ * response_is_ok - Check that a firmware response does not indicate an error.
+ *
+ * The 3141 prefixes error replies with "ERR" (e.g. "ERR: unknown command").
+ * An empty response after a successful transport exchange is also treated as
+ * failure because no meaningful control command produces an empty reply.
+ *
+ * This is a transport vs. command-level distinction: send_command() only
+ * guarantees that bytes were exchanged; callers that need to know whether
+ * the firmware actually accepted the command must call response_is_ok().
+ */
+static bool response_is_ok(const char *response)
+{
+	if (!response || response[0] == '\0')
+		return false;
+
+	if (strncasecmp(response, "ERR", 3) == 0)
+		return false;
+
+	return true;
+}
+
+/*
+ * Minimum-interval helpers - enforce a floor between successive port
+ * operations to protect hardware from rapid switching.
+ */
+static void enforce_min_interval(struct usb4switch *sw)
+{
+	struct timespec now;
+	int elapsed_ms;
+
+	if (sw->last_port_change.tv_sec == 0 &&
+	    sw->last_port_change.tv_nsec == 0)
+		return;
+
+	clock_gettime(CLOCK_MONOTONIC, &now);
+	elapsed_ms = (now.tv_sec - sw->last_port_change.tv_sec) * 1000 +
+		     (now.tv_nsec - sw->last_port_change.tv_nsec) / 1000000;
+
+	if (elapsed_ms < sw->min_switch_interval_ms) {
+		int wait = sw->min_switch_interval_ms - elapsed_ms;
+
+		igt_debug("USB4Switch: enforcing %d ms minimum interval "
+			  "(sleeping %d ms)\n",
+			  sw->min_switch_interval_ms, wait);
+		usleep(wait * 1000);
+	}
+}
+
+/**
+ * send_command:
+ * @sw: switch handle
+ * @cmd: command string (without line ending)
+ * @response: buffer for response
+ * @resp_size: size of response buffer
+ *
+ * Sends a command to the USB4 Switch 3141.
+ * Appends CRLF as required by the switch protocol.
+ *
+ * Note: success means the serial exchange completed and at least one byte
+ * was received. It does not validate the firmware response payload — callers
+ * that care about command-level success must check response_is_ok().
+ *
+ * Returns: true if the exchange succeeded, false on transport error.
+ */
+static bool send_command(struct usb4switch *sw, const char *cmd,
+			 char *response, size_t resp_size)
+{
+	char cmd_with_crlf[256];
+	int len;
+
+	if (!sw || !sw->serial || !cmd)
+		return false;
+
+	len = snprintf(cmd_with_crlf, sizeof(cmd_with_crlf), "%s\r\n", cmd);
+	if (len < 0 || (size_t)len >= sizeof(cmd_with_crlf))
+		return false;
+
+	return igt_serial_command(sw->serial, cmd_with_crlf,
+				  response, resp_size);
+}
+
+static bool verify_communication(struct usb4switch *sw)
+{
+	char response[256];
+
+	if (!send_command(sw, "version", response, sizeof(response))) {
+		igt_debug("USB4Switch: Failed to query version\n");
+		return false;
+	}
+
+	if (!response_is_ok(response)) {
+		igt_debug("USB4Switch: Version command rejected: '%s'\n",
+			  response);
+		return false;
+	}
+
+	/*
+	 * The device was already identified by VID:PID in
+	 * discover_usb4_switch_device(). Here we just confirm the serial
+	 * link is alive.  The firmware returns only its firmware version
+	 * (e.g. "0201"), not the model number.
+	 */
+	igt_debug("USB4Switch: Version response: %s\n", response);
+	return true;
+}
+
+static char *get_config_string(const char *key)
+{
+	char *value = NULL;
+	GError *error = NULL;
+
+	value = g_key_file_get_string(igt_key_file, USB4_SWITCH_SECTION,
+				      key, &error);
+	if (error) {
+		g_error_free(error);
+		return NULL;
+	}
+	return value;
+}
+
+static int get_config_int(const char *key, int default_value)
+{
+	GError *error = NULL;
+	int value;
+
+	value = g_key_file_get_integer(igt_key_file, USB4_SWITCH_SECTION,
+				       key, &error);
+	if (error) {
+		g_error_free(error);
+		return default_value;
+	}
+	return value;
+}
+
+static void free_display_config(struct usb4switch_display *disp)
+{
+	free(disp->connector_path);
+	disp->connector_path = NULL;
+	free(disp->connector_name);
+	disp->connector_name = NULL;
+	free(disp->edid_serial);
+	disp->edid_serial = NULL;
+}
+
+static void free_port_config(struct usb4switch_port *port)
+{
+	int i;
+
+	free(port->name);
+	for (i = 0; i < USB4_SWITCH_MAX_DISPLAYS_PER_PORT; i++)
+		free_display_config(&port->displays[i]);
+}
+
+static void free_config(struct usb4switch *sw)
+{
+	int i;
+
+	free(sw->device_path);
+	for (i = 0; i < USB4_SWITCH_MAX_PORTS; i++)
+		free_port_config(&sw->ports[i]);
+}
+
+static void parse_display_config(struct usb4switch *sw, int port_idx,
+				 int disp_idx)
+{
+	struct usb4switch_display *disp;
+	char key[64];
+
+	disp = &sw->ports[port_idx].displays[disp_idx];
+
+	/* Path takes precedence for MST */
+	snprintf(key, sizeof(key), "Port%d.Display%d.Path",
+		 port_idx + 1, disp_idx + 1);
+	disp->connector_path = get_config_string(key);
+
+	/* Connector name as fallback */
+	snprintf(key, sizeof(key), "Port%d.Display%d.Connector",
+		 port_idx + 1, disp_idx + 1);
+	disp->connector_name = get_config_string(key);
+
+	/* EDID serial for verification */
+	snprintf(key, sizeof(key), "Port%d.Display%d.EDIDSerial",
+		 port_idx + 1, disp_idx + 1);
+	disp->edid_serial = get_config_string(key);
+}
+
+static void parse_port_config(struct usb4switch *sw, int port_idx)
+{
+	struct usb4switch_port *port;
+	char key[64];
+	int i;
+
+	port = &sw->ports[port_idx];
+	port->port_num = port_idx + 1;
+
+	snprintf(key, sizeof(key), "Port%d.Name", port_idx + 1);
+	port->name = get_config_string(key);
+	if (!port->name) {
+		port->name = malloc(16);
+		if (port->name)
+			snprintf(port->name, 16, "Port %d", port_idx + 1);
+	}
+
+	/*
+	 * Parse all display slots, then count the leading contiguous
+	 * prefix.  display_count is the exact number of valid entries
+	 * accessible via displays[0..display_count-1].
+	 */
+	for (i = 0; i < USB4_SWITCH_MAX_DISPLAYS_PER_PORT; i++)
+		parse_display_config(sw, port_idx, i);
+
+	/* Count leading contiguous displays (Display1, Display2, ...) */
+	port->display_count = 0;
+	for (i = 0; i < USB4_SWITCH_MAX_DISPLAYS_PER_PORT; i++) {
+		if (sw->ports[port_idx].displays[i].connector_path ||
+		    sw->ports[port_idx].displays[i].connector_name)
+			port->display_count++;
+		else
+			break;
+	}
+
+	/* Warn about and free any sparse entries beyond the contiguous prefix */
+	for (; i < USB4_SWITCH_MAX_DISPLAYS_PER_PORT; i++) {
+		if (sw->ports[port_idx].displays[i].connector_path ||
+		    sw->ports[port_idx].displays[i].connector_name) {
+			igt_warn("USB4Switch: Port%d.Display%d configured "
+				 "but Display%d is missing; displays must "
+				 "be contiguous from 1 — ignoring\n",
+				 port_idx + 1, i + 1,
+				 port->display_count + 1);
+			free_display_config(&sw->ports[port_idx].displays[i]);
+		}
+	}
+}
+
+static bool parse_config(struct usb4switch *sw)
+{
+	int i;
+
+	sw->device_path = get_config_string(USB4_SWITCH_KEY_DEVICE);
+	if (!sw->device_path) {
+		igt_debug("USB4Switch: No Device configured\n");
+		return false;
+	}
+
+	sw->hotplug_timeout_s =
+		get_config_int(USB4_SWITCH_KEY_HOTPLUG_TIMEOUT,
+			       USB4_SWITCH_DEFAULT_HOTPLUG_TIMEOUT_S);
+	sw->iterations =
+		get_config_int(USB4_SWITCH_KEY_ITERATIONS,
+			       USB4_SWITCH_DEFAULT_ITERATIONS);
+	sw->min_switch_interval_ms =
+		get_config_int(USB4_SWITCH_KEY_MIN_INTERVAL,
+			       USB4_SWITCH_DEFAULT_MIN_INTERVAL_MS);
+
+	/*
+	 * Count only leading contiguous ports that have at least one display.
+	 * Stop at the first port with no displays — this enforces contiguous
+	 * port numbering (Port1, Port2, ...) and means port_count is the exact
+	 * number of valid ports accessible via ports[0..port_count-1].
+	 */
+	sw->port_count = 0;
+	for (i = 0; i < USB4_SWITCH_MAX_PORTS; i++) {
+		parse_port_config(sw, i);
+		if (sw->ports[i].display_count > 0)
+			sw->port_count++;
+		else
+			break;
+	}
+
+	if (sw->port_count == 0)
+		igt_warn("USB4Switch: Device configured but no display keys found\n");
+
+	igt_debug("USB4Switch: Device=%s, Timeout=%ds, Iterations=%d, Ports=%d\n",
+		  sw->device_path, sw->hotplug_timeout_s, sw->iterations,
+		  sw->port_count);
+
+	return true;
+}
+
+static void stamp_port_change(struct usb4switch *sw)
+{
+	clock_gettime(CLOCK_MONOTONIC, &sw->last_port_change);
+}
+
+static bool usb4switch_queue_port_change_delayed(struct usb4switch *sw,
+						 int port,
+						 int delay_seconds,
+						 const char *action)
+{
+	char cmd[32];
+	char response[256];
+
+	if (!sw)
+		return false;
+
+	if (port < 0 || port > USB4_SWITCH_MAX_PORTS) {
+		igt_warn("USB4Switch: Invalid port %d\n", port);
+		return false;
+	}
+
+	if (delay_seconds < 0 || delay_seconds > 3600) {
+		igt_warn("USB4Switch: Invalid delay %d (must be 0-3600)\n",
+			 delay_seconds);
+		return false;
+	}
+
+	enforce_min_interval(sw);
+
+	snprintf(cmd, sizeof(cmd), "delay %d", delay_seconds);
+	if (!send_command(sw, cmd, response, sizeof(response))) {
+		igt_warn("USB4Switch: Failed to set delay %d\n", delay_seconds);
+		return false;
+	}
+
+	if (!response_is_ok(response)) {
+		igt_warn("USB4Switch: Failed to set delay %d (response: '%s')\n",
+			 delay_seconds, response);
+		return false;
+	}
+
+	snprintf(cmd, sizeof(cmd), "port %d", port);
+	if (!send_command(sw, cmd, response, sizeof(response))) {
+		igt_warn("USB4Switch: Failed to queue %s command\n", action);
+		return false;
+	}
+
+	if (!response_is_ok(response)) {
+		igt_warn("USB4Switch: Failed to queue %s command (response: '%s')\n",
+			 action, response);
+		return false;
+	}
+
+	stamp_port_change(sw);
+	igt_debug("USB4Switch: Queued %s with %ds delay\n",
+		  action, delay_seconds);
+
+	return true;
+}
+
+/*
+ * USB VID:PID for Microsoft USB4 Switch 3141
+ */
+#define USB4_SWITCH_VID "045e"
+#define USB4_SWITCH_PID "0646"
+
+/*
+ * Linux USB uevent PRODUCT= format uses lowercase hex without leading
+ * zeros: VID 0x045e → "45e", PID 0x0646 → "646".
+ */
+#define USB4_SWITCH_UEVENT_MATCH "PRODUCT=45e/646/"
+
+/*
+ * When no .igtrc configuration is present, autodiscover:
+ * - USB4 switch device by scanning /sys/class/tty for matching VID:PID
+ * - Displays behind each port by comparing connectors before/after docking
+ */
+static char *discover_usb4_switch_device(void)
+{
+	char path[256];
+	char uevent[512];
+	char *device_path = NULL;
+	FILE *fp;
+	int i;
+
+	/*
+	 * Scan ttyACM0..63. The 3141 almost always lands in the low
+	 * range, but the upper bound is generous to handle busy systems.
+	 */
+	for (i = 0; i < 64; i++) {
+		snprintf(path, sizeof(path),
+			 "/sys/class/tty/ttyACM%d/device/uevent", i);
+
+		fp = fopen(path, "r");
+		if (!fp)
+			continue;
+
+		while (fgets(uevent, sizeof(uevent), fp)) {
+			if (strstr(uevent, USB4_SWITCH_UEVENT_MATCH)) {
+				device_path = malloc(32);
+				if (device_path)
+					snprintf(device_path, 32,
+						 "/dev/ttyACM%d", i);
+				break;
+			}
+		}
+
+		fclose(fp);
+		if (device_path)
+			break;
+	}
+
+	if (device_path)
+		igt_debug("USB4Switch: Autodiscovered device at %s\n",
+			  device_path);
+	else
+		igt_debug("USB4Switch: No device found during autodiscovery\n");
+
+	return device_path;
+}
+
+/*
+ * discover_port_displays - Dock a port and compare connectors to find
+ * which displays appear. drm_fd is passed as parameter, NOT stored.
+ */
+static bool discover_port_displays(struct usb4switch *sw, int drm_fd,
+				   int port_num, uint32_t *before,
+				   int before_count)
+{
+	struct usb4switch_port *port = &sw->ports[port_num - 1];
+	uint32_t after[32];
+	int after_count;
+	char name[32];
+	char serial[64];
+	int i, j, wait;
+	bool found;
+
+	if (!usb4switch_port_enable(sw, port_num)) {
+		igt_debug("USB4Switch: Failed to enable port %d\n", port_num);
+		return false;
+	}
+
+	igt_debug("USB4Switch: Waiting for port %d displays...\n", port_num);
+	/* Poll for new connectors (max 10s) instead of fixed sleep */
+	after_count = 0;
+	for (wait = 0; wait < 10; wait++) {
+		sleep(1);
+		igt_connector_reprobe_all(drm_fd);
+		after_count = igt_connector_get_connected(drm_fd, after, 32);
+		if (after_count > before_count)
+			break;
+	}
+
+	if (after_count <= before_count) {
+		igt_debug("USB4Switch: No new connectors detected on port %d\n",
+			  port_num);
+		usb4switch_port_disable_and_wait(sw);
+		return false;
+	}
+
+	port->port_num = port_num;
+	port->name = malloc(16);
+	if (port->name)
+		snprintf(port->name, 16, "port-%d", port_num);
+	port->display_count = 0;
+
+	for (i = 0; i < after_count; i++) {
+		found = false;
+		for (j = 0; j < before_count; j++) {
+			if (after[i] == before[j]) {
+				found = true;
+				break;
+			}
+		}
+
+		if (!found &&
+		    port->display_count < USB4_SWITCH_MAX_DISPLAYS_PER_PORT) {
+			char path[256];
+
+			if (igt_connector_get_info(drm_fd, after[i],
+						   name, sizeof(name),
+						   serial, sizeof(serial),
+						   path, sizeof(path))) {
+				struct usb4switch_display *disp;
+
+				disp = &port->displays[port->display_count];
+				disp->connector_name = strdup(name);
+				if (!disp->connector_name)
+					continue;
+				disp->edid_serial = serial[0] ?
+						    strdup(serial) : NULL;
+				disp->connector_path = path[0] ?
+						       strdup(path) : NULL;
+
+				igt_info("USB4Switch: Port %d Display %d: %s (EDID: %s)\n",
+					 port_num, port->display_count + 1,
+					 name,
+					 serial[0] ? serial : "none");
+
+				port->display_count++;
+			}
+		}
+	}
+
+	usb4switch_port_disable_and_wait(sw);
+	igt_connector_reprobe_all(drm_fd);
+
+	if (port->display_count > 0)
+		sw->port_count++;
+
+	return port->display_count > 0;
+}
+
+/*
+ * autodiscover_config - Autodiscover switch device and port displays.
+ */
+static bool autodiscover_config(struct usb4switch *sw, int drm_fd)
+{
+	uint32_t before[32];
+	int before_count;
+	int p;
+
+	sw->device_path = discover_usb4_switch_device();
+	if (!sw->device_path)
+		return false;
+
+	sw->hotplug_timeout_s = USB4_SWITCH_DEFAULT_HOTPLUG_TIMEOUT_S;
+	sw->iterations = USB4_SWITCH_DEFAULT_ITERATIONS;
+	sw->min_switch_interval_ms = USB4_SWITCH_DEFAULT_MIN_INTERVAL_MS;
+	sw->port_count = 0;
+
+	sw->serial = igt_serial_open(sw->device_path, 115200);
+	if (!sw->serial) {
+		igt_debug("USB4Switch: Failed to open autodiscovered device %s\n",
+			  sw->device_path);
+		free(sw->device_path);
+		sw->device_path = NULL;
+		return false;
+	}
+
+	if (!verify_communication(sw)) {
+		igt_serial_close(sw->serial);
+		sw->serial = NULL;
+		free(sw->device_path);
+		sw->device_path = NULL;
+		return false;
+	}
+
+	igt_info("USB4Switch: Autodiscovering displays...\n");
+
+	usb4switch_port_disable_and_wait(sw);
+
+	igt_connector_reprobe_all(drm_fd);
+
+	before_count = igt_connector_get_connected(drm_fd, before, 32);
+	if (before_count >= 32)
+		igt_warn("USB4Switch: Connector count %d may exceed array size\n",
+			 before_count);
+	igt_debug("USB4Switch: %d connectors before autodiscovery\n",
+		  before_count);
+
+	/*
+	 * Probe ports sequentially. Stop at the first port that yields no
+	 * displays — same contiguity rule as config-based port counting.
+	 */
+	for (p = 1; p <= USB4_SWITCH_MAX_PORTS; p++) {
+		if (!discover_port_displays(sw, drm_fd, p, before, before_count))
+			break;
+	}
+
+	usb4switch_port_disable(sw);
+
+	igt_info("USB4Switch: Autodiscovery complete - %d ports with displays\n",
+		 sw->port_count);
+
+	return sw->port_count > 0;
+}
+
+/**
+ * usb4switch_init:
+ * @drm_fd: DRM file descriptor (used only for autodiscovery, not stored)
+ *
+ * Initializes USB4 switch from .igtrc configuration.
+ * If no configuration is present, attempts
+ * autodiscovery of the switch device and displays behind each port.
+ *
+ * Returns: Switch handle on success, NULL on failure.
+ */
+struct usb4switch *usb4switch_init(int drm_fd)
+{
+	struct usb4switch *sw;
+	bool config_ok;
+
+	sw = calloc(1, sizeof(*sw));
+	if (!sw)
+		return NULL;
+
+	config_ok = parse_config(sw);
+
+	if (!config_ok) {
+		if (drm_fd < 0) {
+			igt_debug("USB4Switch: No config and no DRM fd for autodiscovery\n");
+			free_config(sw);
+			free(sw);
+			return NULL;
+		}
+
+		igt_info("USB4Switch: No configuration found, attempting autodiscovery...\n");
+		if (!autodiscover_config(sw, drm_fd)) {
+			igt_debug("USB4Switch: Autodiscovery failed\n");
+			if (sw->serial)
+				igt_serial_close(sw->serial);
+			free_config(sw);
+			free(sw);
+			return NULL;
+		}
+		igt_info("USB4Switch: Initialized via autodiscovery (Model 3141)\n");
+		return sw;
+	}
+
+	sw->serial = igt_serial_open(sw->device_path, 115200);
+	if (!sw->serial) {
+		igt_debug("USB4Switch: Failed to open serial port %s\n",
+			  sw->device_path);
+		free_config(sw);
+		free(sw);
+		return NULL;
+	}
+
+	if (!verify_communication(sw)) {
+		igt_serial_close(sw->serial);
+		free_config(sw);
+		free(sw);
+		return NULL;
+	}
+
+	igt_info("USB4Switch: Initialized (Model 3141)\n");
+	return sw;
+}
+
+/**
+ * usb4switch_deinit:
+ * @sw: switch handle
+ *
+ * Closes the switch and frees resources.
+ * Disables all ports before closing.
+ */
+void usb4switch_deinit(struct usb4switch *sw)
+{
+	if (!sw)
+		return;
+
+	usb4switch_port_disable(sw);
+
+	if (sw->serial)
+		igt_serial_close(sw->serial);
+	free_config(sw);
+	free(sw);
+
+	igt_debug("USB4Switch: Deinitialized\n");
+}
+
+/**
+ * usb4switch_port_enable:
+ * @sw: switch handle
+ * @port: port number (1 or 2)
+ *
+ * Enables the specified port.
+ *
+ * Returns: true on success, false on failure.
+ */
+bool usb4switch_port_enable(struct usb4switch *sw, int port)
+{
+	char cmd[32];
+	char response[256];
+
+	if (!sw || port < 1 || port > USB4_SWITCH_MAX_PORTS)
+		return false;
+
+	enforce_min_interval(sw);
+
+	snprintf(cmd, sizeof(cmd), "port %d", port);
+
+	if (!send_command(sw, cmd, response, sizeof(response))) {
+		igt_warn("USB4Switch: Failed to enable port %d\n", port);
+		return false;
+	}
+	if (!response_is_ok(response)) {
+		igt_warn("USB4Switch: Failed to enable port %d (response: '%s')\n",
+			 port, response);
+		return false;
+	}
+
+	stamp_port_change(sw);
+	igt_debug("USB4Switch: Enabled port %d\n", port);
+	return true;
+}
+
+/**
+ * usb4switch_port_enable_delayed:
+ * @sw: switch handle
+ * @port: port number (1 or 2)
+ * @delay_seconds: delay in seconds before port change executes
+ *
+ * Schedules a port enable after the specified delay using the hardware
+ * delay command on Model 3141. Useful for hotplug-during-suspend tests.
+ *
+ * Returns: true on success, false on failure.
+ */
+bool usb4switch_port_enable_delayed(struct usb4switch *sw, int port,
+				    int delay_seconds)
+{
+	return usb4switch_queue_port_change_delayed(sw, port, delay_seconds,
+						    "port enable");
+}
+
+/**
+ * usb4switch_port_disable_delayed:
+ * @sw: switch handle
+ * @delay_seconds: delay in seconds before port disable executes
+ *
+ * Schedules a port disable (undock) after the specified delay.
+ * Useful for undock-during-suspend tests.
+ *
+ * Returns: true on success, false on failure.
+ */
+bool usb4switch_port_disable_delayed(struct usb4switch *sw, int delay_seconds)
+{
+	return usb4switch_queue_port_change_delayed(sw, 0, delay_seconds,
+						    "port disable");
+}
+
+/**
+ * usb4switch_port_disable:
+ * @sw: switch handle
+ *
+ * Disables all ports.
+ *
+ * Returns: true on success, false on failure.
+ */
+bool usb4switch_port_disable(struct usb4switch *sw)
+{
+	char response[256];
+
+	if (!sw)
+		return false;
+
+	enforce_min_interval(sw);
+
+	if (!send_command(sw, "port 0", response, sizeof(response))) {
+		igt_warn("USB4Switch: Failed to disable ports\n");
+		return false;
+	}
+	if (!response_is_ok(response)) {
+		igt_warn("USB4Switch: Failed to disable ports (response: '%s')\n",
+			 response);
+		return false;
+	}
+
+	stamp_port_change(sw);
+	igt_debug("USB4Switch: Disabled all ports\n");
+	return true;
+}
+
+/**
+ * usb4switch_get_active_port:
+ * @sw: switch handle
+ *
+ * Gets currently active port.
+ *
+ * Returns: Port number (1 or 2), 0 if disabled, -1 on error.
+ */
+int usb4switch_get_active_port(struct usb4switch *sw)
+{
+	char response[256];
+	int port;
+
+	if (!sw)
+		return -1;
+
+	if (!send_command(sw, "port ?", response, sizeof(response)))
+		return -1;
+
+	if (!response_is_ok(response)) {
+		igt_warn("USB4Switch: Port query rejected: '%s'\n", response);
+		return -1;
+	}
+
+	if (sscanf(response, "port: %d", &port) == 1 ||
+	    sscanf(response, "port %d", &port) == 1 ||
+	    sscanf(response, "%d", &port) == 1)
+		return port;
+
+	igt_warn("USB4Switch: Could not parse port response: '%s'\n",
+		 response);
+	return -1;
+}
+
+/**
+ * usb4switch_get_status:
+ * @sw: switch handle
+ * @buf: buffer for status
+ * @size: buffer size
+ *
+ * Gets full status from switch.
+ *
+ * Returns: true on success.
+ */
+bool usb4switch_get_status(struct usb4switch *sw, char *buf, size_t size)
+{
+	if (!sw || !buf || size == 0)
+		return false;
+
+	if (!send_command(sw, "status", buf, size))
+		return false;
+
+	return response_is_ok(buf);
+}
+
+/**
+ * usb4switch_get_voltage_mv:
+ * @sw: switch handle
+ *
+ * Gets VBUS voltage by sending the "volts" command.
+ * The 3141 firmware responds with "X.XX V" (e.g. "4.85 V").
+ *
+ * Note: The 3141 hardware may not have accurate VBUS sense circuitry.
+ * Voltage readback may not be meaningful on all units.
+ *
+ * Returns: Voltage in mV, -1 on error.
+ */
+int usb4switch_get_voltage_mv(struct usb4switch *sw)
+{
+	char response[256];
+	float volts;
+
+	if (!sw)
+		return -1;
+
+	if (!send_command(sw, "volts", response, sizeof(response)))
+		return -1;
+
+	if (sscanf(response, "%f", &volts) == 1)
+		return (int)(volts * 1000);
+
+	return -1;
+}
+
+/**
+ * usb4switch_get_current_ma:
+ * @sw: switch handle
+ *
+ * Gets VBUS current by sending the "amps" command.
+ * The 3141 firmware responds with "XXX mA" (e.g. "125 mA").
+ *
+ * Note: The 3141 hardware may not have accurate current sense circuitry.
+ *
+ * Returns: Current in mA, -1 on error.
+ */
+int usb4switch_get_current_ma(struct usb4switch *sw)
+{
+	char response[256];
+	int current;
+
+	if (!sw)
+		return -1;
+
+	if (!send_command(sw, "amps", response, sizeof(response)))
+		return -1;
+
+	if (sscanf(response, "%d", &current) == 1)
+		return current;
+
+	return -1;
+}
+
+/**
+ * usb4switch_wait_vbus_safe:
+ * @sw: switch handle
+ * @timeout_ms: maximum time to wait in milliseconds
+ *
+ * Waits for VBUS voltage to drop below the Vsafe0V threshold (800 mV)
+ * after a port disable. Polls using the "volts" command. If voltage
+ * readback is not supported or returns errors, falls back to a fixed
+ * 1-second delay.
+ *
+ * Returns: true when VBUS is safe (or after fallback delay).
+ */
+bool usb4switch_wait_vbus_safe(struct usb4switch *sw, int timeout_ms)
+{
+	int elapsed = 0;
+	int mv = -1;
+
+	if (!sw)
+		return false;
+
+	while (elapsed < timeout_ms) {
+		mv = usb4switch_get_voltage_mv(sw);
+		if (mv < 0) {
+			/* Voltage readback not supported; use fixed delay */
+			igt_debug("USB4Switch: voltage readback failed, "
+				  "using 1s fallback delay\n");
+			sleep(1);
+			return true;
+		}
+		if (mv < USB4_SWITCH_VBUS_SAFE_MV) {
+			igt_debug("USB4Switch: VBUS safe at %d mV\n", mv);
+			return true;
+		}
+		usleep(USB4_SWITCH_VBUS_SAFE_POLL_MS * 1000);
+		elapsed += USB4_SWITCH_VBUS_SAFE_POLL_MS;
+	}
+
+	igt_warn("USB4Switch: VBUS still at %d mV after %d ms\n",
+		 mv, timeout_ms);
+	return false;
+}
+
+/**
+ * usb4switch_port_disable_and_wait:
+ * @sw: switch handle
+ *
+ * Disables all ports and waits for VBUS to reach safe levels.
+ *
+ * Returns: true on success.
+ */
+bool usb4switch_port_disable_and_wait(struct usb4switch *sw)
+{
+	if (!usb4switch_port_disable(sw))
+		return false;
+
+	return usb4switch_wait_vbus_safe(sw, USB4_SWITCH_VBUS_SAFE_TIMEOUT_MS);
+}
+
+/**
+ * usb4switch_port_switch:
+ * @sw: switch handle
+ * @new_port: target port number (1..MAX_PORTS)
+ *
+ * Safely switches from the currently active port to @new_port.
+ * If another port is active, disables it first and waits for VBUS
+ * discharge before enabling the new port. If @new_port is already
+ * active, this is a no-op.
+ *
+ * Returns: true on success.
+ */
+bool usb4switch_port_switch(struct usb4switch *sw, int new_port)
+{
+	int active;
+
+	if (!sw || new_port < 1 || new_port > USB4_SWITCH_MAX_PORTS)
+		return false;
+
+	active = usb4switch_get_active_port(sw);
+
+	if (active == new_port) {
+		igt_debug("USB4Switch: Port %d already active\n", new_port);
+		return true;
+	}
+
+	if (active > 0) {
+		igt_debug("USB4Switch: Disabling port %d before switching "
+			  "to port %d\n", active, new_port);
+		if (!usb4switch_port_disable_and_wait(sw))
+			return false;
+	}
+
+	return usb4switch_port_enable(sw, new_port);
+}
+
+/**
+ * usb4switch_get_port_config:
+ * @sw: switch handle
+ * @port_index: port index (0-based)
+ *
+ * Returns: Pointer to port config, NULL if invalid.
+ */
+const struct usb4switch_port *usb4switch_get_port_config(struct usb4switch *sw,
+							 int port_index)
+{
+	if (!sw || port_index < 0 || port_index >= sw->port_count)
+		return NULL;
+
+	return &sw->ports[port_index];
+}
+
+/**
+ * usb4switch_get_port_count:
+ * @sw: switch handle
+ *
+ * Returns: Number of configured ports.
+ */
+int usb4switch_get_port_count(struct usb4switch *sw)
+{
+	return sw ? sw->port_count : 0;
+}
+
+/**
+ * usb4switch_get_hotplug_timeout:
+ * @sw: switch handle
+ *
+ * Returns: Hotplug timeout in seconds.
+ */
+int usb4switch_get_hotplug_timeout(struct usb4switch *sw)
+{
+	return sw ? sw->hotplug_timeout_s :
+		    USB4_SWITCH_DEFAULT_HOTPLUG_TIMEOUT_S;
+}
+
+/**
+ * usb4switch_get_iterations:
+ * @sw: switch handle
+ *
+ * Returns: Configured iterations.
+ */
+int usb4switch_get_iterations(struct usb4switch *sw)
+{
+	return sw ? sw->iterations : USB4_SWITCH_DEFAULT_ITERATIONS;
+}
diff --git a/lib/igt_usb4_switch.h b/lib/igt_usb4_switch.h
new file mode 100644
index 000000000..5f1a0d334
--- /dev/null
+++ b/lib/igt_usb4_switch.h
@@ -0,0 +1,157 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2026 Intel Corporation
+ */
+
+#ifndef IGT_USB4_SWITCH_H
+#define IGT_USB4_SWITCH_H
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+/**
+ * USB4_SWITCH_MODEL_3141:
+ *
+ * Model number for Switch 3141.
+ */
+#define USB4_SWITCH_MODEL_3141 3141
+
+/**
+ * USB4_SWITCH_MAX_PORTS:
+ *
+ * Maximum number of ports on the switch.
+ */
+#define USB4_SWITCH_MAX_PORTS 2
+
+/**
+ * USB4_SWITCH_MAX_DISPLAYS_PER_PORT:
+ *
+ * Maximum displays per port (for MST hubs).
+ */
+#define USB4_SWITCH_MAX_DISPLAYS_PER_PORT 4
+
+/**
+ * USB4_SWITCH_RESPONSE_MAX_LEN:
+ *
+ * Recommended buffer size for usb4switch_get_status() callers.
+ * Internal commands use smaller buffers since responses are short.
+ */
+#define USB4_SWITCH_RESPONSE_MAX_LEN 1024
+
+/**
+ * USB4_SWITCH_DEFAULT_TIMEOUT_MS:
+ *
+ * Default command timeout in milliseconds.
+ */
+#define USB4_SWITCH_DEFAULT_TIMEOUT_MS 2000
+
+/**
+ * USB4_SWITCH_DEFAULT_HOTPLUG_TIMEOUT_S:
+ *
+ * Default hotplug wait timeout in seconds.
+ */
+#define USB4_SWITCH_DEFAULT_HOTPLUG_TIMEOUT_S 10
+
+/**
+ * USB4_SWITCH_DEFAULT_ITERATIONS:
+ *
+ * Default dock/undock iterations.
+ */
+#define USB4_SWITCH_DEFAULT_ITERATIONS 3
+
+/**
+ * USB4_SWITCH_VBUS_SAFE_MV:
+ *
+ * VBUS voltage threshold in mV below which VBUS is considered safe
+ * (Vsafe0V per USB PD specification).
+ */
+#define USB4_SWITCH_VBUS_SAFE_MV 800
+
+/**
+ * USB4_SWITCH_VBUS_SAFE_TIMEOUT_MS:
+ *
+ * Maximum time in milliseconds to wait for VBUS to discharge to safe levels.
+ */
+#define USB4_SWITCH_VBUS_SAFE_TIMEOUT_MS 3000
+
+/**
+ * USB4_SWITCH_VBUS_SAFE_POLL_MS:
+ *
+ * Polling interval in milliseconds when waiting for VBUS discharge.
+ */
+#define USB4_SWITCH_VBUS_SAFE_POLL_MS 100
+
+/**
+ * USB4_SWITCH_DEFAULT_MIN_INTERVAL_MS:
+ *
+ * Default minimum interval in milliseconds between successive port
+ * operations.  Matches Cricket UI's 1-second safety guard.
+ */
+#define USB4_SWITCH_DEFAULT_MIN_INTERVAL_MS 1000
+
+/**
+ * struct usb4switch_display:
+ * @connector_path: MST PATH property (e.g., "mst:5-2-8"), preferred for MST
+ * @connector_name: Fallback connector name (e.g., "DP-6") for non-MST
+ * @edid_serial: Expected EDID serial string for verification
+ *
+ * Configuration for an expected display on a switch port.
+ * For MST displays, use connector_path which is stable across hotplug.
+ * For non-MST displays, connector_name can be used.
+ */
+struct usb4switch_display {
+	char *connector_path;
+	char *connector_name;
+	char *edid_serial;
+};
+
+/**
+ * struct usb4switch_port:
+ * @port_num: Port number (1 or 2)
+ * @name: Human-readable port name
+ * @displays: Array of expected displays on this port
+ * @display_count: Number of displays configured
+ *
+ * Configuration for a switch port.
+ */
+struct usb4switch_port {
+	int port_num;
+	char *name;
+	struct usb4switch_display displays[USB4_SWITCH_MAX_DISPLAYS_PER_PORT];
+	int display_count;
+};
+
+struct usb4switch;
+
+/* Lifecycle */
+struct usb4switch *usb4switch_init(int drm_fd);
+void usb4switch_deinit(struct usb4switch *sw);
+
+/* Port control */
+bool usb4switch_port_enable(struct usb4switch *sw, int port);
+bool usb4switch_port_enable_delayed(struct usb4switch *sw, int port,
+				    int delay_seconds);
+bool usb4switch_port_disable(struct usb4switch *sw);
+bool usb4switch_port_disable_delayed(struct usb4switch *sw,
+				     int delay_seconds);
+
+/* VBUS safety */
+bool usb4switch_wait_vbus_safe(struct usb4switch *sw, int timeout_ms);
+bool usb4switch_port_disable_and_wait(struct usb4switch *sw);
+bool usb4switch_port_switch(struct usb4switch *sw, int new_port);
+
+/* Status queries */
+int usb4switch_get_active_port(struct usb4switch *sw);
+bool usb4switch_get_status(struct usb4switch *sw, char *buf, size_t size);
+int usb4switch_get_voltage_mv(struct usb4switch *sw);
+int usb4switch_get_current_ma(struct usb4switch *sw);
+
+/* Configuration getters */
+const struct usb4switch_port *usb4switch_get_port_config(struct usb4switch *sw,
+							 int port_index);
+int usb4switch_get_port_count(struct usb4switch *sw);
+int usb4switch_get_hotplug_timeout(struct usb4switch *sw);
+int usb4switch_get_iterations(struct usb4switch *sw);
+
+#endif /* IGT_USB4_SWITCH_H */
diff --git a/lib/meson.build b/lib/meson.build
index 67b57533c..d03bef209 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -124,6 +124,7 @@ lib_sources = [
 	'igt_dsc.c',
 	'igt_hook.c',
 	'igt_serial.c',
+	'igt_usb4_switch.c',
 	'xe/xe_gt.c',
 	'xe/xe_ioctl.c',
 	'xe/xe_legacy.c',
-- 
2.25.1


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

* [PATCH i-g-t 5/6] tests/kms_feature_discovery: add basic usb4 switch discovery
  2026-02-25 21:28 [PATCH i-g-t 0/6] add test to validate dock/undock and switch Kunal Joshi
                   ` (3 preceding siblings ...)
  2026-02-25 21:28 ` [PATCH i-g-t 4/6] lib/igt_usb4_switch: add helper library for USB4 Switch 3141 Kunal Joshi
@ 2026-02-25 21:28 ` Kunal Joshi
  2026-03-09 10:05   ` [i-g-t,5/6] " Murthy, Arun R
  2026-02-25 21:28 ` [PATCH i-g-t 6/6] tests/intel/kms_usb4_switch: Add USB4 switch test suite Kunal Joshi
                   ` (4 subsequent siblings)
  9 siblings, 1 reply; 25+ messages in thread
From: Kunal Joshi @ 2026-02-25 21:28 UTC (permalink / raw)
  To: igt-dev; +Cc: Kunal Joshi

Add a 'usb4-switch' subtest that verifies the Microsoft USB4 Switch
3141 is reachable. The test initializes the switch library and queries
the active port to confirm communication works.

This enables CI to detect when USB4 switch hardware is available
before running the full kms_usb4_switch test suite.

Signed-off-by: Kunal Joshi <kunal1.joshi@intel.com>
---
 tests/kms_feature_discovery.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/tests/kms_feature_discovery.c b/tests/kms_feature_discovery.c
index f0216a4ce..b05055186 100644
--- a/tests/kms_feature_discovery.c
+++ b/tests/kms_feature_discovery.c
@@ -40,6 +40,7 @@
 #include "igt_psr.h"
 #include "igt_sysfs.h"
 #include "igt_types.h"
+#include "igt_usb4_switch.h"
 
 /**
  * SUBTEST: display
@@ -63,6 +64,9 @@
  * SUBTEST: dp-mst
  * Description: Make sure that we have DP-MST configuration.
  *
+ * SUBTEST: usb4-switch
+ * Description: Verify that USB4 Switch 3141 is available and responding.
+ *
  * arg[1].values: 1, 2, 3, 4
  */
 
@@ -147,6 +151,25 @@ int igt_main() {
 		}
 #endif
 
+		igt_describe("Verify that USB4 Switch 3141 is available and responding.");
+		igt_subtest("usb4-switch") {
+			struct usb4switch *sw;
+			int port;
+
+			sw = usb4switch_init(fd);
+			igt_require_f(sw,
+				      "USB4 Switch 3141 not available\n");
+
+			/* Verify communication works by querying active port */
+			port = usb4switch_get_active_port(sw);
+			igt_assert_f(port >= 0,
+				     "Cannot communicate with USB4 switch\n");
+
+			igt_info("USB4 Switch 3141 available (active port: %d)\n",
+				 port);
+			usb4switch_deinit(sw);
+		}
+
 		igt_describe("Make sure that we have eDP panel with PSR1 support.");
 		igt_subtest("psr1") {
 			igt_require(psr_sink_support(fd, debugfs_fd, PSR_MODE_1, NULL));
-- 
2.25.1


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

* [PATCH i-g-t 6/6] tests/intel/kms_usb4_switch: Add USB4 switch test suite
  2026-02-25 21:28 [PATCH i-g-t 0/6] add test to validate dock/undock and switch Kunal Joshi
                   ` (4 preceding siblings ...)
  2026-02-25 21:28 ` [PATCH i-g-t 5/6] tests/kms_feature_discovery: add basic usb4 switch discovery Kunal Joshi
@ 2026-02-25 21:28 ` Kunal Joshi
  2026-03-09 10:03   ` [i-g-t,6/6] " Murthy, Arun R
  2026-02-26  2:20 ` ✗ Xe.CI.BAT: failure for add test to validate dock/undock and switch (rev3) Patchwork
                   ` (3 subsequent siblings)
  9 siblings, 1 reply; 25+ messages in thread
From: Kunal Joshi @ 2026-02-25 21:28 UTC (permalink / raw)
  To: igt-dev; +Cc: Kunal Joshi

Add a comprehensive test suite for USB4/Thunderbolt dock/undock and
port switching scenarios using the Microsoft USB4 Switch 3141:

 - dock-undock: Basic dock/undock cycles with display verification
 - dock-undock-sr: Dock/undock with suspend/resume stability
 - dock-undock-during-suspend: Dock while system is suspended
 - switch: Port-to-port switching with display verification
 - switch-sr: Port switching with suspend/resume stability
 - switch-during-suspend: Port switch during suspend via HW delay

Signed-off-by: Kunal Joshi <kunal1.joshi@intel.com>
---
 tests/intel/kms_usb4_switch.c | 1254 +++++++++++++++++++++++++++++++++
 tests/meson.build             |    2 +
 2 files changed, 1256 insertions(+)
 create mode 100644 tests/intel/kms_usb4_switch.c

diff --git a/tests/intel/kms_usb4_switch.c b/tests/intel/kms_usb4_switch.c
new file mode 100644
index 000000000..403ad7255
--- /dev/null
+++ b/tests/intel/kms_usb4_switch.c
@@ -0,0 +1,1254 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2026 Intel Corporation
+ */
+
+/**
+ * TEST: kms usb4 switch
+ * Category: Display
+ * Description:        USB4/Thunderbolt dock/undock and port switching tests
+ * Driver requirement: i915, xe
+ * Mega feature:       General Display Features
+ *
+ * SUBTEST: dock-undock
+ * Description:        Test dock/undock cycles with display verification.
+ *                     Verifies hotplug events, EDID serial matching, modeset with
+ *                     max non-joiner mode, and pipe CRC stability.
+ *
+ * SUBTEST: dock-undock-sr
+ * Description:        Test dock/undock with suspend/resume stability.
+ *                     Docks, verifies displays with modeset and CRC, suspends/resumes,
+ *                     then verifies displays still produce valid CRC after resume.
+ *
+ * SUBTEST: dock-during-suspend
+ * Description:        Test docking while system is suspended.
+ *                     Simulates user plugging into a suspended laptop by triggering
+ *                     dock during suspend using hardware delay command. Verifies
+ *                     modeset and pipe CRC after resume.
+ *
+ * SUBTEST: undock-during-suspend
+ * Description:        Test undocking while system is suspended.
+ *                     Docks first, verifies displays, then schedules a delayed
+ *                     undock during suspend. After resume, verifies all port
+ *                     displays have been removed.
+ *
+ * SUBTEST: switch
+ * Description:        Test switching between USB4 switch ports.
+ *                     Verifies hotplug events, display verification with modeset
+ *                     and pipe CRC when switching from one port to another.
+ *
+ * SUBTEST: switch-sr
+ * Description:        Test port switching with suspend/resume stability.
+ *                     Switches ports, verifies displays with modeset and CRC,
+ *                     suspends/resumes, then verifies CRC stability after resume.
+ *
+ * SUBTEST: switch-during-suspend
+ * Description:        Test port switching during suspend using hardware delay.
+ *                     Schedules a delayed switch, suspends system, switch occurs during
+ *                     suspend, then verifies modeset and pipe CRC on new port after resume.
+ */
+
+#include <ctype.h>
+#include <sys/poll.h>
+
+#include "igt.h"
+#include "igt_edid.h"
+#include "igt_kms.h"
+#include "igt_pipe_crc.h"
+#include "igt_usb4_switch.h"
+#include "igt_connector_helper.h"
+#include "kms_joiner_helper.h"
+
+/*
+ * Extended timeout for switch operations.
+ * Port switching requires longer stabilization time than simple dock/undock
+ * due to hardware state transitions and MST topology rebuilds.
+ */
+#define USB4_SWITCH_TIMEOUT_S 20
+
+/* Number of CRC samples for stability check (solid color FB should be stable) */
+#define CRC_STABILITY_SAMPLES 3
+
+/* Maximum displays expected on a single USB4 switch port (MST hub) */
+#define MAX_DISPLAYS_PER_PORT 4
+
+/* Number of reprobe cycles for MST topology stabilization after resume */
+#define MST_STABILIZE_REPROBE_COUNT 10
+
+/* Inter-reprobe delay in microseconds (500 ms) */
+#define MST_STABILIZE_DELAY_US 500000
+
+/*
+ * Iteration helpers for dynamic subtest generation.
+ * Skip ports (or pairs) that have no displays configured.
+ *
+ * for_each_usb4_port_pair iterates adjacent cyclic pairs (0->1, 1->2, ...,
+ * N-1->0).  For the 2-port Switch 3141 this covers the only possible pair.
+ * If the hardware grows beyond 2 ports, consider generating all distinct
+ * pairs instead.
+ */
+#define for_each_usb4_port(sw, count, p, pcfg)				\
+	for ((p) = 0,							\
+	     (pcfg) = usb4switch_get_port_config((sw), 0);		\
+	     (p) < (count) && (pcfg) && (pcfg)->display_count > 0;	\
+	     (pcfg) = usb4switch_get_port_config((sw), ++(p)))
+
+#define for_each_usb4_port_pair(sw, count, p, pa, pb)			\
+	for ((p) = 0,							\
+	     (pa) = usb4switch_get_port_config((sw), 0),		\
+	     (pb) = usb4switch_get_port_config((sw), 1 % (count));	\
+	     (p) < (count) && (pa) && (pb) &&				\
+	     (pa)->display_count > 0 && (pb)->display_count > 0;	\
+	     ++(p),							\
+	     (pa) = usb4switch_get_port_config((sw), (p)),		\
+	     (pb) = usb4switch_get_port_config((sw), ((p) + 1) % (count)))
+
+typedef struct {
+	int drm_fd;
+	igt_display_t display;
+	struct usb4switch *sw;
+	struct udev_monitor *hotplug_mon;
+	int max_dotclock;
+	uint32_t master_pipes;
+	uint32_t valid_pipes;
+} data_t;
+
+/*
+ * Per-display modeset state, used by the composable display building blocks.
+ * Holds everything needed to arm, commit, collect CRC, and disarm one display.
+ */
+struct display_ctx {
+	uint32_t conn_id;
+	igt_output_t *output;
+	igt_plane_t *primary;
+	struct igt_fb fb;
+	drmModeModeInfo mode;
+	bool valid;
+};
+
+/*
+ * find_output_by_id - Find an igt_output_t by DRM connector ID.
+ */
+static igt_output_t *find_output_by_id(igt_display_t *display,
+				       uint32_t connector_id)
+{
+	int i;
+
+	for (i = 0; i < display->n_outputs; i++) {
+		if (display->outputs[i].id == connector_id)
+			return &display->outputs[i];
+	}
+
+	return NULL;
+}
+
+/*
+ * select_max_non_joiner_mode - Pick the largest mode that fits a single pipe.
+ *
+ * "Non-joiner" means hdisplay <= max_pipe_hdisplay AND clock <= max_dotclock.
+ * Among qualifying modes, pick by:
+ *   1. Highest pixel area (hdisplay * vdisplay)
+ *   2. Highest vrefresh (tie-break)
+ *   3. Highest clock (tie-break)
+ *
+ * If max_dotclock is 0 (debugfs unavailable), only hdisplay is checked.
+ *
+ * TODO: Remove this filter when joiner CRC collection is supported;
+ *       the pipe allocator already handles joiner pipe counts.
+ *
+ * Returns: Pointer to a function-static copy of the best mode, or NULL
+ *          if none found. Not reentrant — single-threaded callers only.
+ */
+static drmModeModeInfo *select_max_non_joiner_mode(int drm_fd,
+						   igt_output_t *output,
+						   int max_dotclock)
+{
+	static drmModeModeInfo best;
+	drmModeConnector *conn = output->config.connector;
+	uint64_t best_area = 0;
+	uint32_t best_vrefresh = 0;
+	int best_clock = 0;
+	bool found = false;
+	int i;
+
+	if (!conn || conn->count_modes == 0)
+		return NULL;
+
+	for (i = 0; i < conn->count_modes; i++) {
+		drmModeModeInfo *m = &conn->modes[i];
+		uint64_t area;
+
+		if (igt_bigjoiner_possible(drm_fd, m, max_dotclock))
+			continue;
+
+		area = (uint64_t)m->hdisplay * m->vdisplay;
+
+		if (area > best_area ||
+		    (area == best_area && m->vrefresh > best_vrefresh) ||
+		    (area == best_area && m->vrefresh == best_vrefresh &&
+		     m->clock > best_clock)) {
+			best = *m;
+			best_area = area;
+			best_vrefresh = m->vrefresh;
+			best_clock = m->clock;
+			found = true;
+		}
+	}
+
+	return found ? &best : NULL;
+}
+
+/*
+ * find_connector - Find a connector ID for the given display config.
+ * Prefers PATH property (stable for MST) with name as fallback.
+ */
+static bool find_connector(int drm_fd,
+			   const struct usb4switch_display *disp,
+			   uint32_t *connector_id)
+{
+	if (!disp || !connector_id)
+		return false;
+
+	if (disp->connector_path &&
+	    igt_connector_find_by_path(drm_fd, disp->connector_path,
+				       connector_id))
+		return true;
+
+	if (disp->connector_name &&
+	    igt_connector_find_by_name(drm_fd, disp->connector_name,
+				       connector_id))
+		return true;
+
+	return false;
+}
+
+/*
+ * reprobe_connectors - Force reprobe of connectors and wait for MST topology.
+ * Critical after suspend/resume — without this MST connectors may take 90+ s.
+ *
+ * Timing rationale: MST hubs need ~3 s after reprobe to fully enumerate
+ * their downstream topology, based on empirical testing with USB4/TBT docks.
+ */
+static void reprobe_connectors(int drm_fd)
+{
+	igt_connector_reprobe_all(drm_fd);
+	igt_debug("reprobe: Connector reprobe completed\n");
+}
+
+static bool verify_port_displays(data_t *data,
+				 const struct usb4switch_port *port_cfg)
+{
+	int i;
+
+	for (i = 0; i < port_cfg->display_count; i++) {
+		const struct usb4switch_display *disp = &port_cfg->displays[i];
+		uint32_t conn_id;
+		char name[32];
+		char serial[64];
+
+		if (!find_connector(data->drm_fd, disp, &conn_id)) {
+			igt_warn("Display %d not found for port %d\n",
+				 i + 1, port_cfg->port_num);
+			return false;
+		}
+
+		if (disp->edid_serial) {
+			if (!igt_connector_get_info(data->drm_fd, conn_id,
+						    name, sizeof(name),
+						    serial, sizeof(serial),
+						    NULL, 0)) {
+				igt_warn("Failed to get EDID serial for display %d\n",
+					 i + 1);
+				return false;
+			}
+
+			if (strcmp(serial, disp->edid_serial) != 0) {
+				igt_warn("EDID serial mismatch for display %d: expected '%s', got '%s'\n",
+					 i + 1, disp->edid_serial, serial);
+				return false;
+			}
+
+			igt_debug("Display %d EDID serial verified: %s\n",
+				  i + 1, serial);
+		} else {
+			igt_debug("Display %d: No EDID serial configured, "
+				  "skipping verification\n", i + 1);
+		}
+	}
+
+	igt_info("Port %d: All %d displays verified\n",
+		 port_cfg->port_num, port_cfg->display_count);
+	return true;
+}
+
+/*
+ * init_display_ctx - Resolve a usb4switch_display to an output and select mode.
+ *
+ * Finds the connector, resolves to igt_output_t, and selects the max
+ * non-joiner mode. Must be called before arm_display().
+ */
+static void init_display_ctx(data_t *data, struct display_ctx *ctx,
+			     const struct usb4switch_display *disp)
+{
+	drmModeModeInfo *mode;
+
+	memset(ctx, 0, sizeof(*ctx));
+
+	igt_assert_f(find_connector(data->drm_fd, disp, &ctx->conn_id),
+		     "Display not found for pipeline test\n");
+
+	ctx->output = find_output_by_id(&data->display, ctx->conn_id);
+	igt_assert_f(ctx->output,
+		     "No output for connector %u\n", ctx->conn_id);
+
+	mode = select_max_non_joiner_mode(data->drm_fd, ctx->output,
+					  data->max_dotclock);
+	igt_skip_on_f(!mode,
+		      "No non-joiner mode for connector %u\n", ctx->conn_id);
+
+	ctx->mode = *mode;
+	ctx->valid = true;
+}
+
+/*
+ * arm_display - Create FB, set primary plane, configure mode override.
+ *
+ * Pipe assignment must be done before this (by setup_port_displays).
+ * After arming, caller must commit with igt_display_commit2().
+ */
+static void arm_display(data_t *data, struct display_ctx *ctx)
+{
+	igt_assert(ctx->valid);
+
+	igt_output_override_mode(ctx->output, &ctx->mode);
+
+	ctx->primary = igt_output_get_plane_type(ctx->output,
+						 DRM_PLANE_TYPE_PRIMARY);
+	igt_assert(ctx->primary);
+
+	igt_create_color_fb(data->drm_fd,
+			    ctx->mode.hdisplay, ctx->mode.vdisplay,
+			    DRM_FORMAT_XRGB8888, DRM_FORMAT_MOD_LINEAR,
+			    0.0, 1.0, 0.0, /* green */
+			    &ctx->fb);
+	igt_plane_set_fb(ctx->primary, &ctx->fb);
+
+	igt_info("  Display %s: armed %dx%d@%d (clock %d)\n",
+		 igt_output_name(ctx->output),
+		 ctx->mode.hdisplay, ctx->mode.vdisplay,
+		 ctx->mode.vrefresh, ctx->mode.clock);
+}
+
+/*
+ * collect_display_crc - Collect CRC samples and verify stability.
+ *
+ * Collects CRC_STABILITY_SAMPLES, asserts they are identical (expected
+ * for a solid color FB), and returns the representative CRC in *out_crc.
+ * Display must be armed and committed before calling.
+ */
+static void collect_display_crc(data_t *data, struct display_ctx *ctx,
+				igt_crc_t *out_crc)
+{
+	igt_crtc_t *crtc = igt_output_get_driving_crtc(ctx->output);
+	igt_pipe_crc_t *pipe_crc;
+	igt_crc_t samples[CRC_STABILITY_SAMPLES];
+	int i;
+
+	igt_assert(crtc);
+
+	pipe_crc = igt_crtc_crc_new(crtc, IGT_PIPE_CRC_SOURCE_AUTO);
+	igt_assert(pipe_crc);
+
+	igt_pipe_crc_start(pipe_crc);
+	for (i = 0; i < CRC_STABILITY_SAMPLES; i++)
+		igt_pipe_crc_get_single(pipe_crc, &samples[i]);
+	igt_pipe_crc_stop(pipe_crc);
+
+	/* Solid color FB: all samples must be identical */
+	for (i = 1; i < CRC_STABILITY_SAMPLES; i++)
+		igt_assert_crc_equal(&samples[0], &samples[i]);
+
+	*out_crc = samples[0];
+
+	igt_info("  Display %s: CRC stable (%d samples, pipe %s)\n",
+		 igt_output_name(ctx->output), CRC_STABILITY_SAMPLES,
+		 igt_crtc_name(crtc));
+
+	igt_pipe_crc_free(pipe_crc);
+}
+
+/*
+ * disarm_display - Clear plane, output, and remove FB.
+ *
+ * After disarming all outputs, caller must commit to apply changes.
+ */
+static void disarm_display(data_t *data, struct display_ctx *ctx)
+{
+	if (!ctx->valid)
+		return;
+
+	if (ctx->primary)
+		igt_plane_set_fb(ctx->primary, NULL);
+
+	igt_output_set_crtc(ctx->output, NULL);
+	igt_output_override_mode(ctx->output, NULL);
+
+	if (ctx->fb.fb_id)
+		igt_remove_fb(data->drm_fd, &ctx->fb);
+
+	ctx->primary = NULL;
+	ctx->fb.fb_id = 0;
+	ctx->valid = false;
+}
+
+/*
+ * setup_port_displays - Init contexts, allocate pipes, arm all displays.
+ *
+ * Resolves all displays on a port, selects modes, allocates pipes using
+ * the joiner-aware pipe allocator, and arms all displays.
+ * Caller must commit with igt_display_commit2() after this returns.
+ *
+ * Returns: Number of displays set up.
+ */
+static int setup_port_displays(data_t *data, struct display_ctx *ctxs,
+			       const struct usb4switch_port *port_cfg)
+{
+	igt_output_t *outputs[MAX_DISPLAYS_PER_PORT];
+	uint32_t used_pipes = 0;
+	int i;
+
+	igt_assert(port_cfg->display_count <= MAX_DISPLAYS_PER_PORT);
+
+	for (i = 0; i < port_cfg->display_count; i++) {
+		init_display_ctx(data, &ctxs[i], &port_cfg->displays[i]);
+		outputs[i] = ctxs[i].output;
+	}
+
+	/* Joiner-aware pipe allocation */
+	igt_assert_f(igt_assign_pipes_for_outputs(data->drm_fd, outputs,
+						  port_cfg->display_count,
+						  data->display.n_crtcs,
+						  &used_pipes,
+						  data->master_pipes,
+						  data->valid_pipes),
+		     "Failed to allocate pipes for port %d displays\n",
+		     port_cfg->port_num);
+
+	for (i = 0; i < port_cfg->display_count; i++)
+		arm_display(data, &ctxs[i]);
+
+	return port_cfg->display_count;
+}
+
+static void teardown_port_displays(data_t *data, struct display_ctx *ctxs,
+				   int count)
+{
+	int i;
+
+	for (i = 0; i < count; i++)
+		disarm_display(data, &ctxs[i]);
+}
+
+/*
+ * verify_port_display_pipeline - Modeset all port displays and verify CRC.
+ *
+ * Used in non-suspend paths to confirm the display pipeline is functioning.
+ * Arms all displays, commits, collects stable CRCs, then tears down.
+ */
+static void verify_port_display_pipeline(data_t *data,
+					 const struct usb4switch_port *port_cfg)
+{
+	struct display_ctx ctxs[MAX_DISPLAYS_PER_PORT];
+	igt_crc_t crc;
+	int count, i;
+
+	count = setup_port_displays(data, ctxs, port_cfg);
+	igt_display_commit2(&data->display, COMMIT_ATOMIC);
+
+	for (i = 0; i < count; i++)
+		collect_display_crc(data, &ctxs[i], &crc);
+
+	teardown_port_displays(data, ctxs, count);
+
+	igt_info("Port %d: Pipeline verification passed for %d displays\n",
+		 port_cfg->port_num, count);
+}
+
+/*
+ * get_port_reference_crcs - Modeset and collect reference CRCs before suspend.
+ *
+ * Arms all displays, commits, collects a baseline CRC per display into
+ * ref_crcs[], then tears down. The reference CRCs are compared with
+ * post-resume CRCs to detect display corruption.
+ */
+static void get_port_reference_crcs(data_t *data,
+				    const struct usb4switch_port *port_cfg,
+				    igt_crc_t *ref_crcs)
+{
+	struct display_ctx ctxs[MAX_DISPLAYS_PER_PORT];
+	int count, i;
+
+	count = setup_port_displays(data, ctxs, port_cfg);
+	igt_display_commit2(&data->display, COMMIT_ATOMIC);
+
+	for (i = 0; i < count; i++)
+		collect_display_crc(data, &ctxs[i], &ref_crcs[i]);
+
+	teardown_port_displays(data, ctxs, count);
+
+	igt_info("Port %d: Collected %d reference CRCs for suspend comparison\n",
+		 port_cfg->port_num, count);
+}
+
+/*
+ * verify_port_crcs_after_resume - Compare post-resume CRCs with pre-suspend.
+ *
+ * Arms all displays with the same mode/FB as before suspend, commits,
+ * collects new CRCs, and asserts each matches the corresponding reference.
+ * A mismatch indicates the display is showing garbage after resume.
+ */
+static void verify_port_crcs_after_resume(data_t *data,
+					  const struct usb4switch_port *port_cfg,
+					  const igt_crc_t *ref_crcs)
+{
+	struct display_ctx ctxs[MAX_DISPLAYS_PER_PORT];
+	igt_crc_t resume_crc;
+	int count, i;
+
+	count = setup_port_displays(data, ctxs, port_cfg);
+	igt_display_commit2(&data->display, COMMIT_ATOMIC);
+
+	for (i = 0; i < count; i++) {
+		collect_display_crc(data, &ctxs[i], &resume_crc);
+		igt_assert_crc_equal(&ref_crcs[i], &resume_crc);
+		igt_info("  Display %s: CRC matches pre-suspend reference\n",
+			 igt_output_name(ctxs[i].output));
+	}
+
+	teardown_port_displays(data, ctxs, count);
+
+	igt_info("Port %d: All %d CRCs match pre-suspend reference\n",
+		 port_cfg->port_num, count);
+}
+
+/*
+ * refresh_display - Reinitialize display structure to pick up new connectors.
+ * After hotplug events (dock/undock), new MST connectors may be created.
+ *
+ * WARNING: Any previously cached igt_output_t pointers become invalid
+ * after this call.  Callers must re-resolve outputs via find_output_by_id()
+ * or init_display_ctx() before using them.
+ */
+static void refresh_display(data_t *data)
+{
+	igt_display_fini(&data->display);
+	igt_display_require(&data->display, data->drm_fd);
+}
+
+/*
+ * wait_for_displays - Wait for all displays on a port to connect.
+ */
+static bool wait_for_displays(data_t *data,
+			      const struct usb4switch_port *port,
+			      int timeout_s)
+{
+	int elapsed = 0;
+	int found = 0;
+	int i;
+
+	if (!port)
+		return false;
+
+	while (elapsed < timeout_s) {
+		reprobe_connectors(data->drm_fd);
+
+		found = 0;
+		for (i = 0; i < port->display_count; i++) {
+			uint32_t id;
+
+			if (find_connector(data->drm_fd,
+					   &port->displays[i], &id))
+				found++;
+		}
+
+		if (found == port->display_count) {
+			igt_debug("All %d displays found for port %d\n",
+				  port->display_count, port->port_num);
+			/*
+			 * Reprobe cycles above may have created new MST
+			 * connectors.  Rebuild igt_display_t so callers
+			 * see up-to-date connector IDs and outputs.
+			 */
+			refresh_display(data);
+			return true;
+		}
+
+		sleep(1);
+		elapsed++;
+	}
+
+	igt_warn("Timeout waiting for displays (found %d/%d)\n",
+		 found, port->display_count);
+	return false;
+}
+
+static void wait_for_hotplug(data_t *data, int timeout_s)
+{
+	bool detected;
+
+	detected = igt_hotplug_detected(data->hotplug_mon, timeout_s);
+
+	if (detected)
+		igt_debug("Hotplug detected\n");
+	else
+		igt_warn("Hotplug uevent not detected within %ds\n",
+			 timeout_s);
+
+	reprobe_connectors(data->drm_fd);
+	refresh_display(data);
+}
+
+/*
+ * mst_stabilize - Extended MST topology stabilization after resume.
+ * MST hubs need additional time and reprobe cycles to rebuild their
+ * topology after suspend/resume. Ten iterations with 500 ms spacing
+ * gives the hub firmware enough time to re-enumerate all downstream
+ * ports, based on empirical testing with USB4/TBT docks.
+ */
+static void mst_stabilize(data_t *data)
+{
+	int i;
+
+	for (i = 0; i < MST_STABILIZE_REPROBE_COUNT; i++) {
+		reprobe_connectors(data->drm_fd);
+		usleep(MST_STABILIZE_DELAY_US);
+	}
+}
+
+/*
+ * port_dynamic_name - Format dynamic subtest name for a port.
+ * Uses port name if configured, otherwise falls back to "port-N".
+ *
+ * IGT requires subtest names to contain only [a-zA-Z0-9_-] and to be
+ * lower-case.  Any upper-case letter is lowered, any other invalid
+ * character (e.g. spaces) is replaced with '-'.
+ */
+static const char *port_dynamic_name(const struct usb4switch_port *port,
+				     char *buf, size_t len)
+{
+	size_t i;
+
+	if (port->name) {
+		snprintf(buf, len, "%s", port->name);
+		for (i = 0; buf[i]; i++) {
+			buf[i] = tolower((unsigned char)buf[i]);
+			if (!isalnum((unsigned char)buf[i]) &&
+			    buf[i] != '-' && buf[i] != '_')
+				buf[i] = '-';
+		}
+	} else {
+		snprintf(buf, len, "port-%d", port->port_num);
+	}
+	return buf;
+}
+
+/*
+ * pair_dynamic_name - Format dynamic subtest name for a port pair.
+ * Combines both port names with "-to-" separator.
+ */
+static const char *pair_dynamic_name(const struct usb4switch_port *a,
+				     const struct usb4switch_port *b,
+				     char *buf, size_t len)
+{
+	char na[32], nb[32];
+
+	port_dynamic_name(a, na, sizeof(na));
+	port_dynamic_name(b, nb, sizeof(nb));
+	snprintf(buf, len, "%s-to-%s", na, nb);
+	return buf;
+}
+
+static void test_dock_undock(data_t *data,
+			     const struct usb4switch_port *port_cfg)
+{
+	int iterations = usb4switch_get_iterations(data->sw);
+	int timeout = usb4switch_get_hotplug_timeout(data->sw);
+	int i;
+
+	igt_info("Testing port %d (%s) with %d displays, %d iterations\n",
+		 port_cfg->port_num,
+		 port_cfg->name ? port_cfg->name : "unnamed",
+		 port_cfg->display_count, iterations);
+
+	for (i = 0; i < iterations; i++) {
+		igt_info("Iteration %d/%d\n", i + 1, iterations);
+
+		/* Dock */
+		igt_info("  Docking port %d...\n",
+			 port_cfg->port_num);
+		igt_flush_uevents(data->hotplug_mon);
+		igt_assert(usb4switch_port_switch(data->sw,
+						  port_cfg->port_num));
+		wait_for_hotplug(data, timeout);
+
+		igt_assert_f(wait_for_displays(data, port_cfg, timeout),
+			     "Displays did not enumerate on port %d\n",
+			     port_cfg->port_num);
+
+		igt_assert_f(verify_port_displays(data, port_cfg),
+			     "Display verification failed on port %d\n",
+			     port_cfg->port_num);
+
+		verify_port_display_pipeline(data, port_cfg);
+
+		/* Undock */
+		igt_info("  Undocking...\n");
+		igt_flush_uevents(data->hotplug_mon);
+		igt_assert(usb4switch_port_disable_and_wait(data->sw));
+		wait_for_hotplug(data, timeout);
+	}
+}
+
+static void test_dock_undock_sr(data_t *data,
+				const struct usb4switch_port *port_cfg)
+{
+	igt_crc_t ref_crcs[MAX_DISPLAYS_PER_PORT];
+	int iterations = usb4switch_get_iterations(data->sw);
+	int timeout = usb4switch_get_hotplug_timeout(data->sw);
+	int i;
+
+	igt_info("Testing port %d (%s) dock/undock with S/R, %d iterations\n",
+		 port_cfg->port_num,
+		 port_cfg->name ? port_cfg->name : "unnamed",
+		 iterations);
+
+	for (i = 0; i < iterations; i++) {
+		igt_info("Iteration %d/%d\n", i + 1, iterations);
+
+		/* Dock */
+		igt_info("  Docking port %d...\n",
+			 port_cfg->port_num);
+		igt_flush_uevents(data->hotplug_mon);
+		igt_assert(usb4switch_port_switch(data->sw,
+						  port_cfg->port_num));
+		wait_for_hotplug(data, timeout);
+
+		igt_assert_f(wait_for_displays(data, port_cfg,
+					       timeout),
+			     "Displays did not enumerate\n");
+
+		igt_info("  Verifying displays before suspend...\n");
+		igt_assert_f(verify_port_displays(data, port_cfg),
+			     "Display verification failed before suspend\n");
+
+		/* Collect reference CRCs before suspend */
+		get_port_reference_crcs(data, port_cfg, ref_crcs);
+
+		/* Suspend/Resume while docked */
+		igt_info("  Suspending while docked...\n");
+		igt_system_suspend_autoresume(SUSPEND_STATE_MEM,
+					      SUSPEND_TEST_NONE);
+		igt_info("  Resumed\n");
+
+		mst_stabilize(data);
+
+		igt_assert_f(wait_for_displays(data, port_cfg,
+					       timeout),
+			     "Displays did not enumerate after resume\n");
+		igt_info("  Verifying displays after resume...\n");
+		igt_assert_f(verify_port_displays(data, port_cfg),
+			     "Display verification failed after resume\n");
+
+		/* Compare post-resume CRCs with pre-suspend reference */
+		verify_port_crcs_after_resume(data, port_cfg, ref_crcs);
+
+		/* Undock */
+		igt_info("  Undocking...\n");
+		igt_flush_uevents(data->hotplug_mon);
+		igt_assert(usb4switch_port_disable_and_wait(data->sw));
+		wait_for_hotplug(data, timeout);
+	}
+}
+
+static void test_dock_during_suspend(data_t *data,
+				     const struct usb4switch_port *port_cfg)
+{
+	int iterations = usb4switch_get_iterations(data->sw);
+	int timeout = usb4switch_get_hotplug_timeout(data->sw);
+	int i;
+
+	igt_info("Testing port %d (%s) dock-during-suspend, %d iterations\n",
+		 port_cfg->port_num,
+		 port_cfg->name ? port_cfg->name : "unnamed",
+		 iterations);
+
+	for (i = 0; i < iterations; i++) {
+		igt_info("Iteration %d/%d\n", i + 1, iterations);
+
+		/*
+		 * Schedule dock during suspend using hardware delay.
+		 * Port change executes at T+7s while system is
+		 * suspended (15s suspend cycle).
+		 */
+		igt_info("  Scheduling dock during suspend (T+7s)...\n");
+		igt_assert(usb4switch_port_enable_delayed(data->sw,
+							  port_cfg->port_num,
+							  7));
+
+		igt_info("  Suspending (15s, dock at T+7s)...\n");
+		igt_system_suspend_autoresume(SUSPEND_STATE_MEM,
+					      SUSPEND_TEST_NONE);
+		igt_info("  Resumed\n");
+
+		igt_info("  Reprobing connectors for MST discovery...\n");
+		mst_stabilize(data);
+
+		igt_assert_f(wait_for_displays(data, port_cfg,
+					       timeout),
+			     "Displays did not enumerate after dock-during-suspend\n");
+
+		igt_info("  Verifying displays after dock-during-suspend...\n");
+		igt_assert_f(verify_port_displays(data, port_cfg),
+			     "Display verification failed after dock-during-suspend\n");
+
+		verify_port_display_pipeline(data, port_cfg);
+
+		/* Undock to restore disconnected state for next iteration */
+		igt_info("  Undocking...\n");
+		igt_flush_uevents(data->hotplug_mon);
+		igt_assert(usb4switch_port_disable_and_wait(data->sw));
+		wait_for_hotplug(data, timeout);
+	}
+}
+
+static void test_undock_during_suspend(data_t *data,
+				       const struct usb4switch_port *port_cfg)
+{
+	int iterations = usb4switch_get_iterations(data->sw);
+	int timeout = usb4switch_get_hotplug_timeout(data->sw);
+	int i;
+
+	igt_info("Testing port %d (%s) undock-during-suspend, %d iterations\n",
+		 port_cfg->port_num,
+		 port_cfg->name ? port_cfg->name : "unnamed",
+		 iterations);
+
+	for (i = 0; i < iterations; i++) {
+		int j, found;
+
+		igt_info("Iteration %d/%d\n", i + 1, iterations);
+
+		/* Dock first */
+		igt_info("  Docking port %d...\n", port_cfg->port_num);
+		igt_flush_uevents(data->hotplug_mon);
+		igt_assert(usb4switch_port_switch(data->sw,
+						  port_cfg->port_num));
+		wait_for_hotplug(data, timeout);
+
+		igt_assert_f(wait_for_displays(data, port_cfg, timeout),
+			     "Displays did not enumerate on port %d\n",
+			     port_cfg->port_num);
+		igt_assert_f(verify_port_displays(data, port_cfg),
+			     "Display verification failed on port %d\n",
+			     port_cfg->port_num);
+
+		verify_port_display_pipeline(data, port_cfg);
+
+		/*
+		 * Schedule undock during suspend using hardware delay.
+		 * Port disable executes at T+7s while system is
+		 * suspended (15s suspend cycle).
+		 */
+		igt_info("  Scheduling undock during suspend (T+7s)...\n");
+		igt_assert(usb4switch_port_disable_delayed(data->sw, 7));
+
+		igt_info("  Suspending (15s, undock at T+7s)...\n");
+		igt_system_suspend_autoresume(SUSPEND_STATE_MEM,
+					      SUSPEND_TEST_NONE);
+		igt_info("  Resumed\n");
+
+		mst_stabilize(data);
+
+		/* Verify displays are gone after undock-during-suspend */
+		reprobe_connectors(data->drm_fd);
+		found = 0;
+		for (j = 0; j < port_cfg->display_count; j++) {
+			uint32_t id;
+
+			if (find_connector(data->drm_fd,
+					   &port_cfg->displays[j], &id))
+				found++;
+		}
+		igt_assert_f(found == 0,
+			     "Port %d: %d/%d displays still present after undock-during-suspend\n",
+			     port_cfg->port_num, found,
+			     port_cfg->display_count);
+
+		igt_info("Port %d: All displays removed after undock-during-suspend\n",
+			 port_cfg->port_num);
+	}
+}
+
+static void test_switch(data_t *data,
+			const struct usb4switch_port *port_a,
+			const struct usb4switch_port *port_b)
+{
+	int iterations = usb4switch_get_iterations(data->sw);
+	int timeout = USB4_SWITCH_TIMEOUT_S;
+	int i;
+
+	igt_info("Testing switch port %d -> port %d, %d iterations\n",
+		 port_a->port_num, port_b->port_num, iterations);
+
+	for (i = 0; i < iterations; i++) {
+		igt_info("Iteration %d/%d\n", i + 1, iterations);
+
+		/* Enable port A */
+		igt_info("  Enabling port %d...\n",
+			 port_a->port_num);
+		igt_flush_uevents(data->hotplug_mon);
+		igt_assert(usb4switch_port_switch(data->sw,
+						  port_a->port_num));
+		wait_for_hotplug(data, timeout);
+
+		igt_assert_f(wait_for_displays(data, port_a,
+					       timeout),
+			     "Displays did not enumerate on port %d\n",
+			     port_a->port_num);
+		igt_assert_f(verify_port_displays(data, port_a),
+			     "Display verification failed on port %d\n",
+			     port_a->port_num);
+		verify_port_display_pipeline(data, port_a);
+
+		/* Switch to port B */
+		igt_info("  Switching to port %d...\n",
+			 port_b->port_num);
+		igt_flush_uevents(data->hotplug_mon);
+		igt_assert(usb4switch_port_switch(data->sw,
+						  port_b->port_num));
+		wait_for_hotplug(data, timeout);
+
+		igt_assert_f(wait_for_displays(data, port_b,
+					       timeout),
+			     "Displays did not enumerate after switch to port %d\n",
+			     port_b->port_num);
+		igt_assert_f(verify_port_displays(data, port_b),
+			     "Display verification failed after switch to port %d\n",
+			     port_b->port_num);
+
+		verify_port_display_pipeline(data, port_b);
+	}
+
+	igt_flush_uevents(data->hotplug_mon);
+	igt_assert(usb4switch_port_disable_and_wait(data->sw));
+	wait_for_hotplug(data, timeout);
+}
+
+static void test_switch_during_suspend(data_t *data,
+				       const struct usb4switch_port *port_cfg_a,
+				       const struct usb4switch_port *port_cfg_b)
+{
+	int iterations = usb4switch_get_iterations(data->sw);
+	int timeout = USB4_SWITCH_TIMEOUT_S;
+	int i;
+
+	igt_info("Testing switch during suspend port %d <-> port %d, %d iterations\n",
+		 port_cfg_a->port_num, port_cfg_b->port_num, iterations);
+
+	for (i = 0; i < iterations; i++) {
+		igt_info("Iteration %d/%d\n", i + 1, iterations);
+
+		/* Start on port A */
+		igt_info("  Enabling port %d...\n", port_cfg_a->port_num);
+		igt_flush_uevents(data->hotplug_mon);
+		igt_assert(usb4switch_port_switch(data->sw,
+						  port_cfg_a->port_num));
+		wait_for_hotplug(data, timeout);
+
+		igt_assert_f(wait_for_displays(data, port_cfg_a, timeout),
+			     "Displays did not enumerate on port %d\n",
+			     port_cfg_a->port_num);
+		igt_assert_f(verify_port_displays(data, port_cfg_a),
+			     "Display verification failed on port %d\n",
+			     port_cfg_a->port_num);
+
+		verify_port_display_pipeline(data, port_cfg_a);
+
+		/* Schedule switch to B during suspend */
+		igt_info("  Scheduling switch to port %d during suspend (T+7s)...\n",
+			 port_cfg_b->port_num);
+		igt_assert(usb4switch_port_disable_and_wait(data->sw));
+		igt_assert(usb4switch_port_enable_delayed(data->sw,
+							  port_cfg_b->port_num,
+							  7));
+
+		igt_info("  Suspending (15s, switch at T+7s)...\n");
+		igt_system_suspend_autoresume(SUSPEND_STATE_MEM,
+					      SUSPEND_TEST_NONE);
+		igt_info("  Resumed\n");
+
+		igt_info("  Reprobing connectors for MST discovery...\n");
+		mst_stabilize(data);
+
+		igt_assert_f(wait_for_displays(data, port_cfg_b, timeout),
+			     "Displays did not enumerate on port %d after switch-during-suspend\n",
+			     port_cfg_b->port_num);
+		igt_info("  Verifying displays on port %d...\n",
+			 port_cfg_b->port_num);
+		igt_assert_f(verify_port_displays(data, port_cfg_b),
+			     "Display verification failed on port %d after switch-during-suspend\n",
+			     port_cfg_b->port_num);
+
+		verify_port_display_pipeline(data, port_cfg_b);
+
+		/* Schedule switch back to A during suspend */
+		igt_info("  Scheduling switch to port %d during suspend (T+7s)...\n",
+			 port_cfg_a->port_num);
+		igt_assert(usb4switch_port_disable_and_wait(data->sw));
+		igt_assert(usb4switch_port_enable_delayed(data->sw,
+							  port_cfg_a->port_num,
+							  7));
+
+		igt_info("  Suspending (15s, switch at T+7s)...\n");
+		igt_system_suspend_autoresume(SUSPEND_STATE_MEM,
+					      SUSPEND_TEST_NONE);
+		igt_info("  Resumed\n");
+
+		mst_stabilize(data);
+
+		igt_assert_f(wait_for_displays(data, port_cfg_a, timeout),
+			     "Displays did not enumerate on port %d after switch-during-suspend\n",
+			     port_cfg_a->port_num);
+		igt_info("  Verifying displays on port %d...\n",
+			 port_cfg_a->port_num);
+		igt_assert_f(verify_port_displays(data, port_cfg_a),
+			     "Display verification failed on port %d after switch-during-suspend\n",
+			     port_cfg_a->port_num);
+
+		verify_port_display_pipeline(data, port_cfg_a);
+	}
+
+	igt_flush_uevents(data->hotplug_mon);
+	igt_assert(usb4switch_port_disable_and_wait(data->sw));
+	wait_for_hotplug(data, timeout);
+}
+
+static void test_switch_sr(data_t *data,
+			   const struct usb4switch_port *port_cfg_a,
+			   const struct usb4switch_port *port_cfg_b)
+{
+	igt_crc_t ref_crcs[MAX_DISPLAYS_PER_PORT];
+	int iterations = usb4switch_get_iterations(data->sw);
+	int timeout = USB4_SWITCH_TIMEOUT_S;
+	int i;
+
+	igt_info("Testing switch with S/R port %d <-> port %d, %d iterations\n",
+		 port_cfg_a->port_num, port_cfg_b->port_num, iterations);
+
+	for (i = 0; i < iterations; i++) {
+		igt_info("Iteration %d/%d\n", i + 1, iterations);
+
+		/* Enable port A */
+		igt_info("  Enabling port %d...\n", port_cfg_a->port_num);
+		igt_flush_uevents(data->hotplug_mon);
+		igt_assert(usb4switch_port_switch(data->sw,
+						  port_cfg_a->port_num));
+		wait_for_hotplug(data, timeout);
+
+		igt_assert_f(wait_for_displays(data, port_cfg_a, timeout),
+			     "Displays did not enumerate on port %d\n",
+			     port_cfg_a->port_num);
+		igt_assert_f(verify_port_displays(data, port_cfg_a),
+			     "Display verification failed on port %d\n",
+			     port_cfg_a->port_num);
+
+		/* Collect reference CRCs on port A before suspend */
+		get_port_reference_crcs(data, port_cfg_a, ref_crcs);
+
+		/* Suspend/Resume */
+		igt_info("  Suspending with port %d active...\n",
+			 port_cfg_a->port_num);
+		igt_system_suspend_autoresume(SUSPEND_STATE_MEM,
+					      SUSPEND_TEST_NONE);
+		igt_info("  Resumed\n");
+
+		mst_stabilize(data);
+
+		igt_assert_f(wait_for_displays(data, port_cfg_a, timeout),
+			     "Displays did not enumerate on port %d after resume\n",
+			     port_cfg_a->port_num);
+		igt_assert_f(verify_port_displays(data, port_cfg_a),
+			     "Display verification failed on port %d after resume\n",
+			     port_cfg_a->port_num);
+
+		/* Compare post-resume CRCs with pre-suspend reference */
+		verify_port_crcs_after_resume(data, port_cfg_a, ref_crcs);
+
+		/* Switch to port B */
+		igt_info("  Switching to port %d...\n",
+			 port_cfg_b->port_num);
+		igt_flush_uevents(data->hotplug_mon);
+		igt_assert(usb4switch_port_switch(data->sw,
+						  port_cfg_b->port_num));
+		wait_for_hotplug(data, timeout);
+
+		igt_assert_f(wait_for_displays(data, port_cfg_b, timeout),
+			     "Displays did not enumerate on port %d\n",
+			     port_cfg_b->port_num);
+		igt_assert_f(verify_port_displays(data, port_cfg_b),
+			     "Display verification failed on port %d\n",
+			     port_cfg_b->port_num);
+
+		/* Collect reference CRCs on port B before suspend */
+		get_port_reference_crcs(data, port_cfg_b, ref_crcs);
+
+		/* Suspend/Resume with port B */
+		igt_info("  Suspending with port %d active...\n",
+			 port_cfg_b->port_num);
+		igt_system_suspend_autoresume(SUSPEND_STATE_MEM,
+					      SUSPEND_TEST_NONE);
+		igt_info("  Resumed\n");
+
+		mst_stabilize(data);
+
+		igt_assert_f(wait_for_displays(data, port_cfg_b, timeout),
+			     "Displays did not enumerate on port %d after resume\n",
+			     port_cfg_b->port_num);
+		igt_assert_f(verify_port_displays(data, port_cfg_b),
+			     "Display verification failed on port %d after resume\n",
+			     port_cfg_b->port_num);
+
+		/* Compare post-resume CRCs with pre-suspend reference */
+		verify_port_crcs_after_resume(data, port_cfg_b, ref_crcs);
+	}
+
+	igt_flush_uevents(data->hotplug_mon);
+	igt_assert(usb4switch_port_disable_and_wait(data->sw));
+	wait_for_hotplug(data, timeout);
+}
+
+int igt_main()
+{
+	const struct usb4switch_port *pcfg, *pa, *pb;
+	data_t data = {};
+	igt_crtc_t *crtc;
+	char name[80];
+	int port_count;
+	int p;
+
+	igt_fixture() {
+		data.drm_fd = drm_open_driver_master(DRIVER_INTEL | DRIVER_XE);
+		igt_require(data.drm_fd >= 0);
+
+		kmstest_set_vt_graphics_mode();
+		igt_display_require(&data.display, data.drm_fd);
+
+		data.sw = usb4switch_init(data.drm_fd);
+		igt_require_f(data.sw, "USB4 Switch 3141 not available\n");
+
+		igt_require_pipe_crc(data.drm_fd);
+		data.max_dotclock = igt_get_max_dotclock(data.drm_fd);
+
+		data.hotplug_mon = igt_watch_uevents();
+		igt_require(data.hotplug_mon);
+
+		/* Compute pipe masks for joiner-aware allocation */
+		igt_set_all_master_pipes_for_platform(&data.display,
+						      &data.master_pipes);
+		data.valid_pipes = 0;
+		for_each_crtc(&data.display, crtc)
+			data.valid_pipes |= BIT(crtc->pipe);
+
+		/* Ensure all ports are disconnected */
+		igt_assert(usb4switch_port_disable_and_wait(data.sw));
+	}
+
+	igt_describe("Dock/undock cycles with display verification");
+	igt_subtest_with_dynamic("dock-undock") {
+		port_count = usb4switch_get_port_count(data.sw);
+
+		for_each_usb4_port(data.sw, port_count, p, pcfg) {
+			port_dynamic_name(pcfg, name, sizeof(name));
+			igt_dynamic(name)
+				test_dock_undock(&data, pcfg);
+		}
+	}
+
+	igt_describe("Dock/undock with suspend/resume stability");
+	igt_subtest_with_dynamic("dock-undock-sr") {
+		port_count = usb4switch_get_port_count(data.sw);
+
+		for_each_usb4_port(data.sw, port_count, p, pcfg) {
+			port_dynamic_name(pcfg, name, sizeof(name));
+			igt_dynamic(name)
+				test_dock_undock_sr(&data, pcfg);
+		}
+	}
+
+	igt_describe("Dock during suspend with display verification");
+	igt_subtest_with_dynamic("dock-during-suspend") {
+		port_count = usb4switch_get_port_count(data.sw);
+
+		for_each_usb4_port(data.sw, port_count, p, pcfg) {
+			port_dynamic_name(pcfg, name, sizeof(name));
+			igt_dynamic(name)
+				test_dock_during_suspend(&data, pcfg);
+		}
+	}
+
+	igt_describe("Undock during suspend with display verification");
+	igt_subtest_with_dynamic("undock-during-suspend") {
+		port_count = usb4switch_get_port_count(data.sw);
+
+		for_each_usb4_port(data.sw, port_count, p, pcfg) {
+			port_dynamic_name(pcfg, name, sizeof(name));
+			igt_dynamic(name)
+				test_undock_during_suspend(&data, pcfg);
+		}
+	}
+
+	igt_describe("Port switching with display verification");
+	igt_subtest_with_dynamic("switch") {
+		port_count = usb4switch_get_port_count(data.sw);
+		igt_require(port_count > 1);
+
+		for_each_usb4_port_pair(data.sw, port_count, p, pa, pb) {
+			pair_dynamic_name(pa, pb, name, sizeof(name));
+			igt_dynamic(name)
+				test_switch(&data, pa, pb);
+		}
+	}
+
+	igt_describe("Port switching with suspend/resume stability");
+	igt_subtest_with_dynamic("switch-sr") {
+		port_count = usb4switch_get_port_count(data.sw);
+		igt_require(port_count > 1);
+
+		for_each_usb4_port_pair(data.sw, port_count, p, pa, pb) {
+			pair_dynamic_name(pa, pb, name, sizeof(name));
+			igt_dynamic(name)
+				test_switch_sr(&data, pa, pb);
+		}
+	}
+
+	igt_describe("Port switching during suspend via hardware delay");
+	igt_subtest_with_dynamic("switch-during-suspend") {
+		port_count = usb4switch_get_port_count(data.sw);
+		igt_require(port_count > 1);
+
+		for_each_usb4_port_pair(data.sw, port_count, p, pa, pb) {
+			pair_dynamic_name(pa, pb, name, sizeof(name));
+			igt_dynamic(name)
+				test_switch_during_suspend(&data, pa, pb);
+		}
+	}
+
+	igt_fixture() {
+		if (!usb4switch_port_disable_and_wait(data.sw))
+			igt_warn("Failed to disable ports during cleanup\n");
+		igt_cleanup_uevents(data.hotplug_mon);
+		usb4switch_deinit(data.sw);
+		igt_display_fini(&data.display);
+		drm_close_driver(data.drm_fd);
+	}
+}
diff --git a/tests/meson.build b/tests/meson.build
index 7f356de9b..563c65240 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -276,6 +276,7 @@ intel_kms_progs = [
 	'kms_psr_stress_test',
 	'kms_pwrite_crc',
 	'kms_sharpness_filter',
+	'kms_usb4_switch',
 ]
 
 intel_xe_progs = [
@@ -400,6 +401,7 @@ extra_sources = {
 	'kms_dsc': [ join_paths ('intel', 'kms_dsc_helper.c') ],
 	'kms_joiner': [ join_paths ('intel', 'kms_joiner_helper.c') ],
 	'kms_psr2_sf':  [ join_paths ('intel', 'kms_dsc_helper.c') ],
+	'kms_usb4_switch': [ join_paths ('intel', 'kms_joiner_helper.c') ],
 }
 
 # Extra dependencies used on core and Intel drivers
-- 
2.25.1


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

* ✗ Xe.CI.BAT: failure for add test to validate dock/undock and switch (rev3)
  2026-02-25 21:28 [PATCH i-g-t 0/6] add test to validate dock/undock and switch Kunal Joshi
                   ` (5 preceding siblings ...)
  2026-02-25 21:28 ` [PATCH i-g-t 6/6] tests/intel/kms_usb4_switch: Add USB4 switch test suite Kunal Joshi
@ 2026-02-26  2:20 ` Patchwork
  2026-02-26  3:04 ` ✓ i915.CI.BAT: success " Patchwork
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 25+ messages in thread
From: Patchwork @ 2026-02-26  2:20 UTC (permalink / raw)
  To: Kunal Joshi; +Cc: igt-dev

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

== Series Details ==

Series: add test to validate dock/undock and switch (rev3)
URL   : https://patchwork.freedesktop.org/series/149299/
State : failure

== Summary ==

CI Bug Log - changes from XEIGT_8772_BAT -> XEIGTPW_14620_BAT
====================================================

Summary
-------

  **FAILURE**

  Serious unknown changes coming with XEIGTPW_14620_BAT absolutely need to be
  verified manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in XEIGTPW_14620_BAT, 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.

  

Participating hosts (14 -> 14)
------------------------------

  No changes in participating hosts

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

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

### IGT changes ###

#### Possible regressions ####

  * igt@kms_flip@basic-flip-vs-wf_vblank@c-edp1:
    - bat-adlp-7:         [PASS][1] -> [DMESG-WARN][2]
   [1]: https://intel-gfx-ci.01.org/tree/intel-xe/IGT_8772/bat-adlp-7/igt@kms_flip@basic-flip-vs-wf_vblank@c-edp1.html
   [2]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/bat-adlp-7/igt@kms_flip@basic-flip-vs-wf_vblank@c-edp1.html

  * igt@xe_exec_basic@multigpu-many-execqueues-many-vm-userptr-invalidate-race:
    - bat-bmg-3:          [PASS][3] -> [INCOMPLETE][4]
   [3]: https://intel-gfx-ci.01.org/tree/intel-xe/IGT_8772/bat-bmg-3/igt@xe_exec_basic@multigpu-many-execqueues-many-vm-userptr-invalidate-race.html
   [4]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/bat-bmg-3/igt@xe_exec_basic@multigpu-many-execqueues-many-vm-userptr-invalidate-race.html

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

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

### IGT changes ###

#### Possible fixes ####

  * igt@kms_flip@basic-flip-vs-wf_vblank@d-edp1:
    - bat-adlp-7:         [DMESG-WARN][5] -> [PASS][6]
   [5]: https://intel-gfx-ci.01.org/tree/intel-xe/IGT_8772/bat-adlp-7/igt@kms_flip@basic-flip-vs-wf_vblank@d-edp1.html
   [6]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/bat-adlp-7/igt@kms_flip@basic-flip-vs-wf_vblank@d-edp1.html

  


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

  * IGT: IGT_8772 -> IGTPW_14620
  * Linux: xe-4617-3b1923ab37ecd72e1405c7b8d3b1d9e1f3e59f86 -> xe-4620-f0ec6252eb6d9a4f0cb5a437f5c21fec16d0a440

  IGTPW_14620: 14620
  IGT_8772: 8772
  xe-4617-3b1923ab37ecd72e1405c7b8d3b1d9e1f3e59f86: 3b1923ab37ecd72e1405c7b8d3b1d9e1f3e59f86
  xe-4620-f0ec6252eb6d9a4f0cb5a437f5c21fec16d0a440: f0ec6252eb6d9a4f0cb5a437f5c21fec16d0a440

== Logs ==

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

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

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

* ✓ i915.CI.BAT: success for add test to validate dock/undock and switch (rev3)
  2026-02-25 21:28 [PATCH i-g-t 0/6] add test to validate dock/undock and switch Kunal Joshi
                   ` (6 preceding siblings ...)
  2026-02-26  2:20 ` ✗ Xe.CI.BAT: failure for add test to validate dock/undock and switch (rev3) Patchwork
@ 2026-02-26  3:04 ` Patchwork
  2026-02-26  6:52 ` ✗ Xe.CI.FULL: failure " Patchwork
  2026-02-26  7:45 ` ✗ i915.CI.Full: " Patchwork
  9 siblings, 0 replies; 25+ messages in thread
From: Patchwork @ 2026-02-26  3:04 UTC (permalink / raw)
  To: Kunal Joshi; +Cc: igt-dev

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

== Series Details ==

Series: add test to validate dock/undock and switch (rev3)
URL   : https://patchwork.freedesktop.org/series/149299/
State : success

== Summary ==

CI Bug Log - changes from IGT_8772 -> IGTPW_14620
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

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

Participating hosts (40 -> 41)
------------------------------

  Additional (3): bat-dg2-14 bat-atsm-1 fi-pnv-d510 
  Missing    (2): bat-dg2-13 fi-snb-2520m 

New tests
---------

  New tests have been introduced between IGT_8772 and IGTPW_14620:

### New IGT tests (1) ###

  * igt@gem_lmem_swapping@flink-lifetime:
    - Statuses :
    - Exec time: [None] s

  

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

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

### IGT changes ###

#### Issues hit ####

  * igt@fbdev@info:
    - bat-atsm-1:         NOTRUN -> [SKIP][1] ([i915#1849] / [i915#2582])
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/bat-atsm-1/igt@fbdev@info.html

  * igt@fbdev@read:
    - bat-atsm-1:         NOTRUN -> [SKIP][2] ([i915#2582]) +3 other tests skip
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/bat-atsm-1/igt@fbdev@read.html

  * igt@gem_lmem_swapping@parallel-random-engines:
    - bat-dg1-7:          [PASS][3] -> [ABORT][4] ([i915#15759]) +1 other test abort
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8772/bat-dg1-7/igt@gem_lmem_swapping@parallel-random-engines.html
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/bat-dg1-7/igt@gem_lmem_swapping@parallel-random-engines.html

  * igt@gem_mmap@basic:
    - bat-atsm-1:         NOTRUN -> [SKIP][5] ([i915#4083])
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/bat-atsm-1/igt@gem_mmap@basic.html
    - bat-dg2-14:         NOTRUN -> [SKIP][6] ([i915#4083])
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/bat-dg2-14/igt@gem_mmap@basic.html

  * igt@gem_render_tiled_blits@basic:
    - bat-dg2-14:         NOTRUN -> [SKIP][7] ([i915#4079])
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/bat-dg2-14/igt@gem_render_tiled_blits@basic.html
    - bat-atsm-1:         NOTRUN -> [SKIP][8] ([i915#4079])
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/bat-atsm-1/igt@gem_render_tiled_blits@basic.html

  * igt@gem_tiled_fence_blits@basic:
    - bat-dg2-14:         NOTRUN -> [SKIP][9] ([i915#4077]) +2 other tests skip
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/bat-dg2-14/igt@gem_tiled_fence_blits@basic.html
    - bat-atsm-1:         NOTRUN -> [SKIP][10] ([i915#4077]) +4 other tests skip
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/bat-atsm-1/igt@gem_tiled_fence_blits@basic.html

  * igt@gem_tiled_pread_basic@basic:
    - bat-atsm-1:         NOTRUN -> [SKIP][11] ([i915#15657])
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/bat-atsm-1/igt@gem_tiled_pread_basic@basic.html
    - bat-dg2-14:         NOTRUN -> [SKIP][12] ([i915#15657])
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/bat-dg2-14/igt@gem_tiled_pread_basic@basic.html

  * igt@i915_pm_rps@basic-api:
    - bat-dg2-14:         NOTRUN -> [SKIP][13] ([i915#11681] / [i915#6621])
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/bat-dg2-14/igt@i915_pm_rps@basic-api.html
    - bat-atsm-1:         NOTRUN -> [SKIP][14] ([i915#6621])
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/bat-atsm-1/igt@i915_pm_rps@basic-api.html

  * igt@i915_selftest@live:
    - bat-mtlp-8:         [PASS][15] -> [DMESG-FAIL][16] ([i915#12061]) +1 other test dmesg-fail
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8772/bat-mtlp-8/igt@i915_selftest@live.html
   [16]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/bat-mtlp-8/igt@i915_selftest@live.html
    - bat-arls-5:         [PASS][17] -> [TIMEOUT][18] ([i915#15738]) +1 other test timeout
   [17]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8772/bat-arls-5/igt@i915_selftest@live.html
   [18]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/bat-arls-5/igt@i915_selftest@live.html

  * igt@i915_selftest@live@late_gt_pm:
    - fi-cfl-8109u:       [PASS][19] -> [DMESG-WARN][20] ([i915#13735]) +130 other tests dmesg-warn
   [19]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8772/fi-cfl-8109u/igt@i915_selftest@live@late_gt_pm.html
   [20]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/fi-cfl-8109u/igt@i915_selftest@live@late_gt_pm.html

  * igt@i915_selftest@live@sanitycheck:
    - bat-apl-1:          [PASS][21] -> [DMESG-WARN][22] ([i915#13735]) +77 other tests dmesg-warn
   [21]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8772/bat-apl-1/igt@i915_selftest@live@sanitycheck.html
   [22]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/bat-apl-1/igt@i915_selftest@live@sanitycheck.html
    - bat-arls-5:         [PASS][23] -> [DMESG-WARN][24] ([i915#15738]) +21 other tests dmesg-warn
   [23]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8772/bat-arls-5/igt@i915_selftest@live@sanitycheck.html
   [24]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/bat-arls-5/igt@i915_selftest@live@sanitycheck.html

  * igt@i915_selftest@live@workarounds:
    - bat-atsm-1:         NOTRUN -> [DMESG-FAIL][25] ([i915#12061]) +1 other test dmesg-fail
   [25]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/bat-atsm-1/igt@i915_selftest@live@workarounds.html

  * igt@kms_addfb_basic@addfb25-y-tiled-small-legacy:
    - bat-dg2-14:         NOTRUN -> [SKIP][26] ([i915#5190])
   [26]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/bat-dg2-14/igt@kms_addfb_basic@addfb25-y-tiled-small-legacy.html

  * igt@kms_addfb_basic@basic-y-tiled-legacy:
    - bat-dg2-14:         NOTRUN -> [SKIP][27] ([i915#4215] / [i915#5190])
   [27]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/bat-dg2-14/igt@kms_addfb_basic@basic-y-tiled-legacy.html

  * igt@kms_addfb_basic@size-max:
    - bat-atsm-1:         NOTRUN -> [SKIP][28] ([i915#6077]) +37 other tests skip
   [28]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/bat-atsm-1/igt@kms_addfb_basic@size-max.html

  * igt@kms_addfb_basic@tile-pitch-mismatch:
    - bat-dg2-14:         NOTRUN -> [SKIP][29] ([i915#4212]) +7 other tests skip
   [29]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/bat-dg2-14/igt@kms_addfb_basic@tile-pitch-mismatch.html

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

  * igt@kms_cursor_legacy@basic-flip-after-cursor-atomic:
    - bat-atsm-1:         NOTRUN -> [SKIP][31] ([i915#6078]) +22 other tests skip
   [31]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/bat-atsm-1/igt@kms_cursor_legacy@basic-flip-after-cursor-atomic.html

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

  * igt@kms_force_connector_basic@force-load-detect:
    - bat-dg2-14:         NOTRUN -> [SKIP][33]
   [33]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/bat-dg2-14/igt@kms_force_connector_basic@force-load-detect.html
    - bat-atsm-1:         NOTRUN -> [SKIP][34] ([i915#6093]) +4 other tests skip
   [34]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/bat-atsm-1/igt@kms_force_connector_basic@force-load-detect.html

  * igt@kms_pipe_crc_basic@read-crc-frame-sequence:
    - bat-atsm-1:         NOTRUN -> [SKIP][35] ([i915#1836]) +6 other tests skip
   [35]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/bat-atsm-1/igt@kms_pipe_crc_basic@read-crc-frame-sequence.html

  * igt@kms_pm_backlight@basic-brightness:
    - bat-dg2-14:         NOTRUN -> [SKIP][36] ([i915#5354])
   [36]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/bat-dg2-14/igt@kms_pm_backlight@basic-brightness.html

  * igt@kms_pm_rpm@basic-pci-d3-state:
    - bat-apl-1:          [PASS][37] -> [DMESG-WARN][38] ([i915#13735] / [i915#180]) +49 other tests dmesg-warn
   [37]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8772/bat-apl-1/igt@kms_pm_rpm@basic-pci-d3-state.html
   [38]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/bat-apl-1/igt@kms_pm_rpm@basic-pci-d3-state.html

  * igt@kms_prop_blob@basic:
    - bat-atsm-1:         NOTRUN -> [SKIP][39] ([i915#7357])
   [39]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/bat-atsm-1/igt@kms_prop_blob@basic.html

  * igt@kms_psr@psr-primary-mmap-gtt:
    - fi-pnv-d510:        NOTRUN -> [SKIP][40] +35 other tests skip
   [40]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/fi-pnv-d510/igt@kms_psr@psr-primary-mmap-gtt.html

  * igt@kms_psr@psr-sprite-plane-onoff:
    - bat-dg2-14:         NOTRUN -> [SKIP][41] ([i915#1072] / [i915#9732]) +3 other tests skip
   [41]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/bat-dg2-14/igt@kms_psr@psr-sprite-plane-onoff.html

  * igt@kms_setmode@basic-clone-single-crtc:
    - bat-dg2-14:         NOTRUN -> [SKIP][42] ([i915#3555])
   [42]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/bat-dg2-14/igt@kms_setmode@basic-clone-single-crtc.html
    - bat-atsm-1:         NOTRUN -> [SKIP][43] ([i915#6094])
   [43]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/bat-atsm-1/igt@kms_setmode@basic-clone-single-crtc.html

  * igt@prime_vgem@basic-fence-flip:
    - bat-dg2-14:         NOTRUN -> [SKIP][44] ([i915#3708])
   [44]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/bat-dg2-14/igt@prime_vgem@basic-fence-flip.html

  * igt@prime_vgem@basic-gtt:
    - bat-dg2-14:         NOTRUN -> [SKIP][45] ([i915#3708] / [i915#4077]) +1 other test skip
   [45]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/bat-dg2-14/igt@prime_vgem@basic-gtt.html

  * igt@prime_vgem@basic-write:
    - bat-dg2-14:         NOTRUN -> [SKIP][46] ([i915#3291] / [i915#3708]) +2 other tests skip
   [46]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/bat-dg2-14/igt@prime_vgem@basic-write.html
    - bat-atsm-1:         NOTRUN -> [SKIP][47] +2 other tests skip
   [47]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/bat-atsm-1/igt@prime_vgem@basic-write.html

  
  [i915#1072]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/1072
  [i915#11681]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/11681
  [i915#12061]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/12061
  [i915#13735]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13735
  [i915#15657]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15657
  [i915#15738]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15738
  [i915#15759]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15759
  [i915#180]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/180
  [i915#1836]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/1836
  [i915#1849]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/1849
  [i915#2582]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/2582
  [i915#3291]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3291
  [i915#3555]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3555
  [i915#3708]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3708
  [i915#3840]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3840
  [i915#4077]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4077
  [i915#4079]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4079
  [i915#4083]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4083
  [i915#4103]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4103
  [i915#4212]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4212
  [i915#4213]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4213
  [i915#4215]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4215
  [i915#5190]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/5190
  [i915#5354]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/5354
  [i915#6077]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/6077
  [i915#6078]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/6078
  [i915#6093]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/6093
  [i915#6094]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/6094
  [i915#6621]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/6621
  [i915#7357]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/7357
  [i915#9732]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9732


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

  * CI: CI-20190529 -> None
  * IGT: IGT_8772 -> IGTPW_14620
  * Linux: CI_DRM_18048 -> CI_DRM_18050

  CI-20190529: 20190529
  CI_DRM_18048: 940d2c5064ed09bca924fd8aa017be99cc745b31 @ git://anongit.freedesktop.org/gfx-ci/linux
  CI_DRM_18050: f0ec6252eb6d9a4f0cb5a437f5c21fec16d0a440 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGTPW_14620: 14620
  IGT_8772: 8772

== Logs ==

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

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

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

* ✗ Xe.CI.FULL: failure for add test to validate dock/undock and switch (rev3)
  2026-02-25 21:28 [PATCH i-g-t 0/6] add test to validate dock/undock and switch Kunal Joshi
                   ` (7 preceding siblings ...)
  2026-02-26  3:04 ` ✓ i915.CI.BAT: success " Patchwork
@ 2026-02-26  6:52 ` Patchwork
  2026-02-26  7:45 ` ✗ i915.CI.Full: " Patchwork
  9 siblings, 0 replies; 25+ messages in thread
From: Patchwork @ 2026-02-26  6:52 UTC (permalink / raw)
  To: Kunal Joshi; +Cc: igt-dev

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

== Series Details ==

Series: add test to validate dock/undock and switch (rev3)
URL   : https://patchwork.freedesktop.org/series/149299/
State : failure

== Summary ==

CI Bug Log - changes from XEIGT_8772_FULL -> XEIGTPW_14620_FULL
====================================================

Summary
-------

  **FAILURE**

  Serious unknown changes coming with XEIGTPW_14620_FULL absolutely need to be
  verified manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in XEIGTPW_14620_FULL, 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.

  

Participating hosts (2 -> 2)
------------------------------

  No changes in participating hosts

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

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

### IGT changes ###

#### Possible regressions ####

  * {igt@kms_usb4_switch@dock-during-suspend} (NEW):
    - shard-bmg:          NOTRUN -> [SKIP][1] +7 other tests skip
   [1]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-8/igt@kms_usb4_switch@dock-during-suspend.html

  * {igt@kms_usb4_switch@switch} (NEW):
    - shard-lnl:          NOTRUN -> [SKIP][2] +7 other tests skip
   [2]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-5/igt@kms_usb4_switch@switch.html

  * igt@xe_fault_injection@oa-add-config-fail-xe_oa_alloc_regs:
    - shard-bmg:          [PASS][3] -> [ABORT][4]
   [3]: https://intel-gfx-ci.01.org/tree/intel-xe/IGT_8772/shard-bmg-2/igt@xe_fault_injection@oa-add-config-fail-xe_oa_alloc_regs.html
   [4]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-6/igt@xe_fault_injection@oa-add-config-fail-xe_oa_alloc_regs.html

  
New tests
---------

  New tests have been introduced between XEIGT_8772_FULL and XEIGTPW_14620_FULL:

### New IGT tests (8) ###

  * igt@kms_feature_discovery@usb4-switch:
    - Statuses : 2 skip(s)
    - Exec time: [0.00] s

  * igt@kms_usb4_switch@dock-during-suspend:
    - Statuses : 2 skip(s)
    - Exec time: [0.0] s

  * igt@kms_usb4_switch@dock-undock:
    - Statuses : 2 skip(s)
    - Exec time: [0.0] s

  * igt@kms_usb4_switch@dock-undock-sr:
    - Statuses : 2 skip(s)
    - Exec time: [0.0] s

  * igt@kms_usb4_switch@switch:
    - Statuses : 2 skip(s)
    - Exec time: [0.0] s

  * igt@kms_usb4_switch@switch-during-suspend:
    - Statuses : 2 skip(s)
    - Exec time: [0.0] s

  * igt@kms_usb4_switch@switch-sr:
    - Statuses : 2 skip(s)
    - Exec time: [0.0] s

  * igt@kms_usb4_switch@undock-during-suspend:
    - Statuses : 2 skip(s)
    - Exec time: [0.0] s

  

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

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

### IGT changes ###

#### Issues hit ####

  * igt@kms_async_flips@async-flip-with-page-flip-events-linear:
    - shard-lnl:          [PASS][5] -> [FAIL][6] ([Intel XE#5993]) +3 other tests fail
   [5]: https://intel-gfx-ci.01.org/tree/intel-xe/IGT_8772/shard-lnl-5/igt@kms_async_flips@async-flip-with-page-flip-events-linear.html
   [6]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-3/igt@kms_async_flips@async-flip-with-page-flip-events-linear.html

  * igt@kms_big_fb@4-tiled-32bpp-rotate-270:
    - shard-lnl:          NOTRUN -> [SKIP][7] ([Intel XE#1407]) +1 other test skip
   [7]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-3/igt@kms_big_fb@4-tiled-32bpp-rotate-270.html

  * igt@kms_big_fb@linear-32bpp-rotate-270:
    - shard-bmg:          NOTRUN -> [SKIP][8] ([Intel XE#2327]) +4 other tests skip
   [8]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-4/igt@kms_big_fb@linear-32bpp-rotate-270.html

  * igt@kms_big_fb@linear-max-hw-stride-32bpp-rotate-180-hflip:
    - shard-lnl:          NOTRUN -> [SKIP][9] ([Intel XE#7059])
   [9]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-3/igt@kms_big_fb@linear-max-hw-stride-32bpp-rotate-180-hflip.html
    - shard-bmg:          NOTRUN -> [SKIP][10] ([Intel XE#7059])
   [10]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-2/igt@kms_big_fb@linear-max-hw-stride-32bpp-rotate-180-hflip.html

  * igt@kms_big_fb@y-tiled-32bpp-rotate-0:
    - shard-lnl:          NOTRUN -> [SKIP][11] ([Intel XE#1124]) +5 other tests skip
   [11]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-4/igt@kms_big_fb@y-tiled-32bpp-rotate-0.html

  * igt@kms_big_fb@y-tiled-addfb-size-overflow:
    - shard-lnl:          NOTRUN -> [SKIP][12] ([Intel XE#1428])
   [12]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-4/igt@kms_big_fb@y-tiled-addfb-size-overflow.html

  * igt@kms_big_fb@yf-tiled-64bpp-rotate-270:
    - shard-bmg:          NOTRUN -> [SKIP][13] ([Intel XE#1124]) +4 other tests skip
   [13]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-8/igt@kms_big_fb@yf-tiled-64bpp-rotate-270.html

  * igt@kms_bw@connected-linear-tiling-2-displays-1920x1080p:
    - shard-lnl:          NOTRUN -> [SKIP][14] ([Intel XE#2191]) +2 other tests skip
   [14]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-8/igt@kms_bw@connected-linear-tiling-2-displays-1920x1080p.html

  * igt@kms_bw@connected-linear-tiling-3-displays-1920x1080p:
    - shard-bmg:          NOTRUN -> [SKIP][15] ([Intel XE#2314] / [Intel XE#2894]) +1 other test skip
   [15]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-7/igt@kms_bw@connected-linear-tiling-3-displays-1920x1080p.html

  * igt@kms_ccs@bad-pixel-format-4-tiled-mtl-rc-ccs-cc:
    - shard-lnl:          NOTRUN -> [SKIP][16] ([Intel XE#2887]) +7 other tests skip
   [16]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-3/igt@kms_ccs@bad-pixel-format-4-tiled-mtl-rc-ccs-cc.html

  * igt@kms_ccs@crc-primary-rotation-180-y-tiled-gen12-rc-ccs:
    - shard-bmg:          NOTRUN -> [SKIP][17] ([Intel XE#2887]) +5 other tests skip
   [17]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-7/igt@kms_ccs@crc-primary-rotation-180-y-tiled-gen12-rc-ccs.html

  * igt@kms_ccs@random-ccs-data-4-tiled-lnl-ccs@pipe-c-dp-2:
    - shard-bmg:          NOTRUN -> [SKIP][18] ([Intel XE#2652]) +16 other tests skip
   [18]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-3/igt@kms_ccs@random-ccs-data-4-tiled-lnl-ccs@pipe-c-dp-2.html

  * igt@kms_chamelium_color@ctm-0-25:
    - shard-lnl:          NOTRUN -> [SKIP][19] ([Intel XE#306])
   [19]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-7/igt@kms_chamelium_color@ctm-0-25.html

  * igt@kms_chamelium_color@ctm-red-to-blue:
    - shard-bmg:          NOTRUN -> [SKIP][20] ([Intel XE#2325])
   [20]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-2/igt@kms_chamelium_color@ctm-red-to-blue.html

  * igt@kms_chamelium_edid@dp-edid-resolution-list:
    - shard-bmg:          NOTRUN -> [SKIP][21] ([Intel XE#2252]) +4 other tests skip
   [21]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-3/igt@kms_chamelium_edid@dp-edid-resolution-list.html

  * igt@kms_chamelium_frames@hdmi-crc-nonplanar-formats:
    - shard-lnl:          NOTRUN -> [SKIP][22] ([Intel XE#373]) +7 other tests skip
   [22]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-5/igt@kms_chamelium_frames@hdmi-crc-nonplanar-formats.html

  * igt@kms_color_pipeline@plane-lut1d-lut1d@pipe-a-plane-2:
    - shard-lnl:          NOTRUN -> [FAIL][23] ([Intel XE#7305]) +9 other tests fail
   [23]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-4/igt@kms_color_pipeline@plane-lut1d-lut1d@pipe-a-plane-2.html

  * igt@kms_content_protection@atomic-dpms:
    - shard-lnl:          NOTRUN -> [SKIP][24] ([Intel XE#3278])
   [24]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-8/igt@kms_content_protection@atomic-dpms.html

  * igt@kms_content_protection@content-type-change:
    - shard-bmg:          NOTRUN -> [SKIP][25] ([Intel XE#2341])
   [25]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-7/igt@kms_content_protection@content-type-change.html

  * igt@kms_content_protection@dp-mst-type-1-suspend-resume:
    - shard-bmg:          NOTRUN -> [SKIP][26] ([Intel XE#6974])
   [26]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-4/igt@kms_content_protection@dp-mst-type-1-suspend-resume.html

  * igt@kms_content_protection@legacy-hdcp14:
    - shard-lnl:          NOTRUN -> [SKIP][27] ([Intel XE#6973])
   [27]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-4/igt@kms_content_protection@legacy-hdcp14.html

  * igt@kms_content_protection@lic-type-0@pipe-a-dp-1:
    - shard-bmg:          NOTRUN -> [FAIL][28] ([Intel XE#3304]) +1 other test fail
   [28]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-5/igt@kms_content_protection@lic-type-0@pipe-a-dp-1.html

  * igt@kms_content_protection@srm@pipe-a-dp-2:
    - shard-bmg:          NOTRUN -> [FAIL][29] ([Intel XE#1178] / [Intel XE#3304])
   [29]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-8/igt@kms_content_protection@srm@pipe-a-dp-2.html

  * igt@kms_content_protection@suspend-resume:
    - shard-lnl:          NOTRUN -> [SKIP][30] ([Intel XE#6705])
   [30]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-1/igt@kms_content_protection@suspend-resume.html

  * igt@kms_cursor_crc@cursor-onscreen-512x170:
    - shard-bmg:          NOTRUN -> [SKIP][31] ([Intel XE#2321]) +2 other tests skip
   [31]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-4/igt@kms_cursor_crc@cursor-onscreen-512x170.html

  * igt@kms_cursor_crc@cursor-rapid-movement-32x10:
    - shard-bmg:          NOTRUN -> [SKIP][32] ([Intel XE#2320]) +1 other test skip
   [32]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-8/igt@kms_cursor_crc@cursor-rapid-movement-32x10.html
    - shard-lnl:          NOTRUN -> [SKIP][33] ([Intel XE#1424])
   [33]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-1/igt@kms_cursor_crc@cursor-rapid-movement-32x10.html

  * igt@kms_cursor_crc@cursor-sliding-512x512:
    - shard-lnl:          NOTRUN -> [SKIP][34] ([Intel XE#2321]) +2 other tests skip
   [34]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-7/igt@kms_cursor_crc@cursor-sliding-512x512.html

  * igt@kms_cursor_legacy@cursora-vs-flipb-atomic-transitions-varying-size:
    - shard-lnl:          NOTRUN -> [SKIP][35] ([Intel XE#309]) +5 other tests skip
   [35]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-7/igt@kms_cursor_legacy@cursora-vs-flipb-atomic-transitions-varying-size.html

  * igt@kms_dsc@dsc-fractional-bpp:
    - shard-lnl:          NOTRUN -> [SKIP][36] ([Intel XE#2244]) +2 other tests skip
   [36]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-4/igt@kms_dsc@dsc-fractional-bpp.html

  * igt@kms_fbcon_fbt@psr-suspend:
    - shard-bmg:          NOTRUN -> [SKIP][37] ([Intel XE#776])
   [37]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-8/igt@kms_fbcon_fbt@psr-suspend.html

  * igt@kms_feature_discovery@chamelium:
    - shard-bmg:          NOTRUN -> [SKIP][38] ([Intel XE#2372])
   [38]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-6/igt@kms_feature_discovery@chamelium.html

  * igt@kms_flip@2x-flip-vs-dpms-off-vs-modeset:
    - shard-lnl:          NOTRUN -> [SKIP][39] ([Intel XE#1421])
   [39]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-7/igt@kms_flip@2x-flip-vs-dpms-off-vs-modeset.html

  * igt@kms_flip@flip-vs-expired-vblank@a-edp1:
    - shard-lnl:          [PASS][40] -> [FAIL][41] ([Intel XE#301]) +1 other test fail
   [40]: https://intel-gfx-ci.01.org/tree/intel-xe/IGT_8772/shard-lnl-4/igt@kms_flip@flip-vs-expired-vblank@a-edp1.html
   [41]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-4/igt@kms_flip@flip-vs-expired-vblank@a-edp1.html

  * igt@kms_flip_scaled_crc@flip-32bpp-xtile-to-64bpp-xtile-downscaling@pipe-a-default-mode:
    - shard-lnl:          NOTRUN -> [SKIP][42] ([Intel XE#1397]) +1 other test skip
   [42]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-7/igt@kms_flip_scaled_crc@flip-32bpp-xtile-to-64bpp-xtile-downscaling@pipe-a-default-mode.html

  * igt@kms_flip_scaled_crc@flip-32bpp-yftile-to-32bpp-yftileccs-upscaling:
    - shard-bmg:          NOTRUN -> [SKIP][43] ([Intel XE#7178]) +1 other test skip
   [43]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-7/igt@kms_flip_scaled_crc@flip-32bpp-yftile-to-32bpp-yftileccs-upscaling.html

  * igt@kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile-upscaling:
    - shard-lnl:          NOTRUN -> [SKIP][44] ([Intel XE#7178]) +1 other test skip
   [44]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-5/igt@kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile-upscaling.html

  * igt@kms_flip_scaled_crc@flip-64bpp-linear-to-32bpp-linear-downscaling:
    - shard-lnl:          NOTRUN -> [SKIP][45] ([Intel XE#1397] / [Intel XE#1745]) +1 other test skip
   [45]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-1/igt@kms_flip_scaled_crc@flip-64bpp-linear-to-32bpp-linear-downscaling.html

  * igt@kms_frontbuffer_tracking@drrs-1p-offscreen-pri-shrfb-draw-mmap-wc:
    - shard-lnl:          NOTRUN -> [SKIP][46] ([Intel XE#6312])
   [46]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-7/igt@kms_frontbuffer_tracking@drrs-1p-offscreen-pri-shrfb-draw-mmap-wc.html

  * igt@kms_frontbuffer_tracking@drrs-1p-primscrn-cur-indfb-draw-mmap-wc:
    - shard-lnl:          NOTRUN -> [SKIP][47] ([Intel XE#6312] / [Intel XE#651]) +6 other tests skip
   [47]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-5/igt@kms_frontbuffer_tracking@drrs-1p-primscrn-cur-indfb-draw-mmap-wc.html

  * igt@kms_frontbuffer_tracking@drrs-abgr161616f-draw-mmap-wc:
    - shard-bmg:          NOTRUN -> [SKIP][48] ([Intel XE#7061]) +3 other tests skip
   [48]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-8/igt@kms_frontbuffer_tracking@drrs-abgr161616f-draw-mmap-wc.html

  * igt@kms_frontbuffer_tracking@fbc-1p-primscrn-indfb-pgflip-blt:
    - shard-bmg:          NOTRUN -> [SKIP][49] ([Intel XE#4141]) +5 other tests skip
   [49]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-2/igt@kms_frontbuffer_tracking@fbc-1p-primscrn-indfb-pgflip-blt.html

  * igt@kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-spr-indfb-draw-mmap-wc:
    - shard-bmg:          NOTRUN -> [SKIP][50] ([Intel XE#2311]) +9 other tests skip
   [50]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-8/igt@kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-spr-indfb-draw-mmap-wc.html

  * igt@kms_frontbuffer_tracking@fbcpsr-argb161616f-draw-mmap-wc:
    - shard-lnl:          NOTRUN -> [SKIP][51] ([Intel XE#7061]) +4 other tests skip
   [51]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-8/igt@kms_frontbuffer_tracking@fbcpsr-argb161616f-draw-mmap-wc.html

  * igt@kms_frontbuffer_tracking@psr-2p-primscrn-indfb-plflip-blt:
    - shard-bmg:          NOTRUN -> [SKIP][52] ([Intel XE#2313]) +11 other tests skip
   [52]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-5/igt@kms_frontbuffer_tracking@psr-2p-primscrn-indfb-plflip-blt.html

  * igt@kms_frontbuffer_tracking@psr-2p-scndscrn-shrfb-plflip-blt:
    - shard-lnl:          NOTRUN -> [SKIP][53] ([Intel XE#656]) +23 other tests skip
   [53]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-1/igt@kms_frontbuffer_tracking@psr-2p-scndscrn-shrfb-plflip-blt.html

  * igt@kms_hdmi_inject@inject-audio:
    - shard-bmg:          [PASS][54] -> [SKIP][55] ([Intel XE#7308])
   [54]: https://intel-gfx-ci.01.org/tree/intel-xe/IGT_8772/shard-bmg-3/igt@kms_hdmi_inject@inject-audio.html
   [55]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-2/igt@kms_hdmi_inject@inject-audio.html

  * igt@kms_hdr@invalid-hdr:
    - shard-bmg:          [PASS][56] -> [SKIP][57] ([Intel XE#1503])
   [56]: https://intel-gfx-ci.01.org/tree/intel-xe/IGT_8772/shard-bmg-5/igt@kms_hdr@invalid-hdr.html
   [57]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-2/igt@kms_hdr@invalid-hdr.html

  * igt@kms_hdr@static-swap:
    - shard-lnl:          NOTRUN -> [SKIP][58] ([Intel XE#1503])
   [58]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-3/igt@kms_hdr@static-swap.html

  * igt@kms_joiner@invalid-modeset-ultra-joiner:
    - shard-lnl:          NOTRUN -> [SKIP][59] ([Intel XE#6900])
   [59]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-4/igt@kms_joiner@invalid-modeset-ultra-joiner.html

  * igt@kms_joiner@switch-modeset-ultra-joiner-big-joiner:
    - shard-bmg:          NOTRUN -> [SKIP][60] ([Intel XE#4090])
   [60]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-8/igt@kms_joiner@switch-modeset-ultra-joiner-big-joiner.html

  * igt@kms_plane@pixel-format-4-tiled-lnl-ccs-modifier-source-clamping:
    - shard-bmg:          NOTRUN -> [SKIP][61] ([Intel XE#7283]) +1 other test skip
   [61]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-1/igt@kms_plane@pixel-format-4-tiled-lnl-ccs-modifier-source-clamping.html

  * igt@kms_plane@pixel-format-4-tiled-mtl-rc-ccs-modifier:
    - shard-lnl:          NOTRUN -> [SKIP][62] ([Intel XE#7283])
   [62]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-2/igt@kms_plane@pixel-format-4-tiled-mtl-rc-ccs-modifier.html

  * igt@kms_plane_lowres@tiling-x@pipe-b-edp-1:
    - shard-lnl:          NOTRUN -> [SKIP][63] ([Intel XE#599]) +3 other tests skip
   [63]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-3/igt@kms_plane_lowres@tiling-x@pipe-b-edp-1.html

  * igt@kms_plane_scaling@planes-upscale-factor-0-25-downscale-factor-0-75:
    - shard-lnl:          NOTRUN -> [SKIP][64] ([Intel XE#2763] / [Intel XE#6886]) +7 other tests skip
   [64]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-2/igt@kms_plane_scaling@planes-upscale-factor-0-25-downscale-factor-0-75.html

  * igt@kms_pm_backlight@bad-brightness:
    - shard-bmg:          NOTRUN -> [SKIP][65] ([Intel XE#870])
   [65]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-4/igt@kms_pm_backlight@bad-brightness.html

  * igt@kms_pm_rpm@modeset-non-lpsp-stress-no-wait:
    - shard-lnl:          NOTRUN -> [SKIP][66] ([Intel XE#1439] / [Intel XE#3141]) +1 other test skip
   [66]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-5/igt@kms_pm_rpm@modeset-non-lpsp-stress-no-wait.html

  * igt@kms_psr2_sf@fbc-pr-cursor-plane-move-continuous-exceed-fully-sf:
    - shard-bmg:          NOTRUN -> [SKIP][67] ([Intel XE#1406] / [Intel XE#1489]) +4 other tests skip
   [67]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-8/igt@kms_psr2_sf@fbc-pr-cursor-plane-move-continuous-exceed-fully-sf.html

  * igt@kms_psr2_sf@fbc-psr2-primary-plane-update-sf-dmg-area:
    - shard-lnl:          NOTRUN -> [SKIP][68] ([Intel XE#1406] / [Intel XE#2893] / [Intel XE#4608]) +1 other test skip
   [68]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-2/igt@kms_psr2_sf@fbc-psr2-primary-plane-update-sf-dmg-area.html

  * igt@kms_psr2_sf@fbc-psr2-primary-plane-update-sf-dmg-area@pipe-b-edp-1:
    - shard-lnl:          NOTRUN -> [SKIP][69] ([Intel XE#1406] / [Intel XE#4608]) +3 other tests skip
   [69]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-2/igt@kms_psr2_sf@fbc-psr2-primary-plane-update-sf-dmg-area@pipe-b-edp-1.html

  * igt@kms_psr2_sf@pr-overlay-plane-move-continuous-sf:
    - shard-lnl:          NOTRUN -> [SKIP][70] ([Intel XE#1406] / [Intel XE#2893]) +2 other tests skip
   [70]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-4/igt@kms_psr2_sf@pr-overlay-plane-move-continuous-sf.html

  * igt@kms_psr2_su@page_flip-nv12:
    - shard-lnl:          NOTRUN -> [SKIP][71] ([Intel XE#1128] / [Intel XE#1406])
   [71]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-8/igt@kms_psr2_su@page_flip-nv12.html

  * igt@kms_psr@fbc-psr2-primary-page-flip@edp-1:
    - shard-lnl:          NOTRUN -> [SKIP][72] ([Intel XE#1406] / [Intel XE#4609])
   [72]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-2/igt@kms_psr@fbc-psr2-primary-page-flip@edp-1.html

  * igt@kms_psr@pr-sprite-plane-onoff:
    - shard-lnl:          NOTRUN -> [SKIP][73] ([Intel XE#1406]) +2 other tests skip
   [73]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-5/igt@kms_psr@pr-sprite-plane-onoff.html

  * igt@kms_psr@psr2-no-drrs:
    - shard-bmg:          NOTRUN -> [SKIP][74] ([Intel XE#1406] / [Intel XE#2234] / [Intel XE#2850]) +5 other tests skip
   [74]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-1/igt@kms_psr@psr2-no-drrs.html

  * igt@kms_rotation_crc@bad-tiling:
    - shard-lnl:          NOTRUN -> [SKIP][75] ([Intel XE#3414] / [Intel XE#3904])
   [75]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-2/igt@kms_rotation_crc@bad-tiling.html

  * igt@kms_rotation_crc@primary-yf-tiled-reflect-x-180:
    - shard-bmg:          NOTRUN -> [SKIP][76] ([Intel XE#2330])
   [76]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-3/igt@kms_rotation_crc@primary-yf-tiled-reflect-x-180.html

  * igt@kms_sharpness_filter@invalid-plane-with-filter:
    - shard-bmg:          NOTRUN -> [SKIP][77] ([Intel XE#6503])
   [77]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-7/igt@kms_sharpness_filter@invalid-plane-with-filter.html

  * igt@kms_vrr@flip-suspend:
    - shard-bmg:          NOTRUN -> [SKIP][78] ([Intel XE#1499])
   [78]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-3/igt@kms_vrr@flip-suspend.html

  * igt@kms_vrr@seamless-rr-switch-virtual@pipe-a-edp-1:
    - shard-lnl:          [PASS][79] -> [FAIL][80] ([Intel XE#2142]) +1 other test fail
   [79]: https://intel-gfx-ci.01.org/tree/intel-xe/IGT_8772/shard-lnl-4/igt@kms_vrr@seamless-rr-switch-virtual@pipe-a-edp-1.html
   [80]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-7/igt@kms_vrr@seamless-rr-switch-virtual@pipe-a-edp-1.html

  * igt@kms_vrr@seamless-rr-switch-vrr:
    - shard-lnl:          NOTRUN -> [SKIP][81] ([Intel XE#1499])
   [81]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-8/igt@kms_vrr@seamless-rr-switch-vrr.html

  * igt@xe_eudebug@discovery-race:
    - shard-lnl:          NOTRUN -> [SKIP][82] ([Intel XE#4837]) +3 other tests skip
   [82]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-2/igt@xe_eudebug@discovery-race.html

  * igt@xe_eudebug_online@pagefault-one-of-many:
    - shard-lnl:          NOTRUN -> [SKIP][83] ([Intel XE#6665])
   [83]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-4/igt@xe_eudebug_online@pagefault-one-of-many.html

  * igt@xe_eudebug_online@writes-caching-sram-bb-vram-target-vram:
    - shard-lnl:          NOTRUN -> [SKIP][84] ([Intel XE#4837] / [Intel XE#6665]) +1 other test skip
   [84]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-4/igt@xe_eudebug_online@writes-caching-sram-bb-vram-target-vram.html

  * igt@xe_eudebug_online@writes-caching-vram-bb-vram-target-sram:
    - shard-bmg:          NOTRUN -> [SKIP][85] ([Intel XE#4837] / [Intel XE#6665]) +1 other test skip
   [85]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-8/igt@xe_eudebug_online@writes-caching-vram-bb-vram-target-sram.html

  * igt@xe_eudebug_sriov@deny-sriov:
    - shard-lnl:          NOTRUN -> [SKIP][86] ([Intel XE#4518])
   [86]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-5/igt@xe_eudebug_sriov@deny-sriov.html

  * igt@xe_evict@evict-mixed-many-threads-small:
    - shard-bmg:          [PASS][87] -> [INCOMPLETE][88] ([Intel XE#6321]) +1 other test incomplete
   [87]: https://intel-gfx-ci.01.org/tree/intel-xe/IGT_8772/shard-bmg-9/igt@xe_evict@evict-mixed-many-threads-small.html
   [88]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-1/igt@xe_evict@evict-mixed-many-threads-small.html

  * igt@xe_evict@evict-threads-small-multi-queue:
    - shard-bmg:          NOTRUN -> [SKIP][89] ([Intel XE#7140]) +1 other test skip
   [89]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-8/igt@xe_evict@evict-threads-small-multi-queue.html

  * igt@xe_evict_ccs@evict-overcommit-parallel-nofree-samefd:
    - shard-lnl:          NOTRUN -> [SKIP][90] ([Intel XE#6540] / [Intel XE#688]) +5 other tests skip
   [90]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-1/igt@xe_evict_ccs@evict-overcommit-parallel-nofree-samefd.html

  * igt@xe_exec_balancer@once-cm-parallel-userptr-invalidate-race:
    - shard-lnl:          NOTRUN -> [SKIP][91] ([Intel XE#7482]) +10 other tests skip
   [91]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-4/igt@xe_exec_balancer@once-cm-parallel-userptr-invalidate-race.html

  * igt@xe_exec_basic@multigpu-many-execqueues-many-vm-null-defer-bind:
    - shard-bmg:          NOTRUN -> [SKIP][92] ([Intel XE#2322]) +2 other tests skip
   [92]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-3/igt@xe_exec_basic@multigpu-many-execqueues-many-vm-null-defer-bind.html

  * igt@xe_exec_basic@multigpu-no-exec-userptr-invalidate-race:
    - shard-lnl:          NOTRUN -> [SKIP][93] ([Intel XE#1392]) +4 other tests skip
   [93]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-8/igt@xe_exec_basic@multigpu-no-exec-userptr-invalidate-race.html

  * igt@xe_exec_fault_mode@many-execqueues-multi-queue-userptr:
    - shard-bmg:          NOTRUN -> [SKIP][94] ([Intel XE#7136]) +7 other tests skip
   [94]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-8/igt@xe_exec_fault_mode@many-execqueues-multi-queue-userptr.html

  * igt@xe_exec_fault_mode@many-multi-queue-userptr-invalidate:
    - shard-lnl:          NOTRUN -> [SKIP][95] ([Intel XE#7136]) +8 other tests skip
   [95]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-7/igt@xe_exec_fault_mode@many-multi-queue-userptr-invalidate.html

  * igt@xe_exec_multi_queue@few-execs-preempt-mode-userptr-invalidate:
    - shard-bmg:          NOTRUN -> [SKIP][96] ([Intel XE#6874]) +10 other tests skip
   [96]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-7/igt@xe_exec_multi_queue@few-execs-preempt-mode-userptr-invalidate.html

  * igt@xe_exec_multi_queue@max-queues-preempt-mode-dyn-priority-smem:
    - shard-lnl:          NOTRUN -> [SKIP][97] ([Intel XE#6874]) +16 other tests skip
   [97]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-1/igt@xe_exec_multi_queue@max-queues-preempt-mode-dyn-priority-smem.html

  * igt@xe_exec_sip_eudebug@breakpoint-writesip-nodebug:
    - shard-bmg:          NOTRUN -> [SKIP][98] ([Intel XE#4837]) +1 other test skip
   [98]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-6/igt@xe_exec_sip_eudebug@breakpoint-writesip-nodebug.html

  * igt@xe_exec_system_allocator@pat-index-madvise-pat-idx-wt-single-vma:
    - shard-lnl:          NOTRUN -> [SKIP][99] ([Intel XE#6196])
   [99]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-5/igt@xe_exec_system_allocator@pat-index-madvise-pat-idx-wt-single-vma.html

  * igt@xe_exec_threads@threads-many-queues:
    - shard-lnl:          NOTRUN -> [FAIL][100] ([Intel XE#7166])
   [100]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-8/igt@xe_exec_threads@threads-many-queues.html

  * igt@xe_exec_threads@threads-multi-queue-cm-fd-userptr:
    - shard-bmg:          NOTRUN -> [SKIP][101] ([Intel XE#7138]) +3 other tests skip
   [101]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-7/igt@xe_exec_threads@threads-multi-queue-cm-fd-userptr.html

  * igt@xe_exec_threads@threads-multi-queue-cm-fd-userptr-invalidate-race:
    - shard-lnl:          NOTRUN -> [SKIP][102] ([Intel XE#7138]) +7 other tests skip
   [102]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-1/igt@xe_exec_threads@threads-multi-queue-cm-fd-userptr-invalidate-race.html

  * igt@xe_mmap@pci-membarrier-bad-object:
    - shard-lnl:          NOTRUN -> [SKIP][103] ([Intel XE#5100] / [Intel XE#7322])
   [103]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-5/igt@xe_mmap@pci-membarrier-bad-object.html

  * igt@xe_mmap@vram:
    - shard-lnl:          NOTRUN -> [SKIP][104] ([Intel XE#1416])
   [104]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-8/igt@xe_mmap@vram.html

  * igt@xe_multigpu_svm@mgpu-coherency-fail-basic:
    - shard-bmg:          NOTRUN -> [SKIP][105] ([Intel XE#6964])
   [105]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-8/igt@xe_multigpu_svm@mgpu-coherency-fail-basic.html

  * igt@xe_multigpu_svm@mgpu-latency-basic:
    - shard-lnl:          NOTRUN -> [SKIP][106] ([Intel XE#6964])
   [106]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-2/igt@xe_multigpu_svm@mgpu-latency-basic.html

  * igt@xe_peer2peer@read:
    - shard-lnl:          NOTRUN -> [SKIP][107] ([Intel XE#1061] / [Intel XE#7326])
   [107]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-8/igt@xe_peer2peer@read.html

  * igt@xe_pm@d3cold-mmap-vram:
    - shard-lnl:          NOTRUN -> [SKIP][108] ([Intel XE#2284] / [Intel XE#366]) +1 other test skip
   [108]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-7/igt@xe_pm@d3cold-mmap-vram.html
    - shard-bmg:          NOTRUN -> [SKIP][109] ([Intel XE#2284])
   [109]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-3/igt@xe_pm@d3cold-mmap-vram.html

  * igt@xe_pm@s3-mocs:
    - shard-lnl:          NOTRUN -> [SKIP][110] ([Intel XE#584])
   [110]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-1/igt@xe_pm@s3-mocs.html

  * igt@xe_pmu@fn-engine-activity-load:
    - shard-lnl:          NOTRUN -> [SKIP][111] ([Intel XE#4650])
   [111]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-1/igt@xe_pmu@fn-engine-activity-load.html

  * igt@xe_query@multigpu-query-pxp-status:
    - shard-lnl:          NOTRUN -> [SKIP][112] ([Intel XE#944])
   [112]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-5/igt@xe_query@multigpu-query-pxp-status.html

  * igt@xe_sriov_scheduling@equal-throughput:
    - shard-lnl:          NOTRUN -> [SKIP][113] ([Intel XE#4351])
   [113]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-3/igt@xe_sriov_scheduling@equal-throughput.html

  * igt@xe_sriov_scheduling@equal-throughput@numvfs-random:
    - shard-bmg:          [PASS][114] -> [FAIL][115] ([Intel XE#5937]) +1 other test fail
   [114]: https://intel-gfx-ci.01.org/tree/intel-xe/IGT_8772/shard-bmg-3/igt@xe_sriov_scheduling@equal-throughput@numvfs-random.html
   [115]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-6/igt@xe_sriov_scheduling@equal-throughput@numvfs-random.html

  * igt@xe_survivability@runtime-survivability:
    - shard-lnl:          NOTRUN -> [SKIP][116] ([Intel XE#6529] / [Intel XE#7331])
   [116]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-lnl-3/igt@xe_survivability@runtime-survivability.html

  
#### Possible fixes ####

  * igt@kms_cursor_legacy@cursorb-vs-flipa-varying-size:
    - shard-bmg:          [DMESG-WARN][117] ([Intel XE#5354]) -> [PASS][118]
   [117]: https://intel-gfx-ci.01.org/tree/intel-xe/IGT_8772/shard-bmg-9/igt@kms_cursor_legacy@cursorb-vs-flipa-varying-size.html
   [118]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-8/igt@kms_cursor_legacy@cursorb-vs-flipa-varying-size.html

  * igt@kms_flip@flip-vs-expired-vblank-interruptible@c-dp2:
    - shard-bmg:          [FAIL][119] -> [PASS][120] +1 other test pass
   [119]: https://intel-gfx-ci.01.org/tree/intel-xe/IGT_8772/shard-bmg-9/igt@kms_flip@flip-vs-expired-vblank-interruptible@c-dp2.html
   [120]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-2/igt@kms_flip@flip-vs-expired-vblank-interruptible@c-dp2.html

  * igt@kms_flip@flip-vs-suspend-interruptible:
    - shard-bmg:          [INCOMPLETE][121] ([Intel XE#2049] / [Intel XE#2597]) -> [PASS][122] +1 other test pass
   [121]: https://intel-gfx-ci.01.org/tree/intel-xe/IGT_8772/shard-bmg-4/igt@kms_flip@flip-vs-suspend-interruptible.html
   [122]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-1/igt@kms_flip@flip-vs-suspend-interruptible.html

  * igt@kms_flip_scaled_crc@flip-64bpp-xtile-to-16bpp-xtile-upscaling:
    - shard-bmg:          [DMESG-FAIL][123] -> [PASS][124] +1 other test pass
   [123]: https://intel-gfx-ci.01.org/tree/intel-xe/IGT_8772/shard-bmg-2/igt@kms_flip_scaled_crc@flip-64bpp-xtile-to-16bpp-xtile-upscaling.html
   [124]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-6/igt@kms_flip_scaled_crc@flip-64bpp-xtile-to-16bpp-xtile-upscaling.html

  * igt@xe_exec_system_allocator@threads-many-stride-mmap-new:
    - shard-bmg:          [INCOMPLETE][125] ([Intel XE#2594]) -> [PASS][126]
   [125]: https://intel-gfx-ci.01.org/tree/intel-xe/IGT_8772/shard-bmg-8/igt@xe_exec_system_allocator@threads-many-stride-mmap-new.html
   [126]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-1/igt@xe_exec_system_allocator@threads-many-stride-mmap-new.html

  * igt@xe_pm@s4-multiple-execs:
    - shard-bmg:          [INCOMPLETE][127] -> [PASS][128]
   [127]: https://intel-gfx-ci.01.org/tree/intel-xe/IGT_8772/shard-bmg-2/igt@xe_pm@s4-multiple-execs.html
   [128]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-5/igt@xe_pm@s4-multiple-execs.html

  * igt@xe_pm_residency@aspm_link_residency:
    - shard-bmg:          [SKIP][129] ([Intel XE#7258]) -> [PASS][130]
   [129]: https://intel-gfx-ci.01.org/tree/intel-xe/IGT_8772/shard-bmg-5/igt@xe_pm_residency@aspm_link_residency.html
   [130]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-3/igt@xe_pm_residency@aspm_link_residency.html

  * igt@xe_sriov_flr@flr-each-isolation:
    - shard-bmg:          [FAIL][131] ([Intel XE#6569]) -> [PASS][132]
   [131]: https://intel-gfx-ci.01.org/tree/intel-xe/IGT_8772/shard-bmg-9/igt@xe_sriov_flr@flr-each-isolation.html
   [132]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-9/igt@xe_sriov_flr@flr-each-isolation.html

  * igt@xe_sriov_vram@vf-access-beyond:
    - shard-bmg:          [FAIL][133] ([Intel XE#5937]) -> [PASS][134] +1 other test pass
   [133]: https://intel-gfx-ci.01.org/tree/intel-xe/IGT_8772/shard-bmg-7/igt@xe_sriov_vram@vf-access-beyond.html
   [134]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-7/igt@xe_sriov_vram@vf-access-beyond.html

  
#### Warnings ####

  * igt@kms_tiled_display@basic-test-pattern:
    - shard-bmg:          [FAIL][135] ([Intel XE#1729]) -> [SKIP][136] ([Intel XE#2426])
   [135]: https://intel-gfx-ci.01.org/tree/intel-xe/IGT_8772/shard-bmg-6/igt@kms_tiled_display@basic-test-pattern.html
   [136]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14620/shard-bmg-8/igt@kms_tiled_display@basic-test-pattern.html

  
  {name}: This element is suppressed. This means it is ignored when computing
          the status of the difference (SUCCESS, WARNING, or FAILURE).

  [Intel XE#1061]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1061
  [Intel XE#1124]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1124
  [Intel XE#1128]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1128
  [Intel XE#1178]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1178
  [Intel XE#1392]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1392
  [Intel XE#1397]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1397
  [Intel XE#1406]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1406
  [Intel XE#1407]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1407
  [Intel XE#1416]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1416
  [Intel XE#1421]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1421
  [Intel XE#1424]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1424
  [Intel XE#1428]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1428
  [Intel XE#1439]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1439
  [Intel XE#1489]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1489
  [Intel XE#1499]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1499
  [Intel XE#1503]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1503
  [Intel XE#1729]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1729
  [Intel XE#1745]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1745
  [Intel XE#2049]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2049
  [Intel XE#2142]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2142
  [Intel XE#2191]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2191
  [Intel XE#2234]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2234
  [Intel XE#2244]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2244
  [Intel XE#2252]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2252
  [Intel XE#2284]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2284
  [Intel XE#2311]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2311
  [Intel XE#2313]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2313
  [Intel XE#2314]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2314
  [Intel XE#2320]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2320
  [Intel XE#2321]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2321
  [Intel XE#2322]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2322
  [Intel XE#2325]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2325
  [Intel XE#2327]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2327
  [Intel XE#2330]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2330
  [Intel XE#2341]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2341
  [Intel XE#2372]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2372
  [Intel XE#2426]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2426
  [Intel XE#2594]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2594
  [Intel XE#2597]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2597
  [Intel XE#2652]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2652
  [Intel XE#2763]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2763
  [Intel XE#2850]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2850
  [Intel XE#2887]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2887
  [Intel XE#2893]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2893
  [Intel XE#2894]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2894
  [Intel XE#301]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/301
  [Intel XE#306]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/306
  [Intel XE#309]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/309
  [Intel XE#3141]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/3141
  [Intel XE#3278]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/3278
  [Intel XE#3304]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/3304
  [Intel XE#3414]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/3414
  [Intel XE#366]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/366
  [Intel XE#373]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/373
  [Intel XE#3904]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/3904
  [Intel XE#4090]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4090
  [Intel XE#4141]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4141
  [Intel XE#4351]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4351
  [Intel XE#4518]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4518
  [Intel XE#4608]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4608
  [Intel XE#4609]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4609
  [Intel XE#4650]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4650
  [Intel XE#4837]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4837
  [Intel XE#5100]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/5100
  [Intel XE#5354]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/5354
  [Intel XE#584]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/584
  [Intel XE#5937]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/5937
  [Intel XE#599]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/599
  [Intel XE#5993]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/5993
  [Intel XE#6196]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6196
  [Intel XE#6312]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6312
  [Intel XE#6321]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6321
  [Intel XE#6503]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6503
  [Intel XE#651]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/651
  [Intel XE#6529]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6529
  [Intel XE#6540]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6540
  [Intel XE#656]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/656
  [Intel XE#6569]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6569
  [Intel XE#6665]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6665
  [Intel XE#6705]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6705
  [Intel XE#6874]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6874
  [Intel XE#688]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/688
  [Intel XE#6886]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6886
  [Intel XE#6900]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6900
  [Intel XE#6964]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6964
  [Intel XE#6973]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6973
  [Intel XE#6974]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6974
  [Intel XE#7059]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/7059
  [Intel XE#7061]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/7061
  [Intel XE#7136]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/7136
  [Intel XE#7138]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/7138
  [Intel XE#7140]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/7140
  [Intel XE#7166]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/7166
  [Intel XE#7178]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/7178
  [Intel XE#7258]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/7258
  [Intel XE#7283]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/7283
  [Intel XE#7305]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/7305
  [Intel XE#7308]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/7308
  [Intel XE#7322]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/7322
  [Intel XE#7326]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/7326
  [Intel XE#7331]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/7331
  [Intel XE#7482]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/7482
  [Intel XE#776]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/776
  [Intel XE#870]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/870
  [Intel XE#944]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/944


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

  * IGT: IGT_8772 -> IGTPW_14620
  * Linux: xe-4617-3b1923ab37ecd72e1405c7b8d3b1d9e1f3e59f86 -> xe-4620-f0ec6252eb6d9a4f0cb5a437f5c21fec16d0a440

  IGTPW_14620: 14620
  IGT_8772: 8772
  xe-4617-3b1923ab37ecd72e1405c7b8d3b1d9e1f3e59f86: 3b1923ab37ecd72e1405c7b8d3b1d9e1f3e59f86
  xe-4620-f0ec6252eb6d9a4f0cb5a437f5c21fec16d0a440: f0ec6252eb6d9a4f0cb5a437f5c21fec16d0a440

== Logs ==

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

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

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

* ✗ i915.CI.Full: failure for add test to validate dock/undock and switch (rev3)
  2026-02-25 21:28 [PATCH i-g-t 0/6] add test to validate dock/undock and switch Kunal Joshi
                   ` (8 preceding siblings ...)
  2026-02-26  6:52 ` ✗ Xe.CI.FULL: failure " Patchwork
@ 2026-02-26  7:45 ` Patchwork
  9 siblings, 0 replies; 25+ messages in thread
From: Patchwork @ 2026-02-26  7:45 UTC (permalink / raw)
  To: Kunal Joshi; +Cc: igt-dev

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

== Series Details ==

Series: add test to validate dock/undock and switch (rev3)
URL   : https://patchwork.freedesktop.org/series/149299/
State : failure

== Summary ==

CI Bug Log - changes from CI_DRM_18050_full -> IGTPW_14620_full
====================================================

Summary
-------

  **FAILURE**

  Serious unknown changes coming with IGTPW_14620_full absolutely need to be
  verified manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in IGTPW_14620_full, 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_14620/index.html

Participating hosts (9 -> 9)
------------------------------

  No changes in participating hosts

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

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

### IGT changes ###

#### Possible regressions ####

  * igt@gem_exec_big@single:
    - shard-dg2:          [PASS][1] -> [CRASH][2]
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-3/igt@gem_exec_big@single.html
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-7/igt@gem_exec_big@single.html

  * igt@gem_mmap_gtt@hang:
    - shard-snb:          [PASS][3] -> [INCOMPLETE][4]
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-snb7/igt@gem_mmap_gtt@hang.html
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-snb5/igt@gem_mmap_gtt@hang.html

  * igt@gem_workarounds@suspend-resume-fd:
    - shard-tglu:         [PASS][5] -> [ABORT][6]
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-tglu-8/igt@gem_workarounds@suspend-resume-fd.html
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-9/igt@gem_workarounds@suspend-resume-fd.html

  * igt@i915_drm_fdinfo@memory-info-idle:
    - shard-dg2:          [PASS][7] -> [SKIP][8] +21 other tests skip
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-1/igt@i915_drm_fdinfo@memory-info-idle.html
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@i915_drm_fdinfo@memory-info-idle.html

  * igt@i915_selftest@live@objects:
    - shard-dg2:          NOTRUN -> [FAIL][9] +37 other tests fail
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@i915_selftest@live@objects.html

  * {igt@kms_usb4_switch@dock-during-suspend} (NEW):
    - shard-dg1:          NOTRUN -> [SKIP][10] +5 other tests skip
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-16/igt@kms_usb4_switch@dock-during-suspend.html

  * {igt@kms_usb4_switch@dock-undock} (NEW):
    - shard-tglu:         NOTRUN -> [SKIP][11] +6 other tests skip
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-5/igt@kms_usb4_switch@dock-undock.html
    - shard-mtlp:         NOTRUN -> [SKIP][12] +6 other tests skip
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-mtlp-6/igt@kms_usb4_switch@dock-undock.html

  * {igt@kms_usb4_switch@switch} (NEW):
    - shard-rkl:          NOTRUN -> [SKIP][13] +5 other tests skip
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-8/igt@kms_usb4_switch@switch.html

  * igt@perf_pmu@module-unload:
    - shard-tglu-1:       NOTRUN -> [ABORT][14]
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-1/igt@perf_pmu@module-unload.html

  * igt@perf_pmu@most-busy-idle-check-all:
    - shard-dg2:          NOTRUN -> [SKIP][15] +14 other tests skip
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@perf_pmu@most-busy-idle-check-all.html

  
#### Warnings ####

  * igt@i915_drm_fdinfo@virtual-busy:
    - shard-dg2:          [SKIP][16] ([i915#14118]) -> [SKIP][17]
   [16]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-5/igt@i915_drm_fdinfo@virtual-busy.html
   [17]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@i915_drm_fdinfo@virtual-busy.html

  * igt@kms_pm_rpm@fences-dpms:
    - shard-dg2:          [SKIP][18] ([i915#4077]) -> [SKIP][19]
   [18]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-1/igt@kms_pm_rpm@fences-dpms.html
   [19]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_pm_rpm@fences-dpms.html

  * igt@perf@non-zero-reason:
    - shard-dg2:          [FAIL][20] ([i915#9100]) -> [SKIP][21]
   [20]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-1/igt@perf@non-zero-reason.html
   [21]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@perf@non-zero-reason.html

  * igt@perf_pmu@busy-double-start:
    - shard-dg2:          [FAIL][22] ([i915#4349]) -> [SKIP][23]
   [22]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-7/igt@perf_pmu@busy-double-start.html
   [23]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@perf_pmu@busy-double-start.html

  * igt@perf_pmu@module-unload:
    - shard-dg1:          [ABORT][24] ([i915#13029]) -> [ABORT][25]
   [24]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg1-12/igt@perf_pmu@module-unload.html
   [25]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-14/igt@perf_pmu@module-unload.html

  
New tests
---------

  New tests have been introduced between CI_DRM_18050_full and IGTPW_14620_full:

### New IGT tests (53) ###

  * igt@i915_pm_rps@extended-pageflip-hang-oldfb:
    - Statuses :
    - Exec time: [None] s

  * igt@kms_ccs@bad-aux-stride-y-tiled-gen12-rc-ccs-cc@pipe-a-hdmi-a-4:
    - Statuses : 1 pass(s)
    - Exec time: [0.00] s

  * igt@kms_ccs@bad-aux-stride-y-tiled-gen12-rc-ccs-cc@pipe-b-hdmi-a-4:
    - Statuses : 1 pass(s)
    - Exec time: [0.00] s

  * igt@kms_ccs@bad-aux-stride-y-tiled-gen12-rc-ccs-cc@pipe-c-hdmi-a-4:
    - Statuses : 1 pass(s)
    - Exec time: [0.00] s

  * igt@kms_ccs@bad-aux-stride-y-tiled-gen12-rc-ccs-cc@pipe-d-hdmi-a-4:
    - Statuses : 1 pass(s)
    - Exec time: [0.00] s

  * igt@kms_ccs@bad-aux-stride-yf-tiled-ccs@pipe-c-hdmi-a-2:
    - Statuses : 1 skip(s)
    - Exec time: [0.0] s

  * igt@kms_ccs@bad-pixel-format-4-tiled-mtl-mc-ccs@pipe-c-hdmi-a-2:
    - Statuses : 1 skip(s)
    - Exec time: [0.0] s

  * igt@kms_ccs@bad-rotation-90-4-tiled-mtl-rc-ccs-cc@pipe-c-hdmi-a-2:
    - Statuses : 1 skip(s)
    - Exec time: [0.0] s

  * igt@kms_ccs@bad-rotation-90-4-tiled-mtl-rc-ccs@pipe-a-hdmi-a-3:
    - Statuses : 2 skip(s)
    - Exec time: [0.0] s

  * igt@kms_ccs@bad-rotation-90-4-tiled-mtl-rc-ccs@pipe-b-hdmi-a-3:
    - Statuses : 2 skip(s)
    - Exec time: [0.0] s

  * igt@kms_ccs@bad-rotation-90-4-tiled-mtl-rc-ccs@pipe-c-hdmi-a-3:
    - Statuses : 2 skip(s)
    - Exec time: [0.0] s

  * igt@kms_ccs@bad-rotation-90-4-tiled-mtl-rc-ccs@pipe-d-hdmi-a-3:
    - Statuses : 2 skip(s)
    - Exec time: [0.0] s

  * igt@kms_ccs@bad-rotation-90-yf-tiled-ccs@pipe-a-hdmi-a-1:
    - Statuses : 1 skip(s)
    - Exec time: [0.0] s

  * igt@kms_ccs@bad-rotation-90-yf-tiled-ccs@pipe-a-hdmi-a-2:
    - Statuses : 1 skip(s)
    - Exec time: [0.0] s

  * igt@kms_ccs@bad-rotation-90-yf-tiled-ccs@pipe-a-hdmi-a-4:
    - Statuses : 1 skip(s)
    - Exec time: [0.0] s

  * igt@kms_ccs@bad-rotation-90-yf-tiled-ccs@pipe-b-hdmi-a-1:
    - Statuses : 1 skip(s)
    - Exec time: [0.0] s

  * igt@kms_ccs@bad-rotation-90-yf-tiled-ccs@pipe-b-hdmi-a-2:
    - Statuses : 1 skip(s)
    - Exec time: [0.0] s

  * igt@kms_ccs@bad-rotation-90-yf-tiled-ccs@pipe-b-hdmi-a-4:
    - Statuses : 1 skip(s)
    - Exec time: [0.0] s

  * igt@kms_ccs@bad-rotation-90-yf-tiled-ccs@pipe-c-hdmi-a-1:
    - Statuses : 1 skip(s)
    - Exec time: [0.0] s

  * igt@kms_ccs@bad-rotation-90-yf-tiled-ccs@pipe-c-hdmi-a-2:
    - Statuses : 1 skip(s)
    - Exec time: [0.0] s

  * igt@kms_ccs@bad-rotation-90-yf-tiled-ccs@pipe-c-hdmi-a-4:
    - Statuses : 1 skip(s)
    - Exec time: [0.0] s

  * igt@kms_ccs@bad-rotation-90-yf-tiled-ccs@pipe-d-hdmi-a-1:
    - Statuses : 1 skip(s)
    - Exec time: [0.0] s

  * igt@kms_ccs@bad-rotation-90-yf-tiled-ccs@pipe-d-hdmi-a-4:
    - Statuses : 1 skip(s)
    - Exec time: [0.0] s

  * igt@kms_ccs@ccs-on-another-bo-y-tiled-gen12-rc-ccs@pipe-a-hdmi-a-2:
    - Statuses : 1 pass(s)
    - Exec time: [0.00] s

  * igt@kms_ccs@ccs-on-another-bo-y-tiled-gen12-rc-ccs@pipe-a-hdmi-a-4:
    - Statuses : 1 pass(s)
    - Exec time: [0.00] s

  * igt@kms_ccs@ccs-on-another-bo-y-tiled-gen12-rc-ccs@pipe-b-hdmi-a-2:
    - Statuses : 1 pass(s)
    - Exec time: [0.00] s

  * igt@kms_ccs@ccs-on-another-bo-y-tiled-gen12-rc-ccs@pipe-b-hdmi-a-4:
    - Statuses : 1 pass(s)
    - Exec time: [0.00] s

  * igt@kms_ccs@ccs-on-another-bo-y-tiled-gen12-rc-ccs@pipe-c-hdmi-a-2:
    - Statuses : 1 pass(s)
    - Exec time: [0.00] s

  * igt@kms_ccs@ccs-on-another-bo-y-tiled-gen12-rc-ccs@pipe-c-hdmi-a-4:
    - Statuses : 1 pass(s)
    - Exec time: [0.00] s

  * igt@kms_ccs@ccs-on-another-bo-y-tiled-gen12-rc-ccs@pipe-d-hdmi-a-4:
    - Statuses : 1 pass(s)
    - Exec time: [0.00] s

  * igt@kms_ccs@crc-primary-basic-4-tiled-dg2-rc-ccs@pipe-c-hdmi-a-2:
    - Statuses : 1 skip(s)
    - Exec time: [0.00] s

  * igt@kms_ccs@crc-primary-rotation-180-4-tiled-mtl-rc-ccs@pipe-a-hdmi-a-3:
    - Statuses : 2 skip(s)
    - Exec time: [0.00] s

  * igt@kms_ccs@crc-primary-rotation-180-4-tiled-mtl-rc-ccs@pipe-b-hdmi-a-3:
    - Statuses : 2 skip(s)
    - Exec time: [0.00] s

  * igt@kms_ccs@crc-primary-rotation-180-4-tiled-mtl-rc-ccs@pipe-c-hdmi-a-3:
    - Statuses : 2 skip(s)
    - Exec time: [0.00] s

  * igt@kms_ccs@crc-primary-rotation-180-4-tiled-mtl-rc-ccs@pipe-d-hdmi-a-3:
    - Statuses : 2 skip(s)
    - Exec time: [0.00] s

  * igt@kms_ccs@crc-sprite-planes-basic-4-tiled-dg2-rc-ccs@pipe-c-hdmi-a-2:
    - Statuses : 2 skip(s)
    - Exec time: [0.00, 0.01] s

  * igt@kms_ccs@crc-sprite-planes-basic-y-tiled-gen12-rc-ccs@pipe-a-hdmi-a-3:
    - Statuses : 1 skip(s)
    - Exec time: [0.00] s

  * igt@kms_ccs@crc-sprite-planes-basic-y-tiled-gen12-rc-ccs@pipe-a-hdmi-a-4:
    - Statuses : 1 pass(s)
    - Exec time: [2.44] s

  * igt@kms_ccs@crc-sprite-planes-basic-y-tiled-gen12-rc-ccs@pipe-b-hdmi-a-3:
    - Statuses : 1 skip(s)
    - Exec time: [0.00] s

  * igt@kms_ccs@crc-sprite-planes-basic-y-tiled-gen12-rc-ccs@pipe-b-hdmi-a-4:
    - Statuses : 1 pass(s)
    - Exec time: [0.92] s

  * igt@kms_ccs@crc-sprite-planes-basic-y-tiled-gen12-rc-ccs@pipe-c-hdmi-a-3:
    - Statuses : 1 skip(s)
    - Exec time: [0.00] s

  * igt@kms_ccs@crc-sprite-planes-basic-y-tiled-gen12-rc-ccs@pipe-c-hdmi-a-4:
    - Statuses : 1 pass(s)
    - Exec time: [0.90] s

  * igt@kms_ccs@crc-sprite-planes-basic-y-tiled-gen12-rc-ccs@pipe-d-hdmi-a-3:
    - Statuses : 1 skip(s)
    - Exec time: [0.00] s

  * igt@kms_ccs@crc-sprite-planes-basic-y-tiled-gen12-rc-ccs@pipe-d-hdmi-a-4:
    - Statuses : 1 pass(s)
    - Exec time: [0.92] s

  * igt@kms_ccs@random-ccs-data-4-tiled-dg2-mc-ccs@pipe-c-hdmi-a-2:
    - Statuses : 1 skip(s)
    - Exec time: [0.0] s

  * igt@kms_feature_discovery@usb4-switch:
    - Statuses : 7 skip(s)
    - Exec time: [0.00, 0.01] s

  * igt@kms_usb4_switch@dock-during-suspend:
    - Statuses : 5 skip(s)
    - Exec time: [0.0] s

  * igt@kms_usb4_switch@dock-undock:
    - Statuses : 4 skip(s)
    - Exec time: [0.0] s

  * igt@kms_usb4_switch@dock-undock-sr:
    - Statuses : 1 skip(s)
    - Exec time: [0.0] s

  * igt@kms_usb4_switch@switch:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@kms_usb4_switch@switch-during-suspend:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@kms_usb4_switch@switch-sr:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@kms_usb4_switch@undock-during-suspend:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  

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

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

### IGT changes ###

#### Issues hit ####

  * igt@api_intel_bb@blit-reloc-purge-cache:
    - shard-dg2:          NOTRUN -> [SKIP][26] ([i915#8411]) +1 other test skip
   [26]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-8/igt@api_intel_bb@blit-reloc-purge-cache.html

  * igt@api_intel_bb@crc32:
    - shard-tglu:         NOTRUN -> [SKIP][27] ([i915#6230])
   [27]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-9/igt@api_intel_bb@crc32.html

  * igt@api_intel_bb@object-reloc-keep-cache:
    - shard-rkl:          NOTRUN -> [SKIP][28] ([i915#8411])
   [28]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-5/igt@api_intel_bb@object-reloc-keep-cache.html

  * igt@device_reset@unbind-cold-reset-rebind:
    - shard-dg2:          NOTRUN -> [SKIP][29] ([i915#11078])
   [29]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-4/igt@device_reset@unbind-cold-reset-rebind.html

  * igt@drm_buddy@drm_buddy:
    - shard-dg2:          NOTRUN -> [SKIP][30] ([i915#15678])
   [30]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-4/igt@drm_buddy@drm_buddy.html

  * igt@fbdev@nullptr:
    - shard-dg2:          [PASS][31] -> [SKIP][32] ([i915#2582])
   [31]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-3/igt@fbdev@nullptr.html
   [32]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@fbdev@nullptr.html

  * igt@gem_basic@multigpu-create-close:
    - shard-dg1:          NOTRUN -> [SKIP][33] ([i915#7697]) +1 other test skip
   [33]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-18/igt@gem_basic@multigpu-create-close.html

  * igt@gem_busy@semaphore:
    - shard-dg2:          NOTRUN -> [SKIP][34] ([i915#3936])
   [34]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-7/igt@gem_busy@semaphore.html

  * igt@gem_ccs@ctrl-surf-copy-new-ctx:
    - shard-rkl:          NOTRUN -> [SKIP][35] ([i915#9323])
   [35]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-7/igt@gem_ccs@ctrl-surf-copy-new-ctx.html

  * igt@gem_create@create-ext-cpu-access-big:
    - shard-tglu:         NOTRUN -> [SKIP][36] ([i915#6335])
   [36]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-4/igt@gem_create@create-ext-cpu-access-big.html
    - shard-dg2:          NOTRUN -> [FAIL][37] ([i915#15454])
   [37]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-7/igt@gem_create@create-ext-cpu-access-big.html

  * igt@gem_create@create-ext-set-pat:
    - shard-rkl:          NOTRUN -> [SKIP][38] ([i915#8562])
   [38]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-2/igt@gem_create@create-ext-set-pat.html
    - shard-dg1:          NOTRUN -> [SKIP][39] ([i915#8562])
   [39]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-14/igt@gem_create@create-ext-set-pat.html

  * igt@gem_ctx_engines@execute-allforone:
    - shard-dg2:          [PASS][40] -> [SKIP][41] ([i915#15689] / [i915#2575]) +90 other tests skip
   [40]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-7/igt@gem_ctx_engines@execute-allforone.html
   [41]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@gem_ctx_engines@execute-allforone.html

  * igt@gem_ctx_persistence@engines-hostile:
    - shard-snb:          NOTRUN -> [SKIP][42] ([i915#1099])
   [42]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-snb6/igt@gem_ctx_persistence@engines-hostile.html

  * igt@gem_ctx_persistence@heartbeat-hostile:
    - shard-dg2:          NOTRUN -> [SKIP][43] ([i915#8555]) +2 other tests skip
   [43]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-5/igt@gem_ctx_persistence@heartbeat-hostile.html
    - shard-dg1:          NOTRUN -> [SKIP][44] ([i915#8555]) +1 other test skip
   [44]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-12/igt@gem_ctx_persistence@heartbeat-hostile.html

  * igt@gem_ctx_sseu@engines:
    - shard-tglu:         NOTRUN -> [SKIP][45] ([i915#280])
   [45]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-3/igt@gem_ctx_sseu@engines.html

  * igt@gem_ctx_sseu@invalid-sseu:
    - shard-dg1:          NOTRUN -> [SKIP][46] ([i915#280])
   [46]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-16/igt@gem_ctx_sseu@invalid-sseu.html

  * igt@gem_eio@hibernate:
    - shard-rkl:          [PASS][47] -> [ABORT][48] ([i915#7975])
   [47]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-5/igt@gem_eio@hibernate.html
   [48]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-1/igt@gem_eio@hibernate.html

  * igt@gem_eio@kms:
    - shard-tglu:         [PASS][49] -> [DMESG-WARN][50] ([i915#13363])
   [49]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-tglu-2/igt@gem_eio@kms.html
   [50]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-6/igt@gem_eio@kms.html

  * igt@gem_exec_balancer@hog:
    - shard-dg1:          NOTRUN -> [SKIP][51] ([i915#4812]) +1 other test skip
   [51]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-14/igt@gem_exec_balancer@hog.html
    - shard-mtlp:         NOTRUN -> [SKIP][52] ([i915#4812])
   [52]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-mtlp-8/igt@gem_exec_balancer@hog.html

  * igt@gem_exec_balancer@invalid-bonds:
    - shard-dg1:          NOTRUN -> [SKIP][53] ([i915#4036])
   [53]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-18/igt@gem_exec_balancer@invalid-bonds.html

  * igt@gem_exec_balancer@parallel:
    - shard-tglu:         NOTRUN -> [SKIP][54] ([i915#4525]) +1 other test skip
   [54]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-10/igt@gem_exec_balancer@parallel.html

  * igt@gem_exec_balancer@parallel-keep-in-fence:
    - shard-rkl:          NOTRUN -> [SKIP][55] ([i915#4525])
   [55]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-2/igt@gem_exec_balancer@parallel-keep-in-fence.html

  * igt@gem_exec_fence@submit3:
    - shard-dg2:          NOTRUN -> [SKIP][56] ([i915#4812]) +1 other test skip
   [56]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-3/igt@gem_exec_fence@submit3.html

  * igt@gem_exec_fence@syncobj-stationary-timeline-chain-engines:
    - shard-dg2:          NOTRUN -> [SKIP][57] ([i915#15689] / [i915#2575]) +52 other tests skip
   [57]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@gem_exec_fence@syncobj-stationary-timeline-chain-engines.html

  * igt@gem_exec_flush@basic-batch-kernel-default-uc:
    - shard-dg1:          NOTRUN -> [SKIP][58] ([i915#3539] / [i915#4852]) +2 other tests skip
   [58]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-13/igt@gem_exec_flush@basic-batch-kernel-default-uc.html

  * igt@gem_exec_flush@basic-uc-prw-default:
    - shard-dg2:          NOTRUN -> [SKIP][59] ([i915#3539])
   [59]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-7/igt@gem_exec_flush@basic-uc-prw-default.html

  * igt@gem_exec_flush@basic-uc-set-default:
    - shard-dg1:          NOTRUN -> [SKIP][60] ([i915#3539])
   [60]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-17/igt@gem_exec_flush@basic-uc-set-default.html

  * igt@gem_exec_flush@basic-wb-pro-default:
    - shard-dg2:          NOTRUN -> [SKIP][61] ([i915#3539] / [i915#4852]) +1 other test skip
   [61]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-1/igt@gem_exec_flush@basic-wb-pro-default.html

  * igt@gem_exec_reloc@basic-gtt-read:
    - shard-dg2:          NOTRUN -> [SKIP][62] ([i915#3281]) +6 other tests skip
   [62]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-8/igt@gem_exec_reloc@basic-gtt-read.html

  * igt@gem_exec_reloc@basic-wc-read:
    - shard-dg1:          NOTRUN -> [SKIP][63] ([i915#3281]) +18 other tests skip
   [63]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-12/igt@gem_exec_reloc@basic-wc-read.html

  * igt@gem_exec_reloc@basic-wc-read-noreloc:
    - shard-rkl:          NOTRUN -> [SKIP][64] ([i915#3281]) +9 other tests skip
   [64]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-7/igt@gem_exec_reloc@basic-wc-read-noreloc.html

  * igt@gem_exec_reloc@basic-write-wc:
    - shard-mtlp:         NOTRUN -> [SKIP][65] ([i915#3281]) +2 other tests skip
   [65]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-mtlp-8/igt@gem_exec_reloc@basic-write-wc.html

  * igt@gem_fence_thrash@bo-write-verify-none:
    - shard-dg1:          NOTRUN -> [SKIP][66] ([i915#4860])
   [66]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-13/igt@gem_fence_thrash@bo-write-verify-none.html

  * igt@gem_huc_copy@huc-copy:
    - shard-tglu-1:       NOTRUN -> [SKIP][67] ([i915#2190])
   [67]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-1/igt@gem_huc_copy@huc-copy.html
    - shard-glk:          NOTRUN -> [SKIP][68] ([i915#2190])
   [68]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-glk5/igt@gem_huc_copy@huc-copy.html

  * igt@gem_lmem_swapping@parallel-random-engines:
    - shard-tglu-1:       NOTRUN -> [SKIP][69] ([i915#4613])
   [69]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-1/igt@gem_lmem_swapping@parallel-random-engines.html

  * igt@gem_lmem_swapping@parallel-random-verify:
    - shard-rkl:          NOTRUN -> [SKIP][70] ([i915#4613]) +1 other test skip
   [70]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-3/igt@gem_lmem_swapping@parallel-random-verify.html

  * igt@gem_lmem_swapping@parallel-random-verify-ccs:
    - shard-glk:          NOTRUN -> [SKIP][71] ([i915#4613]) +3 other tests skip
   [71]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-glk5/igt@gem_lmem_swapping@parallel-random-verify-ccs.html

  * igt@gem_lmem_swapping@smem-oom:
    - shard-dg1:          NOTRUN -> [FAIL][72] ([i915#15734])
   [72]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-12/igt@gem_lmem_swapping@smem-oom.html

  * igt@gem_lmem_swapping@smem-oom@lmem0:
    - shard-dg1:          NOTRUN -> [CRASH][73] ([i915#5493])
   [73]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-12/igt@gem_lmem_swapping@smem-oom@lmem0.html

  * igt@gem_lmem_swapping@verify-ccs:
    - shard-tglu:         NOTRUN -> [SKIP][74] ([i915#4613]) +3 other tests skip
   [74]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-3/igt@gem_lmem_swapping@verify-ccs.html

  * igt@gem_lmem_swapping@verify-random-ccs:
    - shard-dg1:          NOTRUN -> [SKIP][75] ([i915#12193]) +1 other test skip
   [75]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-13/igt@gem_lmem_swapping@verify-random-ccs.html

  * igt@gem_lmem_swapping@verify-random-ccs@lmem0:
    - shard-dg1:          NOTRUN -> [SKIP][76] ([i915#4565]) +1 other test skip
   [76]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-13/igt@gem_lmem_swapping@verify-random-ccs@lmem0.html

  * igt@gem_mmap_gtt@big-bo:
    - shard-mtlp:         NOTRUN -> [SKIP][77] ([i915#4077]) +2 other tests skip
   [77]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-mtlp-7/igt@gem_mmap_gtt@big-bo.html

  * igt@gem_mmap_gtt@big-copy-odd:
    - shard-dg2:          NOTRUN -> [SKIP][78] ([i915#4077]) +3 other tests skip
   [78]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-4/igt@gem_mmap_gtt@big-copy-odd.html

  * igt@gem_mmap_gtt@cpuset-basic-small-copy-odd:
    - shard-dg1:          NOTRUN -> [SKIP][79] ([i915#4077]) +7 other tests skip
   [79]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-13/igt@gem_mmap_gtt@cpuset-basic-small-copy-odd.html

  * igt@gem_mmap_wc@write-prefaulted:
    - shard-dg2:          NOTRUN -> [SKIP][80] ([i915#4083]) +4 other tests skip
   [80]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-4/igt@gem_mmap_wc@write-prefaulted.html

  * igt@gem_mmap_wc@write-read:
    - shard-dg1:          NOTRUN -> [SKIP][81] ([i915#4083]) +7 other tests skip
   [81]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-14/igt@gem_mmap_wc@write-read.html

  * igt@gem_partial_pwrite_pread@reads:
    - shard-dg2:          NOTRUN -> [SKIP][82] ([i915#3282]) +3 other tests skip
   [82]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-3/igt@gem_partial_pwrite_pread@reads.html

  * igt@gem_partial_pwrite_pread@writes-after-reads-uncached:
    - shard-rkl:          NOTRUN -> [SKIP][83] ([i915#3282]) +3 other tests skip
   [83]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-2/igt@gem_partial_pwrite_pread@writes-after-reads-uncached.html
    - shard-dg1:          NOTRUN -> [SKIP][84] ([i915#3282]) +2 other tests skip
   [84]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-14/igt@gem_partial_pwrite_pread@writes-after-reads-uncached.html
    - shard-mtlp:         NOTRUN -> [SKIP][85] ([i915#3282]) +1 other test skip
   [85]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-mtlp-2/igt@gem_partial_pwrite_pread@writes-after-reads-uncached.html

  * igt@gem_pwrite@basic-exhaustion:
    - shard-glk:          NOTRUN -> [WARN][86] ([i915#14702] / [i915#2658])
   [86]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-glk2/igt@gem_pwrite@basic-exhaustion.html

  * igt@gem_pxp@display-protected-crc:
    - shard-dg2:          NOTRUN -> [SKIP][87] ([i915#4270]) +3 other tests skip
   [87]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-3/igt@gem_pxp@display-protected-crc.html

  * igt@gem_pxp@hw-rejects-pxp-context:
    - shard-tglu:         NOTRUN -> [SKIP][88] ([i915#13398])
   [88]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-8/igt@gem_pxp@hw-rejects-pxp-context.html

  * igt@gem_pxp@verify-pxp-key-change-after-suspend-resume:
    - shard-dg1:          NOTRUN -> [SKIP][89] ([i915#4270]) +3 other tests skip
   [89]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-18/igt@gem_pxp@verify-pxp-key-change-after-suspend-resume.html

  * igt@gem_render_copy@y-tiled-ccs-to-linear:
    - shard-dg2:          NOTRUN -> [SKIP][90] ([i915#5190] / [i915#8428]) +4 other tests skip
   [90]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-7/igt@gem_render_copy@y-tiled-ccs-to-linear.html

  * igt@gem_render_copy@y-tiled-ccs-to-y-tiled-mc-ccs:
    - shard-glk:          NOTRUN -> [SKIP][91] +224 other tests skip
   [91]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-glk6/igt@gem_render_copy@y-tiled-ccs-to-y-tiled-mc-ccs.html

  * igt@gem_render_copy@yf-tiled-ccs-to-x-tiled:
    - shard-mtlp:         NOTRUN -> [SKIP][92] ([i915#8428])
   [92]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-mtlp-6/igt@gem_render_copy@yf-tiled-ccs-to-x-tiled.html

  * igt@gem_render_copy@yf-tiled-to-vebox-y-tiled:
    - shard-dg2:          NOTRUN -> [SKIP][93] ([i915#15689] / [i915#2575] / [i915#5190])
   [93]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@gem_render_copy@yf-tiled-to-vebox-y-tiled.html

  * igt@gem_softpin@evict-snoop-interruptible:
    - shard-dg1:          NOTRUN -> [SKIP][94] ([i915#4885])
   [94]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-18/igt@gem_softpin@evict-snoop-interruptible.html

  * igt@gem_tiled_pread_pwrite:
    - shard-dg1:          NOTRUN -> [SKIP][95] ([i915#4079]) +1 other test skip
   [95]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-18/igt@gem_tiled_pread_pwrite.html

  * igt@gem_userptr_blits@coherency-unsync:
    - shard-dg2:          NOTRUN -> [SKIP][96] ([i915#3297]) +1 other test skip
   [96]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-7/igt@gem_userptr_blits@coherency-unsync.html
    - shard-mtlp:         NOTRUN -> [SKIP][97] ([i915#3297])
   [97]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-mtlp-1/igt@gem_userptr_blits@coherency-unsync.html

  * igt@gem_userptr_blits@dmabuf-unsync:
    - shard-dg1:          NOTRUN -> [SKIP][98] ([i915#3297]) +3 other tests skip
   [98]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-14/igt@gem_userptr_blits@dmabuf-unsync.html

  * igt@gem_userptr_blits@map-fixed-invalidate-busy:
    - shard-dg1:          NOTRUN -> [SKIP][99] ([i915#3297] / [i915#4880])
   [99]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-14/igt@gem_userptr_blits@map-fixed-invalidate-busy.html

  * igt@gem_userptr_blits@readonly-unsync:
    - shard-tglu:         NOTRUN -> [SKIP][100] ([i915#3297]) +2 other tests skip
   [100]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-2/igt@gem_userptr_blits@readonly-unsync.html

  * igt@gem_userptr_blits@unsync-unmap-after-close:
    - shard-rkl:          NOTRUN -> [SKIP][101] ([i915#3297]) +2 other tests skip
   [101]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-8/igt@gem_userptr_blits@unsync-unmap-after-close.html
    - shard-tglu-1:       NOTRUN -> [SKIP][102] ([i915#3297]) +1 other test skip
   [102]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-1/igt@gem_userptr_blits@unsync-unmap-after-close.html

  * igt@gen7_exec_parse@bitmasks:
    - shard-dg2:          NOTRUN -> [SKIP][103] +10 other tests skip
   [103]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-3/igt@gen7_exec_parse@bitmasks.html

  * igt@gen7_exec_parse@chained-batch:
    - shard-rkl:          NOTRUN -> [SKIP][104] ([i915#14544])
   [104]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-6/igt@gen7_exec_parse@chained-batch.html

  * igt@gen9_exec_parse@allowed-single:
    - shard-glk:          NOTRUN -> [ABORT][105] ([i915#5566])
   [105]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-glk5/igt@gen9_exec_parse@allowed-single.html

  * igt@gen9_exec_parse@bb-oversize:
    - shard-rkl:          NOTRUN -> [SKIP][106] ([i915#2527]) +2 other tests skip
   [106]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-7/igt@gen9_exec_parse@bb-oversize.html
    - shard-tglu:         NOTRUN -> [SKIP][107] ([i915#2527] / [i915#2856])
   [107]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-10/igt@gen9_exec_parse@bb-oversize.html

  * igt@gen9_exec_parse@bb-secure:
    - shard-dg1:          NOTRUN -> [SKIP][108] ([i915#2527]) +2 other tests skip
   [108]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-13/igt@gen9_exec_parse@bb-secure.html

  * igt@gen9_exec_parse@bb-start-param:
    - shard-tglu-1:       NOTRUN -> [SKIP][109] ([i915#2527] / [i915#2856]) +2 other tests skip
   [109]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-1/igt@gen9_exec_parse@bb-start-param.html

  * igt@i915_drm_fdinfo@all-busy-check-all:
    - shard-dg2:          NOTRUN -> [SKIP][110] ([i915#14123])
   [110]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-4/igt@i915_drm_fdinfo@all-busy-check-all.html

  * igt@i915_drm_fdinfo@busy-check-all:
    - shard-dg1:          NOTRUN -> [SKIP][111] ([i915#11527]) +5 other tests skip
   [111]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-14/igt@i915_drm_fdinfo@busy-check-all.html

  * igt@i915_drm_fdinfo@busy-hang@rcs0:
    - shard-dg2:          NOTRUN -> [SKIP][112] ([i915#14073]) +37 other tests skip
   [112]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-3/igt@i915_drm_fdinfo@busy-hang@rcs0.html

  * igt@i915_drm_fdinfo@busy-idle@bcs0:
    - shard-dg1:          NOTRUN -> [SKIP][113] ([i915#14073]) +11 other tests skip
   [113]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-12/igt@i915_drm_fdinfo@busy-idle@bcs0.html

  * igt@i915_drm_fdinfo@busy-idle@rcs0:
    - shard-mtlp:         NOTRUN -> [SKIP][114] ([i915#14073]) +6 other tests skip
   [114]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-mtlp-5/igt@i915_drm_fdinfo@busy-idle@rcs0.html

  * igt@i915_drm_fdinfo@virtual-busy:
    - shard-dg1:          NOTRUN -> [SKIP][115] ([i915#14118]) +2 other tests skip
   [115]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-12/igt@i915_drm_fdinfo@virtual-busy.html

  * igt@i915_drm_fdinfo@virtual-busy-hang-all:
    - shard-mtlp:         NOTRUN -> [SKIP][116] ([i915#14118])
   [116]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-mtlp-7/igt@i915_drm_fdinfo@virtual-busy-hang-all.html

  * igt@i915_fb_tiling@basic-x-tiling:
    - shard-dg2:          NOTRUN -> [SKIP][117] ([i915#13786])
   [117]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-3/igt@i915_fb_tiling@basic-x-tiling.html

  * igt@i915_module_load@reload-no-display:
    - shard-tglu-1:       NOTRUN -> [DMESG-WARN][118] ([i915#13029] / [i915#14545])
   [118]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-1/igt@i915_module_load@reload-no-display.html

  * igt@i915_module_load@resize-bar:
    - shard-dg2:          [PASS][119] -> [DMESG-WARN][120] ([i915#14545])
   [119]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-1/igt@i915_module_load@resize-bar.html
   [120]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-7/igt@i915_module_load@resize-bar.html

  * igt@i915_pm_freq_api@freq-reset-multiple:
    - shard-rkl:          NOTRUN -> [SKIP][121] ([i915#8399])
   [121]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-4/igt@i915_pm_freq_api@freq-reset-multiple.html

  * igt@i915_pm_freq_mult@media-freq@gt0:
    - shard-rkl:          NOTRUN -> [SKIP][122] ([i915#6590]) +1 other test skip
   [122]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-8/igt@i915_pm_freq_mult@media-freq@gt0.html
    - shard-tglu:         NOTRUN -> [SKIP][123] ([i915#6590]) +1 other test skip
   [123]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-5/igt@i915_pm_freq_mult@media-freq@gt0.html

  * igt@i915_pm_rc6_residency@rc6-fence:
    - shard-tglu:         NOTRUN -> [WARN][124] ([i915#13790] / [i915#2681]) +1 other test warn
   [124]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-4/igt@i915_pm_rc6_residency@rc6-fence.html

  * igt@i915_pm_rps@thresholds-idle-park:
    - shard-dg1:          NOTRUN -> [SKIP][125] ([i915#11681])
   [125]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-16/igt@i915_pm_rps@thresholds-idle-park.html

  * igt@i915_pm_sseu@full-enable:
    - shard-dg1:          NOTRUN -> [SKIP][126] ([i915#4387])
   [126]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-18/igt@i915_pm_sseu@full-enable.html

  * igt@i915_suspend@debugfs-reader:
    - shard-glk:          NOTRUN -> [INCOMPLETE][127] ([i915#4817])
   [127]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-glk6/igt@i915_suspend@debugfs-reader.html

  * igt@i915_suspend@fence-restore-untiled:
    - shard-rkl:          [PASS][128] -> [INCOMPLETE][129] ([i915#4817])
   [128]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-2/igt@i915_suspend@fence-restore-untiled.html
   [129]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-6/igt@i915_suspend@fence-restore-untiled.html

  * igt@i915_suspend@forcewake:
    - shard-glk10:        NOTRUN -> [INCOMPLETE][130] ([i915#4817])
   [130]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-glk10/igt@i915_suspend@forcewake.html

  * igt@kms_addfb_basic@addfb25-framebuffer-vs-set-tiling:
    - shard-dg1:          NOTRUN -> [SKIP][131] ([i915#4212]) +1 other test skip
   [131]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-14/igt@kms_addfb_basic@addfb25-framebuffer-vs-set-tiling.html

  * igt@kms_addfb_basic@addfb25-x-tiled-legacy:
    - shard-mtlp:         NOTRUN -> [SKIP][132] ([i915#4212])
   [132]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-mtlp-1/igt@kms_addfb_basic@addfb25-x-tiled-legacy.html

  * igt@kms_addfb_basic@addfb25-y-tiled-legacy:
    - shard-dg2:          [PASS][133] -> [SKIP][134] ([i915#15689] / [i915#5190])
   [133]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-8/igt@kms_addfb_basic@addfb25-y-tiled-legacy.html
   [134]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_addfb_basic@addfb25-y-tiled-legacy.html

  * igt@kms_addfb_basic@addfb25-y-tiled-small-legacy:
    - shard-dg2:          NOTRUN -> [SKIP][135] ([i915#5190]) +1 other test skip
   [135]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-7/igt@kms_addfb_basic@addfb25-y-tiled-small-legacy.html
    - shard-mtlp:         NOTRUN -> [SKIP][136] ([i915#5190])
   [136]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-mtlp-6/igt@kms_addfb_basic@addfb25-y-tiled-small-legacy.html

  * igt@kms_addfb_basic@basic-x-tiled-legacy:
    - shard-dg2:          NOTRUN -> [SKIP][137] ([i915#4212]) +2 other tests skip
   [137]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-6/igt@kms_addfb_basic@basic-x-tiled-legacy.html

  * igt@kms_addfb_basic@invalid-smem-bo-on-discrete:
    - shard-rkl:          NOTRUN -> [SKIP][138] ([i915#12454] / [i915#12712] / [i915#14544])
   [138]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-6/igt@kms_addfb_basic@invalid-smem-bo-on-discrete.html

  * igt@kms_async_flips@async-flip-suspend-resume:
    - shard-glk:          NOTRUN -> [INCOMPLETE][139] ([i915#12761])
   [139]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-glk2/igt@kms_async_flips@async-flip-suspend-resume.html

  * igt@kms_async_flips@async-flip-suspend-resume@pipe-a-hdmi-a-2:
    - shard-glk:          NOTRUN -> [INCOMPLETE][140] ([i915#12761] / [i915#14995])
   [140]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-glk2/igt@kms_async_flips@async-flip-suspend-resume@pipe-a-hdmi-a-2.html

  * igt@kms_async_flips@async-flip-with-page-flip-events-linear:
    - shard-dg2:          NOTRUN -> [SKIP][141] ([i915#15689]) +82 other tests skip
   [141]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_async_flips@async-flip-with-page-flip-events-linear.html

  * igt@kms_atomic@plane-primary-overlay-mutable-zpos:
    - shard-tglu-1:       NOTRUN -> [SKIP][142] ([i915#9531])
   [142]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-1/igt@kms_atomic@plane-primary-overlay-mutable-zpos.html

  * igt@kms_atomic_transition@plane-all-modeset-transition-fencing-internal-panels:
    - shard-snb:          NOTRUN -> [SKIP][143] ([i915#1769])
   [143]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-snb4/igt@kms_atomic_transition@plane-all-modeset-transition-fencing-internal-panels.html
    - shard-tglu:         NOTRUN -> [SKIP][144] ([i915#1769] / [i915#3555])
   [144]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-4/igt@kms_atomic_transition@plane-all-modeset-transition-fencing-internal-panels.html
    - shard-dg2:          NOTRUN -> [SKIP][145] ([i915#1769] / [i915#3555])
   [145]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-7/igt@kms_atomic_transition@plane-all-modeset-transition-fencing-internal-panels.html
    - shard-rkl:          NOTRUN -> [SKIP][146] ([i915#1769] / [i915#3555])
   [146]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-5/igt@kms_atomic_transition@plane-all-modeset-transition-fencing-internal-panels.html

  * igt@kms_atomic_transition@plane-all-modeset-transition-internal-panels:
    - shard-tglu-1:       NOTRUN -> [SKIP][147] ([i915#1769] / [i915#3555])
   [147]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-1/igt@kms_atomic_transition@plane-all-modeset-transition-internal-panels.html
    - shard-glk:          NOTRUN -> [SKIP][148] ([i915#1769])
   [148]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-glk5/igt@kms_atomic_transition@plane-all-modeset-transition-internal-panels.html

  * igt@kms_big_fb@4-tiled-64bpp-rotate-0:
    - shard-tglu-1:       NOTRUN -> [SKIP][149] ([i915#5286]) +2 other tests skip
   [149]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-1/igt@kms_big_fb@4-tiled-64bpp-rotate-0.html

  * igt@kms_big_fb@4-tiled-8bpp-rotate-180:
    - shard-dg1:          NOTRUN -> [SKIP][150] ([i915#4538] / [i915#5286]) +11 other tests skip
   [150]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-14/igt@kms_big_fb@4-tiled-8bpp-rotate-180.html

  * igt@kms_big_fb@4-tiled-addfb-size-overflow:
    - shard-dg1:          NOTRUN -> [SKIP][151] ([i915#5286])
   [151]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-14/igt@kms_big_fb@4-tiled-addfb-size-overflow.html

  * igt@kms_big_fb@4-tiled-max-hw-stride-32bpp-rotate-0-async-flip:
    - shard-tglu:         NOTRUN -> [SKIP][152] ([i915#5286]) +5 other tests skip
   [152]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-10/igt@kms_big_fb@4-tiled-max-hw-stride-32bpp-rotate-0-async-flip.html

  * igt@kms_big_fb@4-tiled-max-hw-stride-32bpp-rotate-0-hflip:
    - shard-rkl:          NOTRUN -> [SKIP][153] ([i915#5286]) +6 other tests skip
   [153]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-3/igt@kms_big_fb@4-tiled-max-hw-stride-32bpp-rotate-0-hflip.html

  * igt@kms_big_fb@linear-32bpp-rotate-90:
    - shard-rkl:          NOTRUN -> [SKIP][154] ([i915#3638]) +2 other tests skip
   [154]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-2/igt@kms_big_fb@linear-32bpp-rotate-90.html

  * igt@kms_big_fb@linear-max-hw-stride-64bpp-rotate-0-hflip:
    - shard-dg1:          NOTRUN -> [SKIP][155] ([i915#3828]) +1 other test skip
   [155]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-12/igt@kms_big_fb@linear-max-hw-stride-64bpp-rotate-0-hflip.html
    - shard-tglu:         NOTRUN -> [SKIP][156] ([i915#3828])
   [156]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-8/igt@kms_big_fb@linear-max-hw-stride-64bpp-rotate-0-hflip.html

  * igt@kms_big_fb@linear-max-hw-stride-64bpp-rotate-180-hflip:
    - shard-rkl:          NOTRUN -> [SKIP][157] ([i915#3828])
   [157]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-2/igt@kms_big_fb@linear-max-hw-stride-64bpp-rotate-180-hflip.html

  * igt@kms_big_fb@x-tiled-64bpp-rotate-180:
    - shard-dg2:          [PASS][158] -> [SKIP][159] ([i915#15689]) +117 other tests skip
   [158]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-7/igt@kms_big_fb@x-tiled-64bpp-rotate-180.html
   [159]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_big_fb@x-tiled-64bpp-rotate-180.html

  * igt@kms_big_fb@y-tiled-64bpp-rotate-90:
    - shard-dg1:          NOTRUN -> [SKIP][160] ([i915#3638]) +4 other tests skip
   [160]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-12/igt@kms_big_fb@y-tiled-64bpp-rotate-90.html

  * igt@kms_big_fb@y-tiled-8bpp-rotate-180:
    - shard-dg2:          NOTRUN -> [SKIP][161] ([i915#4538] / [i915#5190]) +9 other tests skip
   [161]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-5/igt@kms_big_fb@y-tiled-8bpp-rotate-180.html

  * igt@kms_big_fb@y-tiled-addfb-size-offset-overflow:
    - shard-dg2:          NOTRUN -> [SKIP][162] ([i915#15689] / [i915#5190]) +1 other test skip
   [162]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_big_fb@y-tiled-addfb-size-offset-overflow.html

  * igt@kms_big_fb@yf-tiled-64bpp-rotate-180:
    - shard-mtlp:         NOTRUN -> [SKIP][163] +4 other tests skip
   [163]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-mtlp-5/igt@kms_big_fb@yf-tiled-64bpp-rotate-180.html

  * igt@kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-0:
    - shard-dg1:          NOTRUN -> [SKIP][164] ([i915#4538]) +6 other tests skip
   [164]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-12/igt@kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-0.html

  * igt@kms_ccs@bad-aux-stride-4-tiled-mtl-mc-ccs@pipe-a-hdmi-a-4:
    - shard-dg1:          NOTRUN -> [SKIP][165] ([i915#6095]) +184 other tests skip
   [165]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-16/igt@kms_ccs@bad-aux-stride-4-tiled-mtl-mc-ccs@pipe-a-hdmi-a-4.html

  * igt@kms_ccs@bad-pixel-format-4-tiled-mtl-mc-ccs:
    - shard-dg2:          NOTRUN -> [SKIP][166] ([i915#10307] / [i915#6095]) +106 other tests skip
   [166]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-3/igt@kms_ccs@bad-pixel-format-4-tiled-mtl-mc-ccs.html

  * igt@kms_ccs@bad-rotation-90-4-tiled-mtl-mc-ccs@pipe-c-hdmi-a-2:
    - shard-rkl:          NOTRUN -> [SKIP][167] ([i915#14098] / [i915#6095]) +44 other tests skip
   [167]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-3/igt@kms_ccs@bad-rotation-90-4-tiled-mtl-mc-ccs@pipe-c-hdmi-a-2.html

  * igt@kms_ccs@crc-primary-basic-4-tiled-lnl-ccs:
    - shard-tglu-1:       NOTRUN -> [SKIP][168] ([i915#12313])
   [168]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-1/igt@kms_ccs@crc-primary-basic-4-tiled-lnl-ccs.html

  * igt@kms_ccs@crc-primary-rotation-180-4-tiled-dg2-mc-ccs@pipe-b-hdmi-a-1:
    - shard-rkl:          NOTRUN -> [SKIP][169] ([i915#6095]) +70 other tests skip
   [169]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-8/igt@kms_ccs@crc-primary-rotation-180-4-tiled-dg2-mc-ccs@pipe-b-hdmi-a-1.html

  * igt@kms_ccs@crc-primary-rotation-180-4-tiled-mtl-rc-ccs-cc@pipe-d-hdmi-a-1:
    - shard-tglu:         NOTRUN -> [SKIP][170] ([i915#6095]) +29 other tests skip
   [170]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-2/igt@kms_ccs@crc-primary-rotation-180-4-tiled-mtl-rc-ccs-cc@pipe-d-hdmi-a-1.html

  * igt@kms_ccs@crc-primary-suspend-4-tiled-dg2-rc-ccs@pipe-a-hdmi-a-2:
    - shard-rkl:          NOTRUN -> [SKIP][171] ([i915#14544] / [i915#6095]) +2 other tests skip
   [171]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-6/igt@kms_ccs@crc-primary-suspend-4-tiled-dg2-rc-ccs@pipe-a-hdmi-a-2.html

  * igt@kms_ccs@crc-primary-suspend-4-tiled-dg2-rc-ccs@pipe-c-hdmi-a-2:
    - shard-rkl:          NOTRUN -> [SKIP][172] ([i915#14098] / [i915#14544] / [i915#6095]) +2 other tests skip
   [172]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-6/igt@kms_ccs@crc-primary-suspend-4-tiled-dg2-rc-ccs@pipe-c-hdmi-a-2.html

  * igt@kms_ccs@crc-primary-suspend-y-tiled-gen12-rc-ccs-cc@pipe-b-hdmi-a-3:
    - shard-dg2:          NOTRUN -> [SKIP][173] ([i915#6095]) +46 other tests skip
   [173]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-1/igt@kms_ccs@crc-primary-suspend-y-tiled-gen12-rc-ccs-cc@pipe-b-hdmi-a-3.html

  * igt@kms_ccs@crc-primary-suspend-yf-tiled-ccs:
    - shard-glk:          NOTRUN -> [INCOMPLETE][174] ([i915#15582]) +1 other test incomplete
   [174]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-glk9/igt@kms_ccs@crc-primary-suspend-yf-tiled-ccs.html

  * igt@kms_ccs@crc-sprite-planes-basic-4-tiled-bmg-ccs:
    - shard-dg1:          NOTRUN -> [SKIP][175] ([i915#12313]) +2 other tests skip
   [175]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-12/igt@kms_ccs@crc-sprite-planes-basic-4-tiled-bmg-ccs.html

  * igt@kms_ccs@crc-sprite-planes-basic-4-tiled-dg2-rc-ccs-cc@pipe-b-hdmi-a-1:
    - shard-tglu-1:       NOTRUN -> [SKIP][176] ([i915#6095]) +39 other tests skip
   [176]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-1/igt@kms_ccs@crc-sprite-planes-basic-4-tiled-dg2-rc-ccs-cc@pipe-b-hdmi-a-1.html

  * igt@kms_ccs@crc-sprite-planes-basic-4-tiled-lnl-ccs:
    - shard-rkl:          NOTRUN -> [SKIP][177] ([i915#12313]) +1 other test skip
   [177]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-2/igt@kms_ccs@crc-sprite-planes-basic-4-tiled-lnl-ccs.html

  * igt@kms_ccs@crc-sprite-planes-basic-y-tiled-gen12-mc-ccs@pipe-a-edp-1:
    - shard-mtlp:         NOTRUN -> [SKIP][178] ([i915#6095]) +4 other tests skip
   [178]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-mtlp-6/igt@kms_ccs@crc-sprite-planes-basic-y-tiled-gen12-mc-ccs@pipe-a-edp-1.html

  * igt@kms_ccs@missing-ccs-buffer-y-tiled-ccs@pipe-d-hdmi-a-1:
    - shard-dg2:          NOTRUN -> [SKIP][179] ([i915#10307] / [i915#10434] / [i915#6095]) +2 other tests skip
   [179]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-4/igt@kms_ccs@missing-ccs-buffer-y-tiled-ccs@pipe-d-hdmi-a-1.html

  * igt@kms_cdclk@mode-transition@pipe-d-hdmi-a-3:
    - shard-dg2:          NOTRUN -> [SKIP][180] ([i915#13781]) +3 other tests skip
   [180]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-6/igt@kms_cdclk@mode-transition@pipe-d-hdmi-a-3.html

  * igt@kms_chamelium_audio@dp-audio-edid:
    - shard-dg2:          NOTRUN -> [SKIP][181] ([i915#11151] / [i915#7828]) +2 other tests skip
   [181]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-8/igt@kms_chamelium_audio@dp-audio-edid.html

  * igt@kms_chamelium_audio@hdmi-audio:
    - shard-rkl:          NOTRUN -> [SKIP][182] ([i915#11151] / [i915#7828]) +6 other tests skip
   [182]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-5/igt@kms_chamelium_audio@hdmi-audio.html

  * igt@kms_chamelium_edid@vga-edid-read:
    - shard-tglu:         NOTRUN -> [SKIP][183] ([i915#11151] / [i915#7828]) +7 other tests skip
   [183]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-10/igt@kms_chamelium_edid@vga-edid-read.html

  * igt@kms_chamelium_hpd@dp-hpd-for-each-pipe:
    - shard-mtlp:         NOTRUN -> [SKIP][184] ([i915#11151] / [i915#7828]) +2 other tests skip
   [184]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-mtlp-5/igt@kms_chamelium_hpd@dp-hpd-for-each-pipe.html

  * igt@kms_chamelium_hpd@hdmi-hpd-storm-disable:
    - shard-tglu-1:       NOTRUN -> [SKIP][185] ([i915#11151] / [i915#7828]) +4 other tests skip
   [185]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-1/igt@kms_chamelium_hpd@hdmi-hpd-storm-disable.html

  * igt@kms_chamelium_hpd@vga-hpd-fast:
    - shard-dg1:          NOTRUN -> [SKIP][186] ([i915#11151] / [i915#7828]) +7 other tests skip
   [186]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-14/igt@kms_chamelium_hpd@vga-hpd-fast.html

  * igt@kms_color@deep-color:
    - shard-rkl:          [PASS][187] -> [SKIP][188] ([i915#12655] / [i915#3555])
   [187]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-6/igt@kms_color@deep-color.html
   [188]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-2/igt@kms_color@deep-color.html

  * igt@kms_content_protection@atomic:
    - shard-rkl:          NOTRUN -> [SKIP][189] ([i915#6944] / [i915#7118] / [i915#9424])
   [189]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-8/igt@kms_content_protection@atomic.html

  * igt@kms_content_protection@atomic-dpms:
    - shard-dg1:          NOTRUN -> [SKIP][190] ([i915#6944] / [i915#7116] / [i915#9424])
   [190]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-12/igt@kms_content_protection@atomic-dpms.html

  * igt@kms_content_protection@dp-mst-lic-type-0-hdcp14:
    - shard-tglu-1:       NOTRUN -> [SKIP][191] ([i915#15330])
   [191]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-1/igt@kms_content_protection@dp-mst-lic-type-0-hdcp14.html
    - shard-dg1:          NOTRUN -> [SKIP][192] ([i915#15330]) +2 other tests skip
   [192]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-18/igt@kms_content_protection@dp-mst-lic-type-0-hdcp14.html

  * igt@kms_content_protection@dp-mst-type-0:
    - shard-rkl:          NOTRUN -> [SKIP][193] ([i915#15330] / [i915#3116])
   [193]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-8/igt@kms_content_protection@dp-mst-type-0.html
    - shard-tglu:         NOTRUN -> [SKIP][194] ([i915#15330] / [i915#3116] / [i915#3299])
   [194]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-9/igt@kms_content_protection@dp-mst-type-0.html
    - shard-dg2:          NOTRUN -> [SKIP][195] ([i915#15330] / [i915#3299])
   [195]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-8/igt@kms_content_protection@dp-mst-type-0.html

  * igt@kms_content_protection@dp-mst-type-0-hdcp14:
    - shard-dg2:          NOTRUN -> [SKIP][196] ([i915#15330]) +1 other test skip
   [196]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-6/igt@kms_content_protection@dp-mst-type-0-hdcp14.html
    - shard-tglu:         NOTRUN -> [SKIP][197] ([i915#15330])
   [197]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-7/igt@kms_content_protection@dp-mst-type-0-hdcp14.html

  * igt@kms_content_protection@legacy-hdcp14:
    - shard-dg1:          NOTRUN -> [SKIP][198] ([i915#6944])
   [198]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-12/igt@kms_content_protection@legacy-hdcp14.html

  * igt@kms_content_protection@lic-type-1:
    - shard-mtlp:         NOTRUN -> [SKIP][199] ([i915#6944] / [i915#9424])
   [199]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-mtlp-2/igt@kms_content_protection@lic-type-1.html
    - shard-dg1:          NOTRUN -> [SKIP][200] ([i915#6944] / [i915#9424])
   [200]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-13/igt@kms_content_protection@lic-type-1.html

  * igt@kms_content_protection@mei-interface:
    - shard-tglu:         NOTRUN -> [SKIP][201] ([i915#6944] / [i915#9424]) +1 other test skip
   [201]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-3/igt@kms_content_protection@mei-interface.html

  * igt@kms_content_protection@uevent:
    - shard-dg2:          NOTRUN -> [SKIP][202] ([i915#6944] / [i915#7118] / [i915#9424])
   [202]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-4/igt@kms_content_protection@uevent.html

  * igt@kms_content_protection@uevent-hdcp14:
    - shard-tglu-1:       NOTRUN -> [SKIP][203] ([i915#6944])
   [203]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-1/igt@kms_content_protection@uevent-hdcp14.html

  * igt@kms_cursor_crc@cursor-onscreen-128x42:
    - shard-mtlp:         NOTRUN -> [SKIP][204] ([i915#8814]) +1 other test skip
   [204]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-mtlp-4/igt@kms_cursor_crc@cursor-onscreen-128x42.html

  * igt@kms_cursor_crc@cursor-onscreen-512x512:
    - shard-tglu:         NOTRUN -> [SKIP][205] ([i915#13049]) +1 other test skip
   [205]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-4/igt@kms_cursor_crc@cursor-onscreen-512x512.html
    - shard-mtlp:         NOTRUN -> [SKIP][206] ([i915#13049])
   [206]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-mtlp-1/igt@kms_cursor_crc@cursor-onscreen-512x512.html
    - shard-rkl:          NOTRUN -> [SKIP][207] ([i915#13049]) +1 other test skip
   [207]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-5/igt@kms_cursor_crc@cursor-onscreen-512x512.html

  * igt@kms_cursor_crc@cursor-random-32x32:
    - shard-dg1:          NOTRUN -> [SKIP][208] ([i915#3555]) +7 other tests skip
   [208]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-13/igt@kms_cursor_crc@cursor-random-32x32.html
    - shard-tglu:         NOTRUN -> [SKIP][209] ([i915#3555]) +2 other tests skip
   [209]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-6/igt@kms_cursor_crc@cursor-random-32x32.html

  * igt@kms_cursor_crc@cursor-random-512x170:
    - shard-dg2:          NOTRUN -> [SKIP][210] ([i915#13049]) +1 other test skip
   [210]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-6/igt@kms_cursor_crc@cursor-random-512x170.html
    - shard-dg1:          NOTRUN -> [SKIP][211] ([i915#13049]) +2 other tests skip
   [211]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-12/igt@kms_cursor_crc@cursor-random-512x170.html

  * igt@kms_cursor_crc@cursor-random-64x21:
    - shard-rkl:          NOTRUN -> [FAIL][212] ([i915#13566]) +1 other test fail
   [212]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-8/igt@kms_cursor_crc@cursor-random-64x21.html

  * igt@kms_cursor_crc@cursor-sliding-128x42:
    - shard-tglu:         [PASS][213] -> [FAIL][214] ([i915#13566]) +3 other tests fail
   [213]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-tglu-10/igt@kms_cursor_crc@cursor-sliding-128x42.html
   [214]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-7/igt@kms_cursor_crc@cursor-sliding-128x42.html

  * igt@kms_cursor_crc@cursor-sliding-128x42@pipe-a-hdmi-a-1:
    - shard-rkl:          [PASS][215] -> [FAIL][216] ([i915#13566]) +1 other test fail
   [215]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-8/igt@kms_cursor_crc@cursor-sliding-128x42@pipe-a-hdmi-a-1.html
   [216]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-2/igt@kms_cursor_crc@cursor-sliding-128x42@pipe-a-hdmi-a-1.html

  * igt@kms_cursor_crc@cursor-sliding-32x10:
    - shard-dg2:          NOTRUN -> [SKIP][217] ([i915#3555]) +2 other tests skip
   [217]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-1/igt@kms_cursor_crc@cursor-sliding-32x10.html

  * igt@kms_cursor_crc@cursor-sliding-32x32:
    - shard-mtlp:         NOTRUN -> [SKIP][218] ([i915#3555] / [i915#8814]) +1 other test skip
   [218]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-mtlp-4/igt@kms_cursor_crc@cursor-sliding-32x32.html

  * igt@kms_cursor_crc@cursor-sliding-512x170:
    - shard-tglu-1:       NOTRUN -> [SKIP][219] ([i915#13049]) +1 other test skip
   [219]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-1/igt@kms_cursor_crc@cursor-sliding-512x170.html

  * igt@kms_cursor_crc@cursor-suspend:
    - shard-glk10:        NOTRUN -> [INCOMPLETE][220] ([i915#12358] / [i915#14152] / [i915#7882])
   [220]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-glk10/igt@kms_cursor_crc@cursor-suspend.html

  * igt@kms_cursor_crc@cursor-suspend@pipe-a-hdmi-a-1:
    - shard-glk10:        NOTRUN -> [INCOMPLETE][221] ([i915#12358] / [i915#14152])
   [221]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-glk10/igt@kms_cursor_crc@cursor-suspend@pipe-a-hdmi-a-1.html

  * igt@kms_cursor_legacy@2x-flip-vs-cursor-legacy:
    - shard-rkl:          NOTRUN -> [SKIP][222] +18 other tests skip
   [222]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-5/igt@kms_cursor_legacy@2x-flip-vs-cursor-legacy.html

  * igt@kms_cursor_legacy@cursora-vs-flipb-toggle:
    - shard-dg2:          NOTRUN -> [SKIP][223] ([i915#13046] / [i915#5354]) +3 other tests skip
   [223]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-4/igt@kms_cursor_legacy@cursora-vs-flipb-toggle.html

  * igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions:
    - shard-glk:          NOTRUN -> [FAIL][224] ([i915#15764])
   [224]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-glk9/igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions.html

  * igt@kms_cursor_legacy@modeset-atomic-cursor-hotspot:
    - shard-dg1:          NOTRUN -> [SKIP][225] ([i915#9067])
   [225]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-14/igt@kms_cursor_legacy@modeset-atomic-cursor-hotspot.html

  * igt@kms_cursor_legacy@short-busy-flip-before-cursor-atomic-transitions-varying-size:
    - shard-dg1:          NOTRUN -> [SKIP][226] ([i915#4103] / [i915#4213])
   [226]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-14/igt@kms_cursor_legacy@short-busy-flip-before-cursor-atomic-transitions-varying-size.html

  * igt@kms_dirtyfb@drrs-dirtyfb-ioctl:
    - shard-dg1:          NOTRUN -> [SKIP][227] ([i915#9723])
   [227]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-12/igt@kms_dirtyfb@drrs-dirtyfb-ioctl.html
    - shard-tglu:         NOTRUN -> [SKIP][228] ([i915#9723])
   [228]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-3/igt@kms_dirtyfb@drrs-dirtyfb-ioctl.html
    - shard-mtlp:         NOTRUN -> [SKIP][229] ([i915#9833])
   [229]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-mtlp-5/igt@kms_dirtyfb@drrs-dirtyfb-ioctl.html

  * igt@kms_display_modes@extended-mode-basic:
    - shard-tglu-1:       NOTRUN -> [SKIP][230] ([i915#13691])
   [230]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-1/igt@kms_display_modes@extended-mode-basic.html

  * igt@kms_dither@fb-8bpc-vs-panel-6bpc@pipe-a-hdmi-a-2:
    - shard-rkl:          NOTRUN -> [SKIP][231] ([i915#3804])
   [231]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-7/igt@kms_dither@fb-8bpc-vs-panel-6bpc@pipe-a-hdmi-a-2.html

  * igt@kms_dp_aux_dev:
    - shard-dg2:          NOTRUN -> [SKIP][232] ([i915#1257])
   [232]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-8/igt@kms_dp_aux_dev.html
    - shard-tglu:         NOTRUN -> [SKIP][233] ([i915#1257])
   [233]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-5/igt@kms_dp_aux_dev.html

  * igt@kms_dp_link_training@non-uhbr-sst:
    - shard-dg2:          NOTRUN -> [SKIP][234] ([i915#13749])
   [234]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-7/igt@kms_dp_link_training@non-uhbr-sst.html
    - shard-dg1:          NOTRUN -> [SKIP][235] ([i915#13749])
   [235]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-13/igt@kms_dp_link_training@non-uhbr-sst.html

  * igt@kms_dp_link_training@uhbr-mst:
    - shard-tglu-1:       NOTRUN -> [SKIP][236] ([i915#13748])
   [236]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-1/igt@kms_dp_link_training@uhbr-mst.html

  * igt@kms_dsc@dsc-fractional-bpp:
    - shard-dg2:          NOTRUN -> [SKIP][237] ([i915#3840] / [i915#9688])
   [237]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-6/igt@kms_dsc@dsc-fractional-bpp.html

  * igt@kms_dsc@dsc-fractional-bpp-with-bpc:
    - shard-tglu:         NOTRUN -> [SKIP][238] ([i915#3840])
   [238]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-6/igt@kms_dsc@dsc-fractional-bpp-with-bpc.html

  * igt@kms_dsc@dsc-with-bpc:
    - shard-rkl:          NOTRUN -> [SKIP][239] ([i915#14544] / [i915#3555] / [i915#3840])
   [239]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-6/igt@kms_dsc@dsc-with-bpc.html
    - shard-dg1:          NOTRUN -> [SKIP][240] ([i915#3555] / [i915#3840])
   [240]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-16/igt@kms_dsc@dsc-with-bpc.html

  * igt@kms_dsc@dsc-with-output-formats-with-bpc:
    - shard-dg2:          NOTRUN -> [SKIP][241] ([i915#3840] / [i915#9053])
   [241]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-8/igt@kms_dsc@dsc-with-output-formats-with-bpc.html

  * igt@kms_fbcon_fbt@psr:
    - shard-dg1:          NOTRUN -> [SKIP][242] ([i915#3469])
   [242]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-16/igt@kms_fbcon_fbt@psr.html

  * igt@kms_feature_discovery@display-3x:
    - shard-rkl:          NOTRUN -> [SKIP][243] ([i915#1839])
   [243]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-2/igt@kms_feature_discovery@display-3x.html
    - shard-tglu:         NOTRUN -> [SKIP][244] ([i915#1839])
   [244]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-7/igt@kms_feature_discovery@display-3x.html

  * igt@kms_feature_discovery@display-4x:
    - shard-tglu-1:       NOTRUN -> [SKIP][245] ([i915#1839])
   [245]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-1/igt@kms_feature_discovery@display-4x.html

  * igt@kms_feature_discovery@psr1:
    - shard-dg2:          NOTRUN -> [SKIP][246] ([i915#658])
   [246]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-3/igt@kms_feature_discovery@psr1.html
    - shard-dg1:          NOTRUN -> [SKIP][247] ([i915#658])
   [247]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-16/igt@kms_feature_discovery@psr1.html

  * igt@kms_flip@2x-blocking-absolute-wf_vblank:
    - shard-rkl:          NOTRUN -> [SKIP][248] ([i915#14544] / [i915#9934])
   [248]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-6/igt@kms_flip@2x-blocking-absolute-wf_vblank.html

  * igt@kms_flip@2x-busy-flip:
    - shard-dg2:          NOTRUN -> [SKIP][249] ([i915#9934]) +4 other tests skip
   [249]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-7/igt@kms_flip@2x-busy-flip.html

  * igt@kms_flip@2x-flip-vs-dpms-off-vs-modeset-interruptible:
    - shard-rkl:          NOTRUN -> [SKIP][250] ([i915#9934]) +7 other tests skip
   [250]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-8/igt@kms_flip@2x-flip-vs-dpms-off-vs-modeset-interruptible.html

  * igt@kms_flip@2x-flip-vs-dpms-on-nop-interruptible:
    - shard-tglu-1:       NOTRUN -> [SKIP][251] ([i915#9934])
   [251]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-1/igt@kms_flip@2x-flip-vs-dpms-on-nop-interruptible.html

  * igt@kms_flip@2x-flip-vs-fences-interruptible:
    - shard-tglu:         NOTRUN -> [SKIP][252] ([i915#3637] / [i915#9934]) +4 other tests skip
   [252]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-7/igt@kms_flip@2x-flip-vs-fences-interruptible.html

  * igt@kms_flip@2x-flip-vs-panning-vs-hang:
    - shard-mtlp:         NOTRUN -> [SKIP][253] ([i915#3637] / [i915#9934])
   [253]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-mtlp-5/igt@kms_flip@2x-flip-vs-panning-vs-hang.html

  * igt@kms_flip@2x-plain-flip-fb-recreate-interruptible:
    - shard-tglu-1:       NOTRUN -> [SKIP][254] ([i915#3637] / [i915#9934]) +5 other tests skip
   [254]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-1/igt@kms_flip@2x-plain-flip-fb-recreate-interruptible.html

  * igt@kms_flip@2x-plain-flip-interruptible:
    - shard-dg1:          NOTRUN -> [SKIP][255] ([i915#9934]) +7 other tests skip
   [255]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-14/igt@kms_flip@2x-plain-flip-interruptible.html

  * igt@kms_flip@flip-vs-fences-interruptible:
    - shard-dg1:          NOTRUN -> [SKIP][256] ([i915#8381])
   [256]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-18/igt@kms_flip@flip-vs-fences-interruptible.html

  * igt@kms_flip@flip-vs-suspend:
    - shard-rkl:          [PASS][257] -> [INCOMPLETE][258] ([i915#6113])
   [257]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-8/igt@kms_flip@flip-vs-suspend.html
   [258]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-6/igt@kms_flip@flip-vs-suspend.html

  * igt@kms_flip@flip-vs-suspend@a-hdmi-a2:
    - shard-rkl:          NOTRUN -> [INCOMPLETE][259] ([i915#6113])
   [259]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-6/igt@kms_flip@flip-vs-suspend@a-hdmi-a2.html

  * igt@kms_flip_scaled_crc@flip-32bpp-4tile-to-32bpp-4tiledg2rcccs-downscaling:
    - shard-dg2:          NOTRUN -> [SKIP][260] ([i915#15643]) +2 other tests skip
   [260]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-3/igt@kms_flip_scaled_crc@flip-32bpp-4tile-to-32bpp-4tiledg2rcccs-downscaling.html

  * igt@kms_flip_scaled_crc@flip-32bpp-yftileccs-to-64bpp-yftile-upscaling:
    - shard-tglu:         NOTRUN -> [SKIP][261] ([i915#15643]) +3 other tests skip
   [261]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-4/igt@kms_flip_scaled_crc@flip-32bpp-yftileccs-to-64bpp-yftile-upscaling.html

  * igt@kms_flip_scaled_crc@flip-32bpp-ytile-to-32bpp-ytileccs-downscaling:
    - shard-tglu-1:       NOTRUN -> [SKIP][262] ([i915#15643]) +1 other test skip
   [262]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-1/igt@kms_flip_scaled_crc@flip-32bpp-ytile-to-32bpp-ytileccs-downscaling.html

  * igt@kms_flip_scaled_crc@flip-32bpp-ytile-to-32bpp-ytilegen12rcccs-downscaling:
    - shard-dg2:          NOTRUN -> [SKIP][263] ([i915#15643] / [i915#5190]) +2 other tests skip
   [263]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-8/igt@kms_flip_scaled_crc@flip-32bpp-ytile-to-32bpp-ytilegen12rcccs-downscaling.html

  * igt@kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile-upscaling:
    - shard-mtlp:         NOTRUN -> [SKIP][264] ([i915#15643])
   [264]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-mtlp-6/igt@kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile-upscaling.html

  * igt@kms_flip_scaled_crc@flip-64bpp-4tile-to-16bpp-4tile-downscaling:
    - shard-mtlp:         NOTRUN -> [SKIP][265] ([i915#3555] / [i915#8810] / [i915#8813])
   [265]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-mtlp-8/igt@kms_flip_scaled_crc@flip-64bpp-4tile-to-16bpp-4tile-downscaling.html

  * igt@kms_flip_scaled_crc@flip-64bpp-4tile-to-16bpp-4tile-downscaling@pipe-a-default-mode:
    - shard-mtlp:         NOTRUN -> [SKIP][266] ([i915#8810] / [i915#8813])
   [266]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-mtlp-8/igt@kms_flip_scaled_crc@flip-64bpp-4tile-to-16bpp-4tile-downscaling@pipe-a-default-mode.html

  * igt@kms_flip_scaled_crc@flip-64bpp-yftile-to-16bpp-yftile-upscaling:
    - shard-dg1:          NOTRUN -> [SKIP][267] ([i915#15643]) +4 other tests skip
   [267]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-13/igt@kms_flip_scaled_crc@flip-64bpp-yftile-to-16bpp-yftile-upscaling.html

  * igt@kms_flip_scaled_crc@flip-64bpp-yftile-to-32bpp-yftile-upscaling:
    - shard-rkl:          NOTRUN -> [SKIP][268] ([i915#15643]) +2 other tests skip
   [268]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-5/igt@kms_flip_scaled_crc@flip-64bpp-yftile-to-32bpp-yftile-upscaling.html

  * igt@kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-upscaling@pipe-a-valid-mode:
    - shard-glk10:        NOTRUN -> [SKIP][269] +66 other tests skip
   [269]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-glk10/igt@kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-upscaling@pipe-a-valid-mode.html

  * igt@kms_frontbuffer_tracking@fbc-1p-offscreen-pri-shrfb-draw-mmap-gtt:
    - shard-dg1:          NOTRUN -> [SKIP][270] ([i915#15104]) +1 other test skip
   [270]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-18/igt@kms_frontbuffer_tracking@fbc-1p-offscreen-pri-shrfb-draw-mmap-gtt.html

  * igt@kms_frontbuffer_tracking@fbc-1p-primscrn-cur-indfb-onoff:
    - shard-dg2:          [PASS][271] -> [ABORT][272] ([i915#15759])
   [271]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-4/igt@kms_frontbuffer_tracking@fbc-1p-primscrn-cur-indfb-onoff.html
   [272]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-3/igt@kms_frontbuffer_tracking@fbc-1p-primscrn-cur-indfb-onoff.html

  * igt@kms_frontbuffer_tracking@fbc-2p-primscrn-pri-shrfb-draw-mmap-gtt:
    - shard-dg2:          NOTRUN -> [SKIP][273] ([i915#8708]) +16 other tests skip
   [273]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-6/igt@kms_frontbuffer_tracking@fbc-2p-primscrn-pri-shrfb-draw-mmap-gtt.html

  * igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-cur-indfb-draw-render:
    - shard-dg1:          NOTRUN -> [SKIP][274] +39 other tests skip
   [274]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-18/igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-cur-indfb-draw-render.html

  * igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-shrfb-pgflip-blt:
    - shard-snb:          [PASS][275] -> [SKIP][276] +10 other tests skip
   [275]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-snb4/igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-shrfb-pgflip-blt.html
   [276]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-snb1/igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-shrfb-pgflip-blt.html

  * igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-spr-indfb-move:
    - shard-dg2:          NOTRUN -> [SKIP][277] ([i915#5354]) +15 other tests skip
   [277]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-4/igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-spr-indfb-move.html

  * igt@kms_frontbuffer_tracking@fbc-suspend:
    - shard-rkl:          [PASS][278] -> [INCOMPLETE][279] ([i915#10056])
   [278]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-2/igt@kms_frontbuffer_tracking@fbc-suspend.html
   [279]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-4/igt@kms_frontbuffer_tracking@fbc-suspend.html

  * igt@kms_frontbuffer_tracking@fbcpsr-1p-offscreen-pri-shrfb-draw-blt:
    - shard-dg1:          NOTRUN -> [SKIP][280] ([i915#15102]) +4 other tests skip
   [280]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-14/igt@kms_frontbuffer_tracking@fbcpsr-1p-offscreen-pri-shrfb-draw-blt.html

  * igt@kms_frontbuffer_tracking@fbcpsr-1p-primscrn-spr-indfb-move:
    - shard-tglu:         NOTRUN -> [SKIP][281] ([i915#15102]) +15 other tests skip
   [281]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-10/igt@kms_frontbuffer_tracking@fbcpsr-1p-primscrn-spr-indfb-move.html

  * igt@kms_frontbuffer_tracking@fbcpsr-2p-primscrn-pri-indfb-draw-render:
    - shard-tglu-1:       NOTRUN -> [SKIP][282] +37 other tests skip
   [282]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-1/igt@kms_frontbuffer_tracking@fbcpsr-2p-primscrn-pri-indfb-draw-render.html

  * igt@kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-spr-indfb-draw-blt:
    - shard-rkl:          NOTRUN -> [SKIP][283] ([i915#1825]) +14 other tests skip
   [283]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-2/igt@kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-spr-indfb-draw-blt.html

  * igt@kms_frontbuffer_tracking@fbcpsr-rgb101010-draw-blt:
    - shard-dg1:          NOTRUN -> [SKIP][284] ([i915#15102] / [i915#3458]) +20 other tests skip
   [284]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-14/igt@kms_frontbuffer_tracking@fbcpsr-rgb101010-draw-blt.html

  * igt@kms_frontbuffer_tracking@fbcpsr-rgb101010-draw-pwrite:
    - shard-dg2:          NOTRUN -> [SKIP][285] ([i915#10433] / [i915#15102] / [i915#3458])
   [285]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-4/igt@kms_frontbuffer_tracking@fbcpsr-rgb101010-draw-pwrite.html

  * igt@kms_frontbuffer_tracking@fbcpsr-rgb101010-draw-render:
    - shard-tglu-1:       NOTRUN -> [SKIP][286] ([i915#15102]) +15 other tests skip
   [286]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-1/igt@kms_frontbuffer_tracking@fbcpsr-rgb101010-draw-render.html

  * igt@kms_frontbuffer_tracking@fbcpsr-rgb565-draw-blt:
    - shard-rkl:          NOTRUN -> [SKIP][287] ([i915#14544] / [i915#15102] / [i915#3023])
   [287]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-6/igt@kms_frontbuffer_tracking@fbcpsr-rgb565-draw-blt.html

  * igt@kms_frontbuffer_tracking@pipe-fbc-rte:
    - shard-rkl:          NOTRUN -> [SKIP][288] ([i915#9766])
   [288]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-8/igt@kms_frontbuffer_tracking@pipe-fbc-rte.html
    - shard-dg1:          NOTRUN -> [SKIP][289] ([i915#9766])
   [289]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-14/igt@kms_frontbuffer_tracking@pipe-fbc-rte.html

  * igt@kms_frontbuffer_tracking@psr-1p-offscreen-pri-indfb-draw-mmap-gtt:
    - shard-rkl:          NOTRUN -> [SKIP][290] ([i915#15102]) +3 other tests skip
   [290]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-7/igt@kms_frontbuffer_tracking@psr-1p-offscreen-pri-indfb-draw-mmap-gtt.html

  * igt@kms_frontbuffer_tracking@psr-1p-offscreen-pri-indfb-draw-mmap-wc:
    - shard-dg2:          NOTRUN -> [SKIP][291] ([i915#15104])
   [291]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-7/igt@kms_frontbuffer_tracking@psr-1p-offscreen-pri-indfb-draw-mmap-wc.html

  * igt@kms_frontbuffer_tracking@psr-1p-offscreen-pri-shrfb-draw-pwrite:
    - shard-rkl:          NOTRUN -> [SKIP][292] ([i915#14544] / [i915#15102])
   [292]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-6/igt@kms_frontbuffer_tracking@psr-1p-offscreen-pri-shrfb-draw-pwrite.html

  * igt@kms_frontbuffer_tracking@psr-1p-primscrn-cur-indfb-draw-mmap-wc:
    - shard-dg1:          NOTRUN -> [SKIP][293] ([i915#8708]) +13 other tests skip
   [293]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-13/igt@kms_frontbuffer_tracking@psr-1p-primscrn-cur-indfb-draw-mmap-wc.html

  * igt@kms_frontbuffer_tracking@psr-2p-scndscrn-cur-indfb-draw-blt:
    - shard-rkl:          NOTRUN -> [SKIP][294] ([i915#14544] / [i915#1825]) +1 other test skip
   [294]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-6/igt@kms_frontbuffer_tracking@psr-2p-scndscrn-cur-indfb-draw-blt.html

  * igt@kms_frontbuffer_tracking@psr-2p-scndscrn-cur-indfb-draw-pwrite:
    - shard-tglu:         NOTRUN -> [SKIP][295] +52 other tests skip
   [295]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-9/igt@kms_frontbuffer_tracking@psr-2p-scndscrn-cur-indfb-draw-pwrite.html
    - shard-mtlp:         NOTRUN -> [SKIP][296] ([i915#1825]) +4 other tests skip
   [296]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-mtlp-7/igt@kms_frontbuffer_tracking@psr-2p-scndscrn-cur-indfb-draw-pwrite.html

  * igt@kms_frontbuffer_tracking@psr-indfb-scaledprimary:
    - shard-dg2:          NOTRUN -> [SKIP][297] ([i915#15102] / [i915#3458]) +8 other tests skip
   [297]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-8/igt@kms_frontbuffer_tracking@psr-indfb-scaledprimary.html
    - shard-rkl:          NOTRUN -> [SKIP][298] ([i915#15102] / [i915#3023]) +10 other tests skip
   [298]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-8/igt@kms_frontbuffer_tracking@psr-indfb-scaledprimary.html

  * igt@kms_hdmi_inject@inject-4k:
    - shard-mtlp:         [PASS][299] -> [SKIP][300] ([i915#15725])
   [299]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-mtlp-5/igt@kms_hdmi_inject@inject-4k.html
   [300]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-mtlp-1/igt@kms_hdmi_inject@inject-4k.html

  * igt@kms_hdr@bpc-switch:
    - shard-dg1:          NOTRUN -> [SKIP][301] ([i915#3555] / [i915#8228]) +1 other test skip
   [301]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-12/igt@kms_hdr@bpc-switch.html
    - shard-dg2:          NOTRUN -> [SKIP][302] ([i915#3555] / [i915#8228])
   [302]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-5/igt@kms_hdr@bpc-switch.html

  * igt@kms_hdr@brightness-with-hdr:
    - shard-dg2:          NOTRUN -> [SKIP][303] ([i915#12713])
   [303]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-4/igt@kms_hdr@brightness-with-hdr.html
    - shard-tglu:         NOTRUN -> [SKIP][304] ([i915#12713])
   [304]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-10/igt@kms_hdr@brightness-with-hdr.html

  * igt@kms_hdr@static-swap:
    - shard-tglu-1:       NOTRUN -> [SKIP][305] ([i915#3555] / [i915#8228])
   [305]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-1/igt@kms_hdr@static-swap.html

  * igt@kms_hdr@static-toggle-dpms:
    - shard-tglu:         NOTRUN -> [SKIP][306] ([i915#3555] / [i915#8228])
   [306]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-2/igt@kms_hdr@static-toggle-dpms.html

  * igt@kms_joiner@basic-force-ultra-joiner:
    - shard-tglu:         NOTRUN -> [SKIP][307] ([i915#15458])
   [307]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-7/igt@kms_joiner@basic-force-ultra-joiner.html
    - shard-rkl:          NOTRUN -> [SKIP][308] ([i915#15458])
   [308]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-2/igt@kms_joiner@basic-force-ultra-joiner.html

  * igt@kms_joiner@basic-max-non-joiner:
    - shard-dg1:          NOTRUN -> [SKIP][309] ([i915#13688])
   [309]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-18/igt@kms_joiner@basic-max-non-joiner.html

  * igt@kms_joiner@invalid-modeset-force-big-joiner:
    - shard-dg1:          NOTRUN -> [SKIP][310] ([i915#15459])
   [310]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-13/igt@kms_joiner@invalid-modeset-force-big-joiner.html

  * igt@kms_joiner@invalid-modeset-ultra-joiner:
    - shard-dg2:          NOTRUN -> [SKIP][311] ([i915#15458]) +1 other test skip
   [311]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-4/igt@kms_joiner@invalid-modeset-ultra-joiner.html

  * igt@kms_panel_fitting@atomic-fastset:
    - shard-dg2:          NOTRUN -> [SKIP][312] ([i915#6301])
   [312]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-5/igt@kms_panel_fitting@atomic-fastset.html

  * igt@kms_panel_fitting@legacy:
    - shard-tglu:         NOTRUN -> [SKIP][313] ([i915#6301])
   [313]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-7/igt@kms_panel_fitting@legacy.html
    - shard-rkl:          NOTRUN -> [SKIP][314] ([i915#6301])
   [314]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-2/igt@kms_panel_fitting@legacy.html
    - shard-dg1:          NOTRUN -> [SKIP][315] ([i915#6301])
   [315]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-14/igt@kms_panel_fitting@legacy.html

  * igt@kms_pipe_stress@stress-xrgb8888-4tiled:
    - shard-dg1:          NOTRUN -> [SKIP][316] ([i915#14712])
   [316]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-17/igt@kms_pipe_stress@stress-xrgb8888-4tiled.html

  * igt@kms_pipe_stress@stress-xrgb8888-ytiled:
    - shard-dg2:          NOTRUN -> [SKIP][317] ([i915#13705])
   [317]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-8/igt@kms_pipe_stress@stress-xrgb8888-ytiled.html

  * igt@kms_plane@pixel-format-4-tiled-bmg-ccs-modifier:
    - shard-mtlp:         NOTRUN -> [SKIP][318] ([i915#15709]) +1 other test skip
   [318]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-mtlp-3/igt@kms_plane@pixel-format-4-tiled-bmg-ccs-modifier.html

  * igt@kms_plane@pixel-format-4-tiled-dg2-mc-ccs-modifier:
    - shard-dg2:          NOTRUN -> [SKIP][319] ([i915#15709]) +4 other tests skip
   [319]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-8/igt@kms_plane@pixel-format-4-tiled-dg2-mc-ccs-modifier.html

  * igt@kms_plane@pixel-format-4-tiled-dg2-mc-ccs-modifier-source-clamping:
    - shard-tglu:         NOTRUN -> [SKIP][320] ([i915#15709]) +3 other tests skip
   [320]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-2/igt@kms_plane@pixel-format-4-tiled-dg2-mc-ccs-modifier-source-clamping.html

  * igt@kms_plane@pixel-format-4-tiled-dg2-rc-ccs-modifier:
    - shard-rkl:          NOTRUN -> [SKIP][321] ([i915#15709]) +3 other tests skip
   [321]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-4/igt@kms_plane@pixel-format-4-tiled-dg2-rc-ccs-modifier.html

  * igt@kms_plane@pixel-format-4-tiled-mtl-rc-ccs-modifier:
    - shard-tglu-1:       NOTRUN -> [SKIP][322] ([i915#15709]) +3 other tests skip
   [322]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-1/igt@kms_plane@pixel-format-4-tiled-mtl-rc-ccs-modifier.html

  * igt@kms_plane@pixel-format-y-tiled-gen12-mc-ccs-modifier-source-clamping:
    - shard-dg1:          NOTRUN -> [SKIP][323] ([i915#15709]) +4 other tests skip
   [323]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-14/igt@kms_plane@pixel-format-y-tiled-gen12-mc-ccs-modifier-source-clamping.html

  * igt@kms_plane@pixel-format-y-tiled-gen12-rc-ccs-cc-modifier@pipe-a-plane-7:
    - shard-dg1:          NOTRUN -> [SKIP][324] ([i915#15608]) +3 other tests skip
   [324]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-16/igt@kms_plane@pixel-format-y-tiled-gen12-rc-ccs-cc-modifier@pipe-a-plane-7.html
    - shard-tglu:         NOTRUN -> [SKIP][325] ([i915#15608]) +1 other test skip
   [325]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-10/igt@kms_plane@pixel-format-y-tiled-gen12-rc-ccs-cc-modifier@pipe-a-plane-7.html

  * igt@kms_plane@pixel-format-y-tiled-gen12-rc-ccs-cc-modifier@pipe-b-plane-5:
    - shard-rkl:          NOTRUN -> [SKIP][326] ([i915#15608]) +1 other test skip
   [326]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-7/igt@kms_plane@pixel-format-y-tiled-gen12-rc-ccs-cc-modifier@pipe-b-plane-5.html

  * igt@kms_plane_lowres@tiling-yf:
    - shard-tglu-1:       NOTRUN -> [SKIP][327] ([i915#3555]) +2 other tests skip
   [327]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-1/igt@kms_plane_lowres@tiling-yf.html

  * igt@kms_plane_multiple@2x-tiling-x:
    - shard-dg1:          NOTRUN -> [SKIP][328] ([i915#13958])
   [328]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-12/igt@kms_plane_multiple@2x-tiling-x.html

  * igt@kms_plane_multiple@tiling-yf:
    - shard-tglu-1:       NOTRUN -> [SKIP][329] ([i915#14259])
   [329]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-1/igt@kms_plane_multiple@tiling-yf.html

  * igt@kms_plane_scaling@intel-max-src-size:
    - shard-rkl:          [PASS][330] -> [SKIP][331] ([i915#6953])
   [330]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-6/igt@kms_plane_scaling@intel-max-src-size.html
   [331]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-4/igt@kms_plane_scaling@intel-max-src-size.html

  * igt@kms_plane_scaling@plane-downscale-factor-0-75-with-rotation@pipe-a:
    - shard-dg1:          NOTRUN -> [SKIP][332] ([i915#15329]) +4 other tests skip
   [332]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-13/igt@kms_plane_scaling@plane-downscale-factor-0-75-with-rotation@pipe-a.html

  * igt@kms_plane_scaling@plane-scaler-unity-scaling-with-modifiers:
    - shard-dg2:          NOTRUN -> [SKIP][333] ([i915#15689] / [i915#9423])
   [333]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_plane_scaling@plane-scaler-unity-scaling-with-modifiers.html

  * igt@kms_plane_scaling@plane-scaler-with-clipping-clamping-rotation:
    - shard-tglu-1:       NOTRUN -> [SKIP][334] ([i915#15329] / [i915#3555])
   [334]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-1/igt@kms_plane_scaling@plane-scaler-with-clipping-clamping-rotation.html

  * igt@kms_plane_scaling@plane-scaler-with-clipping-clamping-rotation@pipe-b:
    - shard-tglu-1:       NOTRUN -> [SKIP][335] ([i915#15329]) +3 other tests skip
   [335]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-1/igt@kms_plane_scaling@plane-scaler-with-clipping-clamping-rotation@pipe-b.html

  * igt@kms_plane_scaling@planes-downscale-factor-0-5-upscale-20x20:
    - shard-dg2:          [PASS][336] -> [SKIP][337] ([i915#15689] / [i915#9423]) +6 other tests skip
   [336]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-4/igt@kms_plane_scaling@planes-downscale-factor-0-5-upscale-20x20.html
   [337]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_plane_scaling@planes-downscale-factor-0-5-upscale-20x20.html

  * igt@kms_plane_scaling@planes-upscale-factor-0-25-downscale-factor-0-75:
    - shard-mtlp:         NOTRUN -> [SKIP][338] ([i915#15329] / [i915#3555] / [i915#6953])
   [338]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-mtlp-3/igt@kms_plane_scaling@planes-upscale-factor-0-25-downscale-factor-0-75.html

  * igt@kms_plane_scaling@planes-upscale-factor-0-25-downscale-factor-0-75@pipe-a:
    - shard-mtlp:         NOTRUN -> [SKIP][339] ([i915#15329]) +3 other tests skip
   [339]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-mtlp-3/igt@kms_plane_scaling@planes-upscale-factor-0-25-downscale-factor-0-75@pipe-a.html

  * igt@kms_pm_backlight@bad-brightness:
    - shard-dg1:          NOTRUN -> [SKIP][340] ([i915#5354]) +1 other test skip
   [340]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-12/igt@kms_pm_backlight@bad-brightness.html

  * igt@kms_pm_backlight@fade:
    - shard-tglu:         NOTRUN -> [SKIP][341] ([i915#9812])
   [341]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-7/igt@kms_pm_backlight@fade.html
    - shard-rkl:          NOTRUN -> [SKIP][342] ([i915#5354])
   [342]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-2/igt@kms_pm_backlight@fade.html

  * igt@kms_pm_dc@dc6-psr:
    - shard-rkl:          NOTRUN -> [SKIP][343] ([i915#9685])
   [343]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-8/igt@kms_pm_dc@dc6-psr.html
    - shard-tglu-1:       NOTRUN -> [SKIP][344] ([i915#9685])
   [344]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-1/igt@kms_pm_dc@dc6-psr.html

  * igt@kms_pm_lpsp@kms-lpsp:
    - shard-tglu-1:       NOTRUN -> [SKIP][345] ([i915#3828])
   [345]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-1/igt@kms_pm_lpsp@kms-lpsp.html

  * igt@kms_pm_rpm@dpms-non-lpsp:
    - shard-dg1:          [PASS][346] -> [SKIP][347] ([i915#15073])
   [346]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg1-13/igt@kms_pm_rpm@dpms-non-lpsp.html
   [347]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-14/igt@kms_pm_rpm@dpms-non-lpsp.html

  * igt@kms_pm_rpm@modeset-non-lpsp:
    - shard-tglu:         NOTRUN -> [SKIP][348] ([i915#15073])
   [348]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-2/igt@kms_pm_rpm@modeset-non-lpsp.html

  * igt@kms_pm_rpm@modeset-non-lpsp-stress:
    - shard-rkl:          NOTRUN -> [SKIP][349] ([i915#15073])
   [349]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-8/igt@kms_pm_rpm@modeset-non-lpsp-stress.html
    - shard-dg1:          NOTRUN -> [SKIP][350] ([i915#15073])
   [350]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-14/igt@kms_pm_rpm@modeset-non-lpsp-stress.html

  * igt@kms_pm_rpm@package-g7:
    - shard-dg2:          NOTRUN -> [SKIP][351] ([i915#15403])
   [351]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-3/igt@kms_pm_rpm@package-g7.html

  * igt@kms_pm_rpm@system-suspend-modeset:
    - shard-rkl:          [PASS][352] -> [INCOMPLETE][353] ([i915#14419])
   [352]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-7/igt@kms_pm_rpm@system-suspend-modeset.html
   [353]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-6/igt@kms_pm_rpm@system-suspend-modeset.html

  * igt@kms_prime@d3hot:
    - shard-dg1:          NOTRUN -> [SKIP][354] ([i915#6524]) +1 other test skip
   [354]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-14/igt@kms_prime@d3hot.html
    - shard-tglu:         NOTRUN -> [SKIP][355] ([i915#6524])
   [355]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-9/igt@kms_prime@d3hot.html

  * igt@kms_properties@invalid-properties-atomic:
    - shard-dg1:          NOTRUN -> [DMESG-WARN][356] ([i915#4391] / [i915#4423])
   [356]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-12/igt@kms_properties@invalid-properties-atomic.html

  * igt@kms_psr2_sf@fbc-pr-cursor-plane-move-continuous-exceed-sf:
    - shard-dg2:          NOTRUN -> [SKIP][357] ([i915#11520]) +4 other tests skip
   [357]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-4/igt@kms_psr2_sf@fbc-pr-cursor-plane-move-continuous-exceed-sf.html

  * igt@kms_psr2_sf@fbc-pr-overlay-plane-update-continuous-sf:
    - shard-mtlp:         NOTRUN -> [SKIP][358] ([i915#12316])
   [358]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-mtlp-2/igt@kms_psr2_sf@fbc-pr-overlay-plane-update-continuous-sf.html

  * igt@kms_psr2_sf@fbc-psr2-cursor-plane-move-continuous-sf:
    - shard-dg1:          NOTRUN -> [SKIP][359] ([i915#11520]) +9 other tests skip
   [359]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-14/igt@kms_psr2_sf@fbc-psr2-cursor-plane-move-continuous-sf.html

  * igt@kms_psr2_sf@fbc-psr2-primary-plane-update-sf-dmg-area:
    - shard-glk:          NOTRUN -> [SKIP][360] ([i915#11520]) +7 other tests skip
   [360]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-glk9/igt@kms_psr2_sf@fbc-psr2-primary-plane-update-sf-dmg-area.html

  * igt@kms_psr2_sf@pr-overlay-plane-update-sf-dmg-area:
    - shard-rkl:          NOTRUN -> [SKIP][361] ([i915#11520]) +5 other tests skip
   [361]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-8/igt@kms_psr2_sf@pr-overlay-plane-update-sf-dmg-area.html

  * igt@kms_psr2_sf@psr2-overlay-plane-move-continuous-exceed-fully-sf:
    - shard-tglu:         NOTRUN -> [SKIP][362] ([i915#11520]) +7 other tests skip
   [362]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-8/igt@kms_psr2_sf@psr2-overlay-plane-move-continuous-exceed-fully-sf.html

  * igt@kms_psr2_sf@psr2-overlay-plane-move-continuous-sf:
    - shard-tglu-1:       NOTRUN -> [SKIP][363] ([i915#11520]) +3 other tests skip
   [363]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-1/igt@kms_psr2_sf@psr2-overlay-plane-move-continuous-sf.html

  * igt@kms_psr2_su@page_flip-p010:
    - shard-dg2:          NOTRUN -> [SKIP][364] ([i915#9683])
   [364]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-1/igt@kms_psr2_su@page_flip-p010.html

  * igt@kms_psr@fbc-pr-no-drrs:
    - shard-rkl:          NOTRUN -> [SKIP][365] ([i915#1072] / [i915#9732]) +13 other tests skip
   [365]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-5/igt@kms_psr@fbc-pr-no-drrs.html

  * igt@kms_psr@fbc-psr-cursor-mmap-cpu:
    - shard-dg2:          NOTRUN -> [SKIP][366] ([i915#1072] / [i915#9732]) +15 other tests skip
   [366]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-6/igt@kms_psr@fbc-psr-cursor-mmap-cpu.html

  * igt@kms_psr@fbc-psr-no-drrs:
    - shard-tglu:         NOTRUN -> [SKIP][367] ([i915#9732]) +17 other tests skip
   [367]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-9/igt@kms_psr@fbc-psr-no-drrs.html

  * igt@kms_psr@pr-cursor-mmap-gtt:
    - shard-tglu-1:       NOTRUN -> [SKIP][368] ([i915#9732]) +11 other tests skip
   [368]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-1/igt@kms_psr@pr-cursor-mmap-gtt.html

  * igt@kms_psr@pr-suspend:
    - shard-mtlp:         NOTRUN -> [SKIP][369] ([i915#9688]) +2 other tests skip
   [369]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-mtlp-5/igt@kms_psr@pr-suspend.html

  * igt@kms_psr@psr2-primary-mmap-cpu:
    - shard-dg1:          NOTRUN -> [SKIP][370] ([i915#1072] / [i915#9732]) +24 other tests skip
   [370]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-12/igt@kms_psr@psr2-primary-mmap-cpu.html

  * igt@kms_psr_stress_test@flip-primary-invalidate-overlay:
    - shard-tglu:         NOTRUN -> [SKIP][371] ([i915#9685]) +1 other test skip
   [371]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-4/igt@kms_psr_stress_test@flip-primary-invalidate-overlay.html

  * igt@kms_rotation_crc@bad-pixel-format:
    - shard-dg2:          NOTRUN -> [SKIP][372] ([i915#12755])
   [372]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-4/igt@kms_rotation_crc@bad-pixel-format.html

  * igt@kms_rotation_crc@exhaust-fences:
    - shard-dg1:          NOTRUN -> [SKIP][373] ([i915#4884])
   [373]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-17/igt@kms_rotation_crc@exhaust-fences.html

  * igt@kms_rotation_crc@multiplane-rotation-cropping-bottom:
    - shard-dg1:          NOTRUN -> [ABORT][374] ([i915#15759]) +1 other test abort
   [374]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-13/igt@kms_rotation_crc@multiplane-rotation-cropping-bottom.html

  * igt@kms_rotation_crc@primary-4-tiled-reflect-x-180:
    - shard-tglu-1:       NOTRUN -> [SKIP][375] ([i915#5289])
   [375]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-1/igt@kms_rotation_crc@primary-4-tiled-reflect-x-180.html

  * igt@kms_rotation_crc@primary-yf-tiled-reflect-x-270:
    - shard-dg1:          NOTRUN -> [SKIP][376] ([i915#5289]) +1 other test skip
   [376]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-12/igt@kms_rotation_crc@primary-yf-tiled-reflect-x-270.html

  * igt@kms_rotation_crc@sprite-rotation-90:
    - shard-dg1:          [PASS][377] -> [ABORT][378] ([i915#15759]) +2 other tests abort
   [377]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg1-13/igt@kms_rotation_crc@sprite-rotation-90.html
   [378]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-16/igt@kms_rotation_crc@sprite-rotation-90.html

  * igt@kms_scaling_modes@scaling-mode-full-aspect:
    - shard-rkl:          NOTRUN -> [SKIP][379] ([i915#3555]) +2 other tests skip
   [379]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-7/igt@kms_scaling_modes@scaling-mode-full-aspect.html

  * igt@kms_selftest@drm_framebuffer:
    - shard-dg1:          NOTRUN -> [ABORT][380] ([i915#13179]) +1 other test abort
   [380]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-13/igt@kms_selftest@drm_framebuffer.html

  * {igt@kms_usb4_switch@dock-during-suspend} (NEW):
    - shard-snb:          NOTRUN -> [SKIP][381] +78 other tests skip
   [381]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-snb7/igt@kms_usb4_switch@dock-during-suspend.html

  * igt@kms_vrr@flipline:
    - shard-dg2:          NOTRUN -> [SKIP][382] ([i915#15243] / [i915#3555])
   [382]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-5/igt@kms_vrr@flipline.html

  * igt@kms_vrr@negative-basic:
    - shard-tglu-1:       NOTRUN -> [SKIP][383] ([i915#3555] / [i915#9906])
   [383]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-1/igt@kms_vrr@negative-basic.html

  * igt@kms_vrr@seamless-rr-switch-virtual:
    - shard-dg2:          NOTRUN -> [SKIP][384] ([i915#9906]) +1 other test skip
   [384]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-7/igt@kms_vrr@seamless-rr-switch-virtual.html
    - shard-rkl:          NOTRUN -> [SKIP][385] ([i915#9906]) +1 other test skip
   [385]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-3/igt@kms_vrr@seamless-rr-switch-virtual.html
    - shard-tglu:         NOTRUN -> [SKIP][386] ([i915#9906])
   [386]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-4/igt@kms_vrr@seamless-rr-switch-virtual.html

  * igt@kms_vrr@seamless-rr-switch-vrr:
    - shard-dg1:          NOTRUN -> [SKIP][387] ([i915#9906]) +1 other test skip
   [387]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-17/igt@kms_vrr@seamless-rr-switch-vrr.html

  * igt@perf@invalid-oa-exponent:
    - shard-dg2:          [PASS][388] -> [SKIP][389] ([i915#15607])
   [388]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-1/igt@perf@invalid-oa-exponent.html
   [389]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@perf@invalid-oa-exponent.html

  * igt@perf@per-context-mode-unprivileged:
    - shard-rkl:          NOTRUN -> [SKIP][390] ([i915#2435])
   [390]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-3/igt@perf@per-context-mode-unprivileged.html
    - shard-dg1:          NOTRUN -> [SKIP][391] ([i915#2433])
   [391]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-17/igt@perf@per-context-mode-unprivileged.html

  * igt@perf@unprivileged-single-ctx-counters:
    - shard-rkl:          NOTRUN -> [SKIP][392] ([i915#2433])
   [392]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-8/igt@perf@unprivileged-single-ctx-counters.html

  * igt@perf_pmu@busy-double-start@rcs0:
    - shard-mtlp:         [PASS][393] -> [FAIL][394] ([i915#4349])
   [393]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-mtlp-1/igt@perf_pmu@busy-double-start@rcs0.html
   [394]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-mtlp-5/igt@perf_pmu@busy-double-start@rcs0.html

  * igt@perf_pmu@rc6-suspend:
    - shard-glk:          NOTRUN -> [INCOMPLETE][395] ([i915#13356] / [i915#14242])
   [395]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-glk2/igt@perf_pmu@rc6-suspend.html

  * igt@prime_mmap@test_aperture_limit@test_aperture_limit-smem:
    - shard-dg1:          NOTRUN -> [SKIP][396] ([i915#14121]) +1 other test skip
   [396]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-14/igt@prime_mmap@test_aperture_limit@test_aperture_limit-smem.html
    - shard-dg2:          NOTRUN -> [SKIP][397] ([i915#14121])
   [397]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-6/igt@prime_mmap@test_aperture_limit@test_aperture_limit-smem.html

  * igt@prime_vgem@basic-write:
    - shard-dg2:          NOTRUN -> [SKIP][398] ([i915#3291] / [i915#3708])
   [398]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-1/igt@prime_vgem@basic-write.html

  * igt@prime_vgem@coherency-gtt:
    - shard-rkl:          NOTRUN -> [SKIP][399] ([i915#3708]) +1 other test skip
   [399]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-8/igt@prime_vgem@coherency-gtt.html
    - shard-dg1:          NOTRUN -> [SKIP][400] ([i915#3708] / [i915#4077])
   [400]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-18/igt@prime_vgem@coherency-gtt.html

  * igt@prime_vgem@fence-write-hang:
    - shard-dg2:          NOTRUN -> [SKIP][401] ([i915#3708]) +2 other tests skip
   [401]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-4/igt@prime_vgem@fence-write-hang.html

  * igt@sriov_basic@bind-unbind-vf:
    - shard-dg2:          NOTRUN -> [SKIP][402] ([i915#9917])
   [402]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-6/igt@sriov_basic@bind-unbind-vf.html

  * igt@sriov_basic@enable-vfs-bind-unbind-each:
    - shard-dg1:          NOTRUN -> [SKIP][403] ([i915#9917])
   [403]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-16/igt@sriov_basic@enable-vfs-bind-unbind-each.html

  * igt@sriov_basic@enable-vfs-bind-unbind-each-numvfs-all:
    - shard-tglu:         NOTRUN -> [FAIL][404] ([i915#12910])
   [404]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-2/igt@sriov_basic@enable-vfs-bind-unbind-each-numvfs-all.html
    - shard-rkl:          NOTRUN -> [SKIP][405] ([i915#9917])
   [405]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-4/igt@sriov_basic@enable-vfs-bind-unbind-each-numvfs-all.html

  
#### Possible fixes ####

  * igt@fbdev@eof:
    - shard-dg2:          [SKIP][406] ([i915#2582]) -> [PASS][407] +2 other tests pass
   [406]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@fbdev@eof.html
   [407]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-7/igt@fbdev@eof.html

  * igt@fbdev@info:
    - shard-dg2:          [SKIP][408] ([i915#1849] / [i915#2582]) -> [PASS][409]
   [408]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@fbdev@info.html
   [409]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-6/igt@fbdev@info.html

  * igt@fbdev@pan:
    - shard-snb:          [FAIL][410] -> [PASS][411]
   [410]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-snb4/igt@fbdev@pan.html
   [411]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-snb6/igt@fbdev@pan.html

  * igt@gem_ctx_isolation@preservation-s3:
    - shard-rkl:          [INCOMPLETE][412] ([i915#13356]) -> [PASS][413] +1 other test pass
   [412]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-6/igt@gem_ctx_isolation@preservation-s3.html
   [413]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-2/igt@gem_ctx_isolation@preservation-s3.html

  * igt@gem_exec_schedule@preempt-self:
    - shard-dg2:          [SKIP][414] ([i915#15689] / [i915#2575]) -> [PASS][415] +118 other tests pass
   [414]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@gem_exec_schedule@preempt-self.html
   [415]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-5/igt@gem_exec_schedule@preempt-self.html

  * igt@gem_lmem_swapping@parallel-random-verify-ccs:
    - shard-dg2:          [ABORT][416] -> [PASS][417]
   [416]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-8/igt@gem_lmem_swapping@parallel-random-verify-ccs.html
   [417]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-4/igt@gem_lmem_swapping@parallel-random-verify-ccs.html

  * igt@gem_lmem_swapping@smem-oom:
    - shard-dg2:          [FAIL][418] ([i915#15734]) -> [PASS][419]
   [418]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-5/igt@gem_lmem_swapping@smem-oom.html
   [419]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-6/igt@gem_lmem_swapping@smem-oom.html

  * igt@gem_lmem_swapping@smem-oom@lmem0:
    - shard-dg2:          [CRASH][420] ([i915#5493]) -> [PASS][421]
   [420]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-5/igt@gem_lmem_swapping@smem-oom@lmem0.html
   [421]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-6/igt@gem_lmem_swapping@smem-oom@lmem0.html

  * igt@gem_softpin@allocator-basic-reserve:
    - shard-dg1:          [ABORT][422] ([i915#15759]) -> [PASS][423] +4 other tests pass
   [422]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg1-18/igt@gem_softpin@allocator-basic-reserve.html
   [423]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-18/igt@gem_softpin@allocator-basic-reserve.html

  * igt@i915_drm_fdinfo@memory-info-purgeable:
    - shard-dg2:          [ABORT][424] ([i915#15759]) -> [PASS][425] +5 other tests pass
   [424]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-7/igt@i915_drm_fdinfo@memory-info-purgeable.html
   [425]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-6/igt@i915_drm_fdinfo@memory-info-purgeable.html

  * igt@i915_pm_rpm@system-suspend-execbuf:
    - shard-dg1:          [ABORT][426] ([i915#13562]) -> [PASS][427]
   [426]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg1-13/igt@i915_pm_rpm@system-suspend-execbuf.html
   [427]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-18/igt@i915_pm_rpm@system-suspend-execbuf.html

  * igt@i915_selftest@perf:
    - shard-dg2:          [FAIL][428] -> [PASS][429] +5 other tests pass
   [428]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@i915_selftest@perf.html
   [429]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-7/igt@i915_selftest@perf.html

  * igt@kms_cursor_crc@cursor-sliding-64x21:
    - shard-rkl:          [FAIL][430] ([i915#13566]) -> [PASS][431] +1 other test pass
   [430]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-5/igt@kms_cursor_crc@cursor-sliding-64x21.html
   [431]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-5/igt@kms_cursor_crc@cursor-sliding-64x21.html

  * igt@kms_cursor_legacy@cursora-vs-flipb-legacy:
    - shard-snb:          [SKIP][432] -> [PASS][433] +11 other tests pass
   [432]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-snb1/igt@kms_cursor_legacy@cursora-vs-flipb-legacy.html
   [433]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-snb4/igt@kms_cursor_legacy@cursora-vs-flipb-legacy.html

  * igt@kms_flip@2x-flip-vs-suspend-interruptible:
    - shard-snb:          [TIMEOUT][434] ([i915#14033] / [i915#14350]) -> [PASS][435]
   [434]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-snb4/igt@kms_flip@2x-flip-vs-suspend-interruptible.html
   [435]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-snb7/igt@kms_flip@2x-flip-vs-suspend-interruptible.html

  * igt@kms_flip@2x-flip-vs-suspend-interruptible@ab-vga1-hdmi-a1:
    - shard-snb:          [TIMEOUT][436] ([i915#14033]) -> [PASS][437] +2 other tests pass
   [436]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-snb4/igt@kms_flip@2x-flip-vs-suspend-interruptible@ab-vga1-hdmi-a1.html
   [437]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-snb7/igt@kms_flip@2x-flip-vs-suspend-interruptible@ab-vga1-hdmi-a1.html

  * igt@kms_frontbuffer_tracking@fbc-1p-primscrn-cur-indfb-draw-render:
    - shard-dg2:          [FAIL][438] ([i915#15389] / [i915#6880]) -> [PASS][439]
   [438]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-5/igt@kms_frontbuffer_tracking@fbc-1p-primscrn-cur-indfb-draw-render.html
   [439]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-1/igt@kms_frontbuffer_tracking@fbc-1p-primscrn-cur-indfb-draw-render.html

  * igt@kms_frontbuffer_tracking@fbc-1p-primscrn-cur-indfb-move:
    - shard-dg2:          [SKIP][440] ([i915#15689]) -> [PASS][441] +132 other tests pass
   [440]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@kms_frontbuffer_tracking@fbc-1p-primscrn-cur-indfb-move.html
   [441]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-5/igt@kms_frontbuffer_tracking@fbc-1p-primscrn-cur-indfb-move.html

  * igt@kms_hdr@static-swap:
    - shard-rkl:          [SKIP][442] ([i915#3555] / [i915#8228]) -> [PASS][443]
   [442]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-2/igt@kms_hdr@static-swap.html
   [443]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-6/igt@kms_hdr@static-swap.html

  * igt@kms_plane_scaling@plane-upscale-20x20-with-pixel-format:
    - shard-dg2:          [SKIP][444] ([i915#15689] / [i915#9423]) -> [PASS][445] +4 other tests pass
   [444]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@kms_plane_scaling@plane-upscale-20x20-with-pixel-format.html
   [445]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-8/igt@kms_plane_scaling@plane-upscale-20x20-with-pixel-format.html

  * igt@kms_pm_rpm@dpms-mode-unset-non-lpsp:
    - shard-dg2:          [SKIP][446] ([i915#15073]) -> [PASS][447]
   [446]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-4/igt@kms_pm_rpm@dpms-mode-unset-non-lpsp.html
   [447]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-7/igt@kms_pm_rpm@dpms-mode-unset-non-lpsp.html

  * igt@kms_pm_rpm@modeset-lpsp:
    - shard-rkl:          [SKIP][448] ([i915#15073]) -> [PASS][449] +1 other test pass
   [448]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-4/igt@kms_pm_rpm@modeset-lpsp.html
   [449]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-8/igt@kms_pm_rpm@modeset-lpsp.html

  * igt@kms_pm_rpm@modeset-lpsp-stress:
    - shard-dg1:          [SKIP][450] ([i915#15073]) -> [PASS][451]
   [450]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg1-17/igt@kms_pm_rpm@modeset-lpsp-stress.html
   [451]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-14/igt@kms_pm_rpm@modeset-lpsp-stress.html

  * igt@perf@i915-ref-count:
    - shard-dg2:          [SKIP][452] ([i915#15607]) -> [PASS][453] +1 other test pass
   [452]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@perf@i915-ref-count.html
   [453]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-4/igt@perf@i915-ref-count.html

  * igt@perf@low-oa-exponent-permissions:
    - shard-dg2:          [SKIP][454] -> [PASS][455] +16 other tests pass
   [454]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@perf@low-oa-exponent-permissions.html
   [455]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-3/igt@perf@low-oa-exponent-permissions.html

  * igt@perf_pmu@all-busy-idle-check-all:
    - shard-dg2:          [FAIL][456] ([i915#15453]) -> [PASS][457]
   [456]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-1/igt@perf_pmu@all-busy-idle-check-all.html
   [457]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-3/igt@perf_pmu@all-busy-idle-check-all.html
    - shard-mtlp:         [FAIL][458] ([i915#15453]) -> [PASS][459]
   [458]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-mtlp-7/igt@perf_pmu@all-busy-idle-check-all.html
   [459]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-mtlp-2/igt@perf_pmu@all-busy-idle-check-all.html

  * igt@perf_pmu@busy-double-start@vecs0:
    - shard-mtlp:         [FAIL][460] ([i915#4349]) -> [PASS][461] +1 other test pass
   [460]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-mtlp-1/igt@perf_pmu@busy-double-start@vecs0.html
   [461]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-mtlp-5/igt@perf_pmu@busy-double-start@vecs0.html

  
#### Warnings ####

  * igt@gem_ccs@ctrl-surf-copy:
    - shard-rkl:          [SKIP][462] ([i915#14544] / [i915#3555] / [i915#9323]) -> [SKIP][463] ([i915#3555] / [i915#9323])
   [462]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-6/igt@gem_ccs@ctrl-surf-copy.html
   [463]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-3/igt@gem_ccs@ctrl-surf-copy.html

  * igt@gem_ctx_sseu@invalid-sseu:
    - shard-dg2:          [SKIP][464] ([i915#280]) -> [SKIP][465] ([i915#15689] / [i915#2575]) +1 other test skip
   [464]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-4/igt@gem_ctx_sseu@invalid-sseu.html
   [465]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@gem_ctx_sseu@invalid-sseu.html

  * igt@gem_exec_balancer@bonded-dual:
    - shard-dg2:          [SKIP][466] ([i915#15689] / [i915#2575]) -> [SKIP][467] ([i915#4771])
   [466]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@gem_exec_balancer@bonded-dual.html
   [467]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-5/igt@gem_exec_balancer@bonded-dual.html

  * igt@gem_exec_balancer@bonded-false-hang:
    - shard-dg2:          [SKIP][468] ([i915#15689] / [i915#2575]) -> [SKIP][469] ([i915#4812])
   [468]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@gem_exec_balancer@bonded-false-hang.html
   [469]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-4/igt@gem_exec_balancer@bonded-false-hang.html

  * igt@gem_exec_balancer@bonded-sync:
    - shard-dg2:          [SKIP][470] ([i915#4771]) -> [SKIP][471] ([i915#15689] / [i915#2575])
   [470]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-4/igt@gem_exec_balancer@bonded-sync.html
   [471]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@gem_exec_balancer@bonded-sync.html

  * igt@gem_exec_balancer@invalid-bonds:
    - shard-dg2:          [SKIP][472] ([i915#4036]) -> [SKIP][473] ([i915#15689] / [i915#2575])
   [472]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-5/igt@gem_exec_balancer@invalid-bonds.html
   [473]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@gem_exec_balancer@invalid-bonds.html

  * igt@gem_exec_capture@capture:
    - shard-dg2:          [FAIL][474] ([i915#11965]) -> [SKIP][475] ([i915#15689] / [i915#2575])
   [474]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-3/igt@gem_exec_capture@capture.html
   [475]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@gem_exec_capture@capture.html

  * igt@gem_exec_flush@basic-batch-kernel-default-cmd:
    - shard-dg2:          [SKIP][476] ([i915#3539] / [i915#4852]) -> [SKIP][477] ([i915#15689] / [i915#2575])
   [476]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-4/igt@gem_exec_flush@basic-batch-kernel-default-cmd.html
   [477]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@gem_exec_flush@basic-batch-kernel-default-cmd.html

  * igt@gem_exec_flush@basic-uc-set-default:
    - shard-dg2:          [SKIP][478] ([i915#15689] / [i915#2575]) -> [SKIP][479] ([i915#3539])
   [478]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@gem_exec_flush@basic-uc-set-default.html
   [479]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-8/igt@gem_exec_flush@basic-uc-set-default.html

  * igt@gem_exec_flush@basic-wb-prw-default:
    - shard-dg2:          [SKIP][480] ([i915#15689] / [i915#2575]) -> [SKIP][481] ([i915#3539] / [i915#4852]) +3 other tests skip
   [480]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@gem_exec_flush@basic-wb-prw-default.html
   [481]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-8/igt@gem_exec_flush@basic-wb-prw-default.html

  * igt@gem_exec_params@rsvd2-dirt:
    - shard-dg2:          [SKIP][482] ([i915#15689] / [i915#2575]) -> [SKIP][483] ([i915#5107])
   [482]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@gem_exec_params@rsvd2-dirt.html
   [483]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-3/igt@gem_exec_params@rsvd2-dirt.html

  * igt@gem_exec_reloc@basic-cpu-gtt-noreloc:
    - shard-dg2:          [SKIP][484] ([i915#15689] / [i915#2575]) -> [SKIP][485] ([i915#3281]) +3 other tests skip
   [484]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@gem_exec_reloc@basic-cpu-gtt-noreloc.html
   [485]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-4/igt@gem_exec_reloc@basic-cpu-gtt-noreloc.html

  * igt@gem_exec_reloc@basic-cpu-read-noreloc:
    - shard-rkl:          [SKIP][486] ([i915#3281]) -> [SKIP][487] ([i915#14544] / [i915#3281]) +4 other tests skip
   [486]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-8/igt@gem_exec_reloc@basic-cpu-read-noreloc.html
   [487]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-6/igt@gem_exec_reloc@basic-cpu-read-noreloc.html

  * igt@gem_exec_reloc@basic-gtt:
    - shard-dg2:          [SKIP][488] ([i915#3281]) -> [SKIP][489] ([i915#15689] / [i915#2575]) +5 other tests skip
   [488]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-6/igt@gem_exec_reloc@basic-gtt.html
   [489]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@gem_exec_reloc@basic-gtt.html

  * igt@gem_exec_reloc@basic-write-read-active:
    - shard-rkl:          [SKIP][490] ([i915#14544] / [i915#3281]) -> [SKIP][491] ([i915#3281]) +2 other tests skip
   [490]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-6/igt@gem_exec_reloc@basic-write-read-active.html
   [491]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-5/igt@gem_exec_reloc@basic-write-read-active.html

  * igt@gem_exec_schedule@preempt-queue-chain:
    - shard-dg2:          [SKIP][492] ([i915#15689] / [i915#2575]) -> [SKIP][493] ([i915#4537] / [i915#4812]) +1 other test skip
   [492]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@gem_exec_schedule@preempt-queue-chain.html
   [493]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-4/igt@gem_exec_schedule@preempt-queue-chain.html

  * igt@gem_exec_schedule@preempt-queue-contexts-chain:
    - shard-dg2:          [SKIP][494] ([i915#4537] / [i915#4812]) -> [SKIP][495] ([i915#15689] / [i915#2575])
   [494]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-1/igt@gem_exec_schedule@preempt-queue-contexts-chain.html
   [495]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@gem_exec_schedule@preempt-queue-contexts-chain.html

  * igt@gem_exec_suspend@basic-s0:
    - shard-dg2:          [INCOMPLETE][496] ([i915#13356]) -> [SKIP][497] ([i915#15689] / [i915#2575])
   [496]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-5/igt@gem_exec_suspend@basic-s0.html
   [497]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@gem_exec_suspend@basic-s0.html

  * igt@gem_fenced_exec_thrash@no-spare-fences-busy-interruptible:
    - shard-dg2:          [SKIP][498] ([i915#15689] / [i915#2575]) -> [SKIP][499] ([i915#4860])
   [498]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@gem_fenced_exec_thrash@no-spare-fences-busy-interruptible.html
   [499]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-4/igt@gem_fenced_exec_thrash@no-spare-fences-busy-interruptible.html

  * igt@gem_fenced_exec_thrash@no-spare-fences-interruptible:
    - shard-dg2:          [SKIP][500] ([i915#4860]) -> [SKIP][501] ([i915#15689] / [i915#2575]) +2 other tests skip
   [500]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-4/igt@gem_fenced_exec_thrash@no-spare-fences-interruptible.html
   [501]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@gem_fenced_exec_thrash@no-spare-fences-interruptible.html

  * igt@gem_huc_copy@huc-copy:
    - shard-rkl:          [SKIP][502] ([i915#14544] / [i915#2190]) -> [SKIP][503] ([i915#2190])
   [502]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-6/igt@gem_huc_copy@huc-copy.html
   [503]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-2/igt@gem_huc_copy@huc-copy.html

  * igt@gem_lmem_swapping@parallel-multi:
    - shard-rkl:          [SKIP][504] ([i915#4613]) -> [SKIP][505] ([i915#14544] / [i915#4613])
   [504]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-4/igt@gem_lmem_swapping@parallel-multi.html
   [505]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-6/igt@gem_lmem_swapping@parallel-multi.html

  * igt@gem_lmem_swapping@random-engines:
    - shard-rkl:          [SKIP][506] ([i915#14544] / [i915#4613]) -> [SKIP][507] ([i915#4613])
   [506]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-6/igt@gem_lmem_swapping@random-engines.html
   [507]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-4/igt@gem_lmem_swapping@random-engines.html

  * igt@gem_media_fill@media-fill:
    - shard-dg2:          [SKIP][508] ([i915#15689] / [i915#2575]) -> [SKIP][509] ([i915#8289])
   [508]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@gem_media_fill@media-fill.html
   [509]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-5/igt@gem_media_fill@media-fill.html

  * igt@gem_mmap_gtt@fault-concurrent-x:
    - shard-dg2:          [SKIP][510] ([i915#15689] / [i915#2575]) -> [SKIP][511] ([i915#4077]) +7 other tests skip
   [510]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@gem_mmap_gtt@fault-concurrent-x.html
   [511]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-6/igt@gem_mmap_gtt@fault-concurrent-x.html

  * igt@gem_mmap_wc@fault-concurrent:
    - shard-dg2:          [SKIP][512] ([i915#15689] / [i915#2575]) -> [SKIP][513] ([i915#4083]) +3 other tests skip
   [512]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@gem_mmap_wc@fault-concurrent.html
   [513]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-4/igt@gem_mmap_wc@fault-concurrent.html

  * igt@gem_mmap_wc@read-write:
    - shard-dg2:          [SKIP][514] ([i915#4083]) -> [SKIP][515] ([i915#15689] / [i915#2575]) +3 other tests skip
   [514]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-7/igt@gem_mmap_wc@read-write.html
   [515]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@gem_mmap_wc@read-write.html

  * igt@gem_pread@snoop:
    - shard-dg2:          [SKIP][516] ([i915#15689] / [i915#2575]) -> [SKIP][517] ([i915#3282]) +9 other tests skip
   [516]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@gem_pread@snoop.html
   [517]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-7/igt@gem_pread@snoop.html

  * igt@gem_pread@uncached:
    - shard-dg2:          [SKIP][518] ([i915#3282]) -> [SKIP][519] ([i915#15689] / [i915#2575]) +2 other tests skip
   [518]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-4/igt@gem_pread@uncached.html
   [519]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@gem_pread@uncached.html

  * igt@gem_pxp@create-valid-protected-context:
    - shard-dg2:          [SKIP][520] ([i915#15689] / [i915#2575]) -> [SKIP][521] ([i915#4270])
   [520]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@gem_pxp@create-valid-protected-context.html
   [521]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-6/igt@gem_pxp@create-valid-protected-context.html

  * igt@gem_pxp@verify-pxp-execution-after-suspend-resume:
    - shard-dg2:          [SKIP][522] ([i915#4270]) -> [SKIP][523] ([i915#15689] / [i915#2575]) +3 other tests skip
   [522]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-5/igt@gem_pxp@verify-pxp-execution-after-suspend-resume.html
   [523]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@gem_pxp@verify-pxp-execution-after-suspend-resume.html

  * igt@gem_render_copy@linear-to-vebox-yf-tiled:
    - shard-dg2:          [SKIP][524] ([i915#5190] / [i915#8428]) -> [SKIP][525] ([i915#15689] / [i915#2575] / [i915#5190]) +3 other tests skip
   [524]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-1/igt@gem_render_copy@linear-to-vebox-yf-tiled.html
   [525]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@gem_render_copy@linear-to-vebox-yf-tiled.html

  * igt@gem_render_copy@yf-tiled-ccs-to-y-tiled:
    - shard-dg2:          [SKIP][526] ([i915#15689] / [i915#2575] / [i915#5190]) -> [SKIP][527] ([i915#5190] / [i915#8428]) +8 other tests skip
   [526]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@gem_render_copy@yf-tiled-ccs-to-y-tiled.html
   [527]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-8/igt@gem_render_copy@yf-tiled-ccs-to-y-tiled.html

  * igt@gem_set_tiling_vs_blt@tiled-to-untiled:
    - shard-dg2:          [SKIP][528] ([i915#15689] / [i915#2575]) -> [SKIP][529] ([i915#4079]) +1 other test skip
   [528]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@gem_set_tiling_vs_blt@tiled-to-untiled.html
   [529]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-5/igt@gem_set_tiling_vs_blt@tiled-to-untiled.html

  * igt@gem_set_tiling_vs_blt@untiled-to-tiled:
    - shard-rkl:          [SKIP][530] ([i915#8411]) -> [SKIP][531] ([i915#14544] / [i915#8411])
   [530]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-8/igt@gem_set_tiling_vs_blt@untiled-to-tiled.html
   [531]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-6/igt@gem_set_tiling_vs_blt@untiled-to-tiled.html

  * igt@gem_tiled_partial_pwrite_pread@writes:
    - shard-dg2:          [SKIP][532] ([i915#4077]) -> [SKIP][533] ([i915#15689] / [i915#2575]) +9 other tests skip
   [532]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-3/igt@gem_tiled_partial_pwrite_pread@writes.html
   [533]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@gem_tiled_partial_pwrite_pread@writes.html

  * igt@gem_tiled_partial_pwrite_pread@writes-after-reads:
    - shard-rkl:          [SKIP][534] ([i915#3282]) -> [SKIP][535] ([i915#14544] / [i915#3282])
   [534]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-5/igt@gem_tiled_partial_pwrite_pread@writes-after-reads.html
   [535]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-6/igt@gem_tiled_partial_pwrite_pread@writes-after-reads.html

  * igt@gem_tiled_pread_pwrite:
    - shard-dg2:          [SKIP][536] ([i915#4079]) -> [SKIP][537] ([i915#15689] / [i915#2575]) +1 other test skip
   [536]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-5/igt@gem_tiled_pread_pwrite.html
   [537]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@gem_tiled_pread_pwrite.html

  * igt@gem_userptr_blits@create-destroy-unsync:
    - shard-dg2:          [SKIP][538] ([i915#15689] / [i915#2575]) -> [SKIP][539] ([i915#3297]) +2 other tests skip
   [538]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@gem_userptr_blits@create-destroy-unsync.html
   [539]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-5/igt@gem_userptr_blits@create-destroy-unsync.html

  * igt@gem_userptr_blits@map-fixed-invalidate-overlap-busy:
    - shard-dg2:          [SKIP][540] ([i915#15689] / [i915#2575]) -> [SKIP][541] ([i915#3297] / [i915#4880]) +1 other test skip
   [540]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@gem_userptr_blits@map-fixed-invalidate-overlap-busy.html
   [541]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-6/igt@gem_userptr_blits@map-fixed-invalidate-overlap-busy.html

  * igt@gem_userptr_blits@relocations:
    - shard-rkl:          [SKIP][542] ([i915#3281] / [i915#3297]) -> [SKIP][543] ([i915#14544] / [i915#3281] / [i915#3297])
   [542]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-2/igt@gem_userptr_blits@relocations.html
   [543]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-6/igt@gem_userptr_blits@relocations.html

  * igt@gem_userptr_blits@sd-probe:
    - shard-dg2:          [SKIP][544] ([i915#3297] / [i915#4958]) -> [SKIP][545] ([i915#15689] / [i915#2575])
   [544]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-1/igt@gem_userptr_blits@sd-probe.html
   [545]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@gem_userptr_blits@sd-probe.html

  * igt@gem_userptr_blits@unsync-unmap-after-close:
    - shard-dg2:          [SKIP][546] ([i915#3297]) -> [SKIP][547] ([i915#15689] / [i915#2575])
   [546]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-3/igt@gem_userptr_blits@unsync-unmap-after-close.html
   [547]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@gem_userptr_blits@unsync-unmap-after-close.html

  * igt@gen3_mixed_blits:
    - shard-dg2:          [SKIP][548] ([i915#15689] / [i915#2575]) -> [SKIP][549] +1 other test skip
   [548]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@gen3_mixed_blits.html
   [549]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-8/igt@gen3_mixed_blits.html

  * igt@gen9_exec_parse@basic-rejected-ctx-param:
    - shard-rkl:          [SKIP][550] ([i915#2527]) -> [SKIP][551] ([i915#14544] / [i915#2527])
   [550]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-7/igt@gen9_exec_parse@basic-rejected-ctx-param.html
   [551]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-6/igt@gen9_exec_parse@basic-rejected-ctx-param.html

  * igt@gen9_exec_parse@bb-start-far:
    - shard-dg2:          [SKIP][552] ([i915#15689] / [i915#2575]) -> [SKIP][553] ([i915#2856]) +2 other tests skip
   [552]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@gen9_exec_parse@bb-start-far.html
   [553]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-6/igt@gen9_exec_parse@bb-start-far.html

  * igt@gen9_exec_parse@unaligned-access:
    - shard-dg2:          [SKIP][554] ([i915#2856]) -> [SKIP][555] ([i915#15689] / [i915#2575]) +2 other tests skip
   [554]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-1/igt@gen9_exec_parse@unaligned-access.html
   [555]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@gen9_exec_parse@unaligned-access.html

  * igt@i915_drm_fdinfo@all-busy-idle-check-all:
    - shard-dg2:          [SKIP][556] -> [SKIP][557] ([i915#14123])
   [556]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@i915_drm_fdinfo@all-busy-idle-check-all.html
   [557]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-6/igt@i915_drm_fdinfo@all-busy-idle-check-all.html

  * igt@i915_drm_fdinfo@busy:
    - shard-dg2:          [SKIP][558] ([i915#15607]) -> [SKIP][559] ([i915#14073])
   [558]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@i915_drm_fdinfo@busy.html
   [559]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-5/igt@i915_drm_fdinfo@busy.html

  * igt@i915_drm_fdinfo@busy-idle:
    - shard-dg2:          [SKIP][560] -> [SKIP][561] ([i915#14073])
   [560]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@i915_drm_fdinfo@busy-idle.html
   [561]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-5/igt@i915_drm_fdinfo@busy-idle.html

  * igt@i915_drm_fdinfo@virtual-busy-all:
    - shard-dg2:          [SKIP][562] -> [SKIP][563] ([i915#14118])
   [562]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@i915_drm_fdinfo@virtual-busy-all.html
   [563]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-7/igt@i915_drm_fdinfo@virtual-busy-all.html

  * igt@i915_pm_rps@min-max-config-idle:
    - shard-dg2:          [SKIP][564] ([i915#15689] / [i915#2575]) -> [SKIP][565] ([i915#11681] / [i915#6621])
   [564]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@i915_pm_rps@min-max-config-idle.html
   [565]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-7/igt@i915_pm_rps@min-max-config-idle.html

  * igt@i915_pm_rps@thresholds-park:
    - shard-dg2:          [SKIP][566] ([i915#15689] / [i915#2575]) -> [SKIP][567] ([i915#11681]) +1 other test skip
   [566]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@i915_pm_rps@thresholds-park.html
   [567]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-7/igt@i915_pm_rps@thresholds-park.html

  * igt@kms_addfb_basic@clobberred-modifier:
    - shard-dg2:          [SKIP][568] ([i915#15689]) -> [SKIP][569] ([i915#4212]) +1 other test skip
   [568]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@kms_addfb_basic@clobberred-modifier.html
   [569]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-6/igt@kms_addfb_basic@clobberred-modifier.html

  * igt@kms_atomic@plane-primary-overlay-mutable-zpos:
    - shard-dg2:          [SKIP][570] ([i915#9531]) -> [SKIP][571] ([i915#15689])
   [570]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-1/igt@kms_atomic@plane-primary-overlay-mutable-zpos.html
   [571]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_atomic@plane-primary-overlay-mutable-zpos.html

  * igt@kms_atomic_transition@plane-all-modeset-transition-internal-panels:
    - shard-dg2:          [SKIP][572] ([i915#1769] / [i915#3555]) -> [SKIP][573] ([i915#15689])
   [572]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-7/igt@kms_atomic_transition@plane-all-modeset-transition-internal-panels.html
   [573]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_atomic_transition@plane-all-modeset-transition-internal-panels.html

  * igt@kms_big_fb@4-tiled-64bpp-rotate-270:
    - shard-dg2:          [SKIP][574] ([i915#15689]) -> [SKIP][575] +6 other tests skip
   [574]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@kms_big_fb@4-tiled-64bpp-rotate-270.html
   [575]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-8/igt@kms_big_fb@4-tiled-64bpp-rotate-270.html

  * igt@kms_big_fb@4-tiled-8bpp-rotate-90:
    - shard-rkl:          [SKIP][576] ([i915#5286]) -> [SKIP][577] ([i915#14544] / [i915#5286]) +1 other test skip
   [576]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-8/igt@kms_big_fb@4-tiled-8bpp-rotate-90.html
   [577]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-6/igt@kms_big_fb@4-tiled-8bpp-rotate-90.html

  * igt@kms_big_fb@4-tiled-addfb:
    - shard-rkl:          [SKIP][578] ([i915#14544] / [i915#5286]) -> [SKIP][579] ([i915#5286]) +2 other tests skip
   [578]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-6/igt@kms_big_fb@4-tiled-addfb.html
   [579]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-4/igt@kms_big_fb@4-tiled-addfb.html

  * igt@kms_big_fb@linear-16bpp-rotate-270:
    - shard-rkl:          [SKIP][580] ([i915#14544] / [i915#3638]) -> [SKIP][581] ([i915#3638])
   [580]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-6/igt@kms_big_fb@linear-16bpp-rotate-270.html
   [581]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-2/igt@kms_big_fb@linear-16bpp-rotate-270.html

  * igt@kms_big_fb@y-tiled-addfb-size-overflow:
    - shard-dg2:          [SKIP][582] ([i915#5190]) -> [SKIP][583] ([i915#15689] / [i915#5190]) +3 other tests skip
   [582]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-7/igt@kms_big_fb@y-tiled-addfb-size-overflow.html
   [583]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_big_fb@y-tiled-addfb-size-overflow.html

  * igt@kms_big_fb@y-tiled-max-hw-stride-64bpp-rotate-0-async-flip:
    - shard-dg2:          [SKIP][584] ([i915#15689] / [i915#5190]) -> [SKIP][585] ([i915#4538] / [i915#5190]) +11 other tests skip
   [584]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@kms_big_fb@y-tiled-max-hw-stride-64bpp-rotate-0-async-flip.html
   [585]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-8/igt@kms_big_fb@y-tiled-max-hw-stride-64bpp-rotate-0-async-flip.html

  * igt@kms_big_fb@y-tiled-max-hw-stride-64bpp-rotate-0-hflip-async-flip:
    - shard-dg2:          [SKIP][586] ([i915#4538] / [i915#5190]) -> [SKIP][587] ([i915#15689] / [i915#5190]) +13 other tests skip
   [586]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-6/igt@kms_big_fb@y-tiled-max-hw-stride-64bpp-rotate-0-hflip-async-flip.html
   [587]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_big_fb@y-tiled-max-hw-stride-64bpp-rotate-0-hflip-async-flip.html

  * igt@kms_big_fb@yf-tiled-16bpp-rotate-180:
    - shard-dg1:          [SKIP][588] ([i915#4423] / [i915#4538]) -> [SKIP][589] ([i915#4538])
   [588]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg1-13/igt@kms_big_fb@yf-tiled-16bpp-rotate-180.html
   [589]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-12/igt@kms_big_fb@yf-tiled-16bpp-rotate-180.html

  * igt@kms_big_fb@yf-tiled-addfb-size-overflow:
    - shard-dg2:          [SKIP][590] ([i915#15689] / [i915#5190]) -> [SKIP][591] ([i915#5190]) +1 other test skip
   [590]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@kms_big_fb@yf-tiled-addfb-size-overflow.html
   [591]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-8/igt@kms_big_fb@yf-tiled-addfb-size-overflow.html

  * igt@kms_ccs@bad-aux-stride-4-tiled-mtl-mc-ccs:
    - shard-rkl:          [SKIP][592] ([i915#14098] / [i915#6095]) -> [SKIP][593] ([i915#14098] / [i915#14544] / [i915#6095]) +4 other tests skip
   [592]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-3/igt@kms_ccs@bad-aux-stride-4-tiled-mtl-mc-ccs.html
   [593]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-6/igt@kms_ccs@bad-aux-stride-4-tiled-mtl-mc-ccs.html

  * igt@kms_ccs@bad-aux-stride-4-tiled-mtl-mc-ccs@pipe-a-hdmi-a-2:
    - shard-rkl:          [SKIP][594] ([i915#6095]) -> [SKIP][595] ([i915#14544] / [i915#6095]) +3 other tests skip
   [594]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-3/igt@kms_ccs@bad-aux-stride-4-tiled-mtl-mc-ccs@pipe-a-hdmi-a-2.html
   [595]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-6/igt@kms_ccs@bad-aux-stride-4-tiled-mtl-mc-ccs@pipe-a-hdmi-a-2.html

  * igt@kms_ccs@bad-aux-stride-y-tiled-ccs:
    - shard-dg2:          [SKIP][596] ([i915#15689]) -> [SKIP][597] ([i915#10307] / [i915#6095]) +8 other tests skip
   [596]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@kms_ccs@bad-aux-stride-y-tiled-ccs.html
   [597]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-4/igt@kms_ccs@bad-aux-stride-y-tiled-ccs.html

  * igt@kms_ccs@bad-rotation-90-4-tiled-dg2-mc-ccs:
    - shard-dg2:          [SKIP][598] ([i915#15689]) -> [SKIP][599] ([i915#6095]) +4 other tests skip
   [598]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@kms_ccs@bad-rotation-90-4-tiled-dg2-mc-ccs.html
   [599]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-6/igt@kms_ccs@bad-rotation-90-4-tiled-dg2-mc-ccs.html

  * igt@kms_ccs@ccs-on-another-bo-4-tiled-mtl-mc-ccs@pipe-a-hdmi-a-2:
    - shard-rkl:          [SKIP][600] ([i915#14544] / [i915#6095]) -> [SKIP][601] ([i915#6095]) +1 other test skip
   [600]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-6/igt@kms_ccs@ccs-on-another-bo-4-tiled-mtl-mc-ccs@pipe-a-hdmi-a-2.html
   [601]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-4/igt@kms_ccs@ccs-on-another-bo-4-tiled-mtl-mc-ccs@pipe-a-hdmi-a-2.html

  * igt@kms_ccs@crc-primary-rotation-180-4-tiled-dg2-mc-ccs:
    - shard-dg2:          [SKIP][602] ([i915#6095]) -> [SKIP][603] ([i915#15689]) +4 other tests skip
   [602]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-7/igt@kms_ccs@crc-primary-rotation-180-4-tiled-dg2-mc-ccs.html
   [603]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_ccs@crc-primary-rotation-180-4-tiled-dg2-mc-ccs.html

  * igt@kms_ccs@crc-primary-rotation-180-4-tiled-lnl-ccs:
    - shard-dg2:          [SKIP][604] ([i915#15689]) -> [SKIP][605] ([i915#12313]) +1 other test skip
   [604]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@kms_ccs@crc-primary-rotation-180-4-tiled-lnl-ccs.html
   [605]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-5/igt@kms_ccs@crc-primary-rotation-180-4-tiled-lnl-ccs.html

  * igt@kms_ccs@crc-primary-suspend-4-tiled-bmg-ccs:
    - shard-dg2:          [SKIP][606] ([i915#15689]) -> [SKIP][607] ([i915#12805])
   [606]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@kms_ccs@crc-primary-suspend-4-tiled-bmg-ccs.html
   [607]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-8/igt@kms_ccs@crc-primary-suspend-4-tiled-bmg-ccs.html

  * igt@kms_ccs@missing-ccs-buffer-4-tiled-mtl-mc-ccs:
    - shard-rkl:          [SKIP][608] ([i915#14098] / [i915#14544] / [i915#6095]) -> [SKIP][609] ([i915#14098] / [i915#6095]) +3 other tests skip
   [608]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-6/igt@kms_ccs@missing-ccs-buffer-4-tiled-mtl-mc-ccs.html
   [609]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-5/igt@kms_ccs@missing-ccs-buffer-4-tiled-mtl-mc-ccs.html

  * igt@kms_ccs@missing-ccs-buffer-4-tiled-mtl-rc-ccs-cc:
    - shard-dg2:          [SKIP][610] ([i915#10307] / [i915#6095]) -> [SKIP][611] ([i915#15689]) +11 other tests skip
   [610]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-7/igt@kms_ccs@missing-ccs-buffer-4-tiled-mtl-rc-ccs-cc.html
   [611]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_ccs@missing-ccs-buffer-4-tiled-mtl-rc-ccs-cc.html

  * igt@kms_ccs@random-ccs-data-4-tiled-bmg-ccs:
    - shard-dg2:          [SKIP][612] ([i915#12313]) -> [SKIP][613] ([i915#15689]) +1 other test skip
   [612]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-5/igt@kms_ccs@random-ccs-data-4-tiled-bmg-ccs.html
   [613]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_ccs@random-ccs-data-4-tiled-bmg-ccs.html

  * igt@kms_ccs@random-ccs-data-y-tiled-gen12-mc-ccs@pipe-a-hdmi-a-4:
    - shard-dg1:          [SKIP][614] ([i915#6095]) -> [SKIP][615] ([i915#4423] / [i915#6095]) +1 other test skip
   [614]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg1-16/igt@kms_ccs@random-ccs-data-y-tiled-gen12-mc-ccs@pipe-a-hdmi-a-4.html
   [615]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-16/igt@kms_ccs@random-ccs-data-y-tiled-gen12-mc-ccs@pipe-a-hdmi-a-4.html

  * igt@kms_cdclk@mode-transition:
    - shard-dg2:          [SKIP][616] ([i915#15689]) -> [SKIP][617] ([i915#13781])
   [616]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@kms_cdclk@mode-transition.html
   [617]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-6/igt@kms_cdclk@mode-transition.html

  * igt@kms_cdclk@plane-scaling:
    - shard-rkl:          [SKIP][618] ([i915#3742]) -> [SKIP][619] ([i915#14544] / [i915#3742])
   [618]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-2/igt@kms_cdclk@plane-scaling.html
   [619]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-6/igt@kms_cdclk@plane-scaling.html

  * igt@kms_chamelium_color@ctm-green-to-red:
    - shard-dg2:          [SKIP][620] -> [SKIP][621] ([i915#15689]) +5 other tests skip
   [620]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-4/igt@kms_chamelium_color@ctm-green-to-red.html
   [621]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_chamelium_color@ctm-green-to-red.html

  * igt@kms_chamelium_edid@dp-edid-stress-resolution-non-4k:
    - shard-rkl:          [SKIP][622] ([i915#11151] / [i915#7828]) -> [SKIP][623] ([i915#11151] / [i915#14544] / [i915#7828])
   [622]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-8/igt@kms_chamelium_edid@dp-edid-stress-resolution-non-4k.html
   [623]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-6/igt@kms_chamelium_edid@dp-edid-stress-resolution-non-4k.html

  * igt@kms_chamelium_edid@hdmi-edid-change-during-suspend:
    - shard-rkl:          [SKIP][624] ([i915#11151] / [i915#14544] / [i915#7828]) -> [SKIP][625] ([i915#11151] / [i915#7828]) +2 other tests skip
   [624]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-6/igt@kms_chamelium_edid@hdmi-edid-change-during-suspend.html
   [625]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-3/igt@kms_chamelium_edid@hdmi-edid-change-during-suspend.html

  * igt@kms_chamelium_hpd@dp-hpd-storm:
    - shard-dg2:          [SKIP][626] ([i915#11151] / [i915#7828]) -> [SKIP][627] ([i915#15689]) +6 other tests skip
   [626]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-5/igt@kms_chamelium_hpd@dp-hpd-storm.html
   [627]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_chamelium_hpd@dp-hpd-storm.html

  * igt@kms_chamelium_hpd@vga-hpd-after-suspend:
    - shard-dg2:          [SKIP][628] ([i915#15689]) -> [SKIP][629] ([i915#11151] / [i915#7828]) +7 other tests skip
   [628]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@kms_chamelium_hpd@vga-hpd-after-suspend.html
   [629]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-3/igt@kms_chamelium_hpd@vga-hpd-after-suspend.html

  * igt@kms_content_protection@atomic-hdcp14:
    - shard-dg2:          [SKIP][630] ([i915#6944]) -> [SKIP][631] ([i915#15689])
   [630]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-8/igt@kms_content_protection@atomic-hdcp14.html
   [631]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_content_protection@atomic-hdcp14.html

  * igt@kms_content_protection@dp-mst-lic-type-1:
    - shard-dg2:          [SKIP][632] ([i915#15330] / [i915#3299]) -> [SKIP][633] ([i915#15689])
   [632]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-6/igt@kms_content_protection@dp-mst-lic-type-1.html
   [633]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_content_protection@dp-mst-lic-type-1.html

  * igt@kms_content_protection@dp-mst-type-1:
    - shard-dg2:          [SKIP][634] ([i915#15689]) -> [SKIP][635] ([i915#15330] / [i915#3299])
   [634]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@kms_content_protection@dp-mst-type-1.html
   [635]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-4/igt@kms_content_protection@dp-mst-type-1.html

  * igt@kms_content_protection@dp-mst-type-1-suspend-resume:
    - shard-dg2:          [SKIP][636] ([i915#15330]) -> [SKIP][637] ([i915#15689]) +1 other test skip
   [636]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-3/igt@kms_content_protection@dp-mst-type-1-suspend-resume.html
   [637]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_content_protection@dp-mst-type-1-suspend-resume.html

  * igt@kms_content_protection@legacy-hdcp14:
    - shard-dg2:          [SKIP][638] ([i915#15689]) -> [SKIP][639] ([i915#6944])
   [638]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@kms_content_protection@legacy-hdcp14.html
   [639]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-5/igt@kms_content_protection@legacy-hdcp14.html

  * igt@kms_cursor_crc@cursor-offscreen-max-size:
    - shard-dg1:          [ABORT][640] ([i915#15759]) -> [SKIP][641] ([i915#3555])
   [640]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg1-17/igt@kms_cursor_crc@cursor-offscreen-max-size.html
   [641]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-16/igt@kms_cursor_crc@cursor-offscreen-max-size.html

  * igt@kms_cursor_crc@cursor-onscreen-512x170:
    - shard-dg2:          [SKIP][642] ([i915#13049]) -> [SKIP][643] ([i915#15689]) +2 other tests skip
   [642]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-8/igt@kms_cursor_crc@cursor-onscreen-512x170.html
   [643]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_cursor_crc@cursor-onscreen-512x170.html

  * igt@kms_cursor_crc@cursor-random-512x512:
    - shard-dg2:          [SKIP][644] ([i915#15689]) -> [SKIP][645] ([i915#13049]) +2 other tests skip
   [644]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@kms_cursor_crc@cursor-random-512x512.html
   [645]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-4/igt@kms_cursor_crc@cursor-random-512x512.html

  * igt@kms_cursor_crc@cursor-rapid-movement-32x32:
    - shard-dg2:          [SKIP][646] ([i915#3555]) -> [SKIP][647] ([i915#15689]) +3 other tests skip
   [646]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-3/igt@kms_cursor_crc@cursor-rapid-movement-32x32.html
   [647]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_cursor_crc@cursor-rapid-movement-32x32.html

  * igt@kms_cursor_crc@cursor-rapid-movement-max-size:
    - shard-dg2:          [SKIP][648] ([i915#15689]) -> [SKIP][649] ([i915#3555]) +6 other tests skip
   [648]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@kms_cursor_crc@cursor-rapid-movement-max-size.html
   [649]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-3/igt@kms_cursor_crc@cursor-rapid-movement-max-size.html

  * igt@kms_cursor_legacy@2x-flip-vs-cursor-legacy:
    - shard-dg2:          [SKIP][650] ([i915#13046] / [i915#5354]) -> [SKIP][651] ([i915#15689]) +1 other test skip
   [650]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-7/igt@kms_cursor_legacy@2x-flip-vs-cursor-legacy.html
   [651]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_cursor_legacy@2x-flip-vs-cursor-legacy.html

  * igt@kms_cursor_legacy@basic-busy-flip-before-cursor-atomic:
    - shard-rkl:          [SKIP][652] ([i915#14544] / [i915#4103]) -> [SKIP][653] ([i915#4103])
   [652]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-6/igt@kms_cursor_legacy@basic-busy-flip-before-cursor-atomic.html
   [653]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-4/igt@kms_cursor_legacy@basic-busy-flip-before-cursor-atomic.html

  * igt@kms_cursor_legacy@basic-busy-flip-before-cursor-legacy:
    - shard-rkl:          [SKIP][654] ([i915#4103]) -> [SKIP][655] ([i915#14544] / [i915#4103])
   [654]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-4/igt@kms_cursor_legacy@basic-busy-flip-before-cursor-legacy.html
   [655]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-6/igt@kms_cursor_legacy@basic-busy-flip-before-cursor-legacy.html

  * igt@kms_cursor_legacy@cursora-vs-flipb-atomic-transitions:
    - shard-dg2:          [SKIP][656] ([i915#15689]) -> [SKIP][657] ([i915#13046] / [i915#5354]) +1 other test skip
   [656]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@kms_cursor_legacy@cursora-vs-flipb-atomic-transitions.html
   [657]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-5/igt@kms_cursor_legacy@cursora-vs-flipb-atomic-transitions.html

  * igt@kms_cursor_legacy@cursora-vs-flipb-atomic-transitions-varying-size:
    - shard-rkl:          [SKIP][658] ([i915#14544]) -> [SKIP][659] +10 other tests skip
   [658]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-6/igt@kms_cursor_legacy@cursora-vs-flipb-atomic-transitions-varying-size.html
   [659]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-8/igt@kms_cursor_legacy@cursora-vs-flipb-atomic-transitions-varying-size.html

  * igt@kms_cursor_legacy@cursorb-vs-flipa-atomic:
    - shard-rkl:          [SKIP][660] -> [SKIP][661] ([i915#14544]) +3 other tests skip
   [660]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-3/igt@kms_cursor_legacy@cursorb-vs-flipa-atomic.html
   [661]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-6/igt@kms_cursor_legacy@cursorb-vs-flipa-atomic.html

  * igt@kms_cursor_legacy@modeset-atomic-cursor-hotspot:
    - shard-dg2:          [SKIP][662] ([i915#15689]) -> [SKIP][663] ([i915#9067])
   [662]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@kms_cursor_legacy@modeset-atomic-cursor-hotspot.html
   [663]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-6/igt@kms_cursor_legacy@modeset-atomic-cursor-hotspot.html
    - shard-rkl:          [SKIP][664] ([i915#14544] / [i915#9067]) -> [SKIP][665] ([i915#9067])
   [664]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-6/igt@kms_cursor_legacy@modeset-atomic-cursor-hotspot.html
   [665]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-2/igt@kms_cursor_legacy@modeset-atomic-cursor-hotspot.html

  * igt@kms_cursor_legacy@short-busy-flip-before-cursor-toggle:
    - shard-dg2:          [SKIP][666] ([i915#15689]) -> [SKIP][667] ([i915#4103] / [i915#4213]) +1 other test skip
   [666]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@kms_cursor_legacy@short-busy-flip-before-cursor-toggle.html
   [667]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-4/igt@kms_cursor_legacy@short-busy-flip-before-cursor-toggle.html

  * igt@kms_dirtyfb@drrs-dirtyfb-ioctl:
    - shard-dg2:          [SKIP][668] ([i915#15689]) -> [SKIP][669] ([i915#9833])
   [668]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@kms_dirtyfb@drrs-dirtyfb-ioctl.html
   [669]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-5/igt@kms_dirtyfb@drrs-dirtyfb-ioctl.html

  * igt@kms_display_modes@extended-mode-basic:
    - shard-dg2:          [SKIP][670] ([i915#13691]) -> [SKIP][671] ([i915#15689])
   [670]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-7/igt@kms_display_modes@extended-mode-basic.html
   [671]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_display_modes@extended-mode-basic.html

  * igt@kms_dp_link_training@non-uhbr-mst:
    - shard-dg2:          [SKIP][672] ([i915#15689]) -> [SKIP][673] ([i915#13749])
   [672]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@kms_dp_link_training@non-uhbr-mst.html
   [673]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-5/igt@kms_dp_link_training@non-uhbr-mst.html

  * igt@kms_dp_linktrain_fallback@dsc-fallback:
    - shard-rkl:          [SKIP][674] ([i915#13707] / [i915#14544]) -> [SKIP][675] ([i915#13707])
   [674]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-6/igt@kms_dp_linktrain_fallback@dsc-fallback.html
   [675]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-3/igt@kms_dp_linktrain_fallback@dsc-fallback.html

  * igt@kms_draw_crc@draw-method-mmap-wc:
    - shard-dg2:          [SKIP][676] ([i915#8812]) -> [SKIP][677] ([i915#15689])
   [676]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-1/igt@kms_draw_crc@draw-method-mmap-wc.html
   [677]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_draw_crc@draw-method-mmap-wc.html

  * igt@kms_fbcon_fbt@psr:
    - shard-dg2:          [SKIP][678] ([i915#3469]) -> [SKIP][679] ([i915#15689])
   [678]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-4/igt@kms_fbcon_fbt@psr.html
   [679]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_fbcon_fbt@psr.html
    - shard-rkl:          [SKIP][680] ([i915#3955]) -> [SKIP][681] ([i915#14544] / [i915#3955])
   [680]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-3/igt@kms_fbcon_fbt@psr.html
   [681]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-6/igt@kms_fbcon_fbt@psr.html

  * igt@kms_feature_discovery@dp-mst:
    - shard-dg2:          [SKIP][682] ([i915#15689]) -> [SKIP][683] ([i915#9337])
   [682]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@kms_feature_discovery@dp-mst.html
   [683]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-5/igt@kms_feature_discovery@dp-mst.html

  * igt@kms_fence_pin_leak:
    - shard-dg2:          [SKIP][684] ([i915#15689] / [i915#2575]) -> [SKIP][685] ([i915#4881])
   [684]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@kms_fence_pin_leak.html
   [685]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-4/igt@kms_fence_pin_leak.html

  * igt@kms_flip@2x-modeset-vs-vblank-race:
    - shard-dg2:          [SKIP][686] ([i915#9934]) -> [SKIP][687] ([i915#15689]) +9 other tests skip
   [686]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-8/igt@kms_flip@2x-modeset-vs-vblank-race.html
   [687]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_flip@2x-modeset-vs-vblank-race.html
    - shard-rkl:          [SKIP][688] ([i915#9934]) -> [SKIP][689] ([i915#14544] / [i915#9934]) +1 other test skip
   [688]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-4/igt@kms_flip@2x-modeset-vs-vblank-race.html
   [689]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-6/igt@kms_flip@2x-modeset-vs-vblank-race.html

  * igt@kms_flip@2x-nonexisting-fb-interruptible:
    - shard-rkl:          [SKIP][690] ([i915#14544] / [i915#9934]) -> [SKIP][691] ([i915#9934]) +1 other test skip
   [690]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-6/igt@kms_flip@2x-nonexisting-fb-interruptible.html
   [691]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-8/igt@kms_flip@2x-nonexisting-fb-interruptible.html

  * igt@kms_flip@2x-single-buffer-flip-vs-dpms-off-vs-modeset:
    - shard-dg2:          [SKIP][692] ([i915#15689]) -> [SKIP][693] ([i915#9934]) +4 other tests skip
   [692]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@kms_flip@2x-single-buffer-flip-vs-dpms-off-vs-modeset.html
   [693]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-8/igt@kms_flip@2x-single-buffer-flip-vs-dpms-off-vs-modeset.html

  * igt@kms_flip@flip-vs-fences-interruptible:
    - shard-dg2:          [SKIP][694] ([i915#8381]) -> [SKIP][695] ([i915#15689]) +1 other test skip
   [694]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-5/igt@kms_flip@flip-vs-fences-interruptible.html
   [695]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_flip@flip-vs-fences-interruptible.html

  * igt@kms_flip_scaled_crc@flip-32bpp-yftile-to-64bpp-yftile-upscaling:
    - shard-dg1:          [SKIP][696] ([i915#15643]) -> [SKIP][697] ([i915#15643] / [i915#4423])
   [696]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg1-14/igt@kms_flip_scaled_crc@flip-32bpp-yftile-to-64bpp-yftile-upscaling.html
   [697]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg1-12/igt@kms_flip_scaled_crc@flip-32bpp-yftile-to-64bpp-yftile-upscaling.html

  * igt@kms_flip_scaled_crc@flip-32bpp-yftileccs-to-64bpp-yftile-downscaling:
    - shard-rkl:          [SKIP][698] ([i915#15643]) -> [SKIP][699] ([i915#14544] / [i915#15643]) +1 other test skip
   [698]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-3/igt@kms_flip_scaled_crc@flip-32bpp-yftileccs-to-64bpp-yftile-downscaling.html
   [699]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-6/igt@kms_flip_scaled_crc@flip-32bpp-yftileccs-to-64bpp-yftile-downscaling.html

  * igt@kms_flip_scaled_crc@flip-32bpp-ytile-to-32bpp-ytileccs-downscaling:
    - shard-dg2:          [SKIP][700] ([i915#15643] / [i915#5190]) -> [SKIP][701] ([i915#15689] / [i915#5190]) +3 other tests skip
   [700]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-3/igt@kms_flip_scaled_crc@flip-32bpp-ytile-to-32bpp-ytileccs-downscaling.html
   [701]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_flip_scaled_crc@flip-32bpp-ytile-to-32bpp-ytileccs-downscaling.html

  * igt@kms_flip_scaled_crc@flip-64bpp-4tile-to-16bpp-4tile-upscaling:
    - shard-rkl:          [SKIP][702] ([i915#14544] / [i915#15643]) -> [SKIP][703] ([i915#15643]) +2 other tests skip
   [702]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-6/igt@kms_flip_scaled_crc@flip-64bpp-4tile-to-16bpp-4tile-upscaling.html
   [703]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-7/igt@kms_flip_scaled_crc@flip-64bpp-4tile-to-16bpp-4tile-upscaling.html

  * igt@kms_flip_scaled_crc@flip-64bpp-4tile-to-32bpp-4tiledg2rcccs-upscaling:
    - shard-dg2:          [SKIP][704] ([i915#15643]) -> [SKIP][705] ([i915#15689]) +1 other test skip
   [704]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-5/igt@kms_flip_scaled_crc@flip-64bpp-4tile-to-32bpp-4tiledg2rcccs-upscaling.html
   [705]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_flip_scaled_crc@flip-64bpp-4tile-to-32bpp-4tiledg2rcccs-upscaling.html

  * igt@kms_frontbuffer_tracking@fbc-2p-rte:
    - shard-dg2:          [SKIP][706] ([i915#5354]) -> [SKIP][707] ([i915#15689]) +24 other tests skip
   [706]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-1/igt@kms_frontbuffer_tracking@fbc-2p-rte.html
   [707]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_frontbuffer_tracking@fbc-2p-rte.html

  * igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-cur-indfb-draw-mmap-wc:
    - shard-rkl:          [SKIP][708] ([i915#1825]) -> [SKIP][709] ([i915#14544] / [i915#1825]) +5 other tests skip
   [708]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-3/igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-cur-indfb-draw-mmap-wc.html
   [709]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-6/igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-cur-indfb-draw-mmap-wc.html

  * igt@kms_frontbuffer_tracking@fbc-tiling-y:
    - shard-dg2:          [SKIP][710] ([i915#10055]) -> [SKIP][711] ([i915#15689])
   [710]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-7/igt@kms_frontbuffer_tracking@fbc-tiling-y.html
   [711]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_frontbuffer_tracking@fbc-tiling-y.html

  * igt@kms_frontbuffer_tracking@fbcpsr-1p-offscreen-pri-shrfb-draw-mmap-wc:
    - shard-rkl:          [SKIP][712] ([i915#15102]) -> [SKIP][713] ([i915#14544] / [i915#15102])
   [712]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-8/igt@kms_frontbuffer_tracking@fbcpsr-1p-offscreen-pri-shrfb-draw-mmap-wc.html
   [713]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-6/igt@kms_frontbuffer_tracking@fbcpsr-1p-offscreen-pri-shrfb-draw-mmap-wc.html

  * igt@kms_frontbuffer_tracking@fbcpsr-1p-primscrn-cur-indfb-draw-mmap-cpu:
    - shard-dg2:          [SKIP][714] ([i915#15689]) -> [SKIP][715] ([i915#15102] / [i915#3458]) +15 other tests skip
   [714]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@kms_frontbuffer_tracking@fbcpsr-1p-primscrn-cur-indfb-draw-mmap-cpu.html
   [715]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-6/igt@kms_frontbuffer_tracking@fbcpsr-1p-primscrn-cur-indfb-draw-mmap-cpu.html

  * igt@kms_frontbuffer_tracking@fbcpsr-1p-primscrn-shrfb-plflip-blt:
    - shard-dg2:          [SKIP][716] ([i915#15102] / [i915#3458]) -> [SKIP][717] ([i915#15689]) +12 other tests skip
   [716]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-5/igt@kms_frontbuffer_tracking@fbcpsr-1p-primscrn-shrfb-plflip-blt.html
   [717]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_frontbuffer_tracking@fbcpsr-1p-primscrn-shrfb-plflip-blt.html

  * igt@kms_frontbuffer_tracking@fbcpsr-2p-primscrn-pri-indfb-draw-mmap-gtt:
    - shard-dg2:          [SKIP][718] ([i915#15689]) -> [SKIP][719] ([i915#8708]) +18 other tests skip
   [718]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@kms_frontbuffer_tracking@fbcpsr-2p-primscrn-pri-indfb-draw-mmap-gtt.html
   [719]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-4/igt@kms_frontbuffer_tracking@fbcpsr-2p-primscrn-pri-indfb-draw-mmap-gtt.html

  * igt@kms_frontbuffer_tracking@fbcpsr-tiling-4:
    - shard-dg2:          [SKIP][720] ([i915#15102] / [i915#3458]) -> [SKIP][721] ([i915#10433] / [i915#15102] / [i915#3458])
   [720]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-8/igt@kms_frontbuffer_tracking@fbcpsr-tiling-4.html
   [721]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-4/igt@kms_frontbuffer_tracking@fbcpsr-tiling-4.html

  * igt@kms_frontbuffer_tracking@psr-1p-offscreen-pri-indfb-draw-blt:
    - shard-dg2:          [SKIP][722] ([i915#15102]) -> [SKIP][723] ([i915#15689]) +1 other test skip
   [722]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-1/igt@kms_frontbuffer_tracking@psr-1p-offscreen-pri-indfb-draw-blt.html
   [723]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_frontbuffer_tracking@psr-1p-offscreen-pri-indfb-draw-blt.html

  * igt@kms_frontbuffer_tracking@psr-1p-offscreen-pri-shrfb-draw-mmap-gtt:
    - shard-dg2:          [SKIP][724] ([i915#15104]) -> [SKIP][725] ([i915#15689])
   [724]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-1/igt@kms_frontbuffer_tracking@psr-1p-offscreen-pri-shrfb-draw-mmap-gtt.html
   [725]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_frontbuffer_tracking@psr-1p-offscreen-pri-shrfb-draw-mmap-gtt.html

  * igt@kms_frontbuffer_tracking@psr-1p-offscreen-pri-shrfb-draw-mmap-wc:
    - shard-dg2:          [SKIP][726] ([i915#15689]) -> [SKIP][727] ([i915#15104]) +3 other tests skip
   [726]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@kms_frontbuffer_tracking@psr-1p-offscreen-pri-shrfb-draw-mmap-wc.html
   [727]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-6/igt@kms_frontbuffer_tracking@psr-1p-offscreen-pri-shrfb-draw-mmap-wc.html

  * igt@kms_frontbuffer_tracking@psr-1p-offscreen-pri-shrfb-draw-pwrite:
    - shard-dg2:          [SKIP][728] ([i915#15689]) -> [SKIP][729] ([i915#15102]) +3 other tests skip
   [728]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@kms_frontbuffer_tracking@psr-1p-offscreen-pri-shrfb-draw-pwrite.html
   [729]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-5/igt@kms_frontbuffer_tracking@psr-1p-offscreen-pri-shrfb-draw-pwrite.html

  * igt@kms_frontbuffer_tracking@psr-1p-primscrn-cur-indfb-draw-mmap-cpu:
    - shard-rkl:          [SKIP][730] ([i915#15102] / [i915#3023]) -> [SKIP][731] ([i915#14544] / [i915#15102] / [i915#3023]) +3 other tests skip
   [730]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-2/igt@kms_frontbuffer_tracking@psr-1p-primscrn-cur-indfb-draw-mmap-cpu.html
   [731]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-6/igt@kms_frontbuffer_tracking@psr-1p-primscrn-cur-indfb-draw-mmap-cpu.html

  * igt@kms_frontbuffer_tracking@psr-1p-primscrn-cur-indfb-move:
    - shard-dg2:          [SKIP][732] ([i915#10433] / [i915#15102] / [i915#3458]) -> [SKIP][733] ([i915#15102] / [i915#3458]) +2 other tests skip
   [732]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-4/igt@kms_frontbuffer_tracking@psr-1p-primscrn-cur-indfb-move.html
   [733]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-6/igt@kms_frontbuffer_tracking@psr-1p-primscrn-cur-indfb-move.html

  * igt@kms_frontbuffer_tracking@psr-1p-primscrn-shrfb-msflip-blt:
    - shard-rkl:          [SKIP][734] ([i915#14544] / [i915#15102] / [i915#3023]) -> [SKIP][735] ([i915#15102] / [i915#3023]) +6 other tests skip
   [734]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-6/igt@kms_frontbuffer_tracking@psr-1p-primscrn-shrfb-msflip-blt.html
   [735]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-8/igt@kms_frontbuffer_tracking@psr-1p-primscrn-shrfb-msflip-blt.html

  * igt@kms_frontbuffer_tracking@psr-2p-scndscrn-cur-indfb-draw-mmap-cpu:
    - shard-dg2:          [SKIP][736] ([i915#15689]) -> [SKIP][737] ([i915#5354]) +27 other tests skip
   [736]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@kms_frontbuffer_tracking@psr-2p-scndscrn-cur-indfb-draw-mmap-cpu.html
   [737]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-1/igt@kms_frontbuffer_tracking@psr-2p-scndscrn-cur-indfb-draw-mmap-cpu.html

  * igt@kms_frontbuffer_tracking@psr-2p-scndscrn-pri-shrfb-draw-pwrite:
    - shard-rkl:          [SKIP][738] ([i915#14544] / [i915#1825]) -> [SKIP][739] ([i915#1825]) +6 other tests skip
   [738]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-6/igt@kms_frontbuffer_tracking@psr-2p-scndscrn-pri-shrfb-draw-pwrite.html
   [739]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-8/igt@kms_frontbuffer_tracking@psr-2p-scndscrn-pri-shrfb-draw-pwrite.html

  * igt@kms_frontbuffer_tracking@psr-rgb101010-draw-mmap-gtt:
    - shard-dg2:          [SKIP][740] ([i915#8708]) -> [SKIP][741] ([i915#15689]) +10 other tests skip
   [740]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-3/igt@kms_frontbuffer_tracking@psr-rgb101010-draw-mmap-gtt.html
   [741]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_frontbuffer_tracking@psr-rgb101010-draw-mmap-gtt.html

  * igt@kms_hdr@invalid-hdr:
    - shard-rkl:          [SKIP][742] ([i915#14544] / [i915#3555] / [i915#8228]) -> [SKIP][743] ([i915#3555] / [i915#8228])
   [742]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-6/igt@kms_hdr@invalid-hdr.html
   [743]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-4/igt@kms_hdr@invalid-hdr.html

  * igt@kms_hdr@static-toggle:
    - shard-dg2:          [SKIP][744] ([i915#15689]) -> [SKIP][745] ([i915#3555] / [i915#8228]) +1 other test skip
   [744]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@kms_hdr@static-toggle.html
   [745]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-5/igt@kms_hdr@static-toggle.html

  * igt@kms_hdr@static-toggle-suspend:
    - shard-dg2:          [SKIP][746] ([i915#3555] / [i915#8228]) -> [SKIP][747] ([i915#15689])
   [746]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-8/igt@kms_hdr@static-toggle-suspend.html
   [747]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_hdr@static-toggle-suspend.html

  * igt@kms_joiner@invalid-modeset-big-joiner:
    - shard-dg2:          [SKIP][748] ([i915#15460]) -> [SKIP][749] ([i915#15689])
   [748]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-7/igt@kms_joiner@invalid-modeset-big-joiner.html
   [749]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_joiner@invalid-modeset-big-joiner.html

  * igt@kms_multipipe_modeset@basic-max-pipe-crc-check:
    - shard-dg2:          [SKIP][750] ([i915#4816]) -> [SKIP][751] ([i915#15689])
   [750]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-7/igt@kms_multipipe_modeset@basic-max-pipe-crc-check.html
   [751]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_multipipe_modeset@basic-max-pipe-crc-check.html

  * igt@kms_panel_fitting@legacy:
    - shard-dg2:          [SKIP][752] ([i915#15689]) -> [SKIP][753] ([i915#6301])
   [752]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@kms_panel_fitting@legacy.html
   [753]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-6/igt@kms_panel_fitting@legacy.html

  * igt@kms_pipe_b_c_ivb@from-pipe-c-to-b-with-3-lanes:
    - shard-dg2:          [SKIP][754] -> [SKIP][755] ([i915#15689] / [i915#2575]) +4 other tests skip
   [754]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-1/igt@kms_pipe_b_c_ivb@from-pipe-c-to-b-with-3-lanes.html
   [755]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_pipe_b_c_ivb@from-pipe-c-to-b-with-3-lanes.html

  * igt@kms_plane@pixel-format-4-tiled-lnl-ccs-modifier-source-clamping:
    - shard-rkl:          [SKIP][756] ([i915#15709]) -> [SKIP][757] ([i915#14544] / [i915#15709]) +2 other tests skip
   [756]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-8/igt@kms_plane@pixel-format-4-tiled-lnl-ccs-modifier-source-clamping.html
   [757]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-6/igt@kms_plane@pixel-format-4-tiled-lnl-ccs-modifier-source-clamping.html

  * igt@kms_plane@pixel-format-y-tiled-ccs-modifier:
    - shard-dg2:          [SKIP][758] ([i915#15709]) -> [SKIP][759] ([i915#15689]) +3 other tests skip
   [758]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-3/igt@kms_plane@pixel-format-y-tiled-ccs-modifier.html
   [759]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_plane@pixel-format-y-tiled-ccs-modifier.html
    - shard-rkl:          [SKIP][760] ([i915#14544] / [i915#15709]) -> [SKIP][761] ([i915#15709]) +2 other tests skip
   [760]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-6/igt@kms_plane@pixel-format-y-tiled-ccs-modifier.html
   [761]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-4/igt@kms_plane@pixel-format-y-tiled-ccs-modifier.html

  * igt@kms_plane@pixel-format-y-tiled-gen12-mc-ccs-modifier:
    - shard-dg2:          [SKIP][762] ([i915#15689]) -> [SKIP][763] ([i915#15709]) +7 other tests skip
   [762]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@kms_plane@pixel-format-y-tiled-gen12-mc-ccs-modifier.html
   [763]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-3/igt@kms_plane@pixel-format-y-tiled-gen12-mc-ccs-modifier.html

  * igt@kms_plane_lowres@tiling-4:
    - shard-rkl:          [SKIP][764] ([i915#3555]) -> [SKIP][765] ([i915#14544] / [i915#3555]) +1 other test skip
   [764]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-5/igt@kms_plane_lowres@tiling-4.html
   [765]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-6/igt@kms_plane_lowres@tiling-4.html

  * igt@kms_plane_lowres@tiling-yf:
    - shard-dg2:          [SKIP][766] ([i915#3555] / [i915#8821]) -> [SKIP][767] ([i915#15689])
   [766]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-5/igt@kms_plane_lowres@tiling-yf.html
   [767]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_plane_lowres@tiling-yf.html

  * igt@kms_plane_multiple@2x-tiling-x:
    - shard-dg2:          [SKIP][768] ([i915#15689]) -> [SKIP][769] ([i915#13958])
   [768]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@kms_plane_multiple@2x-tiling-x.html
   [769]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-6/igt@kms_plane_multiple@2x-tiling-x.html

  * igt@kms_plane_multiple@2x-tiling-y:
    - shard-rkl:          [SKIP][770] ([i915#13958] / [i915#14544]) -> [SKIP][771] ([i915#13958]) +1 other test skip
   [770]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-6/igt@kms_plane_multiple@2x-tiling-y.html
   [771]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-7/igt@kms_plane_multiple@2x-tiling-y.html

  * igt@kms_plane_multiple@2x-tiling-yf:
    - shard-dg2:          [SKIP][772] ([i915#13958]) -> [SKIP][773] ([i915#15689])
   [772]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-6/igt@kms_plane_multiple@2x-tiling-yf.html
   [773]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_plane_multiple@2x-tiling-yf.html

  * igt@kms_pm_backlight@brightness-with-dpms:
    - shard-dg2:          [SKIP][774] ([i915#15689]) -> [SKIP][775] ([i915#12343])
   [774]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@kms_pm_backlight@brightness-with-dpms.html
   [775]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-8/igt@kms_pm_backlight@brightness-with-dpms.html

  * igt@kms_pm_dc@dc5-retention-flops:
    - shard-rkl:          [SKIP][776] ([i915#3828]) -> [SKIP][777] ([i915#14544] / [i915#3828])
   [776]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-8/igt@kms_pm_dc@dc5-retention-flops.html
   [777]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-6/igt@kms_pm_dc@dc5-retention-flops.html

  * igt@kms_pm_dc@dc6-psr:
    - shard-dg2:          [SKIP][778] ([i915#9685]) -> [SKIP][779] ([i915#15689])
   [778]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-3/igt@kms_pm_dc@dc6-psr.html
   [779]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_pm_dc@dc6-psr.html

  * igt@kms_pm_dc@dc9-dpms:
    - shard-tglu:         [SKIP][780] ([i915#15739]) -> [SKIP][781] ([i915#15128])
   [780]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-tglu-10/igt@kms_pm_dc@dc9-dpms.html
   [781]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-tglu-6/igt@kms_pm_dc@dc9-dpms.html

  * igt@kms_pm_lpsp@kms-lpsp:
    - shard-dg2:          [SKIP][782] ([i915#15689]) -> [SKIP][783] ([i915#9340])
   [782]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@kms_pm_lpsp@kms-lpsp.html
   [783]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-5/igt@kms_pm_lpsp@kms-lpsp.html

  * igt@kms_pm_lpsp@screens-disabled:
    - shard-dg2:          [SKIP][784] ([i915#8430]) -> [SKIP][785] ([i915#15689])
   [784]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-8/igt@kms_pm_lpsp@screens-disabled.html
   [785]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_pm_lpsp@screens-disabled.html

  * igt@kms_pm_rpm@modeset-lpsp:
    - shard-dg2:          [SKIP][786] -> [SKIP][787] ([i915#15073]) +1 other test skip
   [786]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@kms_pm_rpm@modeset-lpsp.html
   [787]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-8/igt@kms_pm_rpm@modeset-lpsp.html

  * igt@kms_pm_rpm@modeset-lpsp-stress-no-wait:
    - shard-rkl:          [SKIP][788] ([i915#14544] / [i915#15073]) -> [SKIP][789] ([i915#15073])
   [788]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-6/igt@kms_pm_rpm@modeset-lpsp-stress-no-wait.html
   [789]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-3/igt@kms_pm_rpm@modeset-lpsp-stress-no-wait.html

  * igt@kms_pm_rpm@pc8-residency:
    - shard-dg2:          [SKIP][790] -> [SKIP][791] ([i915#15693])
   [790]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-8/igt@kms_pm_rpm@pc8-residency.html
   [791]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_pm_rpm@pc8-residency.html

  * igt@kms_pm_rpm@pm-tiling:
    - shard-dg2:          [SKIP][792] ([i915#4077]) -> [SKIP][793] ([i915#15693])
   [792]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-4/igt@kms_pm_rpm@pm-tiling.html
   [793]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_pm_rpm@pm-tiling.html

  * igt@kms_pm_rpm@system-suspend-idle:
    - shard-rkl:          [ABORT][794] ([i915#15132]) -> [INCOMPLETE][795] ([i915#14419])
   [794]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-1/igt@kms_pm_rpm@system-suspend-idle.html
   [795]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-6/igt@kms_pm_rpm@system-suspend-idle.html

  * igt@kms_psr2_sf@fbc-pr-cursor-plane-update-sf:
    - shard-rkl:          [SKIP][796] ([i915#11520]) -> [SKIP][797] ([i915#11520] / [i915#14544])
   [796]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-8/igt@kms_psr2_sf@fbc-pr-cursor-plane-update-sf.html
   [797]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-6/igt@kms_psr2_sf@fbc-pr-cursor-plane-update-sf.html

  * igt@kms_psr2_sf@fbc-psr2-cursor-plane-move-continuous-exceed-sf:
    - shard-dg2:          [SKIP][798] ([i915#15689]) -> [SKIP][799] ([i915#11520]) +4 other tests skip
   [798]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@kms_psr2_sf@fbc-psr2-cursor-plane-move-continuous-exceed-sf.html
   [799]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-3/igt@kms_psr2_sf@fbc-psr2-cursor-plane-move-continuous-exceed-sf.html

  * igt@kms_psr2_sf@fbc-psr2-overlay-primary-update-sf-dmg-area:
    - shard-rkl:          [SKIP][800] ([i915#11520] / [i915#14544]) -> [SKIP][801] ([i915#11520]) +2 other tests skip
   [800]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-6/igt@kms_psr2_sf@fbc-psr2-overlay-primary-update-sf-dmg-area.html
   [801]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-4/igt@kms_psr2_sf@fbc-psr2-overlay-primary-update-sf-dmg-area.html

  * igt@kms_psr2_sf@psr2-overlay-plane-update-continuous-sf:
    - shard-dg2:          [SKIP][802] ([i915#11520]) -> [SKIP][803] ([i915#15689]) +6 other tests skip
   [802]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-3/igt@kms_psr2_sf@psr2-overlay-plane-update-continuous-sf.html
   [803]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_psr2_sf@psr2-overlay-plane-update-continuous-sf.html

  * igt@kms_psr2_su@page_flip-xrgb8888:
    - shard-dg2:          [SKIP][804] ([i915#15689]) -> [SKIP][805] ([i915#9683])
   [804]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@kms_psr2_su@page_flip-xrgb8888.html
   [805]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-4/igt@kms_psr2_su@page_flip-xrgb8888.html

  * igt@kms_psr@fbc-psr-sprite-blt:
    - shard-rkl:          [SKIP][806] ([i915#1072] / [i915#14544] / [i915#9732]) -> [SKIP][807] ([i915#1072] / [i915#9732]) +3 other tests skip
   [806]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-6/igt@kms_psr@fbc-psr-sprite-blt.html
   [807]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-8/igt@kms_psr@fbc-psr-sprite-blt.html

  * igt@kms_psr@psr-primary-mmap-cpu:
    - shard-dg2:          [SKIP][808] ([i915#1072] / [i915#9732]) -> [SKIP][809] ([i915#15689]) +23 other tests skip
   [808]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-8/igt@kms_psr@psr-primary-mmap-cpu.html
   [809]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_psr@psr-primary-mmap-cpu.html
    - shard-rkl:          [SKIP][810] ([i915#1072] / [i915#9732]) -> [SKIP][811] ([i915#1072] / [i915#14544] / [i915#9732]) +3 other tests skip
   [810]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-2/igt@kms_psr@psr-primary-mmap-cpu.html
   [811]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-6/igt@kms_psr@psr-primary-mmap-cpu.html

  * igt@kms_psr@psr2-primary-mmap-gtt:
    - shard-dg2:          [SKIP][812] ([i915#15689]) -> [SKIP][813] ([i915#1072] / [i915#9732]) +22 other tests skip
   [812]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@kms_psr@psr2-primary-mmap-gtt.html
   [813]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-1/igt@kms_psr@psr2-primary-mmap-gtt.html

  * igt@kms_rotation_crc@primary-rotation-270:
    - shard-dg2:          [SKIP][814] ([i915#12755]) -> [SKIP][815] ([i915#15689]) +2 other tests skip
   [814]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-4/igt@kms_rotation_crc@primary-rotation-270.html
   [815]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_rotation_crc@primary-rotation-270.html

  * igt@kms_rotation_crc@primary-yf-tiled-reflect-x-270:
    - shard-dg2:          [SKIP][816] ([i915#15689] / [i915#5190]) -> [SKIP][817] ([i915#12755] / [i915#5190]) +1 other test skip
   [816]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@kms_rotation_crc@primary-yf-tiled-reflect-x-270.html
   [817]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-4/igt@kms_rotation_crc@primary-yf-tiled-reflect-x-270.html
    - shard-rkl:          [SKIP][818] ([i915#14544] / [i915#5289]) -> [SKIP][819] ([i915#5289])
   [818]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-6/igt@kms_rotation_crc@primary-yf-tiled-reflect-x-270.html
   [819]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-4/igt@kms_rotation_crc@primary-yf-tiled-reflect-x-270.html

  * igt@kms_rotation_crc@sprite-rotation-270:
    - shard-dg2:          [SKIP][820] ([i915#15689]) -> [SKIP][821] ([i915#12755])
   [820]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@kms_rotation_crc@sprite-rotation-270.html
   [821]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-3/igt@kms_rotation_crc@sprite-rotation-270.html

  * igt@kms_scaling_modes@scaling-mode-full:
    - shard-rkl:          [SKIP][822] ([i915#14544] / [i915#3555]) -> [SKIP][823] ([i915#3555])
   [822]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-rkl-6/igt@kms_scaling_modes@scaling-mode-full.html
   [823]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-rkl-3/igt@kms_scaling_modes@scaling-mode-full.html

  * igt@kms_vrr@flip-basic:
    - shard-dg2:          [SKIP][824] ([i915#15689]) -> [SKIP][825] ([i915#15243] / [i915#3555])
   [824]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@kms_vrr@flip-basic.html
   [825]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-1/igt@kms_vrr@flip-basic.html

  * igt@kms_vrr@max-min:
    - shard-dg2:          [SKIP][826] ([i915#9906]) -> [SKIP][827] ([i915#15689])
   [826]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-3/igt@kms_vrr@max-min.html
   [827]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@kms_vrr@max-min.html

  * igt@perf@global-sseu-config-invalid:
    - shard-dg2:          [SKIP][828] -> [SKIP][829] ([i915#7387]) +1 other test skip
   [828]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@perf@global-sseu-config-invalid.html
   [829]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-7/igt@perf@global-sseu-config-invalid.html

  * igt@perf@mi-rpc:
    - shard-dg2:          [SKIP][830] -> [SKIP][831] ([i915#2434])
   [830]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@perf@mi-rpc.html
   [831]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-3/igt@perf@mi-rpc.html

  * igt@prime_mmap@test_aperture_limit:
    - shard-dg2:          [SKIP][832] ([i915#15689] / [i915#2575]) -> [SKIP][833] ([i915#14121])
   [832]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@prime_mmap@test_aperture_limit.html
   [833]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-6/igt@prime_mmap@test_aperture_limit.html

  * igt@prime_vgem@basic-gtt:
    - shard-dg2:          [SKIP][834] ([i915#15689] / [i915#2575]) -> [SKIP][835] ([i915#3708] / [i915#4077])
   [834]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@prime_vgem@basic-gtt.html
   [835]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-8/igt@prime_vgem@basic-gtt.html

  * igt@prime_vgem@fence-read-hang:
    - shard-dg2:          [SKIP][836] ([i915#15689] / [i915#2575]) -> [SKIP][837] ([i915#3708])
   [836]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@prime_vgem@fence-read-hang.html
   [837]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-8/igt@prime_vgem@fence-read-hang.html

  * igt@sriov_basic@enable-vfs-autoprobe-off:
    - shard-dg2:          [SKIP][838] ([i915#15689]) -> [SKIP][839] ([i915#9917]) +1 other test skip
   [838]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-11/igt@sriov_basic@enable-vfs-autoprobe-off.html
   [839]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-4/igt@sriov_basic@enable-vfs-autoprobe-off.html

  * igt@sriov_basic@enable-vfs-bind-unbind-each-numvfs-all:
    - shard-dg2:          [SKIP][840] ([i915#9917]) -> [SKIP][841] ([i915#15689]) +1 other test skip
   [840]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_18050/shard-dg2-5/igt@sriov_basic@enable-vfs-bind-unbind-each-numvfs-all.html
   [841]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14620/shard-dg2-11/igt@sriov_basic@enable-vfs-bind-unbind-each-numvfs-all.html

  
  {name}: This element is suppressed. This means it is ignored when computing
          the status of the difference (SUCCESS, WARNING, or FAILURE).

  [i915#10055]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/10055
  [i915#10056]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/10056
  [i915#10307]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/10307
  [i915#10433]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/10433
  [i915#10434]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/10434
  [i915#1072]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/1072
  [i915#1099]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/1099
  [i915#11078]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/11078
  [i915#11151]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/11151
  [i915#11520]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/11520
  [i915#11527]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/11527
  [i915#11681]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/11681
  [i915#11965]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/11965
  [i915#12193]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/12193
  [i915#12313]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/12313
  [i915#12316]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/12316
  [i915#12343]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/12343
  [i915#12358]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/12358
  [i915#12454]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/12454
  [i915#1257]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/1257
  [i915#12655]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/12655
  [i915#12712]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/12712
  [i915#12713]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/12713
  [i915#12755]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/12755
  [i915#12761]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/12761
  [i915#12805]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/12805
  [i915#12910]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/12910
  [i915#13029]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13029
  [i915#13046]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13046
  [i915#13049]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13049
  [i915#13179]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13179
  [i915#13356]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13356
  [i915#13363]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13363
  [i915#13398]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13398
  [i915#13562]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13562
  [i915#13566]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13566
  [i915#13688]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13688
  [i915#13691]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13691
  [i915#13705]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13705
  [i915#13707]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13707
  [i915#13748]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13748
  [i915#13749]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13749
  [i915#13781]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13781
  [i915#13786]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13786
  [i915#13790]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13790
  [i915#13958]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13958
  [i915#14033]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14033
  [i915#14073]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14073
  [i915#14098]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14098
  [i915#14118]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14118
  [i915#14121]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14121
  [i915#14123]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14123
  [i915#14152]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14152
  [i915#14242]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14242
  [i915#14259]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14259
  [i915#14350]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14350
  [i915#14419]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14419
  [i915#14544]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14544
  [i915#14545]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14545
  [i915#14702]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14702
  [i915#14712]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14712
  [i915#14995]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14995
  [i915#15073]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15073
  [i915#15102]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15102
  [i915#15104]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15104
  [i915#15128]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15128
  [i915#15132]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15132
  [i915#15243]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15243
  [i915#15329]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15329
  [i915#15330]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15330
  [i915#15389]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15389
  [i915#15403]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15403
  [i915#15453]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15453
  [i915#15454]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15454
  [i915#15458]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15458
  [i915#15459]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15459
  [i915#15460]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15460
  [i915#15582]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15582
  [i915#15607]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15607
  [i915#15608]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15608
  [i915#15643]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15643
  [i915#15678]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15678
  [i915#15689]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15689
  [i915#15693]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15693
  [i915#15709]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15709
  [i915#15725]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15725
  [i915#15734]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15734
  [i915#15739]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15739
  [i915#15759]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15759
  [i915#15764]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15764
  [i915#1769]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/1769
  [i915#1825]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/1825
  [i915#1839]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/1839
  [i915#1849]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/1849
  [i915#2190]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/2190
  [i915#2433]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/2433
  [i915#2434]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/2434
  [i915#2435]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/2435
  [i915#2527]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/2527
  [i915#2575]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/2575
  [i915#2582]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/2582
  [i915#2658]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/2658
  [i915#2681]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/2681
  [i915#280]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/280
  [i915#2856]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/2856
  [i915#3023]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3023
  [i915#3116]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3116
  [i915#3281]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3281
  [i915#3282]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3282
  [i915#3291]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3291
  [i915#3297]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3297
  [i915#3299]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3299
  [i915#3458]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3458
  [i915#3469]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3469
  [i915#3539]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3539
  [i915#3555]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3555
  [i915#3637]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3637
  [i915#3638]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3638
  [i915#3708]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3708
  [i915#3742]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3742
  [i915#3804]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3804
  [i915#3828]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3828
  [i915#3840]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3840
  [i915#3936]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3936
  [i915#3955]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3955
  [i915#4036]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4036
  [i915#4077]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4077
  [i915#4079]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4079
  [i915#4083]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4083
  [i915#4103]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4103
  [i915#4212]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4212
  [i915#4213]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4213
  [i915#4270]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4270
  [i915#4349]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4349
  [i915#4387]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4387
  [i915#4391]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4391
  [i915#4423]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4423
  [i915#4525]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4525
  [i915#4537]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4537
  [i915#4538]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4538
  [i915#4565]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4565
  [i915#4613]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4613
  [i915#4771]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4771
  [i915#4812]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4812
  [i915#4816]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4816
  [i915#4817]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4817
  [i915#4852]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4852
  [i915#4860]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4860
  [i915#4880]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4880
  [i915#4881]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4881
  [i915#4884]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4884
  [i915#4885]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4885
  [i915#4958]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4958
  [i915#5107]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/5107
  [i915#5190]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/5190
  [i915#5286]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/5286
  [i915#5289]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/5289
  [i915#5354]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/5354
  [i915#5493]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/5493
  [i915#5566]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/5566
  [i915#6095]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/6095
  [i915#6113]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/6113
  [i915#6230]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/6230
  [i915#6301]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/6301
  [i915#6335]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/6335
  [i915#6524]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/6524
  [i915#658]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/658
  [i915#6590]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/6590
  [i915#6621]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/6621
  [i915#6880]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/6880
  [i915#6944]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/6944
  [i915#6953]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/6953
  [i915#7116]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/7116
  [i915#7118]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/7118
  [i915#7387]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/7387
  [i915#7697]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/7697
  [i915#7828]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/7828
  [i915#7882]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/7882
  [i915#7975]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/7975
  [i915#8228]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/8228
  [i915#8289]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/8289
  [i915#8381]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/8381
  [i915#8399]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/8399
  [i915#8411]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/8411
  [i915#8428]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/8428
  [i915#8430]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/8430
  [i915#8555]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/8555
  [i915#8562]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/8562
  [i915#8708]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/8708
  [i915#8810]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/8810
  [i915#8812]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/8812
  [i915#8813]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/8813
  [i915#8814]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/8814
  [i915#8821]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/8821
  [i915#9053]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9053
  [i915#9067]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9067
  [i915#9100]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9100
  [i915#9323]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9323
  [i915#9337]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9337
  [i915#9340]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9340
  [i915#9423]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9423
  [i915#9424]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9424
  [i915#9531]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9531
  [i915#9683]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9683
  [i915#9685]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9685
  [i915#9688]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9688
  [i915#9723]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9723
  [i915#9732]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9732
  [i915#9766]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9766
  [i915#9812]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9812
  [i915#9833]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9833
  [i915#9906]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9906
  [i915#9917]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9917
  [i915#9934]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9934


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

  * CI: CI-20190529 -> None
  * IGT: IGT_8772 -> IGTPW_14620
  * Piglit: piglit_4509 -> None

  CI-20190529: 20190529
  CI_DRM_18050: f0ec6252eb6d9a4f0cb5a437f5c21fec16d0a440 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGTPW_14620: 14620
  IGT_8772: 8772
  piglit_4509: fdc5a4ca11124ab8413c7988896eec4c97336694 @ git://anongit.freedesktop.org/piglit

== Logs ==

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

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

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

* Re: [i-g-t,1/6] lib/igt_edid: add EDID serial extraction helpers
  2026-02-25 21:28 ` [PATCH i-g-t 1/6] lib/igt_edid: add EDID serial extraction helpers Kunal Joshi
@ 2026-03-09  9:30   ` Murthy, Arun R
  2026-03-09 11:02     ` Joshi, Kunal1
  0 siblings, 1 reply; 25+ messages in thread
From: Murthy, Arun R @ 2026-03-09  9:30 UTC (permalink / raw)
  To: Kunal Joshi, igt-dev

On 26-02-2026 02:58, Kunal Joshi wrote:
> Add helpers to extract serial identification from EDID data.
>
>   - edid_get_serial_string(): extract ASCII serial from descriptor 0xFF
>   - edid_get_serial_number(): extract 32-bit serial from EDID header
>   - edid_get_any_serial(): convenience helper that tries ASCII serial
>     first, then falls back to 32-bit header serial formatted as hex
>
> These are needed by the connector helper and USB4 switch test suite
> for EDID-based display verification after dock/undock events.
>
> Signed-off-by: Kunal Joshi <kunal1.joshi@intel.com>
> ---
>   lib/igt_edid.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++
>   lib/igt_edid.h |  5 +++
>   2 files changed, 96 insertions(+)
>
> diff --git a/lib/igt_edid.c b/lib/igt_edid.c
> index c68ccf671..e7fcbf0b9 100644
> --- a/lib/igt_edid.c
> +++ b/lib/igt_edid.c
> @@ -249,6 +249,97 @@ void edid_get_monitor_name(const struct edid *edid, char *name, size_t name_size
>   	name[0] = '\0';
>   }
>   
> +/**
> + * edid_get_serial_string:
> + * @edid: EDID structure
> + * @serial: buffer to write serial string
> + * @serial_size: size of serial buffer; must be > 1
> + *
> + * Extract the serial string from EDID descriptor block type 0xFF.
> + * The descriptor payload is a 13-byte fixed-width field; trailing
> + * whitespace is stripped and the result is NUL-terminated.
> + * @serial is left empty when no 0xFF descriptor is found.
> + */
> +void edid_get_serial_string(const struct edid *edid,
> +			    char *serial, size_t serial_size)
We are trying to get the timings so rather than a generic name 
serial_string, can this be replaced with get_detailed_timings ?
> +{
> +	size_t copy_len, i, n;
> +
> +	igt_assert(edid);
> +	igt_assert(serial);
> +	igt_assert(serial_size > 1);
> +	serial[0] = '\0';
> +
> +	for (i = 0; i < DETAILED_TIMINGS_LEN; i++) {
> +		const uint8_t *d = (const uint8_t *)&edid->detailed_timings[i];
> +
> +		if (d[0] != 0x00 || d[1] != 0x00 || d[2] != 0x00)
> +			continue;
> +
> +		if (d[3] != EDID_DETAIL_MONITOR_SERIAL || d[4] != 0x00)
> +			continue;
> +
> +		/* Descriptor string payload is 13 bytes starting at d[5] */
> +		copy_len = serial_size - 1 < 13 ? serial_size - 1 : 13;
> +		memcpy(serial, &d[5], copy_len);
Can strncpy() be used instead?
> +		serial[copy_len] = '\0';
> +
> +		for (n = strlen(serial);
> +		     n > 0 && isspace((unsigned char)serial[n - 1]); n--)
> +			serial[n - 1] = '\0';
> +
> +		return;
> +	}
> +}
> +
> +/**
> + * edid_get_serial_number:
> + * @edid: EDID structure
> + *
> + * Extract the 32-bit serial number from the EDID base block header
> + * (bytes 12–15, the manufacturer/product section).  This is different
> + * from the ASCII serial string in descriptor block 0xFF.
> + *
> + * Returns: 32-bit serial number (little-endian), 0 if absent.
> + */
> +uint32_t edid_get_serial_number(const struct edid *edid)
> +{
> +	return (uint32_t)edid->serial[0] |
> +	       ((uint32_t)edid->serial[1] << 8) |
> +	       ((uint32_t)edid->serial[2] << 16) |
> +	       ((uint32_t)edid->serial[3] << 24);
> +}
> +
> +/**
> + * edid_get_any_serial:
No description added?

Thanks and Regards,
Arun R Murthy
--------------------
> + * @edid: EDID structure
> + * @serial: buffer to write serial string
> + * @serial_size: size of serial buffer; must be > 1
> + *
> + * Convenience helper that tries to extract a serial identifier from EDID.
> + * First tries the ASCII serial string descriptor (0xFF). If that is empty,
> + * falls back to the 32-bit header serial number formatted as 8-char hex.
> + * If neither source provides a usable serial (no 0xFF descriptor and the
> + * header serial is 0), @serial is left empty.
> + */
> +void edid_get_any_serial(const struct edid *edid,
> +			 char *serial, size_t serial_size)
> +{
> +	uint32_t serial_num;
> +
> +	igt_assert(edid);
> +	igt_assert(serial);
> +	igt_assert(serial_size > 1);
> +
> +	edid_get_serial_string(edid, serial, serial_size);
> +	if (serial[0])
> +		return;
> +
> +	serial_num = edid_get_serial_number(edid);
> +	if (serial_num != 0)
> +		snprintf(serial, serial_size, "%08X", serial_num);
> +}
> +
>   static void edid_set_mfg(struct edid *edid, const char mfg[static 3])
>   {
>   	edid->mfg_id[0] = (mfg[0] - '@') << 2 | (mfg[1] - '@') >> 3;
> diff --git a/lib/igt_edid.h b/lib/igt_edid.h
> index be0ccf529..d9e396065 100644
> --- a/lib/igt_edid.h
> +++ b/lib/igt_edid.h
> @@ -457,5 +457,10 @@ void *dispid_block_tiled(void *ptr,
>   			 int hsize, int vsize,
>   			 const char *topology_id);
>   void edid_get_monitor_name(const struct edid *edid, char *name, size_t name_size);
> +void edid_get_serial_string(const struct edid *edid,
> +			    char *serial, size_t serial_size);
> +uint32_t edid_get_serial_number(const struct edid *edid);
> +void edid_get_any_serial(const struct edid *edid,
> +			 char *serial, size_t serial_size);
>   
>   #endif

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

* Re: [i-g-t,2/6] lib/igt_connector_helper: Add generic connector helpers
  2026-02-25 21:28 ` [PATCH i-g-t 2/6] lib/igt_connector_helper: Add generic connector helpers Kunal Joshi
@ 2026-03-09  9:38   ` Murthy, Arun R
  2026-03-09 11:06     ` Joshi, Kunal1
  0 siblings, 1 reply; 25+ messages in thread
From: Murthy, Arun R @ 2026-03-09  9:38 UTC (permalink / raw)
  To: Kunal Joshi, igt-dev

On 26-02-2026 02:58, Kunal Joshi wrote:
> Add a lightweight helper library for DRM connector operations used
> by USB4 switch and other dock/undock tests:
>
>   - igt_connector_get_connected(): enumerate connected connectors
>   - igt_connector_get_info(): query name, EDID serial, and MST path
>   - igt_connector_find_by_path(): PATH-based connector lookup (MST)
>   - igt_connector_find_by_name(): name-based connector lookup
>   - igt_connector_reprobe_all(): force reprobe all connectors by
>     iterating each connector to trigger DRM core re-detection
>
> These helpers abstract common DRM connector patterns that are needed
> by multiple test suites for display enumeration and verification.
The contents of these are already present in lib/igt__kms.c

Instead of a new file, can these be exported from lib/igt_kms.c ?


Thanks and Regards,
Arun R Murthy
-------------------

>
> Signed-off-by: Kunal Joshi <kunal1.joshi@intel.com>
> ---
>   lib/igt_connector_helper.c | 299 +++++++++++++++++++++++++++++++++++++
>   lib/igt_connector_helper.h |  27 ++++
>   lib/meson.build            |   1 +
>   3 files changed, 327 insertions(+)
>   create mode 100644 lib/igt_connector_helper.c
>   create mode 100644 lib/igt_connector_helper.h
>
> diff --git a/lib/igt_connector_helper.c b/lib/igt_connector_helper.c
> new file mode 100644
> index 000000000..6be849b7a
> --- /dev/null
> +++ b/lib/igt_connector_helper.c
> @@ -0,0 +1,299 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2026 Intel Corporation
> + */
> +
> +/**
> + * SECTION:igt_connector_helper
> + * @short_description: Generic connector helper functions for DRM/KMS
> + * @title: Connector Helper
> + * @include: igt_connector_helper.h
> + *
> + * Helper functions for DRM connector operations including enumeration,
> + * lookup by name/path, and EDID serial extraction.
> + */
> +
> +#include <string.h>
> +#include <xf86drm.h>
> +#include <xf86drmMode.h>
> +
> +#include "igt_core.h"
> +#include "igt_edid.h"
> +#include "igt_kms.h"
> +#include "igt_connector_helper.h"
> +
> +/**
> + * igt_connector_get_connected:
> + * @drm_fd: DRM file descriptor
> + * @connectors: array to store connector IDs; must be valid if @max_connectors > 0
> + * @max_connectors: maximum number of connectors to store
> + *
> + * Walks all DRM connectors and stores the IDs of those currently connected.
> + * Scanning stops once @max_connectors IDs have been collected; later
> + * connectors are not examined.
> + *
> + * Returns: number of connector IDs written to @connectors, capped by
> + * @max_connectors.
> + */
> +int igt_connector_get_connected(int drm_fd, uint32_t *connectors,
> +				int max_connectors)
> +{
> +	drmModeRes *res;
> +	drmModeConnector *conn;
> +	int count = 0;
> +	int i;
> +
> +	igt_assert(max_connectors >= 0);
> +	if (max_connectors > 0)
> +		igt_assert(connectors);
> +
> +	res = drmModeGetResources(drm_fd);
> +	if (!res)
> +		return 0;
> +
> +	for (i = 0; i < res->count_connectors && count < max_connectors; i++) {
> +		conn = drmModeGetConnector(drm_fd, res->connectors[i]);
> +		if (!conn)
> +			continue;
> +
> +		if (conn->connection == DRM_MODE_CONNECTED)
> +			connectors[count++] = conn->connector_id;
> +
> +		drmModeFreeConnector(conn);
> +	}
> +
> +	drmModeFreeResources(res);
> +	return count;
> +}
> +
> +/**
> + * igt_connector_get_info:
> + * @drm_fd: DRM file descriptor
> + * @connector_id: connector ID
> + * @name: buffer for connector name (mandatory)
> + * @name_size: size of @name; must be > 0
> + * @serial: buffer for EDID-derived serial (mandatory)
> + * @serial_size: size of @serial; must be > 1
> + * @path: buffer for MST PATH property (optional, may be NULL)
> + * @path_size: size of @path buffer
> + *
> + * Fills connector name, MST PATH, and EDID-derived serial for a connector.
> + * @name is always filled when the connector is found. @serial is filled from
> + * the ASCII serial string descriptor (0xFF) if present, else from the 32-bit
> + * header serial number; left empty if no EDID is available. @path is filled
> + * only if requested and the PATH property exists.
> + *
> + * Success means the connector object was found and @name was filled.
> + * @serial and @path are best-effort and may still be empty on success.
> + *
> + * Returns: true if the connector was found, false otherwise.
> + */
> +bool igt_connector_get_info(int drm_fd, uint32_t connector_id,
> +			    char *name, size_t name_size,
> +			    char *serial, size_t serial_size,
> +			    char *path, size_t path_size)
> +{
> +	drmModeConnector *conn;
> +	drmModePropertyBlobPtr edid_blob = NULL;
> +	uint64_t blob_id = 0;
> +	drmModePropertyPtr prop;
> +	const struct edid *edid;
> +	int i;
> +
> +	igt_assert(name && name_size > 0);
> +	igt_assert(serial && serial_size > 1);
> +	igt_assert(!path || path_size > 0);
> +
> +	name[0] = '\0';
> +	serial[0] = '\0';
> +	if (path)
> +		path[0] = '\0';
> +
> +	conn = drmModeGetConnector(drm_fd, connector_id);
> +	if (!conn)
> +		return false;
> +
> +	snprintf(name, name_size, "%s-%d",
> +		 kmstest_connector_type_str(conn->connector_type),
> +		 conn->connector_type_id);
> +
> +	for (i = 0; i < conn->count_props; i++) {
> +		prop = drmModeGetProperty(drm_fd, conn->props[i]);
> +		if (!prop)
> +			continue;
> +
> +		if (strcmp(prop->name, "EDID") == 0)
> +			blob_id = conn->prop_values[i];
> +
> +		drmModeFreeProperty(prop);
> +		if (blob_id)
> +			break;
> +	}
> +
> +	/* Extract MST PATH if requested */
> +	if (path) {
> +		drmModePropertyBlobPtr path_blob;
> +
> +		/* PATH blob payload is a NUL-terminated string */
> +		path_blob = kmstest_get_path_blob(drm_fd, connector_id);
> +		if (path_blob) {
> +			snprintf(path, path_size, "%s",
> +				 (const char *)path_blob->data);
> +			drmModeFreePropertyBlob(path_blob);
> +		}
> +	}
> +
> +	drmModeFreeConnector(conn);
> +
> +	if (blob_id) {
> +		edid_blob = drmModeGetPropertyBlob(drm_fd, blob_id);
> +		if (edid_blob) {
> +			if (edid_blob->length >= sizeof(struct edid)) {
> +				edid = edid_blob->data;
> +				edid_get_any_serial(edid, serial, serial_size);
> +			}
> +			drmModeFreePropertyBlob(edid_blob);
> +		}
> +	}
> +
> +	return true;
> +}
> +
> +/**
> + * igt_connector_find_by_path:
> + * @drm_fd: DRM file descriptor
> + * @path: MST PATH property value to match
> + * @connector_id: output for connector ID (filled on success)
> + *
> + * Finds the currently connected connector whose PATH property matches @path
> + * (exact string comparison).  PATH is the preferred stable identity for MST
> + * connectors; connector IDs may change across hotplug events.
> + *
> + * Returns: true if a matching connected connector was found.
> + */
> +bool igt_connector_find_by_path(int drm_fd, const char *path,
> +				uint32_t *connector_id)
> +{
> +	drmModeRes *res;
> +	drmModeConnector *conn;
> +	drmModePropertyBlobPtr path_blob;
> +	bool found = false;
> +	int i;
> +
> +	if (!path || !connector_id)
> +		return false;
> +
> +	res = drmModeGetResources(drm_fd);
> +	if (!res)
> +		return false;
> +
> +	for (i = 0; i < res->count_connectors && !found; i++) {
> +		conn = drmModeGetConnector(drm_fd, res->connectors[i]);
> +		if (!conn)
> +			continue;
> +
> +		if (conn->connection == DRM_MODE_CONNECTED) {
> +			path_blob = kmstest_get_path_blob(drm_fd,
> +							  conn->connector_id);
> +			if (path_blob) {
> +				if (strcmp(path_blob->data, path) == 0) {
> +					*connector_id = conn->connector_id;
> +					found = true;
> +				}
> +				drmModeFreePropertyBlob(path_blob);
> +			}
> +		}
> +
> +		drmModeFreeConnector(conn);
> +	}
> +
> +	drmModeFreeResources(res);
> +
> +	if (found)
> +		igt_debug("igt_connector: Found connector %u for path '%s'\n",
> +			  *connector_id, path);
> +
> +	return found;
> +}
> +
> +/**
> + * igt_connector_find_by_name:
> + * @drm_fd: DRM file descriptor
> + * @name: connector name to match (e.g., "DP-6")
> + * @connector_id: output for connector ID (filled on success)
> + *
> + * Name-based lookup helper.  Prefer igt_connector_find_by_path() for MST
> + * connectors, since connector names and IDs may change across hotplug events.
> + *
> + * Returns: true if a matching connected connector was found.
> + */
> +bool igt_connector_find_by_name(int drm_fd, const char *name,
> +				uint32_t *connector_id)
> +{
> +	drmModeRes *res;
> +	drmModeConnector *conn;
> +	char conn_name[IGT_CONNECTOR_NAME_MAX];
> +	bool found = false;
> +	int i;
> +
> +	if (!name || !connector_id)
> +		return false;
> +
> +	res = drmModeGetResources(drm_fd);
> +	if (!res)
> +		return false;
> +
> +	for (i = 0; i < res->count_connectors && !found; i++) {
> +		conn = drmModeGetConnector(drm_fd, res->connectors[i]);
> +		if (!conn)
> +			continue;
> +
> +		snprintf(conn_name, sizeof(conn_name), "%s-%d",
> +			 kmstest_connector_type_str(conn->connector_type),
> +			 conn->connector_type_id);
> +
> +		if (strcmp(conn_name, name) == 0 &&
> +		    conn->connection == DRM_MODE_CONNECTED) {
> +			*connector_id = conn->connector_id;
> +			found = true;
> +		}
> +
> +		drmModeFreeConnector(conn);
> +	}
> +
> +	drmModeFreeResources(res);
> +
> +	if (found)
> +		igt_debug("igt_connector: Found connector %u for name '%s'\n",
> +			  *connector_id, name);
> +
> +	return found;
> +}
> +
> +/**
> + * igt_connector_reprobe_all:
> + * @drm_fd: DRM file descriptor
> + *
> + * Issues a GETCONNECTOR ioctl for every connector, requesting fresh state
> + * from the kernel. This is often sufficient to refresh connector status and
> + * MST topology visibility after hotplug events, but does not guarantee a
> + * full hardware reprobe in all driver paths.
> + */
> +void igt_connector_reprobe_all(int drm_fd)
> +{
> +	drmModeRes *res;
> +	drmModeConnector *conn;
> +	int i;
> +
> +	res = drmModeGetResources(drm_fd);
> +	if (!res)
> +		return;
> +
> +	for (i = 0; i < res->count_connectors; i++) {
> +		conn = drmModeGetConnector(drm_fd, res->connectors[i]);
> +		if (conn)
> +			drmModeFreeConnector(conn);
> +	}
> +
> +	drmModeFreeResources(res);
> +}
> diff --git a/lib/igt_connector_helper.h b/lib/igt_connector_helper.h
> new file mode 100644
> index 000000000..fffb2661b
> --- /dev/null
> +++ b/lib/igt_connector_helper.h
> @@ -0,0 +1,27 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright © 2026 Intel Corporation
> + */
> +
> +#ifndef IGT_CONNECTOR_HELPER_H
> +#define IGT_CONNECTOR_HELPER_H
> +
> +#include <stdbool.h>
> +#include <stddef.h>
> +#include <stdint.h>
> +
> +#define IGT_CONNECTOR_NAME_MAX 32
> +
> +int igt_connector_get_connected(int drm_fd, uint32_t *connectors,
> +				int max_connectors);
> +bool igt_connector_get_info(int drm_fd, uint32_t connector_id,
> +			    char *name, size_t name_size,
> +			    char *serial, size_t serial_size,
> +			    char *path, size_t path_size);
> +bool igt_connector_find_by_path(int drm_fd, const char *path,
> +				uint32_t *connector_id);
> +bool igt_connector_find_by_name(int drm_fd, const char *name,
> +				uint32_t *connector_id);
> +void igt_connector_reprobe_all(int drm_fd);
> +
> +#endif /* IGT_CONNECTOR_HELPER_H */
> diff --git a/lib/meson.build b/lib/meson.build
> index ea721ecf7..074b21fdf 100644
> --- a/lib/meson.build
> +++ b/lib/meson.build
> @@ -113,6 +113,7 @@ lib_sources = [
>   	'igt_vmwgfx.c',
>   	'igt_psr.c',
>   	'igt_amd.c',
> +	'igt_connector_helper.c',
>   	'igt_edid.c',
>   	'igt_eld.c',
>   	'igt_infoframe.c',

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

* Re: [i-g-t,6/6] tests/intel/kms_usb4_switch: Add USB4 switch test suite
  2026-02-25 21:28 ` [PATCH i-g-t 6/6] tests/intel/kms_usb4_switch: Add USB4 switch test suite Kunal Joshi
@ 2026-03-09 10:03   ` Murthy, Arun R
  2026-03-09 11:14     ` Joshi, Kunal1
  0 siblings, 1 reply; 25+ messages in thread
From: Murthy, Arun R @ 2026-03-09 10:03 UTC (permalink / raw)
  To: Kunal Joshi, igt-dev


On 26-02-2026 02:58, Kunal Joshi wrote:
> Add a comprehensive test suite for USB4/Thunderbolt dock/undock and
> port switching scenarios using the Microsoft USB4 Switch 3141:
>
>   - dock-undock: Basic dock/undock cycles with display verification
>   - dock-undock-sr: Dock/undock with suspend/resume stability
>   - dock-undock-during-suspend: Dock while system is suspended
>   - switch: Port-to-port switching with display verification
>   - switch-sr: Port switching with suspend/resume stability
>   - switch-during-suspend: Port switch during suspend via HW delay
>
> Signed-off-by: Kunal Joshi <kunal1.joshi@intel.com>
> ---
>   tests/intel/kms_usb4_switch.c | 1254 +++++++++++++++++++++++++++++++++
>   tests/meson.build             |    2 +
>   2 files changed, 1256 insertions(+)
>   create mode 100644 tests/intel/kms_usb4_switch.c
>
> diff --git a/tests/intel/kms_usb4_switch.c b/tests/intel/kms_usb4_switch.c
> new file mode 100644
> index 000000000..403ad7255
> --- /dev/null
> +++ b/tests/intel/kms_usb4_switch.c
> @@ -0,0 +1,1254 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2026 Intel Corporation
> + */
> +
> +/**
> + * TEST: kms usb4 switch
> + * Category: Display
> + * Description:        USB4/Thunderbolt dock/undock and port switching tests
> + * Driver requirement: i915, xe
> + * Mega feature:       General Display Features
> + *
> + * SUBTEST: dock-undock
> + * Description:        Test dock/undock cycles with display verification.
> + *                     Verifies hotplug events, EDID serial matching, modeset with
> + *                     max non-joiner mode, and pipe CRC stability.
> + *
> + * SUBTEST: dock-undock-sr
> + * Description:        Test dock/undock with suspend/resume stability.
> + *                     Docks, verifies displays with modeset and CRC, suspends/resumes,
> + *                     then verifies displays still produce valid CRC after resume.
> + *
> + * SUBTEST: dock-during-suspend
> + * Description:        Test docking while system is suspended.
> + *                     Simulates user plugging into a suspended laptop by triggering
> + *                     dock during suspend using hardware delay command. Verifies
> + *                     modeset and pipe CRC after resume.
> + *
> + * SUBTEST: undock-during-suspend
> + * Description:        Test undocking while system is suspended.
> + *                     Docks first, verifies displays, then schedules a delayed
> + *                     undock during suspend. After resume, verifies all port
> + *                     displays have been removed.
> + *
> + * SUBTEST: switch
> + * Description:        Test switching between USB4 switch ports.
> + *                     Verifies hotplug events, display verification with modeset
> + *                     and pipe CRC when switching from one port to another.
> + *
> + * SUBTEST: switch-sr
> + * Description:        Test port switching with suspend/resume stability.
> + *                     Switches ports, verifies displays with modeset and CRC,
> + *                     suspends/resumes, then verifies CRC stability after resume.
> + *
> + * SUBTEST: switch-during-suspend
> + * Description:        Test port switching during suspend using hardware delay.
> + *                     Schedules a delayed switch, suspends system, switch occurs during
> + *                     suspend, then verifies modeset and pipe CRC on new port after resume.
> + */
> +
> +#include <ctype.h>
> +#include <sys/poll.h>
> +
> +#include "igt.h"
> +#include "igt_edid.h"
> +#include "igt_kms.h"
> +#include "igt_pipe_crc.h"
> +#include "igt_usb4_switch.h"
> +#include "igt_connector_helper.h"
> +#include "kms_joiner_helper.h"
> +
> +/*
> + * Extended timeout for switch operations.
> + * Port switching requires longer stabilization time than simple dock/undock
> + * due to hardware state transitions and MST topology rebuilds.
> + */
> +#define USB4_SWITCH_TIMEOUT_S 20
> +
> +/* Number of CRC samples for stability check (solid color FB should be stable) */
> +#define CRC_STABILITY_SAMPLES 3
> +
> +/* Maximum displays expected on a single USB4 switch port (MST hub) */
> +#define MAX_DISPLAYS_PER_PORT 4
> +
> +/* Number of reprobe cycles for MST topology stabilization after resume */
> +#define MST_STABILIZE_REPROBE_COUNT 10
> +
> +/* Inter-reprobe delay in microseconds (500 ms) */
> +#define MST_STABILIZE_DELAY_US 500000
> +
> +/*
> + * Iteration helpers for dynamic subtest generation.
> + * Skip ports (or pairs) that have no displays configured.
> + *
> + * for_each_usb4_port_pair iterates adjacent cyclic pairs (0->1, 1->2, ...,
> + * N-1->0).  For the 2-port Switch 3141 this covers the only possible pair.
> + * If the hardware grows beyond 2 ports, consider generating all distinct
> + * pairs instead.
> + */
> +#define for_each_usb4_port(sw, count, p, pcfg)				\
> +	for ((p) = 0,							\
> +	     (pcfg) = usb4switch_get_port_config((sw), 0);		\
> +	     (p) < (count) && (pcfg) && (pcfg)->display_count > 0;	\
> +	     (pcfg) = usb4switch_get_port_config((sw), ++(p)))
> +
> +#define for_each_usb4_port_pair(sw, count, p, pa, pb)			\
> +	for ((p) = 0,							\
> +	     (pa) = usb4switch_get_port_config((sw), 0),		\
> +	     (pb) = usb4switch_get_port_config((sw), 1 % (count));	\
> +	     (p) < (count) && (pa) && (pb) &&				\
> +	     (pa)->display_count > 0 && (pb)->display_count > 0;	\
> +	     ++(p),							\
> +	     (pa) = usb4switch_get_port_config((sw), (p)),		\
> +	     (pb) = usb4switch_get_port_config((sw), ((p) + 1) % (count)))
> +
> +typedef struct {
> +	int drm_fd;
> +	igt_display_t display;
> +	struct usb4switch *sw;
> +	struct udev_monitor *hotplug_mon;
> +	int max_dotclock;
> +	uint32_t master_pipes;
> +	uint32_t valid_pipes;
> +} data_t;
> +
> +/*
> + * Per-display modeset state, used by the composable display building blocks.
> + * Holds everything needed to arm, commit, collect CRC, and disarm one display.
> + */
> +struct display_ctx {
> +	uint32_t conn_id;
> +	igt_output_t *output;
> +	igt_plane_t *primary;
> +	struct igt_fb fb;
> +	drmModeModeInfo mode;
> +	bool valid;
> +};
> +
> +/*
> + * find_output_by_id - Find an igt_output_t by DRM connector ID.
> + */
> +static igt_output_t *find_output_by_id(igt_display_t *display,
> +				       uint32_t connector_id)
> +{
> +	int i;
> +
> +	for (i = 0; i < display->n_outputs; i++) {
> +		if (display->outputs[i].id == connector_id)
> +			return &display->outputs[i];
> +	}
> +
> +	return NULL;
> +}
> +
> +/*
> + * select_max_non_joiner_mode - Pick the largest mode that fits a single pipe.
> + *
> + * "Non-joiner" means hdisplay <= max_pipe_hdisplay AND clock <= max_dotclock.
> + * Among qualifying modes, pick by:
> + *   1. Highest pixel area (hdisplay * vdisplay)
> + *   2. Highest vrefresh (tie-break)
> + *   3. Highest clock (tie-break)
> + *
> + * If max_dotclock is 0 (debugfs unavailable), only hdisplay is checked.
> + *
> + * TODO: Remove this filter when joiner CRC collection is supported;
> + *       the pipe allocator already handles joiner pipe counts.
> + *
> + * Returns: Pointer to a function-static copy of the best mode, or NULL
> + *          if none found. Not reentrant — single-threaded callers only.
> + */
> +static drmModeModeInfo *select_max_non_joiner_mode(int drm_fd,
> +						   igt_output_t *output,
> +						   int max_dotclock)
> +{
> +	static drmModeModeInfo best;
> +	drmModeConnector *conn = output->config.connector;
> +	uint64_t best_area = 0;
> +	uint32_t best_vrefresh = 0;
> +	int best_clock = 0;
> +	bool found = false;
> +	int i;
> +
> +	if (!conn || conn->count_modes == 0)
> +		return NULL;
> +
> +	for (i = 0; i < conn->count_modes; i++) {
> +		drmModeModeInfo *m = &conn->modes[i];
> +		uint64_t area;
> +
> +		if (igt_bigjoiner_possible(drm_fd, m, max_dotclock))
> +			continue;
> +
> +		area = (uint64_t)m->hdisplay * m->vdisplay;
> +
> +		if (area > best_area ||
> +		    (area == best_area && m->vrefresh > best_vrefresh) ||
> +		    (area == best_area && m->vrefresh == best_vrefresh &&
> +		     m->clock > best_clock)) {
> +			best = *m;
> +			best_area = area;
> +			best_vrefresh = m->vrefresh;
> +			best_clock = m->clock;
> +			found = true;
> +		}
> +	}
> +
> +	return found ? &best : NULL;
> +}
> +
> +/*
> + * find_connector - Find a connector ID for the given display config.
> + * Prefers PATH property (stable for MST) with name as fallback.
> + */
> +static bool find_connector(int drm_fd,
> +			   const struct usb4switch_display *disp,
> +			   uint32_t *connector_id)
> +{
> +	if (!disp || !connector_id)
> +		return false;
> +
> +	if (disp->connector_path &&
> +	    igt_connector_find_by_path(drm_fd, disp->connector_path,
> +				       connector_id))
> +		return true;
> +
> +	if (disp->connector_name &&
> +	    igt_connector_find_by_name(drm_fd, disp->connector_name,
> +				       connector_id))
> +		return true;
> +
> +	return false;
> +}
> +
> +/*
> + * reprobe_connectors - Force reprobe of connectors and wait for MST topology.
> + * Critical after suspend/resume — without this MST connectors may take 90+ s.
> + *
> + * Timing rationale: MST hubs need ~3 s after reprobe to fully enumerate
> + * their downstream topology, based on empirical testing with USB4/TBT docks.
> + */
> +static void reprobe_connectors(int drm_fd)
> +{
> +	igt_connector_reprobe_all(drm_fd);
> +	igt_debug("reprobe: Connector reprobe completed\n");
> +}
> +
> +static bool verify_port_displays(data_t *data,
> +				 const struct usb4switch_port *port_cfg)
> +{
> +	int i;
> +
> +	for (i = 0; i < port_cfg->display_count; i++) {
> +		const struct usb4switch_display *disp = &port_cfg->displays[i];
> +		uint32_t conn_id;
> +		char name[32];
> +		char serial[64];
> +
> +		if (!find_connector(data->drm_fd, disp, &conn_id)) {
> +			igt_warn("Display %d not found for port %d\n",
> +				 i + 1, port_cfg->port_num);
> +			return false;
> +		}
> +
> +		if (disp->edid_serial) {
> +			if (!igt_connector_get_info(data->drm_fd, conn_id,
> +						    name, sizeof(name),
> +						    serial, sizeof(serial),
> +						    NULL, 0)) {
> +				igt_warn("Failed to get EDID serial for display %d\n",
> +					 i + 1);
> +				return false;
> +			}
> +
> +			if (strcmp(serial, disp->edid_serial) != 0) {
> +				igt_warn("EDID serial mismatch for display %d: expected '%s', got '%s'\n",
> +					 i + 1, disp->edid_serial, serial);
> +				return false;
> +			}
> +
> +			igt_debug("Display %d EDID serial verified: %s\n",
> +				  i + 1, serial);
> +		} else {
> +			igt_debug("Display %d: No EDID serial configured, "
> +				  "skipping verification\n", i + 1);
> +		}
> +	}
> +
> +	igt_info("Port %d: All %d displays verified\n",
> +		 port_cfg->port_num, port_cfg->display_count);
> +	return true;
> +}
> +
> +/*
> + * init_display_ctx - Resolve a usb4switch_display to an output and select mode.
> + *
> + * Finds the connector, resolves to igt_output_t, and selects the max
> + * non-joiner mode. Must be called before arm_display().
> + */
> +static void init_display_ctx(data_t *data, struct display_ctx *ctx,
> +			     const struct usb4switch_display *disp)
> +{
> +	drmModeModeInfo *mode;
> +
> +	memset(ctx, 0, sizeof(*ctx));
> +
> +	igt_assert_f(find_connector(data->drm_fd, disp, &ctx->conn_id),
> +		     "Display not found for pipeline test\n");
> +
> +	ctx->output = find_output_by_id(&data->display, ctx->conn_id);
> +	igt_assert_f(ctx->output,
> +		     "No output for connector %u\n", ctx->conn_id);
> +
> +	mode = select_max_non_joiner_mode(data->drm_fd, ctx->output,
> +					  data->max_dotclock);
> +	igt_skip_on_f(!mode,
> +		      "No non-joiner mode for connector %u\n", ctx->conn_id);
> +
> +	ctx->mode = *mode;
> +	ctx->valid = true;
> +}
> +
> +/*
> + * arm_display - Create FB, set primary plane, configure mode override.
> + *
> + * Pipe assignment must be done before this (by setup_port_displays).
> + * After arming, caller must commit with igt_display_commit2().
> + */
> +static void arm_display(data_t *data, struct display_ctx *ctx)
> +{
> +	igt_assert(ctx->valid);
> +
> +	igt_output_override_mode(ctx->output, &ctx->mode);
> +
> +	ctx->primary = igt_output_get_plane_type(ctx->output,
> +						 DRM_PLANE_TYPE_PRIMARY);
> +	igt_assert(ctx->primary);
> +
> +	igt_create_color_fb(data->drm_fd,
> +			    ctx->mode.hdisplay, ctx->mode.vdisplay,
> +			    DRM_FORMAT_XRGB8888, DRM_FORMAT_MOD_LINEAR,
> +			    0.0, 1.0, 0.0, /* green */
> +			    &ctx->fb);
> +	igt_plane_set_fb(ctx->primary, &ctx->fb);
> +
> +	igt_info("  Display %s: armed %dx%d@%d (clock %d)\n",
> +		 igt_output_name(ctx->output),
> +		 ctx->mode.hdisplay, ctx->mode.vdisplay,
> +		 ctx->mode.vrefresh, ctx->mode.clock);
> +}
> +
> +/*
> + * collect_display_crc - Collect CRC samples and verify stability.
> + *
> + * Collects CRC_STABILITY_SAMPLES, asserts they are identical (expected
> + * for a solid color FB), and returns the representative CRC in *out_crc.
> + * Display must be armed and committed before calling.
> + */
> +static void collect_display_crc(data_t *data, struct display_ctx *ctx,
> +				igt_crc_t *out_crc)
> +{
> +	igt_crtc_t *crtc = igt_output_get_driving_crtc(ctx->output);
> +	igt_pipe_crc_t *pipe_crc;
> +	igt_crc_t samples[CRC_STABILITY_SAMPLES];
> +	int i;
> +
> +	igt_assert(crtc);
> +
> +	pipe_crc = igt_crtc_crc_new(crtc, IGT_PIPE_CRC_SOURCE_AUTO);
> +	igt_assert(pipe_crc);
> +
> +	igt_pipe_crc_start(pipe_crc);
> +	for (i = 0; i < CRC_STABILITY_SAMPLES; i++)
> +		igt_pipe_crc_get_single(pipe_crc, &samples[i]);
> +	igt_pipe_crc_stop(pipe_crc);
> +
> +	/* Solid color FB: all samples must be identical */
> +	for (i = 1; i < CRC_STABILITY_SAMPLES; i++)
> +		igt_assert_crc_equal(&samples[0], &samples[i]);
> +
> +	*out_crc = samples[0];
> +
> +	igt_info("  Display %s: CRC stable (%d samples, pipe %s)\n",
> +		 igt_output_name(ctx->output), CRC_STABILITY_SAMPLES,
> +		 igt_crtc_name(crtc));
> +
> +	igt_pipe_crc_free(pipe_crc);
> +}
> +
> +/*
> + * disarm_display - Clear plane, output, and remove FB.
> + *
> + * After disarming all outputs, caller must commit to apply changes.
> + */
> +static void disarm_display(data_t *data, struct display_ctx *ctx)
> +{
> +	if (!ctx->valid)
> +		return;
> +
> +	if (ctx->primary)
> +		igt_plane_set_fb(ctx->primary, NULL);
> +
> +	igt_output_set_crtc(ctx->output, NULL);
> +	igt_output_override_mode(ctx->output, NULL);
> +
> +	if (ctx->fb.fb_id)
> +		igt_remove_fb(data->drm_fd, &ctx->fb);
> +
> +	ctx->primary = NULL;
> +	ctx->fb.fb_id = 0;
> +	ctx->valid = false;
> +}
> +
> +/*
> + * setup_port_displays - Init contexts, allocate pipes, arm all displays.
> + *
> + * Resolves all displays on a port, selects modes, allocates pipes using
> + * the joiner-aware pipe allocator, and arms all displays.
> + * Caller must commit with igt_display_commit2() after this returns.
> + *
> + * Returns: Number of displays set up.
> + */
> +static int setup_port_displays(data_t *data, struct display_ctx *ctxs,
> +			       const struct usb4switch_port *port_cfg)
> +{
> +	igt_output_t *outputs[MAX_DISPLAYS_PER_PORT];
> +	uint32_t used_pipes = 0;
> +	int i;
> +
> +	igt_assert(port_cfg->display_count <= MAX_DISPLAYS_PER_PORT);
> +
> +	for (i = 0; i < port_cfg->display_count; i++) {
> +		init_display_ctx(data, &ctxs[i], &port_cfg->displays[i]);
> +		outputs[i] = ctxs[i].output;
> +	}
> +
> +	/* Joiner-aware pipe allocation */
> +	igt_assert_f(igt_assign_pipes_for_outputs(data->drm_fd, outputs,
> +						  port_cfg->display_count,
> +						  data->display.n_crtcs,
> +						  &used_pipes,
> +						  data->master_pipes,
> +						  data->valid_pipes),
> +		     "Failed to allocate pipes for port %d displays\n",
> +		     port_cfg->port_num);
> +
> +	for (i = 0; i < port_cfg->display_count; i++)
> +		arm_display(data, &ctxs[i]);
> +
> +	return port_cfg->display_count;
> +}
> +
> +static void teardown_port_displays(data_t *data, struct display_ctx *ctxs,
> +				   int count)
> +{
> +	int i;
> +
> +	for (i = 0; i < count; i++)
> +		disarm_display(data, &ctxs[i]);
> +}
> +
> +/*
> + * verify_port_display_pipeline - Modeset all port displays and verify CRC.
> + *
> + * Used in non-suspend paths to confirm the display pipeline is functioning.
> + * Arms all displays, commits, collects stable CRCs, then tears down.
> + */
> +static void verify_port_display_pipeline(data_t *data,
> +					 const struct usb4switch_port *port_cfg)
> +{
> +	struct display_ctx ctxs[MAX_DISPLAYS_PER_PORT];
> +	igt_crc_t crc;
> +	int count, i;
> +
> +	count = setup_port_displays(data, ctxs, port_cfg);
> +	igt_display_commit2(&data->display, COMMIT_ATOMIC);
> +
> +	for (i = 0; i < count; i++)
> +		collect_display_crc(data, &ctxs[i], &crc);
> +
> +	teardown_port_displays(data, ctxs, count);
> +
> +	igt_info("Port %d: Pipeline verification passed for %d displays\n",
> +		 port_cfg->port_num, count);
> +}
> +
> +/*
> + * get_port_reference_crcs - Modeset and collect reference CRCs before suspend.
> + *
> + * Arms all displays, commits, collects a baseline CRC per display into
> + * ref_crcs[], then tears down. The reference CRCs are compared with
> + * post-resume CRCs to detect display corruption.
> + */
> +static void get_port_reference_crcs(data_t *data,
> +				    const struct usb4switch_port *port_cfg,
> +				    igt_crc_t *ref_crcs)
> +{
> +	struct display_ctx ctxs[MAX_DISPLAYS_PER_PORT];
> +	int count, i;
> +
> +	count = setup_port_displays(data, ctxs, port_cfg);
> +	igt_display_commit2(&data->display, COMMIT_ATOMIC);
> +
> +	for (i = 0; i < count; i++)
> +		collect_display_crc(data, &ctxs[i], &ref_crcs[i]);
> +
> +	teardown_port_displays(data, ctxs, count);
> +
> +	igt_info("Port %d: Collected %d reference CRCs for suspend comparison\n",
> +		 port_cfg->port_num, count);
> +}
> +
> +/*
> + * verify_port_crcs_after_resume - Compare post-resume CRCs with pre-suspend.
> + *
> + * Arms all displays with the same mode/FB as before suspend, commits,
> + * collects new CRCs, and asserts each matches the corresponding reference.
> + * A mismatch indicates the display is showing garbage after resume.
> + */
> +static void verify_port_crcs_after_resume(data_t *data,
> +					  const struct usb4switch_port *port_cfg,
> +					  const igt_crc_t *ref_crcs)
> +{
> +	struct display_ctx ctxs[MAX_DISPLAYS_PER_PORT];
> +	igt_crc_t resume_crc;
> +	int count, i;
> +
> +	count = setup_port_displays(data, ctxs, port_cfg);
> +	igt_display_commit2(&data->display, COMMIT_ATOMIC);
> +
> +	for (i = 0; i < count; i++) {
> +		collect_display_crc(data, &ctxs[i], &resume_crc);
> +		igt_assert_crc_equal(&ref_crcs[i], &resume_crc);
> +		igt_info("  Display %s: CRC matches pre-suspend reference\n",
> +			 igt_output_name(ctxs[i].output));
> +	}
> +
> +	teardown_port_displays(data, ctxs, count);
> +
> +	igt_info("Port %d: All %d CRCs match pre-suspend reference\n",
> +		 port_cfg->port_num, count);
> +}
> +
> +/*
> + * refresh_display - Reinitialize display structure to pick up new connectors.
> + * After hotplug events (dock/undock), new MST connectors may be created.
> + *
> + * WARNING: Any previously cached igt_output_t pointers become invalid
> + * after this call.  Callers must re-resolve outputs via find_output_by_id()
> + * or init_display_ctx() before using them.
> + */
> +static void refresh_display(data_t *data)
> +{
> +	igt_display_fini(&data->display);
> +	igt_display_require(&data->display, data->drm_fd);
> +}
> +
> +/*
> + * wait_for_displays - Wait for all displays on a port to connect.
> + */
> +static bool wait_for_displays(data_t *data,
> +			      const struct usb4switch_port *port,
> +			      int timeout_s)
> +{
> +	int elapsed = 0;
> +	int found = 0;
> +	int i;
> +
> +	if (!port)
> +		return false;
> +
> +	while (elapsed < timeout_s) {
> +		reprobe_connectors(data->drm_fd);
> +
> +		found = 0;
> +		for (i = 0; i < port->display_count; i++) {
> +			uint32_t id;
> +
> +			if (find_connector(data->drm_fd,
> +					   &port->displays[i], &id))
> +				found++;
> +		}
> +
> +		if (found == port->display_count) {
> +			igt_debug("All %d displays found for port %d\n",
> +				  port->display_count, port->port_num);
> +			/*
> +			 * Reprobe cycles above may have created new MST
> +			 * connectors.  Rebuild igt_display_t so callers
> +			 * see up-to-date connector IDs and outputs.
> +			 */
> +			refresh_display(data);
> +			return true;
> +		}
> +
> +		sleep(1);
> +		elapsed++;
> +	}
> +
> +	igt_warn("Timeout waiting for displays (found %d/%d)\n",
> +		 found, port->display_count);
> +	return false;
> +}
> +
> +static void wait_for_hotplug(data_t *data, int timeout_s)
> +{
> +	bool detected;
> +
> +	detected = igt_hotplug_detected(data->hotplug_mon, timeout_s);
> +
> +	if (detected)
> +		igt_debug("Hotplug detected\n");
> +	else
> +		igt_warn("Hotplug uevent not detected within %ds\n",
> +			 timeout_s);
> +
> +	reprobe_connectors(data->drm_fd);
> +	refresh_display(data);
> +}
> +
> +/*
> + * mst_stabilize - Extended MST topology stabilization after resume.
> + * MST hubs need additional time and reprobe cycles to rebuild their
> + * topology after suspend/resume. Ten iterations with 500 ms spacing
> + * gives the hub firmware enough time to re-enumerate all downstream
> + * ports, based on empirical testing with USB4/TBT docks.
> + */
> +static void mst_stabilize(data_t *data)
> +{
> +	int i;
> +
> +	for (i = 0; i < MST_STABILIZE_REPROBE_COUNT; i++) {
> +		reprobe_connectors(data->drm_fd);
> +		usleep(MST_STABILIZE_DELAY_US);
> +	}
> +}
> +
> +/*
> + * port_dynamic_name - Format dynamic subtest name for a port.
> + * Uses port name if configured, otherwise falls back to "port-N".
> + *
> + * IGT requires subtest names to contain only [a-zA-Z0-9_-] and to be
> + * lower-case.  Any upper-case letter is lowered, any other invalid
> + * character (e.g. spaces) is replaced with '-'.
> + */
> +static const char *port_dynamic_name(const struct usb4switch_port *port,
> +				     char *buf, size_t len)
> +{
> +	size_t i;
> +
> +	if (port->name) {
> +		snprintf(buf, len, "%s", port->name);
> +		for (i = 0; buf[i]; i++) {
> +			buf[i] = tolower((unsigned char)buf[i]);
> +			if (!isalnum((unsigned char)buf[i]) &&
> +			    buf[i] != '-' && buf[i] != '_')
> +				buf[i] = '-';
> +		}
> +	} else {
> +		snprintf(buf, len, "port-%d", port->port_num);
> +	}
> +	return buf;
> +}
> +
> +/*
> + * pair_dynamic_name - Format dynamic subtest name for a port pair.
> + * Combines both port names with "-to-" separator.
> + */
> +static const char *pair_dynamic_name(const struct usb4switch_port *a,
> +				     const struct usb4switch_port *b,
> +				     char *buf, size_t len)
> +{
> +	char na[32], nb[32];
> +
> +	port_dynamic_name(a, na, sizeof(na));
> +	port_dynamic_name(b, nb, sizeof(nb));
> +	snprintf(buf, len, "%s-to-%s", na, nb);
> +	return buf;
> +}
> +
> +static void test_dock_undock(data_t *data,
> +			     const struct usb4switch_port *port_cfg)
> +{
> +	int iterations = usb4switch_get_iterations(data->sw);
> +	int timeout = usb4switch_get_hotplug_timeout(data->sw);
> +	int i;
> +
> +	igt_info("Testing port %d (%s) with %d displays, %d iterations\n",
> +		 port_cfg->port_num,
> +		 port_cfg->name ? port_cfg->name : "unnamed",
> +		 port_cfg->display_count, iterations);
> +
> +	for (i = 0; i < iterations; i++) {
> +		igt_info("Iteration %d/%d\n", i + 1, iterations);
> +
> +		/* Dock */
> +		igt_info("  Docking port %d...\n",
> +			 port_cfg->port_num);
> +		igt_flush_uevents(data->hotplug_mon);
> +		igt_assert(usb4switch_port_switch(data->sw,
> +						  port_cfg->port_num));
> +		wait_for_hotplug(data, timeout);
> +
> +		igt_assert_f(wait_for_displays(data, port_cfg, timeout),
> +			     "Displays did not enumerate on port %d\n",
> +			     port_cfg->port_num);
> +
> +		igt_assert_f(verify_port_displays(data, port_cfg),
> +			     "Display verification failed on port %d\n",
> +			     port_cfg->port_num);
> +
> +		verify_port_display_pipeline(data, port_cfg);
> +
> +		/* Undock */
> +		igt_info("  Undocking...\n");
> +		igt_flush_uevents(data->hotplug_mon);
> +		igt_assert(usb4switch_port_disable_and_wait(data->sw));
> +		wait_for_hotplug(data, timeout);
> +	}
> +}
> +
> +static void test_dock_undock_sr(data_t *data,
> +				const struct usb4switch_port *port_cfg)
> +{
> +	igt_crc_t ref_crcs[MAX_DISPLAYS_PER_PORT];
> +	int iterations = usb4switch_get_iterations(data->sw);
> +	int timeout = usb4switch_get_hotplug_timeout(data->sw);
> +	int i;
> +
> +	igt_info("Testing port %d (%s) dock/undock with S/R, %d iterations\n",
> +		 port_cfg->port_num,
> +		 port_cfg->name ? port_cfg->name : "unnamed",
> +		 iterations);
> +
> +	for (i = 0; i < iterations; i++) {
> +		igt_info("Iteration %d/%d\n", i + 1, iterations);
> +
> +		/* Dock */
> +		igt_info("  Docking port %d...\n",
> +			 port_cfg->port_num);
> +		igt_flush_uevents(data->hotplug_mon);
> +		igt_assert(usb4switch_port_switch(data->sw,
> +						  port_cfg->port_num));
> +		wait_for_hotplug(data, timeout);
> +
> +		igt_assert_f(wait_for_displays(data, port_cfg,
> +					       timeout),
> +			     "Displays did not enumerate\n");
> +
> +		igt_info("  Verifying displays before suspend...\n");
> +		igt_assert_f(verify_port_displays(data, port_cfg),
> +			     "Display verification failed before suspend\n");
> +
> +		/* Collect reference CRCs before suspend */
> +		get_port_reference_crcs(data, port_cfg, ref_crcs);
> +
> +		/* Suspend/Resume while docked */
> +		igt_info("  Suspending while docked...\n");
> +		igt_system_suspend_autoresume(SUSPEND_STATE_MEM,
> +					      SUSPEND_TEST_NONE);
> +		igt_info("  Resumed\n");
> +
> +		mst_stabilize(data);
> +
> +		igt_assert_f(wait_for_displays(data, port_cfg,
> +					       timeout),
> +			     "Displays did not enumerate after resume\n");
> +		igt_info("  Verifying displays after resume...\n");
> +		igt_assert_f(verify_port_displays(data, port_cfg),
> +			     "Display verification failed after resume\n");
> +
> +		/* Compare post-resume CRCs with pre-suspend reference */
> +		verify_port_crcs_after_resume(data, port_cfg, ref_crcs);
> +
> +		/* Undock */
> +		igt_info("  Undocking...\n");
> +		igt_flush_uevents(data->hotplug_mon);
> +		igt_assert(usb4switch_port_disable_and_wait(data->sw));
> +		wait_for_hotplug(data, timeout);
> +	}
> +}
> +
> +static void test_dock_during_suspend(data_t *data,
> +				     const struct usb4switch_port *port_cfg)
> +{
> +	int iterations = usb4switch_get_iterations(data->sw);
> +	int timeout = usb4switch_get_hotplug_timeout(data->sw);
> +	int i;
> +
> +	igt_info("Testing port %d (%s) dock-during-suspend, %d iterations\n",
> +		 port_cfg->port_num,
> +		 port_cfg->name ? port_cfg->name : "unnamed",
> +		 iterations);
> +
> +	for (i = 0; i < iterations; i++) {
> +		igt_info("Iteration %d/%d\n", i + 1, iterations);
> +
> +		/*
> +		 * Schedule dock during suspend using hardware delay.
> +		 * Port change executes at T+7s while system is
> +		 * suspended (15s suspend cycle).
> +		 */
> +		igt_info("  Scheduling dock during suspend (T+7s)...\n");
> +		igt_assert(usb4switch_port_enable_delayed(data->sw,
> +							  port_cfg->port_num,
> +							  7));
> +
> +		igt_info("  Suspending (15s, dock at T+7s)...\n");
> +		igt_system_suspend_autoresume(SUSPEND_STATE_MEM,
> +					      SUSPEND_TEST_NONE);
> +		igt_info("  Resumed\n");
> +
> +		igt_info("  Reprobing connectors for MST discovery...\n");
> +		mst_stabilize(data);
> +
> +		igt_assert_f(wait_for_displays(data, port_cfg,
> +					       timeout),
> +			     "Displays did not enumerate after dock-during-suspend\n");
> +
> +		igt_info("  Verifying displays after dock-during-suspend...\n");
> +		igt_assert_f(verify_port_displays(data, port_cfg),
> +			     "Display verification failed after dock-during-suspend\n");
> +
> +		verify_port_display_pipeline(data, port_cfg);
> +
> +		/* Undock to restore disconnected state for next iteration */
> +		igt_info("  Undocking...\n");
> +		igt_flush_uevents(data->hotplug_mon);
> +		igt_assert(usb4switch_port_disable_and_wait(data->sw));
> +		wait_for_hotplug(data, timeout);
> +	}
> +}
> +
> +static void test_undock_during_suspend(data_t *data,
> +				       const struct usb4switch_port *port_cfg)
> +{
> +	int iterations = usb4switch_get_iterations(data->sw);
> +	int timeout = usb4switch_get_hotplug_timeout(data->sw);
> +	int i;
> +
> +	igt_info("Testing port %d (%s) undock-during-suspend, %d iterations\n",
> +		 port_cfg->port_num,
> +		 port_cfg->name ? port_cfg->name : "unnamed",
> +		 iterations);
> +
> +	for (i = 0; i < iterations; i++) {
> +		int j, found;
> +
> +		igt_info("Iteration %d/%d\n", i + 1, iterations);
> +
> +		/* Dock first */
> +		igt_info("  Docking port %d...\n", port_cfg->port_num);
> +		igt_flush_uevents(data->hotplug_mon);
> +		igt_assert(usb4switch_port_switch(data->sw,
> +						  port_cfg->port_num));
> +		wait_for_hotplug(data, timeout);
> +
> +		igt_assert_f(wait_for_displays(data, port_cfg, timeout),
> +			     "Displays did not enumerate on port %d\n",
> +			     port_cfg->port_num);
> +		igt_assert_f(verify_port_displays(data, port_cfg),
> +			     "Display verification failed on port %d\n",
> +			     port_cfg->port_num);
> +
> +		verify_port_display_pipeline(data, port_cfg);
> +
> +		/*
> +		 * Schedule undock during suspend using hardware delay.
> +		 * Port disable executes at T+7s while system is
> +		 * suspended (15s suspend cycle).
> +		 */
> +		igt_info("  Scheduling undock during suspend (T+7s)...\n");
> +		igt_assert(usb4switch_port_disable_delayed(data->sw, 7));
> +
> +		igt_info("  Suspending (15s, undock at T+7s)...\n");
> +		igt_system_suspend_autoresume(SUSPEND_STATE_MEM,
> +					      SUSPEND_TEST_NONE);
> +		igt_info("  Resumed\n");
> +
> +		mst_stabilize(data);
> +
> +		/* Verify displays are gone after undock-during-suspend */
> +		reprobe_connectors(data->drm_fd);
> +		found = 0;
> +		for (j = 0; j < port_cfg->display_count; j++) {
> +			uint32_t id;
> +
> +			if (find_connector(data->drm_fd,
> +					   &port_cfg->displays[j], &id))
> +				found++;
> +		}
> +		igt_assert_f(found == 0,
> +			     "Port %d: %d/%d displays still present after undock-during-suspend\n",
> +			     port_cfg->port_num, found,
> +			     port_cfg->display_count);
> +
> +		igt_info("Port %d: All displays removed after undock-during-suspend\n",
> +			 port_cfg->port_num);
> +	}
> +}
> +
> +static void test_switch(data_t *data,
> +			const struct usb4switch_port *port_a,
> +			const struct usb4switch_port *port_b)
> +{
> +	int iterations = usb4switch_get_iterations(data->sw);
> +	int timeout = USB4_SWITCH_TIMEOUT_S;
> +	int i;
> +
> +	igt_info("Testing switch port %d -> port %d, %d iterations\n",
> +		 port_a->port_num, port_b->port_num, iterations);
> +
> +	for (i = 0; i < iterations; i++) {
> +		igt_info("Iteration %d/%d\n", i + 1, iterations);
> +
> +		/* Enable port A */
> +		igt_info("  Enabling port %d...\n",
> +			 port_a->port_num);
> +		igt_flush_uevents(data->hotplug_mon);
> +		igt_assert(usb4switch_port_switch(data->sw,
> +						  port_a->port_num));
> +		wait_for_hotplug(data, timeout);
> +
> +		igt_assert_f(wait_for_displays(data, port_a,
> +					       timeout),
> +			     "Displays did not enumerate on port %d\n",
> +			     port_a->port_num);
> +		igt_assert_f(verify_port_displays(data, port_a),
> +			     "Display verification failed on port %d\n",
> +			     port_a->port_num);
> +		verify_port_display_pipeline(data, port_a);
> +
> +		/* Switch to port B */
> +		igt_info("  Switching to port %d...\n",
> +			 port_b->port_num);
> +		igt_flush_uevents(data->hotplug_mon);
> +		igt_assert(usb4switch_port_switch(data->sw,
> +						  port_b->port_num));
> +		wait_for_hotplug(data, timeout);
> +
> +		igt_assert_f(wait_for_displays(data, port_b,
> +					       timeout),
> +			     "Displays did not enumerate after switch to port %d\n",
> +			     port_b->port_num);
> +		igt_assert_f(verify_port_displays(data, port_b),
> +			     "Display verification failed after switch to port %d\n",
> +			     port_b->port_num);
> +
> +		verify_port_display_pipeline(data, port_b);
> +	}
> +
> +	igt_flush_uevents(data->hotplug_mon);
> +	igt_assert(usb4switch_port_disable_and_wait(data->sw));
> +	wait_for_hotplug(data, timeout);
> +}
> +
> +static void test_switch_during_suspend(data_t *data,
> +				       const struct usb4switch_port *port_cfg_a,
> +				       const struct usb4switch_port *port_cfg_b)
> +{
> +	int iterations = usb4switch_get_iterations(data->sw);
> +	int timeout = USB4_SWITCH_TIMEOUT_S;

No use of this having as a variable, why not use the macro directly?
Same for all above!


> +	int i;
> +
> +	igt_info("Testing switch during suspend port %d <-> port %d, %d iterations\n",
> +		 port_cfg_a->port_num, port_cfg_b->port_num, iterations);
> +
> +	for (i = 0; i < iterations; i++) {
> +		igt_info("Iteration %d/%d\n", i + 1, iterations);
> +
> +		/* Start on port A */
> +		igt_info("  Enabling port %d...\n", port_cfg_a->port_num);
> +		igt_flush_uevents(data->hotplug_mon);
> +		igt_assert(usb4switch_port_switch(data->sw,
> +						  port_cfg_a->port_num));
> +		wait_for_hotplug(data, timeout);
> +
> +		igt_assert_f(wait_for_displays(data, port_cfg_a, timeout),
> +			     "Displays did not enumerate on port %d\n",
> +			     port_cfg_a->port_num);
> +		igt_assert_f(verify_port_displays(data, port_cfg_a),
> +			     "Display verification failed on port %d\n",
> +			     port_cfg_a->port_num);
> +
> +		verify_port_display_pipeline(data, port_cfg_a);
> +
> +		/* Schedule switch to B during suspend */
> +		igt_info("  Scheduling switch to port %d during suspend (T+7s)...\n",
> +			 port_cfg_b->port_num);
> +		igt_assert(usb4switch_port_disable_and_wait(data->sw));
> +		igt_assert(usb4switch_port_enable_delayed(data->sw,
> +							  port_cfg_b->port_num,
> +							  7));
> +
> +		igt_info("  Suspending (15s, switch at T+7s)...\n");
> +		igt_system_suspend_autoresume(SUSPEND_STATE_MEM,
> +					      SUSPEND_TEST_NONE);
> +		igt_info("  Resumed\n");
> +
> +		igt_info("  Reprobing connectors for MST discovery...\n");
> +		mst_stabilize(data);
> +
> +		igt_assert_f(wait_for_displays(data, port_cfg_b, timeout),
> +			     "Displays did not enumerate on port %d after switch-during-suspend\n",
> +			     port_cfg_b->port_num);
> +		igt_info("  Verifying displays on port %d...\n",
> +			 port_cfg_b->port_num);
> +		igt_assert_f(verify_port_displays(data, port_cfg_b),
> +			     "Display verification failed on port %d after switch-during-suspend\n",
> +			     port_cfg_b->port_num);
> +
> +		verify_port_display_pipeline(data, port_cfg_b);
> +
> +		/* Schedule switch back to A during suspend */
> +		igt_info("  Scheduling switch to port %d during suspend (T+7s)...\n",
> +			 port_cfg_a->port_num);
> +		igt_assert(usb4switch_port_disable_and_wait(data->sw));
> +		igt_assert(usb4switch_port_enable_delayed(data->sw,
> +							  port_cfg_a->port_num,
> +							  7));
> +
> +		igt_info("  Suspending (15s, switch at T+7s)...\n");
> +		igt_system_suspend_autoresume(SUSPEND_STATE_MEM,
> +					      SUSPEND_TEST_NONE);
> +		igt_info("  Resumed\n");
> +
> +		mst_stabilize(data);
> +
> +		igt_assert_f(wait_for_displays(data, port_cfg_a, timeout),
> +			     "Displays did not enumerate on port %d after switch-during-suspend\n",
> +			     port_cfg_a->port_num);
> +		igt_info("  Verifying displays on port %d...\n",
> +			 port_cfg_a->port_num);
> +		igt_assert_f(verify_port_displays(data, port_cfg_a),
> +			     "Display verification failed on port %d after switch-during-suspend\n",
> +			     port_cfg_a->port_num);
> +
> +		verify_port_display_pipeline(data, port_cfg_a);
> +	}
> +
> +	igt_flush_uevents(data->hotplug_mon);
> +	igt_assert(usb4switch_port_disable_and_wait(data->sw));
> +	wait_for_hotplug(data, timeout);
> +}
> +
> +static void test_switch_sr(data_t *data,
> +			   const struct usb4switch_port *port_cfg_a,
> +			   const struct usb4switch_port *port_cfg_b)
> +{
> +	igt_crc_t ref_crcs[MAX_DISPLAYS_PER_PORT];
> +	int iterations = usb4switch_get_iterations(data->sw);
> +	int timeout = USB4_SWITCH_TIMEOUT_S;
Why not have it as a const or use the macro directly?
> +	int i;
> +
> +	igt_info("Testing switch with S/R port %d <-> port %d, %d iterations\n",
> +		 port_cfg_a->port_num, port_cfg_b->port_num, iterations);
> +
> +	for (i = 0; i < iterations; i++) {
> +		igt_info("Iteration %d/%d\n", i + 1, iterations);
> +
> +		/* Enable port A */
> +		igt_info("  Enabling port %d...\n", port_cfg_a->port_num);
> +		igt_flush_uevents(data->hotplug_mon);
> +		igt_assert(usb4switch_port_switch(data->sw,
> +						  port_cfg_a->port_num));
> +		wait_for_hotplug(data, timeout);
> replace timeout with the macro/magic value directly.
> +
> +		igt_assert_f(wait_for_displays(data, port_cfg_a, timeout),
> +			     "Displays did not enumerate on port %d\n",
> +			     port_cfg_a->port_num);
> +		igt_assert_f(verify_port_displays(data, port_cfg_a),
> +			     "Display verification failed on port %d\n",
> +			     port_cfg_a->port_num);
> +
> +		/* Collect reference CRCs on port A before suspend */
> +		get_port_reference_crcs(data, port_cfg_a, ref_crcs);
> +
> +		/* Suspend/Resume */
> +		igt_info("  Suspending with port %d active...\n",
> +			 port_cfg_a->port_num);
> +		igt_system_suspend_autoresume(SUSPEND_STATE_MEM,
> +					      SUSPEND_TEST_NONE);
> +		igt_info("  Resumed\n");
> +
> +		mst_stabilize(data);
> +
> +		igt_assert_f(wait_for_displays(data, port_cfg_a, timeout),
> +			     "Displays did not enumerate on port %d after resume\n",
> +			     port_cfg_a->port_num);
> +		igt_assert_f(verify_port_displays(data, port_cfg_a),
> +			     "Display verification failed on port %d after resume\n",
> +			     port_cfg_a->port_num);
> +
> +		/* Compare post-resume CRCs with pre-suspend reference */
> +		verify_port_crcs_after_resume(data, port_cfg_a, ref_crcs);
> +
> +		/* Switch to port B */
> +		igt_info("  Switching to port %d...\n",
> +			 port_cfg_b->port_num);
> +		igt_flush_uevents(data->hotplug_mon);
> +		igt_assert(usb4switch_port_switch(data->sw,
> +						  port_cfg_b->port_num));
> +		wait_for_hotplug(data, timeout);
> +
> +		igt_assert_f(wait_for_displays(data, port_cfg_b, timeout),
> +			     "Displays did not enumerate on port %d\n",
> +			     port_cfg_b->port_num);
> +		igt_assert_f(verify_port_displays(data, port_cfg_b),
> +			     "Display verification failed on port %d\n",
> +			     port_cfg_b->port_num);
> +
> +		/* Collect reference CRCs on port B before suspend */
> +		get_port_reference_crcs(data, port_cfg_b, ref_crcs);
> +
> +		/* Suspend/Resume with port B */
> +		igt_info("  Suspending with port %d active...\n",
> +			 port_cfg_b->port_num);
> +		igt_system_suspend_autoresume(SUSPEND_STATE_MEM,
> +					      SUSPEND_TEST_NONE);
> +		igt_info("  Resumed\n");
> +
> +		mst_stabilize(data);
> +
> +		igt_assert_f(wait_for_displays(data, port_cfg_b, timeout),
> +			     "Displays did not enumerate on port %d after resume\n",
> +			     port_cfg_b->port_num);
> +		igt_assert_f(verify_port_displays(data, port_cfg_b),
> +			     "Display verification failed on port %d after resume\n",
> +			     port_cfg_b->port_num);
> +
> +		/* Compare post-resume CRCs with pre-suspend reference */
> +		verify_port_crcs_after_resume(data, port_cfg_b, ref_crcs);
> +	}
> +
> +	igt_flush_uevents(data->hotplug_mon);
> +	igt_assert(usb4switch_port_disable_and_wait(data->sw));
> +	wait_for_hotplug(data, timeout);
> +}
> +
> +int igt_main()
> +{
> +	const struct usb4switch_port *pcfg, *pa, *pb;
> +	data_t data = {};
> +	igt_crtc_t *crtc;
> +	char name[80];
> +	int port_count;
> +	int p;
> +
> +	igt_fixture() {
> +		data.drm_fd = drm_open_driver_master(DRIVER_INTEL | DRIVER_XE);
> +		igt_require(data.drm_fd >= 0);
> +
> +		kmstest_set_vt_graphics_mode();
> +		igt_display_require(&data.display, data.drm_fd);
> +
> +		data.sw = usb4switch_init(data.drm_fd);
> +		igt_require_f(data.sw, "USB4 Switch 3141 not available\n");
> +
> +		igt_require_pipe_crc(data.drm_fd);
> +		data.max_dotclock = igt_get_max_dotclock(data.drm_fd);
> +
> +		data.hotplug_mon = igt_watch_uevents();
> +		igt_require(data.hotplug_mon);
> +
> +		/* Compute pipe masks for joiner-aware allocation */
> +		igt_set_all_master_pipes_for_platform(&data.display,
> +						      &data.master_pipes);
> +		data.valid_pipes = 0;
> +		for_each_crtc(&data.display, crtc)
> +			data.valid_pipes |= BIT(crtc->pipe);
> +
> +		/* Ensure all ports are disconnected */
> +		igt_assert(usb4switch_port_disable_and_wait(data.sw));
> +	}
> +
> +	igt_describe("Dock/undock cycles with display verification");
> +	igt_subtest_with_dynamic("dock-undock") {
> +		port_count = usb4switch_get_port_count(data.sw);
> +
> +		for_each_usb4_port(data.sw, port_count, p, pcfg) {
> +			port_dynamic_name(pcfg, name, sizeof(name));
> +			igt_dynamic(name)
> +				test_dock_undock(&data, pcfg);
> +		}
> +	}
> +
> +	igt_describe("Dock/undock with suspend/resume stability");
> +	igt_subtest_with_dynamic("dock-undock-sr") {
> +		port_count = usb4switch_get_port_count(data.sw);
> +
> +		for_each_usb4_port(data.sw, port_count, p, pcfg) {
> +			port_dynamic_name(pcfg, name, sizeof(name));
> +			igt_dynamic(name)
> +				test_dock_undock_sr(&data, pcfg);
> +		}
> +	}
> +
> +	igt_describe("Dock during suspend with display verification");
> +	igt_subtest_with_dynamic("dock-during-suspend") {
> +		port_count = usb4switch_get_port_count(data.sw);
> +
> +		for_each_usb4_port(data.sw, port_count, p, pcfg) {
> +			port_dynamic_name(pcfg, name, sizeof(name));
> +			igt_dynamic(name)
> +				test_dock_during_suspend(&data, pcfg);
> +		}
> +	}
> +
> +	igt_describe("Undock during suspend with display verification");
> +	igt_subtest_with_dynamic("undock-during-suspend") {
> +		port_count = usb4switch_get_port_count(data.sw);
> +
> +		for_each_usb4_port(data.sw, port_count, p, pcfg) {
> +			port_dynamic_name(pcfg, name, sizeof(name));
> +			igt_dynamic(name)
> +				test_undock_during_suspend(&data, pcfg);
> +		}
> +	}
> +
> +	igt_describe("Port switching with display verification");
> +	igt_subtest_with_dynamic("switch") {
> +		port_count = usb4switch_get_port_count(data.sw);
> +		igt_require(port_count > 1);
> +
> +		for_each_usb4_port_pair(data.sw, port_count, p, pa, pb) {
> +			pair_dynamic_name(pa, pb, name, sizeof(name));
> +			igt_dynamic(name)
> +				test_switch(&data, pa, pb);
> +		}
> +	}
> +
> +	igt_describe("Port switching with suspend/resume stability");
> +	igt_subtest_with_dynamic("switch-sr") {
> +		port_count = usb4switch_get_port_count(data.sw);
> +		igt_require(port_count > 1);
> +
> +		for_each_usb4_port_pair(data.sw, port_count, p, pa, pb) {
> +			pair_dynamic_name(pa, pb, name, sizeof(name));
> +			igt_dynamic(name)
> +				test_switch_sr(&data, pa, pb);
> +		}
> +	}
> +
> +	igt_describe("Port switching during suspend via hardware delay");
> +	igt_subtest_with_dynamic("switch-during-suspend") {
> +		port_count = usb4switch_get_port_count(data.sw);
> +		igt_require(port_count > 1);
> +
> +		for_each_usb4_port_pair(data.sw, port_count, p, pa, pb) {
> +			pair_dynamic_name(pa, pb, name, sizeof(name));
> +			igt_dynamic(name)
> +				test_switch_during_suspend(&data, pa, pb);
> +		}
> +	}
> +
> +	igt_fixture() {
> +		if (!usb4switch_port_disable_and_wait(data.sw))
> +			igt_warn("Failed to disable ports during cleanup\n");
> +		igt_cleanup_uevents(data.hotplug_mon);
> +		usb4switch_deinit(data.sw);
> +		igt_display_fini(&data.display);
> +		drm_close_driver(data.drm_fd);
> +	}
> +}
> diff --git a/tests/meson.build b/tests/meson.build
> index 7f356de9b..563c65240 100644
> --- a/tests/meson.build
> +++ b/tests/meson.build
> @@ -276,6 +276,7 @@ intel_kms_progs = [
>   	'kms_psr_stress_test',
>   	'kms_pwrite_crc',
>   	'kms_sharpness_filter',
> +	'kms_usb4_switch',
>   ]
>   
>   intel_xe_progs = [
> @@ -400,6 +401,7 @@ extra_sources = {
>   	'kms_dsc': [ join_paths ('intel', 'kms_dsc_helper.c') ],
>   	'kms_joiner': [ join_paths ('intel', 'kms_joiner_helper.c') ],
>   	'kms_psr2_sf':  [ join_paths ('intel', 'kms_dsc_helper.c') ],
> +	'kms_usb4_switch': [ join_paths ('intel', 'kms_joiner_helper.c') ],
>   }
>   
>   # Extra dependencies used on core and Intel drivers

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

* Re: [i-g-t,5/6] tests/kms_feature_discovery: add basic usb4 switch discovery
  2026-02-25 21:28 ` [PATCH i-g-t 5/6] tests/kms_feature_discovery: add basic usb4 switch discovery Kunal Joshi
@ 2026-03-09 10:05   ` Murthy, Arun R
  0 siblings, 0 replies; 25+ messages in thread
From: Murthy, Arun R @ 2026-03-09 10:05 UTC (permalink / raw)
  To: Kunal Joshi, igt-dev


On 26-02-2026 02:58, Kunal Joshi wrote:
> Add a 'usb4-switch' subtest that verifies the Microsoft USB4 Switch
> 3141 is reachable. The test initializes the switch library and queries
> the active port to confirm communication works.
>
> This enables CI to detect when USB4 switch hardware is available
> before running the full kms_usb4_switch test suite.
>
> Signed-off-by: Kunal Joshi <kunal1.joshi@intel.com>
Looks good to me

Reviewed-by: Arun R Murthy <arun.r.murthy@intel.com>

Thanks and Regards,
Arun R Murthy
--------------------

> ---
>   tests/kms_feature_discovery.c | 23 +++++++++++++++++++++++
>   1 file changed, 23 insertions(+)
>
> diff --git a/tests/kms_feature_discovery.c b/tests/kms_feature_discovery.c
> index f0216a4ce..b05055186 100644
> --- a/tests/kms_feature_discovery.c
> +++ b/tests/kms_feature_discovery.c
> @@ -40,6 +40,7 @@
>   #include "igt_psr.h"
>   #include "igt_sysfs.h"
>   #include "igt_types.h"
> +#include "igt_usb4_switch.h"
>   
>   /**
>    * SUBTEST: display
> @@ -63,6 +64,9 @@
>    * SUBTEST: dp-mst
>    * Description: Make sure that we have DP-MST configuration.
>    *
> + * SUBTEST: usb4-switch
> + * Description: Verify that USB4 Switch 3141 is available and responding.
> + *
>    * arg[1].values: 1, 2, 3, 4
>    */
>   
> @@ -147,6 +151,25 @@ int igt_main() {
>   		}
>   #endif
>   
> +		igt_describe("Verify that USB4 Switch 3141 is available and responding.");
> +		igt_subtest("usb4-switch") {
> +			struct usb4switch *sw;
> +			int port;
> +
> +			sw = usb4switch_init(fd);
> +			igt_require_f(sw,
> +				      "USB4 Switch 3141 not available\n");
> +
> +			/* Verify communication works by querying active port */
> +			port = usb4switch_get_active_port(sw);
> +			igt_assert_f(port >= 0,
> +				     "Cannot communicate with USB4 switch\n");
> +
> +			igt_info("USB4 Switch 3141 available (active port: %d)\n",
> +				 port);
> +			usb4switch_deinit(sw);
> +		}
> +
>   		igt_describe("Make sure that we have eDP panel with PSR1 support.");
>   		igt_subtest("psr1") {
>   			igt_require(psr_sink_support(fd, debugfs_fd, PSR_MODE_1, NULL));

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

* Re: [i-g-t,1/6] lib/igt_edid: add EDID serial extraction helpers
  2026-03-09  9:30   ` [i-g-t,1/6] " Murthy, Arun R
@ 2026-03-09 11:02     ` Joshi, Kunal1
  2026-03-16  3:03       ` Murthy, Arun R
  0 siblings, 1 reply; 25+ messages in thread
From: Joshi, Kunal1 @ 2026-03-09 11:02 UTC (permalink / raw)
  To: Murthy, Arun R, igt-dev

Hello Arun,

Thanks for looking at the patches,

On 09-03-2026 15:00, Murthy, Arun R wrote:
> On 26-02-2026 02:58, Kunal Joshi wrote:
>> Add helpers to extract serial identification from EDID data.
>>
>>   - edid_get_serial_string(): extract ASCII serial from descriptor 0xFF
>>   - edid_get_serial_number(): extract 32-bit serial from EDID header
>>   - edid_get_any_serial(): convenience helper that tries ASCII serial
>>     first, then falls back to 32-bit header serial formatted as hex
>>
>> These are needed by the connector helper and USB4 switch test suite
>> for EDID-based display verification after dock/undock events.
>>
>> Signed-off-by: Kunal Joshi <kunal1.joshi@intel.com>
>> ---
>>   lib/igt_edid.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++
>>   lib/igt_edid.h |  5 +++
>>   2 files changed, 96 insertions(+)
>>
>> diff --git a/lib/igt_edid.c b/lib/igt_edid.c
>> index c68ccf671..e7fcbf0b9 100644
>> --- a/lib/igt_edid.c
>> +++ b/lib/igt_edid.c
>> @@ -249,6 +249,97 @@ void edid_get_monitor_name(const struct edid 
>> *edid, char *name, size_t name_size
>>       name[0] = '\0';
>>   }
>>   +/**
>> + * edid_get_serial_string:
>> + * @edid: EDID structure
>> + * @serial: buffer to write serial string
>> + * @serial_size: size of serial buffer; must be > 1
>> + *
>> + * Extract the serial string from EDID descriptor block type 0xFF.
>> + * The descriptor payload is a 13-byte fixed-width field; trailing
>> + * whitespace is stripped and the result is NUL-terminated.
>> + * @serial is left empty when no 0xFF descriptor is found.
>> + */
>> +void edid_get_serial_string(const struct edid *edid,
>> +                char *serial, size_t serial_size)
> We are trying to get the timings so rather than a generic name 
> serial_string, can this be replaced with get_detailed_timings ?
Spec section 3.10.3.1
defines tag FFh as Display Product Serial Number Descriptor, not a 
detailed timing descriptor

Section 3.10.3
Notes display descriptors are not a detailed timing.
>> +{
>> +    size_t copy_len, i, n;
>> +
>> +    igt_assert(edid);
>> +    igt_assert(serial);
>> +    igt_assert(serial_size > 1);
>> +    serial[0] = '\0';
>> +
>> +    for (i = 0; i < DETAILED_TIMINGS_LEN; i++) {
>> +        const uint8_t *d = (const uint8_t *)&edid->detailed_timings[i];
>> +
>> +        if (d[0] != 0x00 || d[1] != 0x00 || d[2] != 0x00)
>> +            continue;
>> +
>> +        if (d[3] != EDID_DETAIL_MONITOR_SERIAL || d[4] != 0x00)
>> +            continue;
>> +
>> +        /* Descriptor string payload is 13 bytes starting at d[5] */
>> +        copy_len = serial_size - 1 < 13 ? serial_size - 1 : 13;
>> +        memcpy(serial, &d[5], copy_len);
> Can strncpy() be used instead?
strncpy() is not a better fit here. The EDID serial field is a
fixed-width 13-byte payload, not a NUL-terminated C string. Copying the
bounded payload with memcpy(), then explicitly NUL-terminating the
destination and trimming trailing whitespace/newline, matches the EDID
encoding better.
>> +        serial[copy_len] = '\0';
>> +
>> +        for (n = strlen(serial);
>> +             n > 0 && isspace((unsigned char)serial[n - 1]); n--)
>> +            serial[n - 1] = '\0';
>> +
>> +        return;
>> +    }
>> +}
>> +
>> +/**
>> + * edid_get_serial_number:
>> + * @edid: EDID structure
>> + *
>> + * Extract the 32-bit serial number from the EDID base block header
>> + * (bytes 12–15, the manufacturer/product section).  This is different
>> + * from the ASCII serial string in descriptor block 0xFF.
>> + *
>> + * Returns: 32-bit serial number (little-endian), 0 if absent.
>> + */
>> +uint32_t edid_get_serial_number(const struct edid *edid)
>> +{
>> +    return (uint32_t)edid->serial[0] |
>> +           ((uint32_t)edid->serial[1] << 8) |
>> +           ((uint32_t)edid->serial[2] << 16) |
>> +           ((uint32_t)edid->serial[3] << 24);
>> +}
>> +
>> +/**
>> + * edid_get_any_serial:
> No description added?
Description of the function is present below

Thanks and Regards
Kunal Joshi
>
>
> Thanks and Regards,
> Arun R Murthy
> --------------------
>> + * @edid: EDID structure
>> + * @serial: buffer to write serial string
>> + * @serial_size: size of serial buffer; must be > 1
>> + *
>> + * Convenience helper that tries to extract a serial identifier from 
>> EDID.
>> + * First tries the ASCII serial string descriptor (0xFF). If that is 
>> empty,
>> + * falls back to the 32-bit header serial number formatted as 8-char 
>> hex.
>> + * If neither source provides a usable serial (no 0xFF descriptor 
>> and the
>> + * header serial is 0), @serial is left empty.
>> + */
>> +void edid_get_any_serial(const struct edid *edid,
>> +             char *serial, size_t serial_size)
>> +{
>> +    uint32_t serial_num;
>> +
>> +    igt_assert(edid);
>> +    igt_assert(serial);
>> +    igt_assert(serial_size > 1);
>> +
>> +    edid_get_serial_string(edid, serial, serial_size);
>> +    if (serial[0])
>> +        return;
>> +
>> +    serial_num = edid_get_serial_number(edid);
>> +    if (serial_num != 0)
>> +        snprintf(serial, serial_size, "%08X", serial_num);
>> +}
>> +
>>   static void edid_set_mfg(struct edid *edid, const char mfg[static 3])
>>   {
>>       edid->mfg_id[0] = (mfg[0] - '@') << 2 | (mfg[1] - '@') >> 3;
>> diff --git a/lib/igt_edid.h b/lib/igt_edid.h
>> index be0ccf529..d9e396065 100644
>> --- a/lib/igt_edid.h
>> +++ b/lib/igt_edid.h
>> @@ -457,5 +457,10 @@ void *dispid_block_tiled(void *ptr,
>>                int hsize, int vsize,
>>                const char *topology_id);
>>   void edid_get_monitor_name(const struct edid *edid, char *name, 
>> size_t name_size);
>> +void edid_get_serial_string(const struct edid *edid,
>> +                char *serial, size_t serial_size);
>> +uint32_t edid_get_serial_number(const struct edid *edid);
>> +void edid_get_any_serial(const struct edid *edid,
>> +             char *serial, size_t serial_size);
>>     #endif

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

* Re: [i-g-t,2/6] lib/igt_connector_helper: Add generic connector helpers
  2026-03-09  9:38   ` [i-g-t,2/6] " Murthy, Arun R
@ 2026-03-09 11:06     ` Joshi, Kunal1
  2026-03-16  3:17       ` Murthy, Arun R
  0 siblings, 1 reply; 25+ messages in thread
From: Joshi, Kunal1 @ 2026-03-09 11:06 UTC (permalink / raw)
  To: Murthy, Arun R, igt-dev

Hello Arun,

On 09-03-2026 15:08, Murthy, Arun R wrote:
> On 26-02-2026 02:58, Kunal Joshi wrote:
>> Add a lightweight helper library for DRM connector operations used
>> by USB4 switch and other dock/undock tests:
>>
>>   - igt_connector_get_connected(): enumerate connected connectors
>>   - igt_connector_get_info(): query name, EDID serial, and MST path
>>   - igt_connector_find_by_path(): PATH-based connector lookup (MST)
>>   - igt_connector_find_by_name(): name-based connector lookup
>>   - igt_connector_reprobe_all(): force reprobe all connectors by
>>     iterating each connector to trigger DRM core re-detection
>>
>> These helpers abstract common DRM connector patterns that are needed
>> by multiple test suites for display enumeration and verification.
> The contents of these are already present in lib/igt__kms.c
>
Wasn't able to find similar helper that maybe already present,
Could you please point to those function names?
> Instead of a new file, can these be exported from lib/igt_kms.c ?
It was intentional, since igt_kms is already over 8k lines, want to have 
separate lib's grouped by entity,
In this case created connector_helper for having all connector related 
helpers at one place.

Thanks and Regards
Kunal Joshi
>
>
> Thanks and Regards,
> Arun R Murthy
> -------------------
>
>>
>> Signed-off-by: Kunal Joshi <kunal1.joshi@intel.com>
>> ---
>>   lib/igt_connector_helper.c | 299 +++++++++++++++++++++++++++++++++++++
>>   lib/igt_connector_helper.h |  27 ++++
>>   lib/meson.build            |   1 +
>>   3 files changed, 327 insertions(+)
>>   create mode 100644 lib/igt_connector_helper.c
>>   create mode 100644 lib/igt_connector_helper.h
>>
>> diff --git a/lib/igt_connector_helper.c b/lib/igt_connector_helper.c
>> new file mode 100644
>> index 000000000..6be849b7a
>> --- /dev/null
>> +++ b/lib/igt_connector_helper.c
>> @@ -0,0 +1,299 @@
>> +// SPDX-License-Identifier: MIT
>> +/*
>> + * Copyright © 2026 Intel Corporation
>> + */
>> +
>> +/**
>> + * SECTION:igt_connector_helper
>> + * @short_description: Generic connector helper functions for DRM/KMS
>> + * @title: Connector Helper
>> + * @include: igt_connector_helper.h
>> + *
>> + * Helper functions for DRM connector operations including enumeration,
>> + * lookup by name/path, and EDID serial extraction.
>> + */
>> +
>> +#include <string.h>
>> +#include <xf86drm.h>
>> +#include <xf86drmMode.h>
>> +
>> +#include "igt_core.h"
>> +#include "igt_edid.h"
>> +#include "igt_kms.h"
>> +#include "igt_connector_helper.h"
>> +
>> +/**
>> + * igt_connector_get_connected:
>> + * @drm_fd: DRM file descriptor
>> + * @connectors: array to store connector IDs; must be valid if 
>> @max_connectors > 0
>> + * @max_connectors: maximum number of connectors to store
>> + *
>> + * Walks all DRM connectors and stores the IDs of those currently 
>> connected.
>> + * Scanning stops once @max_connectors IDs have been collected; later
>> + * connectors are not examined.
>> + *
>> + * Returns: number of connector IDs written to @connectors, capped by
>> + * @max_connectors.
>> + */
>> +int igt_connector_get_connected(int drm_fd, uint32_t *connectors,
>> +                int max_connectors)
>> +{
>> +    drmModeRes *res;
>> +    drmModeConnector *conn;
>> +    int count = 0;
>> +    int i;
>> +
>> +    igt_assert(max_connectors >= 0);
>> +    if (max_connectors > 0)
>> +        igt_assert(connectors);
>> +
>> +    res = drmModeGetResources(drm_fd);
>> +    if (!res)
>> +        return 0;
>> +
>> +    for (i = 0; i < res->count_connectors && count < max_connectors; 
>> i++) {
>> +        conn = drmModeGetConnector(drm_fd, res->connectors[i]);
>> +        if (!conn)
>> +            continue;
>> +
>> +        if (conn->connection == DRM_MODE_CONNECTED)
>> +            connectors[count++] = conn->connector_id;
>> +
>> +        drmModeFreeConnector(conn);
>> +    }
>> +
>> +    drmModeFreeResources(res);
>> +    return count;
>> +}
>> +
>> +/**
>> + * igt_connector_get_info:
>> + * @drm_fd: DRM file descriptor
>> + * @connector_id: connector ID
>> + * @name: buffer for connector name (mandatory)
>> + * @name_size: size of @name; must be > 0
>> + * @serial: buffer for EDID-derived serial (mandatory)
>> + * @serial_size: size of @serial; must be > 1
>> + * @path: buffer for MST PATH property (optional, may be NULL)
>> + * @path_size: size of @path buffer
>> + *
>> + * Fills connector name, MST PATH, and EDID-derived serial for a 
>> connector.
>> + * @name is always filled when the connector is found. @serial is 
>> filled from
>> + * the ASCII serial string descriptor (0xFF) if present, else from 
>> the 32-bit
>> + * header serial number; left empty if no EDID is available. @path 
>> is filled
>> + * only if requested and the PATH property exists.
>> + *
>> + * Success means the connector object was found and @name was filled.
>> + * @serial and @path are best-effort and may still be empty on success.
>> + *
>> + * Returns: true if the connector was found, false otherwise.
>> + */
>> +bool igt_connector_get_info(int drm_fd, uint32_t connector_id,
>> +                char *name, size_t name_size,
>> +                char *serial, size_t serial_size,
>> +                char *path, size_t path_size)
>> +{
>> +    drmModeConnector *conn;
>> +    drmModePropertyBlobPtr edid_blob = NULL;
>> +    uint64_t blob_id = 0;
>> +    drmModePropertyPtr prop;
>> +    const struct edid *edid;
>> +    int i;
>> +
>> +    igt_assert(name && name_size > 0);
>> +    igt_assert(serial && serial_size > 1);
>> +    igt_assert(!path || path_size > 0);
>> +
>> +    name[0] = '\0';
>> +    serial[0] = '\0';
>> +    if (path)
>> +        path[0] = '\0';
>> +
>> +    conn = drmModeGetConnector(drm_fd, connector_id);
>> +    if (!conn)
>> +        return false;
>> +
>> +    snprintf(name, name_size, "%s-%d",
>> +         kmstest_connector_type_str(conn->connector_type),
>> +         conn->connector_type_id);
>> +
>> +    for (i = 0; i < conn->count_props; i++) {
>> +        prop = drmModeGetProperty(drm_fd, conn->props[i]);
>> +        if (!prop)
>> +            continue;
>> +
>> +        if (strcmp(prop->name, "EDID") == 0)
>> +            blob_id = conn->prop_values[i];
>> +
>> +        drmModeFreeProperty(prop);
>> +        if (blob_id)
>> +            break;
>> +    }
>> +
>> +    /* Extract MST PATH if requested */
>> +    if (path) {
>> +        drmModePropertyBlobPtr path_blob;
>> +
>> +        /* PATH blob payload is a NUL-terminated string */
>> +        path_blob = kmstest_get_path_blob(drm_fd, connector_id);
>> +        if (path_blob) {
>> +            snprintf(path, path_size, "%s",
>> +                 (const char *)path_blob->data);
>> +            drmModeFreePropertyBlob(path_blob);
>> +        }
>> +    }
>> +
>> +    drmModeFreeConnector(conn);
>> +
>> +    if (blob_id) {
>> +        edid_blob = drmModeGetPropertyBlob(drm_fd, blob_id);
>> +        if (edid_blob) {
>> +            if (edid_blob->length >= sizeof(struct edid)) {
>> +                edid = edid_blob->data;
>> +                edid_get_any_serial(edid, serial, serial_size);
>> +            }
>> +            drmModeFreePropertyBlob(edid_blob);
>> +        }
>> +    }
>> +
>> +    return true;
>> +}
>> +
>> +/**
>> + * igt_connector_find_by_path:
>> + * @drm_fd: DRM file descriptor
>> + * @path: MST PATH property value to match
>> + * @connector_id: output for connector ID (filled on success)
>> + *
>> + * Finds the currently connected connector whose PATH property 
>> matches @path
>> + * (exact string comparison).  PATH is the preferred stable identity 
>> for MST
>> + * connectors; connector IDs may change across hotplug events.
>> + *
>> + * Returns: true if a matching connected connector was found.
>> + */
>> +bool igt_connector_find_by_path(int drm_fd, const char *path,
>> +                uint32_t *connector_id)
>> +{
>> +    drmModeRes *res;
>> +    drmModeConnector *conn;
>> +    drmModePropertyBlobPtr path_blob;
>> +    bool found = false;
>> +    int i;
>> +
>> +    if (!path || !connector_id)
>> +        return false;
>> +
>> +    res = drmModeGetResources(drm_fd);
>> +    if (!res)
>> +        return false;
>> +
>> +    for (i = 0; i < res->count_connectors && !found; i++) {
>> +        conn = drmModeGetConnector(drm_fd, res->connectors[i]);
>> +        if (!conn)
>> +            continue;
>> +
>> +        if (conn->connection == DRM_MODE_CONNECTED) {
>> +            path_blob = kmstest_get_path_blob(drm_fd,
>> +                              conn->connector_id);
>> +            if (path_blob) {
>> +                if (strcmp(path_blob->data, path) == 0) {
>> +                    *connector_id = conn->connector_id;
>> +                    found = true;
>> +                }
>> +                drmModeFreePropertyBlob(path_blob);
>> +            }
>> +        }
>> +
>> +        drmModeFreeConnector(conn);
>> +    }
>> +
>> +    drmModeFreeResources(res);
>> +
>> +    if (found)
>> +        igt_debug("igt_connector: Found connector %u for path '%s'\n",
>> +              *connector_id, path);
>> +
>> +    return found;
>> +}
>> +
>> +/**
>> + * igt_connector_find_by_name:
>> + * @drm_fd: DRM file descriptor
>> + * @name: connector name to match (e.g., "DP-6")
>> + * @connector_id: output for connector ID (filled on success)
>> + *
>> + * Name-based lookup helper.  Prefer igt_connector_find_by_path() 
>> for MST
>> + * connectors, since connector names and IDs may change across 
>> hotplug events.
>> + *
>> + * Returns: true if a matching connected connector was found.
>> + */
>> +bool igt_connector_find_by_name(int drm_fd, const char *name,
>> +                uint32_t *connector_id)
>> +{
>> +    drmModeRes *res;
>> +    drmModeConnector *conn;
>> +    char conn_name[IGT_CONNECTOR_NAME_MAX];
>> +    bool found = false;
>> +    int i;
>> +
>> +    if (!name || !connector_id)
>> +        return false;
>> +
>> +    res = drmModeGetResources(drm_fd);
>> +    if (!res)
>> +        return false;
>> +
>> +    for (i = 0; i < res->count_connectors && !found; i++) {
>> +        conn = drmModeGetConnector(drm_fd, res->connectors[i]);
>> +        if (!conn)
>> +            continue;
>> +
>> +        snprintf(conn_name, sizeof(conn_name), "%s-%d",
>> + kmstest_connector_type_str(conn->connector_type),
>> +             conn->connector_type_id);
>> +
>> +        if (strcmp(conn_name, name) == 0 &&
>> +            conn->connection == DRM_MODE_CONNECTED) {
>> +            *connector_id = conn->connector_id;
>> +            found = true;
>> +        }
>> +
>> +        drmModeFreeConnector(conn);
>> +    }
>> +
>> +    drmModeFreeResources(res);
>> +
>> +    if (found)
>> +        igt_debug("igt_connector: Found connector %u for name '%s'\n",
>> +              *connector_id, name);
>> +
>> +    return found;
>> +}
>> +
>> +/**
>> + * igt_connector_reprobe_all:
>> + * @drm_fd: DRM file descriptor
>> + *
>> + * Issues a GETCONNECTOR ioctl for every connector, requesting fresh 
>> state
>> + * from the kernel. This is often sufficient to refresh connector 
>> status and
>> + * MST topology visibility after hotplug events, but does not 
>> guarantee a
>> + * full hardware reprobe in all driver paths.
>> + */
>> +void igt_connector_reprobe_all(int drm_fd)
>> +{
>> +    drmModeRes *res;
>> +    drmModeConnector *conn;
>> +    int i;
>> +
>> +    res = drmModeGetResources(drm_fd);
>> +    if (!res)
>> +        return;
>> +
>> +    for (i = 0; i < res->count_connectors; i++) {
>> +        conn = drmModeGetConnector(drm_fd, res->connectors[i]);
>> +        if (conn)
>> +            drmModeFreeConnector(conn);
>> +    }
>> +
>> +    drmModeFreeResources(res);
>> +}
>> diff --git a/lib/igt_connector_helper.h b/lib/igt_connector_helper.h
>> new file mode 100644
>> index 000000000..fffb2661b
>> --- /dev/null
>> +++ b/lib/igt_connector_helper.h
>> @@ -0,0 +1,27 @@
>> +/* SPDX-License-Identifier: MIT */
>> +/*
>> + * Copyright © 2026 Intel Corporation
>> + */
>> +
>> +#ifndef IGT_CONNECTOR_HELPER_H
>> +#define IGT_CONNECTOR_HELPER_H
>> +
>> +#include <stdbool.h>
>> +#include <stddef.h>
>> +#include <stdint.h>
>> +
>> +#define IGT_CONNECTOR_NAME_MAX 32
>> +
>> +int igt_connector_get_connected(int drm_fd, uint32_t *connectors,
>> +                int max_connectors);
>> +bool igt_connector_get_info(int drm_fd, uint32_t connector_id,
>> +                char *name, size_t name_size,
>> +                char *serial, size_t serial_size,
>> +                char *path, size_t path_size);
>> +bool igt_connector_find_by_path(int drm_fd, const char *path,
>> +                uint32_t *connector_id);
>> +bool igt_connector_find_by_name(int drm_fd, const char *name,
>> +                uint32_t *connector_id);
>> +void igt_connector_reprobe_all(int drm_fd);
>> +
>> +#endif /* IGT_CONNECTOR_HELPER_H */
>> diff --git a/lib/meson.build b/lib/meson.build
>> index ea721ecf7..074b21fdf 100644
>> --- a/lib/meson.build
>> +++ b/lib/meson.build
>> @@ -113,6 +113,7 @@ lib_sources = [
>>       'igt_vmwgfx.c',
>>       'igt_psr.c',
>>       'igt_amd.c',
>> +    'igt_connector_helper.c',
>>       'igt_edid.c',
>>       'igt_eld.c',
>>       'igt_infoframe.c',

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

* Re: [i-g-t,6/6] tests/intel/kms_usb4_switch: Add USB4 switch test suite
  2026-03-09 10:03   ` [i-g-t,6/6] " Murthy, Arun R
@ 2026-03-09 11:14     ` Joshi, Kunal1
  2026-03-16  3:38       ` Murthy, Arun R
  0 siblings, 1 reply; 25+ messages in thread
From: Joshi, Kunal1 @ 2026-03-09 11:14 UTC (permalink / raw)
  To: Murthy, Arun R, igt-dev

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

Hello Arun,

On 09-03-2026 15:33, Murthy, Arun R wrote:
>> +static void test_switch_sr(data_t *data,
>> +               const struct usb4switch_port *port_cfg_a,
>> +               const struct usb4switch_port *port_cfg_b)
>> +{
>> +    igt_crc_t ref_crcs[MAX_DISPLAYS_PER_PORT];
>> +    int iterations = usb4switch_get_iterations(data->sw);
>> +    int timeout = USB4_SWITCH_TIMEOUT_S;
> Why not have it as a const or use the macro directly?
Kept it as a local alias since this pattern is used widely in IGT for
function-local knobs such as timeout/iterations/count, and it makes call
sites a bit easier to read when reused multiple times.

That said, since this one is not modified, I can make it const to 
express that more clearly.

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

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

* RE: [i-g-t,1/6] lib/igt_edid: add EDID serial extraction helpers
  2026-03-09 11:02     ` Joshi, Kunal1
@ 2026-03-16  3:03       ` Murthy, Arun R
  0 siblings, 0 replies; 25+ messages in thread
From: Murthy, Arun R @ 2026-03-16  3:03 UTC (permalink / raw)
  To: Joshi, Kunal1, igt-dev@lists.freedesktop.org

Based on the response 

Reviewed-by: Arun R Murthy <arun.r.murthy@gmail.com>

Thanks and Regards,
Arun R Murthy
--------------------
> -----Original Message-----
> From: Joshi, Kunal1 <kunal1.joshi@intel.com>
> Sent: Monday, March 9, 2026 4:32 PM
> To: Murthy, Arun R <arun.r.murthy@intel.com>; igt-dev@lists.freedesktop.org
> Subject: Re: [i-g-t,1/6] lib/igt_edid: add EDID serial extraction helpers
> 
> Hello Arun,
> 
> Thanks for looking at the patches,
> 
> On 09-03-2026 15:00, Murthy, Arun R wrote:
> > On 26-02-2026 02:58, Kunal Joshi wrote:
> >> Add helpers to extract serial identification from EDID data.
> >>
> >>   - edid_get_serial_string(): extract ASCII serial from descriptor
> >> 0xFF
> >>   - edid_get_serial_number(): extract 32-bit serial from EDID header
> >>   - edid_get_any_serial(): convenience helper that tries ASCII serial
> >>     first, then falls back to 32-bit header serial formatted as hex
> >>
> >> These are needed by the connector helper and USB4 switch test suite
> >> for EDID-based display verification after dock/undock events.
> >>
> >> Signed-off-by: Kunal Joshi <kunal1.joshi@intel.com>
> >> ---
> >>   lib/igt_edid.c | 91
> >> ++++++++++++++++++++++++++++++++++++++++++++++++++
> >>   lib/igt_edid.h |  5 +++
> >>   2 files changed, 96 insertions(+)
> >>
> >> diff --git a/lib/igt_edid.c b/lib/igt_edid.c index
> >> c68ccf671..e7fcbf0b9 100644
> >> --- a/lib/igt_edid.c
> >> +++ b/lib/igt_edid.c
> >> @@ -249,6 +249,97 @@ void edid_get_monitor_name(const struct edid
> >> *edid, char *name, size_t name_size
> >>       name[0] = '\0';
> >>   }
> >>   +/**
> >> + * edid_get_serial_string:
> >> + * @edid: EDID structure
> >> + * @serial: buffer to write serial string
> >> + * @serial_size: size of serial buffer; must be > 1
> >> + *
> >> + * Extract the serial string from EDID descriptor block type 0xFF.
> >> + * The descriptor payload is a 13-byte fixed-width field; trailing
> >> + * whitespace is stripped and the result is NUL-terminated.
> >> + * @serial is left empty when no 0xFF descriptor is found.
> >> + */
> >> +void edid_get_serial_string(const struct edid *edid,
> >> +                char *serial, size_t serial_size)
> > We are trying to get the timings so rather than a generic name
> > serial_string, can this be replaced with get_detailed_timings ?
> Spec section 3.10.3.1
> defines tag FFh as Display Product Serial Number Descriptor, not a detailed
> timing descriptor
> 
> Section 3.10.3
> Notes display descriptors are not a detailed timing.
> >> +{
> >> +    size_t copy_len, i, n;
> >> +
> >> +    igt_assert(edid);
> >> +    igt_assert(serial);
> >> +    igt_assert(serial_size > 1);
> >> +    serial[0] = '\0';
> >> +
> >> +    for (i = 0; i < DETAILED_TIMINGS_LEN; i++) {
> >> +        const uint8_t *d = (const uint8_t
> >> +*)&edid->detailed_timings[i];
> >> +
> >> +        if (d[0] != 0x00 || d[1] != 0x00 || d[2] != 0x00)
> >> +            continue;
> >> +
> >> +        if (d[3] != EDID_DETAIL_MONITOR_SERIAL || d[4] != 0x00)
> >> +            continue;
> >> +
> >> +        /* Descriptor string payload is 13 bytes starting at d[5] */
> >> +        copy_len = serial_size - 1 < 13 ? serial_size - 1 : 13;
> >> +        memcpy(serial, &d[5], copy_len);
> > Can strncpy() be used instead?
> strncpy() is not a better fit here. The EDID serial field is a fixed-width 13-byte
> payload, not a NUL-terminated C string. Copying the bounded payload with
> memcpy(), then explicitly NUL-terminating the destination and trimming
> trailing whitespace/newline, matches the EDID encoding better.
> >> +        serial[copy_len] = '\0';
> >> +
> >> +        for (n = strlen(serial);
> >> +             n > 0 && isspace((unsigned char)serial[n - 1]); n--)
> >> +            serial[n - 1] = '\0';
> >> +
> >> +        return;
> >> +    }
> >> +}
> >> +
> >> +/**
> >> + * edid_get_serial_number:
> >> + * @edid: EDID structure
> >> + *
> >> + * Extract the 32-bit serial number from the EDID base block header
> >> + * (bytes 12–15, the manufacturer/product section).  This is
> >> +different
> >> + * from the ASCII serial string in descriptor block 0xFF.
> >> + *
> >> + * Returns: 32-bit serial number (little-endian), 0 if absent.
> >> + */
> >> +uint32_t edid_get_serial_number(const struct edid *edid) {
> >> +    return (uint32_t)edid->serial[0] |
> >> +           ((uint32_t)edid->serial[1] << 8) |
> >> +           ((uint32_t)edid->serial[2] << 16) |
> >> +           ((uint32_t)edid->serial[3] << 24); }
> >> +
> >> +/**
> >> + * edid_get_any_serial:
> > No description added?
> Description of the function is present below
> 
> Thanks and Regards
> Kunal Joshi
> >
> >
> > Thanks and Regards,
> > Arun R Murthy
> > --------------------
> >> + * @edid: EDID structure
> >> + * @serial: buffer to write serial string
> >> + * @serial_size: size of serial buffer; must be > 1
> >> + *
> >> + * Convenience helper that tries to extract a serial identifier from
> >> EDID.
> >> + * First tries the ASCII serial string descriptor (0xFF). If that is
> >> empty,
> >> + * falls back to the 32-bit header serial number formatted as 8-char
> >> hex.
> >> + * If neither source provides a usable serial (no 0xFF descriptor
> >> and the
> >> + * header serial is 0), @serial is left empty.
> >> + */
> >> +void edid_get_any_serial(const struct edid *edid,
> >> +             char *serial, size_t serial_size) {
> >> +    uint32_t serial_num;
> >> +
> >> +    igt_assert(edid);
> >> +    igt_assert(serial);
> >> +    igt_assert(serial_size > 1);
> >> +
> >> +    edid_get_serial_string(edid, serial, serial_size);
> >> +    if (serial[0])
> >> +        return;
> >> +
> >> +    serial_num = edid_get_serial_number(edid);
> >> +    if (serial_num != 0)
> >> +        snprintf(serial, serial_size, "%08X", serial_num); }
> >> +
> >>   static void edid_set_mfg(struct edid *edid, const char mfg[static
> >> 3])
> >>   {
> >>       edid->mfg_id[0] = (mfg[0] - '@') << 2 | (mfg[1] - '@') >> 3;
> >> diff --git a/lib/igt_edid.h b/lib/igt_edid.h index
> >> be0ccf529..d9e396065 100644
> >> --- a/lib/igt_edid.h
> >> +++ b/lib/igt_edid.h
> >> @@ -457,5 +457,10 @@ void *dispid_block_tiled(void *ptr,
> >>                int hsize, int vsize,
> >>                const char *topology_id);
> >>   void edid_get_monitor_name(const struct edid *edid, char *name,
> >> size_t name_size);
> >> +void edid_get_serial_string(const struct edid *edid,
> >> +                char *serial, size_t serial_size); uint32_t
> >> +edid_get_serial_number(const struct edid *edid); void
> >> +edid_get_any_serial(const struct edid *edid,
> >> +             char *serial, size_t serial_size);
> >>     #endif

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

* RE: [i-g-t,2/6] lib/igt_connector_helper: Add generic connector helpers
  2026-03-09 11:06     ` Joshi, Kunal1
@ 2026-03-16  3:17       ` Murthy, Arun R
  0 siblings, 0 replies; 25+ messages in thread
From: Murthy, Arun R @ 2026-03-16  3:17 UTC (permalink / raw)
  To: Joshi, Kunal1, igt-dev@lists.freedesktop.org

> -----Original Message-----
> From: Joshi, Kunal1 <kunal1.joshi@intel.com>
> Sent: Monday, March 9, 2026 4:37 PM
> To: Murthy, Arun R <arun.r.murthy@intel.com>; igt-dev@lists.freedesktop.org
> Subject: Re: [i-g-t,2/6] lib/igt_connector_helper: Add generic connector helpers
> 
> Hello Arun,
> 
> On 09-03-2026 15:08, Murthy, Arun R wrote:
> > On 26-02-2026 02:58, Kunal Joshi wrote:
> >> Add a lightweight helper library for DRM connector operations used by
> >> USB4 switch and other dock/undock tests:
> >>
> >>   - igt_connector_get_connected(): enumerate connected connectors
> >>   - igt_connector_get_info(): query name, EDID serial, and MST path
> >>   - igt_connector_find_by_path(): PATH-based connector lookup (MST)
> >>   - igt_connector_find_by_name(): name-based connector lookup
> >>   - igt_connector_reprobe_all(): force reprobe all connectors by
> >>     iterating each connector to trigger DRM core re-detection
> >>
> >> These helpers abstract common DRM connector patterns that are needed
> >> by multiple test suites for display enumeration and verification.
> > The contents of these are already present in lib/igt__kms.c
> >
> Wasn't able to find similar helper that maybe already present, Could you please
> point to those function names?
kmstest_get_connector_config()

> > Instead of a new file, can these be exported from lib/igt_kms.c ?
> It was intentional, since igt_kms is already over 8k lines, want to have separate
> lib's grouped by entity, In this case created connector_helper for having all
> connector related helpers at one place.
> 
What I meant was all of what is required is already there in igt_kms.c, just need to export them.

Thanks and Regards,
Arun R Murthy
-------------------

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

* Re: [i-g-t,6/6] tests/intel/kms_usb4_switch: Add USB4 switch test suite
  2026-03-09 11:14     ` Joshi, Kunal1
@ 2026-03-16  3:38       ` Murthy, Arun R
  0 siblings, 0 replies; 25+ messages in thread
From: Murthy, Arun R @ 2026-03-16  3:38 UTC (permalink / raw)
  To: Joshi, Kunal1, igt-dev

On 09-03-2026 16:44, Joshi, Kunal1 wrote:
> Hello Arun,
>
> On 09-03-2026 15:33, Murthy, Arun R wrote:
>>> +static void test_switch_sr(data_t *data,
>>> +               const struct usb4switch_port *port_cfg_a,
>>> +               const struct usb4switch_port *port_cfg_b)
>>> +{
>>> +    igt_crc_t ref_crcs[MAX_DISPLAYS_PER_PORT];
>>> +    int iterations = usb4switch_get_iterations(data->sw);
>>> +    int timeout = USB4_SWITCH_TIMEOUT_S;
>> Why not have it as a const or use the macro directly?
> Kept it as a local alias since this pattern is used widely in IGT for
> function-local knobs such as timeout/iterations/count, and it makes call
> sites a bit easier to read when reused multiple times.
>
> That said, since this one is not modified, I can make it const to 
> express that more clearly. 
ok.


Thanks and Regards,
Arun R Murthy
-------------------


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

* Re: [i-g-t,3/6] lib/igt_serial: add generic serial communication helper
  2026-02-25 21:28 ` [PATCH i-g-t 3/6] lib/igt_serial: add generic serial communication helper Kunal Joshi
@ 2026-03-16  5:40   ` Murthy, Arun R
  0 siblings, 0 replies; 25+ messages in thread
From: Murthy, Arun R @ 2026-03-16  5:40 UTC (permalink / raw)
  To: Kunal Joshi, igt-dev

Logic looks good to me.
  Reviewed-by: Arun R Murthy <arun.r.murthy@intel.com>

Thanks and Regards,
Arun R Murthy
--------------------

On 26-02-2026 02:58, Kunal Joshi wrote:
> Add a reusable serial communication library for host-to-device
>
>   - igt_serial_open()/close(): lifecycle with configurable baud rate
>   - igt_serial_send()/read(): raw data transfer
>   - igt_serial_command(): send command and capture response
>   - igt_serial_flush(): drain stale data from receive buffer
>   - igt_serial_set_timeout(): adjust per-operation VTIME timeouts
>
> Used by lib/igt_usb4_switch to communicate with the Microsoft USB4
> Switch 3141 over its serial/USB interface.
>
> Signed-off-by: Kunal Joshi <kunal1.joshi@intel.com>
> ---
>   lib/igt_serial.c | 435 +++++++++++++++++++++++++++++++++++++++++++++++
>   lib/igt_serial.h |  32 ++++
>   lib/meson.build  |   1 +
>   3 files changed, 468 insertions(+)
>   create mode 100644 lib/igt_serial.c
>   create mode 100644 lib/igt_serial.h
>
> diff --git a/lib/igt_serial.c b/lib/igt_serial.c
> new file mode 100644
> index 000000000..35fbadd7c
> --- /dev/null
> +++ b/lib/igt_serial.c
> @@ -0,0 +1,435 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2026 Intel Corporation
> + */
> +
> +/**
> + * SECTION:igt_serial
> + * @short_description: Generic serial port communication library
> + * @title: Serial Communication
> + * @include: igt_serial.h
> + *
> + * This library provides a clean API for serial port communication,
> + * useful for test equipment that uses serial/USB-CDC interfaces.
> + */
> +
> +#include <errno.h>
> +#include <fcntl.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <termios.h>
> +#include <unistd.h>
> +
> +#include "igt_core.h"
> +#include "igt_serial.h"
> +
> +struct igt_serial {
> +	int fd;
> +	char *device;
> +	struct termios orig_termios;
> +	bool termios_saved;
> +	int read_timeout_ds;
> +};
> +
> +static speed_t baud_to_speed(int baud)
> +{
> +	switch (baud) {
> +	case 9600:   return B9600;
> +	case 19200:  return B19200;
> +	case 38400:  return B38400;
> +	case 57600:  return B57600;
> +	case 115200: return B115200;
> +	case 230400: return B230400;
> +	case 460800: return B460800;
> +	case 921600: return B921600;
> +	default:
> +		return 0;
> +	}
> +}
> +
> +/**
> + * igt_serial_open:
> + * @device: path to the serial device (e.g., "/dev/ttyACM0")
> + * @baud_rate: baud rate (e.g., 115200)
> + *
> + * Opens a serial port with the specified baud rate.
> + * Uses 8N1 configuration (8 data bits, no parity, 1 stop bit).
> + *
> + * Returns: A serial handle on success, NULL on failure.
> + */
> +struct igt_serial *igt_serial_open(const char *device, int baud_rate)
> +{
> +	struct igt_serial *s;
> +	struct termios tty;
> +	speed_t speed;
> +
> +	if (!device) {
> +		igt_debug("Serial: NULL device path\n");
> +		return NULL;
> +	}
> +
> +	s = calloc(1, sizeof(*s));
> +	if (!s) {
> +		igt_debug("Serial: Failed to allocate memory\n");
> +		return NULL;
> +	}
> +
> +	s->fd = -1;
> +
> +	s->device = strdup(device);
> +	if (!s->device)
> +		goto err_free;
> +
> +	/* Default timeout: 1 second (10 deciseconds) */
> +	s->read_timeout_ds = 10;
> +	s->fd = open(device, O_RDWR | O_NOCTTY);
> +
> +	if (s->fd < 0) {
> +		igt_debug("Serial: Failed to open %s: %s\n",
> +			  device, strerror(errno));
> +		goto err_free_device;
> +	}
> +
> +	if (tcgetattr(s->fd, &tty) != 0) {
> +		igt_debug("Serial: tcgetattr failed: %s\n", strerror(errno));
> +		goto err_close;
> +	}
> +
> +	s->orig_termios = tty;
> +	s->termios_saved = true;
> +	speed = baud_to_speed(baud_rate);
> +
> +	if (!speed) {
> +		igt_debug("Serial: Unsupported baud rate %d\n", baud_rate);
> +		goto err_close;
> +	}
> +
> +	cfsetospeed(&tty, speed);
> +	cfsetispeed(&tty, speed);
> +
> +	/* 8N1: 8 data bits, no parity, 1 stop bit */
> +	tty.c_cflag &= ~PARENB;
> +	tty.c_cflag &= ~CSTOPB;
> +	tty.c_cflag &= ~CSIZE;
> +	tty.c_cflag |= CS8;
> +	tty.c_cflag &= ~CRTSCTS;
> +	tty.c_cflag |= CREAD | CLOCAL;
> +
> +	/* Disable canonical mode, echo, and signals */
> +	tty.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
> +
> +	/* Disable output post-processing */
> +	tty.c_oflag &= ~OPOST;
> +
> +	/* Disable software flow control and input translations */
> +	tty.c_iflag &= ~(IXON | IXOFF | IXANY);
> +	tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP |
> +			  INLCR | IGNCR | ICRNL);
> +
> +	/*
> +	 * Blocking read with timeout.
> +	 * VMIN=0, VTIME>0: return after timeout or when data available.
> +	 */
> +	tty.c_cc[VMIN] = 0;
> +	tty.c_cc[VTIME] = s->read_timeout_ds;
> +
> +	if (tcsetattr(s->fd, TCSANOW, &tty) != 0) {
> +		igt_debug("Serial: tcsetattr failed: %s\n", strerror(errno));
> +		goto err_close;
> +	}
> +
> +	/* Flush any stale input */
> +	if (tcflush(s->fd, TCIFLUSH) != 0)
> +		igt_debug("Serial: tcflush failed: %s\n", strerror(errno));
> +
> +	igt_debug("Serial: Opened %s at %d baud (timeout=%dms)\n",
> +		  s->device, baud_rate, s->read_timeout_ds * 100);
> +	return s;
> +
> +err_close:
> +	close(s->fd);
> +err_free_device:
> +	free(s->device);
> +err_free:
> +	free(s);
> +	return NULL;
> +}
> +
> +/**
> + * igt_serial_close:
> + * @s: serial handle
> + *
> + * Closes the serial port and frees resources.
> + */
> +void igt_serial_close(struct igt_serial *s)
> +{
> +	if (!s)
> +		return;
> +
> +	if (s->termios_saved) {
> +		if (tcsetattr(s->fd, TCSANOW, &s->orig_termios) != 0)
> +			igt_debug("Serial: tcsetattr restore failed: %s\n",
> +				  strerror(errno));
> +	}
> +
> +	if (s->fd >= 0)
> +		close(s->fd);
> +	igt_debug("Serial: Closed %s\n", s->device ? s->device : "(unknown)");
> +	free(s->device);
> +	free(s);
> +}
> +
> +/**
> + * igt_serial_set_timeout:
> + * @s: serial handle
> + * @timeout_ms: timeout in milliseconds (0 enables polling mode)
> + *
> + * Sets the read timeout for the serial port. VTIME has a granularity
> + * of 100 ms (deciseconds); non-zero values are rounded up. Setting
> + * @timeout_ms to 0 configures polling mode where reads return
> + * immediately if no data is available.
> + *
> + * Returns: true on success, false on failure.
> + */
> +bool igt_serial_set_timeout(struct igt_serial *s, int timeout_ms)
> +{
> +	struct termios tty;
> +	int new_timeout_ds;
> +
> +	if (!s || timeout_ms < 0)
> +		return false;
> +
> +	if (tcgetattr(s->fd, &tty) != 0) {
> +		igt_debug("Serial: tcgetattr failed: %s\n", strerror(errno));
> +		return false;
> +	}
> +
> +	/* Convert ms to deciseconds (0.1s units), clamp to cc_t max (255) */
> +	new_timeout_ds = (timeout_ms + 99) / 100;
> +	if (new_timeout_ds > 255)
> +		new_timeout_ds = 255;
> +
> +	tty.c_cc[VTIME] = new_timeout_ds;
> +
> +	if (tcsetattr(s->fd, TCSANOW, &tty) != 0) {
> +		igt_debug("Serial: tcsetattr failed: %s\n", strerror(errno));
> +		return false;
> +	}
> +	s->read_timeout_ds = new_timeout_ds;
> +	igt_debug("Serial: Timeout set to %dms (applied %dms)\n",
> +		  timeout_ms, s->read_timeout_ds * 100);
> +	return true;
> +}
> +
> +/**
> + * igt_serial_send:
> + * @s: serial handle
> + * @cmd: command string to send
> + *
> + * Sends a command string to the serial port exactly as provided.
> + * The caller is responsible for adding any required line endings.
> + * Handles short writes that may occur on USB-CDC devices under load.
> + *
> + * Returns: true on success, false on failure.
> + */
> +bool igt_serial_send(struct igt_serial *s, const char *cmd)
> +{
> +	size_t len, total = 0;
> +	ssize_t written;
> +
> +	if (!s || !cmd)
> +		return false;
> +
> +	len = strlen(cmd);
> +	if (len == 0)
> +		return true;
> +
> +	while (total < len) {
> +		written = write(s->fd, cmd + total, len - total);
> +		if (written <= 0) {
> +			if (written < 0 && errno == EINTR)
> +				continue;
> +			igt_debug("Serial: Write failed: %s\n",
> +				  written < 0 ? strerror(errno) : "zero bytes written");
> +			return false;
> +		}
> +		total += written;
> +	}
> +
> +	if (tcdrain(s->fd) != 0) {
> +		igt_debug("Serial: tcdrain failed: %s\n", strerror(errno));
> +		return false;
> +	}
> +
> +	igt_debug("Serial: Sent '%s'\n", cmd);
> +	return true;
> +}
> +
> +/*
> + * igt_serial_readline - Read a line from serial port (until newline or timeout).
> + *
> + * Returns number of bytes in buf (0 means timeout/no data), or -1 on error.
> + */
> +static ssize_t igt_serial_readline(struct igt_serial *s, char *buf, size_t size)
> +{
> +	size_t total = 0;
> +	ssize_t n;
> +
> +	if (!s || !buf || size == 0)
> +		return -1;
> +
> +	/*
> +	 * Read one byte at a time until newline or timeout.
> +	 * VTIME timeout ensures read() returns 0 on timeout.
> +	 */
> +	while (total < size - 1) {
> +		n = read(s->fd, buf + total, 1);
> +		if (n < 0) {
> +			if (errno == EINTR)
> +				continue;
> +			igt_debug("Serial: Read error: %s\n", strerror(errno));
> +			return -1;
> +		}
> +		if (n == 0)
> +			break;
> +
> +		total++;
> +
> +		if (buf[total - 1] == '\n')
> +			break;
> +	}
> +
> +	buf[total] = '\0';
> +	return (ssize_t)total;
> +}
> +
> +/**
> + * igt_serial_read:
> + * @s: serial handle
> + * @buf: buffer to read into
> + * @size: size of buffer
> + *
> + * Reads one line (up to newline or timeout) from the serial port.
> + * This is a line-oriented read, not an arbitrary byte read — it stops
> + * at the first newline character or when the VTIME timeout expires.
> + * Use igt_serial_set_timeout() to adjust the timeout before calling.
> + *
> + * Returns: Number of bytes read, 0 on timeout/no data, or -1 on error.
> + */
> +ssize_t igt_serial_read(struct igt_serial *s, char *buf, size_t size)
> +{
> +	ssize_t n;
> +
> +	n = igt_serial_readline(s, buf, size);
> +
> +	igt_debug("Serial: Read %zd bytes: '%s'\n", n, n > 0 ? buf : "");
> +	return n;
> +}
> +
> +/**
> + * igt_serial_command:
> + * @s: serial handle
> + * @cmd: command string to send
> + * @response: buffer for response
> + * @resp_size: size of response buffer
> + *
> + * Convenience function to send a command and read the response.
> + * Flushes stale input before sending, sends the command, then reads
> + * one response line. If @response is non-NULL, at least one byte must
> + * be received before the configured VTIME timeout for success.
> + *
> + * Returns: true if the send succeeded and, when @response is given,
> + * at least one response byte was received; false otherwise.
> + */
> +bool igt_serial_command(struct igt_serial *s, const char *cmd,
> +			char *response, size_t resp_size)
> +{
> +	ssize_t n;
> +
> +	if (!s || !cmd)
> +		return false;
> +
> +	igt_serial_flush(s);
> +
> +	if (!igt_serial_send(s, cmd))
> +		return false;
> +
> +	if (response && resp_size > 0) {
> +		n = igt_serial_readline(s, response, resp_size);
> +		if (n <= 0) {
> +			igt_debug("Serial: No response received\n");
> +			return false;
> +		}
> +		igt_debug("Serial: Response: '%s'\n", response);
> +	}
> +
> +	return true;
> +}
> +
> +/**
> + * igt_serial_flush:
> + * @s: serial handle
> + *
> + * Discards stale input. Does not touch pending output.
> + * Calls TCIFLUSH to drop kernel-queued input, then temporarily sets
> + * O_NONBLOCK and drains any bytes already readable to reduce races
> + * with in-flight input. Assumes single-threaded access.
> + */
> +void igt_serial_flush(struct igt_serial *s)
> +{
> +	char discard[256];
> +	ssize_t n;
> +	int flags;
> +
> +	if (!s)
> +		return;
> +
> +	/* Discard kernel-queued input; never touch pending output */
> +	if (tcflush(s->fd, TCIFLUSH) != 0)
> +		igt_debug("Serial: tcflush failed: %s\n", strerror(errno));
> +
> +	/* Drain bytes already readable to reduce races with in-flight input */
> +	flags = fcntl(s->fd, F_GETFL);
> +	if (flags < 0) {
> +		igt_debug("Serial: fcntl(F_GETFL) failed: %s\n", strerror(errno));
> +		return;
> +	}
> +
> +	if (fcntl(s->fd, F_SETFL, flags | O_NONBLOCK) < 0) {
> +		igt_debug("Serial: fcntl(F_SETFL) failed: %s\n", strerror(errno));
> +		return;
> +	}
> +
> +	for (;;) {
> +		n = read(s->fd, discard, sizeof(discard));
> +		if (n > 0)
> +			continue;
> +		if (n == 0)
> +			break;
> +		/* n < 0 */
> +		if (errno == EINTR)
> +			continue;
> +		if (errno != EAGAIN)
> +			igt_debug("Serial: unexpected read error in flush: %s\n",
> +				  strerror(errno));
> +		break;
> +	}
> +
> +	if (fcntl(s->fd, F_SETFL, flags) < 0)
> +		igt_debug("Serial: fcntl(F_SETFL) restore failed: %s\n", strerror(errno));
> +
> +	igt_debug("Serial: Flushed\n");
> +}
> +
> +/**
> + * igt_serial_get_fd:
> + * @s: serial handle
> + *
> + * Gets the underlying file descriptor for advanced operations.
> + *
> + * Returns: File descriptor, or -1 if handle is NULL.
> + */
> +int igt_serial_get_fd(struct igt_serial *s)
> +{
> +	return s ? s->fd : -1;
> +}
> diff --git a/lib/igt_serial.h b/lib/igt_serial.h
> new file mode 100644
> index 000000000..b460fbf16
> --- /dev/null
> +++ b/lib/igt_serial.h
> @@ -0,0 +1,32 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright © 2026 Intel Corporation
> + */
> +
> +#ifndef IGT_SERIAL_H
> +#define IGT_SERIAL_H
> +
> +#include <stdbool.h>
> +#include <stddef.h>
> +#include <sys/types.h>
> +
> +/**
> + * IGT_SERIAL_DEFAULT_TIMEOUT_MS:
> + *
> + * Default timeout for serial read operations in milliseconds.
> + */
> +#define IGT_SERIAL_DEFAULT_TIMEOUT_MS 1000
> +
> +struct igt_serial;
> +
> +struct igt_serial *igt_serial_open(const char *device, int baud_rate);
> +void igt_serial_close(struct igt_serial *s);
> +bool igt_serial_set_timeout(struct igt_serial *s, int timeout_ms);
> +bool igt_serial_send(struct igt_serial *s, const char *cmd);
> +ssize_t igt_serial_read(struct igt_serial *s, char *buf, size_t size);
> +bool igt_serial_command(struct igt_serial *s, const char *cmd,
> +			char *response, size_t resp_size);
> +void igt_serial_flush(struct igt_serial *s);
> +int igt_serial_get_fd(struct igt_serial *s);
> +
> +#endif /* IGT_SERIAL_H */
> diff --git a/lib/meson.build b/lib/meson.build
> index 074b21fdf..67b57533c 100644
> --- a/lib/meson.build
> +++ b/lib/meson.build
> @@ -123,6 +123,7 @@ lib_sources = [
>   	'igt_msm.c',
>   	'igt_dsc.c',
>   	'igt_hook.c',
> +	'igt_serial.c',
>   	'xe/xe_gt.c',
>   	'xe/xe_ioctl.c',
>   	'xe/xe_legacy.c',

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

* Re: [i-g-t,4/6] lib/igt_usb4_switch: add helper library for USB4 Switch 3141
  2026-02-25 21:28 ` [PATCH i-g-t 4/6] lib/igt_usb4_switch: add helper library for USB4 Switch 3141 Kunal Joshi
@ 2026-03-16  8:45   ` Murthy, Arun R
  0 siblings, 0 replies; 25+ messages in thread
From: Murthy, Arun R @ 2026-03-16  8:45 UTC (permalink / raw)
  To: Kunal Joshi, igt-dev

Looks Good.

Reviewed-by: Arun R Murthy <arun.r.murthy@intel.com>

Thanks and Regards,
Arun R Murthy
-------------------

On 26-02-2026 02:58, Kunal Joshi wrote:
> Add a control library for the Microsft USB4 Switch 3141 test equipment,
> used for automated USB4/Thunderbolt dock/undock testing:
>
>   - usb4switch_init()/deinit(): lifecycle with
>     .igtrc config or autodiscovery
>   - usb4switch_port_enable()/disable(): port control with optional HW delay
>   - usb4switch_get_active_port(): query current port state
>   - usb4switch_get_voltage_mv()/get_current_ma(): VBUS monitoring
>   - usb4switch_get_orientation(): USB-C cable orientation
>
> Signed-off-by: Kunal Joshi <kunal1.joshi@intel.com>
> ---
>   lib/igt_usb4_switch.c | 1055 +++++++++++++++++++++++++++++++++++++++++
>   lib/igt_usb4_switch.h |  157 ++++++
>   lib/meson.build       |    1 +
>   3 files changed, 1213 insertions(+)
>   create mode 100644 lib/igt_usb4_switch.c
>   create mode 100644 lib/igt_usb4_switch.h
>
> diff --git a/lib/igt_usb4_switch.c b/lib/igt_usb4_switch.c
> new file mode 100644
> index 000000000..5cede4d60
> --- /dev/null
> +++ b/lib/igt_usb4_switch.c
> @@ -0,0 +1,1055 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2026 Intel Corporation
> + */
> +
> +/**
> + * SECTION:igt_usb4_switch
> + * @short_description: USB4 Switch 3141 control library
> + * @title: USB4 Switch
> + * @include: igt_usb4_switch.h
> + *
> + * This library provides control and status functions for the Microsoft
> + * USB4 Switch 3141 test equipment, used for automated USB4/Thunderbolt
> + * dock/undock testing.
> + *
> + * The library handles serial communication, port control, and
> + * configuration parsing.
> + */
> +
> +#include <stdlib.h>
> +#include <string.h>
> +#include <strings.h>
> +#include <time.h>
> +#include <unistd.h>
> +
> +#include "igt_core.h"
> +#include "igt_rc.h"
> +#include "igt_serial.h"
> +#include "igt_usb4_switch.h"
> +#include "igt_connector_helper.h"
> +
> +struct usb4switch {
> +	struct igt_serial *serial;
> +
> +	/* Configuration */
> +	char *device_path;
> +	int hotplug_timeout_s;
> +	int iterations;
> +	int min_switch_interval_ms;
> +
> +	/* Timestamp of last port change for minimum interval enforcement */
> +	struct timespec last_port_change;
> +
> +	/* Port configuration */
> +	struct usb4switch_port ports[USB4_SWITCH_MAX_PORTS];
> +	int port_count;
> +};
> +
> +/* .igtrc section and key names */
> +#define USB4_SWITCH_SECTION "USB4Switch"
> +#define USB4_SWITCH_KEY_DEVICE "Device"
> +#define USB4_SWITCH_KEY_HOTPLUG_TIMEOUT "HotplugTimeout"
> +#define USB4_SWITCH_KEY_ITERATIONS "DockUndockIterations"
> +#define USB4_SWITCH_KEY_MIN_INTERVAL "MinSwitchInterval"
> +
> +/*
> + * response_is_ok - Check that a firmware response does not indicate an error.
> + *
> + * The 3141 prefixes error replies with "ERR" (e.g. "ERR: unknown command").
> + * An empty response after a successful transport exchange is also treated as
> + * failure because no meaningful control command produces an empty reply.
> + *
> + * This is a transport vs. command-level distinction: send_command() only
> + * guarantees that bytes were exchanged; callers that need to know whether
> + * the firmware actually accepted the command must call response_is_ok().
> + */
> +static bool response_is_ok(const char *response)
> +{
> +	if (!response || response[0] == '\0')
> +		return false;
> +
> +	if (strncasecmp(response, "ERR", 3) == 0)
> +		return false;
> +
> +	return true;
> +}
> +
> +/*
> + * Minimum-interval helpers - enforce a floor between successive port
> + * operations to protect hardware from rapid switching.
> + */
> +static void enforce_min_interval(struct usb4switch *sw)
> +{
> +	struct timespec now;
> +	int elapsed_ms;
> +
> +	if (sw->last_port_change.tv_sec == 0 &&
> +	    sw->last_port_change.tv_nsec == 0)
> +		return;
> +
> +	clock_gettime(CLOCK_MONOTONIC, &now);
> +	elapsed_ms = (now.tv_sec - sw->last_port_change.tv_sec) * 1000 +
> +		     (now.tv_nsec - sw->last_port_change.tv_nsec) / 1000000;
> +
> +	if (elapsed_ms < sw->min_switch_interval_ms) {
> +		int wait = sw->min_switch_interval_ms - elapsed_ms;
> +
> +		igt_debug("USB4Switch: enforcing %d ms minimum interval "
> +			  "(sleeping %d ms)\n",
> +			  sw->min_switch_interval_ms, wait);
> +		usleep(wait * 1000);
> +	}
> +}
> +
> +/**
> + * send_command:
> + * @sw: switch handle
> + * @cmd: command string (without line ending)
> + * @response: buffer for response
> + * @resp_size: size of response buffer
> + *
> + * Sends a command to the USB4 Switch 3141.
> + * Appends CRLF as required by the switch protocol.
> + *
> + * Note: success means the serial exchange completed and at least one byte
> + * was received. It does not validate the firmware response payload — callers
> + * that care about command-level success must check response_is_ok().
> + *
> + * Returns: true if the exchange succeeded, false on transport error.
> + */
> +static bool send_command(struct usb4switch *sw, const char *cmd,
> +			 char *response, size_t resp_size)
> +{
> +	char cmd_with_crlf[256];
> +	int len;
> +
> +	if (!sw || !sw->serial || !cmd)
> +		return false;
> +
> +	len = snprintf(cmd_with_crlf, sizeof(cmd_with_crlf), "%s\r\n", cmd);
> +	if (len < 0 || (size_t)len >= sizeof(cmd_with_crlf))
> +		return false;
> +
> +	return igt_serial_command(sw->serial, cmd_with_crlf,
> +				  response, resp_size);
> +}
> +
> +static bool verify_communication(struct usb4switch *sw)
> +{
> +	char response[256];
> +
> +	if (!send_command(sw, "version", response, sizeof(response))) {
> +		igt_debug("USB4Switch: Failed to query version\n");
> +		return false;
> +	}
> +
> +	if (!response_is_ok(response)) {
> +		igt_debug("USB4Switch: Version command rejected: '%s'\n",
> +			  response);
> +		return false;
> +	}
> +
> +	/*
> +	 * The device was already identified by VID:PID in
> +	 * discover_usb4_switch_device(). Here we just confirm the serial
> +	 * link is alive.  The firmware returns only its firmware version
> +	 * (e.g. "0201"), not the model number.
> +	 */
> +	igt_debug("USB4Switch: Version response: %s\n", response);
> +	return true;
> +}
> +
> +static char *get_config_string(const char *key)
> +{
> +	char *value = NULL;
> +	GError *error = NULL;
> +
> +	value = g_key_file_get_string(igt_key_file, USB4_SWITCH_SECTION,
> +				      key, &error);
> +	if (error) {
> +		g_error_free(error);
> +		return NULL;
> +	}
> +	return value;
> +}
> +
> +static int get_config_int(const char *key, int default_value)
> +{
> +	GError *error = NULL;
> +	int value;
> +
> +	value = g_key_file_get_integer(igt_key_file, USB4_SWITCH_SECTION,
> +				       key, &error);
> +	if (error) {
> +		g_error_free(error);
> +		return default_value;
> +	}
> +	return value;
> +}
> +
> +static void free_display_config(struct usb4switch_display *disp)
> +{
> +	free(disp->connector_path);
> +	disp->connector_path = NULL;
> +	free(disp->connector_name);
> +	disp->connector_name = NULL;
> +	free(disp->edid_serial);
> +	disp->edid_serial = NULL;
> +}
> +
> +static void free_port_config(struct usb4switch_port *port)
> +{
> +	int i;
> +
> +	free(port->name);
> +	for (i = 0; i < USB4_SWITCH_MAX_DISPLAYS_PER_PORT; i++)
> +		free_display_config(&port->displays[i]);
> +}
> +
> +static void free_config(struct usb4switch *sw)
> +{
> +	int i;
> +
> +	free(sw->device_path);
> +	for (i = 0; i < USB4_SWITCH_MAX_PORTS; i++)
> +		free_port_config(&sw->ports[i]);
> +}
> +
> +static void parse_display_config(struct usb4switch *sw, int port_idx,
> +				 int disp_idx)
> +{
> +	struct usb4switch_display *disp;
> +	char key[64];
> +
> +	disp = &sw->ports[port_idx].displays[disp_idx];
> +
> +	/* Path takes precedence for MST */
> +	snprintf(key, sizeof(key), "Port%d.Display%d.Path",
> +		 port_idx + 1, disp_idx + 1);
> +	disp->connector_path = get_config_string(key);
> +
> +	/* Connector name as fallback */
> +	snprintf(key, sizeof(key), "Port%d.Display%d.Connector",
> +		 port_idx + 1, disp_idx + 1);
> +	disp->connector_name = get_config_string(key);
> +
> +	/* EDID serial for verification */
> +	snprintf(key, sizeof(key), "Port%d.Display%d.EDIDSerial",
> +		 port_idx + 1, disp_idx + 1);
> +	disp->edid_serial = get_config_string(key);
> +}
> +
> +static void parse_port_config(struct usb4switch *sw, int port_idx)
> +{
> +	struct usb4switch_port *port;
> +	char key[64];
> +	int i;
> +
> +	port = &sw->ports[port_idx];
> +	port->port_num = port_idx + 1;
> +
> +	snprintf(key, sizeof(key), "Port%d.Name", port_idx + 1);
> +	port->name = get_config_string(key);
> +	if (!port->name) {
> +		port->name = malloc(16);
> +		if (port->name)
> +			snprintf(port->name, 16, "Port %d", port_idx + 1);
> +	}
> +
> +	/*
> +	 * Parse all display slots, then count the leading contiguous
> +	 * prefix.  display_count is the exact number of valid entries
> +	 * accessible via displays[0..display_count-1].
> +	 */
> +	for (i = 0; i < USB4_SWITCH_MAX_DISPLAYS_PER_PORT; i++)
> +		parse_display_config(sw, port_idx, i);
> +
> +	/* Count leading contiguous displays (Display1, Display2, ...) */
> +	port->display_count = 0;
> +	for (i = 0; i < USB4_SWITCH_MAX_DISPLAYS_PER_PORT; i++) {
> +		if (sw->ports[port_idx].displays[i].connector_path ||
> +		    sw->ports[port_idx].displays[i].connector_name)
> +			port->display_count++;
> +		else
> +			break;
> +	}
> +
> +	/* Warn about and free any sparse entries beyond the contiguous prefix */
> +	for (; i < USB4_SWITCH_MAX_DISPLAYS_PER_PORT; i++) {
> +		if (sw->ports[port_idx].displays[i].connector_path ||
> +		    sw->ports[port_idx].displays[i].connector_name) {
> +			igt_warn("USB4Switch: Port%d.Display%d configured "
> +				 "but Display%d is missing; displays must "
> +				 "be contiguous from 1 — ignoring\n",
> +				 port_idx + 1, i + 1,
> +				 port->display_count + 1);
> +			free_display_config(&sw->ports[port_idx].displays[i]);
> +		}
> +	}
> +}
> +
> +static bool parse_config(struct usb4switch *sw)
> +{
> +	int i;
> +
> +	sw->device_path = get_config_string(USB4_SWITCH_KEY_DEVICE);
> +	if (!sw->device_path) {
> +		igt_debug("USB4Switch: No Device configured\n");
> +		return false;
> +	}
> +
> +	sw->hotplug_timeout_s =
> +		get_config_int(USB4_SWITCH_KEY_HOTPLUG_TIMEOUT,
> +			       USB4_SWITCH_DEFAULT_HOTPLUG_TIMEOUT_S);
> +	sw->iterations =
> +		get_config_int(USB4_SWITCH_KEY_ITERATIONS,
> +			       USB4_SWITCH_DEFAULT_ITERATIONS);
> +	sw->min_switch_interval_ms =
> +		get_config_int(USB4_SWITCH_KEY_MIN_INTERVAL,
> +			       USB4_SWITCH_DEFAULT_MIN_INTERVAL_MS);
> +
> +	/*
> +	 * Count only leading contiguous ports that have at least one display.
> +	 * Stop at the first port with no displays — this enforces contiguous
> +	 * port numbering (Port1, Port2, ...) and means port_count is the exact
> +	 * number of valid ports accessible via ports[0..port_count-1].
> +	 */
> +	sw->port_count = 0;
> +	for (i = 0; i < USB4_SWITCH_MAX_PORTS; i++) {
> +		parse_port_config(sw, i);
> +		if (sw->ports[i].display_count > 0)
> +			sw->port_count++;
> +		else
> +			break;
> +	}
> +
> +	if (sw->port_count == 0)
> +		igt_warn("USB4Switch: Device configured but no display keys found\n");
> +
> +	igt_debug("USB4Switch: Device=%s, Timeout=%ds, Iterations=%d, Ports=%d\n",
> +		  sw->device_path, sw->hotplug_timeout_s, sw->iterations,
> +		  sw->port_count);
> +
> +	return true;
> +}
> +
> +static void stamp_port_change(struct usb4switch *sw)
> +{
> +	clock_gettime(CLOCK_MONOTONIC, &sw->last_port_change);
> +}
> +
> +static bool usb4switch_queue_port_change_delayed(struct usb4switch *sw,
> +						 int port,
> +						 int delay_seconds,
> +						 const char *action)
> +{
> +	char cmd[32];
> +	char response[256];
> +
> +	if (!sw)
> +		return false;
> +
> +	if (port < 0 || port > USB4_SWITCH_MAX_PORTS) {
> +		igt_warn("USB4Switch: Invalid port %d\n", port);
> +		return false;
> +	}
> +
> +	if (delay_seconds < 0 || delay_seconds > 3600) {
> +		igt_warn("USB4Switch: Invalid delay %d (must be 0-3600)\n",
> +			 delay_seconds);
> +		return false;
> +	}
> +
> +	enforce_min_interval(sw);
> +
> +	snprintf(cmd, sizeof(cmd), "delay %d", delay_seconds);
> +	if (!send_command(sw, cmd, response, sizeof(response))) {
> +		igt_warn("USB4Switch: Failed to set delay %d\n", delay_seconds);
> +		return false;
> +	}
> +
> +	if (!response_is_ok(response)) {
> +		igt_warn("USB4Switch: Failed to set delay %d (response: '%s')\n",
> +			 delay_seconds, response);
> +		return false;
> +	}
> +
> +	snprintf(cmd, sizeof(cmd), "port %d", port);
> +	if (!send_command(sw, cmd, response, sizeof(response))) {
> +		igt_warn("USB4Switch: Failed to queue %s command\n", action);
> +		return false;
> +	}
> +
> +	if (!response_is_ok(response)) {
> +		igt_warn("USB4Switch: Failed to queue %s command (response: '%s')\n",
> +			 action, response);
> +		return false;
> +	}
> +
> +	stamp_port_change(sw);
> +	igt_debug("USB4Switch: Queued %s with %ds delay\n",
> +		  action, delay_seconds);
> +
> +	return true;
> +}
> +
> +/*
> + * USB VID:PID for Microsoft USB4 Switch 3141
> + */
> +#define USB4_SWITCH_VID "045e"
> +#define USB4_SWITCH_PID "0646"
> +
> +/*
> + * Linux USB uevent PRODUCT= format uses lowercase hex without leading
> + * zeros: VID 0x045e → "45e", PID 0x0646 → "646".
> + */
> +#define USB4_SWITCH_UEVENT_MATCH "PRODUCT=45e/646/"
> +
> +/*
> + * When no .igtrc configuration is present, autodiscover:
> + * - USB4 switch device by scanning /sys/class/tty for matching VID:PID
> + * - Displays behind each port by comparing connectors before/after docking
> + */
> +static char *discover_usb4_switch_device(void)
> +{
> +	char path[256];
> +	char uevent[512];
> +	char *device_path = NULL;
> +	FILE *fp;
> +	int i;
> +
> +	/*
> +	 * Scan ttyACM0..63. The 3141 almost always lands in the low
> +	 * range, but the upper bound is generous to handle busy systems.
> +	 */
> +	for (i = 0; i < 64; i++) {
> +		snprintf(path, sizeof(path),
> +			 "/sys/class/tty/ttyACM%d/device/uevent", i);
> +
> +		fp = fopen(path, "r");
> +		if (!fp)
> +			continue;
> +
> +		while (fgets(uevent, sizeof(uevent), fp)) {
> +			if (strstr(uevent, USB4_SWITCH_UEVENT_MATCH)) {
> +				device_path = malloc(32);
> +				if (device_path)
> +					snprintf(device_path, 32,
> +						 "/dev/ttyACM%d", i);
> +				break;
> +			}
> +		}
> +
> +		fclose(fp);
> +		if (device_path)
> +			break;
> +	}
> +
> +	if (device_path)
> +		igt_debug("USB4Switch: Autodiscovered device at %s\n",
> +			  device_path);
> +	else
> +		igt_debug("USB4Switch: No device found during autodiscovery\n");
> +
> +	return device_path;
> +}
> +
> +/*
> + * discover_port_displays - Dock a port and compare connectors to find
> + * which displays appear. drm_fd is passed as parameter, NOT stored.
> + */
> +static bool discover_port_displays(struct usb4switch *sw, int drm_fd,
> +				   int port_num, uint32_t *before,
> +				   int before_count)
> +{
> +	struct usb4switch_port *port = &sw->ports[port_num - 1];
> +	uint32_t after[32];
> +	int after_count;
> +	char name[32];
> +	char serial[64];
> +	int i, j, wait;
> +	bool found;
> +
> +	if (!usb4switch_port_enable(sw, port_num)) {
> +		igt_debug("USB4Switch: Failed to enable port %d\n", port_num);
> +		return false;
> +	}
> +
> +	igt_debug("USB4Switch: Waiting for port %d displays...\n", port_num);
> +	/* Poll for new connectors (max 10s) instead of fixed sleep */
> +	after_count = 0;
> +	for (wait = 0; wait < 10; wait++) {
> +		sleep(1);
> +		igt_connector_reprobe_all(drm_fd);
> +		after_count = igt_connector_get_connected(drm_fd, after, 32);
> +		if (after_count > before_count)
> +			break;
> +	}
> +
> +	if (after_count <= before_count) {
> +		igt_debug("USB4Switch: No new connectors detected on port %d\n",
> +			  port_num);
> +		usb4switch_port_disable_and_wait(sw);
> +		return false;
> +	}
> +
> +	port->port_num = port_num;
> +	port->name = malloc(16);
> +	if (port->name)
> +		snprintf(port->name, 16, "port-%d", port_num);
> +	port->display_count = 0;
> +
> +	for (i = 0; i < after_count; i++) {
> +		found = false;
> +		for (j = 0; j < before_count; j++) {
> +			if (after[i] == before[j]) {
> +				found = true;
> +				break;
> +			}
> +		}
> +
> +		if (!found &&
> +		    port->display_count < USB4_SWITCH_MAX_DISPLAYS_PER_PORT) {
> +			char path[256];
> +
> +			if (igt_connector_get_info(drm_fd, after[i],
> +						   name, sizeof(name),
> +						   serial, sizeof(serial),
> +						   path, sizeof(path))) {
> +				struct usb4switch_display *disp;
> +
> +				disp = &port->displays[port->display_count];
> +				disp->connector_name = strdup(name);
> +				if (!disp->connector_name)
> +					continue;
> +				disp->edid_serial = serial[0] ?
> +						    strdup(serial) : NULL;
> +				disp->connector_path = path[0] ?
> +						       strdup(path) : NULL;
> +
> +				igt_info("USB4Switch: Port %d Display %d: %s (EDID: %s)\n",
> +					 port_num, port->display_count + 1,
> +					 name,
> +					 serial[0] ? serial : "none");
> +
> +				port->display_count++;
> +			}
> +		}
> +	}
> +
> +	usb4switch_port_disable_and_wait(sw);
> +	igt_connector_reprobe_all(drm_fd);
> +
> +	if (port->display_count > 0)
> +		sw->port_count++;
> +
> +	return port->display_count > 0;
> +}
> +
> +/*
> + * autodiscover_config - Autodiscover switch device and port displays.
> + */
> +static bool autodiscover_config(struct usb4switch *sw, int drm_fd)
> +{
> +	uint32_t before[32];
> +	int before_count;
> +	int p;
> +
> +	sw->device_path = discover_usb4_switch_device();
> +	if (!sw->device_path)
> +		return false;
> +
> +	sw->hotplug_timeout_s = USB4_SWITCH_DEFAULT_HOTPLUG_TIMEOUT_S;
> +	sw->iterations = USB4_SWITCH_DEFAULT_ITERATIONS;
> +	sw->min_switch_interval_ms = USB4_SWITCH_DEFAULT_MIN_INTERVAL_MS;
> +	sw->port_count = 0;
> +
> +	sw->serial = igt_serial_open(sw->device_path, 115200);
> +	if (!sw->serial) {
> +		igt_debug("USB4Switch: Failed to open autodiscovered device %s\n",
> +			  sw->device_path);
> +		free(sw->device_path);
> +		sw->device_path = NULL;
> +		return false;
> +	}
> +
> +	if (!verify_communication(sw)) {
> +		igt_serial_close(sw->serial);
> +		sw->serial = NULL;
> +		free(sw->device_path);
> +		sw->device_path = NULL;
> +		return false;
> +	}
> +
> +	igt_info("USB4Switch: Autodiscovering displays...\n");
> +
> +	usb4switch_port_disable_and_wait(sw);
> +
> +	igt_connector_reprobe_all(drm_fd);
> +
> +	before_count = igt_connector_get_connected(drm_fd, before, 32);
> +	if (before_count >= 32)
> +		igt_warn("USB4Switch: Connector count %d may exceed array size\n",
> +			 before_count);
> +	igt_debug("USB4Switch: %d connectors before autodiscovery\n",
> +		  before_count);
> +
> +	/*
> +	 * Probe ports sequentially. Stop at the first port that yields no
> +	 * displays — same contiguity rule as config-based port counting.
> +	 */
> +	for (p = 1; p <= USB4_SWITCH_MAX_PORTS; p++) {
> +		if (!discover_port_displays(sw, drm_fd, p, before, before_count))
> +			break;
> +	}
> +
> +	usb4switch_port_disable(sw);
> +
> +	igt_info("USB4Switch: Autodiscovery complete - %d ports with displays\n",
> +		 sw->port_count);
> +
> +	return sw->port_count > 0;
> +}
> +
> +/**
> + * usb4switch_init:
> + * @drm_fd: DRM file descriptor (used only for autodiscovery, not stored)
> + *
> + * Initializes USB4 switch from .igtrc configuration.
> + * If no configuration is present, attempts
> + * autodiscovery of the switch device and displays behind each port.
> + *
> + * Returns: Switch handle on success, NULL on failure.
> + */
> +struct usb4switch *usb4switch_init(int drm_fd)
> +{
> +	struct usb4switch *sw;
> +	bool config_ok;
> +
> +	sw = calloc(1, sizeof(*sw));
> +	if (!sw)
> +		return NULL;
> +
> +	config_ok = parse_config(sw);
> +
> +	if (!config_ok) {
> +		if (drm_fd < 0) {
> +			igt_debug("USB4Switch: No config and no DRM fd for autodiscovery\n");
> +			free_config(sw);
> +			free(sw);
> +			return NULL;
> +		}
> +
> +		igt_info("USB4Switch: No configuration found, attempting autodiscovery...\n");
> +		if (!autodiscover_config(sw, drm_fd)) {
> +			igt_debug("USB4Switch: Autodiscovery failed\n");
> +			if (sw->serial)
> +				igt_serial_close(sw->serial);
> +			free_config(sw);
> +			free(sw);
> +			return NULL;
> +		}
> +		igt_info("USB4Switch: Initialized via autodiscovery (Model 3141)\n");
> +		return sw;
> +	}
> +
> +	sw->serial = igt_serial_open(sw->device_path, 115200);
> +	if (!sw->serial) {
> +		igt_debug("USB4Switch: Failed to open serial port %s\n",
> +			  sw->device_path);
> +		free_config(sw);
> +		free(sw);
> +		return NULL;
> +	}
> +
> +	if (!verify_communication(sw)) {
> +		igt_serial_close(sw->serial);
> +		free_config(sw);
> +		free(sw);
> +		return NULL;
> +	}
> +
> +	igt_info("USB4Switch: Initialized (Model 3141)\n");
> +	return sw;
> +}
> +
> +/**
> + * usb4switch_deinit:
> + * @sw: switch handle
> + *
> + * Closes the switch and frees resources.
> + * Disables all ports before closing.
> + */
> +void usb4switch_deinit(struct usb4switch *sw)
> +{
> +	if (!sw)
> +		return;
> +
> +	usb4switch_port_disable(sw);
> +
> +	if (sw->serial)
> +		igt_serial_close(sw->serial);
> +	free_config(sw);
> +	free(sw);
> +
> +	igt_debug("USB4Switch: Deinitialized\n");
> +}
> +
> +/**
> + * usb4switch_port_enable:
> + * @sw: switch handle
> + * @port: port number (1 or 2)
> + *
> + * Enables the specified port.
> + *
> + * Returns: true on success, false on failure.
> + */
> +bool usb4switch_port_enable(struct usb4switch *sw, int port)
> +{
> +	char cmd[32];
> +	char response[256];
> +
> +	if (!sw || port < 1 || port > USB4_SWITCH_MAX_PORTS)
> +		return false;
> +
> +	enforce_min_interval(sw);
> +
> +	snprintf(cmd, sizeof(cmd), "port %d", port);
> +
> +	if (!send_command(sw, cmd, response, sizeof(response))) {
> +		igt_warn("USB4Switch: Failed to enable port %d\n", port);
> +		return false;
> +	}
> +	if (!response_is_ok(response)) {
> +		igt_warn("USB4Switch: Failed to enable port %d (response: '%s')\n",
> +			 port, response);
> +		return false;
> +	}
> +
> +	stamp_port_change(sw);
> +	igt_debug("USB4Switch: Enabled port %d\n", port);
> +	return true;
> +}
> +
> +/**
> + * usb4switch_port_enable_delayed:
> + * @sw: switch handle
> + * @port: port number (1 or 2)
> + * @delay_seconds: delay in seconds before port change executes
> + *
> + * Schedules a port enable after the specified delay using the hardware
> + * delay command on Model 3141. Useful for hotplug-during-suspend tests.
> + *
> + * Returns: true on success, false on failure.
> + */
> +bool usb4switch_port_enable_delayed(struct usb4switch *sw, int port,
> +				    int delay_seconds)
> +{
> +	return usb4switch_queue_port_change_delayed(sw, port, delay_seconds,
> +						    "port enable");
> +}
> +
> +/**
> + * usb4switch_port_disable_delayed:
> + * @sw: switch handle
> + * @delay_seconds: delay in seconds before port disable executes
> + *
> + * Schedules a port disable (undock) after the specified delay.
> + * Useful for undock-during-suspend tests.
> + *
> + * Returns: true on success, false on failure.
> + */
> +bool usb4switch_port_disable_delayed(struct usb4switch *sw, int delay_seconds)
> +{
> +	return usb4switch_queue_port_change_delayed(sw, 0, delay_seconds,
> +						    "port disable");
> +}
> +
> +/**
> + * usb4switch_port_disable:
> + * @sw: switch handle
> + *
> + * Disables all ports.
> + *
> + * Returns: true on success, false on failure.
> + */
> +bool usb4switch_port_disable(struct usb4switch *sw)
> +{
> +	char response[256];
> +
> +	if (!sw)
> +		return false;
> +
> +	enforce_min_interval(sw);
> +
> +	if (!send_command(sw, "port 0", response, sizeof(response))) {
> +		igt_warn("USB4Switch: Failed to disable ports\n");
> +		return false;
> +	}
> +	if (!response_is_ok(response)) {
> +		igt_warn("USB4Switch: Failed to disable ports (response: '%s')\n",
> +			 response);
> +		return false;
> +	}
> +
> +	stamp_port_change(sw);
> +	igt_debug("USB4Switch: Disabled all ports\n");
> +	return true;
> +}
> +
> +/**
> + * usb4switch_get_active_port:
> + * @sw: switch handle
> + *
> + * Gets currently active port.
> + *
> + * Returns: Port number (1 or 2), 0 if disabled, -1 on error.
> + */
> +int usb4switch_get_active_port(struct usb4switch *sw)
> +{
> +	char response[256];
> +	int port;
> +
> +	if (!sw)
> +		return -1;
> +
> +	if (!send_command(sw, "port ?", response, sizeof(response)))
> +		return -1;
> +
> +	if (!response_is_ok(response)) {
> +		igt_warn("USB4Switch: Port query rejected: '%s'\n", response);
> +		return -1;
> +	}
> +
> +	if (sscanf(response, "port: %d", &port) == 1 ||
> +	    sscanf(response, "port %d", &port) == 1 ||
> +	    sscanf(response, "%d", &port) == 1)
> +		return port;
> +
> +	igt_warn("USB4Switch: Could not parse port response: '%s'\n",
> +		 response);
> +	return -1;
> +}
> +
> +/**
> + * usb4switch_get_status:
> + * @sw: switch handle
> + * @buf: buffer for status
> + * @size: buffer size
> + *
> + * Gets full status from switch.
> + *
> + * Returns: true on success.
> + */
> +bool usb4switch_get_status(struct usb4switch *sw, char *buf, size_t size)
> +{
> +	if (!sw || !buf || size == 0)
> +		return false;
> +
> +	if (!send_command(sw, "status", buf, size))
> +		return false;
> +
> +	return response_is_ok(buf);
> +}
> +
> +/**
> + * usb4switch_get_voltage_mv:
> + * @sw: switch handle
> + *
> + * Gets VBUS voltage by sending the "volts" command.
> + * The 3141 firmware responds with "X.XX V" (e.g. "4.85 V").
> + *
> + * Note: The 3141 hardware may not have accurate VBUS sense circuitry.
> + * Voltage readback may not be meaningful on all units.
> + *
> + * Returns: Voltage in mV, -1 on error.
> + */
> +int usb4switch_get_voltage_mv(struct usb4switch *sw)
> +{
> +	char response[256];
> +	float volts;
> +
> +	if (!sw)
> +		return -1;
> +
> +	if (!send_command(sw, "volts", response, sizeof(response)))
> +		return -1;
> +
> +	if (sscanf(response, "%f", &volts) == 1)
> +		return (int)(volts * 1000);
> +
> +	return -1;
> +}
> +
> +/**
> + * usb4switch_get_current_ma:
> + * @sw: switch handle
> + *
> + * Gets VBUS current by sending the "amps" command.
> + * The 3141 firmware responds with "XXX mA" (e.g. "125 mA").
> + *
> + * Note: The 3141 hardware may not have accurate current sense circuitry.
> + *
> + * Returns: Current in mA, -1 on error.
> + */
> +int usb4switch_get_current_ma(struct usb4switch *sw)
> +{
> +	char response[256];
> +	int current;
> +
> +	if (!sw)
> +		return -1;
> +
> +	if (!send_command(sw, "amps", response, sizeof(response)))
> +		return -1;
> +
> +	if (sscanf(response, "%d", &current) == 1)
> +		return current;
> +
> +	return -1;
> +}
> +
> +/**
> + * usb4switch_wait_vbus_safe:
> + * @sw: switch handle
> + * @timeout_ms: maximum time to wait in milliseconds
> + *
> + * Waits for VBUS voltage to drop below the Vsafe0V threshold (800 mV)
> + * after a port disable. Polls using the "volts" command. If voltage
> + * readback is not supported or returns errors, falls back to a fixed
> + * 1-second delay.
> + *
> + * Returns: true when VBUS is safe (or after fallback delay).
> + */
> +bool usb4switch_wait_vbus_safe(struct usb4switch *sw, int timeout_ms)
> +{
> +	int elapsed = 0;
> +	int mv = -1;
> +
> +	if (!sw)
> +		return false;
> +
> +	while (elapsed < timeout_ms) {
> +		mv = usb4switch_get_voltage_mv(sw);
> +		if (mv < 0) {
> +			/* Voltage readback not supported; use fixed delay */
> +			igt_debug("USB4Switch: voltage readback failed, "
> +				  "using 1s fallback delay\n");
> +			sleep(1);
> +			return true;
> +		}
> +		if (mv < USB4_SWITCH_VBUS_SAFE_MV) {
> +			igt_debug("USB4Switch: VBUS safe at %d mV\n", mv);
> +			return true;
> +		}
> +		usleep(USB4_SWITCH_VBUS_SAFE_POLL_MS * 1000);
> +		elapsed += USB4_SWITCH_VBUS_SAFE_POLL_MS;
> +	}
> +
> +	igt_warn("USB4Switch: VBUS still at %d mV after %d ms\n",
> +		 mv, timeout_ms);
> +	return false;
> +}
> +
> +/**
> + * usb4switch_port_disable_and_wait:
> + * @sw: switch handle
> + *
> + * Disables all ports and waits for VBUS to reach safe levels.
> + *
> + * Returns: true on success.
> + */
> +bool usb4switch_port_disable_and_wait(struct usb4switch *sw)
> +{
> +	if (!usb4switch_port_disable(sw))
> +		return false;
> +
> +	return usb4switch_wait_vbus_safe(sw, USB4_SWITCH_VBUS_SAFE_TIMEOUT_MS);
> +}
> +
> +/**
> + * usb4switch_port_switch:
> + * @sw: switch handle
> + * @new_port: target port number (1..MAX_PORTS)
> + *
> + * Safely switches from the currently active port to @new_port.
> + * If another port is active, disables it first and waits for VBUS
> + * discharge before enabling the new port. If @new_port is already
> + * active, this is a no-op.
> + *
> + * Returns: true on success.
> + */
> +bool usb4switch_port_switch(struct usb4switch *sw, int new_port)
> +{
> +	int active;
> +
> +	if (!sw || new_port < 1 || new_port > USB4_SWITCH_MAX_PORTS)
> +		return false;
> +
> +	active = usb4switch_get_active_port(sw);
> +
> +	if (active == new_port) {
> +		igt_debug("USB4Switch: Port %d already active\n", new_port);
> +		return true;
> +	}
> +
> +	if (active > 0) {
> +		igt_debug("USB4Switch: Disabling port %d before switching "
> +			  "to port %d\n", active, new_port);
> +		if (!usb4switch_port_disable_and_wait(sw))
> +			return false;
> +	}
> +
> +	return usb4switch_port_enable(sw, new_port);
> +}
> +
> +/**
> + * usb4switch_get_port_config:
> + * @sw: switch handle
> + * @port_index: port index (0-based)
> + *
> + * Returns: Pointer to port config, NULL if invalid.
> + */
> +const struct usb4switch_port *usb4switch_get_port_config(struct usb4switch *sw,
> +							 int port_index)
> +{
> +	if (!sw || port_index < 0 || port_index >= sw->port_count)
> +		return NULL;
> +
> +	return &sw->ports[port_index];
> +}
> +
> +/**
> + * usb4switch_get_port_count:
> + * @sw: switch handle
> + *
> + * Returns: Number of configured ports.
> + */
> +int usb4switch_get_port_count(struct usb4switch *sw)
> +{
> +	return sw ? sw->port_count : 0;
> +}
> +
> +/**
> + * usb4switch_get_hotplug_timeout:
> + * @sw: switch handle
> + *
> + * Returns: Hotplug timeout in seconds.
> + */
> +int usb4switch_get_hotplug_timeout(struct usb4switch *sw)
> +{
> +	return sw ? sw->hotplug_timeout_s :
> +		    USB4_SWITCH_DEFAULT_HOTPLUG_TIMEOUT_S;
> +}
> +
> +/**
> + * usb4switch_get_iterations:
> + * @sw: switch handle
> + *
> + * Returns: Configured iterations.
> + */
> +int usb4switch_get_iterations(struct usb4switch *sw)
> +{
> +	return sw ? sw->iterations : USB4_SWITCH_DEFAULT_ITERATIONS;
> +}
> diff --git a/lib/igt_usb4_switch.h b/lib/igt_usb4_switch.h
> new file mode 100644
> index 000000000..5f1a0d334
> --- /dev/null
> +++ b/lib/igt_usb4_switch.h
> @@ -0,0 +1,157 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright © 2026 Intel Corporation
> + */
> +
> +#ifndef IGT_USB4_SWITCH_H
> +#define IGT_USB4_SWITCH_H
> +
> +#include <stdbool.h>
> +#include <stddef.h>
> +#include <stdint.h>
> +
> +/**
> + * USB4_SWITCH_MODEL_3141:
> + *
> + * Model number for Switch 3141.
> + */
> +#define USB4_SWITCH_MODEL_3141 3141
> +
> +/**
> + * USB4_SWITCH_MAX_PORTS:
> + *
> + * Maximum number of ports on the switch.
> + */
> +#define USB4_SWITCH_MAX_PORTS 2
> +
> +/**
> + * USB4_SWITCH_MAX_DISPLAYS_PER_PORT:
> + *
> + * Maximum displays per port (for MST hubs).
> + */
> +#define USB4_SWITCH_MAX_DISPLAYS_PER_PORT 4
> +
> +/**
> + * USB4_SWITCH_RESPONSE_MAX_LEN:
> + *
> + * Recommended buffer size for usb4switch_get_status() callers.
> + * Internal commands use smaller buffers since responses are short.
> + */
> +#define USB4_SWITCH_RESPONSE_MAX_LEN 1024
> +
> +/**
> + * USB4_SWITCH_DEFAULT_TIMEOUT_MS:
> + *
> + * Default command timeout in milliseconds.
> + */
> +#define USB4_SWITCH_DEFAULT_TIMEOUT_MS 2000
> +
> +/**
> + * USB4_SWITCH_DEFAULT_HOTPLUG_TIMEOUT_S:
> + *
> + * Default hotplug wait timeout in seconds.
> + */
> +#define USB4_SWITCH_DEFAULT_HOTPLUG_TIMEOUT_S 10
> +
> +/**
> + * USB4_SWITCH_DEFAULT_ITERATIONS:
> + *
> + * Default dock/undock iterations.
> + */
> +#define USB4_SWITCH_DEFAULT_ITERATIONS 3
> +
> +/**
> + * USB4_SWITCH_VBUS_SAFE_MV:
> + *
> + * VBUS voltage threshold in mV below which VBUS is considered safe
> + * (Vsafe0V per USB PD specification).
> + */
> +#define USB4_SWITCH_VBUS_SAFE_MV 800
> +
> +/**
> + * USB4_SWITCH_VBUS_SAFE_TIMEOUT_MS:
> + *
> + * Maximum time in milliseconds to wait for VBUS to discharge to safe levels.
> + */
> +#define USB4_SWITCH_VBUS_SAFE_TIMEOUT_MS 3000
> +
> +/**
> + * USB4_SWITCH_VBUS_SAFE_POLL_MS:
> + *
> + * Polling interval in milliseconds when waiting for VBUS discharge.
> + */
> +#define USB4_SWITCH_VBUS_SAFE_POLL_MS 100
> +
> +/**
> + * USB4_SWITCH_DEFAULT_MIN_INTERVAL_MS:
> + *
> + * Default minimum interval in milliseconds between successive port
> + * operations.  Matches Cricket UI's 1-second safety guard.
> + */
> +#define USB4_SWITCH_DEFAULT_MIN_INTERVAL_MS 1000
> +
> +/**
> + * struct usb4switch_display:
> + * @connector_path: MST PATH property (e.g., "mst:5-2-8"), preferred for MST
> + * @connector_name: Fallback connector name (e.g., "DP-6") for non-MST
> + * @edid_serial: Expected EDID serial string for verification
> + *
> + * Configuration for an expected display on a switch port.
> + * For MST displays, use connector_path which is stable across hotplug.
> + * For non-MST displays, connector_name can be used.
> + */
> +struct usb4switch_display {
> +	char *connector_path;
> +	char *connector_name;
> +	char *edid_serial;
> +};
> +
> +/**
> + * struct usb4switch_port:
> + * @port_num: Port number (1 or 2)
> + * @name: Human-readable port name
> + * @displays: Array of expected displays on this port
> + * @display_count: Number of displays configured
> + *
> + * Configuration for a switch port.
> + */
> +struct usb4switch_port {
> +	int port_num;
> +	char *name;
> +	struct usb4switch_display displays[USB4_SWITCH_MAX_DISPLAYS_PER_PORT];
> +	int display_count;
> +};
> +
> +struct usb4switch;
> +
> +/* Lifecycle */
> +struct usb4switch *usb4switch_init(int drm_fd);
> +void usb4switch_deinit(struct usb4switch *sw);
> +
> +/* Port control */
> +bool usb4switch_port_enable(struct usb4switch *sw, int port);
> +bool usb4switch_port_enable_delayed(struct usb4switch *sw, int port,
> +				    int delay_seconds);
> +bool usb4switch_port_disable(struct usb4switch *sw);
> +bool usb4switch_port_disable_delayed(struct usb4switch *sw,
> +				     int delay_seconds);
> +
> +/* VBUS safety */
> +bool usb4switch_wait_vbus_safe(struct usb4switch *sw, int timeout_ms);
> +bool usb4switch_port_disable_and_wait(struct usb4switch *sw);
> +bool usb4switch_port_switch(struct usb4switch *sw, int new_port);
> +
> +/* Status queries */
> +int usb4switch_get_active_port(struct usb4switch *sw);
> +bool usb4switch_get_status(struct usb4switch *sw, char *buf, size_t size);
> +int usb4switch_get_voltage_mv(struct usb4switch *sw);
> +int usb4switch_get_current_ma(struct usb4switch *sw);
> +
> +/* Configuration getters */
> +const struct usb4switch_port *usb4switch_get_port_config(struct usb4switch *sw,
> +							 int port_index);
> +int usb4switch_get_port_count(struct usb4switch *sw);
> +int usb4switch_get_hotplug_timeout(struct usb4switch *sw);
> +int usb4switch_get_iterations(struct usb4switch *sw);
> +
> +#endif /* IGT_USB4_SWITCH_H */
> diff --git a/lib/meson.build b/lib/meson.build
> index 67b57533c..d03bef209 100644
> --- a/lib/meson.build
> +++ b/lib/meson.build
> @@ -124,6 +124,7 @@ lib_sources = [
>   	'igt_dsc.c',
>   	'igt_hook.c',
>   	'igt_serial.c',
> +	'igt_usb4_switch.c',
>   	'xe/xe_gt.c',
>   	'xe/xe_ioctl.c',
>   	'xe/xe_legacy.c',

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

* [PATCH i-g-t 1/6] lib/igt_edid: add EDID serial extraction helpers
  2026-04-09  4:37 [PATCH i-g-t 0/6] add test to validate dock/undock and switch Kunal Joshi
@ 2026-04-09  4:37 ` Kunal Joshi
  0 siblings, 0 replies; 25+ messages in thread
From: Kunal Joshi @ 2026-04-09  4:37 UTC (permalink / raw)
  To: igt-dev; +Cc: Kunal Joshi, Arun R Murthy

Add helpers to extract serial identification from EDID data.

 - edid_get_serial_string(): extract ASCII serial from descriptor 0xFF
 - edid_get_serial_number(): extract 32-bit serial from EDID header
 - edid_get_any_serial(): convenience helper that tries ASCII serial
   first, then falls back to 32-bit header serial formatted as hex

These are needed by the connector helper and USB4 switch test suite
for EDID-based display verification after dock/undock events.

Signed-off-by: Kunal Joshi <kunal1.joshi@intel.com>
Reviewed-by: Arun R Murthy <arun.r.murthy@gmail.com>
---
 lib/igt_edid.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/igt_edid.h |  5 +++
 2 files changed, 96 insertions(+)

diff --git a/lib/igt_edid.c b/lib/igt_edid.c
index c68ccf671..e7fcbf0b9 100644
--- a/lib/igt_edid.c
+++ b/lib/igt_edid.c
@@ -249,6 +249,97 @@ void edid_get_monitor_name(const struct edid *edid, char *name, size_t name_size
 	name[0] = '\0';
 }
 
+/**
+ * edid_get_serial_string:
+ * @edid: EDID structure
+ * @serial: buffer to write serial string
+ * @serial_size: size of serial buffer; must be > 1
+ *
+ * Extract the serial string from EDID descriptor block type 0xFF.
+ * The descriptor payload is a 13-byte fixed-width field; trailing
+ * whitespace is stripped and the result is NUL-terminated.
+ * @serial is left empty when no 0xFF descriptor is found.
+ */
+void edid_get_serial_string(const struct edid *edid,
+			    char *serial, size_t serial_size)
+{
+	size_t copy_len, i, n;
+
+	igt_assert(edid);
+	igt_assert(serial);
+	igt_assert(serial_size > 1);
+	serial[0] = '\0';
+
+	for (i = 0; i < DETAILED_TIMINGS_LEN; i++) {
+		const uint8_t *d = (const uint8_t *)&edid->detailed_timings[i];
+
+		if (d[0] != 0x00 || d[1] != 0x00 || d[2] != 0x00)
+			continue;
+
+		if (d[3] != EDID_DETAIL_MONITOR_SERIAL || d[4] != 0x00)
+			continue;
+
+		/* Descriptor string payload is 13 bytes starting at d[5] */
+		copy_len = serial_size - 1 < 13 ? serial_size - 1 : 13;
+		memcpy(serial, &d[5], copy_len);
+		serial[copy_len] = '\0';
+
+		for (n = strlen(serial);
+		     n > 0 && isspace((unsigned char)serial[n - 1]); n--)
+			serial[n - 1] = '\0';
+
+		return;
+	}
+}
+
+/**
+ * edid_get_serial_number:
+ * @edid: EDID structure
+ *
+ * Extract the 32-bit serial number from the EDID base block header
+ * (bytes 12–15, the manufacturer/product section).  This is different
+ * from the ASCII serial string in descriptor block 0xFF.
+ *
+ * Returns: 32-bit serial number (little-endian), 0 if absent.
+ */
+uint32_t edid_get_serial_number(const struct edid *edid)
+{
+	return (uint32_t)edid->serial[0] |
+	       ((uint32_t)edid->serial[1] << 8) |
+	       ((uint32_t)edid->serial[2] << 16) |
+	       ((uint32_t)edid->serial[3] << 24);
+}
+
+/**
+ * edid_get_any_serial:
+ * @edid: EDID structure
+ * @serial: buffer to write serial string
+ * @serial_size: size of serial buffer; must be > 1
+ *
+ * Convenience helper that tries to extract a serial identifier from EDID.
+ * First tries the ASCII serial string descriptor (0xFF). If that is empty,
+ * falls back to the 32-bit header serial number formatted as 8-char hex.
+ * If neither source provides a usable serial (no 0xFF descriptor and the
+ * header serial is 0), @serial is left empty.
+ */
+void edid_get_any_serial(const struct edid *edid,
+			 char *serial, size_t serial_size)
+{
+	uint32_t serial_num;
+
+	igt_assert(edid);
+	igt_assert(serial);
+	igt_assert(serial_size > 1);
+
+	edid_get_serial_string(edid, serial, serial_size);
+	if (serial[0])
+		return;
+
+	serial_num = edid_get_serial_number(edid);
+	if (serial_num != 0)
+		snprintf(serial, serial_size, "%08X", serial_num);
+}
+
 static void edid_set_mfg(struct edid *edid, const char mfg[static 3])
 {
 	edid->mfg_id[0] = (mfg[0] - '@') << 2 | (mfg[1] - '@') >> 3;
diff --git a/lib/igt_edid.h b/lib/igt_edid.h
index be0ccf529..d9e396065 100644
--- a/lib/igt_edid.h
+++ b/lib/igt_edid.h
@@ -457,5 +457,10 @@ void *dispid_block_tiled(void *ptr,
 			 int hsize, int vsize,
 			 const char *topology_id);
 void edid_get_monitor_name(const struct edid *edid, char *name, size_t name_size);
+void edid_get_serial_string(const struct edid *edid,
+			    char *serial, size_t serial_size);
+uint32_t edid_get_serial_number(const struct edid *edid);
+void edid_get_any_serial(const struct edid *edid,
+			 char *serial, size_t serial_size);
 
 #endif
-- 
2.25.1


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

end of thread, other threads:[~2026-04-09  4:16 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-25 21:28 [PATCH i-g-t 0/6] add test to validate dock/undock and switch Kunal Joshi
2026-02-25 21:28 ` [PATCH i-g-t 1/6] lib/igt_edid: add EDID serial extraction helpers Kunal Joshi
2026-03-09  9:30   ` [i-g-t,1/6] " Murthy, Arun R
2026-03-09 11:02     ` Joshi, Kunal1
2026-03-16  3:03       ` Murthy, Arun R
2026-02-25 21:28 ` [PATCH i-g-t 2/6] lib/igt_connector_helper: Add generic connector helpers Kunal Joshi
2026-03-09  9:38   ` [i-g-t,2/6] " Murthy, Arun R
2026-03-09 11:06     ` Joshi, Kunal1
2026-03-16  3:17       ` Murthy, Arun R
2026-02-25 21:28 ` [PATCH i-g-t 3/6] lib/igt_serial: add generic serial communication helper Kunal Joshi
2026-03-16  5:40   ` [i-g-t,3/6] " Murthy, Arun R
2026-02-25 21:28 ` [PATCH i-g-t 4/6] lib/igt_usb4_switch: add helper library for USB4 Switch 3141 Kunal Joshi
2026-03-16  8:45   ` [i-g-t,4/6] " Murthy, Arun R
2026-02-25 21:28 ` [PATCH i-g-t 5/6] tests/kms_feature_discovery: add basic usb4 switch discovery Kunal Joshi
2026-03-09 10:05   ` [i-g-t,5/6] " Murthy, Arun R
2026-02-25 21:28 ` [PATCH i-g-t 6/6] tests/intel/kms_usb4_switch: Add USB4 switch test suite Kunal Joshi
2026-03-09 10:03   ` [i-g-t,6/6] " Murthy, Arun R
2026-03-09 11:14     ` Joshi, Kunal1
2026-03-16  3:38       ` Murthy, Arun R
2026-02-26  2:20 ` ✗ Xe.CI.BAT: failure for add test to validate dock/undock and switch (rev3) Patchwork
2026-02-26  3:04 ` ✓ i915.CI.BAT: success " Patchwork
2026-02-26  6:52 ` ✗ Xe.CI.FULL: failure " Patchwork
2026-02-26  7:45 ` ✗ i915.CI.Full: " Patchwork
  -- strict thread matches above, loose matches on Subject: below --
2026-04-09  4:37 [PATCH i-g-t 0/6] add test to validate dock/undock and switch Kunal Joshi
2026-04-09  4:37 ` [PATCH i-g-t 1/6] lib/igt_edid: add EDID serial extraction helpers Kunal Joshi
2026-02-25 19:42 [PATCH i-g-t 0/6] add test to validate dock/undock and switch Kunal Joshi
2026-02-25 19:42 ` [PATCH i-g-t 1/6] lib/igt_edid: add EDID serial extraction helpers Kunal Joshi

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