From nobody Mon Feb 9 16:01:08 2026 Received: from smtpout-03.galae.net (smtpout-03.galae.net [185.246.85.4]) (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 00C57348877; Wed, 29 Oct 2025 13:30:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.85.4 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761744658; cv=none; b=OJDuCx1ka90ZH0y96cC2jOY+6Zjl+ZOM1ZKRHE4wWzmdhLkhxnr6eSTFjS3YYiyF70ilI4HApTKMnXBaOv7aVl3CYnNVS4lKD313bAT6AyeGAwZIqM+KqJnG6yx4Wych7SeWyseyGN38zLLif9P42j8wIKsX8wNCfPaXZT0kl2s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761744658; c=relaxed/simple; bh=BMVGN+9+t9auyeVa0Egl37tcKEFQ9wQUAEN2uScKJxI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=dkS1kkjifdc6nUZHgClXtwSzfhCS8X38FCwYU3mh0AdU0+ffx6jJZtBgUeImqTD+QMnxQxZjRMP0SXSlGO9L6glqf9vaY3I2LLba/211g8Px3LYNaahmtlHIv9r1cxYS02e/GlWp703p7NJqusHlkqaFcGLdz2dFIb4ZrE6AirM= 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=T2xPsI9b; arc=none smtp.client-ip=185.246.85.4 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="T2xPsI9b" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id A75024E413D0; Wed, 29 Oct 2025 13:30:54 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 727D2606E8; Wed, 29 Oct 2025 13:30:54 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 414AD117F8047; Wed, 29 Oct 2025 14:30:52 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1761744653; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=RDpTgbAVmwlCytnSgkakGECg7adgLDFGZNh1TIOlRlw=; b=T2xPsI9baanfR5P3/tZVY7YxR0rp/OcohpU79jQtzuHQlXUguG0eoLJcxVBq8lekZj16v1 x7HdF9gQEpOb3QHXMu65FJtOnUdvrmtDWPsNIb3Zd4bO1ywkjrgeFDlhTqJjN2ysmksi20 Q04G9ahj4mQ6RV9lwEFCP8o1Q+GXol1/omtNhrhxIbrTz/9Mh6txKSZfWM2uJJVdgXyhFd R3hnJIu3AsiJ4B+kcLj8wyRC0o6BWze7UUuCEasTCp18vcxxHHsfwWiPustWJ+Kx3hDEib h2GC7vdhGcFBP1QfarIWhWLDAqY9dknan45PHJUHm3D6jXaYFL8OzrWYsTFD0w== From: Louis Chauvet Date: Wed, 29 Oct 2025 14:30:27 +0100 Subject: [PATCH v2 17/32] drm/vkms: Introduce configfs for plane format 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: <20251029-vkms-all-config-v2-17-be20b9bf146e@bootlin.com> References: <20251029-vkms-all-config-v2-0-be20b9bf146e@bootlin.com> In-Reply-To: <20251029-vkms-all-config-v2-0-be20b9bf146e@bootlin.com> To: Haneen Mohammed , Simona Vetter , Melissa Wen , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , jose.exposito89@gmail.com, Jonathan Corbet 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 X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=10458; i=louis.chauvet@bootlin.com; h=from:subject:message-id; bh=BMVGN+9+t9auyeVa0Egl37tcKEFQ9wQUAEN2uScKJxI=; b=owEBbQKS/ZANAwAKASCtLsZbECziAcsmYgBpAhbrtiEdWcSV2NOayXdSjqF+6TdyBXJqeBKxT V+O0s2GKFyJAjMEAAEKAB0WIQRPj7g/vng8MQxQWQQgrS7GWxAs4gUCaQIW6wAKCRAgrS7GWxAs 4nmLD/9H0YT5x+8nydbcPgkwqy3AqfCu+poRWwjViT9699UXeXBjt892qOaw7mcIT+PHVKS0yOa xleZsqyIH9xet2GnsZtzWSMFPm4+PBKOdT1LrtI3sFNwTz7szxRoa74VmPWnMf1oMQnBRHms/l5 V9OBG7CBgXuUcXTzVo6e9/tB5K0MnAAxrActIUwrpXbc1PL9P4kOtzUXpcgeC1x1bG77U/T4SfF luDhf4huqdVadLMXwXgbsYRpktsF9YN4SYmnupTH8Tzx0kRJ7f1/R199I8miD/wWe6MAXpOj/wS 27vKNj59VT0qgLlsmnPMoGIHcXLJ5t1ofVcnL4D1+QMBy9kNpZzHQ+inn8Fs3AgN0VIayMPI8rv JOlKMaMWHSZClM+oTx0KGzUNxUhJIr9cc/Zk4nyDm8usWpbCJxfZUfnJGelVCfiHvfJal9aDgfj FoQlSeOkjnnFervSe0y8H+b7W1Cv+pLqXE00ySnlPMGIhCqqhOUYwgEP1milK917oC/kXNXMpqT zTaSA5cljeC4SxjLug/LFQh6SS6+INjT/d3ItoWfyUgd+Hymi8S7aT3mf69mCKfEvIkpuIYT7jD lMVmHvJzkonF2mCbgim3d7GlSDdCA/4v5UoEX3fjJXPEbmM52IQzPF3eg10wc3o7i00ds7L7G7F fhRn9HeWTppvuNw== X-Developer-Key: i=louis.chauvet@bootlin.com; a=openpgp; fpr=8B7104AE9A272D6693F527F2EC1883F55E0B40A5 X-Last-TLS-Session-Version: TLSv1.3 To allow the userspace to test many hardware configuration, introduce a new interface to configure the available formats per planes. VKMS supports multiple formats, so the userspace can choose any combination. The supported formats are configured by writing the fourcc code in supported_formats: # enable AR24 format echo '+AR24' > /config/vkms/DEVICE_1/planes/PLANE_1/supported_formats # disable AR24 format echo '-AR24' > /config/vkms/DEVICE_1/planes/PLANE_1/supported_formats # enable all format supported by VKMS echo '+*' > /config/vkms/DEVICE_1/planes/PLANE_1/supported_formats # disable all formats echo '-*' > /config/vkms/DEVICE_1/planes/PLANE_1/supported_formats Signed-off-by: Louis Chauvet --- Documentation/gpu/vkms.rst | 7 +- drivers/gpu/drm/vkms/tests/Makefile | 1 + drivers/gpu/drm/vkms/tests/vkms_configfs_test.c | 102 ++++++++++++++++++++ drivers/gpu/drm/vkms/vkms_configfs.c | 119 ++++++++++++++++++++= ++++ drivers/gpu/drm/vkms/vkms_configfs.h | 6 ++ 5 files changed, 234 insertions(+), 1 deletion(-) diff --git a/Documentation/gpu/vkms.rst b/Documentation/gpu/vkms.rst index 8383e1b94668..779ae363110d 100644 --- a/Documentation/gpu/vkms.rst +++ b/Documentation/gpu/vkms.rst @@ -87,7 +87,7 @@ Start by creating one or more planes:: =20 sudo mkdir /config/vkms/my-vkms/planes/plane0 =20 -Planes have 8 configurable attributes: +Planes have 9 configurable attributes: =20 - type: Plane type: 0 overlay, 1 primary, 2 cursor (same values as those exposed by the "type" property of a plane) @@ -109,6 +109,11 @@ Planes have 8 configurable attributes: must be set too. - default_color_range: Default color range presented to the userspace, same values as supported_color_range +- supported_formats: List of supported formats for this plane. To add a ne= w item in the + list, write it using a plus its fourcc code: +XR24 + To remove a format, use a minus and its fourcc: -XR24 + To add all formats use +* + To remove all formats, use -* =20 Continue by creating one or more CRTCs:: =20 diff --git a/drivers/gpu/drm/vkms/tests/Makefile b/drivers/gpu/drm/vkms/tes= ts/Makefile index 5750f0bd9d40..a2dc4008d27e 100644 --- a/drivers/gpu/drm/vkms/tests/Makefile +++ b/drivers/gpu/drm/vkms/tests/Makefile @@ -2,6 +2,7 @@ =20 vkms-kunit-tests-y :=3D \ vkms_config_test.o \ + vkms_configfs_test.o \ vkms_format_test.o =20 obj-$(CONFIG_DRM_VKMS_KUNIT_TEST) +=3D vkms-kunit-tests.o diff --git a/drivers/gpu/drm/vkms/tests/vkms_configfs_test.c b/drivers/gpu/= drm/vkms/tests/vkms_configfs_test.c new file mode 100644 index 000000000000..0963a8e8a585 --- /dev/null +++ b/drivers/gpu/drm/vkms/tests/vkms_configfs_test.c @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include "linux/printk.h" +#include + +#include "../vkms_configfs.h" + +MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING"); + +/** + * struct vkms_configfs_parse_format_case - Store test case for format par= sing + * @data: Contains the string to parse + * @data_len: data len + * @expected_len: expected len of the matched format + * @expected_offset: expected offset in the string for the parsed format + */ +struct vkms_configfs_parse_format_case { + const char *data; + int data_len; + int expected_len; + int expected_offset; +}; + +struct vkms_configfs_parse_format_case vkms_configfs_parse_format_test_cas= es[] =3D { + { + .data =3D "+RG24", + .data_len =3D 6, + .expected_len =3D 5, + .expected_offset =3D 0, + }, { + .data =3D "-RG24", + .data_len =3D 6, + .expected_len =3D 5, + .expected_offset =3D 0 + }, { + .data =3D " -RG24", + .data_len =3D 8, + .expected_len =3D 5, + .expected_offset =3D 2 + }, { + .data =3D "+*", + .data_len =3D 3, + .expected_len =3D 2, + .expected_offset =3D 0 + }, { + .data =3D "-RG24+RG24", + .data_len =3D 11, + .expected_len =3D 5, + .expected_offset =3D 0 + }, { + .data =3D "-R1+RG24", + .data_len =3D 9, + .expected_len =3D 3, + .expected_offset =3D 0 + }, { + .data =3D "\n-R1", + .data_len =3D 5, + .expected_len =3D 3, + .expected_offset =3D 1 + }, { + .data =3D "-R1111", + .data_len =3D 3, + .expected_len =3D 3, + .expected_offset =3D 0 + } +}; + +static void vkms_configfs_test_parse_format(struct kunit *test) +{ + const struct vkms_configfs_parse_format_case *param =3D test->param_value; + char *out; + int len =3D vkms_configfs_parse_next_format(param->data, param->data + pa= ram->data_len, &out); + + KUNIT_EXPECT_EQ(test, len, param->expected_len); + KUNIT_EXPECT_PTR_EQ(test, out, param->data + param->expected_offset); +} + +static void vkms_configfs_test_parse_format_get_desc(struct vkms_configfs_= parse_format_case *t, + char *desc) +{ + snprintf(desc, KUNIT_PARAM_DESC_SIZE, "%s", t->data); +} + +KUNIT_ARRAY_PARAM(vkms_configfs_test_parse_format, vkms_configfs_parse_for= mat_test_cases, + vkms_configfs_test_parse_format_get_desc +); + +static struct kunit_case vkms_configfs_test_cases[] =3D { + KUNIT_CASE_PARAM(vkms_configfs_test_parse_format, + vkms_configfs_test_parse_format_gen_params), + {} +}; + +static struct kunit_suite vkms_configfs_test_suite =3D { + .name =3D "vkms-configfs", + .test_cases =3D vkms_configfs_test_cases, +}; + +kunit_test_suite(vkms_configfs_test_suite); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Kunit test for vkms configfs utility"); diff --git a/drivers/gpu/drm/vkms/vkms_configfs.c b/drivers/gpu/drm/vkms/vk= ms_configfs.c index 3f658dd41272..b0a26c4dbebe 100644 --- a/drivers/gpu/drm/vkms/vkms_configfs.c +++ b/drivers/gpu/drm/vkms/vkms_configfs.c @@ -1,8 +1,11 @@ // SPDX-License-Identifier: GPL-2.0+ + #include #include #include #include +#include +#include =20 #include "vkms_drv.h" #include "vkms_config.h" @@ -618,6 +621,120 @@ static ssize_t plane_default_color_encoding_store(str= uct config_item *item, return count; } =20 +static ssize_t plane_supported_formats_show(struct config_item *item, char= *page) +{ + struct vkms_configfs_plane *plane; + + plane =3D plane_item_to_vkms_configfs_plane(item); + + page[0] =3D '\0'; + + scoped_guard(mutex, &plane->dev->lock) { + u32 *formats =3D vkms_config_plane_get_supported_formats(plane->config); + + for (int i =3D 0; + i < vkms_config_plane_get_supported_formats_count(plane->config); + i++) { + char tmp[6] =3D { 0 }; + const ssize_t ret =3D snprintf(tmp, ARRAY_SIZE(tmp), "%.*s\n", + (int)sizeof(*formats), + (char *)&formats[i]); + if (ret < 0) + return ret; + /* + * Limitation of ConfigFS attributes, an attribute can't be bigger + * than PAGE_SIZE. This will crop the result if this plane support + * more than =E2=89=881000 formats. + */ + if (ret + strlen(page) > PAGE_SIZE - 1) + return -ENOMEM; + strncat(page, tmp, ARRAY_SIZE(tmp)); + } + } + + return strlen(page); +} + +/** + * parse_next_format() - Parse the next format in page, skipping all non f= ourcc-related characters + * @page: page to search into + * @page_end: last charater of the page + * @out: Output pointer, will point inside page + * + * Returns: size of the matched format, @out will point to the + or - + */ +VISIBLE_IF_KUNIT +int vkms_configfs_parse_next_format(const char *page, const char *page_end= , char **out) +{ + int count =3D page - page_end; + char *tmp_plus =3D strnchr(page, count, '+'); + char *tmp_minus =3D strnchr(page, count, '-'); + + if (!tmp_plus && !tmp_minus) + return 0; + if (!tmp_plus) + *out =3D tmp_minus; + else if (!tmp_minus) + *out =3D tmp_plus; + else + *out =3D min(tmp_plus, tmp_minus); + + char *end =3D *out + 1; + + while (end < page_end) { + if (!isalnum(*end) && *end !=3D '*') + break; + end++; + } + + return end - *out; +} +EXPORT_SYMBOL_IF_KUNIT(vkms_configfs_parse_next_format); + +static ssize_t plane_supported_formats_store(struct config_item *item, + const char *page, size_t count) +{ + struct vkms_configfs_plane *plane; + + plane =3D plane_item_to_vkms_configfs_plane(item); + int ret =3D 0; + const char *end_page =3D page + count; + + scoped_guard(mutex, &plane->dev->lock) { + while (1) { + char *tmp; + char fmt[4] =3D {' ', ' ', ' ', ' '}; + int len =3D vkms_configfs_parse_next_format(page, end_page, &tmp); + + // No fourcc code found + if (len <=3D 1) + break; + + page =3D tmp + len; + memcpy(tmp, &fmt[1], min(len - 1, 4)); + if (tmp[0] =3D=3D '+') { + if (fmt[0] =3D=3D '*') { + ret =3D vkms_config_plane_add_all_formats(plane->config); + if (ret) + return ret; + } else { + ret =3D vkms_config_plane_add_format(plane->config, + *(int *)fmt); + if (ret) + return ret; + } + } else if (tmp[0] =3D=3D '-') { + if (fmt[0] =3D=3D '*') + vkms_config_plane_remove_all_formats(plane->config); + else + vkms_config_plane_remove_format(plane->config, *(int *)fmt); + } + } + } + + return count; +} + CONFIGFS_ATTR(plane_, type); CONFIGFS_ATTR(plane_, name); CONFIGFS_ATTR(plane_, supported_rotations); @@ -626,6 +743,7 @@ CONFIGFS_ATTR(plane_, supported_color_ranges); CONFIGFS_ATTR(plane_, default_color_range); CONFIGFS_ATTR(plane_, supported_color_encodings); CONFIGFS_ATTR(plane_, default_color_encoding); +CONFIGFS_ATTR(plane_, supported_formats); =20 static struct configfs_attribute *plane_item_attrs[] =3D { &plane_attr_type, @@ -636,6 +754,7 @@ static struct configfs_attribute *plane_item_attrs[] = =3D { &plane_attr_default_color_range, &plane_attr_supported_color_encodings, &plane_attr_default_color_encoding, + &plane_attr_supported_formats, NULL, }; =20 diff --git a/drivers/gpu/drm/vkms/vkms_configfs.h b/drivers/gpu/drm/vkms/vk= ms_configfs.h index e9020b0043db..2774655bfcc5 100644 --- a/drivers/gpu/drm/vkms/vkms_configfs.h +++ b/drivers/gpu/drm/vkms/vkms_configfs.h @@ -2,7 +2,13 @@ #ifndef _VKMS_CONFIGFS_H_ #define _VKMS_CONFIGFS_H_ =20 +#include + int vkms_configfs_register(void); void vkms_configfs_unregister(void); =20 +#if IS_ENABLED(CONFIG_KUNIT) +int vkms_configfs_parse_next_format(const char *page, const char *end_page= , char **out); +#endif + #endif /* _VKMS_CONFIGFS_H_ */ --=20 2.51.0