[igt-dev] [PATCH] Chamelium: Handle getting port connector if it's MST.
Mark Yacoub
markyacoub at chromium.org
Fri Sep 23 20:05:04 UTC 2022
[Why]
When getting a connector for a port, the connector ID might be invalid
after a replug if it's an MST connector. Getting the connector with just
the connector ID will not always work.
[How]
Check if the connector is MST by checking the port's connector path.
If it is, iterate through all connectors until a connector with a
matching path is found.
TEST=./kms_chamelium --run-subtest dp-hpd [on intel Volteer board with
Chamelium V3 connected]
Signed-off-by: Mark Yacoub <markyacoub at chromium.org>
---
lib/igt_chamelium.c | 107 +++++++++++++++++++++++++++++++++++---------
lib/igt_kms.c | 16 +++++++
lib/igt_kms.h | 1 +
3 files changed, 102 insertions(+), 22 deletions(-)
diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c
index 0fee8a83..26244bd5 100644
--- a/lib/igt_chamelium.c
+++ b/lib/igt_chamelium.c
@@ -182,6 +182,20 @@ unsigned int chamelium_port_get_type(const struct chamelium_port *port) {
return port->type;
}
+/**
+ * chamelium_port_get_name:
+ * @port: The chamelium port to retrieve the name of
+ *
+ * Gets the name of the DRM connector corresponding to the given Chamelium
+ * port.
+ *
+ * Returns: the name of the DRM connector
+ */
+const char *chamelium_port_get_name(struct chamelium_port *port)
+{
+ return port->name;
+}
+
/**
* chamelium_port_get_connector:
* @chamelium: The Chamelium instance to use
@@ -197,30 +211,79 @@ drmModeConnector *chamelium_port_get_connector(struct chamelium *chamelium,
struct chamelium_port *port,
bool reprobe)
{
- drmModeConnector *connector;
+ typedef drmModeConnectorPtr (*getConnectorPtr)(int fd,
+ uint32_t connector_id);
- if (reprobe)
- connector = drmModeGetConnector(chamelium->drm_fd,
- port->connector_id);
- else
- connector = drmModeGetConnectorCurrent(
- chamelium->drm_fd, port->connector_id);
+ drmModeRes *res = NULL;
+ int i;
- return connector;
-}
+ bool is_mst_port = !!port->connector_path;
+ getConnectorPtr getConnector = reprobe ? &drmModeGetConnector :
+ &drmModeGetConnectorCurrent;
+ int drm_fd = chamelium->drm_fd;
+ drmModeConnector *connector = getConnector(drm_fd, port->connector_id);
-/**
- * chamelium_port_get_name:
- * @port: The chamelium port to retrieve the name of
- *
- * Gets the name of the DRM connector corresponding to the given Chamelium
- * port.
- *
- * Returns: the name of the DRM connector
- */
-const char *chamelium_port_get_name(struct chamelium_port *port)
-{
- return port->name;
+ /* If the port isn't MST, then the connector ID should be consistent to grab the connector. */
+ if (!is_mst_port) {
+ return connector;
+ }
+
+ /* If the port is MST, then we need to find the connector ID from the path. */
+
+ /* In case the connector ID is still valid, do a quick check if we're have the connector we expect.
+ * Otherwise, read the new resources and find the new connector we're looking for. */
+ if (connector) {
+ drmModePropertyBlobPtr path_blob =
+ kmstest_get_path_blob(drm_fd, connector->connector_id);
+ if (path_blob) {
+ bool is_correct_connector =
+ strcmp(port->connector_path, path_blob->data) ==
+ 0;
+ drmModeFreePropertyBlob(path_blob);
+ if (is_correct_connector)
+ return connector;
+ }
+
+ drmModeFreeConnector(connector);
+ connector = NULL;
+ }
+
+ res = drmModeGetResources(drm_fd);
+ for (i = 0; i < res->count_connectors; i++) {
+ drmModePropertyBlobPtr path_blob = NULL;
+
+ connector = getConnector(drm_fd, res->connectors[i]);
+ /* Check if the connector is not disconnected and in zombie mode. */
+ if (!connector)
+ continue;
+ /* Check if the connector is MST. */
+ path_blob =
+ kmstest_get_path_blob(drm_fd, connector->connector_id);
+ if (!path_blob)
+ continue;
+
+ if (strcmp(path_blob->data, port->connector_path) == 0) {
+ char connector_name[50];
+ /* At finding the connector, update its metadata. */
+ 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);
+
+ goto out;
+ }
+
+ drmModeFreePropertyBlob(path_blob);
+ drmModeFreeConnector(connector);
+ connector = NULL;
+ }
+
+out:
+ drmModeFreeResources(res);
+ return connector;
}
/**
@@ -2862,7 +2925,7 @@ struct chamelium *chamelium_init(int drm_fd)
bool type_mismatch = false;
struct chamelium_port * port = &chamelium->ports[i];
drmModeConnectorPtr connector =
- drmModeGetConnectorCurrent(drm_fd, port->connector_id);
+ chamelium_port_get_connector(chamelium, port, false);
igt_assert(connector != NULL);
diff --git a/lib/igt_kms.c b/lib/igt_kms.c
index 665594aa..55fcd811 100644
--- a/lib/igt_kms.c
+++ b/lib/igt_kms.c
@@ -1786,6 +1786,22 @@ bool kmstest_get_connector_config(int drm_fd, uint32_t connector_id,
config, 0);
}
+drmModePropertyBlobPtr kmstest_get_path_blob(int drm_fd, uint32_t connector_id)
+{
+ uint64_t path_blob_id = 0;
+ drmModePropertyBlobPtr path_blob = NULL;
+
+ if (!kmstest_get_property(drm_fd, connector_id,
+ DRM_MODE_OBJECT_CONNECTOR, "PATH", NULL,
+ &path_blob_id, NULL)) {
+ return NULL;
+ }
+
+ path_blob = drmModeGetPropertyBlob(drm_fd, path_blob_id);
+ igt_assert(path_blob);
+ return path_blob;
+}
+
/**
* kmstest_probe_connector_config:
* @drm_fd: DRM fd
diff --git a/lib/igt_kms.h b/lib/igt_kms.h
index 3d78c37f..eddfb6fc 100644
--- a/lib/igt_kms.h
+++ b/lib/igt_kms.h
@@ -234,6 +234,7 @@ bool kmstest_get_connector_default_mode(int drm_fd, drmModeConnector *connector,
bool kmstest_get_connector_config(int drm_fd, uint32_t connector_id,
unsigned long crtc_idx_mask,
struct kmstest_connector_config *config);
+drmModePropertyBlobPtr kmstest_get_path_blob(int drm_fd, uint32_t connector_id);
bool kmstest_probe_connector_config(int drm_fd, uint32_t connector_id,
unsigned long crtc_idx_mask,
struct kmstest_connector_config *config);
--
2.37.3.998.g577e59143f-goog
More information about the igt-dev
mailing list