From nobody Mon Feb 9 19:26:28 2026 Received: from mail-wm1-f46.google.com (mail-wm1-f46.google.com [209.85.128.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3A6961DE2DF for ; Wed, 29 Jan 2025 11:01:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738148484; cv=none; b=KGbO7brILB9wDqT9Q96vgkfxrIbSbB9nyJ22aS7NJK43kqy3J6WJMMUp+aPq3fS1StRorDplGpwW1Za/ahQ2I6PGjB8PdLZMhW4wgpEABLX0DXWQKL3V+zEJA6Ezupn2wfiOCS76Gf5p5S1uSLuQs+eVlTzDvzqrtGwoNphcH+E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738148484; c=relaxed/simple; bh=/jBhHanDmkGrRyvU8dWme3OC1r2m8gUKypaMTNYj8AI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=ga+UMBRlxfC9M+ijYzVd8bQVVtgL1bP+K5uFAsWRROygOROjK3et6qtqb55SVASivirfbTMzO3qE1cDF81otXfWy/T727ssAv97FdOVqR1Sy9alv+G4zALr68W4tn9qox7Z5GgVtyuGUlzQaXktG3177CBSnmFLFxhY3o0AwPFQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=ZnfB5vVz; arc=none smtp.client-ip=209.85.128.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ZnfB5vVz" Received: by mail-wm1-f46.google.com with SMTP id 5b1f17b1804b1-436a03197b2so45433225e9.2 for ; Wed, 29 Jan 2025 03:01:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1738148480; x=1738753280; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=sPKCrtDQeB9pT35xBqaZjucly7gQR5uxUbB7ZFp2HeA=; b=ZnfB5vVzgwqCB7VNBQt8mhXfocZ/2i6OiNjAGly5lnR9lzzYQW3dYZLBS2y+2AQf00 j+/888UGnPpkEekJswgp1sFIkwfELCiqF7sRXNY8paJgpr1ho++P8Eqp1/2csb3Kod0s djeA3dPIz8/kDhhhzkl/BZyOc79B0+PfPSV6UjZUMo9PNlM7YYj/S2+yZo+whKZGFttv kdiX+owaDIDejnqkul7oHZl7RGsWgloLurE/CZVcfj2E5MU5M1AsVgyUqLrfbuSGa/2u ZDwcscXCTixDYa391eMVGfZwQuRns4/buiNgAuSIYM1IeYIv1F4TeHisUNSzHzYi7f8F /Vsw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1738148480; x=1738753280; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=sPKCrtDQeB9pT35xBqaZjucly7gQR5uxUbB7ZFp2HeA=; b=Rs3j8tB8hQUR+UYuHHkailf1gbOqS1aNjFg/bhSwg0s1XycafRZdWJTSQSEkyCz8O9 FDfZCL2pevadrOfMrx31bp8EOTtzzbgGkqJ5G8dU5QUzT7BYftzPuRxO4+w60AIJELC2 YyyzpZoDiYBTnCxR87eByB3bE8JHtHXqQBSbhvVLJWBwvPbmkubK7lU1eLmhaMTduQkV O+PzI4HJltsBkjeFxtiBgYuTtU/gGFXTn2P/2ufP88oQgWOi7GA4gWFjbyiu+odnD1Fj OcproRlI/yYW3afq8lQiA/1GXd04lnmNIei5nEXlyuxcOvOC3yvCpr2NkI0PU26Opzfj u1wg== X-Forwarded-Encrypted: i=1; AJvYcCVrI1CwrkI6OGA9PRO07KhgT8Zg3Km06oygGi2aBWQTtancrL1N0Y1zLi/5x/iKEu9H72OnB+HHn1p1Fws=@vger.kernel.org X-Gm-Message-State: AOJu0Yx5htetGlFIN2NcBrnM0nqLT0F8o5ZcR1yhMfENBB2MgxffUOlB ng7uV/JJ7oOW+NmlFDfFfpQmwBkXy/4hl2VKpas/O2O4f8iQnFc9 X-Gm-Gg: ASbGncv5M1PWuZiUeBPXxkY07MLLGSz0EvuYBxusUsGcmID0dMlFRA77NW8JGSfIjk3 Gm0W+skh8dQCbbWcbPbuAWufsnQWj06Rq9ZcUWHZT8ATDJSPCPNPXuoRx/vp8iS7SkbJZtfMZZ/ IqPaFFtakdZbBVfMirdWeOHtm2OMYPE0JMsh9bdXxE6FKOU9jh1/QdffqVEGxrKSEDSNJeea1E/ oPstLi1LC3ogbQOqqJUlD93VkCGPJArXhva2NLzU+k9tJwwaMWI/q6zYhCvIMyfxSPouUFxBNFV QtcuSv/GG+rGr/La X-Google-Smtp-Source: AGHT+IHe873lwgBSOx12roMFUoX/pWu+ybMJMlclWGzsLsm+W6rPbHJG1LVgiHlxQhQxStQL04VdHw== X-Received: by 2002:a05:600c:3494:b0:434:a315:19c with SMTP id 5b1f17b1804b1-438dc3a85b3mr20395585e9.3.1738148480162; Wed, 29 Jan 2025 03:01:20 -0800 (PST) Received: from fedora.. ([94.73.37.161]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-38c2a176434sm16947113f8f.13.2025.01.29.03.01.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Jan 2025 03:01:18 -0800 (PST) From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= To: 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, =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= Subject: [PATCH 13/13] drm/vkms: Allow to attach connectors and encoders Date: Wed, 29 Jan 2025 12:00:59 +0100 Message-ID: <20250129110059.12199-14-jose.exposito89@gmail.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250129110059.12199-1-jose.exposito89@gmail.com> References: <20250129110059.12199-1-jose.exposito89@gmail.com> 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 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. Signed-off-by: Louis Chauvet Signed-off-by: Jos=C3=A9 Exp=C3=B3sito --- drivers/gpu/drm/vkms/tests/vkms_config_test.c | 62 +++++++++++++++++ drivers/gpu/drm/vkms/vkms_config.c | 69 +++++++++++++++++++ drivers/gpu/drm/vkms/vkms_config.h | 33 +++++++++ drivers/gpu/drm/vkms/vkms_output.c | 57 +++++++++++---- 4 files changed, 209 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/vkms/tests/vkms_config_test.c b/drivers/gpu/dr= m/vkms/tests/vkms_config_test.c index 40c385eedc1d..d89acdc1a752 100644 --- a/drivers/gpu/drm/vkms/tests/vkms_config_test.c +++ b/drivers/gpu/drm/vkms/tests/vkms_config_test.c @@ -688,6 +688,67 @@ static void vkms_config_test_encoder_get_possible_crtc= s(struct kunit *test) vkms_config_destroy(config); } =20 +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 **array; + size_t length; + int err; + + config =3D vkms_config_create("test"); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config); + + connector_cfg1 =3D vkms_config_add_connector(config); + connector_cfg2 =3D vkms_config_add_connector(config); + encoder_cfg1 =3D vkms_config_add_encoder(config); + encoder_cfg2 =3D vkms_config_add_encoder(config); + + /* No possible encoders */ + array =3D vkms_config_connector_get_possible_encoders(connector_cfg1, &le= ngth); + KUNIT_ASSERT_EQ(test, length, 0); + KUNIT_ASSERT_NULL(test, array); + + array =3D vkms_config_connector_get_possible_encoders(connector_cfg2, &le= ngth); + KUNIT_ASSERT_EQ(test, length, 0); + KUNIT_ASSERT_NULL(test, array); + + /* Connector 1 attached to encoders 1 and 2 */ + err =3D vkms_config_connector_attach_encoder(connector_cfg1, encoder_cfg1= ); + KUNIT_EXPECT_EQ(test, err, 0); + err =3D vkms_config_connector_attach_encoder(connector_cfg1, encoder_cfg2= ); + KUNIT_EXPECT_EQ(test, err, 0); + + array =3D vkms_config_connector_get_possible_encoders(connector_cfg1, &le= ngth); + KUNIT_ASSERT_EQ(test, length, 2); + KUNIT_ASSERT_PTR_EQ(test, array[0], encoder_cfg1); + KUNIT_ASSERT_PTR_EQ(test, array[1], encoder_cfg2); + kfree(array); + + array =3D vkms_config_connector_get_possible_encoders(connector_cfg2, &le= ngth); + KUNIT_ASSERT_EQ(test, length, 0); + KUNIT_ASSERT_NULL(test, array); + + /* Connector 1 attached to encoder 1 and connector 2 to encoder 2 */ + vkms_config_connector_detach_encoder(connector_cfg1, encoder_cfg2); + + array =3D vkms_config_connector_get_possible_encoders(connector_cfg1, &le= ngth); + KUNIT_ASSERT_EQ(test, length, 1); + KUNIT_ASSERT_PTR_EQ(test, array[0], encoder_cfg1); + kfree(array); + + err =3D vkms_config_connector_attach_encoder(connector_cfg2, encoder_cfg2= ); + KUNIT_EXPECT_EQ(test, err, 0); + + array =3D vkms_config_connector_get_possible_encoders(connector_cfg2, &le= ngth); + KUNIT_ASSERT_EQ(test, length, 1); + KUNIT_ASSERT_PTR_EQ(test, array[0], encoder_cfg2); + kfree(array); + + vkms_config_destroy(config); +} + static struct kunit_case vkms_config_test_cases[] =3D { KUNIT_CASE(vkms_config_test_empty_config), KUNIT_CASE_PARAM(vkms_config_test_default_config, @@ -706,6 +767,7 @@ static struct kunit_case vkms_config_test_cases[] =3D { 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), {} }; =20 diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms= _config.c index e94e48fe3ad9..db6e3c71fd68 100644 --- a/drivers/gpu/drm/vkms/vkms_config.c +++ b/drivers/gpu/drm/vkms/vkms_config.c @@ -94,6 +94,9 @@ struct vkms_config *vkms_config_default_create(bool enabl= e_cursor, goto err_alloc; vkms_config_connector_set_enabled(connector_cfg, true); =20 + if (vkms_config_connector_attach_encoder(connector_cfg, encoder_cfg)) + goto err_alloc; + return config; =20 err_alloc: @@ -629,6 +632,11 @@ struct vkms_config_encoder *vkms_config_add_encoder(st= ruct vkms_config *config) void vkms_config_destroy_encoder(struct vkms_config *config, struct vkms_config_encoder *encoder_cfg) { + struct vkms_config_connector *connector_cfg; + + list_for_each_entry(connector_cfg, &config->connectors, link) + vkms_config_connector_detach_encoder(connector_cfg, encoder_cfg); + xa_destroy(&encoder_cfg->possible_crtcs); list_del(&encoder_cfg->link); kfree(encoder_cfg); @@ -702,6 +710,7 @@ struct vkms_config_connector *vkms_config_add_connector= (struct vkms_config *conf return ERR_PTR(-ENOMEM); =20 vkms_config_connector_set_enabled(connector_cfg, false); + xa_init_flags(&connector_cfg->possible_encoders, XA_FLAGS_ALLOC); =20 list_add_tail(&connector_cfg->link, &config->connectors); =20 @@ -710,6 +719,66 @@ struct vkms_config_connector *vkms_config_add_connecto= r(struct vkms_config *conf =20 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_c= onnector *connector_cfg, + struct vkms_config_encoder *encoder_cfg) +{ + struct vkms_config_encoder *possible_encoder; + unsigned long idx =3D 0; + u32 encoder_idx =3D 0; + + xa_for_each(&connector_cfg->possible_encoders, idx, possible_encoder) { + if (possible_encoder =3D=3D 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 *co= nnector_cfg, + struct vkms_config_encoder *encoder_cfg) +{ + struct vkms_config_encoder *possible_encoder; + unsigned long idx =3D 0; + + xa_for_each(&connector_cfg->possible_encoders, idx, possible_encoder) { + if (possible_encoder =3D=3D encoder_cfg) + xa_erase(&connector_cfg->possible_encoders, idx); + } +} + +struct vkms_config_encoder ** +vkms_config_connector_get_possible_encoders(struct vkms_config_connector *= connector_cfg, + size_t *out_length) +{ + struct vkms_config_encoder **array; + struct vkms_config_encoder *possible_encoder; + unsigned long idx; + size_t length =3D 0; + int n =3D 0; + + xa_for_each(&connector_cfg->possible_encoders, idx, possible_encoder) + length++; + + if (length =3D=3D 0) { + *out_length =3D length; + return NULL; + } + + array =3D kmalloc_array(length, sizeof(*array), GFP_KERNEL); + if (!array) + return ERR_PTR(-ENOMEM); + + xa_for_each(&connector_cfg->possible_encoders, idx, possible_encoder) { + array[n] =3D possible_encoder; + n++; + } + + *out_length =3D length; + return array; +} diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms= _config.h index cc32aadfda8d..24052de05e98 100644 --- a/drivers/gpu/drm/vkms/vkms_config.h +++ b/drivers/gpu/drm/vkms/vkms_config.h @@ -94,6 +94,7 @@ struct vkms_config_encoder { * @enabled: Connector are a different from planes, CRTCs and encoders bec= ause * they can be added and removed once the device is created. * This flag represents if they are part of the device or not. + * @possible_encoders: Array of encoders that can be used with this connec= tor * @connector: Internal usage. This pointer should never be considered as = valid. * It can be used to store a temporary reference to a VKMS con= nector * during device creation. This pointer is not managed by the @@ -103,6 +104,7 @@ struct vkms_config_connector { struct list_head link; =20 bool enabled; + struct xarray possible_encoders; =20 /* Internal usage */ struct vkms_connector *connector; @@ -443,4 +445,35 @@ vkms_config_connector_set_enabled(struct vkms_config_c= onnector *connector_cfg, connector_cfg->enabled =3D enabled; } =20 +/** + * 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_c= onnector *connector_cfg, + struct vkms_config_encoder *encoder_cfg); + +/** + * vkms_config_connector_detach_encoder - Detach a connector from an encod= er + * @connector_cfg: Connector to detach + * @encoder_cfg: Encoder to detach @connector_cfg from + */ +void vkms_config_connector_detach_encoder(struct vkms_config_connector *co= nnector_cfg, + struct vkms_config_encoder *encoder_cfg); + +/** + * vkms_config_connector_get_possible_encoders() - Return the array of pos= sible + * encoders + * @connector_cfg: Connector to get the possible encoders from + * @out_length: Length of the returned array + * + * Returns: + * A list of pointers to the configurations. On success, the caller is + * responsible to free the returned array, but not its contents. On error, + * it returns an error and @out_length is invalid. + */ +struct vkms_config_encoder ** +vkms_config_connector_get_possible_encoders(struct vkms_config_connector *= connector_cfg, + size_t *out_length); + #endif /* _VKMS_CONFIG_H_ */ diff --git a/drivers/gpu/drm/vkms/vkms_output.c b/drivers/gpu/drm/vkms/vkms= _output.c index 9c3e00817add..20ee8fdfa6f8 100644 --- a/drivers/gpu/drm/vkms/vkms_output.c +++ b/drivers/gpu/drm/vkms/vkms_output.c @@ -8,13 +8,14 @@ int vkms_output_init(struct vkms_device *vkmsdev) { struct drm_device *dev =3D &vkmsdev->drm; - struct vkms_connector *connector; struct vkms_config_plane **plane_cfgs =3D NULL; size_t n_planes; struct vkms_config_crtc **crtc_cfgs =3D NULL; size_t n_crtcs; struct vkms_config_encoder **encoder_cfgs =3D NULL; size_t n_encoders; + struct vkms_config_connector **connector_cfgs =3D NULL; + size_t n_connectors; int ret =3D 0; int writeback; unsigned int n, i; @@ -35,6 +36,13 @@ int vkms_output_init(struct vkms_device *vkmsdev) goto err_free; } =20 + connector_cfgs =3D vkms_config_get_connectors(vkmsdev->config, + &n_connectors); + if (IS_ERR(connector_cfgs)) { + ret =3D PTR_ERR(connector_cfgs); + goto err_free; + } + for (n =3D 0; n < n_planes; n++) { struct vkms_config_plane *plane_cfg; enum drm_plane_type type; @@ -136,18 +144,42 @@ int vkms_output_init(struct vkms_device *vkmsdev) kfree(possible_crtcs); } =20 - connector =3D vkms_connector_init(vkmsdev); - if (IS_ERR(connector)) { - DRM_ERROR("Failed to init connector\n"); - ret =3D PTR_ERR(connector); - goto err_free; - } + for (n =3D 0; n < n_connectors; n++) { + struct vkms_config_connector *connector_cfg; + struct vkms_config_encoder **possible_encoders; + size_t n_possible_encoders; =20 - /* Attach the encoder and the connector */ - ret =3D drm_connector_attach_encoder(&connector->base, encoder_cfgs[0]->e= ncoder); - if (ret) { - DRM_ERROR("Failed to attach connector to encoder\n"); - goto err_free; + connector_cfg =3D connector_cfgs[n]; + + connector_cfg->connector =3D vkms_connector_init(vkmsdev); + if (IS_ERR(connector_cfg->connector)) { + DRM_ERROR("Failed to init connector\n"); + ret =3D PTR_ERR(connector_cfg->connector); + goto err_free; + } + + possible_encoders =3D + vkms_config_connector_get_possible_encoders(connector_cfg, + &n_possible_encoders); + if (IS_ERR(possible_encoders)) { + ret =3D PTR_ERR(possible_encoders); + goto err_free; + } + + for (i =3D 0; i < n_possible_encoders; i++) { + struct vkms_config_encoder *possible_encoder; + + possible_encoder =3D possible_encoders[i]; + ret =3D drm_connector_attach_encoder(&connector_cfg->connector->base, + possible_encoder->encoder); + if (ret) { + DRM_ERROR("Failed to attach connector to encoder\n"); + kfree(possible_encoders); + goto err_free; + } + } + + kfree(possible_encoders); } =20 drm_mode_config_reset(dev); @@ -156,6 +188,7 @@ int vkms_output_init(struct vkms_device *vkmsdev) kfree(plane_cfgs); kfree(crtc_cfgs); kfree(encoder_cfgs); + kfree(connector_cfgs); =20 return ret; } --=20 2.48.1