From nobody Mon Feb 9 17:05:08 2026 Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4E9B01B4C56 for ; Wed, 14 Aug 2024 15:16:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723648570; cv=none; b=gM9YuNITElOBxnHKeXPPo/hyoO2G2EbaSBcbCfGwjHL3p883CBdK0bb/HTD29thkdrZ1+xkokytEQzJGc5YEsmaAIdZo7Fe0HsP5v7fe1+Oub+cky2ulGS5CsH/cvlFQvMoxjOCPWoKNyKJXvqn+Fxa3ameZbGSYqlaPYKYeFOY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723648570; c=relaxed/simple; bh=Nsg/uRD+2tjnA4hgI+v/8HLJQELciWuCytDhk8mD3jU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=KJzxlknYkzbjHBSnmsyLvuQAgBB9HSXRwZe3aqZsdfih4Fz4xGoZm3Rn6f/FI0zRW9S4hZFn0hz2sBEl5UhAIr03H7YsSWKt/V2jF8ky4HIbVU/qjPvdq1Pgo/QQugR5EY2iiShr2HqCpWkRJmmxf0Mw+XKnHPaHQ30vqeAJUAM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=SsBxRMZe; arc=none smtp.client-ip=217.70.183.195 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="SsBxRMZe" Received: by mail.gandi.net (Postfix) with ESMTPSA id 11DFD6000F; Wed, 14 Aug 2024 15:16:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1723648566; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=MaTjbXPWIRzTBUyMwGINxQZs0jxBhFozYAqNlfR9KmE=; b=SsBxRMZeqybDYVbztyYH4dC0904IXI5pGf3Zek9POFDl7Gc0UCb26WxeGymfKTLW4y0raX LNnM+dNFsRNlDvDsDFc7lxBdqYOBqRRgOom8oArZx/2LWX1Dt/1ziMY3QRBsLu4P7x2B1y +3Mbmlo42Xv+w1SPhm8BMsqYqss5J6qfTZ4kQvfFFVH4KG0xGOhBuXrT4yAOL/gbwu7C4H 9of4JjNV3q0w0dG1iV8GW2CkjDSw+xtfncM3B/t5FL+TKvLKcOnqCc3jLJtGfAKr9SQUni OSoT50hwwmEcZpOVhnK4zGkNdGihGZe4D6ejSYaynoYoMhlTQjdVQUEkM+Ul4g== From: Louis Chauvet Date: Wed, 14 Aug 2024 17:15:54 +0200 Subject: [PATCH RFC 7/7] drm/vkms: Add crtc and encoder configuration in ConfigFS Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20240814-google-config-fs-v1-7-8363181907a6@bootlin.com> References: <20240814-google-config-fs-v1-0-8363181907a6@bootlin.com> In-Reply-To: <20240814-google-config-fs-v1-0-8363181907a6@bootlin.com> To: Rodrigo Siqueira , Melissa Wen , =?utf-8?q?Ma=C3=ADra_Canal?= , Haneen Mohammed , Daniel Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie Cc: dri-devel@lists.freedesktop.org, arthurgrillo@riseup.net, linux-kernel@vger.kernel.org, jeremie.dautheribes@bootlin.com, miquel.raynal@bootlin.com, thomas.petazzoni@bootlin.com, seanpaul@google.com, nicolejadeyee@google.com, Louis Chauvet X-Mailer: b4 0.15-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=20727; i=louis.chauvet@bootlin.com; h=from:subject:message-id; bh=Nsg/uRD+2tjnA4hgI+v/8HLJQELciWuCytDhk8mD3jU=; b=owEBbQKS/ZANAwAIASCtLsZbECziAcsmYgBmvMou5lkcipOcd3X60wbj02dn6IJsw43+YyCPo OTYFDBKcm2JAjMEAAEIAB0WIQRPj7g/vng8MQxQWQQgrS7GWxAs4gUCZrzKLgAKCRAgrS7GWxAs 4jy7EADPULHBS5PfvafU7PC+e5LcX8M5CHKAKAYljEYw6wPtj5bxnxmhOV+sWtOBkrFfFR5NIaC 3p8xiX0jqF983y2ba5igzN1Ve2zbSAwK+jUqeicVaSKccOUk0kxCSy243eMj2lNLiNaSmJHcpy5 rCXziLHYLf+bcKWgLnj2sK1/YJx6weKz4AiP7Utw4HCjG9GIhEIKYjqtHzirO50GKVstW6wsVt8 4hKloy3PlK70mlFtk5tYiW9PR99navIbYCT9PX4cIj/kW5ZaeSiTdXFsW2KF+R1i36Y9VeXo7YJ bIp4xA47DxraExl1/13yBZSQ4Uqxmq4LUhbSG6oGSIPCIIOMIeRmBlDZStcY/eW1CmNT4oCTWas L8ytWqGx+Q7AY+40TdqiumJVIPDHe++xXgDeyo1BDWrI3pUYokASwI2b9D/t58KbNfTBJUpfnIz LiVRCz7JTwROHWbBH8aRCr85GIWX4YIc829IUPy864oYd8tMXqepxP4MT24YxLW2hJ82H8T6ATy GNhTcmfP0EH3eHbnco+8yR8Sb1KfzQtnawJ3iOqayWL+Ky0rx1yGM4jijIRcaFHU07ip8l3t5E3 KweQ7qq65+sfeInmokMmPY0fIM4G6ZkudN7oG9NV8x79GBhrZvvaaHaJqWYQNhLgVuzZESu9g6R e/WPAAVust5wlxw== X-Developer-Key: i=louis.chauvet@bootlin.com; a=openpgp; fpr=8B7104AE9A272D6693F527F2EC1883F55E0B40A5 X-GND-Sasl: louis.chauvet@bootlin.com To allows the userspace to test many hardware configuration, introduce a new interface to configure CRTCs and encoders. The CRTCs and encoders are created in their own directory. To link the CRTC, symlinks are used in the `possible_crtcs` folders. The current interface is: /config/vkms DEVICE_1 =E2=94=A3=E2=94=81 enable =E2=94=A3=E2=94=81 planes =E2=94=83 =E2=94=97=E2=94=81 PLANE_1 =E2=94=83 =E2=94=A3=E2=94=81 type =E2=94=83 =E2=94=A3=E2=94=81 supported_rotations =E2=94=83 =E2=94=A3=E2=94=81 supported_color_encoding =E2=94=83 =E2=94=A3=E2=94=81 supported_color_ranges =E2=94=83 =E2=94=A3=E2=94=81 default_rotation =E2=94=83 =E2=94=A3=E2=94=81 default_color_encoding =E2=94=83 =E2=94=A3=E2=94=81 default_color_range =E2=94=83 =E2=94=97=E2=94=81 possible_crtcs =E2=94=83 =E2=94=97=E2=94=81 >> /config/vkms/DEVICE_1/crtcs/CRTC_1 =E2=94=A3=E2=94=81 encoders =E2=94=83 =E2=94=97=E2=94=81 ENCODER_1 =E2=94=83 =E2=94=97=E2=94=81 possible_crtcs =E2=94=83 =E2=94=97=E2=94=81 >> /config/vkms/DEVICE_1/crtcs/CRTC_1 =E2=94=A3=E2=94=81 crtcs =E2=94=83 =E2=94=97=E2=94=81 CRTC_1 DEVICE_2 =E2=94=97=E2=94=81 ditto Signed-off-by: Louis Chauvet --- drivers/gpu/drm/vkms/vkms_configfs.c | 404 +++++++++++++++++++++++++++++++= ++-- drivers/gpu/drm/vkms/vkms_configfs.h | 54 ++++- 2 files changed, 437 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/vkms/vkms_configfs.c b/drivers/gpu/drm/vkms/vk= ms_configfs.c index aabc83283626..50628ec91b9a 100644 --- a/drivers/gpu/drm/vkms/vkms_configfs.c +++ b/drivers/gpu/drm/vkms/vkms_configfs.c @@ -5,6 +5,7 @@ #include #include #include +#include =20 #include "vkms_configfs.h" #include "vkms_drv.h" @@ -394,6 +395,83 @@ static const struct config_item_type subgroup_plane = =3D { .ct_item_ops =3D &plane_item_operations, .ct_owner =3D THIS_MODULE, }; +static const struct config_item_type crtc_item_type; +static const struct config_item_type planes_item_type; + +static int possible_crtcs_allow_link(struct config_item *src, + struct config_item *target) +{ + struct vkms_configfs_device *vkms_configfs =3D plane_possible_crtc_src_it= em_to_vkms_configfs_device(src); + struct vkms_config_crtc *crtc; + + mutex_lock(&vkms_configfs->lock); + + if (target->ci_type !=3D &crtc_item_type) { + mutex_unlock(&vkms_configfs->lock); + return -EINVAL; + } + + crtc =3D crtc_item_to_vkms_configfs_crtc(target)->vkms_config_crtc; + struct vkms_config_plane *plane =3D plane_possible_crtc_src_item_to_vkms_= configfs_plane(src)->vkms_config_plane; + + struct vkms_config_crtc *crtc_entry; + unsigned long idx =3D 0; + + xa_for_each(&plane->possible_crtcs, idx, crtc_entry) { + if (crtc_entry =3D=3D crtc) { + mutex_unlock(&vkms_configfs->lock); + return -EINVAL; + } + } + + if (vkms_config_plane_attach_crtc(plane, crtc)) + return -EINVAL; + + mutex_unlock(&vkms_configfs->lock); + + return 0; +} + +static void possible_crtcs_drop_link(struct config_item *src, + struct config_item *target) +{ + struct vkms_config_crtc *crtc; + struct vkms_configfs_device *vkms_configfs =3D plane_possible_crtc_src_it= em_to_vkms_configfs_device(src); + + mutex_lock(&vkms_configfs->lock); + + crtc =3D crtc_item_to_vkms_configfs_crtc(target)->vkms_config_crtc; + struct vkms_config_plane *plane =3D plane_possible_crtc_src_item_to_vkms_= configfs_plane(src)->vkms_config_plane; + + struct vkms_config_crtc *crtc_entry; + struct vkms_config_plane *plane_entry; + unsigned long crtc_idx =3D -1; + + xa_for_each(&plane->possible_crtcs, crtc_idx, crtc_entry) { + if (crtc_entry =3D=3D crtc) + break; + } + unsigned long plane_idx =3D -1; + + xa_erase(&plane->possible_crtcs, crtc_idx); + xa_for_each(&crtc->possible_planes, plane_idx, plane_entry) { + if (plane_entry =3D=3D plane) + break; + } + xa_erase(&crtc->possible_planes, plane_idx); + + mutex_unlock(&vkms_configfs->lock); +} + +static struct configfs_item_operations plane_possible_crtcs_item_ops =3D { + .allow_link =3D &possible_crtcs_allow_link, + .drop_link =3D &possible_crtcs_drop_link, +}; + +static struct config_item_type plane_possible_crtcs_group_type =3D { + .ct_item_ops =3D &plane_possible_crtcs_item_ops, + .ct_owner =3D THIS_MODULE, +}; =20 static struct config_group *planes_make_group(struct config_group *config_= group, const char *name) @@ -419,10 +497,7 @@ static struct config_group *planes_make_group(struct c= onfig_group *config_group, =20 if (list_count_nodes(&vkms_configfs->vkms_config->planes) =3D=3D 1) vkms_configfs_plane->vkms_config_plane->type =3D DRM_PLANE_TYPE_PRIMARY; - - if (!vkms_configfs_plane->vkms_config_plane || - vkms_config_plane_attach_crtc(vkms_configfs_plane->vkms_config_plane, - vkms_configfs->vkms_config_crtc)) { + if (!vkms_configfs_plane->vkms_config_plane) { kfree(vkms_configfs_plane); mutex_unlock(&vkms_configfs->lock); return ERR_PTR(-ENOMEM); @@ -439,7 +514,12 @@ static struct config_group *planes_make_group(struct c= onfig_group *config_group, =20 config_group_init_type_name(&vkms_configfs_plane->group, name, &subgroup_= plane); =20 + config_group_init_type_name(&vkms_configfs_plane->possible_crtc_group, "p= ossible_crtcs", + &plane_possible_crtcs_group_type); + configfs_add_default_group(&vkms_configfs_plane->possible_crtc_group, + &vkms_configfs_plane->group); vkms_configfs_plane->vkms_configfs_device =3D vkms_configfs; + mutex_unlock(&vkms_configfs->lock); =20 return &vkms_configfs_plane->group; @@ -454,6 +534,287 @@ static const struct config_item_type planes_item_type= =3D { .ct_owner =3D THIS_MODULE, }; =20 +static void crtc_release(struct config_item *item) +{ + struct vkms_configfs_crtc *vkms_configfs_crtc =3D crtc_item_to_vkms_confi= gfs_crtc(item); + + mutex_lock(&vkms_configfs_crtc->vkms_configfs_device->lock); + vkms_config_delete_crtc(vkms_configfs_crtc->vkms_config_crtc, + vkms_configfs_crtc->vkms_configfs_device->vkms_config); + mutex_unlock(&vkms_configfs_crtc->vkms_configfs_device->lock); + + kfree(vkms_configfs_crtc); +} + +static struct configfs_item_operations crtc_item_operations =3D { + .release =3D crtc_release, +}; + +static const struct config_item_type crtc_item_type =3D { + .ct_owner =3D THIS_MODULE, + .ct_item_ops =3D &crtc_item_operations, +}; + +static struct config_group *crtcs_make_group(struct config_group *config_g= roup, + const char *name) +{ + struct config_item *root_item =3D config_group->cg_item.ci_parent; + struct vkms_configfs_device *vkms_configfs =3D config_item_to_vkms_config= fs_device(root_item); + struct vkms_configfs_crtc *vkms_configfs_crtc; + + vkms_configfs_crtc =3D kzalloc(sizeof(*vkms_configfs_crtc), GFP_KERNEL); + + if (!vkms_configfs_crtc) + return ERR_PTR(-ENOMEM); + + mutex_lock(&vkms_configfs->lock); + vkms_configfs_crtc->vkms_configfs_device =3D vkms_configfs; + + if (vkms_configfs->enabled) { + kfree(vkms_configfs_crtc); + mutex_unlock(&vkms_configfs->lock); + return ERR_PTR(-EINVAL); + } + + vkms_configfs_crtc->vkms_config_crtc =3D vkms_config_create_crtc(vkms_con= figfs->vkms_config); + + if (!vkms_configfs_crtc->vkms_config_crtc) { + kfree(vkms_configfs_crtc); + mutex_unlock(&vkms_configfs->lock); + return ERR_PTR(-ENOMEM); + } + + vkms_configfs_crtc->vkms_config_crtc->name =3D kzalloc(strlen(name) + 1, = GFP_KERNEL); + if (!vkms_configfs_crtc->vkms_config_crtc->name) { + kfree(vkms_configfs_crtc->vkms_config_crtc); + kfree(vkms_configfs_crtc); + mutex_unlock(&vkms_configfs->lock); + return ERR_PTR(-ENOMEM); + } + + vkms_configfs_crtc->vkms_configfs_device =3D vkms_configfs; + + strscpy(vkms_configfs_crtc->vkms_config_crtc->name, name, strlen(name) + = 1); + config_group_init_type_name(&vkms_configfs_crtc->group, name, + &crtc_item_type); + + + mutex_unlock(&vkms_configfs->lock); + + return &vkms_configfs_crtc->group; +} + + +static struct configfs_group_operations crtcs_group_operations =3D { + .make_group =3D &crtcs_make_group, +}; + + +static const struct config_item_type crtcs_item_type =3D { + .ct_group_ops =3D &crtcs_group_operations, + .ct_owner =3D THIS_MODULE, +}; + +static int encoder_possible_crtcs_allow_link(struct config_item *src, + struct config_item *target) +{ + struct vkms_config_crtc *crtc; + struct vkms_configfs_device *vkms_configfs =3D encoder_possible_crtc_src_= item_to_vkms_configfs_device(src); + + mutex_lock(&vkms_configfs->lock); + + if (target->ci_type !=3D &crtc_item_type) { + DRM_ERROR("Unable to link non-CRTCs.\n"); + mutex_unlock(&vkms_configfs->lock); + return -EINVAL; + } + + crtc =3D crtc_item_to_vkms_configfs_crtc(target)->vkms_config_crtc; + struct vkms_config_encoder *encoder =3D encoder_possible_crtc_src_item_to= _vkms_configfs_encoder(src)->vkms_config_encoder; + + struct vkms_config_crtc *crtc_entry; + unsigned long idx =3D 0; + + xa_for_each(&encoder->possible_crtcs, idx, crtc_entry) { + if (crtc_entry =3D=3D crtc) { + pr_err("Tried to add two symlinks to the same CRTC from the same object= .\n"); + mutex_unlock(&vkms_configfs->lock); + return -EINVAL; + } + } + + if (vkms_config_encoder_attach_crtc(encoder, crtc)) + return -EINVAL; + + mutex_unlock(&vkms_configfs->lock); + + return 0; +} + +static void encoder_possible_crtcs_drop_link(struct config_item *src, + struct config_item *target) +{ + struct vkms_config_crtc *crtc; + struct vkms_configfs_device *vkms_configfs =3D encoder_possible_crtc_src_= item_to_vkms_configfs_device(src); + + mutex_lock(&vkms_configfs->lock); + + crtc =3D crtc_item_to_vkms_configfs_crtc(target)->vkms_config_crtc; + struct vkms_config_encoder *encoder =3D encoder_possible_crtc_src_item_to= _vkms_configfs_encoder(src)->vkms_config_encoder; + + struct vkms_config_encoder *encoder_entry; + struct vkms_config_crtc *crtc_entry; + unsigned long encoder_idx =3D -1; + unsigned long crtc_idx =3D -1; + + xa_for_each(&encoder->possible_crtcs, crtc_idx, crtc_entry) { + if (crtc_entry =3D=3D crtc) + break; + } + xa_erase(&encoder->possible_crtcs, crtc_idx); + xa_for_each(&crtc->possible_encoders, encoder_idx, encoder_entry) { + if (encoder_entry =3D=3D encoder) + break; + } + xa_erase(&crtc->possible_encoders, encoder_idx); + + mutex_unlock(&vkms_configfs->lock); +} + +static struct configfs_item_operations encoder_possible_crtcs_item_operati= ons =3D { + .allow_link =3D &encoder_possible_crtcs_allow_link, + .drop_link =3D &encoder_possible_crtcs_drop_link, +}; + +static struct config_item_type encoder_possible_crtcs_item_type =3D { + .ct_item_ops =3D &encoder_possible_crtcs_item_operations, + .ct_owner =3D THIS_MODULE, +}; + +static void encoder_release(struct config_item *item) +{ + struct vkms_configfs_encoder *vkms_configfs_encoder =3D encoder_item_to_v= kms_configfs_encoder(item); + + mutex_lock(&vkms_configfs_encoder->vkms_configfs_device->lock); + vkms_config_delete_encoder(vkms_configfs_encoder->vkms_config_encoder, vk= ms_configfs_encoder->vkms_configfs_device->vkms_config); + mutex_unlock(&vkms_configfs_encoder->vkms_configfs_device->lock); + + kfree(vkms_configfs_encoder); +} + +static struct configfs_item_operations encoder_item_operations =3D { + .release =3D encoder_release, +}; + +static const struct config_item_type encoder_item_type =3D { + .ct_item_ops =3D &encoder_item_operations, + .ct_owner =3D THIS_MODULE, +}; + +static struct config_group *encoder_make_group(struct config_group *config= _group, + const char *name) +{ + struct vkms_configfs_device *vkms_configfs =3D encoder_item_to_vkms_confi= gfs_device(&config_group->cg_item); + struct vkms_configfs_encoder *vkms_configfs_encoder; + + vkms_configfs_encoder =3D kzalloc(sizeof(*vkms_configfs_encoder), GFP_KER= NEL); + + if (!vkms_configfs_encoder) + return ERR_PTR(-ENOMEM); + + mutex_lock(&vkms_configfs->lock); + + if (vkms_configfs->enabled) { + kfree(vkms_configfs_encoder); + mutex_unlock(&vkms_configfs->lock); + return ERR_PTR(-EINVAL); + } + + vkms_configfs_encoder->vkms_config_encoder =3D vkms_config_create_encoder( + vkms_configfs->vkms_config); + + if (!vkms_configfs_encoder->vkms_config_encoder) { + kfree(vkms_configfs_encoder); + mutex_unlock(&vkms_configfs->lock); + return ERR_PTR(-ENOMEM); + } + + vkms_configfs_encoder->vkms_config_encoder->name =3D kzalloc(strlen(name)= + 1, GFP_KERNEL); + if (!vkms_configfs_encoder->vkms_config_encoder->name) { + kfree(vkms_configfs_encoder->vkms_config_encoder); + kfree(vkms_configfs_encoder); + mutex_unlock(&vkms_configfs->lock); + return ERR_PTR(-ENOMEM); + } + + strscpy(vkms_configfs_encoder->vkms_config_encoder->name, name, strlen(na= me) + 1); + config_group_init_type_name(&vkms_configfs_encoder->group, name, + &encoder_item_type); + + config_group_init_type_name(&vkms_configfs_encoder->possible_crtc_group, = "possible_crtcs", + &encoder_possible_crtcs_item_type); + configfs_add_default_group(&vkms_configfs_encoder->possible_crtc_group, + &vkms_configfs_encoder->group); + vkms_configfs_encoder->vkms_configfs_device =3D vkms_configfs; + + mutex_unlock(&vkms_configfs->lock); + + return &vkms_configfs_encoder->group; +} + +static struct configfs_group_operations encoder_group_operations =3D { + .make_group =3D &encoder_make_group, +}; + +static const struct config_item_type encoders_item_type =3D { + .ct_group_ops =3D &encoder_group_operations, + .ct_owner =3D THIS_MODULE, +}; + +/** + * configfs_lock_dependencies() - In order to forbid the userspace to dele= te items when the + * device is enabled, mark all configfs items as dependent + * + * @vkms_configfs_device - Device to lock + */ +static void configfs_lock_dependencies(struct vkms_configfs_device *vkms_c= onfigfs_device) +{ + /* Lock the group itself */ + configfs_depend_item_unlocked(vkms_configfs_device->group.cg_subsys, + &vkms_configfs_device->group.cg_item); + /* Lock the planes elements */ + struct config_item *item; + + list_for_each_entry(item, &vkms_configfs_device->plane_group.cg_children,= ci_entry) { + configfs_depend_item_unlocked(vkms_configfs_device->plane_group.cg_subsy= s, + item); + } + list_for_each_entry(item, &vkms_configfs_device->crtc_group.cg_children, = ci_entry) { + configfs_depend_item_unlocked(vkms_configfs_device->crtc_group.cg_subsys, + item); + } +} + +/** + * configfs_unlock_dependencies() - Once the device is disable, its config= uration can be modified. + * + * @vkms_configfs_device - Device to unlock + */ +static void configfs_unlock_dependencies(struct vkms_configfs_device *vkms= _configfs_device) +{ + struct config_item *item; + + configfs_undepend_item_unlocked(&vkms_configfs_device->group.cg_item); + + list_for_each_entry(item, &vkms_configfs_device->plane_group.cg_children,= ci_entry) { + configfs_undepend_item_unlocked(item); + } + list_for_each_entry(item, &vkms_configfs_device->crtc_group.cg_children, = ci_entry) { + configfs_undepend_item_unlocked(item); + } +} + + static ssize_t device_enable_show(struct config_item *item, char *page) { return sprintf(page, "%d\n", @@ -474,13 +835,25 @@ static ssize_t device_enable_store(struct config_item= *item, return -EINVAL; =20 mutex_lock(&vkms_configfs_device->lock); + if (vkms_configfs_device->enabled =3D=3D value) { + mutex_unlock(&vkms_configfs_device->lock); + return (ssize_t) count; + } + + if (value && !vkms_config_is_valid(vkms_configfs_device->vkms_config)) { + mutex_unlock(&vkms_configfs_device->lock); + return -EINVAL; + } =20 vkms_configfs_device->enabled =3D value; =20 - if (value) + if (value) { + configfs_lock_dependencies(vkms_configfs_device); vkms_create(vkms_configfs_device->vkms_config); - else + } else { + configfs_unlock_dependencies(vkms_configfs_device); vkms_destroy(vkms_configfs_device->vkms_config); + } =20 mutex_unlock(&vkms_configfs_device->lock); =20 @@ -519,9 +892,6 @@ static const struct config_item_type device_item_type = =3D { static struct config_group *root_make_group(struct config_group *group, const char *name) { - struct vkms_config_plane *plane; - struct vkms_config_crtc *crtc; - struct vkms_config_encoder *encoder; struct vkms_configfs_device *configfs =3D kzalloc(sizeof(*configfs), GFP_= KERNEL); =20 if (!configfs) @@ -536,22 +906,18 @@ static struct config_group *root_make_group(struct co= nfig_group *group, return ERR_PTR(-ENOMEM); } =20 - configfs->vkms_config_crtc =3D vkms_config_create_crtc(configfs->vkms_con= fig); - configfs->vkms_config_encoder =3D vkms_config_create_encoder(configfs->vk= ms_config); - if (!configfs->vkms_config_crtc || !configfs->vkms_config_encoder || - vkms_config_encoder_attach_crtc(configfs->vkms_config_encoder, - configfs->vkms_config_crtc)) { - vkms_config_destroy(configfs->vkms_config); - kfree(configfs); - return ERR_PTR(-ENOMEM); - } - config_group_init_type_name(&configfs->group, name, &device_item_type); =20 config_group_init_type_name(&configfs->plane_group, "planes", &planes_ite= m_type); configfs_add_default_group(&configfs->plane_group, &configfs->group); =20 + config_group_init_type_name(&configfs->crtc_group, "crtcs", &crtcs_item_t= ype); + configfs_add_default_group(&configfs->crtc_group, &configfs->group); + + config_group_init_type_name(&configfs->encoder_group, "encoders", &encode= rs_item_type); + configfs_add_default_group(&configfs->encoder_group, &configfs->group); + return &configfs->group; } =20 diff --git a/drivers/gpu/drm/vkms/vkms_configfs.h b/drivers/gpu/drm/vkms/vk= ms_configfs.h index 6dc4d34a9e44..df743e0107f4 100644 --- a/drivers/gpu/drm/vkms/vkms_configfs.h +++ b/drivers/gpu/drm/vkms/vkms_configfs.h @@ -20,34 +20,84 @@ struct vkms_configfs_device { struct config_group group; =20 struct config_group plane_group; + struct config_group crtc_group; + struct config_group encoder_group; =20 struct mutex lock; bool enabled; =20 struct vkms_config *vkms_config; - struct vkms_config_crtc *vkms_config_crtc; - struct vkms_config_encoder *vkms_config_encoder; }; =20 struct vkms_configfs_plane { struct config_group group; + struct config_group possible_crtc_group; =20 struct vkms_configfs_device *vkms_configfs_device; struct vkms_config_plane *vkms_config_plane; }; =20 +struct vkms_configfs_crtc { + struct config_group group; + + struct vkms_configfs_device *vkms_configfs_device; + struct vkms_config_crtc *vkms_config_crtc; +}; + +struct vkms_configfs_encoder { + /* must be first because it is a krefcounted stuff */ + struct config_group group; + + struct config_group possible_crtc_group; + struct vkms_configfs_device *vkms_configfs_device; + struct vkms_config_encoder *vkms_config_encoder; +}; + #define config_item_to_vkms_configfs_device(item) \ container_of(to_config_group((item)), struct vkms_configfs_device, group) =20 #define planes_item_to_vkms_configfs_device(item) \ config_item_to_vkms_configfs_device((item)->ci_parent) =20 +#define encoders_item_to_vkms_configfs_device(item) \ + config_item_to_vkms_configfs_device((item)->ci_parent) + +#define crtc_item_to_vkms_configfs_crtc(item) \ + container_of(to_config_group((item)), struct vkms_configfs_crtc, group) + +#define encoder_item_to_vkms_configfs_encoder(item) \ + container_of(to_config_group((item)), struct vkms_configfs_encoder, group) + #define plane_item_to_vkms_configfs_device(item) \ planes_item_to_vkms_configfs_device((item)->ci_parent) =20 #define plane_item_to_vkms_configfs_plane(item) \ container_of(to_config_group((item)), struct vkms_configfs_plane, group) =20 +#define plane_possible_crtc_src_item_to_vkms_configfs_device(item) \ + plane_item_to_vkms_configfs_device((item)->ci_parent) + +#define plane_possible_crtc_src_item_to_vkms_configfs_plane(item) \ + plane_item_to_vkms_configfs_plane((item)->ci_parent) + +#define crtc_item_to_vkms_configfs_device(item) \ + config_item_to_vkms_configfs_device((item)->ci_parent) + +#define crtc_child_item_to_vkms_configfs_device(item) \ + crtc_item_to_vkms_configfs_device((item)->ci_parent) + +#define encoder_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 encoder_possible_crtc_src_item_to_vkms_configfs_encoder(item) \ + encoder_item_to_vkms_configfs_encoder((item)->ci_parent) + /* ConfigFS Support */ int vkms_init_configfs(void); void vkms_unregister_configfs(void); --=20 2.44.2