[igt-dev] [PATCH v2] lib/chamelium: Use MST Path property to reprobe an MST connector.
Mark Yacoub
markyacoub at chromium.org
Mon Aug 15 19:47:55 UTC 2022
[Why]
On replugs, MST connectors can change their names and IDs. The only
constant thing is their path property.
[How]
If a connector has a PATH prop, it's a MST connector.
On reprobe, look for MST connector with the same PATH prop.
Tested on Volteer with Chamelium V3 connected via a 2-DP-port CableMatters
hub.
Test: kms_chamelium --run-subtest dp-hpd
Signed-off-by: Mark Yacoub <markyacoub at chromium.org>
---
lib/igt_chamelium.c | 116 ++++++++++++++++++++++++++++++++++++++++----
1 file changed, 107 insertions(+), 9 deletions(-)
diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c
index 7b790064..b2ce4174 100644
--- a/lib/igt_chamelium.c
+++ b/lib/igt_chamelium.c
@@ -105,6 +105,7 @@ struct chamelium_port {
int connector_id;
char *name;
bool adapter_allowed;
+ char *connector_path;
};
struct chamelium_frame_dump {
@@ -266,21 +267,97 @@ chamelium_reprobe_connector(igt_display_t *display,
struct chamelium_port *port)
{
drmModeConnector *connector;
- drmModeConnection status;
+ drmModeConnection connection_status;
igt_output_t *output;
+ bool is_mst_port = !!port->connector_path;
igt_debug("Reprobing %s...\n", chamelium_port_get_name(port));
- connector = chamelium_port_get_connector(chamelium, port, true);
+
+ if (is_mst_port)
+ {
+ int drm_fd = display->drm_fd;
+ drmModeRes *res = drmModeGetResources(drm_fd);
+ bool is_connector_found = false;
+ int i;
+
+ for (i = 0; i < res->count_connectors; ++i)
+ {
+ char connector_name[50];
+ uint64_t path_blob_id;
+ drmModePropertyBlobPtr path_blob = NULL;
+
+ connector = drmModeGetConnector(drm_fd, res->connectors[i]);
+ /* If the connector is now unplugged, the spawned connectors will no
+ longer be available but can still be counted as part of
+ res->count_connectors */
+ if (!connector)
+ {
+ drmModeFreeConnector(connector);
+ connector = NULL;
+ continue;
+ }
+
+ /* If the post is MST, it must have a path property - skip if not */
+ if (!kmstest_get_property(drm_fd, connector->connector_id,
+ DRM_MODE_OBJECT_CONNECTOR, "PATH", NULL,
+ &path_blob_id, NULL))
+ {
+ drmModeFreeConnector(connector);
+ connector = NULL;
+ continue;
+ }
+
+ igt_assert(path_blob =
+ drmModeGetPropertyBlob(drm_fd, path_blob_id));
+ /* With MST, the only thing that is guaranteed to persist between
+ plugs and unplugs is the PATH property. Verify that it matches
+ what we previously saved. */
+ if (strcmp(path_blob->data, port->connector_path) == 0)
+ {
+ is_connector_found = true;
+ /* Update name and connector ID they can change between plugs and
+ unplugs */
+ port->connector_id = connector->connector_id;
+ snprintf(connector_name, 50, "%s-%u",
+ kmstest_connector_type_str(connector->connector_type),
+ connector->connector_type_id);
+ port->name = strdup(connector_name);
+
+ drmModeFreePropertyBlob(path_blob);
+ break;
+ }
+
+ drmModeFreePropertyBlob(path_blob);
+ drmModeFreeConnector(connector);
+ connector = NULL;
+ }
+ drmModeFreeResources(res);
+
+ if (!is_connector_found)
+ {
+ igt_assert(!connector);
+ return DRM_MODE_DISCONNECTED;
+ }
+ }
+ else
+ {
+ connector = chamelium_port_get_connector(chamelium, port, true);
+ }
+
igt_assert(connector);
- status = connector->connection;
+ connection_status = connector->connection;
- /* let's make sure that igt_display is up to date too */
+ /* If we still have a connector, let's make sure that igt_display and
+ the port are up to date too */
output = igt_output_from_connector(display, connector);
- output->force_reprobe = true;
- igt_output_refresh(output);
+ if (output)
+ {
+ output->force_reprobe = true;
+ igt_output_refresh(output);
+ }
drmModeFreeConnector(connector);
- return status;
+ return connection_status;
}
/**
@@ -2272,6 +2349,23 @@ static size_t chamelium_get_video_ports(struct chamelium *chamelium,
return port_ids_len;
}
+static void chamelium_set_port_path(struct chamelium_port *port,
+ uint32_t connector_id,
+ int drm_fd)
+{
+ uint64_t path_blob_id;
+ drmModePropertyBlobPtr path_blob = NULL;
+
+ if (kmstest_get_property(drm_fd, connector_id, DRM_MODE_OBJECT_CONNECTOR,
+ "PATH", NULL, &path_blob_id, NULL))
+ {
+ igt_assert(path_blob = drmModeGetPropertyBlob(drm_fd, path_blob_id));
+ port->connector_path = strdup(path_blob->data);
+
+ drmModeFreePropertyBlob(path_blob);
+ }
+}
+
static bool chamelium_read_port_mappings(struct chamelium *chamelium,
int drm_fd)
{
@@ -2345,6 +2439,9 @@ static bool chamelium_read_port_mappings(struct chamelium *chamelium,
if (strcmp(name, map_name) == 0)
port->connector_id = connector->connector_id;
+ chamelium_set_port_path(port, connector->connector_id,
+ drm_fd);
+
drmModeFreeConnector(connector);
}
if (!port->connector_id) {
@@ -2566,10 +2663,11 @@ static bool chamelium_autodiscover(struct chamelium *chamelium, int drm_fd)
connector = drmModeGetConnectorCurrent(drm_fd, conn_id);
snprintf(conn_name, sizeof(conn_name), "%s-%u",
- kmstest_connector_type_str(connector->connector_type),
- connector->connector_type_id);
+ kmstest_connector_type_str(connector->connector_type),
+ connector->connector_type_id);
drmModeFreeConnector(connector);
port->name = strdup(conn_name);
+ chamelium_set_port_path(port, port->connector_id, drm_fd);
}
elapsed_ns = igt_nsec_elapsed(&start);
--
2.37.1.595.g718a3a8f04-goog
More information about the igt-dev
mailing list