[igt-dev] [PATCH] Chamelium: Handle getting port connector if it's MST.

Lyude Paul lyude at redhat.com
Mon Oct 17 18:55:28 UTC 2022


Reviewed-by: Lyude Paul <lyude at redhat.com>

On Fri, 2022-09-23 at 16:05 -0400, Mark Yacoub wrote:
> [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);

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat



More information about the igt-dev mailing list