From: Louis Chauvet <louis.chauvet@bootlin.com>
To: Haneen Mohammed <hamohammed.sa@gmail.com>,
Simona Vetter <simona@ffwll.ch>,
Melissa Wen <melissa.srw@gmail.com>,
Maarten Lankhorst <maarten.lankhorst@linux.intel.com>,
Maxime Ripard <mripard@kernel.org>,
Thomas Zimmermann <tzimmermann@suse.de>,
David Airlie <airlied@gmail.com>,
jose.exposito89@gmail.com, Jonathan Corbet <corbet@lwn.net>,
Shuah Khan <skhan@linuxfoundation.org>,
Miguel Ojeda <ojeda@kernel.org>,
Nathan Chancellor <nathan@kernel.org>,
Nick Desaulniers <nick.desaulniers+lkml@gmail.com>,
Bill Wendling <morbo@google.com>,
Justin Stitt <justinstitt@google.com>
Cc: victoria@system76.com, sebastian.wick@redhat.com,
victoria@system76.com, airlied@gmail.com,
thomas.petazzoni@bootlin.com, dri-devel@lists.freedesktop.org,
linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org,
Louis Chauvet <louis.chauvet@bootlin.com>,
llvm@lists.linux.dev
Subject: [PATCH v4 35/37] drm/vkms: Introduce configfs for dynamic connector creation
Date: Wed, 22 Apr 2026 18:48:32 +0200 [thread overview]
Message-ID: <20260422-vkms-all-config-v4-35-dbb52e9aadc3@bootlin.com> (raw)
In-Reply-To: <20260422-vkms-all-config-v4-0-dbb52e9aadc3@bootlin.com>
DRM allows the connector to be created after the device. To allows
emulating this, add two configfs attributes to connector to allows this.
Using the dynamic attribute you can set if a connector will be dynamic or
not.
Using the enabled attribute, you can set at runtime if a dynamic connector
is present or not.
Co-developed-by: José Expósito <jose.exposito89@gmail.com>
Signed-off-by: José Expósito <jose.exposito89@gmail.com>
Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
Documentation/ABI/testing/configfs-vkms | 14 ++++
Documentation/gpu/vkms.rst | 6 +-
drivers/gpu/drm/vkms/vkms_configfs.c | 144 ++++++++++++++++++++++++++++++--
3 files changed, 155 insertions(+), 9 deletions(-)
diff --git a/Documentation/ABI/testing/configfs-vkms b/Documentation/ABI/testing/configfs-vkms
index 8215cd3ff466..99911aa36467 100644
--- a/Documentation/ABI/testing/configfs-vkms
+++ b/Documentation/ABI/testing/configfs-vkms
@@ -62,6 +62,20 @@ Description:
Content of the EDID for this connector. Ignored if
edid_enabled is not set.
+What: /sys/kernel/config/vkms/<device>/connectors/<connector>/dynamic
+Date: Nov 2025
+Contact: dri-devel@lists.freedesktop.org
+Description:
+ Set to 1 to create a dynamic connector (emulates DP MST).
+ Value: 1 - dynamic, 0 - static.
+
+What: /sys/kernel/config/vkms/<device>/connectors/<connector>/enabled
+Date: Nov 2025
+Contact: dri-devel@lists.freedesktop.org
+Description:
+ For dynamic connectors, set to 1 to create the connector,
+ 0 to remove it. Value: 1 - enabled, 0 - disabled.
+
What: /sys/kernel/config/vkms/<device>/connectors/<connector>/possible_encoders
Date: Nov 2025
Contact: dri-devel@lists.freedesktop.org
diff --git a/Documentation/gpu/vkms.rst b/Documentation/gpu/vkms.rst
index a7d6a4a3b53b..5c013014c457 100644
--- a/Documentation/gpu/vkms.rst
+++ b/Documentation/gpu/vkms.rst
@@ -138,7 +138,7 @@ Last but not least, create one or more connectors::
sudo mkdir /config/vkms/my-vkms/connectors/connector0
-Connectors have 5 configurable attribute:
+Connectors have 7 configurable attribute:
- status: Connection status: 1 connected, 2 disconnected, 3 unknown (same values
as those exposed by the "status" property of a connector)
@@ -150,7 +150,9 @@ Connectors have 5 configurable attribute:
- edid_enabled: Enable or not EDID for this connector. Some connectors may not have an
EDID but just a list of modes, this attribute allows to disable EDID property.
- edid: Content of the EDID. Ignored if edid_enabled is not set
-
+- dynamic: Set to 1 while configuring the device to create a dynamic connector. A dynamic
+ connector can be used to emulate DP MST connectors.
+- enabled: For dynamic connector, set it to 1 to create the connector, 0 to remove it.
To finish the configuration, link the different pipeline items::
diff --git a/drivers/gpu/drm/vkms/vkms_configfs.c b/drivers/gpu/drm/vkms/vkms_configfs.c
index cf388851910b..e7752ac1cd51 100644
--- a/drivers/gpu/drm/vkms/vkms_configfs.c
+++ b/drivers/gpu/drm/vkms/vkms_configfs.c
@@ -1147,6 +1147,12 @@ static ssize_t connector_status_show(struct config_item *item, char *page)
return sprintf(page, "%u", status);
}
+static bool connector_is_enabled(struct vkms_config_connector *connector_cfg)
+{
+ return !connector_cfg->dynamic ||
+ (connector_cfg->dynamic && connector_cfg->enabled);
+}
+
static ssize_t connector_status_store(struct config_item *item,
const char *page, size_t count)
{
@@ -1166,7 +1172,7 @@ static ssize_t connector_status_store(struct config_item *item,
scoped_guard(mutex, &connector->dev->lock) {
vkms_config_connector_set_status(connector->config, status);
- if (connector->dev->enabled)
+ if (connector->dev->enabled && connector_is_enabled(connector->config))
vkms_trigger_connector_hotplug(connector->dev->config->dev);
}
@@ -1227,7 +1233,7 @@ static ssize_t connector_type_store(struct config_item *item,
}
scoped_guard(mutex, &connector->dev->lock) {
- if (connector->dev->enabled)
+ if (connector->dev->enabled && connector_is_enabled(connector->config))
return -EBUSY;
vkms_config_connector_set_type(connector->config, val);
@@ -1346,6 +1352,107 @@ static ssize_t connector_edid_store(struct config_item *item,
connector_status_disconnected)
vkms_trigger_connector_hotplug(connector->dev->config->dev);
}
+ return count;
+}
+
+static ssize_t connector_enabled_show(struct config_item *item, char *page)
+{
+ struct vkms_configfs_connector *connector;
+ bool enabled;
+
+ connector = connector_item_to_vkms_configfs_connector(item);
+
+ scoped_guard(mutex, &connector->dev->lock)
+ enabled = vkms_config_connector_is_enabled(connector->config);
+
+ return sprintf(page, "%d\n", enabled);
+}
+
+static ssize_t connector_enabled_store(struct config_item *item,
+ const char *page, size_t count)
+{
+ struct vkms_configfs_connector *connector;
+ struct vkms_config_connector *connector_cfg;
+ bool enabled, was_enabled;
+
+ connector = connector_item_to_vkms_configfs_connector(item);
+ connector_cfg = connector->config;
+
+ if (kstrtobool(page, &enabled))
+ return -EINVAL;
+ scoped_guard(mutex, &connector->dev->lock) {
+ if (!connector->dev->enabled) {
+ vkms_config_connector_set_enabled(connector_cfg, enabled);
+ } else {
+ // Only dynamic connector can be enabled/disabled at runtime
+ if (!connector_cfg->dynamic)
+ return -EBUSY;
+
+ was_enabled = vkms_config_connector_is_enabled(connector_cfg);
+ vkms_config_connector_set_enabled(connector_cfg, enabled);
+
+ // Resulting configuration is invalid (missing encoder for example)
+ // Early return to avoid drm core issue
+ if (!vkms_config_is_valid(connector->dev->config)) {
+ count = -EINVAL;
+ goto rollback;
+ }
+
+ if (!was_enabled && enabled) {
+ // Adding the connector
+ connector_cfg->connector = vkms_connector_hot_add(connector->dev->config->dev,
+ connector_cfg);
+ if (IS_ERR(connector_cfg->connector)) {
+ count = PTR_ERR(connector_cfg->connector);
+ goto rollback;
+ }
+ } else if (was_enabled && !enabled) {
+ vkms_connector_hot_remove(connector->dev->config->dev,
+ connector_cfg->connector);
+ }
+ }
+ }
+ return count;
+
+rollback:
+ vkms_config_connector_set_enabled(connector_cfg, was_enabled);
+ return count;
+}
+
+static ssize_t connector_dynamic_show(struct config_item *item, char *page)
+{
+ struct vkms_configfs_connector *connector;
+ bool enabled;
+
+ connector = connector_item_to_vkms_configfs_connector(item);
+
+ scoped_guard(mutex, &connector->dev->lock) {
+ enabled = vkms_config_connector_is_dynamic(connector->config);
+ }
+
+ return sprintf(page, "%d\n", enabled);
+}
+
+static ssize_t connector_dynamic_store(struct config_item *item,
+ const char *page, size_t count)
+{
+ struct vkms_configfs_connector *connector;
+ struct vkms_config_connector *connector_cfg;
+ bool dynamic;
+
+ connector = connector_item_to_vkms_configfs_connector(item);
+ connector_cfg = connector->config;
+
+ if (kstrtobool(page, &dynamic))
+ return -EINVAL;
+
+ scoped_guard(mutex, &connector->dev->lock) {
+ // Can't change the dynamic status when the device is activated
+ if (connector->dev->enabled)
+ return -EBUSY;
+
+ vkms_config_connector_set_dynamic(connector_cfg, dynamic);
+ }
return count;
}
@@ -1355,6 +1462,8 @@ CONFIGFS_ATTR(connector_, type);
CONFIGFS_ATTR(connector_, supported_colorspaces);
CONFIGFS_ATTR(connector_, edid_enabled);
CONFIGFS_ATTR(connector_, edid);
+CONFIGFS_ATTR(connector_, dynamic);
+CONFIGFS_ATTR(connector_, enabled);
static struct configfs_attribute *connector_item_attrs[] = {
&connector_attr_status,
@@ -1362,19 +1471,28 @@ static struct configfs_attribute *connector_item_attrs[] = {
&connector_attr_supported_colorspaces,
&connector_attr_edid_enabled,
&connector_attr_edid,
+ &connector_attr_dynamic,
+ &connector_attr_enabled,
NULL,
};
static void connector_release(struct config_item *item)
{
struct vkms_configfs_connector *connector;
+ struct vkms_config_connector *connector_cfg;
struct mutex *lock;
connector = connector_item_to_vkms_configfs_connector(item);
+ connector_cfg = connector->config;
lock = &connector->dev->lock;
scoped_guard(mutex, lock) {
+ if (connector->dev->enabled && connector_cfg->dynamic && connector_cfg->enabled)
+ vkms_connector_hot_remove(connector->dev->config->dev,
+ connector_cfg->connector);
+
vkms_config_destroy_connector(connector->config);
+
kfree(connector);
}
}
@@ -1393,6 +1511,7 @@ static int connector_possible_encoders_allow_link(struct config_item *src,
struct config_item *target)
{
struct vkms_configfs_connector *connector;
+ struct vkms_config_connector *connector_cfg;
struct vkms_configfs_encoder *encoder;
int ret;
@@ -1400,14 +1519,25 @@ static int connector_possible_encoders_allow_link(struct config_item *src,
return -EINVAL;
connector = connector_possible_encoders_item_to_vkms_configfs_connector(src);
+ connector_cfg = connector->config;
encoder = encoder_item_to_vkms_configfs_encoder(target);
scoped_guard(mutex, &connector->dev->lock) {
- if (connector->dev->enabled)
- return -EBUSY;
+ if (connector->dev->enabled && connector_cfg->enabled) {
+ if (!connector_cfg->dynamic)
+ return -EBUSY;
+
+ ret = vkms_connector_hot_attach_encoder(connector->dev->config->dev,
+ connector->config->connector,
+ encoder->config->encoder);
+ if (ret)
+ return ret;
+ }
ret = vkms_config_connector_attach_encoder(connector->config,
encoder->config);
+ if (ret)
+ return ret;
}
return ret;
@@ -1448,9 +1578,6 @@ static struct config_group *make_connector_group(struct config_group *group,
dev = child_group_to_vkms_configfs_device(group);
scoped_guard(mutex, &dev->lock) {
- if (dev->enabled)
- return ERR_PTR(-EBUSY);
-
connector = kzalloc(sizeof(*connector), GFP_KERNEL);
if (!connector)
return ERR_PTR(-ENOMEM);
@@ -1464,6 +1591,9 @@ static struct config_group *make_connector_group(struct config_group *group,
return ERR_PTR(ret);
}
+ vkms_config_connector_set_dynamic(connector->config, connector->dev->enabled);
+ vkms_config_connector_set_enabled(connector->config, !connector->dev->enabled);
+
config_group_init_type_name(&connector->group, name,
&connector_item_type);
--
2.54.0
next prev parent reply other threads:[~2026-04-22 16:50 UTC|newest]
Thread overview: 39+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-22 16:47 [PATCH v4 00/37] VKMS: Introduce multiple configFS attributes Louis Chauvet
2026-04-22 16:47 ` [PATCH v4 01/37] drm/drm_mode_config: Add helper to get plane type name Louis Chauvet
2026-04-22 16:47 ` [PATCH v4 02/37] drm/blend: Get a rotation name from it's bitfield Louis Chauvet
2026-04-22 16:52 ` Ville Syrjälä
2026-04-22 16:48 ` [PATCH v4 03/37] drm/drm_color_mgmt: Expose drm_get_color_encoding_name Louis Chauvet
2026-04-22 16:48 ` [PATCH v4 04/37] drm/drm_color_mgmt: Expose drm_get_color_range_name Louis Chauvet
2026-04-22 16:48 ` [PATCH v4 05/37] drm/connector: Export drm_get_colorspace_name Louis Chauvet
2026-04-22 16:48 ` [PATCH v4 06/37] drm/drm_atomic_state_helper: Properly load default value for rotation Louis Chauvet
2026-04-22 16:48 ` [PATCH v4 07/37] Documentation: ABI: vkms: Add current VKMS ABI documentation Louis Chauvet
2026-04-22 16:48 ` [PATCH v4 08/37] drm/vkms: Add error handling in plane config creation Louis Chauvet
2026-04-22 16:48 ` [PATCH v4 09/37] drm/vkms: Simplify plane_release code Louis Chauvet
2026-04-22 16:48 ` [PATCH v4 10/37] drm/vkms: Explicitly display plane type Louis Chauvet
2026-04-22 16:48 ` [PATCH v4 11/37] drm/vkms: Use enabled/disabled instead of 1/0 for debug Louis Chauvet
2026-04-22 16:48 ` [PATCH v4 12/37] drm/vkms: Explicitly display connector status Louis Chauvet
2026-04-22 16:48 ` [PATCH v4 13/37] drm/vkms: Introduce config for plane name Louis Chauvet
2026-04-22 16:48 ` [PATCH v4 14/37] drm/vkms: Introduce configfs " Louis Chauvet
2026-04-22 16:48 ` [PATCH v4 15/37] drm/vkms: Introduce config for plane rotation Louis Chauvet
2026-04-22 16:48 ` [PATCH v4 16/37] drm/vkms: Introduce configfs " Louis Chauvet
2026-04-22 16:48 ` [PATCH v4 17/37] drm/vkms: Introduce config for plane color encoding Louis Chauvet
2026-04-22 16:48 ` [PATCH v4 18/37] drm/vkms: Introduce configfs " Louis Chauvet
2026-04-22 16:48 ` [PATCH v4 19/37] drm/vkms: Introduce config for plane color range Louis Chauvet
2026-04-22 16:48 ` [PATCH v4 20/37] drm/vkms: Introduce configfs " Louis Chauvet
2026-04-22 16:48 ` [PATCH v4 21/37] drm/vkms: Introduce config for plane format Louis Chauvet
2026-04-22 16:48 ` [PATCH v4 22/37] drm/vkms: Introduce configfs " Louis Chauvet
2026-04-22 16:48 ` [PATCH v4 23/37] drm/vkms: Properly render plane using their zpos Louis Chauvet
2026-04-22 16:48 ` [PATCH v4 24/37] drm/vkms: Introduce config for plane zpos property Louis Chauvet
2026-04-22 16:48 ` [PATCH v4 25/37] drm/vkms: Introduce configfs " Louis Chauvet
2026-04-22 16:48 ` [PATCH v4 26/37] drm/vkms: Introduce config for connector type Louis Chauvet
2026-04-22 16:48 ` [PATCH v4 27/37] drm/vkms: Introduce configfs " Louis Chauvet
2026-04-22 16:48 ` [PATCH v4 28/37] drm/vkms: Rename vkms_connector_init to vkms_connector_init_static Louis Chauvet
2026-04-22 16:48 ` [PATCH v4 29/37] drm/vkms: Introduce config for connector supported colorspace Louis Chauvet
2026-04-22 16:48 ` [PATCH v4 30/37] drm/vkms: Introduce configfs " Louis Chauvet
2026-04-22 16:48 ` [PATCH v4 31/37] drm/vkms: Introduce config for connector EDID Louis Chauvet
2026-04-22 16:48 ` [PATCH v4 32/37] drm/vkms: Introduce configfs " Louis Chauvet
2026-04-22 16:48 ` [PATCH v4 33/37] drm/vkms: Store the enabled/disabled status for connector Louis Chauvet
2026-04-22 16:48 ` [PATCH v4 34/37] drm/vkms: Allow to hot-add connectors Louis Chauvet
2026-04-22 16:48 ` Louis Chauvet [this message]
2026-04-22 16:48 ` [PATCH v4 36/37] drm/vkms: Add connector parent configuration in vkms_config Louis Chauvet
2026-04-22 16:48 ` [PATCH v4 37/37] drm/vkms: Add ConfigFS interface for connector parent and port_id 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=20260422-vkms-all-config-v4-35-dbb52e9aadc3@bootlin.com \
--to=louis.chauvet@bootlin.com \
--cc=airlied@gmail.com \
--cc=corbet@lwn.net \
--cc=dri-devel@lists.freedesktop.org \
--cc=hamohammed.sa@gmail.com \
--cc=jose.exposito89@gmail.com \
--cc=justinstitt@google.com \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=llvm@lists.linux.dev \
--cc=maarten.lankhorst@linux.intel.com \
--cc=melissa.srw@gmail.com \
--cc=morbo@google.com \
--cc=mripard@kernel.org \
--cc=nathan@kernel.org \
--cc=nick.desaulniers+lkml@gmail.com \
--cc=ojeda@kernel.org \
--cc=sebastian.wick@redhat.com \
--cc=simona@ffwll.ch \
--cc=skhan@linuxfoundation.org \
--cc=thomas.petazzoni@bootlin.com \
--cc=tzimmermann@suse.de \
--cc=victoria@system76.com \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox