Igt-dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Louis Chauvet <louis.chauvet@bootlin.com>
To: igt-dev@lists.freedesktop.org, ihf@google.com,
	markyacoub@google.com,  thomas.petazzoni@bootlin.com,
	jeremie.dautheribes@bootlin.com
Cc: Louis Chauvet <louis.chauvet@bootlin.com>
Subject: [PATCH i-g-t v2 29/39] lib/chamelium/v3: Implement Chamelium port autodetection algorithm
Date: Tue, 09 Jul 2024 17:34:45 +0200	[thread overview]
Message-ID: <20240709-dev-remove-static-ports-v2-29-5adfc6985778@bootlin.com> (raw)
In-Reply-To: <20240709-dev-remove-static-ports-v2-0-5adfc6985778@bootlin.com>

To streamline the usage of Chamelium, this commit introduces an
autodetection algorithm. Please note that the algorithm may be somewhat
slow, as it needs to identify each port individually.

Note for future contributors: As of now, the RPC call IsPhysicalConnected
is known to be broken. Although it could potentially avoid testing all
ports, it cannot be used at this time.

Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
 lib/chamelium/v3/igt_chamelium.c | 348 ++++++++++++++++++++++++++++++++++++++-
 lib/chamelium/v3/igt_chamelium.h |   2 +-
 lib/igt_kms.c                    |   2 +-
 3 files changed, 349 insertions(+), 3 deletions(-)

diff --git a/lib/chamelium/v3/igt_chamelium.c b/lib/chamelium/v3/igt_chamelium.c
index 736e593a465e..e5810e06dbc6 100644
--- a/lib/chamelium/v3/igt_chamelium.c
+++ b/lib/chamelium/v3/igt_chamelium.c
@@ -7,6 +7,7 @@
 #include "igt_core.h"
 #include "igt_kms.h"
 #include "igt_rc.h"
+#include "igt_kms.h"
 
 #define CHAMELIUM_CONFIG_SECTION "Chameliumv3"
 #define CHAMELIUM_CONFIG_URL "URL"
@@ -341,6 +342,330 @@ static void chamelium_v3_port_mapping_info_list(struct igt_list_head *head)
 	}
 }
 
+/**
+ * list_contains() - Search an element in the list
+ *
+ * @list: Pointer to the list to search into
+ * @list_len: Length of the list
+ * @value: Value to search in the list
+ *
+ * Returns true if @list contains @value
+ */
+static bool list_contains(const uint32_t *list, int list_len, uint32_t value)
+{
+	igt_assert(list);
+	for (int i = 0; i < list_len; i++) {
+		if (list[i] == value)
+			return true;
+	}
+	return false;
+}
+
+/**
+ * get_list_diff() - Compute and return the difference between two lists
+ *
+ * @list_a: Pointer to the first list to compare
+ * @list_a_len: Length of the first list
+ * @list_b: Pointer to the second list to compare
+ * @list_b_len: Length of the second list
+ * @diff: Out pointer for the difference. Can be null to only count new elements.
+ *
+ * Returns the number of element which are in @list_a but not in @list_b.
+ */
+static int
+get_list_diff(const uint32_t *list_a, int list_a_len, const uint32_t *list_b, int list_b_len,
+	      uint32_t **diff)
+{
+	int diff_len = 0;
+
+	igt_assert(list_a);
+	igt_assert(list_b);
+
+	if (diff)
+		*diff = malloc(0);
+
+	for (int i = 0; i < list_a_len; i++) {
+		if (!list_contains(list_b, list_b_len, list_a[i])) {
+			if (diff) {
+				*diff = reallocarray(*diff, diff_len + 1, sizeof(**diff));
+				igt_assert(*diff);
+				(*diff)[diff_len] = list_a[i];
+			}
+
+			diff_len++;
+		}
+	}
+
+	return diff_len;
+}
+
+/**
+ * chamelium_v3_wait_for_new_connectors() - Wait for new connector to appear
+ *
+ * @list_a: Pointer to the first list to compare
+ * @list_a_len: Length of the first list
+ * @list_b: Pointer to the second list to compare
+ * @list_b_len: Length of the second list
+ * @diff: Out pointer for the difference. Can be null.
+ *
+ * Returns the number of element which differ between the two lists.
+ */
+static int chamelium_v3_wait_for_new_connectors(uint32_t **newly_connected,
+						const uint32_t *already_connected,
+						int already_connected_count, int drm_fd)
+{
+	int newly_connected_count;
+	struct timespec start, end;
+
+	igt_assert(newly_connected);
+	igt_assert(already_connected);
+	igt_assert(drm_fd);
+
+	clock_gettime(CLOCK_MONOTONIC, &start);
+	clock_gettime(CLOCK_MONOTONIC, &end);
+	do {
+		if (*newly_connected)
+			free(*newly_connected);
+		newly_connected_count = igt_get_connected_connectors(drm_fd, newly_connected);
+		clock_gettime(CLOCK_MONOTONIC, &end);
+	} while (get_list_diff(*newly_connected, newly_connected_count,
+			       already_connected, already_connected_count,
+			       NULL) == 0 &&
+		 igt_time_elapsed(&start, &end) <= igt_default_detect_timeout());
+
+	return newly_connected_count;
+}
+
+/**
+ * chamelium_v3_autodetect_non_mst_port() - Attempt to detect a port without MST
+ *
+ * @chamelium: Chamelium to use
+ * @drm_fd: drm file descriptor used to get the connected connectors
+ * @port: Chamlium port to use
+ *
+ * It will plug the chamelium @port and attempt to find a newly connected connector in DRM. It will
+ * add this mapping in the chamelium structure.
+ */
+static void
+chamelium_v3_autodetect_non_mst_port(struct igt_chamelium_v3 *chamelium, int drm_fd,
+				     chamelium_v3_port_id port)
+{
+	int newly_connected_count, already_connected_count, diff_len;
+	uint32_t *newly_connected = NULL, *already_connected = NULL;
+	struct chamelium_v3_port_mapping *mapping;
+	drmModeConnectorPtr connector;
+	char *port_name;
+	uint32_t *diff = NULL;
+
+	port_name = chamelium_v3_get_port_name(chamelium, port);
+	chamelium_v3_reset(chamelium);
+
+	/*
+	 * Hard sleep is required here as we don't know how long it will take for the device under
+	 * test to properly detect the port disconnection.
+	 */
+	sleep(igt_default_detect_timeout());
+
+	already_connected_count = igt_get_connected_connectors(drm_fd, &already_connected);
+
+	chamelium_v3_apply_edid(chamelium, port, 0);
+	chamelium_v3_plug(chamelium, port);
+
+	newly_connected_count = chamelium_v3_wait_for_new_connectors(&newly_connected,
+								     already_connected,
+								     already_connected_count,
+								     drm_fd);
+
+	diff_len = get_list_diff(newly_connected, newly_connected_count,
+				 already_connected, already_connected_count, &diff);
+
+	if (diff_len == 0) {
+		igt_info("\t\t\tNo newly connected connector, assuming this port is not connected.\n");
+	} else if (diff_len > 1) {
+		igt_info("\t\t\tMore than one new connectors connected, this is not supported by autodetection.\n");
+	} else {
+		igt_info("\t\t\tFound one connector (%d) connected to the port %d (%s)\n", diff[0],
+			 port, port_name);
+
+		connector = drmModeGetConnector(drm_fd, diff[0]);
+		igt_assert(connector);
+		mapping = chamelium_v3_port_mapping_alloc();
+		mapping->port_id = port;
+		igt_assert(asprintf(&mapping->connector_name, "%s-%u",
+				    kmstest_connector_type_str(connector->connector_type),
+				    connector->connector_type_id) != -1);
+		igt_list_add(&mapping->link, &chamelium->port_mapping);
+		drmModeFreeConnector(connector);
+	}
+
+	free(already_connected);
+	free(newly_connected);
+	free(diff);
+	free(port_name);
+}
+
+/**
+ * chamelium_v3_autodetect_mst_children_port() - Attempt to find the mapping between a children port
+ *	and a MST path
+ *
+ * @chamelium: Chamelium to use
+ * @drm_fd: drm file descriptor to detect the connector
+ * @port: parent port of the children port
+ * @children: children port
+ *
+ * It will plug the chamelium @port and @children and attempt to find a newly connected connector in
+ * DRM. It will add this mapping in the chamelium structure.
+ */
+static void
+chamelium_v3_autodetect_mst_children_port(struct igt_chamelium_v3 *chamelium, int drm_fd,
+					  chamelium_v3_port_id port, chamelium_v3_port_id children)
+{
+	struct chamelium_v3_port_mapping *mapping;
+	drmModePropertyBlobPtr path_blob;
+	struct timespec start, end;
+	uint32_t *newly_connected = NULL;
+	char *port_name;
+
+	igt_assert(chamelium);
+	igt_assert(drm_fd);
+
+	port_name = chamelium_v3_get_port_name(chamelium, children);
+	chamelium_v3_reset(chamelium);
+	chamelium_v3_apply_edid(chamelium, port, 0);
+	chamelium_v3_apply_edid(chamelium, children, 0);
+	chamelium_v3_plug_with_children(chamelium, port, &children, 1);
+
+	/*
+	 * Waiting for a connector not already in the mappings
+	 */
+	clock_gettime(CLOCK_MONOTONIC, &start);
+	clock_gettime(CLOCK_MONOTONIC, &end);
+	while (igt_time_elapsed(&start, &end) <= igt_default_detect_timeout()) {
+		if (newly_connected)
+			free(newly_connected);
+
+		for (int i = 0; i < igt_get_connected_connectors(drm_fd, &newly_connected); i++) {
+			path_blob = kmstest_get_path_blob(drm_fd, newly_connected[i]);
+
+			if (path_blob) {
+				struct chamelium_v3_port_mapping *tmp, *pos;
+				bool found = false;
+
+				igt_list_for_each_entry_safe(pos, tmp, &chamelium->port_mapping,
+							     link) {
+					if (strcmp((const char *)path_blob->data, pos->mst_path)
+					    == 0) {
+						found = true;
+					}
+				}
+				if (!found) {
+					igt_info("\t\t\tFound one children connector (%d) connected to the port %d (%s)\n",
+						 newly_connected[i], children, port_name);
+
+					mapping = chamelium_v3_port_mapping_alloc();
+					mapping->port_id = children;
+					mapping->is_children = true;
+					mapping->parent_id = port;
+					mapping->mst_path = strndup(path_blob->data,
+								    path_blob->length);
+					drmModeFreePropertyBlob(path_blob);
+					igt_list_add(&mapping->link, &chamelium->port_mapping);
+					free(port_name);
+					return;
+				}
+				drmModeFreePropertyBlob(path_blob);
+			}
+		}
+
+		clock_gettime(CLOCK_MONOTONIC, &end);
+	}
+	free(port_name);
+}
+
+/**
+ * chamelium_v3_autodetect_mst_children_port() - Attempt to find the mapping between a MST port, its
+ *	children and their MST path
+ *
+ * @chamelium: Chamelium to use
+ * @drm_fd: drm file descriptor to detect the connector
+ * @port: MST port
+ *
+ * It will plug the chamelium @port and its children and attempt to find a mapping between them and
+ * a drm connector. It will add this mapping in the chamelium structure.
+ */
+static void
+chamelium_v3_autodetect_mst_port(struct igt_chamelium_v3 *chamelium, int drm_fd,
+				 chamelium_v3_port_id port)
+{
+	int already_connected_count, newly_connected_count;
+	uint32_t *already_connected = NULL, *newly_connected = NULL;
+	chamelium_v3_port_id *children_ports = NULL;
+	struct chamelium_v3_port_mapping *mapping;
+	int diff_len, children_port_count;
+	drmModePropertyBlobPtr path_blob;
+	char *port_name;
+	uint32_t *diff = NULL;
+
+	port_name = chamelium_v3_get_port_name(chamelium, port);
+	chamelium_v3_reset(chamelium);
+
+	/*
+	 * Hard sleep is required here as we don't know how long it will take for the device under
+	 * test to properly detect the port disconnection.
+	 */
+	sleep(igt_default_detect_timeout());
+
+	already_connected_count = igt_get_connected_connectors(drm_fd, &already_connected);
+
+	chamelium_v3_apply_edid(chamelium, port, 0);
+	chamelium_v3_plug(chamelium, port);
+
+	newly_connected_count = chamelium_v3_wait_for_new_connectors(&newly_connected,
+								     already_connected,
+								     already_connected_count,
+								     drm_fd);
+
+	diff_len = get_list_diff(newly_connected, newly_connected_count,
+				 already_connected, already_connected_count,
+				 &diff);
+
+	if (diff_len == 0) {
+		igt_info("\t\t\tNo newly connected connector, assuming this port is not connected.\n");
+	} else if (diff_len > 1) {
+		igt_info("\t\t\tMore than one new connectors connected, this is not supported by autodetection.\n");
+	} else {
+		igt_info("\t\t\tFound one connector (%d) connected to the port %d (%s). Autodetecting MST children...\n",
+			 diff[0], port, port_name);
+		path_blob = kmstest_get_path_blob(drm_fd, diff[0]);
+
+		if (path_blob) {
+			mapping = chamelium_v3_port_mapping_alloc();
+			mapping->port_id = port;
+			mapping->is_children = false;
+			mapping->mst_path = strndup(path_blob->data, path_blob->length);
+			drmModeFreePropertyBlob(path_blob);
+			igt_list_add(&mapping->link, &chamelium->port_mapping);
+
+			children_port_count = chamelium_v3_get_children(chamelium, port,
+									&children_ports);
+
+			for (int i = 0; i < children_port_count; i++) {
+				chamelium_v3_autodetect_mst_children_port(chamelium, drm_fd, port,
+									  children_ports[i]);
+			}
+
+			free(children_ports);
+		} else {
+			igt_info("\t\t\tNo PATH blob found for this connector. Assuming this DUT does not support MST and skip this port.\n");
+		}
+	}
+
+	free(already_connected);
+	free(newly_connected);
+	free(diff);
+	free(port_name);
+}
+
 /**
  * chamelium_v3_fill_port_mapping() - Read the configuration file and fill the port_mapping
  *	structure.
@@ -350,7 +675,7 @@ static void chamelium_v3_port_mapping_info_list(struct igt_list_head *head)
  * It will read the configuration file searching for a Cv3 configuration. If this configuration does
  * not exist or is empty, it will try to read a Cv2 configuration.
  */
-void chamelium_v3_fill_port_mapping(struct igt_chamelium_v3 *chamelium)
+void chamelium_v3_fill_port_mapping(struct igt_chamelium_v3 *chamelium, int drm_fd)
 {
 	if (igt_key_file) {
 		chamelium_v3_fill_port_mapping_from_config_v3(chamelium);
@@ -358,6 +683,27 @@ void chamelium_v3_fill_port_mapping(struct igt_chamelium_v3 *chamelium)
 			chamelium_v3_fill_port_mapping_from_config_v2(chamelium);
 	}
 
+	if (igt_list_empty(&chamelium->port_mapping)) {
+		chamelium_v3_port_id *ports;
+		char *port_name;
+		int port_count;
+
+		igt_info("Chamelium configuration empty, autodetecting...\n");
+		igt_info("\tAutodetect ports:\n");
+		ports = NULL;
+		port_count = chamelium_v3_get_supported_ports(chamelium, &ports);
+		for (int i = 0; i < port_count; i++) {
+			port_name = chamelium_v3_get_port_name(chamelium, ports[i]);
+			igt_info("\t\tAutodetect port %d (%s)...\n", ports[i], port_name);
+			if (!chamelium_v3_is_mst(chamelium, ports[i]))
+				chamelium_v3_autodetect_non_mst_port(chamelium, drm_fd, ports[i]);
+			else
+				chamelium_v3_autodetect_mst_port(chamelium, drm_fd, ports[i]);
+			free(port_name);
+		}
+		free(ports);
+	}
+
 	chamelium_v3_port_mapping_info_list(&chamelium->port_mapping);
 }
 
diff --git a/lib/chamelium/v3/igt_chamelium.h b/lib/chamelium/v3/igt_chamelium.h
index 834f446f4317..0d2e481f6cca 100644
--- a/lib/chamelium/v3/igt_chamelium.h
+++ b/lib/chamelium/v3/igt_chamelium.h
@@ -51,7 +51,7 @@ struct chamelium_v3_port_mapping {
 struct igt_chamelium_v3 *chamelium_v3_init(char *url);
 struct igt_chamelium_v3 *chamelium_v3_init_from_config(void);
 
-void chamelium_v3_fill_port_mapping(struct igt_chamelium_v3 *chamelium);
+void chamelium_v3_fill_port_mapping(struct igt_chamelium_v3 *chamelium, int drm_fd);
 struct igt_list_head *chamelium_v3_get_port_mapping(struct igt_chamelium_v3 *chamelium);
 struct chamelium_v3_port_mapping *
 chamelium_v3_get_port_mapping_for_chamelium_port_id(struct igt_chamelium_v3 *chamelium,
diff --git a/lib/igt_kms.c b/lib/igt_kms.c
index a30bb483594c..974d9c5f02e7 100644
--- a/lib/igt_kms.c
+++ b/lib/igt_kms.c
@@ -2910,7 +2910,7 @@ void igt_display_require(igt_display_t *display, int drm_fd)
 			struct chamelium_v3_port_mapping *mapping, *tmp;
 
 			chamelium_v3_reset(chamelium);
-			chamelium_v3_fill_port_mapping(chamelium);
+			chamelium_v3_fill_port_mapping(chamelium, drm_fd);
 
 			igt_list_for_each_entry_safe(mapping, tmp,
 						     chamelium_v3_get_port_mapping(chamelium),

-- 
2.44.2


  parent reply	other threads:[~2024-07-09 15:35 UTC|newest]

Thread overview: 51+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-07-09 15:34 [PATCH i-g-t v2 00/39] tests/chamelium: Integrate the chamelium v3 Louis Chauvet
2024-07-09 15:34 ` [PATCH i-g-t v2 01/39] lib/igt_kms: Add a detect timeout value Louis Chauvet
2024-08-27  7:51   ` Kamil Konieczny
2024-08-28 14:31     ` Louis Chauvet
2024-07-09 15:34 ` [PATCH i-g-t v2 02/39] lib/igt_kms: Add helper to wait for a specific status on a connector Louis Chauvet
2024-07-09 15:34 ` [PATCH i-g-t v2 03/39] lib/igt_kms: Add function to list connected connectors Louis Chauvet
2024-07-09 15:34 ` [PATCH i-g-t v2 04/39] lib/igt_kms: Add helper to obtain a connector by its name or MST path Louis Chauvet
2024-07-09 15:34 ` [PATCH i-g-t v2 05/39] lib/igt_kms: Add function to get valid pipe for specific output Louis Chauvet
2024-07-09 15:34 ` [PATCH i-g-t v2 06/39] lib/monitor_edids: Add helper functions for using monitor_edid objects Louis Chauvet
2024-07-09 15:34 ` [PATCH i-g-t v2 07/39] lib/monitor_edids: Add helper to get an EDID by its name Louis Chauvet
2024-07-09 15:34 ` [PATCH i-g-t v2 08/39] lib/monitor_edids: Add helper to print all available EDID names Louis Chauvet
2024-07-09 15:34 ` [PATCH i-g-t v2 09/39] lib/monitor_edids: Fix missing names in some monitor EDID Louis Chauvet
2024-07-09 15:34 ` [PATCH i-g-t v2 10/39] lib/monitor_edids: Add new EDID for HDMI 4k Louis Chauvet
2024-07-09 15:34 ` [PATCH i-g-t v2 11/39] tests/chamelium: Extract Chamelium v2 tests into a separate directory Louis Chauvet
2024-07-09 15:34 ` [PATCH i-g-t v2 12/39] lib/chamelium/v2: Extract chamelium v2 wrapper into its own directory Louis Chauvet
2024-07-09 15:34 ` [PATCH i-g-t v2 13/39] lib/chamelium/v2: Modify build options to separate Chamelium v2 and v3 Louis Chauvet
2024-07-09 15:34 ` [PATCH i-g-t v2 14/39] lib/chamelium/v3: Introduce the foundation for the Chamelium v3 wrapper Louis Chauvet
2024-08-26  9:22   ` Vignesh Raman
2024-08-28 17:26     ` Louis Chauvet
2024-07-09 15:34 ` [PATCH i-g-t v2 15/39] lib/chamelium/v3: Introduce initialization and cleanup of Chamelium-related structures Louis Chauvet
2024-07-09 15:34 ` [PATCH i-g-t v2 16/39] lib/chamelium/v3: Add method to discover Chamelium ports Louis Chauvet
2024-07-09 15:34 ` [PATCH i-g-t v2 17/39] lib/chamelium/v3: Implement method to retrieve Chamelium port names Louis Chauvet
2024-07-09 15:34 ` [PATCH i-g-t v2 18/39] tests/chamelium/v3: Implement a basic Chamelium v3 accessibility test Louis Chauvet
2024-07-09 15:34 ` [PATCH i-g-t v2 19/39] lib/chamelium/v3: Implement Chamelium reinitialization via Reset RPC call Louis Chauvet
2024-07-09 15:34 ` [PATCH i-g-t v2 20/39] lib/chamelium/v3: Implement methods for plugging Chamelium ports Louis Chauvet
2024-07-09 15:34 ` [PATCH i-g-t v2 21/39] lib/chamelium/v3: Implement methods for managing Chamelium EDID Louis Chauvet
2024-07-09 15:34 ` [PATCH i-g-t v2 22/39] lib/chamelium/v3: Implement Chamelium configuration parsing Louis Chauvet
2024-07-09 15:34 ` [PATCH i-g-t v2 23/39] lib/chamelium/v3: Log port mapping for debugging purposes Louis Chauvet
2024-07-09 15:34 ` [PATCH i-g-t v2 24/39] lib/chamelium/v3: Introduce new configuration format for MST support Louis Chauvet
2024-07-09 15:34 ` [PATCH i-g-t v2 25/39] lib/chamelium/v3: Provide access to port_mapping via method call Louis Chauvet
2024-07-09 15:34 ` [PATCH i-g-t v2 26/39] lib/chamelium/v3: Implement helper function to get port mapping from Chameleon port id Louis Chauvet
2024-07-09 15:34 ` [PATCH i-g-t v2 27/39] lib/chamelium/v3: Implement helper function to retrieve connector from port mapping Louis Chauvet
2024-07-09 15:34 ` [PATCH i-g-t v2 28/39] lib/chamelium/v3: Plug specific ports for all tests Louis Chauvet
2024-08-26  9:26   ` Vignesh Raman
2024-08-28 17:26     ` Louis Chauvet
2024-07-09 15:34 ` Louis Chauvet [this message]
2024-07-09 15:34 ` [PATCH i-g-t v2 30/39] lib/chamelium/v3: Add save option to avoid doing autodetection every time Louis Chauvet
2024-07-09 15:34 ` [PATCH i-g-t v2 31/39] tests/chamelium/v3: Implement basic EDID handling test Louis Chauvet
2024-07-09 15:34 ` [PATCH i-g-t v2 32/39] tests/chamelium/v3: Implement 4K EDID stress test Louis Chauvet
2024-07-09 15:34 ` [PATCH i-g-t v2 33/39] tests/chamelium/v3: Implement non-4K " Louis Chauvet
2024-07-09 15:34 ` [PATCH i-g-t v2 34/39] lib/chamelium/v3: Implement method to discover video signal status Louis Chauvet
2024-07-09 15:34 ` [PATCH i-g-t v2 35/39] tests/chamelium/v3: Implement test for DRM device resolution Louis Chauvet
2024-07-09 15:34 ` [PATCH i-g-t v2 36/39] lib/chamelium/v3: Implement hot plug toggle scheduling method Louis Chauvet
2024-07-09 15:34 ` [PATCH i-g-t v2 37/39] tests/chamelium/v3: Add test for display change detection during sleep Louis Chauvet
2024-07-09 15:34 ` [PATCH i-g-t v2 38/39] tests/chamelium/v3: Add MST EDID reading test Louis Chauvet
2024-07-09 15:34 ` [PATCH i-g-t v2 39/39] docs: Add Chamelium v3 Louis Chauvet
2024-07-09 15:47 ` [PATCH i-g-t v2 00/39] tests/chamelium: Integrate the chamelium v3 Louis Chauvet
2024-07-09 16:16 ` ✗ Fi.CI.BUILD: failure for " Patchwork
2024-07-10  9:48   ` Louis Chauvet
2024-08-26  9:30     ` Vignesh Raman
2024-07-09 16:21 ` ✗ GitLab.Pipeline: warning " Patchwork

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240709-dev-remove-static-ports-v2-29-5adfc6985778@bootlin.com \
    --to=louis.chauvet@bootlin.com \
    --cc=igt-dev@lists.freedesktop.org \
    --cc=ihf@google.com \
    --cc=jeremie.dautheribes@bootlin.com \
    --cc=markyacoub@google.com \
    --cc=thomas.petazzoni@bootlin.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox