[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250121-google-config-fs-v3-7-8154a6945142@bootlin.com>
Date: Tue, 21 Jan 2025 15:34:51 +0100
From: Louis Chauvet <louis.chauvet@...tlin.com>
To: Rodrigo Siqueira <rodrigosiqueiramelo@...il.com>,
Melissa Wen <melissa.srw@...il.com>,
Maíra Canal <mairacanal@...eup.net>,
Haneen Mohammed <hamohammed.sa@...il.com>,
Maarten Lankhorst <maarten.lankhorst@...ux.intel.com>,
Maxime Ripard <mripard@...nel.org>, Thomas Zimmermann <tzimmermann@...e.de>,
David Airlie <airlied@...il.com>, Simona Vetter <simona@...ll.ch>,
Simona Vetter <simona.vetter@...ll.ch>
Cc: jose.exposito89@...il.com, dri-devel@...ts.freedesktop.org,
arthurgrillo@...eup.net, linux-kernel@...r.kernel.org,
jeremie.dautheribes@...tlin.com, miquel.raynal@...tlin.com,
thomas.petazzoni@...tlin.com, seanpaul@...gle.com, nicolejadeyee@...gle.com,
Louis Chauvet <louis.chauvet@...tlin.com>
Subject: [PATCH RFC v3 07/14] drm/vkms: Introduce configfs for connectors
To allows the userspace to test many hardware configuration, introduce a
new interface to create and configure connectors.
The connectors are created by creating a directory in the `connectors`
directory.
Connectors and encoders can be linked by creating a symlink in the
possible_encoders directory.
The current interface is:
/config/vkms
DEVICE_1
┣━ enable
┣━ planes
┃ ┗━ [...]
┣━ connectors
┃ ┗━ CONNECTOR_1
┃ ┗━ possible_encoders
┃ ┗━ >> DEVICE_1/encoders/ENCODER_1
┗━ encoders
┗━ ENCODER_1
Signed-off-by: Louis Chauvet <louis.chauvet@...tlin.com>
---
drivers/gpu/drm/vkms/vkms_config.c | 13 ++++
drivers/gpu/drm/vkms/vkms_config.h | 3 +
drivers/gpu/drm/vkms/vkms_configfs.c | 138 +++++++++++++++++++++++++++++++++++
drivers/gpu/drm/vkms/vkms_configfs.h | 23 ++++++
4 files changed, 177 insertions(+)
diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms_config.c
index 8ac9cd52cc00f7c317f2514a73c3d2f3908b085b..cb97bf292b72e9faf0050338fe845a254f691987 100644
--- a/drivers/gpu/drm/vkms/vkms_config.c
+++ b/drivers/gpu/drm/vkms/vkms_config.c
@@ -479,6 +479,19 @@ vkms_config_connector_attach_encoder(struct vkms_config_connector *vkms_config_c
return ret;
}
+void vkms_config_connector_detach_encoder(struct vkms_config_connector *vkms_config_connector,
+ struct vkms_config_encoder *vkms_config_encoder)
+{
+ struct vkms_config_encoder *encoder_entry;
+ unsigned long encoder_idx;
+
+ xa_for_each(&vkms_config_connector->possible_encoders, encoder_idx, encoder_entry) {
+ if (encoder_entry == vkms_config_encoder)
+ break;
+ }
+ xa_erase(&vkms_config_connector->possible_encoders, encoder_idx);
+}
+
bool vkms_config_is_valid(struct vkms_config *config)
{
struct vkms_config_plane *config_plane;
diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms_config.h
index 2e5d2aa34a4f039c738cb9ac5642f3c75df36ba7..57cdf5fc2df1a62f57b4588c36ad0a99f63bee2a 100644
--- a/drivers/gpu/drm/vkms/vkms_config.h
+++ b/drivers/gpu/drm/vkms/vkms_config.h
@@ -189,6 +189,9 @@ int __must_check vkms_config_encoder_attach_crtc(struct vkms_config_encoder *vkm
int __must_check
vkms_config_connector_attach_encoder(struct vkms_config_connector *vkms_config_connector,
struct vkms_config_encoder *vkms_config_encoder);
+void vkms_config_connector_detach_encoder(struct vkms_config_connector *vkms_config_connector,
+ struct vkms_config_encoder *vkms_config_encoder);
+
/**
* vkms_config_delete_plane() - Remove a plane configuration and frees its memory
*
diff --git a/drivers/gpu/drm/vkms/vkms_configfs.c b/drivers/gpu/drm/vkms/vkms_configfs.c
index 9f41506849552960970aa08b9329b4f88d0aa8e7..8bb3223c810dddb7d713ad4b01cece825f9939f6 100644
--- a/drivers/gpu/drm/vkms/vkms_configfs.c
+++ b/drivers/gpu/drm/vkms/vkms_configfs.c
@@ -536,6 +536,7 @@ static struct config_group *encoder_make_group(struct config_group *config_group
}
strscpy(vkms_configfs_encoder->vkms_config_encoder->name, name, strlen(name) + 1);
+
config_group_init_type_name(&vkms_configfs_encoder->group, name,
&encoder_item_type);
@@ -559,6 +560,139 @@ static const struct config_item_type encoders_item_type = {
.ct_owner = THIS_MODULE,
};
+static int connector_possible_encoders_allow_link(struct config_item *src,
+ struct config_item *target)
+{
+ struct vkms_config_encoder *vkms_config_encoder;
+ struct vkms_configfs_device *vkms_configfs =
+ connector_possible_encoder_src_item_to_vkms_configfs_device
+ (src);
+
+ mutex_lock(&vkms_configfs->lock);
+
+ if (target->ci_type != &encoder_item_type) {
+ DRM_ERROR("Unable to link non-CRTCs.\n");
+ mutex_unlock(&vkms_configfs->lock);
+ return -EINVAL;
+ }
+
+ vkms_config_encoder = encoder_item_to_vkms_configfs_encoder(target)
+ ->vkms_config_encoder;
+ struct vkms_config_connector *vkms_config_connector =
+ connector_possible_encoder_src_item_to_vkms_configfs_connector
+ (src)
+ ->vkms_config_connector;
+
+ if (vkms_config_connector_attach_encoder(vkms_config_connector,
+ vkms_config_encoder))
+ return -EINVAL;
+
+ mutex_unlock(&vkms_configfs->lock);
+
+ return 0;
+}
+
+static void connector_possible_encoders_drop_link(struct config_item *src,
+ struct config_item *target)
+{
+ struct vkms_config_encoder *vkms_config_encoder;
+ struct vkms_configfs_device *vkms_configfs =
+ connector_possible_encoder_src_item_to_vkms_configfs_device(src);
+
+ mutex_lock(&vkms_configfs->lock);
+
+ vkms_config_encoder = encoder_item_to_vkms_configfs_encoder(target)->vkms_config_encoder;
+ struct vkms_config_connector *vkms_config_connector =
+ connector_possible_encoder_src_item_to_vkms_configfs_connector(src)
+ ->vkms_config_connector;
+
+ vkms_config_connector_detach_encoder(vkms_config_connector, vkms_config_encoder);
+
+ mutex_unlock(&vkms_configfs->lock);
+}
+
+static struct configfs_item_operations connector_possible_encoders_item_operations = {
+ .allow_link = &connector_possible_encoders_allow_link,
+ .drop_link = &connector_possible_encoders_drop_link,
+};
+
+static struct config_item_type connector_possible_encoders_item_type = {
+ .ct_item_ops = &connector_possible_encoders_item_operations,
+ .ct_owner = THIS_MODULE,
+};
+
+static void connector_release(struct config_item *item)
+{
+ struct vkms_configfs_connector *vkms_configfs_connector =
+ connector_item_to_vkms_configfs_connector(item);
+
+ mutex_lock(&vkms_configfs_connector->vkms_configfs_device->lock);
+ vkms_config_delete_connector(vkms_configfs_connector->vkms_config_connector);
+ mutex_unlock(&vkms_configfs_connector->vkms_configfs_device->lock);
+
+ kfree(vkms_configfs_connector);
+}
+
+static struct configfs_item_operations connector_item_operations = {
+ .release = connector_release,
+};
+
+static const struct config_item_type connector_item_type = {
+ .ct_item_ops = &connector_item_operations,
+ .ct_owner = THIS_MODULE,
+};
+
+static struct config_group *connector_make_group(struct config_group *config_group,
+ const char *name)
+{
+ struct vkms_configfs_device *vkms_configfs =
+ connector_item_to_vkms_configfs_device(&config_group->cg_item);
+ struct vkms_configfs_connector *vkms_configfs_connector;
+
+ vkms_configfs_connector = kzalloc(sizeof(*vkms_configfs_connector), GFP_KERNEL);
+
+ if (!vkms_configfs_connector)
+ return ERR_PTR(-ENOMEM);
+
+ mutex_lock(&vkms_configfs->lock);
+
+ if (vkms_configfs->enabled) {
+ kfree(vkms_configfs_connector);
+ mutex_unlock(&vkms_configfs->lock);
+ return ERR_PTR(-EINVAL);
+ }
+
+ vkms_configfs_connector->vkms_config_connector =
+ vkms_config_create_connector(vkms_configfs->vkms_config);
+
+ if (!vkms_configfs_connector->vkms_config_connector) {
+ kfree(vkms_configfs_connector);
+ mutex_unlock(&vkms_configfs->lock);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ config_group_init_type_name(&vkms_configfs_connector->group, name, &connector_item_type);
+
+ config_group_init_type_name(&vkms_configfs_connector->possible_encoder_group,
+ "possible_encoders", &connector_possible_encoders_item_type);
+ configfs_add_default_group(&vkms_configfs_connector->possible_encoder_group,
+ &vkms_configfs_connector->group);
+ vkms_configfs_connector->vkms_configfs_device = vkms_configfs;
+
+ mutex_unlock(&vkms_configfs->lock);
+
+ return &vkms_configfs_connector->group;
+}
+
+static struct configfs_group_operations connector_group_operations = {
+ .make_group = &connector_make_group,
+};
+
+static const struct config_item_type connectors_item_type = {
+ .ct_group_ops = &connector_group_operations,
+ .ct_owner = THIS_MODULE,
+};
+
/**
* configfs_lock_dependencies() - In order to forbid the userspace to delete items when the
* device is enabled, mark all configfs items as dependent
@@ -705,6 +839,10 @@ static struct config_group *root_make_group(struct config_group *group,
config_group_init_type_name(&configfs->encoder_group, "encoders", &encoders_item_type);
configfs_add_default_group(&configfs->encoder_group, &configfs->group);
+ config_group_init_type_name(&configfs->connector_group, "connectors",
+ &connectors_item_type);
+ configfs_add_default_group(&configfs->connector_group, &configfs->group);
+
return &configfs->group;
}
diff --git a/drivers/gpu/drm/vkms/vkms_configfs.h b/drivers/gpu/drm/vkms/vkms_configfs.h
index c033810f86ce467f564a14f74165198f12ea044c..5e13941df3382ed30770e79a0432bf37764d7c59 100644
--- a/drivers/gpu/drm/vkms/vkms_configfs.h
+++ b/drivers/gpu/drm/vkms/vkms_configfs.h
@@ -22,6 +22,7 @@ struct vkms_configfs_device {
struct config_group plane_group;
struct config_group crtc_group;
struct config_group encoder_group;
+ struct config_group connector_group;
struct mutex lock;
bool enabled;
@@ -53,6 +54,14 @@ struct vkms_configfs_encoder {
struct vkms_config_encoder *vkms_config_encoder;
};
+struct vkms_configfs_connector {
+ struct config_group group;
+
+ struct config_group possible_encoder_group;
+ struct vkms_configfs_device *vkms_configfs_device;
+ struct vkms_config_connector *vkms_config_connector;
+};
+
#define config_item_to_vkms_configfs_device(item) \
container_of(to_config_group((item)), struct vkms_configfs_device, group)
@@ -68,6 +77,9 @@ struct vkms_configfs_encoder {
#define encoder_item_to_vkms_configfs_encoder(item) \
container_of(to_config_group((item)), struct vkms_configfs_encoder, group)
+#define connector_item_to_vkms_configfs_connector(item) \
+ container_of(to_config_group((item)), struct vkms_configfs_connector, group)
+
#define plane_item_to_vkms_configfs_device(item) \
planes_item_to_vkms_configfs_device((item)->ci_parent)
@@ -89,14 +101,25 @@ struct vkms_configfs_encoder {
#define encoder_item_to_vkms_configfs_device(item) \
config_item_to_vkms_configfs_device((item)->ci_parent)
+#define connector_item_to_vkms_configfs_device(item) \
+ config_item_to_vkms_configfs_device((item)->ci_parent)
+
#define encoder_child_item_to_vkms_configfs_device(item) \
encoder_item_to_vkms_configfs_device((item)->ci_parent)
#define encoder_possible_crtc_src_item_to_vkms_configfs_device(item) \
encoder_child_item_to_vkms_configfs_device((item)->ci_parent)
+#define connector_child_item_to_vkms_configfs_device(item) \
+ connector_item_to_vkms_configfs_device((item)->ci_parent)
+
+#define connector_possible_encoder_src_item_to_vkms_configfs_device(item) \
+ connector_child_item_to_vkms_configfs_device((item)->ci_parent)
+
#define encoder_possible_crtc_src_item_to_vkms_configfs_encoder(item) \
encoder_item_to_vkms_configfs_encoder((item)->ci_parent)
+#define connector_possible_encoder_src_item_to_vkms_configfs_connector(item) \
+ connector_item_to_vkms_configfs_connector((item)->ci_parent)
/* ConfigFS Support */
int vkms_init_configfs(void);
--
2.47.1
Powered by blists - more mailing lists