[igt-dev] [RFC incomplete PATCH i-g-t] lib/igt_kms: Reduce probing and allow initial hotplug during igt_display_init()

Maarten Lankhorst maarten.lankhorst at linux.intel.com
Fri Mar 23 12:48:28 UTC 2018


When booting with fbdev disabled, all outputs are set to UNKNOWNCONNECTION.
In this case we have to reprobe, but in all others we can safely assume that
the output connector status is valid.

Enumerate all outputs, and for good measure recheck after we probed, to add
and DP-MST we may have missed.

Signed-off-by: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
Cc: Lyude <lyude at redhat.com>
Cc: Dhinakaran Pandiyan <dhinakaran.pandiyan at intel.com>
---
Unfortunately we lack a way to determine whether the probing will enumerate
additional DP-MST displays, so the only way right now to test DP-MST would be
to add a sleep(5) in igt_display_check_hotplug.

Any thoughts how we can make this more reliable for DP-MST?

~Maarten

lib/igt_kms.c | 120 +++++++++++++++++++++++++++++++++++++++++++++++-----------
 lib/igt_kms.h |   2 +-
 2 files changed, 99 insertions(+), 23 deletions(-)

diff --git a/lib/igt_kms.c b/lib/igt_kms.c
index 9e32f40673bb..2417af2fc082 100644
--- a/lib/igt_kms.c
+++ b/lib/igt_kms.c
@@ -974,7 +974,7 @@ _kmstest_connector_config_find_encoder(int drm_fd, drmModeConnector *connector,
 static bool _kmstest_connector_config(int drm_fd, uint32_t connector_id,
 				      unsigned long crtc_idx_mask,
 				      struct kmstest_connector_config *config,
-				      bool probe)
+				      int probe)
 {
 	drmModeRes *resources;
 	drmModeConnector *connector;
@@ -988,11 +988,19 @@ static bool _kmstest_connector_config(int drm_fd, uint32_t connector_id,
 	}
 
 	/* First, find the connector & mode */
-	if (probe)
+	if (probe > 0)
 		connector = drmModeGetConnector(drm_fd, connector_id);
-	else
+	else {
 		connector = drmModeGetConnectorCurrent(drm_fd, connector_id);
 
+		if (probe < 0 && connector &&
+		    connector->connection == DRM_MODE_UNKNOWNCONNECTION) {
+			drmModeFreeConnector(connector);
+
+			connector = drmModeGetConnector(drm_fd, connector_id);
+		}
+	}
+
 	if (!connector)
 		goto err2;
 
@@ -1802,6 +1810,87 @@ void igt_display_reset(igt_display_t *display)
 	}
 }
 
+static void __igt_display_append_output(igt_display_t *display, unsigned id)
+{
+	igt_output_t *output;
+
+	output = &display->outputs[display->n_outputs++];
+	memset(output, 0, sizeof(*output));
+
+	/*
+	 * We don't assign each output a pipe unless
+	 * a pipe is set with igt_output_set_pipe().
+	 */
+	output->id = id;
+	output->display = display;
+	output->pending_pipe = PIPE_NONE;
+	output->force_reprobe = -1;
+
+	igt_output_refresh(output);
+}
+
+static void igt_display_append_output(igt_display_t *display, unsigned id)
+{
+	display->outputs = realloc(display->outputs, sizeof(*display->outputs) * (1 + display->n_outputs));
+	igt_assert(display->outputs);
+
+	__igt_display_append_output(display, id);
+
+	igt_info("HOTPLUG! Added new output %s\n", output->name);
+}
+
+static void igt_display_check_hotplug(igt_display_t *display)
+{
+	int i, j, num_outputs;
+	uint64_t connector_mask = 0;
+	igt_output_t *new_outputs;
+	drmModeRes *resources;
+
+	/* Outputs may have been discovered by igt_output_refresh(), retry.. */
+	resources = drmModeGetResources(display->drm_fd);
+
+	for (i = 0; i < resources->count_connectors; i++) {
+		unsigned id = resources->connectors[i];
+		bool found = false;
+
+		for (j = 0; j < display->n_outputs; j++) {
+			igt_output_t *output = &display->outputs[j];
+
+			if (output->id != id)
+				continue;
+
+			found = true;
+			break;
+		}
+
+		if (!found)
+			igt_display_append_output(display, id);
+
+		connector_mask |= 1ULL << j;
+	}
+
+	drmModeFreeResources(resources);
+
+	num_outputs = __builtin_popcountll(connector_mask);
+	if (num_outputs == display->n_outputs)
+		return;
+
+	new_outputs = malloc(sizeof(*new_outputs) * num_outputs);
+
+	/* Garbage collect dead outputs. */
+	for (i = j = 0; i < display->n_outputs; i++) {
+		if (!(connector_mask & (1ULL << i))) {
+			igt_info("Output %s disappeared!\n", display->outputs[i].name);
+			continue;
+		}
+
+		new_outputs[j++] = display->outputs[i];
+	}
+
+	free(display->outputs);
+	display->outputs = new_outputs;
+}
+
 static void igt_fill_plane_format_mod(igt_display_t *display, igt_plane_t *plane);
 static void igt_fill_display_format_mod(igt_display_t *display);
 
@@ -2012,31 +2101,18 @@ void igt_display_init(igt_display_t *display, int drm_fd)
 
 	igt_fill_display_format_mod(display);
 
-	/*
-	 * The number of connectors is set, so we just initialize the outputs
-	 * array in _init(). This may change when we need dynamic connectors
-	 * (say DisplayPort MST).
-	 */
-	display->n_outputs = resources->count_connectors;
-	display->outputs = calloc(display->n_outputs, sizeof(igt_output_t));
+	display->n_outputs = 0;
+	display->outputs = malloc(display->n_outputs * sizeof(igt_output_t));
 	igt_assert_f(display->outputs, "Failed to allocate memory for %d outputs\n", display->n_outputs);
 
-	for (i = 0; i < display->n_outputs; i++) {
-		igt_output_t *output = &display->outputs[i];
-
-		/*
-		 * We don't assign each output a pipe unless
-		 * a pipe is set with igt_output_set_pipe().
-		 */
-		output->id = resources->connectors[i];
-		output->display = display;
-
-		igt_output_refresh(output);
-	}
+	for (i = 0; i < display->n_outputs; i++)
+		__igt_display_append_output(display, resources->connectors[i]);
 
 	drmModeFreePlaneResources(plane_resources);
 	drmModeFreeResources(resources);
 
+	igt_display_check_hotplug(display);
+
 	/* Set reasonable default values for every object in the display. */
 	igt_display_reset(display);
 
diff --git a/lib/igt_kms.h b/lib/igt_kms.h
index 6f16dc8cf85e..9e734ab1a5b8 100644
--- a/lib/igt_kms.h
+++ b/lib/igt_kms.h
@@ -340,7 +340,7 @@ typedef struct {
 	uint32_t id;					/* KMS id */
 	struct kmstest_connector_config config;
 	char *name;
-	bool force_reprobe;
+	int force_reprobe;
 	enum pipe pending_pipe;
 	bool use_override_mode;
 	drmModeModeInfo override_mode;
-- 
2.16.2



More information about the igt-dev mailing list