From: "José Expósito" <jose.exposito89@gmail.com>
To: Louis Chauvet <louis.chauvet@bootlin.com>
Cc: hamohammed.sa@gmail.com, simona@ffwll.ch, melissa.srw@gmail.com,
maarten.lankhorst@linux.intel.com, mripard@kernel.org,
tzimmermann@suse.de, airlied@gmail.com,
dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH v3 13/14] drm/vkms: Allow to configure multiple connectors
Date: Tue, 18 Feb 2025 11:11:21 +0100 [thread overview]
Message-ID: <Z7RcyT2XEVYiNZ70@fedora> (raw)
In-Reply-To: <6e1496ac-892d-4267-a670-75e6eb50e936@bootlin.com>
On Mon, Feb 17, 2025 at 04:45:41PM +0100, Louis Chauvet wrote:
>
>
> Le 17/02/2025 à 11:01, José Expósito a écrit :
> > Add a list of connectors to vkms_config and helper functions to add and
> > remove as many connectors as wanted.
> >
> > For backwards compatibility, add one enabled connector to the default
> > configuration.
> >
> > A future patch will allow to attach connectors and encoders, but for the
> > moment there are no changes in the way the output is configured.
> >
> > Co-developed-by: Louis Chauvet <louis.chauvet@bootlin.com>
> > Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
> > Signed-off-by: José Expósito <jose.exposito89@gmail.com>
> > ---
> > .clang-format | 1 +
> > drivers/gpu/drm/vkms/tests/vkms_config_test.c | 74 +++++++++++++++++++
> > drivers/gpu/drm/vkms/vkms_config.c | 54 ++++++++++++++
> > drivers/gpu/drm/vkms/vkms_config.h | 44 +++++++++++
> > drivers/gpu/drm/vkms/vkms_connector.c | 11 +++
> > 5 files changed, 184 insertions(+)
> >
> > diff --git a/.clang-format b/.clang-format
> > index 5d21c0e4edbd..ca49832993c5 100644
> > --- a/.clang-format
> > +++ b/.clang-format
> > @@ -690,6 +690,7 @@ ForEachMacros:
> > - 'v4l2_m2m_for_each_src_buf'
> > - 'v4l2_m2m_for_each_src_buf_safe'
> > - 'virtio_device_for_each_vq'
> > + - 'vkms_config_for_each_connector'
> > - 'vkms_config_for_each_crtc'
> > - 'vkms_config_for_each_encoder'
> > - 'vkms_config_for_each_plane'
> > diff --git a/drivers/gpu/drm/vkms/tests/vkms_config_test.c b/drivers/gpu/drm/vkms/tests/vkms_config_test.c
> > index 62fbcba4520f..0034f922713e 100644
> > --- a/drivers/gpu/drm/vkms/tests/vkms_config_test.c
> > +++ b/drivers/gpu/drm/vkms/tests/vkms_config_test.c
> > @@ -27,6 +27,7 @@ static void vkms_config_test_empty_config(struct kunit *test)
> > KUNIT_EXPECT_TRUE(test, list_empty(&config->planes));
> > KUNIT_EXPECT_TRUE(test, list_empty(&config->crtcs));
> > KUNIT_EXPECT_TRUE(test, list_empty(&config->encoders));
> > + KUNIT_EXPECT_TRUE(test, list_empty(&config->connectors));
>
> Ditto
> With this modification:
> Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
>
> > KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config));
> > @@ -103,6 +104,9 @@ static void vkms_config_test_default_config(struct kunit *test)
> > /* Encoders */
> > KUNIT_EXPECT_EQ(test, list_count_nodes(&config->encoders), 1);
> > + /* Connectors */
> > + KUNIT_EXPECT_EQ(test, list_count_nodes(&config->connectors), 1);
> > +
> > KUNIT_EXPECT_TRUE(test, vkms_config_is_valid(config));
> > vkms_config_destroy(config);
> > @@ -232,6 +236,51 @@ static void vkms_config_test_get_encoders(struct kunit *test)
> > vkms_config_destroy(config);
> > }
> > +static void vkms_config_test_get_connectors(struct kunit *test)
> > +{
> > + struct vkms_config *config;
> > + struct vkms_config_connector *connector_cfg;
> > + struct vkms_config_connector *connector_cfg1, *connector_cfg2;
> > + int n_connectors = 0;
> > +
> > + config = vkms_config_create("test");
> > + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
> > +
> > + vkms_config_for_each_connector(config, connector_cfg)
> > + n_connectors++;
> > + KUNIT_ASSERT_EQ(test, n_connectors, 0);
> > +
> > + connector_cfg1 = vkms_config_create_connector(config);
> > + vkms_config_for_each_connector(config, connector_cfg) {
> > + n_connectors++;
> > + if (connector_cfg != connector_cfg1)
> > + KUNIT_FAIL(test, "Unexpected connector");
> > + }
> > + KUNIT_ASSERT_EQ(test, n_connectors, 1);
> > + n_connectors = 0;
> > +
> > + connector_cfg2 = vkms_config_create_connector(config);
> > + vkms_config_for_each_connector(config, connector_cfg) {
> > + n_connectors++;
> > + if (connector_cfg != connector_cfg1 &&
> > + connector_cfg != connector_cfg2)
> > + KUNIT_FAIL(test, "Unexpected connector");
> > + }
> > + KUNIT_ASSERT_EQ(test, n_connectors, 2);
> > + n_connectors = 0;
> > +
> > + vkms_config_destroy_connector(connector_cfg2);
> > + vkms_config_for_each_connector(config, connector_cfg) {
> > + n_connectors++;
> > + if (connector_cfg != connector_cfg1)
> > + KUNIT_FAIL(test, "Unexpected connector");
> > + }
> > + KUNIT_ASSERT_EQ(test, n_connectors, 1);
> > + n_connectors = 0;
> > +
> > + vkms_config_destroy(config);
> > +}
> > +
> > static void vkms_config_test_invalid_plane_number(struct kunit *test)
> > {
> > struct vkms_config *config;
> > @@ -439,6 +488,29 @@ static void vkms_config_test_valid_encoder_possible_crtcs(struct kunit *test)
> > vkms_config_destroy(config);
> > }
> > +static void vkms_config_test_invalid_connector_number(struct kunit *test)
> > +{
> > + struct vkms_config *config;
> > + struct vkms_config_connector *connector_cfg;
> > + int n;
> > +
> > + config = vkms_config_default_create(false, false, false);
> > + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
> > +
> > + /* Invalid: No connectors */
> > + connector_cfg = list_first_entry(&config->connectors, typeof(*connector_cfg), link);
> > + vkms_config_destroy_connector(connector_cfg);
> > + KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config));
> > +
> > + /* Invalid: Too many connectors */
> > + for (n = 0; n <= 32; n++)
> > + connector_cfg = vkms_config_create_connector(config);
> > +
> > + KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config));
> > +
> > + vkms_config_destroy(config);
> > +}
> > +
> > static void vkms_config_test_attach_different_configs(struct kunit *test)
> > {
> > struct vkms_config *config1, *config2;
> > @@ -678,12 +750,14 @@ static struct kunit_case vkms_config_test_cases[] = {
> > KUNIT_CASE(vkms_config_test_get_planes),
> > KUNIT_CASE(vkms_config_test_get_crtcs),
> > KUNIT_CASE(vkms_config_test_get_encoders),
> > + KUNIT_CASE(vkms_config_test_get_connectors),
> > KUNIT_CASE(vkms_config_test_invalid_plane_number),
> > KUNIT_CASE(vkms_config_test_valid_plane_type),
> > KUNIT_CASE(vkms_config_test_valid_plane_possible_crtcs),
> > KUNIT_CASE(vkms_config_test_invalid_crtc_number),
> > 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_attach_different_configs),
> > KUNIT_CASE(vkms_config_test_plane_attach_crtc),
> > KUNIT_CASE(vkms_config_test_plane_get_possible_crtcs),
> > diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms_config.c
> > index 17262a9c2567..fbbdee6068ce 100644
> > --- a/drivers/gpu/drm/vkms/vkms_config.c
> > +++ b/drivers/gpu/drm/vkms/vkms_config.c
> > @@ -25,6 +25,7 @@ struct vkms_config *vkms_config_create(const char *dev_name)
> > INIT_LIST_HEAD(&config->planes);
> > INIT_LIST_HEAD(&config->crtcs);
> > INIT_LIST_HEAD(&config->encoders);
> > + INIT_LIST_HEAD(&config->connectors);
> > return config;
> > }
> > @@ -38,6 +39,7 @@ struct vkms_config *vkms_config_default_create(bool enable_cursor,
> > 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 n;
> > config = vkms_config_create(DEFAULT_DEVICE_NAME);
> > @@ -89,6 +91,10 @@ struct vkms_config *vkms_config_default_create(bool enable_cursor,
> > if (vkms_config_encoder_attach_crtc(encoder_cfg, crtc_cfg))
> > goto err_alloc;
> > + connector_cfg = vkms_config_create_connector(config);
> > + if (IS_ERR(connector_cfg))
> > + goto err_alloc;
> > +
> > return config;
> > err_alloc:
> > @@ -102,6 +108,7 @@ void vkms_config_destroy(struct vkms_config *config)
> > struct vkms_config_plane *plane_cfg, *plane_tmp;
> > struct vkms_config_crtc *crtc_cfg, *crtc_tmp;
> > struct vkms_config_encoder *encoder_cfg, *encoder_tmp;
> > + struct vkms_config_connector *connector_cfg, *connector_tmp;
> > list_for_each_entry_safe(plane_cfg, plane_tmp, &config->planes, link)
> > vkms_config_destroy_plane(plane_cfg);
> > @@ -112,6 +119,9 @@ void vkms_config_destroy(struct vkms_config *config)
> > list_for_each_entry_safe(encoder_cfg, encoder_tmp, &config->encoders, link)
> > vkms_config_destroy_encoder(config, encoder_cfg);
> > + list_for_each_entry_safe(connector_cfg, connector_tmp, &config->connectors, link)
> > + vkms_config_destroy_connector(connector_cfg);
> > +
> > kfree_const(config->dev_name);
> > kfree(config);
> > }
> > @@ -255,6 +265,20 @@ static bool valid_encoder_possible_crtcs(const struct vkms_config *config)
> > return true;
> > }
> > +static bool valid_connector_number(const struct vkms_config *config)
> > +{
> > + struct drm_device *dev = config->dev ? &config->dev->drm : NULL;
> > + size_t n_connectors;
> > +
> > + n_connectors = list_count_nodes((struct list_head *)&config->connectors);
> > + if (n_connectors <= 0 || n_connectors >= 32) {
> > + drm_info(dev, "The number of connectors must be between 1 and 31\n");
> > + return false;
> > + }
> > +
> > + return true;
> > +}
> > +
> > bool vkms_config_is_valid(const struct vkms_config *config)
> > {
> > struct vkms_config_crtc *crtc_cfg;
> > @@ -268,6 +292,9 @@ bool vkms_config_is_valid(const struct vkms_config *config)
> > if (!valid_encoder_number(config))
> > return false;
> > + if (!valid_connector_number(config))
> > + return false;
> > +
> > if (!valid_plane_possible_crtcs(config))
> > return false;
> > @@ -292,6 +319,7 @@ static int vkms_config_show(struct seq_file *m, void *data)
> > struct vkms_config_plane *plane_cfg;
> > struct vkms_config_crtc *crtc_cfg;
> > struct vkms_config_encoder *encoder_cfg;
> > + struct vkms_config_connector *connector_cfg;
> > dev_name = vkms_config_get_device_name((struct vkms_config *)vkmsdev->config);
> > seq_printf(m, "dev_name=%s\n", dev_name);
> > @@ -311,6 +339,9 @@ static int vkms_config_show(struct seq_file *m, void *data)
> > vkms_config_for_each_encoder(vkmsdev->config, encoder_cfg)
> > seq_puts(m, "encoder\n");
> > + vkms_config_for_each_connector(vkmsdev->config, connector_cfg)
> > + seq_puts(m, "connector\n");
> > +
> > return 0;
> > }
> > @@ -520,3 +551,26 @@ void vkms_config_encoder_detach_crtc(struct vkms_config_encoder *encoder_cfg,
> > }
> > }
> > EXPORT_SYMBOL_IF_KUNIT(vkms_config_encoder_detach_crtc);
> > +
> > +struct vkms_config_connector *vkms_config_create_connector(struct vkms_config *config)
> > +{
> > + struct vkms_config_connector *connector_cfg;
> > +
> > + connector_cfg = kzalloc(sizeof(*connector_cfg), GFP_KERNEL);
> > + if (!connector_cfg)
> > + return ERR_PTR(-ENOMEM);
> > +
> > + connector_cfg->config = config;
> > +
> > + list_add_tail(&connector_cfg->link, &config->connectors);
> > +
> > + return connector_cfg;
> > +}
> > +EXPORT_SYMBOL_IF_KUNIT(vkms_config_create_connector);
> > +
> > +void vkms_config_destroy_connector(struct vkms_config_connector *connector_cfg)
> > +{
> > + list_del(&connector_cfg->link);
> > + kfree(connector_cfg);
> > +}
> > +EXPORT_SYMBOL_IF_KUNIT(vkms_config_destroy_connector);
> > diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms_config.h
> > index 3e5b2e407378..73562c894102 100644
> > --- a/drivers/gpu/drm/vkms/vkms_config.h
> > +++ b/drivers/gpu/drm/vkms/vkms_config.h
> > @@ -16,6 +16,7 @@
> > * @planes: List of planes configured for the device
> > * @crtcs: List of CRTCs configured for the device
> > * @encoders: List of encoders configured for the device
> > + * @connectors: List of connectors configured for the device
> > * @dev: Used to store the current VKMS device. Only set when the device is instantiated.
> > */
> > struct vkms_config {
> > @@ -23,6 +24,7 @@ struct vkms_config {
> > struct list_head planes;
> > struct list_head crtcs;
> > struct list_head encoders;
> > + struct list_head connectors;
> > struct vkms_device *dev;
> > };
> > @@ -92,6 +94,24 @@ struct vkms_config_encoder {
> > struct drm_encoder *encoder;
> > };
> > +/**
> > + * struct vkms_config_connector
> > + *
> > + * @link: Link to the others connector in vkms_config
> > + * @config: The vkms_config this connector belongs to
> > + * @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
> > + * configuration and must be managed by other means.
> > + */
> > +struct vkms_config_connector {
> > + struct list_head link;
> > + struct vkms_config *config;
> > +
> > + /* Internal usage */
> > + struct vkms_connector *connector;
> > +};
> > +
> > /**
> > * vkms_config_for_each_plane - Iterate over the vkms_config planes
> > * @config: &struct vkms_config pointer
> > @@ -116,6 +136,14 @@ struct vkms_config_encoder {
> > #define vkms_config_for_each_encoder(config, encoder_cfg) \
> > list_for_each_entry((encoder_cfg), &(config)->encoders, link)
> > +/**
> > + * vkms_config_for_each_connector - Iterate over the vkms_config connectors
> > + * @config: &struct vkms_config pointer
> > + * @connector_cfg: &struct vkms_config_connector pointer used as cursor
> > + */
> > +#define vkms_config_for_each_connector(config, connector_cfg) \
> > + list_for_each_entry((connector_cfg), &(config)->connectors, link)
> > +
> > /**
> > * vkms_config_plane_for_each_possible_crtc - Iterate over the vkms_config_plane
> > * possible CRTCs
> > @@ -361,4 +389,20 @@ int __must_check vkms_config_encoder_attach_crtc(struct vkms_config_encoder *enc
> > void vkms_config_encoder_detach_crtc(struct vkms_config_encoder *encoder_cfg,
> > struct vkms_config_crtc *crtc_cfg);
> > +/**
> > + * vkms_config_create_connector() - Add a new connector configuration
> > + * @config: Configuration to add the connector to
> > + *
> > + * Returns:
> > + * The new connector configuration or an error. Call
> > + * vkms_config_destroy_connector() to free the returned connector configuration.
> > + */
> > +struct vkms_config_connector *vkms_config_create_connector(struct vkms_config *config);
> > +
> > +/**
> > + * vkms_config_destroy_connector() - Remove and free a connector configuration
> > + * @connector_cfg: Connector configuration to destroy
> > + */
> > +void vkms_config_destroy_connector(struct vkms_config_connector *connector_cfg);
> > +
> > #endif /* _VKMS_CONFIG_H_ */
> > diff --git a/drivers/gpu/drm/vkms/vkms_connector.c b/drivers/gpu/drm/vkms/vkms_connector.c
> > index ab8b52a84151..48b10cba322a 100644
> > --- a/drivers/gpu/drm/vkms/vkms_connector.c
> > +++ b/drivers/gpu/drm/vkms/vkms_connector.c
> > @@ -25,8 +25,19 @@ static int vkms_conn_get_modes(struct drm_connector *connector)
> > return count;
> > }
> > +static struct drm_encoder *vkms_conn_best_encoder(struct drm_connector *connector)
> > +{
> > + struct drm_encoder *encoder;
> > +
> > + drm_connector_for_each_possible_encoder(connector, encoder)
> > + return encoder;
> > +
> > + return NULL;
> > +}
> > +
>
> Not for this series, but does it make sense to make the "best_encoder"
> configurable?
Yes, definitely something we can configure in the future. The "pick the
first one" algorithm leaves room for improvement.
Sending v4 with the requested changes :)
Jose
> Thanks,
> Louis Chauvet
>
> > static const struct drm_connector_helper_funcs vkms_conn_helper_funcs = {
> > .get_modes = vkms_conn_get_modes,
> > + .best_encoder = vkms_conn_best_encoder,
> > };
> > struct vkms_connector *vkms_connector_init(struct vkms_device *vkmsdev)
>
> --
> Louis Chauvet, Bootlin
> Embedded Linux and Kernel engineering
> https://bootlin.com
>
next prev parent reply other threads:[~2025-02-18 10:11 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-02-17 10:01 [PATCH v3 00/14] drm/vkms: Allow to configure device José Expósito
2025-02-17 10:01 ` [PATCH v3 01/14] drm/vkms: Extract vkms_connector header José Expósito
2025-02-17 10:01 ` [PATCH v3 02/14] drm/vkms: Create vkms_connector struct José Expósito
2025-02-17 10:01 ` [PATCH v3 03/14] drm/vkms: Add KUnit test scaffolding José Expósito
2025-02-17 10:01 ` [PATCH v3 04/14] drm/vkms: Extract vkms_config header José Expósito
2025-02-17 10:01 ` [PATCH v3 05/14] drm/vkms: Move default_config creation to its own function José Expósito
2025-02-17 10:01 ` [PATCH v3 06/14] drm/vkms: Set device name from vkms_config José Expósito
2025-02-17 10:01 ` [PATCH v3 07/14] drm/vkms: Add a validation function for VKMS configuration José Expósito
2025-02-17 10:01 ` [PATCH v3 08/14] drm/vkms: Allow to configure multiple planes José Expósito
2025-02-17 15:45 ` Louis Chauvet
2025-02-17 16:34 ` José Expósito
2025-02-17 17:06 ` Louis Chauvet
2025-02-17 10:01 ` [PATCH v3 09/14] drm/vkms: Allow to configure multiple CRTCs José Expósito
2025-02-17 15:45 ` Louis Chauvet
2025-02-17 10:01 ` [PATCH v3 10/14] drm/vkms: Allow to attach planes and CRTCs José Expósito
2025-02-17 15:45 ` Louis Chauvet
2025-02-17 10:01 ` [PATCH v3 11/14] drm/vkms: Allow to configure multiple encoders José Expósito
2025-02-17 15:45 ` Louis Chauvet
2025-02-17 10:01 ` [PATCH v3 12/14] drm/vkms: Allow to attach encoders and CRTCs José Expósito
2025-02-17 15:45 ` Louis Chauvet
2025-02-17 10:01 ` [PATCH v3 13/14] drm/vkms: Allow to configure multiple connectors José Expósito
2025-02-17 15:45 ` Louis Chauvet
2025-02-18 10:11 ` José Expósito [this message]
2025-02-17 10:01 ` [PATCH v3 14/14] drm/vkms: Allow to attach connectors and encoders José Expósito
2025-02-17 15:45 ` Louis Chauvet
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Z7RcyT2XEVYiNZ70@fedora \
--to=jose.exposito89@gmail.com \
--cc=airlied@gmail.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=hamohammed.sa@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=louis.chauvet@bootlin.com \
--cc=maarten.lankhorst@linux.intel.com \
--cc=melissa.srw@gmail.com \
--cc=mripard@kernel.org \
--cc=simona@ffwll.ch \
--cc=tzimmermann@suse.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.