Re: [PATCH v2 15/15] drm/vkms: Allow to attach connectors and encoders

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 11/02/25 - 12:09, José Expósito wrote:
> Add a list of possible encoders to the connector configuration and
> helpers to attach and detach them.
> 
> Now that the default configuration has its connector and encoder
> correctly, configure the output following the configuration.
> 
> Co-developed-by: Louis Chauvet <louis.chauvet@xxxxxxxxxxx>
> Signed-off-by: Louis Chauvet <louis.chauvet@xxxxxxxxxxx>
> Signed-off-by: José Expósito <jose.exposito89@xxxxxxxxx>

The compilation is broken as module:

diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms_config.c
index 7f4e21e8ee0c..76f24bd463f6 100644
--- a/drivers/gpu/drm/vkms/vkms_config.c
+++ b/drivers/gpu/drm/vkms/vkms_config.c
@@ -610,6 +610,7 @@ int __must_check vkms_config_connector_attach_encoder(struct vkms_config_connect
        return xa_alloc(&connector_cfg->possible_encoders, &encoder_idx,
                        encoder_cfg, xa_limit_32b, GFP_KERNEL);
 }
+EXPORT_SYMBOL_IF_KUNIT(vkms_config_connector_attach_encoder);

 void vkms_config_connector_detach_encoder(struct vkms_config_connector *connector_cfg,
                                          struct vkms_config_encoder *encoder_cfg)
@@ -623,3 +624,4 @@ void vkms_config_connector_detach_encoder(struct vkms_config_connector *connecto
                        xa_erase(&connector_cfg->possible_encoders, idx);
        }
 }
+EXPORT_SYMBOL_IF_KUNIT(vkms_config_connector_detach_encoder);


> ---
>  .clang-format                                 |  1 +
>  drivers/gpu/drm/vkms/tests/vkms_config_test.c | 94 +++++++++++++++++++
>  drivers/gpu/drm/vkms/vkms_config.c            | 60 ++++++++++++
>  drivers/gpu/drm/vkms/vkms_config.h            | 29 ++++++
>  drivers/gpu/drm/vkms/vkms_output.c            | 33 ++++---
>  5 files changed, 204 insertions(+), 13 deletions(-)
> 
> diff --git a/.clang-format b/.clang-format
> index ca49832993c5..7630990aa07a 100644
> --- a/.clang-format
> +++ b/.clang-format
> @@ -694,6 +694,7 @@ ForEachMacros:
>    - 'vkms_config_for_each_crtc'
>    - 'vkms_config_for_each_encoder'
>    - 'vkms_config_for_each_plane'
> +  - 'vkms_config_connector_for_each_possible_encoder'
>    - 'vkms_config_encoder_for_each_possible_crtc'
>    - 'vkms_config_plane_for_each_possible_crtc'
>    - 'while_for_each_ftrace_op'
> diff --git a/drivers/gpu/drm/vkms/tests/vkms_config_test.c b/drivers/gpu/drm/vkms/tests/vkms_config_test.c
> index cba7e9d2fcad..2d104ecfde3b 100644
> --- a/drivers/gpu/drm/vkms/tests/vkms_config_test.c
> +++ b/drivers/gpu/drm/vkms/tests/vkms_config_test.c
> @@ -511,6 +511,27 @@ static void vkms_config_test_invalid_connector_number(struct kunit *test)
>  	vkms_config_destroy(config);
>  }
>  
> +static void vkms_config_test_valid_connector_possible_encoders(struct kunit *test)
> +{
> +	struct vkms_config *config;
> +	struct vkms_config_encoder *encoder_cfg;
> +	struct vkms_config_connector *connector_cfg;
> +
> +	config = vkms_config_default_create(false, false, false);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
> +
> +	encoder_cfg = list_first_entry(&config->encoders,
> +				       typeof(*encoder_cfg), link);
> +	connector_cfg = list_first_entry(&config->connectors,
> +					 typeof(*connector_cfg), link);
> +
> +	/* Invalid: Connector without a possible encoder */
> +	vkms_config_connector_detach_encoder(connector_cfg, encoder_cfg);
> +	KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config));
> +
> +	vkms_config_destroy(config);
> +}
> +
>  static void vkms_config_test_plane_attach_crtc(struct kunit *test)
>  {
>  	struct vkms_config *config;
> @@ -700,6 +721,77 @@ static void vkms_config_test_encoder_get_possible_crtcs(struct kunit *test)
>  	vkms_config_destroy(config);
>  }
>  
> +static void vkms_config_test_connector_get_possible_encoders(struct kunit *test)
> +{
> +	struct vkms_config *config;
> +	struct vkms_config_connector *connector_cfg1, *connector_cfg2;
> +	struct vkms_config_encoder *encoder_cfg1, *encoder_cfg2;
> +	struct vkms_config_encoder *possible_encoder;
> +	unsigned long idx = 0;
> +	int n_encoders = 0;
> +	int err;
> +
> +	config = vkms_config_create("test");
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
> +
> +	connector_cfg1 = vkms_config_create_connector(config);
> +	connector_cfg2 = vkms_config_create_connector(config);
> +	encoder_cfg1 = vkms_config_create_encoder(config);
> +	encoder_cfg2 = vkms_config_create_encoder(config);
> +
> +	/* No possible encoders */
> +	vkms_config_connector_for_each_possible_encoder(connector_cfg1, idx,
> +							possible_encoder)
> +		KUNIT_FAIL(test, "Unexpected possible encoder");
> +
> +	vkms_config_connector_for_each_possible_encoder(connector_cfg2, idx,
> +							possible_encoder)
> +		KUNIT_FAIL(test, "Unexpected possible encoder");
> +
> +	/* Connector 1 attached to encoders 1 and 2 */
> +	err = vkms_config_connector_attach_encoder(connector_cfg1, encoder_cfg1);
> +	KUNIT_EXPECT_EQ(test, err, 0);
> +	err = vkms_config_connector_attach_encoder(connector_cfg1, encoder_cfg2);
> +	KUNIT_EXPECT_EQ(test, err, 0);
> +
> +	vkms_config_connector_for_each_possible_encoder(connector_cfg1, idx,
> +							possible_encoder) {
> +		n_encoders++;
> +		if (possible_encoder != encoder_cfg1 &&
> +		    possible_encoder != encoder_cfg2)
> +			KUNIT_FAIL(test, "Unexpected possible encoder");
> +	}
> +	KUNIT_ASSERT_EQ(test, n_encoders, 2);
> +	n_encoders = 0;
> +
> +	vkms_config_connector_for_each_possible_encoder(connector_cfg2, idx,
> +							possible_encoder)
> +		KUNIT_FAIL(test, "Unexpected possible encoder");
> +
> +	/* Connector 1 attached to encoder 1 and connector 2 to encoder 2 */
> +	vkms_config_connector_detach_encoder(connector_cfg1, encoder_cfg2);
> +	vkms_config_connector_for_each_possible_encoder(connector_cfg1, idx,
> +							possible_encoder) {
> +		n_encoders++;
> +		if (possible_encoder != encoder_cfg1)
> +			KUNIT_FAIL(test, "Unexpected possible encoder");
> +	}
> +	KUNIT_ASSERT_EQ(test, n_encoders, 1);
> +	n_encoders = 0;
> +
> +	err = vkms_config_connector_attach_encoder(connector_cfg2, encoder_cfg2);
> +	KUNIT_EXPECT_EQ(test, err, 0);
> +	vkms_config_connector_for_each_possible_encoder(connector_cfg2, idx,
> +							possible_encoder) {
> +		n_encoders++;
> +		if (possible_encoder != encoder_cfg2)
> +			KUNIT_FAIL(test, "Unexpected possible encoder");
> +	}
> +	KUNIT_ASSERT_EQ(test, n_encoders, 1);
> +
> +	vkms_config_destroy(config);
> +}
> +
>  static struct kunit_case vkms_config_test_cases[] = {
>  	KUNIT_CASE(vkms_config_test_empty_config),
>  	KUNIT_CASE_PARAM(vkms_config_test_default_config,
> @@ -715,9 +807,11 @@ static struct kunit_case vkms_config_test_cases[] = {
>  	KUNIT_CASE(vkms_config_test_invalid_encoder_number),
>  	KUNIT_CASE(vkms_config_test_valid_encoder_possible_crtcs),
>  	KUNIT_CASE(vkms_config_test_invalid_connector_number),
> +	KUNIT_CASE(vkms_config_test_valid_connector_possible_encoders),
>  	KUNIT_CASE(vkms_config_test_plane_attach_crtc),
>  	KUNIT_CASE(vkms_config_test_plane_get_possible_crtcs),
>  	KUNIT_CASE(vkms_config_test_encoder_get_possible_crtcs),
> +	KUNIT_CASE(vkms_config_test_connector_get_possible_encoders),
>  	{}
>  };
>  
> diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms_config.c
> index d52280d3bbee..3d95dc713151 100644
> --- a/drivers/gpu/drm/vkms/vkms_config.c
> +++ b/drivers/gpu/drm/vkms/vkms_config.c
> @@ -93,6 +93,9 @@ struct vkms_config *vkms_config_default_create(bool enable_cursor,
>  	if (IS_ERR(connector_cfg))
>  		goto err_alloc;
>  
> +	if (vkms_config_connector_attach_encoder(connector_cfg, encoder_cfg))
> +		goto err_alloc;
> +
>  	return config;
>  
>  err_alloc:
> @@ -275,6 +278,22 @@ static bool valid_connector_number(struct vkms_config *config)
>  	return true;
>  }
>  
> +static bool valid_connector_possible_encoders(struct vkms_config *config)
> +{
> +	struct drm_device *dev = &config->dev->drm;
> +	struct vkms_config_connector *connector_cfg;
> +
> +	vkms_config_for_each_connector(config, connector_cfg) {
> +		if (xa_empty(&connector_cfg->possible_encoders)) {
> +			drm_info(dev,
> +				 "All connectors must have at least one possible encoder\n");
> +			return false;
> +		}
> +	}
> +
> +	return true;
> +}
> +
>  bool vkms_config_is_valid(struct vkms_config *config)
>  {
>  	struct vkms_config_crtc *crtc_cfg;
> @@ -302,6 +321,9 @@ bool vkms_config_is_valid(struct vkms_config *config)
>  	if (!valid_encoder_possible_crtcs(config))
>  		return false;
>  
> +	if (!valid_connector_possible_encoders(config))
> +		return false;
> +
>  	return true;
>  }
>  
> @@ -493,6 +515,11 @@ struct vkms_config_encoder *vkms_config_create_encoder(struct vkms_config *confi
>  void vkms_config_destroy_encoder(struct vkms_config *config,
>  				 struct vkms_config_encoder *encoder_cfg)
>  {
> +	struct vkms_config_connector *connector_cfg;
> +
> +	vkms_config_for_each_connector(config, connector_cfg)
> +		vkms_config_connector_detach_encoder(connector_cfg, encoder_cfg);
> +
>  	xa_destroy(&encoder_cfg->possible_crtcs);
>  	list_del(&encoder_cfg->link);
>  	kfree(encoder_cfg);
> @@ -534,6 +561,8 @@ struct vkms_config_connector *vkms_config_create_connector(struct vkms_config *c
>  	if (!connector_cfg)
>  		return ERR_PTR(-ENOMEM);
>  
> +	xa_init_flags(&connector_cfg->possible_encoders, XA_FLAGS_ALLOC);
> +
>  	list_add_tail(&connector_cfg->link, &config->connectors);
>  
>  	return connector_cfg;
> @@ -541,6 +570,37 @@ struct vkms_config_connector *vkms_config_create_connector(struct vkms_config *c
>  
>  void vkms_config_destroy_connector(struct vkms_config_connector *connector_cfg)
>  {
> +	xa_destroy(&connector_cfg->possible_encoders);
>  	list_del(&connector_cfg->link);
>  	kfree(connector_cfg);
>  }
> +
> +int __must_check vkms_config_connector_attach_encoder(struct vkms_config_connector *connector_cfg,
> +						      struct vkms_config_encoder *encoder_cfg)
> +{
> +	struct vkms_config_encoder *possible_encoder;
> +	unsigned long idx = 0;
> +	u32 encoder_idx = 0;
> +
> +	vkms_config_connector_for_each_possible_encoder(connector_cfg, idx,
> +							possible_encoder) {
> +		if (possible_encoder == encoder_cfg)
> +			return -EINVAL;
> +	}
> +
> +	return xa_alloc(&connector_cfg->possible_encoders, &encoder_idx,
> +			encoder_cfg, xa_limit_32b, GFP_KERNEL);
> +}
> +
> +void vkms_config_connector_detach_encoder(struct vkms_config_connector *connector_cfg,
> +					  struct vkms_config_encoder *encoder_cfg)
> +{
> +	struct vkms_config_encoder *possible_encoder;
> +	unsigned long idx = 0;
> +
> +	vkms_config_connector_for_each_possible_encoder(connector_cfg, idx,
> +							possible_encoder) {
> +		if (possible_encoder == encoder_cfg)
> +			xa_erase(&connector_cfg->possible_encoders, idx);
> +	}
> +}
> diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms_config.h
> index 8451c2f127b6..c87513d174f2 100644
> --- a/drivers/gpu/drm/vkms/vkms_config.h
> +++ b/drivers/gpu/drm/vkms/vkms_config.h
> @@ -92,6 +92,7 @@ struct vkms_config_encoder {
>   * struct vkms_config_connector
>   *
>   * @link: Link to the others connector in vkms_config
> + * @possible_encoders: Array of encoders that can be used with this connector
>   * @connector: Internal usage. This pointer should never be considered as valid.
>   *             It can be used to store a temporary reference to a VKMS connector
>   *             during device creation. This pointer is not managed by the
> @@ -100,6 +101,8 @@ struct vkms_config_encoder {
>  struct vkms_config_connector {
>  	struct list_head link;
>  
> +	struct xarray possible_encoders;
> +
>  	/* Internal usage */
>  	struct vkms_connector *connector;
>  };
> @@ -156,6 +159,16 @@ struct vkms_config_connector {
>  #define vkms_config_encoder_for_each_possible_crtc(encoder_cfg, idx, possible_crtc) \
>  	xa_for_each(&(encoder_cfg)->possible_crtcs, idx, (possible_crtc))
>  
> +/**
> + * vkms_config_connector_for_each_possible_encoder - Iterate over the
> + * vkms_config_connector possible encoders
> + * @connector_cfg: &struct vkms_config_connector pointer
> + * @idx: Index of the cursor
> + * @possible_encoder: &struct vkms_config_encoder pointer used as cursor
> + */
> +#define vkms_config_connector_for_each_possible_encoder(connector_cfg, idx, possible_encoder) \
> +	xa_for_each(&(connector_cfg)->possible_encoders, idx, (possible_encoder))
> +
>  /**
>   * vkms_config_create() - Create a new VKMS configuration
>   * @dev_name: Name of the device
> @@ -397,4 +410,20 @@ struct vkms_config_connector *vkms_config_create_connector(struct vkms_config *c
>   */
>  void vkms_config_destroy_connector(struct vkms_config_connector *connector_cfg);
>  
> +/**
> + * vkms_config_connector_attach_encoder - Attach a connector to an encoder
> + * @connector_cfg: Connector to attach
> + * @encoder_cfg: Encoder to attach @connector_cfg to
> + */
> +int __must_check vkms_config_connector_attach_encoder(struct vkms_config_connector *connector_cfg,
> +						      struct vkms_config_encoder *encoder_cfg);
> +
> +/**
> + * vkms_config_connector_detach_encoder - Detach a connector from an encoder
> + * @connector_cfg: Connector to detach
> + * @encoder_cfg: Encoder to detach @connector_cfg from
> + */
> +void vkms_config_connector_detach_encoder(struct vkms_config_connector *connector_cfg,
> +					  struct vkms_config_encoder *encoder_cfg);
> +
>  #endif /* _VKMS_CONFIG_H_ */
> diff --git a/drivers/gpu/drm/vkms/vkms_output.c b/drivers/gpu/drm/vkms/vkms_output.c
> index 8920d6b5d105..8d7ca0cdd79f 100644
> --- a/drivers/gpu/drm/vkms/vkms_output.c
> +++ b/drivers/gpu/drm/vkms/vkms_output.c
> @@ -8,10 +8,10 @@
>  int vkms_output_init(struct vkms_device *vkmsdev)
>  {
>  	struct drm_device *dev = &vkmsdev->drm;
> -	struct vkms_connector *connector;
>  	struct vkms_config_plane *plane_cfg;
>  	struct vkms_config_crtc *crtc_cfg;
>  	struct vkms_config_encoder *encoder_cfg;
> +	struct vkms_config_connector *connector_cfg;
>  	int ret;
>  	int writeback;
>  
> @@ -83,22 +83,29 @@ int vkms_output_init(struct vkms_device *vkmsdev)
>  		}
>  	}
>  
> -	connector = vkms_connector_init(vkmsdev);
> -	if (IS_ERR(connector)) {
> -		DRM_ERROR("Failed to init connector\n");
> -		return PTR_ERR(connector);
> -	}
> +	vkms_config_for_each_connector(vkmsdev->config, connector_cfg) {
> +		struct vkms_config_encoder *possible_encoder;
> +		unsigned long idx = 0;
>  
> -	/* Attach the encoder and the connector */
> -	vkms_config_for_each_encoder(vkmsdev->config, encoder_cfg) {
> -		ret = drm_connector_attach_encoder(&connector->base, encoder_cfg->encoder);
> -		if (ret) {
> -			DRM_ERROR("Failed to attach connector to encoder\n");
> -			return ret;
> +		connector_cfg->connector = vkms_connector_init(vkmsdev);
> +		if (IS_ERR(connector_cfg->connector)) {
> +			DRM_ERROR("Failed to init connector\n");
> +			return PTR_ERR(connector_cfg->connector);
> +		}
> +
> +		vkms_config_connector_for_each_possible_encoder(connector_cfg,
> +								idx,
> +								possible_encoder) {
> +			ret = drm_connector_attach_encoder(&connector_cfg->connector->base,
> +							   possible_encoder->encoder);
> +			if (ret) {
> +				DRM_ERROR("Failed to attach connector to encoder\n");
> +				return ret;
> +			}
>  		}
>  	}
>  
>  	drm_mode_config_reset(dev);
>  
> -	return ret;
> +	return 0;
>  }
> -- 
> 2.48.1
> 



[Index of Archives]     [Linux DRI Users]     [Linux Intel Graphics]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux