From nobody Mon Feb 9 13:37:02 2026 Received: from mail-wm1-f51.google.com (mail-wm1-f51.google.com [209.85.128.51]) (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 F1371199230 for ; Wed, 29 Jan 2025 11:01:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738148469; cv=none; b=U/zhUX/J2XkhZZ88BoMM3PPiGYVckjQTI/VPyPcRKSL8on8Yp6Od8gFK3zRhoIguB/KFSrxu30+dhMEjPGa6tdS5/eRqadN+rSSA2q3jVCaBqNEqHoP4RT0sv5FEtbxAItOUT13b3WRVajSjisDVnciI3yvB0kRouIvKhJMUYew= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738148469; c=relaxed/simple; bh=jTWvVXKK9XDaJbYor54RHRHgA8EphIDA4CQFEt1p2yk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=KCpQuJOXZesG0DImKZm6jtJK2n9ktwWWRMu9Ku6tINlRFm/sUvPi3CHOyhDLdf2n2NhkqMkN16iQgwXiDbMCyZazNLlNXGitZe6PbaxC2TbMStMsBQyIQTdXtZHbzg5Hek0O+G84VWFXwGuzWZI5iPx6c/x2u/ncuCYpp+1lNQM= 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=lY02aCiN; arc=none smtp.client-ip=209.85.128.51 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="lY02aCiN" Received: by mail-wm1-f51.google.com with SMTP id 5b1f17b1804b1-436341f575fso74033045e9.1 for ; Wed, 29 Jan 2025 03:01:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1738148466; x=1738753266; 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=9S+7C5eQRPWzuHKFjKrS6n1FuYqDvplaGUQ2TD3AN7Y=; b=lY02aCiNKnor4Ew3heylyzh+c+JzoMWqDKYmXFw988ZUjQbpOatCX6rC9xA9xhM9gh wew4Tjqf6t2LRKR3XROv5q/F9id4Ya1sD/mXc8eIoh9ystO32DK0Ds5B1zuplq4Yt/BN 5FCL47l9kEl+vz1vFaPU29mIv0Ckp3IzOt7JahKme8YzPqQqO2X2vV+cexyTBaMCdfNN jeo4dqJdPsBE2YdLne7EYxHkdCw35kIPZBpcsjZ8SiQXVyNKummHQ1cetIjcOuMm1v8o PdT7ScCPVMcMwa7OpSogjTgF1orvYvOj7Z0CFJsQ9Uw59sDkrgGRQ9PeaLMbG8NGNKn2 mbIw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1738148466; x=1738753266; 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=9S+7C5eQRPWzuHKFjKrS6n1FuYqDvplaGUQ2TD3AN7Y=; b=RIuBxX9svw+HWK2t61ccARFYlMGLFlZ6kOYsdxThTxjebPx66Rt4AnW7Yc6IABU0pN STpp2KZUyUZNEiVc3PB083yy2Qbck2ZNG7ZPO/5aCU0Mh8TOVsoRFDMsAjRC/3fRAVxp xD30YabNVSlu+Ejfvh7xIAwnSR01JT37vpHEHbB7Yc8Ge+lOvLL8ujX0hFj2QmS3yEvg RAvFRBgjTCojKJ8+XOR0/ZRVk7hOILv0Szu3U7Hb5cdBOv+ot17yxbKQtlVeVHIGbFOQ WUMEowner6xm5G+Xo8JoJumIUYvWetu6AO4BT21q7MbTbOOUwb5jjq2XDAmlyQLxDQpt oRTg== X-Forwarded-Encrypted: i=1; AJvYcCWywvRf6az9pWlIzXmRJlk7ZsPmfjyvnTACoBmTIbxuMcDwQBKtjc1SRHbhe3X1nAaQJ0b+vUG9IDwhBCU=@vger.kernel.org X-Gm-Message-State: AOJu0Yyt+UMPY2bcpQRzkyIdZXHqV7aWbnaAyuK4/U+jHFS+kZSfO1kT kdqjKsD/GHmEcz3kxDME9xCaqT6LIZf2cNdKEJTikTXgDRFoQaUb X-Gm-Gg: ASbGnctn7dxDdcJE97Bbs1Bv9i7PM8YMrazgtpEHE+g87WBEwYoNRjEvBhAqrAF6GoQ faH9dtIco6g5bk7r+qJbOUcoIXdxt/GCSS2uKlHDT/v1vSJQb4G7FH+Mi17GawiiRYYB+C0Ie/l AtVKi6AmomBJwQ7pMU8EEfFDls6ETTyYPy4lQE79EQHplb0Lug68FQ3RyP8anCgbF1+bjFTc3jp RlUAieD7MbgcMpQ7k/XMXmbuE3OJrQGslaf4h70ZlpoGZ0h6IPYSI4NsFhaR5FqgzGU6BCsrszu +Z3t1Hg/SJIhwlPX X-Google-Smtp-Source: AGHT+IGHXcYWBGVD149ms+rmsIFUA7ZyRH6Ih7lsGoiLaHzrNT56I8mZyx+mQ+eMvA8IwLloDChjhg== X-Received: by 2002:a05:600c:3b94:b0:434:ff45:cbbe with SMTP id 5b1f17b1804b1-438dc3cba35mr22656875e9.18.1738148465987; Wed, 29 Jan 2025 03:01:05 -0800 (PST) Received: from fedora.. ([94.73.37.161]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-38c2a176434sm16947113f8f.13.2025.01.29.03.01.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Jan 2025 03:01:05 -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 01/13] drm/vkms: Extract vkms_connector header Date: Wed, 29 Jan 2025 12:00:47 +0100 Message-ID: <20250129110059.12199-2-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 Up until now, the logic to manage connectors was in vkms_output.c. Since more options will be added to connectors in the future, extract the code to its own file. Refactor, no functional changes. Signed-off-by: Jos=C3=A9 Exp=C3=B3sito Reviewed-by: Louis Chauvet --- drivers/gpu/drm/vkms/Makefile | 3 +- drivers/gpu/drm/vkms/vkms_connector.c | 50 +++++++++++++++++++++++++++ drivers/gpu/drm/vkms/vkms_connector.h | 26 ++++++++++++++ drivers/gpu/drm/vkms/vkms_output.c | 45 ++++-------------------- 4 files changed, 84 insertions(+), 40 deletions(-) create mode 100644 drivers/gpu/drm/vkms/vkms_connector.c create mode 100644 drivers/gpu/drm/vkms/vkms_connector.h diff --git a/drivers/gpu/drm/vkms/Makefile b/drivers/gpu/drm/vkms/Makefile index 1b28a6a32948..6b0615c424f2 100644 --- a/drivers/gpu/drm/vkms/Makefile +++ b/drivers/gpu/drm/vkms/Makefile @@ -6,6 +6,7 @@ vkms-y :=3D \ vkms_formats.o \ vkms_crtc.o \ vkms_composer.o \ - vkms_writeback.o + vkms_writeback.o \ + vkms_connector.o =20 obj-$(CONFIG_DRM_VKMS) +=3D vkms.o diff --git a/drivers/gpu/drm/vkms/vkms_connector.c b/drivers/gpu/drm/vkms/v= kms_connector.c new file mode 100644 index 000000000000..ab8b52a84151 --- /dev/null +++ b/drivers/gpu/drm/vkms/vkms_connector.c @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include +#include +#include +#include + +#include "vkms_connector.h" + +static const struct drm_connector_funcs vkms_connector_funcs =3D { + .fill_modes =3D drm_helper_probe_single_connector_modes, + .reset =3D drm_atomic_helper_connector_reset, + .atomic_duplicate_state =3D drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state =3D drm_atomic_helper_connector_destroy_state, +}; + +static int vkms_conn_get_modes(struct drm_connector *connector) +{ + int count; + + /* Use the default modes list from DRM */ + count =3D drm_add_modes_noedid(connector, XRES_MAX, YRES_MAX); + drm_set_preferred_mode(connector, XRES_DEF, YRES_DEF); + + return count; +} + +static const struct drm_connector_helper_funcs vkms_conn_helper_funcs =3D { + .get_modes =3D vkms_conn_get_modes, +}; + +struct vkms_connector *vkms_connector_init(struct vkms_device *vkmsdev) +{ + struct drm_device *dev =3D &vkmsdev->drm; + struct vkms_connector *connector; + int ret; + + connector =3D drmm_kzalloc(dev, sizeof(*connector), GFP_KERNEL); + if (!connector) + return ERR_PTR(-ENOMEM); + + ret =3D drmm_connector_init(dev, &connector->base, &vkms_connector_funcs, + DRM_MODE_CONNECTOR_VIRTUAL, NULL); + if (ret) + return ERR_PTR(ret); + + drm_connector_helper_add(&connector->base, &vkms_conn_helper_funcs); + + return connector; +} diff --git a/drivers/gpu/drm/vkms/vkms_connector.h b/drivers/gpu/drm/vkms/v= kms_connector.h new file mode 100644 index 000000000000..c9149c1b7af0 --- /dev/null +++ b/drivers/gpu/drm/vkms/vkms_connector.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#ifndef _VKMS_CONNECTOR_H_ +#define _VKMS_CONNECTOR_H_ + +#include "vkms_drv.h" + +/** + * struct vkms_connector - VKMS custom type wrapping around the DRM connec= tor + * + * @drm: Base DRM connector + */ +struct vkms_connector { + struct drm_connector base; +}; + +/** + * vkms_connector_init() - Initialize a connector + * @vkmsdev: VKMS device containing the connector + * + * Returns: + * The connector or an error on failure. + */ +struct vkms_connector *vkms_connector_init(struct vkms_device *vkmsdev); + +#endif /* _VKMS_CONNECTOR_H_ */ diff --git a/drivers/gpu/drm/vkms/vkms_output.c b/drivers/gpu/drm/vkms/vkms= _output.c index 22f0d678af3a..4b5abe159add 100644 --- a/drivers/gpu/drm/vkms/vkms_output.c +++ b/drivers/gpu/drm/vkms/vkms_output.c @@ -1,37 +1,13 @@ // SPDX-License-Identifier: GPL-2.0+ =20 +#include "vkms_connector.h" #include "vkms_drv.h" -#include -#include #include -#include - -static const struct drm_connector_funcs vkms_connector_funcs =3D { - .fill_modes =3D drm_helper_probe_single_connector_modes, - .reset =3D drm_atomic_helper_connector_reset, - .atomic_duplicate_state =3D drm_atomic_helper_connector_duplicate_state, - .atomic_destroy_state =3D drm_atomic_helper_connector_destroy_state, -}; - -static int vkms_conn_get_modes(struct drm_connector *connector) -{ - int count; - - /* Use the default modes list from DRM */ - count =3D drm_add_modes_noedid(connector, XRES_MAX, YRES_MAX); - drm_set_preferred_mode(connector, XRES_DEF, YRES_DEF); - - return count; -} - -static const struct drm_connector_helper_funcs vkms_conn_helper_funcs =3D { - .get_modes =3D vkms_conn_get_modes, -}; =20 int vkms_output_init(struct vkms_device *vkmsdev) { struct drm_device *dev =3D &vkmsdev->drm; - struct drm_connector *connector; + struct vkms_connector *connector; struct drm_encoder *encoder; struct vkms_output *output; struct vkms_plane *primary, *overlay, *cursor =3D NULL; @@ -73,21 +49,12 @@ int vkms_output_init(struct vkms_device *vkmsdev) } } =20 - connector =3D drmm_kzalloc(dev, sizeof(*connector), GFP_KERNEL); - if (!connector) { - DRM_ERROR("Failed to allocate connector\n"); - return -ENOMEM; - } - - ret =3D drmm_connector_init(dev, connector, &vkms_connector_funcs, - DRM_MODE_CONNECTOR_VIRTUAL, NULL); - if (ret) { + connector =3D vkms_connector_init(vkmsdev); + if (IS_ERR(connector)) { DRM_ERROR("Failed to init connector\n"); - return ret; + return PTR_ERR(connector); } =20 - drm_connector_helper_add(connector, &vkms_conn_helper_funcs); - encoder =3D drmm_kzalloc(dev, sizeof(*encoder), GFP_KERNEL); if (!encoder) { DRM_ERROR("Failed to allocate encoder\n"); @@ -102,7 +69,7 @@ int vkms_output_init(struct vkms_device *vkmsdev) encoder->possible_crtcs =3D drm_crtc_mask(&output->crtc); =20 /* Attach the encoder and the connector */ - ret =3D drm_connector_attach_encoder(connector, encoder); + ret =3D drm_connector_attach_encoder(&connector->base, encoder); if (ret) { DRM_ERROR("Failed to attach connector to encoder\n"); return ret; --=20 2.48.1 From nobody Mon Feb 9 13:37:02 2026 Received: from mail-wr1-f49.google.com (mail-wr1-f49.google.com [209.85.221.49]) (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 A27061B0F11 for ; Wed, 29 Jan 2025 11:01:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.49 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738148471; cv=none; b=MEc4s2TbBuI/E3ugzNbpxA3AxwXmHRLasmFU1rRWvYgQtxpbERt8C9I4a6GaMzkU/XDQKdWtNkX64zXsvB28cZTNBUMhJLIBSSShC7LSj6A6WxNBRIF6FFaU0PS7nCvZQQWOjVr2U4oaHBmPZrq5hyNSGfijdlA/r0DDFn/JVik= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738148471; c=relaxed/simple; bh=lBEbcd1iOjWx0wmR/qwE3tKBQUawvDozD6hMsTu7uME=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=LZ0gl8E2Ifj0YCotUsH5OxDijWbyd92EEwlCacPPPl7XHIXvT4efmLNp4irg/LNnI0mZfPdvnlv6k2FxlAFz0Ypmvd0IFF2VLMtr+gg+G0lTGUM3WftIALz9a/mTp4MqJE1KJxO0aEIB9TIDZa6qUueNrLnhr5HZSwp8AYM/hC8= 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=EfowVzkb; arc=none smtp.client-ip=209.85.221.49 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="EfowVzkb" Received: by mail-wr1-f49.google.com with SMTP id ffacd0b85a97d-38637614567so3260917f8f.3 for ; Wed, 29 Jan 2025 03:01:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1738148468; x=1738753268; 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=9bX+6EwizABkI0McC7gIJiE+k/hJhaZ4QvaDj5BOaFA=; b=EfowVzkb8fXV2j3o9SO31CvC1hKcpibFJhvBm33u6e6X/JuFlhmLlr1rYEO0Kd0NNQ Dw3QYshZ+PzTDU8GldBYeG1phYT2uyjJMpH7OhBBkI+jh+8IzTjFavspYSHW+WN0gQHA wKs0s3+3MGSAiSeaEvevUu+wiH1CVn8PyEUTVgtkSnM7QbOdnnuBGjWR4tWh0uy3YlOV 85KRU3WfxDmXn4M61CmtdLsnmkTzgpGoTNkJv2QT4D86JdC5lVu2a/UKFzvyh9QEFPYp nHoYAkJi5F6EvXrdSr03CBe/sf0d4IOccggysBS5OkDtYwM64IUesM1zjV0DRpSqz5CP ekvQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1738148468; x=1738753268; 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=9bX+6EwizABkI0McC7gIJiE+k/hJhaZ4QvaDj5BOaFA=; b=Z15CJT54zDaA8SbQowHoM2h+yu79OAU8P6gswPfIM2fZCBlZGbkmKmDdBFtlOi6c4l H6CfZdTwQd2tHXP5cM1Db1AsV0N7G2heA2sRq81dEyzqesDrvQI5JCEiGyjAAKM8Kdhc uTWjg8jDTcWb34JJahY4uOOofDpUv/+3MHDYVJJQvbYhQY8eAZSLflkcdM9rkS4x1geG AkvzN0WuL0O3GyFB5ZAHLlnqXwG6OprlskZOD0cNNB4yZtBNDwlDWsyIQesxjOy0N0/W 0o0M4sNLbYjMQm2rpdg8quhpSwr7sInUzXhDUySDzZP+ZmWbWpoPVNU3Nj3wLQWm1YK9 Nxiw== X-Forwarded-Encrypted: i=1; AJvYcCX82TKRGYErXDQ4jZvoFbNe8fbblRB22Raqz+lHTwwmTCjTTh/G/iUU3fIrdZtilAttp15bTRZIX37sPQk=@vger.kernel.org X-Gm-Message-State: AOJu0YwVkkIT0uvjXO13sgj7UZInFFtOcPAFzE86UOO/LU3K1sXL2knS PuMqHIashQP5krJ2MYK+U3uePhuDAKoP9JuXAZoCXlVfzQlfSk9q X-Gm-Gg: ASbGnctzXJc3SeP0AUzi3fCtcdInC2HQJNJ1HcgMA5Q6Y/HmzY1t9B2981jojQ+vZ92 PsF2+krAS7JEi2TWZa9iCY0kdTPRh96+/1pZSeVcg8zc5jlGO+NatXNk+SsN+9qf3+CeF8a0fVu So0yVJBAyDYmTkERozMXn/7gshJQxQolep2fBcznN4KxDcstai5HHw+8PmN7Yh5u/PNF2YfSGoH O0z4XCAZ8ghFnj8Y2OmTWVy4ySYlTCMIQ4roQycJTdoVtcTf3zmEtnvoDoML/2CMtUf9mt11SCG ppgK0WHIXbXZkiAr X-Google-Smtp-Source: AGHT+IF0iya3LHyS6aQhAfiWBUhNrHZ30Sab7dWyXgj5JiWlbgQ4M/vCB2thWkPLBNN7BECgrimYKg== X-Received: by 2002:a05:6000:4008:b0:386:459e:655d with SMTP id ffacd0b85a97d-38c51952173mr2188558f8f.20.1738148467573; Wed, 29 Jan 2025 03:01:07 -0800 (PST) Received: from fedora.. ([94.73.37.161]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-38c2a176434sm16947113f8f.13.2025.01.29.03.01.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Jan 2025 03:01:06 -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?= , Arthur Grillo Subject: [PATCH 02/13] drm/vkms: Add KUnit test scaffolding Date: Wed, 29 Jan 2025 12:00:48 +0100 Message-ID: <20250129110059.12199-3-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 the required boilerplate to start creating KUnit test. To run the tests: $ ./tools/testing/kunit/kunit.py run \ --kunitconfig=3Ddrivers/gpu/drm/vkms/tests Signed-off-by: Arthur Grillo Signed-off-by: Louis Chauvet Signed-off-by: Jos=C3=A9 Exp=C3=B3sito Reviewed-by: Louis Chauvet --- drivers/gpu/drm/vkms/Kconfig | 15 +++++++++++++ drivers/gpu/drm/vkms/Makefile | 1 + drivers/gpu/drm/vkms/tests/.kunitconfig | 4 ++++ drivers/gpu/drm/vkms/tests/Makefile | 3 +++ drivers/gpu/drm/vkms/tests/vkms_config_test.c | 21 +++++++++++++++++++ 5 files changed, 44 insertions(+) create mode 100644 drivers/gpu/drm/vkms/tests/.kunitconfig create mode 100644 drivers/gpu/drm/vkms/tests/Makefile create mode 100644 drivers/gpu/drm/vkms/tests/vkms_config_test.c diff --git a/drivers/gpu/drm/vkms/Kconfig b/drivers/gpu/drm/vkms/Kconfig index 9def079f685b..d4665e913de7 100644 --- a/drivers/gpu/drm/vkms/Kconfig +++ b/drivers/gpu/drm/vkms/Kconfig @@ -14,3 +14,18 @@ config DRM_VKMS a VKMS. =20 If M is selected the module will be called vkms. + +config DRM_VKMS_KUNIT_TESTS + tristate "KUnit tests for VKMS." if !KUNIT_ALL_TESTS + depends on DRM_VKMS && KUNIT + default KUNIT_ALL_TESTS + help + This builds unit tests for VKMS. This option is not useful for + distributions or general kernels, but only for kernel + developers working on VKMS. + + For more information on KUnit and unit tests in general, + please refer to the KUnit documentation in + Documentation/dev-tools/kunit/. + + If in doubt, say "N". diff --git a/drivers/gpu/drm/vkms/Makefile b/drivers/gpu/drm/vkms/Makefile index 6b0615c424f2..45ef4b89379e 100644 --- a/drivers/gpu/drm/vkms/Makefile +++ b/drivers/gpu/drm/vkms/Makefile @@ -10,3 +10,4 @@ vkms-y :=3D \ vkms_connector.o =20 obj-$(CONFIG_DRM_VKMS) +=3D vkms.o +obj-$(CONFIG_DRM_VKMS_KUNIT_TESTS) +=3D tests/ diff --git a/drivers/gpu/drm/vkms/tests/.kunitconfig b/drivers/gpu/drm/vkms= /tests/.kunitconfig new file mode 100644 index 000000000000..70e378228cbd --- /dev/null +++ b/drivers/gpu/drm/vkms/tests/.kunitconfig @@ -0,0 +1,4 @@ +CONFIG_KUNIT=3Dy +CONFIG_DRM=3Dy +CONFIG_DRM_VKMS=3Dy +CONFIG_DRM_VKMS_KUNIT_TESTS=3Dy diff --git a/drivers/gpu/drm/vkms/tests/Makefile b/drivers/gpu/drm/vkms/tes= ts/Makefile new file mode 100644 index 000000000000..b78371d08aa9 --- /dev/null +++ b/drivers/gpu/drm/vkms/tests/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0-only + +obj-$(CONFIG_DRM_VKMS_KUNIT_TESTS) +=3D vkms_config_test.o diff --git a/drivers/gpu/drm/vkms/tests/vkms_config_test.c b/drivers/gpu/dr= m/vkms/tests/vkms_config_test.c new file mode 100644 index 000000000000..ba93d864d57f --- /dev/null +++ b/drivers/gpu/drm/vkms/tests/vkms_config_test.c @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include + +#include "../vkms_config.h" + +MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING"); + +static struct kunit_case vkms_config_test_cases[] =3D { + {} +}; + +static struct kunit_suite vkms_config_test_suite =3D { + .name =3D "vkms-config", + .test_cases =3D vkms_config_test_cases, +}; + +kunit_test_suite(vkms_config_test_suite); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Kunit test for vkms config utility"); --=20 2.48.1 From nobody Mon Feb 9 13:37:02 2026 Received: from mail-wm1-f49.google.com (mail-wm1-f49.google.com [209.85.128.49]) (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 E93311B85D1 for ; Wed, 29 Jan 2025 11:01:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.49 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738148472; cv=none; b=ip21m0va+OWtBqZKP4OUPhVqw8FZoQr847SGk8tCI1/sgHYWpA8XDqUywMr/xWhhgRF7Y25HDVQ7kSjDw4yqX+b+e/2KS3a/2KA6muo7gBZjdU0xHRTHxDuRXJh77lIBtBQPEVlv6OBsfjB+PNujXn6I6pTolidUf09ti+Kshz4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738148472; c=relaxed/simple; bh=TQ05MTIEaYwJSl1EjvqqWaL3pItomATTQgohxRT713c=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=TgMmx6IQG3ahXPfyA5fTqX5McQzBgM1vyiAtEfLKi0t3v4CdXS0pRddxZz2ViTzFBhL6IAd7M9Qdg4TntNGy4O0CFoZ2yYsBX96aFudt3EM++WDskXscJ107Ht5Aeu1uTZTL9Jv2hO3COL2IIzmdfW+WO94x0YAie2EMYOgFa7g= 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=bGR/1ZWm; arc=none smtp.client-ip=209.85.128.49 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="bGR/1ZWm" Received: by mail-wm1-f49.google.com with SMTP id 5b1f17b1804b1-436345cc17bso47917615e9.0 for ; Wed, 29 Jan 2025 03:01:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1738148469; x=1738753269; 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=6bzQMlUxW1EEe5ba9zNeNJsn9NRKOLczD9tgi8KPhh0=; b=bGR/1ZWmC9lr7Qqbq6ZKoYKSMLiujyCAy9qMmUGicWSLxopc1r6GWfDu2+JB6wQ7fU uX8523Te1vS+4slkC2hKYKRv4U2E+XULxZrF/FMwYRw6gdOQPDKIKovZz0Yen6iWczve 8zD0CnTZZZ/cB74CHXJYbGwL5lp5QnjVbSGQxFqbk5Uwkc9UVRW/sA/4W4UE4OSPUeKW 2UHwmtJg5fy1nfpaN0JRb8zpKTlogO3PgJj+xAgr0o21QYrBzBY5EX+hHZagybnVylFG Apcxboclp1Xvr8jhZ80P2Lg7O/U4R5y7Dd6UYCly1a3SquwJUvWatF6ol1IdgAYz77GR Wvxw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1738148469; x=1738753269; 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=6bzQMlUxW1EEe5ba9zNeNJsn9NRKOLczD9tgi8KPhh0=; b=VNx/1n/7CmlPTDbDnylBNP+ZI3rpqd2iMtniuVGVzpFY9uIzGLoWt2WmMpsvw3L1Mi /DddXZcUKoUyEllxWdbiSJhhDo6eDtZI9PlOILkOMkSZ+kEBze327AZzSyYsmTuL0Gtz cnlf8hDSuKvl0wyoIVDyvHLSxnbY5XhPZqjtxw/YQ6Twv6WCWIQFitSWJM6M9sU+WbQo GSH/eRCJlshyRBZSzQyHFlspLV01fKg4xPm78lZnfVn+qSmMsslkpV8fnqhO9x326SJh tmC5xwKesKJnkCblRDpCPjY+uMtrfnQ9NQrBP3p2GAPZtZPdE+cH7h2pfBDAtlRfbYOt FiwQ== X-Forwarded-Encrypted: i=1; AJvYcCUOvL3TJdWSx9VSNqpkCax61/TWJxVbmHzmO9KXCsnZY1U14WAssMYrophnPJwElhDr8JGlp/YoOTMLsJo=@vger.kernel.org X-Gm-Message-State: AOJu0YyP/X9lzxcOqROEB9unFWGwow86qL9A421vnD8uhr4FPz1bhDQM AUVib6AygN04w5QBS6sw0md80u2i9Q4YS7HVWk5rhNdGN78BiOWQ X-Gm-Gg: ASbGncu7WO/ngz9YR4tQhVbfr+QSfEjYGxdHenighzBAT+dEk7ARcnpIc/vFjmEjucc od4bpoP2eniX6H+hvNDDxDULjSV1HBZ3gXMa5dFJ13/UnT7Tp8uVDEij3OLgfatLFdKGSkQ9jg3 dXCDBfMA/nXjo6ZihGXr/hwp10rFocQiPNubuXW/B5pO/cimR4whFDCFVQcz2eU7AAhgQ0SmfAe HSh8lCNIX2cEh30HsD8sj2Ls1QRQpY0AxQxA0UoSdZNOv2eTz9SvVrAqXN9TbM7+QVLY9gRm4Qk Shm/7FmPesyhhsaO X-Google-Smtp-Source: AGHT+IEaD5Epnui96Ne96gVy0PYPsd828wNvu1Ty2RyBjkfQ3XZw1V5TBTPbNeiOqJZdOBbVOxUpfg== X-Received: by 2002:a05:6000:1fa4:b0:38a:673b:3738 with SMTP id ffacd0b85a97d-38c519738d2mr2325796f8f.33.1738148468729; Wed, 29 Jan 2025 03:01:08 -0800 (PST) Received: from fedora.. ([94.73.37.161]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-38c2a176434sm16947113f8f.13.2025.01.29.03.01.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Jan 2025 03:01:08 -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 03/13] drm/vkms: Extract vkms_config header Date: Wed, 29 Jan 2025 12:00:49 +0100 Message-ID: <20250129110059.12199-4-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 Creating a new vkms_config structure will be more complex once we start adding more options. Extract the vkms_config structure to its own header and source files and add functions to create and delete a vkms_config and to initialize debugfs. Refactor, no functional changes. Signed-off-by: Louis Chauvet Signed-off-by: Jos=C3=A9 Exp=C3=B3sito Reviewed-by: Louis Chauvet --- drivers/gpu/drm/vkms/Makefile | 3 +- drivers/gpu/drm/vkms/tests/vkms_config_test.c | 11 +++++ drivers/gpu/drm/vkms/vkms_config.c | 47 +++++++++++++++++++ drivers/gpu/drm/vkms/vkms_config.h | 47 +++++++++++++++++++ drivers/gpu/drm/vkms/vkms_drv.c | 34 +++----------- drivers/gpu/drm/vkms/vkms_drv.h | 15 +----- drivers/gpu/drm/vkms/vkms_output.c | 1 + 7 files changed, 116 insertions(+), 42 deletions(-) create mode 100644 drivers/gpu/drm/vkms/vkms_config.c create mode 100644 drivers/gpu/drm/vkms/vkms_config.h diff --git a/drivers/gpu/drm/vkms/Makefile b/drivers/gpu/drm/vkms/Makefile index 45ef4b89379e..9bf6b8f94daf 100644 --- a/drivers/gpu/drm/vkms/Makefile +++ b/drivers/gpu/drm/vkms/Makefile @@ -7,7 +7,8 @@ vkms-y :=3D \ vkms_crtc.o \ vkms_composer.o \ vkms_writeback.o \ - vkms_connector.o + vkms_connector.o \ + vkms_config.o =20 obj-$(CONFIG_DRM_VKMS) +=3D vkms.o obj-$(CONFIG_DRM_VKMS_KUNIT_TESTS) +=3D tests/ diff --git a/drivers/gpu/drm/vkms/tests/vkms_config_test.c b/drivers/gpu/dr= m/vkms/tests/vkms_config_test.c index ba93d864d57f..a7060504f3dc 100644 --- a/drivers/gpu/drm/vkms/tests/vkms_config_test.c +++ b/drivers/gpu/drm/vkms/tests/vkms_config_test.c @@ -6,7 +6,18 @@ =20 MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING"); =20 +static void vkms_config_test_empty_config(struct kunit *test) +{ + struct vkms_config *config; + + config =3D vkms_config_create(); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config); + + vkms_config_destroy(config); +} + static struct kunit_case vkms_config_test_cases[] =3D { + KUNIT_CASE(vkms_config_test_empty_config), {} }; =20 diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms= _config.c new file mode 100644 index 000000000000..152b2ecd6aef --- /dev/null +++ b/drivers/gpu/drm/vkms/vkms_config.c @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include + +#include +#include + +#include "vkms_config.h" + +struct vkms_config *vkms_config_create(void) +{ + struct vkms_config *config; + + config =3D kzalloc(sizeof(*config), GFP_KERNEL); + if (!config) + return ERR_PTR(-ENOMEM); + + return config; +} + +void vkms_config_destroy(struct vkms_config *config) +{ + kfree(config); +} + +static int vkms_config_show(struct seq_file *m, void *data) +{ + struct drm_debugfs_entry *entry =3D m->private; + struct drm_device *dev =3D entry->dev; + struct vkms_device *vkmsdev =3D drm_device_to_vkms_device(dev); + + seq_printf(m, "writeback=3D%d\n", vkmsdev->config->writeback); + seq_printf(m, "cursor=3D%d\n", vkmsdev->config->cursor); + seq_printf(m, "overlay=3D%d\n", vkmsdev->config->overlay); + + return 0; +} + +static const struct drm_debugfs_info vkms_config_debugfs_list[] =3D { + { "vkms_config", vkms_config_show, 0 }, +}; + +void vkms_config_register_debugfs(struct vkms_device *vkms_device) +{ + drm_debugfs_add_files(&vkms_device->drm, vkms_config_debugfs_list, + ARRAY_SIZE(vkms_config_debugfs_list)); +} diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms= _config.h new file mode 100644 index 000000000000..ced10f56a812 --- /dev/null +++ b/drivers/gpu/drm/vkms/vkms_config.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#ifndef _VKMS_CONFIG_H_ +#define _VKMS_CONFIG_H_ + +#include + +#include "vkms_drv.h" + +/** + * struct vkms_config - General configuration for VKMS driver + * + * @writeback: If true, a writeback buffer can be attached to the CRTC + * @cursor: If true, a cursor plane is created in the VKMS device + * @overlay: If true, NUM_OVERLAY_PLANES will be created for the VKMS devi= ce + * @dev: Used to store the current VKMS device. Only set when the device i= s instantiated. + */ +struct vkms_config { + bool writeback; + bool cursor; + bool overlay; + struct vkms_device *dev; +}; + +/** + * vkms_config_create() - Create a new VKMS configuration + * + * Returns: + * The new vkms_config or an error. Call vkms_config_destroy() to free the + * returned configuration. + */ +struct vkms_config *vkms_config_create(void); + +/** + * vkms_config_destroy() - Free a VKMS configuration + * @config: vkms_config to free + */ +void vkms_config_destroy(struct vkms_config *config); + +/** + * vkms_config_register_debugfs() - Register a debugfs file to show the de= vice's + * configuration + * @vkms_device: Device to register + */ +void vkms_config_register_debugfs(struct vkms_device *vkms_device); + +#endif /* _VKMS_CONFIG_H_ */ diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_dr= v.c index 7c142bfc3bd9..b19f76f902b3 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.c +++ b/drivers/gpu/drm/vkms/vkms_drv.c @@ -27,11 +27,9 @@ #include #include =20 +#include "vkms_config.h" #include "vkms_drv.h" =20 -#include -#include - #define DRIVER_NAME "vkms" #define DRIVER_DESC "Virtual Kernel Mode Setting" #define DRIVER_MAJOR 1 @@ -81,23 +79,6 @@ static void vkms_atomic_commit_tail(struct drm_atomic_st= ate *old_state) drm_atomic_helper_cleanup_planes(dev, old_state); } =20 -static int vkms_config_show(struct seq_file *m, void *data) -{ - struct drm_debugfs_entry *entry =3D m->private; - struct drm_device *dev =3D entry->dev; - struct vkms_device *vkmsdev =3D drm_device_to_vkms_device(dev); - - seq_printf(m, "writeback=3D%d\n", vkmsdev->config->writeback); - seq_printf(m, "cursor=3D%d\n", vkmsdev->config->cursor); - seq_printf(m, "overlay=3D%d\n", vkmsdev->config->overlay); - - return 0; -} - -static const struct drm_debugfs_info vkms_config_debugfs_list[] =3D { - { "vkms_config", vkms_config_show, 0 }, -}; - static const struct drm_driver vkms_driver =3D { .driver_features =3D DRIVER_MODESET | DRIVER_ATOMIC | DRIVER_GEM, .fops =3D &vkms_driver_fops, @@ -208,8 +189,7 @@ static int vkms_create(struct vkms_config *config) if (ret) goto out_devres; =20 - drm_debugfs_add_files(&vkms_device->drm, vkms_config_debugfs_list, - ARRAY_SIZE(vkms_config_debugfs_list)); + vkms_config_register_debugfs(vkms_device); =20 ret =3D drm_dev_register(&vkms_device->drm, 0); if (ret) @@ -231,9 +211,9 @@ static int __init vkms_init(void) int ret; struct vkms_config *config; =20 - config =3D kmalloc(sizeof(*config), GFP_KERNEL); - if (!config) - return -ENOMEM; + config =3D vkms_config_create(); + if (IS_ERR(config)) + return PTR_ERR(config); =20 default_config =3D config; =20 @@ -243,7 +223,7 @@ static int __init vkms_init(void) =20 ret =3D vkms_create(config); if (ret) - kfree(config); + vkms_config_destroy(config); =20 return ret; } @@ -272,7 +252,7 @@ static void __exit vkms_exit(void) if (default_config->dev) vkms_destroy(default_config); =20 - kfree(default_config); + vkms_config_destroy(default_config); } =20 module_init(vkms_init); diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_dr= v.h index abbb652be2b5..af7081c940d6 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.h +++ b/drivers/gpu/drm/vkms/vkms_drv.h @@ -189,20 +189,7 @@ struct vkms_output { spinlock_t composer_lock; }; =20 -/** - * struct vkms_config - General configuration for VKMS driver - * - * @writeback: If true, a writeback buffer can be attached to the CRTC - * @cursor: If true, a cursor plane is created in the VKMS device - * @overlay: If true, NUM_OVERLAY_PLANES will be created for the VKMS devi= ce - * @dev: Used to store the current VKMS device. Only set when the device i= s instantiated. - */ -struct vkms_config { - bool writeback; - bool cursor; - bool overlay; - struct vkms_device *dev; -}; +struct vkms_config; =20 /** * struct vkms_device - Description of a VKMS device diff --git a/drivers/gpu/drm/vkms/vkms_output.c b/drivers/gpu/drm/vkms/vkms= _output.c index 4b5abe159add..068a7f87ecec 100644 --- a/drivers/gpu/drm/vkms/vkms_output.c +++ b/drivers/gpu/drm/vkms/vkms_output.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ =20 +#include "vkms_config.h" #include "vkms_connector.h" #include "vkms_drv.h" #include --=20 2.48.1 From nobody Mon Feb 9 13:37:02 2026 Received: from mail-wr1-f51.google.com (mail-wr1-f51.google.com [209.85.221.51]) (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 A03461B87CE for ; Wed, 29 Jan 2025 11:01:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738148473; cv=none; b=HNy6sSlE8tr2aua97BCmb6gChdMYocHjD0sMOBMpC/6/rAlWHU3nOVykWr1JpjgubHbd8CFgxmlPFdHLIjgpwZscgcW2C50DKOQ7+w9lo0F+uyNERKejuX4cvhHT45brtmRcbVA8bg7czlywOFxt9wU19jjWMVA6/G9W4b2D4mI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738148473; c=relaxed/simple; bh=HAk0pU6WHZBvScogqj5WoFQyT43pHDnPUqwdiCUpdXc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=SnwI7iz+iEntS1AeQobuGzvlJCvFN1m0Hmevv8QrxzBPh4omPu8MGxj9wcgbYNEvjaAl2rotnM3IvXkJfEEKbgp5GtsP6J8GP1yvBKuI5ENZqqjR8PzdlSh58ywPM036DvcclJ5kUwgFi3lB66uxuewG8gD1ZT57PxN9A3Vx1fQ= 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=RPQLOnUT; arc=none smtp.client-ip=209.85.221.51 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="RPQLOnUT" Received: by mail-wr1-f51.google.com with SMTP id ffacd0b85a97d-38a8b35e168so350193f8f.1 for ; Wed, 29 Jan 2025 03:01:11 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1738148470; x=1738753270; 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=FjL+ZAAo0YHDYt7gQTJ/b5ubGw71F7Pu1taWojvFhk4=; b=RPQLOnUTmAtDRJTgoqM0Qa3GoWjlm9aBSJCWduDxL3mDJFp8GxjClNPqoxi7QMNSXb Ba56W86wN1EMdjw/ZBYQ0ICAWdiQPL7UI9GO9j/xQbaGNaOgsewApwDCOtymBuBjngJr 7ZTuhA/5v/F+sTvfcZjTukKMhHR8tDAY2dlXdy0m/Ew0oSCZdRiuFztD32dE5/WLDGon QGg9zM7cnbWPsdeEIWVNdpyvCJJc/x2zulYi31tAsfrT+pez1TiN5UEcQY5F62gkDLsS XWJEdy4tBj6t+hdIoW/XtNby6omkr85Osoa1HZ+ezO0McDhFTh+FWMN8RaZC/mEWqA64 NbRw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1738148470; x=1738753270; 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=FjL+ZAAo0YHDYt7gQTJ/b5ubGw71F7Pu1taWojvFhk4=; b=GXDmfVwdYOdugyhTMRsZAvVd+ojxceyJWtS98XcFihVrqGMkSfOTUuQX8zsCkhQw+w D7xj8J6cq2l69J40gpDOtF39o9GgNIlc8lCV4W0i1FJFF1ful2pAFC/4Z0oOQRdBYaVS xQdOqBAwaqbtXUP62SDMjCY3CPBnsUS4VO/S2PQgt7lPeKhZHNCKjb0bnbYY1U3yENOV cQvRQoRABkzKiLF2DM6WM/iuP5J0L49vIthsHWWiTjrJLS/JRHSOsKEid7RnIIUcxxov XnRN29wRu0FfvcY0EcTWg+EY/I3ZorwS2i0rRrtiQ8zoeLIoGNZXdhmE395gbTexNsA+ f93g== X-Forwarded-Encrypted: i=1; AJvYcCUsZg/GVpfTksancmnmmwdnBWfGVAnNzbTjAdR5Qgv6hvjof0jrzeEzyUpINyW4K2vEuQ9UtfKuaZsKkBo=@vger.kernel.org X-Gm-Message-State: AOJu0YxfYF/Z50h9tvqU3moAsw/Puf5R6q2kxgTwalXQdmYqmqocXa02 RVhTSlKPYFTljAcUHXO1KIQ5BhE2+lGDUbMVupIJDGXWP4B5nD39 X-Gm-Gg: ASbGncuUJuXUnG95dtf9KRixP0WJHgbKrmwSqPbW5tUaQPbGqycxeSy54eWYwBbR2e5 pwrrYK7ey0pwmyMXIwKvS0Xkvj8jtJQVLrFtBV69V8UrGCstY6korxLOpKjvYyWLCNJtZEea76L Lanm3PXFtwo9bSG5BZ7a5w2atIogmfxoaEmQoyiBwDdLMV+nsGOWQYZK6zeEO3/JxRjeTu0aQyh 6kPjrHlwJlRYXKQ4VdZEJwb2E+Rr9fOdkWuVUNZXela8o0QGhnJ0+lETwKMKWlsR8mT/l0ez7HU lj+v6WMFJxhxTmg8 X-Google-Smtp-Source: AGHT+IGM65LZ6HAHnzroF2O3ycdsns+/7UUPzidfbU/yRI5s3eUChQJUUJRV3aYPtOLqqIewACxIzg== X-Received: by 2002:a05:6000:4011:b0:38b:ee9f:52d5 with SMTP id ffacd0b85a97d-38c50ff1713mr2361965f8f.16.1738148469669; Wed, 29 Jan 2025 03:01:09 -0800 (PST) Received: from fedora.. ([94.73.37.161]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-38c2a176434sm16947113f8f.13.2025.01.29.03.01.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Jan 2025 03:01:09 -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 04/13] drm/vkms: Move default_config creation to its own function Date: Wed, 29 Jan 2025 12:00:50 +0100 Message-ID: <20250129110059.12199-5-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 Extract the initialization of the default configuration to a function. Refactor, no functional changes. Signed-off-by: Louis Chauvet Signed-off-by: Jos=C3=A9 Exp=C3=B3sito Reviewed-by: Louis Chauvet --- drivers/gpu/drm/vkms/tests/vkms_config_test.c | 38 +++++++++++++++++++ drivers/gpu/drm/vkms/vkms_config.c | 17 +++++++++ drivers/gpu/drm/vkms/vkms_config.h | 14 +++++++ drivers/gpu/drm/vkms/vkms_drv.c | 6 +-- 4 files changed, 70 insertions(+), 5 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 a7060504f3dc..d8644a1e3e18 100644 --- a/drivers/gpu/drm/vkms/tests/vkms_config_test.c +++ b/drivers/gpu/drm/vkms/tests/vkms_config_test.c @@ -6,6 +6,12 @@ =20 MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING"); =20 +struct default_config_case { + bool enable_cursor; + bool enable_writeback; + bool enable_overlay; +}; + static void vkms_config_test_empty_config(struct kunit *test) { struct vkms_config *config; @@ -16,8 +22,40 @@ static void vkms_config_test_empty_config(struct kunit *= test) vkms_config_destroy(config); } =20 +static struct default_config_case default_config_cases[] =3D { + { false, false, false }, + { true, false, false }, + { true, true, false }, + { true, false, true }, + { false, true, false }, + { false, true, true }, + { false, false, true }, + { true, true, true }, +}; + +KUNIT_ARRAY_PARAM(default_config, default_config_cases, NULL); + +static void vkms_config_test_default_config(struct kunit *test) +{ + const struct default_config_case *params =3D test->param_value; + struct vkms_config *config; + + config =3D vkms_config_default_create(params->enable_cursor, + params->enable_writeback, + params->enable_overlay); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config); + + KUNIT_EXPECT_EQ(test, config->cursor, params->enable_cursor); + KUNIT_EXPECT_EQ(test, config->writeback, params->enable_writeback); + KUNIT_EXPECT_EQ(test, config->overlay, params->enable_overlay); + + 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, + default_config_gen_params), {} }; =20 diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms= _config.c index 152b2ecd6aef..30ce4b23553f 100644 --- a/drivers/gpu/drm/vkms/vkms_config.c +++ b/drivers/gpu/drm/vkms/vkms_config.c @@ -18,6 +18,23 @@ struct vkms_config *vkms_config_create(void) return config; } =20 +struct vkms_config *vkms_config_default_create(bool enable_cursor, + bool enable_writeback, + bool enable_overlay) +{ + struct vkms_config *config; + + config =3D vkms_config_create(); + if (IS_ERR(config)) + return config; + + config->cursor =3D enable_cursor; + config->writeback =3D enable_writeback; + config->overlay =3D enable_overlay; + + return config; +} + void vkms_config_destroy(struct vkms_config *config) { kfree(config); diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms= _config.h index ced10f56a812..d0868750826a 100644 --- a/drivers/gpu/drm/vkms/vkms_config.h +++ b/drivers/gpu/drm/vkms/vkms_config.h @@ -31,6 +31,20 @@ struct vkms_config { */ struct vkms_config *vkms_config_create(void); =20 +/** + * vkms_config_default_create() - Create the configuration for the default= device + * @enable_cursor: Create or not a cursor plane + * @enable_writeback: Create or not a writeback connector + * @enable_overlay: Create or not overlay planes + * + * Returns: + * The default vkms_config or an error. Call vkms_config_destroy() to free= the + * returned configuration. + */ +struct vkms_config *vkms_config_default_create(bool enable_cursor, + bool enable_writeback, + bool enable_overlay); + /** * vkms_config_destroy() - Free a VKMS configuration * @config: vkms_config to free diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_dr= v.c index b19f76f902b3..700cf43389b7 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.c +++ b/drivers/gpu/drm/vkms/vkms_drv.c @@ -211,16 +211,12 @@ static int __init vkms_init(void) int ret; struct vkms_config *config; =20 - config =3D vkms_config_create(); + config =3D vkms_config_default_create(enable_cursor, enable_writeback, en= able_overlay); if (IS_ERR(config)) return PTR_ERR(config); =20 default_config =3D config; =20 - config->cursor =3D enable_cursor; - config->writeback =3D enable_writeback; - config->overlay =3D enable_overlay; - ret =3D vkms_create(config); if (ret) vkms_config_destroy(config); --=20 2.48.1 From nobody Mon Feb 9 13:37:02 2026 Received: from mail-wr1-f42.google.com (mail-wr1-f42.google.com [209.85.221.42]) (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 1582C1BEF87 for ; Wed, 29 Jan 2025 11:01:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738148475; cv=none; b=gOAUeYShRl5FE77m6sKn9LcgLS6nImL71PeJznx+J18tgO8bUPa6XzjXaTe6os/au32w0OWCjjLcZqHZmBAfEMQ6vq067bTJzNT4E8ic063JjeNhD/R3ZDNq/CXWYfgchem/eBPmuHQNzrFvfLNayGSeKGuaGCOxO7gL/cMXrnQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738148475; c=relaxed/simple; bh=YIwpSyiUXb+Mxx78WqhM3Du/1Ol6vEVO/mtkWJkhoME=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=m6LN/LDtZOC5KltbcykOO/1X4Co/SEcy1iRpxRfD7z4qfNVANrIpbO2unyAHkIlpcm7rCzUE7oRC89cjDWVNyFPdSbaIVn4U4LgxO3Ygy6HWfghi9/lMK48M3CHInOR7YNH/QJ2GK2I5teJRUd+TkBIuEz+F5cpOLfhxXHgvUsU= 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=Gk3hCU36; arc=none smtp.client-ip=209.85.221.42 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="Gk3hCU36" Received: by mail-wr1-f42.google.com with SMTP id ffacd0b85a97d-38632b8ae71so5228827f8f.0 for ; Wed, 29 Jan 2025 03:01:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1738148471; x=1738753271; 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=3Jdlaybe4dLW4Pxw5Cu5C4SOJCAFhex6WH7zjUJEIng=; b=Gk3hCU36TWeDq4s3aenFO+Tf2VH3zfdT7xMSLmDT2e5F0JPuXLZKlvcECuSB0pAFFF 52praSMMv80yyqDZPc32HQlbldioUqfbnxK7urLEYzVm2NOEIxfCmzuEuL84Qcoxf+Z3 dBfQgZiQQWnFELGZKsJkKlR5bCk02lv4UOJfkDe/IBGlCbGcdOAmH2fdwj/HKo5efwqp TNVHAaFBRdhNbeDKW4Cc35qA6dUx4ZTWkwKCr1HRB4mfVjFfxg49HZ//ckCmU31WNDC7 uGt4BJPydWXTrH9XDqocM+l+qAr3COsq4x1OD9mMtvyFyVNDkIxbMjrgEvDqBmkWUzcz Nwlg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1738148471; x=1738753271; 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=3Jdlaybe4dLW4Pxw5Cu5C4SOJCAFhex6WH7zjUJEIng=; b=p8etwyrWWlQpC8gfxTeAknKBpxKuP4ISFiZlI6gDyUlFq+wzZLdEknG+3gfqYpAzxI JzJx35ACpeiq9apxupFdo/gmkvCQ+vFSr1Ma8cO5Jqsl4JK7bwsnoHFYk+tXsZLeMV9O dU4wyz4Y/ofxreL63DdK41AubQJ9cS01SMNe7Yq+8n/tHueIFYpnNHr5kfgj3Cc+c5+Q k6BUYgoXeTREgl91bLv6bWa6vJg1ABswU9dTekrKis9d4xwib+zZalkXQF4cWZc/BFQl HeCfxD8EApk54NiU01pT9PI3bhNriQZSkOsbPiSGHxOTW/UtCDZ4tul8KWd50i1INwDK Ruow== X-Forwarded-Encrypted: i=1; AJvYcCW9AB4R90HzFtsWnT1SOdo6YGyjmRGcTut4WzTOJopoxXYWbMqAxmntAvHKhyxaXffo8gqBCyzf+juAZ34=@vger.kernel.org X-Gm-Message-State: AOJu0Ywozpc6GVne4+fDneLwyKDk6mj6Tbu2hCxgpZvBkNCrrvraxaqH 0FeIBMgb4mdkaIp+v21yEzSAjjQ28OHyQSazhBKSELqw0IX7hvUf X-Gm-Gg: ASbGncsNfUnrizhgo/myaxwrLRCG+SB8cIeBWNJ1aIOaLyNOW/3M8WfGi1F6RnXP+E6 DUrOWladSVck9xQHdnY5z1KDJ2dWm4UB105EJUq+ZcwmZM3SX7p1cmiLgxlK8Pu8ZTPbSjMOf0W S89tnAHSzeRd6F3PeFOY1wRh2nn0GZtuUlL8joocexz3KeybUWr2WVBEDlD3Yb8muklqJHAdlUv ENfpcbs6zvPEfx8yOOvtswNVCkZKHdpRVRsuPXEc4pNJh9u4H1l7Xpp8v0XhotRL7MhQ86jqbv0 0a3OboLEaO4NT/67+nsVrO+fKRo= X-Google-Smtp-Source: AGHT+IF8ZlTcVpl9sITm6XddqK7H71VOTly30mhKNuiqqkEfAUFNz4gd4TU2PHgDJf555zpXIlbBUQ== X-Received: by 2002:a05:6000:194b:b0:38a:418e:1171 with SMTP id ffacd0b85a97d-38c52097117mr1431760f8f.37.1738148470894; Wed, 29 Jan 2025 03:01:10 -0800 (PST) Received: from fedora.. ([94.73.37.161]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-38c2a176434sm16947113f8f.13.2025.01.29.03.01.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Jan 2025 03:01:10 -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 05/13] drm/vkms: Set device name from vkms_config Date: Wed, 29 Jan 2025 12:00:51 +0100 Message-ID: <20250129110059.12199-6-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 In order to be able to create multiple devices, the device name needs to be unique. Allow to set it in the VKMS configuration. Signed-off-by: Jos=C3=A9 Exp=C3=B3sito Reviewed-by: Louis Chauvet --- drivers/gpu/drm/vkms/tests/vkms_config_test.c | 7 ++++++- drivers/gpu/drm/vkms/vkms_config.c | 14 ++++++++++++-- drivers/gpu/drm/vkms/vkms_config.h | 15 ++++++++++++++- drivers/gpu/drm/vkms/vkms_drv.c | 4 +++- drivers/gpu/drm/vkms/vkms_drv.h | 2 ++ 5 files changed, 37 insertions(+), 5 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 d8644a1e3e18..526800b1afb4 100644 --- a/drivers/gpu/drm/vkms/tests/vkms_config_test.c +++ b/drivers/gpu/drm/vkms/tests/vkms_config_test.c @@ -15,10 +15,15 @@ struct default_config_case { static void vkms_config_test_empty_config(struct kunit *test) { struct vkms_config *config; + const char *dev_name =3D "test"; =20 - config =3D vkms_config_create(); + config =3D vkms_config_create(dev_name); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config); =20 + /* The dev_name string and the config have different live times */ + dev_name =3D NULL; + KUNIT_EXPECT_STREQ(test, vkms_config_get_device_name(config), "test"); + vkms_config_destroy(config); } =20 diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms= _config.c index 30ce4b23553f..11b0e539920b 100644 --- a/drivers/gpu/drm/vkms/vkms_config.c +++ b/drivers/gpu/drm/vkms/vkms_config.c @@ -7,7 +7,7 @@ =20 #include "vkms_config.h" =20 -struct vkms_config *vkms_config_create(void) +struct vkms_config *vkms_config_create(const char *dev_name) { struct vkms_config *config; =20 @@ -15,6 +15,12 @@ struct vkms_config *vkms_config_create(void) if (!config) return ERR_PTR(-ENOMEM); =20 + config->dev_name =3D kstrdup_const(dev_name, GFP_KERNEL); + if (!config->dev_name) { + kfree(config); + return ERR_PTR(-ENOMEM); + } + return config; } =20 @@ -24,7 +30,7 @@ struct vkms_config *vkms_config_default_create(bool enabl= e_cursor, { struct vkms_config *config; =20 - config =3D vkms_config_create(); + config =3D vkms_config_create(DEFAULT_DEVICE_NAME); if (IS_ERR(config)) return config; =20 @@ -37,6 +43,7 @@ struct vkms_config *vkms_config_default_create(bool enabl= e_cursor, =20 void vkms_config_destroy(struct vkms_config *config) { + kfree_const(config->dev_name); kfree(config); } =20 @@ -45,7 +52,10 @@ static int vkms_config_show(struct seq_file *m, void *da= ta) struct drm_debugfs_entry *entry =3D m->private; struct drm_device *dev =3D entry->dev; struct vkms_device *vkmsdev =3D drm_device_to_vkms_device(dev); + const char *dev_name; =20 + dev_name =3D vkms_config_get_device_name((struct vkms_config *)vkmsdev->c= onfig); + seq_printf(m, "dev_name=3D%s\n", dev_name); seq_printf(m, "writeback=3D%d\n", vkmsdev->config->writeback); seq_printf(m, "cursor=3D%d\n", vkmsdev->config->cursor); seq_printf(m, "overlay=3D%d\n", vkmsdev->config->overlay); diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms= _config.h index d0868750826a..3e4f39cbe2e2 100644 --- a/drivers/gpu/drm/vkms/vkms_config.h +++ b/drivers/gpu/drm/vkms/vkms_config.h @@ -10,12 +10,14 @@ /** * struct vkms_config - General configuration for VKMS driver * + * @dev_name: Name of the device * @writeback: If true, a writeback buffer can be attached to the CRTC * @cursor: If true, a cursor plane is created in the VKMS device * @overlay: If true, NUM_OVERLAY_PLANES will be created for the VKMS devi= ce * @dev: Used to store the current VKMS device. Only set when the device i= s instantiated. */ struct vkms_config { + const char *dev_name; bool writeback; bool cursor; bool overlay; @@ -24,12 +26,13 @@ struct vkms_config { =20 /** * vkms_config_create() - Create a new VKMS configuration + * @dev_name: Name of the device * * Returns: * The new vkms_config or an error. Call vkms_config_destroy() to free the * returned configuration. */ -struct vkms_config *vkms_config_create(void); +struct vkms_config *vkms_config_create(const char *dev_name); =20 /** * vkms_config_default_create() - Create the configuration for the default= device @@ -51,6 +54,16 @@ struct vkms_config *vkms_config_default_create(bool enab= le_cursor, */ void vkms_config_destroy(struct vkms_config *config); =20 +/** + * vkms_config_get_device_name() - Return the name of the device + * @config: Configuration to get the device name from + */ +static inline const char * +vkms_config_get_device_name(struct vkms_config *config) +{ + return config->dev_name; +} + /** * vkms_config_register_debugfs() - Register a debugfs file to show the de= vice's * configuration diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_dr= v.c index 700cf43389b7..f23ee1a053e9 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.c +++ b/drivers/gpu/drm/vkms/vkms_drv.c @@ -151,8 +151,10 @@ static int vkms_create(struct vkms_config *config) int ret; struct platform_device *pdev; struct vkms_device *vkms_device; + const char *dev_name; =20 - pdev =3D platform_device_register_simple(DRIVER_NAME, -1, NULL, 0); + dev_name =3D vkms_config_get_device_name(config); + pdev =3D platform_device_register_simple(dev_name, -1, NULL, 0); if (IS_ERR(pdev)) return PTR_ERR(pdev); =20 diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_dr= v.h index af7081c940d6..a74a7fc3a056 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.h +++ b/drivers/gpu/drm/vkms/vkms_drv.h @@ -12,6 +12,8 @@ #include #include =20 +#define DEFAULT_DEVICE_NAME "vkms" + #define XRES_MIN 10 #define YRES_MIN 10 =20 --=20 2.48.1 From nobody Mon Feb 9 13:37:02 2026 Received: from mail-wr1-f50.google.com (mail-wr1-f50.google.com [209.85.221.50]) (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 D905E1D5CC6 for ; Wed, 29 Jan 2025 11:01:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738148475; cv=none; b=i8EosJ2rRT7RmFeUIacTbITBj8OT2Q4orKjID66euRPn0JRTUHrO5zt4XxzR6WtwBj6gTuTvauxtFa532HBa89hnkjmnVnil4s5jSxz+ChrypFRpfZ2RAd72XWmw4rTcZmSKjVQt1nq+L9iOYI/1HbBmiaHJwRE7CaQ48N4H/mM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738148475; c=relaxed/simple; bh=XFnNDeHiwz9uXy0C4eKOF7Z1i2GXBUm3LTRHYxbjzpE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=s+sDbm5ZtCmKzE9Ri6ed3bZkZRI5vM5WA74kdDzt9aTxGb1syJAUbMGPrkGjfi6ASs2uazMKeoM/HxZYh2uD39Yu7teA3FHDkhh0RUMehBdM6MXiIsEB1PnzQ8SXxf/1OZQoPT1XVrsscjC/TTZRe0boX/aP4OlghSuDVSYmBg0= 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=Jm0B0cZv; arc=none smtp.client-ip=209.85.221.50 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="Jm0B0cZv" Received: by mail-wr1-f50.google.com with SMTP id ffacd0b85a97d-38633b5dbcfso7486113f8f.2 for ; Wed, 29 Jan 2025 03:01:13 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1738148472; x=1738753272; 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=vcLgxm3SUTsLjkaczvOfL6Bm5o46S9pgFwtVrMuPL9A=; b=Jm0B0cZvs9eglHPhitHnoF5yPTKCk16KR9U8/O5HeIMlJKBrTLk5jkkS0k08sUEMP5 UfHbUmf06UZ8MsonRvlDnHNtUX247qjSdsEg2fzexxW8uvDH4Y93tQlW0dMyHGZt4qxn AX4kFPpMaEUWh0zS7aENcddxOxkmDpJtGRAc2m8cg2W6IWb/Tz4hVAYIBC0Iz0ZDwGqF fIaYAWe1UwbsyQ3QmLPFDvBSIa5Xhzt9zw+fM/d7Vi+ZQexVNjJvjAzMnLOtcLsOlLjA bZ2M/BFI7b2Sh1yvAzfJLG/qFOXjJh5KF0IpE7wjx/Y/eUpejHJcgwQJstd2cpTgD2Og 9nKw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1738148472; x=1738753272; 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=vcLgxm3SUTsLjkaczvOfL6Bm5o46S9pgFwtVrMuPL9A=; b=iV+GWDFC53ie5qc65Z0sbtJlXisB39YX61WOOQV+FETmdy0+f+/KiIJ4fmXp6xGLRD 6hqhLjV60Je0Lc0TJPwDuj80/U/pPJPEfsuSsNRVqCMrCHtXfUNxQGavBcpoF5hgYC+c UcnYHCljBlidJwLnx/jskmsg2JociRn+xn9sL4ufS81v34brTUcDDIT4LBq1zYwxCa/M H8HtH7iMhsRu313FmoTuqGtahPfz1dYf9T1pdX/0L2sRZC90KP46y1sobfLX10XmrobE TYCJ6N73dqsxpAwNHUQ1ytJc03oh/fuCqCdMk7iRhxTz1e/UfrlB0cdjsALB4g95QJhL ELLA== X-Forwarded-Encrypted: i=1; AJvYcCWgeMmCCQAH3rDoTUtsjfywkFOlcKJWQD6kRKrSKnFk81CI6MHABC8NAZG/74xGATPmFN7te/uCXJJyKYk=@vger.kernel.org X-Gm-Message-State: AOJu0YyVbJ91swoamneEGJ5HmzoNiz2RP8bbh+6bq1YTDAjI9oGTPMm4 0FZpV/nBFbjBnP5gfmvBL3e/t2pbv3SFKilX39VYseJY+T8twtZc X-Gm-Gg: ASbGncutIv/YEhr66nwWyWJRiW2he0bLZZzEjTeDRml6pa1wKHtSzKTQU4tArL3yhxV fypp/RVXFsFii8oHrMTjX/RqEOu/QbQAOzpHWiKJczR3zuCI2hMHFcy8Uru+88Ovsm4K+XruSW4 XBU/AelhQBcqFQe5rA77sPA73fVMyesM7xMPblR9w0ysEiANWLl05pRI+/7zH1AgnwPUxqCVrIO Z/enMVzwlxgdiFIRcng+uoH5n9Wb3CAywH1ZpE6+SyS7kUx44rfWXZ5mKKXcrTp/1zSOSSdlRtg 0E2BddxoD2up5K7T X-Google-Smtp-Source: AGHT+IGJkECaHDdVMqpyu56d/KRmlF5eI3OFpcFDGpoPoyaY9mw51GmEv0T/B7Cfz1VL8PGPqNskXA== X-Received: by 2002:a5d:6d88:0:b0:38a:418e:1179 with SMTP id ffacd0b85a97d-38c519380afmr2274027f8f.2.1738148472073; Wed, 29 Jan 2025 03:01:12 -0800 (PST) Received: from fedora.. ([94.73.37.161]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-38c2a176434sm16947113f8f.13.2025.01.29.03.01.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Jan 2025 03:01:11 -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 06/13] drm/vkms: Add a validation function for VKMS configuration Date: Wed, 29 Jan 2025 12:00:52 +0100 Message-ID: <20250129110059.12199-7-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 From: Louis Chauvet As the configuration will be used by userspace, add a validator to avoid creating a broken DRM device. For the moment, the function always returns true, but rules will be added in future patches. Signed-off-by: Jos=C3=A9 Exp=C3=B3sito Signed-off-by: Louis Chauvet Reviewed-by: Louis Chauvet --- drivers/gpu/drm/vkms/tests/vkms_config_test.c | 2 ++ drivers/gpu/drm/vkms/vkms_config.c | 5 +++++ drivers/gpu/drm/vkms/vkms_config.h | 10 ++++++++++ 3 files changed, 17 insertions(+) diff --git a/drivers/gpu/drm/vkms/tests/vkms_config_test.c b/drivers/gpu/dr= m/vkms/tests/vkms_config_test.c index 526800b1afb4..66c2c6cb4a0e 100644 --- a/drivers/gpu/drm/vkms/tests/vkms_config_test.c +++ b/drivers/gpu/drm/vkms/tests/vkms_config_test.c @@ -54,6 +54,8 @@ static void vkms_config_test_default_config(struct kunit = *test) KUNIT_EXPECT_EQ(test, config->writeback, params->enable_writeback); KUNIT_EXPECT_EQ(test, config->overlay, params->enable_overlay); =20 + KUNIT_EXPECT_TRUE(test, vkms_config_is_valid(config)); + vkms_config_destroy(config); } =20 diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms= _config.c index 11b0e539920b..67f71d29596e 100644 --- a/drivers/gpu/drm/vkms/vkms_config.c +++ b/drivers/gpu/drm/vkms/vkms_config.c @@ -47,6 +47,11 @@ void vkms_config_destroy(struct vkms_config *config) kfree(config); } =20 +bool vkms_config_is_valid(struct vkms_config *config) +{ + return true; +} + static int vkms_config_show(struct seq_file *m, void *data) { struct drm_debugfs_entry *entry =3D m->private; diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms= _config.h index 3e4f39cbe2e2..963f22b9b4bd 100644 --- a/drivers/gpu/drm/vkms/vkms_config.h +++ b/drivers/gpu/drm/vkms/vkms_config.h @@ -64,6 +64,16 @@ vkms_config_get_device_name(struct vkms_config *config) return config->dev_name; } =20 +/** + * vkms_config_is_valid() - Validate a configuration + * @config: Configuration to validate + * + * Returns: + * Whether the configuration is valid or not. + * For example, a configuration without primary planes is not valid. + */ +bool vkms_config_is_valid(struct vkms_config *config); + /** * vkms_config_register_debugfs() - Register a debugfs file to show the de= vice's * configuration --=20 2.48.1 From nobody Mon Feb 9 13:37:03 2026 Received: from mail-wr1-f52.google.com (mail-wr1-f52.google.com [209.85.221.52]) (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 A49CC1D90D7 for ; Wed, 29 Jan 2025 11:01:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738148478; cv=none; b=GxeiShcFe2/YsizUOhPWXC+z4ozg/D4noOfES2Fcxm0jUiY9/DVeXsdqlYsCuQt/qKf9I6WY3iWI/rvp9oyJ+qgSMWgBg+xHHAlTT+8ZAxuADGMbl4O2Algo3HXFCeXpvNBgpO2UmnTkLKy7HEG+nM7LLY4G2WHeJCxgBwsjtwc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738148478; c=relaxed/simple; bh=M94wVIQzNE/XQ6qK4XXtXGje4JwIlwziNCm0Q4og/yM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=PyhtzSKdc02Z0gwV5QAfInM5TRAWuOFig3odyD4Gdaf0u0gMyrK+47I1devdHfyOXwI48yVoUisfay8bXBHbDhPzsFiSnsm4OsrdxYNFeJr0l9ldP4KNa7eQD3k5H9tz6iTDsGU895lfLMSL7a3LBV/l9VQTnQ42tsM0keCE9rA= 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=S7JxHliG; arc=none smtp.client-ip=209.85.221.52 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="S7JxHliG" Received: by mail-wr1-f52.google.com with SMTP id ffacd0b85a97d-3862a921123so4543996f8f.3 for ; Wed, 29 Jan 2025 03:01:15 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1738148474; x=1738753274; 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=vojZaZ8F+NK/iPnjUpn4N9qYryOnpEU70w91WMVOaic=; b=S7JxHliGRRqDKTKsIei/axg+ownLhZxnU4XSKyu6J+uvtv+7mU+ewLqEHgN/MxHsOg CmKwFYJeLnditzxQu8cZeqTKzMeXyHFpPN2bKZc5sQQOIS5mfD/NMyRJ8UPa5QPFp46Y 01NFPxkjdfSraKdTt+gCjAEmr1eP/xFlOEe9Kp21+4gC9WQhyHsAbyXerlLrsgBc/o3l UHdUt12/h60Niya8PZm8B81VwlQyhYxxyYFZ7xx/7Mvc4azhEM+kXPkN7hcM4gJp5hms 2sSz+s4TgaoKYSMAoEb6yRlR7x4ZFkedn2HbAuHZGauheTLrs0TGvwAGH4NoC0mngk4V xQ/A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1738148474; x=1738753274; 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=vojZaZ8F+NK/iPnjUpn4N9qYryOnpEU70w91WMVOaic=; b=j1UlIa032YoPUARVlgLRmQbqX3qv+yhg/bkk+GYNe9riy7pLng0Zs1cmnlfIMCKtnW ELOz7LicIA4SXoRTe2uPhbMDtATS5YGXFKudOj6HiRwYc2hNbZnoQM2dqjPirH5Wo9aN bJXAUkOb1qsEsu2exl3lI9XjURcznqnLiN20rpvJ0h8yNqSbQEO3WGlx9ENIipfEt3ar ciObmSatBcPte3QhahZd8LBcqeFQ+R1jbm+YDRVsjFiqvY8nhzE40oWTW2z+nHWhhIjR qNqnEQrklD2c7FDSnmkvXTRpIgolFPJCKWlMPLPBQ9z3m6+At+ChCjKaPQ/Jm9TvRT+7 uuzw== X-Forwarded-Encrypted: i=1; AJvYcCUDijlllOk2ZOQ9Vrwe5urQfxa7ErHHGBkUys7XHnC28hkx3WGqCN8dGAq+Nnhcz+F4rduFQSBCQ4i5NAA=@vger.kernel.org X-Gm-Message-State: AOJu0YxePaMcaqvsBbbvOajqMR4XH+M4+s6Y3pXHIpNV81axPZxjIyOD ltjzdNUnLEaQ/LlxKlAcARngBX0PwrmwbL+CLwizIr7ItmlNu3uM X-Gm-Gg: ASbGncvEdz25C1pxfalyFUANbSg/rmlCS9dx73yZygUWrHH2nFfduSOW4z1Xe7a4C6U R/hj2cP+Otonny6lrEij1RFh+cN7bb+pH4qDIBggIMhKV+mK2LoAw4hia3a2yeHUzCu/iaEPKAU 9HMc2HhyAgq19aQtSwAqQb6LldmoRmow0YEiF8f6AVXWIyZ3RPTEc3qj5slEr4L3k4btJtBabDv jiq/RAUQmtf0QEPAUe/udAbsHc7TPdAQ0wxQstdrNLzwAEQX6hv1bqyS4PahM99CASVc2N7P+YU xcbRwxxzeL9FGtI6 X-Google-Smtp-Source: AGHT+IGlv8nmLgUmiKojqFWxzvaUL7Lfp9PLXTfmvbPvfCDgXUEhyDos5aI69wAbNCN9hEyXOrofYw== X-Received: by 2002:a5d:6c66:0:b0:38b:d7d2:12f6 with SMTP id ffacd0b85a97d-38c51932163mr2081326f8f.2.1738148473606; Wed, 29 Jan 2025 03:01:13 -0800 (PST) Received: from fedora.. ([94.73.37.161]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-38c2a176434sm16947113f8f.13.2025.01.29.03.01.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Jan 2025 03:01:12 -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 07/13] drm/vkms: Allow to configure multiple planes Date: Wed, 29 Jan 2025 12:00:53 +0100 Message-ID: <20250129110059.12199-8-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 planes to vkms_config and create as many planes as configured during output initialization. For backwards compatibility, add one primary plane and, if configured, one cursor plane and NUM_OVERLAY_PLANES planes to the default configuration. Signed-off-by: Louis Chauvet Signed-off-by: Jos=C3=A9 Exp=C3=B3sito --- drivers/gpu/drm/vkms/tests/vkms_config_test.c | 133 +++++++++++++++- drivers/gpu/drm/vkms/vkms_config.c | 149 +++++++++++++++++- drivers/gpu/drm/vkms/vkms_config.h | 78 ++++++++- drivers/gpu/drm/vkms/vkms_output.c | 67 ++++---- 4 files changed, 386 insertions(+), 41 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 66c2c6cb4a0e..7d9cb3956741 100644 --- a/drivers/gpu/drm/vkms/tests/vkms_config_test.c +++ b/drivers/gpu/drm/vkms/tests/vkms_config_test.c @@ -24,6 +24,10 @@ static void vkms_config_test_empty_config(struct kunit *= test) dev_name =3D NULL; KUNIT_EXPECT_STREQ(test, vkms_config_get_device_name(config), "test"); =20 + KUNIT_EXPECT_TRUE(test, list_empty(&config->planes)); + + KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config)); + vkms_config_destroy(config); } =20 @@ -44,16 +48,138 @@ static void vkms_config_test_default_config(struct kun= it *test) { const struct default_config_case *params =3D test->param_value; struct vkms_config *config; + struct vkms_config_plane *plane_cfg; + int n_primaries =3D 0; + int n_cursors =3D 0; + int n_overlays =3D 0; =20 config =3D vkms_config_default_create(params->enable_cursor, params->enable_writeback, params->enable_overlay); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config); =20 - KUNIT_EXPECT_EQ(test, config->cursor, params->enable_cursor); KUNIT_EXPECT_EQ(test, config->writeback, params->enable_writeback); - KUNIT_EXPECT_EQ(test, config->overlay, params->enable_overlay); =20 + /* Planes */ + list_for_each_entry(plane_cfg, &config->planes, link) { + switch (vkms_config_plane_get_type(plane_cfg)) { + case DRM_PLANE_TYPE_PRIMARY: + n_primaries++; + break; + case DRM_PLANE_TYPE_CURSOR: + n_cursors++; + break; + case DRM_PLANE_TYPE_OVERLAY: + n_overlays++; + break; + default: + KUNIT_FAIL_AND_ABORT(test, "Unknown plane type"); + } + } + KUNIT_EXPECT_EQ(test, n_primaries, 1); + KUNIT_EXPECT_EQ(test, n_cursors, params->enable_cursor ? 1 : 0); + KUNIT_EXPECT_EQ(test, n_overlays, params->enable_overlay ? 8 : 0); + + KUNIT_EXPECT_TRUE(test, vkms_config_is_valid(config)); + + vkms_config_destroy(config); +} + +static void vkms_config_test_get_planes(struct kunit *test) +{ + struct vkms_config *config; + struct vkms_config_plane *plane_cfg1, *plane_cfg2; + struct vkms_config_plane **array; + size_t length; + + config =3D vkms_config_create("test"); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config); + + array =3D vkms_config_get_planes(config, &length); + KUNIT_ASSERT_EQ(test, length, 0); + KUNIT_ASSERT_NULL(test, array); + + plane_cfg1 =3D vkms_config_add_plane(config); + array =3D vkms_config_get_planes(config, &length); + KUNIT_ASSERT_EQ(test, length, 1); + KUNIT_ASSERT_PTR_EQ(test, array[0], plane_cfg1); + kfree(array); + + plane_cfg2 =3D vkms_config_add_plane(config); + array =3D vkms_config_get_planes(config, &length); + KUNIT_ASSERT_EQ(test, length, 2); + KUNIT_ASSERT_PTR_EQ(test, array[0], plane_cfg1); + KUNIT_ASSERT_PTR_EQ(test, array[1], plane_cfg2); + kfree(array); + + vkms_config_destroy_plane(plane_cfg1); + array =3D vkms_config_get_planes(config, &length); + KUNIT_ASSERT_EQ(test, length, 1); + KUNIT_ASSERT_PTR_EQ(test, array[0], plane_cfg2); + kfree(array); + + vkms_config_destroy(config); +} + +static void vkms_config_test_valid_plane_number(struct kunit *test) +{ + struct vkms_config *config; + struct vkms_config_plane *plane_cfg; + int n; + + config =3D vkms_config_default_create(false, false, false); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config); + + /* Invalid: No planes */ + plane_cfg =3D list_first_entry(&config->planes, typeof(*plane_cfg), link); + vkms_config_destroy_plane(plane_cfg); + KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config)); + + /* Invalid: Too many planes */ + for (n =3D 0; n <=3D 32; n++) + vkms_config_add_plane(config); + + KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config)); + + vkms_config_destroy(config); +} + +static void vkms_config_test_valid_plane_type(struct kunit *test) +{ + struct vkms_config *config; + struct vkms_config_plane *plane_cfg; + + config =3D vkms_config_default_create(false, false, false); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config); + + plane_cfg =3D list_first_entry(&config->planes, typeof(*plane_cfg), link); + vkms_config_destroy_plane(plane_cfg); + + /* Invalid: No primary plane */ + plane_cfg =3D vkms_config_add_plane(config); + vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_OVERLAY); + KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config)); + + /* Invalid: Multiple primary planes */ + plane_cfg =3D vkms_config_add_plane(config); + vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_PRIMARY); + plane_cfg =3D vkms_config_add_plane(config); + vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_PRIMARY); + KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config)); + + /* Valid: One primary plane */ + vkms_config_destroy_plane(plane_cfg); + KUNIT_EXPECT_TRUE(test, vkms_config_is_valid(config)); + + /* Invalid: Multiple cursor planes */ + plane_cfg =3D vkms_config_add_plane(config); + vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_CURSOR); + plane_cfg =3D vkms_config_add_plane(config); + vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_CURSOR); + KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config)); + + /* Valid: One primary and one cursor plane */ + vkms_config_destroy_plane(plane_cfg); KUNIT_EXPECT_TRUE(test, vkms_config_is_valid(config)); =20 vkms_config_destroy(config); @@ -63,6 +189,9 @@ static struct kunit_case vkms_config_test_cases[] =3D { KUNIT_CASE(vkms_config_test_empty_config), KUNIT_CASE_PARAM(vkms_config_test_default_config, default_config_gen_params), + KUNIT_CASE(vkms_config_test_get_planes), + KUNIT_CASE(vkms_config_test_valid_plane_number), + KUNIT_CASE(vkms_config_test_valid_plane_type), {} }; =20 diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms= _config.c index 67f71d29596e..a5a77612645f 100644 --- a/drivers/gpu/drm/vkms/vkms_config.c +++ b/drivers/gpu/drm/vkms/vkms_config.c @@ -21,6 +21,8 @@ struct vkms_config *vkms_config_create(const char *dev_na= me) return ERR_PTR(-ENOMEM); } =20 + INIT_LIST_HEAD(&config->planes); + return config; } =20 @@ -29,26 +31,139 @@ struct vkms_config *vkms_config_default_create(bool en= able_cursor, bool enable_overlay) { struct vkms_config *config; + struct vkms_config_plane *plane_cfg; + int n; =20 config =3D vkms_config_create(DEFAULT_DEVICE_NAME); if (IS_ERR(config)) return config; =20 - config->cursor =3D enable_cursor; config->writeback =3D enable_writeback; - config->overlay =3D enable_overlay; + + plane_cfg =3D vkms_config_add_plane(config); + if (IS_ERR(plane_cfg)) + goto err_alloc; + vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_PRIMARY); + + if (enable_overlay) { + for (n =3D 0; n < NUM_OVERLAY_PLANES; n++) { + plane_cfg =3D vkms_config_add_plane(config); + if (IS_ERR(plane_cfg)) + goto err_alloc; + vkms_config_plane_set_type(plane_cfg, + DRM_PLANE_TYPE_OVERLAY); + } + } + + if (enable_cursor) { + plane_cfg =3D vkms_config_add_plane(config); + if (IS_ERR(plane_cfg)) + goto err_alloc; + vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_CURSOR); + } =20 return config; + +err_alloc: + vkms_config_destroy(config); + return ERR_PTR(-ENOMEM); } =20 void vkms_config_destroy(struct vkms_config *config) { + struct vkms_config_plane *plane_cfg, *plane_tmp; + + list_for_each_entry_safe(plane_cfg, plane_tmp, &config->planes, link) + vkms_config_destroy_plane(plane_cfg); + kfree_const(config->dev_name); kfree(config); } =20 +struct vkms_config_plane **vkms_config_get_planes(const struct vkms_config= *config, + size_t *out_length) +{ + struct vkms_config_plane **array; + struct vkms_config_plane *plane_cfg; + size_t length; + int n =3D 0; + + length =3D list_count_nodes((struct list_head *)&config->planes); + 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); + + list_for_each_entry(plane_cfg, &config->planes, link) { + array[n] =3D plane_cfg; + n++; + } + + *out_length =3D length; + return array; +} + +static bool valid_plane_number(struct vkms_config *config) +{ + size_t n_planes; + + n_planes =3D list_count_nodes(&config->planes); + if (n_planes <=3D 0 || n_planes >=3D 32) { + pr_err("The number of planes must be between 1 and 31\n"); + return false; + } + + return true; +} + +static bool valid_plane_type(struct vkms_config *config) +{ + struct vkms_config_plane *plane_cfg; + bool has_primary_plane =3D false; + bool has_cursor_plane =3D false; + + list_for_each_entry(plane_cfg, &config->planes, link) { + enum drm_plane_type type; + + type =3D vkms_config_plane_get_type(plane_cfg); + + if (type =3D=3D DRM_PLANE_TYPE_PRIMARY) { + if (has_primary_plane) { + pr_err("Multiple primary planes\n"); + return false; + } + + has_primary_plane =3D true; + } else if (type =3D=3D DRM_PLANE_TYPE_CURSOR) { + if (has_cursor_plane) { + pr_err("Multiple cursor planes\n"); + return false; + } + + has_cursor_plane =3D true; + } + } + + if (!has_primary_plane) { + pr_err("Primary plane not found\n"); + return false; + } + + return true; +} + bool vkms_config_is_valid(struct vkms_config *config) { + if (!valid_plane_number(config)) + return false; + + if (!valid_plane_type(config)) + return false; + return true; } =20 @@ -58,12 +173,17 @@ static int vkms_config_show(struct seq_file *m, void *= data) struct drm_device *dev =3D entry->dev; struct vkms_device *vkmsdev =3D drm_device_to_vkms_device(dev); const char *dev_name; + struct vkms_config_plane *plane_cfg; =20 dev_name =3D vkms_config_get_device_name((struct vkms_config *)vkmsdev->c= onfig); seq_printf(m, "dev_name=3D%s\n", dev_name); seq_printf(m, "writeback=3D%d\n", vkmsdev->config->writeback); - seq_printf(m, "cursor=3D%d\n", vkmsdev->config->cursor); - seq_printf(m, "overlay=3D%d\n", vkmsdev->config->overlay); + + list_for_each_entry(plane_cfg, &vkmsdev->config->planes, link) { + seq_puts(m, "plane:\n"); + seq_printf(m, "\ttype=3D%d\n", + vkms_config_plane_get_type(plane_cfg)); + } =20 return 0; } @@ -77,3 +197,24 @@ void vkms_config_register_debugfs(struct vkms_device *v= kms_device) drm_debugfs_add_files(&vkms_device->drm, vkms_config_debugfs_list, ARRAY_SIZE(vkms_config_debugfs_list)); } + +struct vkms_config_plane *vkms_config_add_plane(struct vkms_config *config) +{ + struct vkms_config_plane *plane_cfg; + + plane_cfg =3D kzalloc(sizeof(*plane_cfg), GFP_KERNEL); + if (!plane_cfg) + return ERR_PTR(-ENOMEM); + + vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_OVERLAY); + + list_add_tail(&plane_cfg->link, &config->planes); + + return plane_cfg; +} + +void vkms_config_destroy_plane(struct vkms_config_plane *plane_cfg) +{ + list_del(&plane_cfg->link); + kfree(plane_cfg); +} diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms= _config.h index 963f22b9b4bd..d9aeba1762d1 100644 --- a/drivers/gpu/drm/vkms/vkms_config.h +++ b/drivers/gpu/drm/vkms/vkms_config.h @@ -3,6 +3,7 @@ #ifndef _VKMS_CONFIG_H_ #define _VKMS_CONFIG_H_ =20 +#include #include =20 #include "vkms_drv.h" @@ -12,18 +13,36 @@ * * @dev_name: Name of the device * @writeback: If true, a writeback buffer can be attached to the CRTC - * @cursor: If true, a cursor plane is created in the VKMS device - * @overlay: If true, NUM_OVERLAY_PLANES will be created for the VKMS devi= ce + * @planes: List of planes configured for the device * @dev: Used to store the current VKMS device. Only set when the device i= s instantiated. */ struct vkms_config { const char *dev_name; bool writeback; - bool cursor; - bool overlay; + struct list_head planes; struct vkms_device *dev; }; =20 +/** + * struct vkms_config_plane + * + * @link: Link to the others planes in vkms_config + * @type: Type of the plane. The creator of configuration needs to ensures= that + * at least one primary plane is present. + * @plane: Internal usage. This pointer should never be considered as vali= d. + * It can be used to store a temporary reference to a VKMS plane d= uring + * device creation. This pointer is not managed by the configurati= on and + * must be managed by other means. + */ +struct vkms_config_plane { + struct list_head link; + + enum drm_plane_type type; + + /* Internal usage */ + struct vkms_plane *plane; +}; + /** * vkms_config_create() - Create a new VKMS configuration * @dev_name: Name of the device @@ -64,6 +83,19 @@ vkms_config_get_device_name(struct vkms_config *config) return config->dev_name; } =20 +/** + * vkms_config_planes() - Return the array of planes of the device + * @config: Configuration to get the planes 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_plane **vkms_config_get_planes(const struct vkms_config= *config, + size_t *out_length); + /** * vkms_config_is_valid() - Validate a configuration * @config: Configuration to validate @@ -81,4 +113,42 @@ bool vkms_config_is_valid(struct vkms_config *config); */ void vkms_config_register_debugfs(struct vkms_device *vkms_device); =20 +/** + * vkms_config_add_plane() - Add a new plane configuration + * @config: Configuration to add the plane to + * + * Returns: + * The new plane configuration or an error. Call vkms_config_destroy_plane= () to + * free the returned plane configuration. + */ +struct vkms_config_plane *vkms_config_add_plane(struct vkms_config *config= ); + +/** + * vkms_config_destroy_plane() - Remove and free a plane configuration + * @plane_cfg: Plane configuration to destroy + */ +void vkms_config_destroy_plane(struct vkms_config_plane *plane_cfg); + +/** + * vkms_config_plane_type() - Return the plane type + * @plane_cfg: Plane to get the type from + */ +static inline enum drm_plane_type +vkms_config_plane_get_type(struct vkms_config_plane *plane_cfg) +{ + return plane_cfg->type; +} + +/** + * vkms_config_plane_set_type() - Set the plane type + * @plane_cfg: Plane to set the type to + * @type: New plane type + */ +static inline void +vkms_config_plane_set_type(struct vkms_config_plane *plane_cfg, + enum drm_plane_type type) +{ + plane_cfg->type =3D type; +} + #endif /* _VKMS_CONFIG_H_ */ diff --git a/drivers/gpu/drm/vkms/vkms_output.c b/drivers/gpu/drm/vkms/vkms= _output.c index 068a7f87ecec..b2ae269e5827 100644 --- a/drivers/gpu/drm/vkms/vkms_output.c +++ b/drivers/gpu/drm/vkms/vkms_output.c @@ -11,61 +11,63 @@ int vkms_output_init(struct vkms_device *vkmsdev) struct vkms_connector *connector; struct drm_encoder *encoder; struct vkms_output *output; - struct vkms_plane *primary, *overlay, *cursor =3D NULL; - int ret; + struct vkms_plane *primary =3D NULL, *cursor =3D NULL; + struct vkms_config_plane **plane_cfgs =3D NULL; + size_t n_planes; + int ret =3D 0; int writeback; unsigned int n; =20 - /* - * Initialize used plane. One primary plane is required to perform the co= mposition. - * - * The overlay and cursor planes are not mandatory, but can be used to pe= rform complex - * composition. - */ - primary =3D vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_PRIMARY); - if (IS_ERR(primary)) - return PTR_ERR(primary); + plane_cfgs =3D vkms_config_get_planes(vkmsdev->config, &n_planes); + if (IS_ERR(plane_cfgs)) + return PTR_ERR(plane_cfgs); =20 - if (vkmsdev->config->cursor) { - cursor =3D vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_CURSOR); - if (IS_ERR(cursor)) - return PTR_ERR(cursor); + for (n =3D 0; n < n_planes; n++) { + struct vkms_config_plane *plane_cfg; + enum drm_plane_type type; + + plane_cfg =3D plane_cfgs[n]; + type =3D vkms_config_plane_get_type(plane_cfg); + + plane_cfg->plane =3D vkms_plane_init(vkmsdev, type); + if (IS_ERR(plane_cfg->plane)) { + DRM_DEV_ERROR(dev->dev, "Failed to init vkms plane\n"); + ret =3D PTR_ERR(plane_cfg->plane); + goto err_free; + } + + if (type =3D=3D DRM_PLANE_TYPE_PRIMARY) + primary =3D plane_cfg->plane; + else if (type =3D=3D DRM_PLANE_TYPE_CURSOR) + cursor =3D plane_cfg->plane; } =20 output =3D vkms_crtc_init(dev, &primary->base, cursor ? &cursor->base : NULL); if (IS_ERR(output)) { DRM_ERROR("Failed to allocate CRTC\n"); - return PTR_ERR(output); - } - - if (vkmsdev->config->overlay) { - for (n =3D 0; n < NUM_OVERLAY_PLANES; n++) { - overlay =3D vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_OVERLAY); - if (IS_ERR(overlay)) { - DRM_DEV_ERROR(dev->dev, "Failed to init vkms plane\n"); - return PTR_ERR(overlay); - } - overlay->base.possible_crtcs =3D drm_crtc_mask(&output->crtc); - } + ret =3D PTR_ERR(output); + goto err_free; } =20 connector =3D vkms_connector_init(vkmsdev); if (IS_ERR(connector)) { DRM_ERROR("Failed to init connector\n"); - return PTR_ERR(connector); + ret =3D PTR_ERR(connector); + goto err_free; } =20 encoder =3D drmm_kzalloc(dev, sizeof(*encoder), GFP_KERNEL); if (!encoder) { DRM_ERROR("Failed to allocate encoder\n"); - return -ENOMEM; + ret =3D -ENOMEM; + goto err_free; } ret =3D drmm_encoder_init(dev, encoder, NULL, DRM_MODE_ENCODER_VIRTUAL, NULL); if (ret) { DRM_ERROR("Failed to init encoder\n"); - return ret; + goto err_free; } encoder->possible_crtcs =3D drm_crtc_mask(&output->crtc); =20 @@ -73,7 +75,7 @@ int vkms_output_init(struct vkms_device *vkmsdev) ret =3D drm_connector_attach_encoder(&connector->base, encoder); if (ret) { DRM_ERROR("Failed to attach connector to encoder\n"); - return ret; + goto err_free; } =20 /* Initialize the writeback component */ @@ -85,5 +87,8 @@ int vkms_output_init(struct vkms_device *vkmsdev) =20 drm_mode_config_reset(dev); =20 +err_free: + kfree(plane_cfgs); + return ret; } --=20 2.48.1 From nobody Mon Feb 9 13:37:03 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 246001DC994 for ; Wed, 29 Jan 2025 11:01:16 +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=1738148479; cv=none; b=gCAu0vJwyqWwH1IByRez6D0HQYGSbvFPO8PMtLSgiZF8ouhFl9i9o3P77+QvVsCF8EPhr8L3Z1TXLHMzDdJ7flVEbI6nKSZUwMg4Y/10xukVv5o1LhvvshJU4unC/lppmmYrfxDH35f2+8p8tzPnvQU/ksul5IU0cZItuYVthO4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738148479; c=relaxed/simple; bh=nRWUanf2aYIWh9Biii177WqEpjgXWVgmEWktBBM2LAw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=j3Su5mnJSKA2BSCyp1BFCCYFCDbrFNeOvfdCpjZ2bxtLlvuRxc33B9T5fYaHk/YK7J/kEsVW/Ud8HYKNIgQFWKgzTOQmPKUZDFcBnRAGryeebvVkwOGM3wOb2Izih/Np2866MXCVzj8BKDHEpo70I56UGPIwDHO6rjnM1POQETQ= 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=DiLe6HRB; 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="DiLe6HRB" Received: by mail-wm1-f46.google.com with SMTP id 5b1f17b1804b1-438a39e659cso44442985e9.2 for ; Wed, 29 Jan 2025 03:01:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1738148475; x=1738753275; 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=PWyhKU7rNdH8bD+VJvosWh8sByoTXBt/ga10H7y8Dnk=; b=DiLe6HRBddv7Op3oGADqcvbIXKfKywiI//6V6bu38hnUWBKeMBQujRVzzDPffB49Ls 0ghNbKVSJx3nBDY290RToc2wW405mLMPLhuL312zmlAzIiR08qusUz2XNr3rGh51tzEA C3hZ2uwVfbkXel9Yv4osJk0iU84M5GrSGf7AuZ6Gw+sPPSYGVglfFWJBMS90TLHulQGS BkPn1Ut6zKTFAEXBOKyX98ytar+khQ9nn2yg8541k2EuBhSi2zWkjXn9BFXyGdiwNl5T sasZa52P2XgfShC2WmEI/9QXtOc7T7CE+EmL944lEG0OebS4dsCE0z3BG4C5x40QEERL kF/Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1738148475; x=1738753275; 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=PWyhKU7rNdH8bD+VJvosWh8sByoTXBt/ga10H7y8Dnk=; b=vAKzeNV2QSTdzXSDlFp6j5alXqcwwFrrcklByUQ/BXhphgfCg4PhbE65GAnZ5HkYln baUtLRca80jl0buaPYrouTq+VuY7vqVOjRQvzdvYK5Smk4dgx2PTI523VBSDvfrhLF2N ux0pAZpttQOGhO3zkBy9s9Frnfu/Fl+bik4kTGQZXuHA8jy1ICn6ZpiepBTx5YqBw1AU lxzQ2qzFrraxpGKU17zOB1ESl2k1IH8txR8/8gNAGrHopBx08JuXYBLrczz4PPtliWVS lrzQhKOoBYuykLQuYCqJCU21dt+oHScnyQHnwFX4uHDCJyUJi7yAgnhR79IGPkqCThuh 2SzQ== X-Forwarded-Encrypted: i=1; AJvYcCXDYEl+J0qqPqp6sOSeZNLZ0V+PU/haRtRmfkfx9FIzqLJ9xBnPcKN+QdKpn+VbzYApgKJyDLA7Nfr+aHw=@vger.kernel.org X-Gm-Message-State: AOJu0YzbWGnM3b4E7Gl3o4sjatMjurZ/C7qnQAd5zrDrJajAk07vbSnW j/WZZ6dxTwfgIKMdjKjdp+IYxiSZCzzwIqkKZ7mkiiNEqZssQpEY X-Gm-Gg: ASbGncuQ5JUYrqFQsSbhfzts7mRRLVXOK474uBHu71fX2EnM19o5VvSZybmNQYG9IRz dWLJlYwOpi6+o2e3gK7tdcPBSBfjyjt+WCSfn/H91YaOEUSQgOroEYDtvlDhHh4HGGrVCdJX8ni LAtnxegMGv1U7KsIiqwD+Vgba+rxLmNwympgwgv//8IJkdrhM7YIij+6ZiJymGw+X+elxEGJiVR Z8ITjoSJH7goVFnqkC05yI9p2YMlBstixOwc9WexGl7fJUzuqTlC3MHVw6Qm6+tgFLlRtulBk2G MMH9DEmyU5w4CcL5 X-Google-Smtp-Source: AGHT+IGxI/8h+i7c/jW6fIxV1OZm8Cs90w6P/3JNhZdaD1QTZvYbrc/QvBvLcOlI+/Ue+T0wtoOzjA== X-Received: by 2002:a05:600c:458a:b0:436:ed50:4f8a with SMTP id 5b1f17b1804b1-438dc3c333cmr23449305e9.10.1738148474804; Wed, 29 Jan 2025 03:01:14 -0800 (PST) Received: from fedora.. ([94.73.37.161]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-38c2a176434sm16947113f8f.13.2025.01.29.03.01.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Jan 2025 03:01:14 -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 08/13] drm/vkms: Allow to configure multiple CRTCs Date: Wed, 29 Jan 2025 12:00:54 +0100 Message-ID: <20250129110059.12199-9-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 CRTCs to vkms_config and helper functions to add and remove as many CRTCs as wanted. For backwards compatibility, add one CRTC to the default configuration. A future patch will allow to attach planes and CRTCs, but for the moment there are no changes in the way the output is configured. Signed-off-by: Louis Chauvet Signed-off-by: Jos=C3=A9 Exp=C3=B3sito --- drivers/gpu/drm/vkms/tests/vkms_config_test.c | 72 +++++++++++++++- drivers/gpu/drm/vkms/vkms_config.c | 86 ++++++++++++++++++- drivers/gpu/drm/vkms/vkms_config.h | 83 ++++++++++++++++++ drivers/gpu/drm/vkms/vkms_drv.c | 3 +- 4 files changed, 238 insertions(+), 6 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 7d9cb3956741..b5907b060a5c 100644 --- a/drivers/gpu/drm/vkms/tests/vkms_config_test.c +++ b/drivers/gpu/drm/vkms/tests/vkms_config_test.c @@ -25,6 +25,7 @@ static void vkms_config_test_empty_config(struct kunit *t= est) KUNIT_EXPECT_STREQ(test, vkms_config_get_device_name(config), "test"); =20 KUNIT_EXPECT_TRUE(test, list_empty(&config->planes)); + KUNIT_EXPECT_TRUE(test, list_empty(&config->crtcs)); =20 KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config)); =20 @@ -49,6 +50,7 @@ static void vkms_config_test_default_config(struct kunit = *test) const struct default_config_case *params =3D test->param_value; struct vkms_config *config; struct vkms_config_plane *plane_cfg; + struct vkms_config_crtc *crtc_cfg; int n_primaries =3D 0; int n_cursors =3D 0; int n_overlays =3D 0; @@ -58,8 +60,6 @@ static void vkms_config_test_default_config(struct kunit = *test) params->enable_overlay); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config); =20 - KUNIT_EXPECT_EQ(test, config->writeback, params->enable_writeback); - /* Planes */ list_for_each_entry(plane_cfg, &config->planes, link) { switch (vkms_config_plane_get_type(plane_cfg)) { @@ -80,6 +80,13 @@ static void vkms_config_test_default_config(struct kunit= *test) KUNIT_EXPECT_EQ(test, n_cursors, params->enable_cursor ? 1 : 0); KUNIT_EXPECT_EQ(test, n_overlays, params->enable_overlay ? 8 : 0); =20 + /* CRTCs */ + crtc_cfg =3D list_first_entry(&config->crtcs, typeof(*crtc_cfg), link); + + KUNIT_EXPECT_EQ(test, list_count_nodes(&config->crtcs), 1); + KUNIT_EXPECT_EQ(test, vkms_config_crtc_get_writeback(crtc_cfg), + params->enable_writeback); + KUNIT_EXPECT_TRUE(test, vkms_config_is_valid(config)); =20 vkms_config_destroy(config); @@ -121,6 +128,42 @@ static void vkms_config_test_get_planes(struct kunit *= test) vkms_config_destroy(config); } =20 +static void vkms_config_test_get_crtcs(struct kunit *test) +{ + struct vkms_config *config; + struct vkms_config_crtc *crtc_cfg1, *crtc_cfg2; + struct vkms_config_crtc **array; + size_t length; + + config =3D vkms_config_create("test"); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config); + + array =3D vkms_config_get_crtcs(config, &length); + KUNIT_ASSERT_EQ(test, length, 0); + KUNIT_ASSERT_NULL(test, array); + + crtc_cfg1 =3D vkms_config_add_crtc(config); + array =3D vkms_config_get_crtcs(config, &length); + KUNIT_ASSERT_EQ(test, length, 1); + KUNIT_ASSERT_PTR_EQ(test, array[0], crtc_cfg1); + kfree(array); + + crtc_cfg2 =3D vkms_config_add_crtc(config); + array =3D vkms_config_get_crtcs(config, &length); + KUNIT_ASSERT_EQ(test, length, 2); + KUNIT_ASSERT_PTR_EQ(test, array[0], crtc_cfg1); + KUNIT_ASSERT_PTR_EQ(test, array[1], crtc_cfg2); + kfree(array); + + vkms_config_destroy_crtc(config, crtc_cfg2); + array =3D vkms_config_get_crtcs(config, &length); + KUNIT_ASSERT_EQ(test, length, 1); + KUNIT_ASSERT_PTR_EQ(test, array[0], crtc_cfg1); + kfree(array); + + vkms_config_destroy(config); +} + static void vkms_config_test_valid_plane_number(struct kunit *test) { struct vkms_config *config; @@ -185,13 +228,38 @@ static void vkms_config_test_valid_plane_type(struct = kunit *test) vkms_config_destroy(config); } =20 +static void vkms_config_test_valid_crtc_number(struct kunit *test) +{ + struct vkms_config *config; + struct vkms_config_crtc *crtc_cfg; + int n; + + config =3D vkms_config_default_create(false, false, false); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config); + + /* Invalid: No CRTCs */ + crtc_cfg =3D list_first_entry(&config->crtcs, typeof(*crtc_cfg), link); + vkms_config_destroy_crtc(config, crtc_cfg); + KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config)); + + /* Invalid: Too many CRTCs */ + for (n =3D 0; n <=3D 32; n++) + vkms_config_add_crtc(config); + + KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config)); + + 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, default_config_gen_params), KUNIT_CASE(vkms_config_test_get_planes), + KUNIT_CASE(vkms_config_test_get_crtcs), KUNIT_CASE(vkms_config_test_valid_plane_number), KUNIT_CASE(vkms_config_test_valid_plane_type), + KUNIT_CASE(vkms_config_test_valid_crtc_number), {} }; =20 diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms= _config.c index a5a77612645f..4128892836d7 100644 --- a/drivers/gpu/drm/vkms/vkms_config.c +++ b/drivers/gpu/drm/vkms/vkms_config.c @@ -22,6 +22,7 @@ struct vkms_config *vkms_config_create(const char *dev_na= me) } =20 INIT_LIST_HEAD(&config->planes); + INIT_LIST_HEAD(&config->crtcs); =20 return config; } @@ -32,19 +33,23 @@ struct vkms_config *vkms_config_default_create(bool ena= ble_cursor, { struct vkms_config *config; struct vkms_config_plane *plane_cfg; + struct vkms_config_crtc *crtc_cfg; int n; =20 config =3D vkms_config_create(DEFAULT_DEVICE_NAME); if (IS_ERR(config)) return config; =20 - config->writeback =3D enable_writeback; - plane_cfg =3D vkms_config_add_plane(config); if (IS_ERR(plane_cfg)) goto err_alloc; vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_PRIMARY); =20 + crtc_cfg =3D vkms_config_add_crtc(config); + if (IS_ERR(crtc_cfg)) + goto err_alloc; + vkms_config_crtc_set_writeback(crtc_cfg, enable_writeback); + if (enable_overlay) { for (n =3D 0; n < NUM_OVERLAY_PLANES; n++) { plane_cfg =3D vkms_config_add_plane(config); @@ -72,10 +77,14 @@ struct vkms_config *vkms_config_default_create(bool ena= ble_cursor, void vkms_config_destroy(struct vkms_config *config) { struct vkms_config_plane *plane_cfg, *plane_tmp; + struct vkms_config_crtc *crtc_cfg, *crtc_tmp; =20 list_for_each_entry_safe(plane_cfg, plane_tmp, &config->planes, link) vkms_config_destroy_plane(plane_cfg); =20 + list_for_each_entry_safe(crtc_cfg, crtc_tmp, &config->crtcs, link) + vkms_config_destroy_crtc(config, crtc_cfg); + kfree_const(config->dev_name); kfree(config); } @@ -107,6 +116,33 @@ struct vkms_config_plane **vkms_config_get_planes(cons= t struct vkms_config *conf return array; } =20 +struct vkms_config_crtc **vkms_config_get_crtcs(const struct vkms_config *= config, + size_t *out_length) +{ + struct vkms_config_crtc **array; + struct vkms_config_crtc *crtc_cfg; + size_t length; + int n =3D 0; + + length =3D list_count_nodes((struct list_head *)&config->crtcs); + 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); + + list_for_each_entry(crtc_cfg, &config->crtcs, link) { + array[n] =3D crtc_cfg; + n++; + } + + *out_length =3D length; + return array; +} + static bool valid_plane_number(struct vkms_config *config) { size_t n_planes; @@ -156,11 +192,27 @@ static bool valid_plane_type(struct vkms_config *conf= ig) return true; } =20 +static bool valid_crtc_number(struct vkms_config *config) +{ + size_t n_crtcs; + + n_crtcs =3D list_count_nodes(&config->crtcs); + if (n_crtcs <=3D 0 || n_crtcs >=3D 32) { + pr_err("The number of CRTCs must be between 1 and 31\n"); + return false; + } + + return true; +} + bool vkms_config_is_valid(struct vkms_config *config) { if (!valid_plane_number(config)) return false; =20 + if (!valid_crtc_number(config)) + return false; + if (!valid_plane_type(config)) return false; =20 @@ -174,10 +226,10 @@ static int vkms_config_show(struct seq_file *m, void = *data) struct vkms_device *vkmsdev =3D drm_device_to_vkms_device(dev); const char *dev_name; struct vkms_config_plane *plane_cfg; + struct vkms_config_crtc *crtc_cfg; =20 dev_name =3D vkms_config_get_device_name((struct vkms_config *)vkmsdev->c= onfig); seq_printf(m, "dev_name=3D%s\n", dev_name); - seq_printf(m, "writeback=3D%d\n", vkmsdev->config->writeback); =20 list_for_each_entry(plane_cfg, &vkmsdev->config->planes, link) { seq_puts(m, "plane:\n"); @@ -185,6 +237,12 @@ static int vkms_config_show(struct seq_file *m, void *= data) vkms_config_plane_get_type(plane_cfg)); } =20 + list_for_each_entry(crtc_cfg, &vkmsdev->config->crtcs, link) { + seq_puts(m, "crtc:\n"); + seq_printf(m, "\twriteback=3D%d\n", + vkms_config_crtc_get_writeback(crtc_cfg)); + } + return 0; } =20 @@ -218,3 +276,25 @@ void vkms_config_destroy_plane(struct vkms_config_plan= e *plane_cfg) list_del(&plane_cfg->link); kfree(plane_cfg); } + +struct vkms_config_crtc *vkms_config_add_crtc(struct vkms_config *config) +{ + struct vkms_config_crtc *crtc_cfg; + + crtc_cfg =3D kzalloc(sizeof(*crtc_cfg), GFP_KERNEL); + if (!crtc_cfg) + return ERR_PTR(-ENOMEM); + + vkms_config_crtc_set_writeback(crtc_cfg, false); + + list_add_tail(&crtc_cfg->link, &config->crtcs); + + return crtc_cfg; +} + +void vkms_config_destroy_crtc(struct vkms_config *config, + struct vkms_config_crtc *crtc_cfg) +{ + list_del(&crtc_cfg->link); + kfree(crtc_cfg); +} diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms= _config.h index d9aeba1762d1..a7828fe0c4b2 100644 --- a/drivers/gpu/drm/vkms/vkms_config.h +++ b/drivers/gpu/drm/vkms/vkms_config.h @@ -14,12 +14,14 @@ * @dev_name: Name of the device * @writeback: If true, a writeback buffer can be attached to the CRTC * @planes: List of planes configured for the device + * @crtcs: List of CRTCs configured for the device * @dev: Used to store the current VKMS device. Only set when the device i= s instantiated. */ struct vkms_config { const char *dev_name; bool writeback; struct list_head planes; + struct list_head crtcs; struct vkms_device *dev; }; =20 @@ -43,6 +45,25 @@ struct vkms_config_plane { struct vkms_plane *plane; }; =20 +/** + * struct vkms_config_crtc + * + * @link: Link to the others CRTCs in vkms_config + * @writeback: If true, a writeback buffer can be attached to the CRTC + * @crtc: Internal usage. This pointer should never be considered as valid. + * It can be used to store a temporary reference to a VKMS CRTC dur= ing + * device creation. This pointer is not managed by the configuratio= n and + * must be managed by other means. + */ +struct vkms_config_crtc { + struct list_head link; + + bool writeback; + + /* Internal usage */ + struct vkms_output *crtc; +}; + /** * vkms_config_create() - Create a new VKMS configuration * @dev_name: Name of the device @@ -96,6 +117,28 @@ vkms_config_get_device_name(struct vkms_config *config) struct vkms_config_plane **vkms_config_get_planes(const struct vkms_config= *config, size_t *out_length); =20 +/** + * vkms_config_get_num_crtcs() - Return the number of CRTCs in the configu= ration + * @config: Configuration to get the number of CRTCs from + */ +static inline size_t vkms_config_get_num_crtcs(struct vkms_config *config) +{ + return list_count_nodes(&config->crtcs); +} + +/** + * vkms_config_get_crtcs() - Return the array of CRTCs of the device + * @config: Configuration to get the CRTCs 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_crtc **vkms_config_get_crtcs(const struct vkms_config *= config, + size_t *out_length); + /** * vkms_config_is_valid() - Validate a configuration * @config: Configuration to validate @@ -151,4 +194,44 @@ vkms_config_plane_set_type(struct vkms_config_plane *p= lane_cfg, plane_cfg->type =3D type; } =20 +/** + * vkms_config_add_crtc() - Add a new CRTC configuration + * @config: Configuration to add the CRTC to + * + * Returns: + * The new CRTC configuration or an error. Call vkms_config_destroy_crtc()= to + * free the returned CRTC configuration. + */ +struct vkms_config_crtc *vkms_config_add_crtc(struct vkms_config *config); + +/** + * vkms_config_destroy_crtc() - Remove and free a CRTC configuration + * @config: Configuration to remove the CRTC from + * @crtc_cfg: CRTC configuration to destroy + */ +void vkms_config_destroy_crtc(struct vkms_config *config, + struct vkms_config_crtc *crtc_cfg); + +/** + * vkms_config_crtc_get_writeback() - If a writeback connector will be cre= ated + * @crtc_cfg: CRTC with or without a writeback connector + */ +static inline bool +vkms_config_crtc_get_writeback(struct vkms_config_crtc *crtc_cfg) +{ + return crtc_cfg->writeback; +} + +/** + * vkms_config_crtc_set_writeback() - If a writeback connector will be cre= ated + * @crtc_cfg: Target CRTC + * @writeback: Enable or disable the writeback connector + */ +static inline void +vkms_config_crtc_set_writeback(struct vkms_config_crtc *crtc_cfg, + bool writeback) +{ + crtc_cfg->writeback =3D writeback; +} + #endif /* _VKMS_CONFIG_H_ */ diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_dr= v.c index f23ee1a053e9..77f24b802849 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.c +++ b/drivers/gpu/drm/vkms/vkms_drv.c @@ -181,7 +181,8 @@ static int vkms_create(struct vkms_config *config) goto out_devres; } =20 - ret =3D drm_vblank_init(&vkms_device->drm, 1); + ret =3D drm_vblank_init(&vkms_device->drm, + vkms_config_get_num_crtcs(config)); if (ret) { DRM_ERROR("Failed to vblank\n"); goto out_devres; --=20 2.48.1 From nobody Mon Feb 9 13:37:03 2026 Received: from mail-wr1-f44.google.com (mail-wr1-f44.google.com [209.85.221.44]) (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 E04041DDC03 for ; Wed, 29 Jan 2025 11:01:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.44 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738148480; cv=none; b=W2wApF8bDc3TGIaV3slhH25T0dqZCg4Cq6Ph2cqVqSBjkAaxD/kX75X9itTrIu5n6nhiMHT5NVx5ud7YgC0X+yK1M2hZJknAxMGLwOfOe9e9t9j5CGgoOw4zCV6RMzbI21iFEmEPAaFZT5Ef6xE6y0rJpsQh3GdA6IuaKU3oYNs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738148480; c=relaxed/simple; bh=xt9y9griwrDkz21B79ZRhlUQ54QCkFUACv5p0RVf3LU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=GNVnmCdx+Yitu2s18JxA0VliYVf+Yd8AgG8cm7qoBZg2EyarWgka91ULO7Ch0/2r1esSHqHfQYcECTGw+6QVBbXNLbR72pkQBEwfMdtJjAjAT4lhSyMOmfZxyRwgpvzON0s249Vao4t2D7+eJRApKhaP4pBUqN7vrvLQkOSxEkk= 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=IoKFoJwE; arc=none smtp.client-ip=209.85.221.44 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="IoKFoJwE" Received: by mail-wr1-f44.google.com with SMTP id ffacd0b85a97d-38a88ba968aso6539010f8f.3 for ; Wed, 29 Jan 2025 03:01:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1738148476; x=1738753276; 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=q88yikrH24hbqKVdPbrR3EWE1tAj+IlW/np5tlv3WjE=; b=IoKFoJwEQ1zj6Gflaal8AABli0RTv+1JQRhURbW3BnMQrxObjQ00If5+zXHL9BBmrm Bz3QQaHpNFhfR9XYC1CNYsU8attvla99J02vZefSGSM1sSUzjuExj/MFGDFTPWPgpGmr 4lNXQXfCgSavGsy+KwlyRQE6rz/unfUP57fV5HUL7v6xuEgXQvVkPNtTel77epzf5m6k lv1BH8TlJzJEnXCmwG+8sueIj8y/EWOek5Xju8ldu50b6haVK4aK8pmBCQGPlD7vcE9O opSZbwG3YK/ie9OcrOVUQiBEuiePXm5PueIKEHhRMJXtxb9mC2xE/IGiFbA5b4d2XJEe /UuQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1738148476; x=1738753276; 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=q88yikrH24hbqKVdPbrR3EWE1tAj+IlW/np5tlv3WjE=; b=ozRujJwwBpd12wXYw68SrIIKqeNnquh2KeF+WRlPxCkTPXz0jE/h5b9WO8tZMTd0SP cfOk5LT6qI6jTvhKT6NpDbpCNi/TI7YiLrnylxo/OYsB7HK6gPWGxF5MvIu0tGfVP0Hd HeY+gkXNczA7WbxJFA7AXZHxSTkcxGX2Vb4z/u6z+Phl1pFIVtuPal0RmmUGZWn25wIn /e5kvmyLWYLlx8c6Eo2EayP25Q+weLdEfj0VXd507f2eZAlL0Vaz31es3gcPp7p+rWUq siTPs6GQo2uM2YzX1p4XqyaCt8ohen2JCszXBdetID2sSknDMurSluUa1MeP5fWYvfOJ eeSQ== X-Forwarded-Encrypted: i=1; AJvYcCUUK9wOD65QabaR5UbFxDMOqNOZ35fT5J60uKi8BBGrJ7iiqKnVVuDNTNtfnGQwy0k06FFyJWH49FNReqI=@vger.kernel.org X-Gm-Message-State: AOJu0YzGyrax7krKYb0rIgeeUbTDRr/ranfegxHFVuuqlPjphnJpLI6L g3Y6Ce+UMDfssGQAYXbx9M312YyBL3MM+RLddIbO9tVOLRB0OlmN X-Gm-Gg: ASbGncvsD2qnQEEsvnM0XGmws2vB5zT3iVk+GTBnPQcnzICu/l25GEWW8wuXsDs6IOd kGlFWafa0bvmNliIBaOQ6yM2tOU/ZOhOURLH3WfITcwQmE2W2ppT20fzYcWHplIUY/6OdZp6ydO gGRHC05wYUjIaoXGOGpagxhLviP7S+Sq34u+pdK7Q4qUqyRHhRGSxIJKLSdSMQ+OJyl56uyyFzu aD7piAnZv8DQCenXaedCgWM9pHCHzqr/QhMHJGbvAkvv/KObBV5ecJ/poW9CntckZxccrngsMfm a0LV1kZBZlwjwpNm X-Google-Smtp-Source: AGHT+IHDlygoZF3UMYScVhrgVjNYuMwkTq/5UtcpTgAKwbdLoTEd/tYv5i194zzG2JjgIAWcJ9vP7Q== X-Received: by 2002:adf:f943:0:b0:385:f996:1b8e with SMTP id ffacd0b85a97d-38c51951006mr2222645f8f.16.1738148475782; Wed, 29 Jan 2025 03:01:15 -0800 (PST) Received: from fedora.. ([94.73.37.161]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-38c2a176434sm16947113f8f.13.2025.01.29.03.01.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Jan 2025 03:01:15 -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 09/13] drm/vkms: Allow to attach planes and CRTCs Date: Wed, 29 Jan 2025 12:00:55 +0100 Message-ID: <20250129110059.12199-10-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 CRTCs to the plane configuration and helpers to attach, detach and get the primary and cursor planes attached to a CRTC. Now that the default configuration has its planes and CRTC correctly attached, 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 | 185 ++++++++++++++++++ drivers/gpu/drm/vkms/vkms_config.c | 166 ++++++++++++++-- drivers/gpu/drm/vkms/vkms_config.h | 55 +++++- drivers/gpu/drm/vkms/vkms_output.c | 77 ++++++-- 4 files changed, 446 insertions(+), 37 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 b5907b060a5c..5e698616491a 100644 --- a/drivers/gpu/drm/vkms/tests/vkms_config_test.c +++ b/drivers/gpu/drm/vkms/tests/vkms_config_test.c @@ -87,6 +87,18 @@ static void vkms_config_test_default_config(struct kunit= *test) KUNIT_EXPECT_EQ(test, vkms_config_crtc_get_writeback(crtc_cfg), params->enable_writeback); =20 + list_for_each_entry(plane_cfg, &config->planes, link) { + struct vkms_config_crtc *possible_crtc; + int n_possible_crtcs =3D 0; + unsigned long idx =3D 0; + + xa_for_each(&plane_cfg->possible_crtcs, idx, possible_crtc) { + KUNIT_EXPECT_PTR_EQ(test, crtc_cfg, possible_crtc); + n_possible_crtcs++; + } + KUNIT_EXPECT_EQ(test, n_possible_crtcs, 1); + } + KUNIT_EXPECT_TRUE(test, vkms_config_is_valid(config)); =20 vkms_config_destroy(config); @@ -191,6 +203,8 @@ static void vkms_config_test_valid_plane_type(struct ku= nit *test) { struct vkms_config *config; struct vkms_config_plane *plane_cfg; + struct vkms_config_crtc *crtc_cfg; + int err; =20 config =3D vkms_config_default_create(false, false, false); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config); @@ -198,16 +212,26 @@ static void vkms_config_test_valid_plane_type(struct = kunit *test) plane_cfg =3D list_first_entry(&config->planes, typeof(*plane_cfg), link); vkms_config_destroy_plane(plane_cfg); =20 + crtc_cfg =3D list_first_entry(&config->crtcs, typeof(*crtc_cfg), link); + /* Invalid: No primary plane */ plane_cfg =3D vkms_config_add_plane(config); vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_OVERLAY); + err =3D vkms_config_plane_attach_crtc(plane_cfg, crtc_cfg); + KUNIT_EXPECT_EQ(test, err, 0); KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config)); =20 /* Invalid: Multiple primary planes */ plane_cfg =3D vkms_config_add_plane(config); vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_PRIMARY); + err =3D vkms_config_plane_attach_crtc(plane_cfg, crtc_cfg); + KUNIT_EXPECT_EQ(test, err, 0); + plane_cfg =3D vkms_config_add_plane(config); vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_PRIMARY); + err =3D vkms_config_plane_attach_crtc(plane_cfg, crtc_cfg); + KUNIT_EXPECT_EQ(test, err, 0); + KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config)); =20 /* Valid: One primary plane */ @@ -217,14 +241,50 @@ static void vkms_config_test_valid_plane_type(struct = kunit *test) /* Invalid: Multiple cursor planes */ plane_cfg =3D vkms_config_add_plane(config); vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_CURSOR); + err =3D vkms_config_plane_attach_crtc(plane_cfg, crtc_cfg); + KUNIT_EXPECT_EQ(test, err, 0); + plane_cfg =3D vkms_config_add_plane(config); vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_CURSOR); + err =3D vkms_config_plane_attach_crtc(plane_cfg, crtc_cfg); + KUNIT_EXPECT_EQ(test, err, 0); + KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config)); =20 /* Valid: One primary and one cursor plane */ vkms_config_destroy_plane(plane_cfg); KUNIT_EXPECT_TRUE(test, vkms_config_is_valid(config)); =20 + /* Invalid: Second CRTC without primary plane */ + crtc_cfg =3D vkms_config_add_crtc(config); + KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config)); + + /* Valid: Second CRTC with a primary plane */ + plane_cfg =3D vkms_config_add_plane(config); + vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_PRIMARY); + err =3D vkms_config_plane_attach_crtc(plane_cfg, crtc_cfg); + KUNIT_EXPECT_EQ(test, err, 0); + KUNIT_EXPECT_TRUE(test, vkms_config_is_valid(config)); + + vkms_config_destroy(config); +} + +static void vkms_config_test_valid_plane_possible_crtcs(struct kunit *test) +{ + struct vkms_config *config; + struct vkms_config_plane *plane_cfg; + struct vkms_config_crtc *crtc_cfg; + + config =3D vkms_config_default_create(false, false, false); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config); + + plane_cfg =3D list_first_entry(&config->planes, typeof(*plane_cfg), link); + crtc_cfg =3D list_first_entry(&config->crtcs, typeof(*crtc_cfg), link); + + /* Invalid: Primary plane without a possible CRTC */ + vkms_config_plane_detach_crtc(plane_cfg, crtc_cfg); + KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config)); + vkms_config_destroy(config); } =20 @@ -251,6 +311,128 @@ static void vkms_config_test_valid_crtc_number(struct= kunit *test) vkms_config_destroy(config); } =20 +static void vkms_config_test_plane_attach_crtc(struct kunit *test) +{ + struct vkms_config *config; + struct vkms_config_plane *overlay_cfg; + struct vkms_config_plane *primary_cfg; + struct vkms_config_plane *cursor_cfg; + struct vkms_config_crtc *crtc_cfg; + int err; + + config =3D vkms_config_create("test"); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config); + + overlay_cfg =3D vkms_config_add_plane(config); + vkms_config_plane_set_type(overlay_cfg, DRM_PLANE_TYPE_OVERLAY); + primary_cfg =3D vkms_config_add_plane(config); + vkms_config_plane_set_type(primary_cfg, DRM_PLANE_TYPE_PRIMARY); + cursor_cfg =3D vkms_config_add_plane(config); + vkms_config_plane_set_type(cursor_cfg, DRM_PLANE_TYPE_CURSOR); + + crtc_cfg =3D vkms_config_add_crtc(config); + + /* No primary or cursor planes */ + KUNIT_EXPECT_NULL(test, vkms_config_crtc_primary_plane(config, crtc_cfg)); + KUNIT_EXPECT_NULL(test, vkms_config_crtc_cursor_plane(config, crtc_cfg)); + + /* Overlay plane, but no primary or cursor planes */ + err =3D vkms_config_plane_attach_crtc(overlay_cfg, crtc_cfg); + KUNIT_EXPECT_EQ(test, err, 0); + KUNIT_EXPECT_NULL(test, vkms_config_crtc_primary_plane(config, crtc_cfg)); + KUNIT_EXPECT_NULL(test, vkms_config_crtc_cursor_plane(config, crtc_cfg)); + + /* Primary plane, attaching it twice must fail */ + err =3D vkms_config_plane_attach_crtc(primary_cfg, crtc_cfg); + KUNIT_EXPECT_EQ(test, err, 0); + err =3D vkms_config_plane_attach_crtc(primary_cfg, crtc_cfg); + KUNIT_EXPECT_NE(test, err, 0); + KUNIT_EXPECT_PTR_EQ(test, + vkms_config_crtc_primary_plane(config, crtc_cfg), + primary_cfg); + KUNIT_EXPECT_NULL(test, vkms_config_crtc_cursor_plane(config, crtc_cfg)); + + /* Primary and cursor planes */ + err =3D vkms_config_plane_attach_crtc(cursor_cfg, crtc_cfg); + KUNIT_EXPECT_EQ(test, err, 0); + KUNIT_EXPECT_PTR_EQ(test, + vkms_config_crtc_primary_plane(config, crtc_cfg), + primary_cfg); + KUNIT_EXPECT_PTR_EQ(test, + vkms_config_crtc_cursor_plane(config, crtc_cfg), + cursor_cfg); + + /* Detach primary and destroy cursor plane */ + vkms_config_plane_detach_crtc(overlay_cfg, crtc_cfg); + vkms_config_plane_detach_crtc(primary_cfg, crtc_cfg); + vkms_config_destroy_plane(cursor_cfg); + KUNIT_EXPECT_NULL(test, vkms_config_crtc_primary_plane(config, crtc_cfg)); + KUNIT_EXPECT_NULL(test, vkms_config_crtc_cursor_plane(config, crtc_cfg)); + + vkms_config_destroy(config); +} + +static void vkms_config_test_plane_get_possible_crtcs(struct kunit *test) +{ + struct vkms_config *config; + struct vkms_config_plane *plane_cfg1, *plane_cfg2; + struct vkms_config_crtc *crtc_cfg1, *crtc_cfg2; + struct vkms_config_crtc **array; + size_t length; + int err; + + config =3D vkms_config_create("test"); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config); + + plane_cfg1 =3D vkms_config_add_plane(config); + plane_cfg2 =3D vkms_config_add_plane(config); + crtc_cfg1 =3D vkms_config_add_crtc(config); + crtc_cfg2 =3D vkms_config_add_crtc(config); + + /* No possible CRTCs */ + array =3D vkms_config_plane_get_possible_crtcs(plane_cfg1, &length); + KUNIT_ASSERT_EQ(test, length, 0); + KUNIT_ASSERT_NULL(test, array); + + array =3D vkms_config_plane_get_possible_crtcs(plane_cfg2, &length); + KUNIT_ASSERT_EQ(test, length, 0); + KUNIT_ASSERT_NULL(test, array); + + /* Plane 1 attached to CRTC 1 and 2 */ + err =3D vkms_config_plane_attach_crtc(plane_cfg1, crtc_cfg1); + KUNIT_EXPECT_EQ(test, err, 0); + err =3D vkms_config_plane_attach_crtc(plane_cfg1, crtc_cfg2); + KUNIT_EXPECT_EQ(test, err, 0); + + array =3D vkms_config_plane_get_possible_crtcs(plane_cfg1, &length); + KUNIT_ASSERT_EQ(test, length, 2); + KUNIT_ASSERT_PTR_EQ(test, array[0], crtc_cfg1); + KUNIT_ASSERT_PTR_EQ(test, array[1], crtc_cfg2); + kfree(array); + + array =3D vkms_config_plane_get_possible_crtcs(plane_cfg2, &length); + KUNIT_ASSERT_EQ(test, length, 0); + KUNIT_ASSERT_NULL(test, array); + + /* Plane 1 attached to CRTC 1 and plane 2 to CRTC 2 */ + vkms_config_plane_detach_crtc(plane_cfg1, crtc_cfg2); + + array =3D vkms_config_plane_get_possible_crtcs(plane_cfg1, &length); + KUNIT_ASSERT_EQ(test, length, 1); + KUNIT_ASSERT_PTR_EQ(test, array[0], crtc_cfg1); + kfree(array); + + err =3D vkms_config_plane_attach_crtc(plane_cfg2, crtc_cfg2); + KUNIT_EXPECT_EQ(test, err, 0); + + array =3D vkms_config_plane_get_possible_crtcs(plane_cfg2, &length); + KUNIT_ASSERT_EQ(test, length, 1); + KUNIT_ASSERT_PTR_EQ(test, array[0], crtc_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, @@ -259,7 +441,10 @@ static struct kunit_case vkms_config_test_cases[] =3D { KUNIT_CASE(vkms_config_test_get_crtcs), KUNIT_CASE(vkms_config_test_valid_plane_number), KUNIT_CASE(vkms_config_test_valid_plane_type), + KUNIT_CASE(vkms_config_test_valid_plane_possible_crtcs), KUNIT_CASE(vkms_config_test_valid_crtc_number), + KUNIT_CASE(vkms_config_test_plane_attach_crtc), + KUNIT_CASE(vkms_config_test_plane_get_possible_crtcs), {} }; =20 diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms= _config.c index 4128892836d7..a2ce4905589b 100644 --- a/drivers/gpu/drm/vkms/vkms_config.c +++ b/drivers/gpu/drm/vkms/vkms_config.c @@ -50,13 +50,20 @@ struct vkms_config *vkms_config_default_create(bool ena= ble_cursor, goto err_alloc; vkms_config_crtc_set_writeback(crtc_cfg, enable_writeback); =20 + if (vkms_config_plane_attach_crtc(plane_cfg, crtc_cfg)) + goto err_alloc; + if (enable_overlay) { for (n =3D 0; n < NUM_OVERLAY_PLANES; n++) { plane_cfg =3D vkms_config_add_plane(config); if (IS_ERR(plane_cfg)) goto err_alloc; + vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_OVERLAY); + + if (vkms_config_plane_attach_crtc(plane_cfg, crtc_cfg)) + goto err_alloc; } } =20 @@ -64,7 +71,11 @@ struct vkms_config *vkms_config_default_create(bool enab= le_cursor, plane_cfg =3D vkms_config_add_plane(config); if (IS_ERR(plane_cfg)) goto err_alloc; + vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_CURSOR); + + if (vkms_config_plane_attach_crtc(plane_cfg, crtc_cfg)) + goto err_alloc; } =20 return config; @@ -156,31 +167,39 @@ static bool valid_plane_number(struct vkms_config *co= nfig) return true; } =20 -static bool valid_plane_type(struct vkms_config *config) +static bool valid_plane_type(struct vkms_config *config, + struct vkms_config_crtc *crtc_cfg) { struct vkms_config_plane *plane_cfg; bool has_primary_plane =3D false; bool has_cursor_plane =3D false; =20 list_for_each_entry(plane_cfg, &config->planes, link) { + struct vkms_config_crtc *possible_crtc; + unsigned long idx =3D 0; enum drm_plane_type type; =20 type =3D vkms_config_plane_get_type(plane_cfg); =20 - if (type =3D=3D DRM_PLANE_TYPE_PRIMARY) { - if (has_primary_plane) { - pr_err("Multiple primary planes\n"); - return false; - } + xa_for_each(&plane_cfg->possible_crtcs, idx, possible_crtc) { + if (possible_crtc !=3D crtc_cfg) + continue; =20 - has_primary_plane =3D true; - } else if (type =3D=3D DRM_PLANE_TYPE_CURSOR) { - if (has_cursor_plane) { - pr_err("Multiple cursor planes\n"); - return false; - } + if (type =3D=3D DRM_PLANE_TYPE_PRIMARY) { + if (has_primary_plane) { + pr_err("Multiple primary planes\n"); + return false; + } =20 - has_cursor_plane =3D true; + has_primary_plane =3D true; + } else if (type =3D=3D DRM_PLANE_TYPE_CURSOR) { + if (has_cursor_plane) { + pr_err("Multiple cursor planes\n"); + return false; + } + + has_cursor_plane =3D true; + } } } =20 @@ -192,6 +211,20 @@ static bool valid_plane_type(struct vkms_config *confi= g) return true; } =20 +static bool valid_plane_possible_crtcs(struct vkms_config *config) +{ + struct vkms_config_plane *plane_cfg; + + list_for_each_entry(plane_cfg, &config->planes, link) { + if (xa_empty(&plane_cfg->possible_crtcs)) { + pr_err("All planes must have at least one possible CRTC\n"); + return false; + } + } + + return true; +} + static bool valid_crtc_number(struct vkms_config *config) { size_t n_crtcs; @@ -207,15 +240,22 @@ static bool valid_crtc_number(struct vkms_config *con= fig) =20 bool vkms_config_is_valid(struct vkms_config *config) { + struct vkms_config_crtc *crtc_cfg; + if (!valid_plane_number(config)) return false; =20 if (!valid_crtc_number(config)) return false; =20 - if (!valid_plane_type(config)) + if (!valid_plane_possible_crtcs(config)) return false; =20 + list_for_each_entry(crtc_cfg, &config->crtcs, link) { + if (!valid_plane_type(config, crtc_cfg)) + return false; + } + return true; } =20 @@ -265,6 +305,7 @@ struct vkms_config_plane *vkms_config_add_plane(struct = vkms_config *config) return ERR_PTR(-ENOMEM); =20 vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_OVERLAY); + xa_init_flags(&plane_cfg->possible_crtcs, XA_FLAGS_ALLOC); =20 list_add_tail(&plane_cfg->link, &config->planes); =20 @@ -273,10 +314,69 @@ struct vkms_config_plane *vkms_config_add_plane(struc= t vkms_config *config) =20 void vkms_config_destroy_plane(struct vkms_config_plane *plane_cfg) { + xa_destroy(&plane_cfg->possible_crtcs); list_del(&plane_cfg->link); kfree(plane_cfg); } =20 +int __must_check vkms_config_plane_attach_crtc(struct vkms_config_plane *p= lane_cfg, + struct vkms_config_crtc *crtc_cfg) +{ + struct vkms_config_crtc *possible_crtc; + unsigned long idx =3D 0; + u32 crtc_idx =3D 0; + + xa_for_each(&plane_cfg->possible_crtcs, idx, possible_crtc) { + if (possible_crtc =3D=3D crtc_cfg) + return -EINVAL; + } + + return xa_alloc(&plane_cfg->possible_crtcs, &crtc_idx, crtc_cfg, + xa_limit_32b, GFP_KERNEL); +} + +void vkms_config_plane_detach_crtc(struct vkms_config_plane *plane_cfg, + struct vkms_config_crtc *crtc_cfg) +{ + struct vkms_config_crtc *possible_crtc; + unsigned long idx =3D 0; + + xa_for_each(&plane_cfg->possible_crtcs, idx, possible_crtc) { + if (possible_crtc =3D=3D crtc_cfg) + xa_erase(&plane_cfg->possible_crtcs, idx); + } +} + +struct vkms_config_crtc **vkms_config_plane_get_possible_crtcs(struct vkms= _config_plane *plane_cfg, + size_t *out_length) +{ + struct vkms_config_crtc **array; + struct vkms_config_crtc *possible_crtc; + unsigned long idx; + size_t length =3D 0; + int n =3D 0; + + xa_for_each(&plane_cfg->possible_crtcs, idx, possible_crtc) + 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(&plane_cfg->possible_crtcs, idx, possible_crtc) { + array[n] =3D possible_crtc; + n++; + } + + *out_length =3D length; + return array; +} + struct vkms_config_crtc *vkms_config_add_crtc(struct vkms_config *config) { struct vkms_config_crtc *crtc_cfg; @@ -295,6 +395,44 @@ struct vkms_config_crtc *vkms_config_add_crtc(struct v= kms_config *config) void vkms_config_destroy_crtc(struct vkms_config *config, struct vkms_config_crtc *crtc_cfg) { + struct vkms_config_plane *plane_cfg; + + list_for_each_entry(plane_cfg, &config->planes, link) + vkms_config_plane_detach_crtc(plane_cfg, crtc_cfg); + list_del(&crtc_cfg->link); kfree(crtc_cfg); } + +static struct vkms_config_plane *vkms_config_crtc_get_plane(const struct v= kms_config *config, + struct vkms_config_crtc *crtc_cfg, + enum drm_plane_type type) +{ + struct vkms_config_plane *plane_cfg; + struct vkms_config_crtc *possible_crtc; + enum drm_plane_type current_type; + unsigned long idx; + + list_for_each_entry(plane_cfg, &config->planes, link) { + current_type =3D vkms_config_plane_get_type(plane_cfg); + + xa_for_each(&plane_cfg->possible_crtcs, idx, possible_crtc) { + if (possible_crtc =3D=3D crtc_cfg && current_type =3D=3D type) + return plane_cfg; + } + } + + return NULL; +} + +struct vkms_config_plane *vkms_config_crtc_primary_plane(const struct vkms= _config *config, + struct vkms_config_crtc *crtc_cfg) +{ + return vkms_config_crtc_get_plane(config, crtc_cfg, DRM_PLANE_TYPE_PRIMAR= Y); +} + +struct vkms_config_plane *vkms_config_crtc_cursor_plane(const struct vkms_= config *config, + struct vkms_config_crtc *crtc_cfg) +{ + return vkms_config_crtc_get_plane(config, crtc_cfg, DRM_PLANE_TYPE_CURSOR= ); +} diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms= _config.h index a7828fe0c4b2..1f2e6c485d08 100644 --- a/drivers/gpu/drm/vkms/vkms_config.h +++ b/drivers/gpu/drm/vkms/vkms_config.h @@ -12,14 +12,12 @@ * struct vkms_config - General configuration for VKMS driver * * @dev_name: Name of the device - * @writeback: If true, a writeback buffer can be attached to the CRTC * @planes: List of planes configured for the device * @crtcs: List of CRTCs configured for the device * @dev: Used to store the current VKMS device. Only set when the device i= s instantiated. */ struct vkms_config { const char *dev_name; - bool writeback; struct list_head planes; struct list_head crtcs; struct vkms_device *dev; @@ -31,6 +29,7 @@ struct vkms_config { * @link: Link to the others planes in vkms_config * @type: Type of the plane. The creator of configuration needs to ensures= that * at least one primary plane is present. + * @possible_crtcs: Array of CRTCs that can be used with this plane * @plane: Internal usage. This pointer should never be considered as vali= d. * It can be used to store a temporary reference to a VKMS plane d= uring * device creation. This pointer is not managed by the configurati= on and @@ -40,6 +39,7 @@ struct vkms_config_plane { struct list_head link; =20 enum drm_plane_type type; + struct xarray possible_crtcs; =20 /* Internal usage */ struct vkms_plane *plane; @@ -194,6 +194,35 @@ vkms_config_plane_set_type(struct vkms_config_plane *p= lane_cfg, plane_cfg->type =3D type; } =20 +/** + * vkms_config_plane_attach_crtc - Attach a plane to a CRTC + * @plane_cfg: Plane to attach + * @crtc_cfg: CRTC to attach @plane_cfg to + */ +int __must_check vkms_config_plane_attach_crtc(struct vkms_config_plane *p= lane_cfg, + struct vkms_config_crtc *crtc_cfg); + +/** + * vkms_config_plane_attach_crtc - Detach a plane from a CRTC + * @plane_cfg: Plane to detach + * @crtc_cfg: CRTC to detach @plane_cfg from + */ +void vkms_config_plane_detach_crtc(struct vkms_config_plane *plane_cfg, + struct vkms_config_crtc *crtc_cfg); + +/** + * vkms_config_plane_get_possible_crtcs() - Return the array of possible C= RTCs + * @plane_cfg: Plane to get the possible CRTCs 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_crtc **vkms_config_plane_get_possible_crtcs(struct vkms= _config_plane *plane_cfg, + size_t *out_length); + /** * vkms_config_add_crtc() - Add a new CRTC configuration * @config: Configuration to add the CRTC to @@ -234,4 +263,26 @@ vkms_config_crtc_set_writeback(struct vkms_config_crtc= *crtc_cfg, crtc_cfg->writeback =3D writeback; } =20 +/** + * vkms_config_crtc_primary_plane() - Return the primary plane for a CRTC + * @config: Configuration containing the CRTC + * @crtc_config: Target CRTC + * + * Returns: + * The primary plane or NULL if none is assigned yet. + */ +struct vkms_config_plane *vkms_config_crtc_primary_plane(const struct vkms= _config *config, + struct vkms_config_crtc *crtc_cfg); + +/** + * vkms_config_crtc_cursor_plane() - Return the cursor plane for a CRTC + * @config: Configuration containing the CRTC + * @crtc_config: Target CRTC + * + * Returns: + * The cursor plane or NULL if none is assigned yet. + */ +struct vkms_config_plane *vkms_config_crtc_cursor_plane(const struct vkms_= config *config, + struct vkms_config_crtc *crtc_cfg); + #endif /* _VKMS_CONFIG_H_ */ diff --git a/drivers/gpu/drm/vkms/vkms_output.c b/drivers/gpu/drm/vkms/vkms= _output.c index b2ae269e5827..427d0aad8901 100644 --- a/drivers/gpu/drm/vkms/vkms_output.c +++ b/drivers/gpu/drm/vkms/vkms_output.c @@ -10,18 +10,24 @@ int vkms_output_init(struct vkms_device *vkmsdev) struct drm_device *dev =3D &vkmsdev->drm; struct vkms_connector *connector; struct drm_encoder *encoder; - struct vkms_output *output; - struct vkms_plane *primary =3D NULL, *cursor =3D NULL; struct vkms_config_plane **plane_cfgs =3D NULL; size_t n_planes; + struct vkms_config_crtc **crtc_cfgs =3D NULL; + size_t n_crtcs; int ret =3D 0; int writeback; - unsigned int n; + unsigned int n, i; =20 plane_cfgs =3D vkms_config_get_planes(vkmsdev->config, &n_planes); if (IS_ERR(plane_cfgs)) return PTR_ERR(plane_cfgs); =20 + crtc_cfgs =3D vkms_config_get_crtcs(vkmsdev->config, &n_crtcs); + if (IS_ERR(crtc_cfgs)) { + ret =3D PTR_ERR(crtc_cfgs); + goto err_free; + } + for (n =3D 0; n < n_planes; n++) { struct vkms_config_plane *plane_cfg; enum drm_plane_type type; @@ -35,19 +41,54 @@ int vkms_output_init(struct vkms_device *vkmsdev) ret =3D PTR_ERR(plane_cfg->plane); goto err_free; } + } + + for (n =3D 0; n < n_crtcs; n++) { + struct vkms_config_crtc *crtc_cfg; + struct vkms_config_plane *primary, *cursor; + + crtc_cfg =3D crtc_cfgs[n]; + primary =3D vkms_config_crtc_primary_plane(vkmsdev->config, crtc_cfg); + cursor =3D vkms_config_crtc_cursor_plane(vkmsdev->config, crtc_cfg); + + crtc_cfg->crtc =3D vkms_crtc_init(dev, &primary->plane->base, + cursor ? &cursor->plane->base : NULL); + if (IS_ERR(crtc_cfg->crtc)) { + DRM_ERROR("Failed to allocate CRTC\n"); + ret =3D PTR_ERR(crtc_cfg->crtc); + goto err_free; + } =20 - if (type =3D=3D DRM_PLANE_TYPE_PRIMARY) - primary =3D plane_cfg->plane; - else if (type =3D=3D DRM_PLANE_TYPE_CURSOR) - cursor =3D plane_cfg->plane; + /* Initialize the writeback component */ + if (vkms_config_crtc_get_writeback(crtc_cfg)) { + writeback =3D vkms_enable_writeback_connector(vkmsdev, crtc_cfg->crtc); + if (writeback) + DRM_ERROR("Failed to init writeback connector\n"); + } } =20 - output =3D vkms_crtc_init(dev, &primary->base, - cursor ? &cursor->base : NULL); - if (IS_ERR(output)) { - DRM_ERROR("Failed to allocate CRTC\n"); - ret =3D PTR_ERR(output); - goto err_free; + for (n =3D 0; n < n_planes; n++) { + struct vkms_config_plane *plane_cfg; + struct vkms_config_crtc **possible_crtcs; + size_t n_possible_crtcs; + + plane_cfg =3D plane_cfgs[n]; + possible_crtcs =3D vkms_config_plane_get_possible_crtcs(plane_cfg, + &n_possible_crtcs); + if (IS_ERR(possible_crtcs)) { + ret =3D PTR_ERR(possible_crtcs); + goto err_free; + } + + for (i =3D 0; i < n_possible_crtcs; i++) { + struct vkms_config_crtc *possible_crtc; + + possible_crtc =3D possible_crtcs[i]; + plane_cfg->plane->base.possible_crtcs |=3D + drm_crtc_mask(&possible_crtc->crtc->crtc); + } + + kfree(possible_crtcs); } =20 connector =3D vkms_connector_init(vkmsdev); @@ -69,7 +110,7 @@ int vkms_output_init(struct vkms_device *vkmsdev) DRM_ERROR("Failed to init encoder\n"); goto err_free; } - encoder->possible_crtcs =3D drm_crtc_mask(&output->crtc); + encoder->possible_crtcs =3D drm_crtc_mask(&crtc_cfgs[0]->crtc->crtc); =20 /* Attach the encoder and the connector */ ret =3D drm_connector_attach_encoder(&connector->base, encoder); @@ -78,17 +119,11 @@ int vkms_output_init(struct vkms_device *vkmsdev) goto err_free; } =20 - /* Initialize the writeback component */ - if (vkmsdev->config->writeback) { - writeback =3D vkms_enable_writeback_connector(vkmsdev, output); - if (writeback) - DRM_ERROR("Failed to init writeback connector\n"); - } - drm_mode_config_reset(dev); =20 err_free: kfree(plane_cfgs); + kfree(crtc_cfgs); =20 return ret; } --=20 2.48.1 From nobody Mon Feb 9 13:37:03 2026 Received: from mail-wm1-f52.google.com (mail-wm1-f52.google.com [209.85.128.52]) (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 CCF3F1DDC3A for ; Wed, 29 Jan 2025 11:01:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738148480; cv=none; b=Ed+/ZPR+3bn/W3vJ5D/lflzUQHlj9a5gpnodcizpCUUO+8l8nVMA1bxiapdcwNwigz57JWntFCREIDkw0rc2aGlhAu+n7se24IstGIlBNSwTkY7lyVU6wHkZjpJTvG0isqtayN9BnUlJblN1N1DzBHj5i+1qlvAuJ4uR2b2zMOo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738148480; c=relaxed/simple; bh=Sq2kgKQ3CAouXoUtf/behLth/g+vKu2ro2ZKC0IBz6o=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=YO59dbINFeRgISpbGglhOEe8KiSbkeeWvwidIIQEp/tEhjwf+gGBCmSuGbzK4Ks+TuHLfPKq7qK03nPlIsJk7XCH7KKJIfqYgObJo0gi4ZrY55CPefIvPMSasZNin6Tde59IDO5Q3xAPu0asF5O8XFjV+firtc59lPkrXVOh2A8= 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=Vrqz8ehk; arc=none smtp.client-ip=209.85.128.52 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="Vrqz8ehk" Received: by mail-wm1-f52.google.com with SMTP id 5b1f17b1804b1-43618283d48so47822585e9.1 for ; Wed, 29 Jan 2025 03:01:18 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1738148477; x=1738753277; 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=AeAv/5lTYD8GiNcnw1WJeIlZJ4ADDa5O2/fInNJ5TA0=; b=Vrqz8ehkVlSDIt/SWIQXbXRhsAbF994W0ZD73TSU2GKAbC+GU0uv2CwY8DlIC/yPxQ ezLFKJDaMOEFpZ7JlZs3i4jiu2KFKb39/eWLxXT7qzr5rBwABAYhPzuKbmN9rdw62nGT 595U+RlFZrkDckDQ/CQJk10VLI9xlXignZ3k6uXTPtAisyO6kkI9tiUt0cT2iBwhZBiY riJHTeCAo/24vrrbEFoplPHTUl5CGh7jGRTshHOFQv//PUOPm/YtnoaeplXkHBJnNuel 2zzjix7t8qqBCiQ7Hhmg70bDoZSXgWH+4sD9U97vSmYMZsg8A+6hGeBehaCZdVoCMb6V 74SQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1738148477; x=1738753277; 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=AeAv/5lTYD8GiNcnw1WJeIlZJ4ADDa5O2/fInNJ5TA0=; b=ufZKF8qVmbNMalh8nJg2KFe1gm6T+bNPYpwddKZzItwS/X7+hudmzv/1fvMJFMek5f eoDlxySmrgn+wHi188HqRixO1niYc/IK4NN6f92ld4TtN5kK6qVqyEILdiE1RXBrgp81 A5kRF7GkVChgUCnATEcvTd2VxoLzq4cs4Yfl7gyz5nRFkXG/bX1Cssro62u1Lbm4y6s2 z+ISL4YM+5ovPVCadrJATRSA05H4hGJ8wIpzu9moWtnaDVa6U/mewReA3VOi59qqsWWl 6qPyFyMB0soiRYMHvqrjDJXvfuzLnPFlm1qt86uFtpkubhBO/DmdYB7dmhckeakshvYl /T6A== X-Forwarded-Encrypted: i=1; AJvYcCVXQYuk4EGjUWdjTaYpRMQU2i4tYH1bIrQy6Ue8Uxdch3tIgSJSdFABho7zULYFmONLerBgq6q/rFH3oWs=@vger.kernel.org X-Gm-Message-State: AOJu0Yz1WEzW/wub6mAX9ewRiPVAp8eZp8ddmp/cPh8j0eh8baCDkNUz OuBY+HRVExhCihnnTlXXg3lY5WteooJw8lp4ILYtqNgkMTW4RrTP X-Gm-Gg: ASbGncvY8/bAq3tCiqhj7dUFf0kSAOMEKT7/m+Wn3nsfeWr14PvCRKt1aTArcL8fJXz 6bshVh32PDEslSDb1wKjbGnmT982zyegOUusR0YndwOX39+ITXmtgYargEwOSZOlW16CLw2+9Ah 2e7V27aNGBG+L0GKlR87MI0Esfo4Vglkwupi0TCXBW3VXARwMh2DXWKPHga405Z+Ri41qMjfC2f k+6lVHQ6L9UzgkdNROhs5FFgpi5TqFVlwkK4nXsk5NE99k9nCD32ZQryfhyyN9IoAMs40IULr3f pTZHIvNyhM+L3VBBS0jjHRayu8s= X-Google-Smtp-Source: AGHT+IHHCx+npwL1T2h8TDIMwNBgX+6NeaIWD3PcUKnbkw8C0FD0i29soN8lgyZbFPebW96899TEDA== X-Received: by 2002:a5d:64a1:0:b0:385:f17b:de54 with SMTP id ffacd0b85a97d-38c5193112amr2151371f8f.5.1738148476587; Wed, 29 Jan 2025 03:01:16 -0800 (PST) Received: from fedora.. ([94.73.37.161]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-38c2a176434sm16947113f8f.13.2025.01.29.03.01.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Jan 2025 03:01:16 -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 10/13] drm/vkms: Allow to configure multiple encoders Date: Wed, 29 Jan 2025 12:00:56 +0100 Message-ID: <20250129110059.12199-11-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 encoders to vkms_config and helper functions to add and remove as many encoders as wanted. For backwards compatibility, add one encoder to the default configuration. A future patch will allow to attach encoders and CRTCs, but for the moment there are no changes in the way the output is configured. Signed-off-by: Louis Chauvet Signed-off-by: Jos=C3=A9 Exp=C3=B3sito --- drivers/gpu/drm/vkms/tests/vkms_config_test.c | 65 ++++++++++++++++ drivers/gpu/drm/vkms/vkms_config.c | 78 +++++++++++++++++++ drivers/gpu/drm/vkms/vkms_config.h | 49 ++++++++++++ 3 files changed, 192 insertions(+) diff --git a/drivers/gpu/drm/vkms/tests/vkms_config_test.c b/drivers/gpu/dr= m/vkms/tests/vkms_config_test.c index 5e698616491a..6c09363d9a96 100644 --- a/drivers/gpu/drm/vkms/tests/vkms_config_test.c +++ b/drivers/gpu/drm/vkms/tests/vkms_config_test.c @@ -26,6 +26,7 @@ static void vkms_config_test_empty_config(struct kunit *t= est) =20 KUNIT_EXPECT_TRUE(test, list_empty(&config->planes)); KUNIT_EXPECT_TRUE(test, list_empty(&config->crtcs)); + KUNIT_EXPECT_TRUE(test, list_empty(&config->encoders)); =20 KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config)); =20 @@ -99,6 +100,9 @@ static void vkms_config_test_default_config(struct kunit= *test) KUNIT_EXPECT_EQ(test, n_possible_crtcs, 1); } =20 + /* Encoders */ + KUNIT_EXPECT_EQ(test, list_count_nodes(&config->encoders), 1); + KUNIT_EXPECT_TRUE(test, vkms_config_is_valid(config)); =20 vkms_config_destroy(config); @@ -176,6 +180,42 @@ static void vkms_config_test_get_crtcs(struct kunit *t= est) vkms_config_destroy(config); } =20 +static void vkms_config_test_get_encoders(struct kunit *test) +{ + struct vkms_config *config; + struct vkms_config_encoder *encoder_cfg1, *encoder_cfg2; + struct vkms_config_encoder **array; + size_t length; + + config =3D vkms_config_create("test"); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config); + + array =3D vkms_config_get_encoders(config, &length); + KUNIT_ASSERT_EQ(test, length, 0); + KUNIT_ASSERT_NULL(test, array); + + encoder_cfg1 =3D vkms_config_add_encoder(config); + array =3D vkms_config_get_encoders(config, &length); + KUNIT_ASSERT_EQ(test, length, 1); + KUNIT_ASSERT_PTR_EQ(test, array[0], encoder_cfg1); + kfree(array); + + encoder_cfg2 =3D vkms_config_add_encoder(config); + array =3D vkms_config_get_encoders(config, &length); + 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); + + vkms_config_destroy_encoder(config, encoder_cfg2); + array =3D vkms_config_get_encoders(config, &length); + KUNIT_ASSERT_EQ(test, length, 1); + KUNIT_ASSERT_PTR_EQ(test, array[0], encoder_cfg1); + kfree(array); + + vkms_config_destroy(config); +} + static void vkms_config_test_valid_plane_number(struct kunit *test) { struct vkms_config *config; @@ -311,6 +351,29 @@ static void vkms_config_test_valid_crtc_number(struct = kunit *test) vkms_config_destroy(config); } =20 +static void vkms_config_test_valid_encoder_number(struct kunit *test) +{ + struct vkms_config *config; + struct vkms_config_encoder *encoder_cfg; + int n; + + config =3D vkms_config_default_create(false, false, false); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config); + + /* Invalid: No encoders */ + encoder_cfg =3D list_first_entry(&config->encoders, typeof(*encoder_cfg),= link); + vkms_config_destroy_encoder(config, encoder_cfg); + KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config)); + + /* Invalid: Too many encoders */ + for (n =3D 0; n <=3D 32; n++) + vkms_config_add_encoder(config); + + KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config)); + + vkms_config_destroy(config); +} + static void vkms_config_test_plane_attach_crtc(struct kunit *test) { struct vkms_config *config; @@ -439,10 +502,12 @@ static struct kunit_case vkms_config_test_cases[] =3D= { default_config_gen_params), KUNIT_CASE(vkms_config_test_get_planes), KUNIT_CASE(vkms_config_test_get_crtcs), + KUNIT_CASE(vkms_config_test_get_encoders), KUNIT_CASE(vkms_config_test_valid_plane_number), KUNIT_CASE(vkms_config_test_valid_plane_type), KUNIT_CASE(vkms_config_test_valid_plane_possible_crtcs), KUNIT_CASE(vkms_config_test_valid_crtc_number), + KUNIT_CASE(vkms_config_test_valid_encoder_number), KUNIT_CASE(vkms_config_test_plane_attach_crtc), KUNIT_CASE(vkms_config_test_plane_get_possible_crtcs), {} diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms= _config.c index a2ce4905589b..75e72f9b5972 100644 --- a/drivers/gpu/drm/vkms/vkms_config.c +++ b/drivers/gpu/drm/vkms/vkms_config.c @@ -23,6 +23,7 @@ struct vkms_config *vkms_config_create(const char *dev_na= me) =20 INIT_LIST_HEAD(&config->planes); INIT_LIST_HEAD(&config->crtcs); + INIT_LIST_HEAD(&config->encoders); =20 return config; } @@ -34,6 +35,7 @@ struct vkms_config *vkms_config_default_create(bool enabl= e_cursor, struct vkms_config *config; struct vkms_config_plane *plane_cfg; struct vkms_config_crtc *crtc_cfg; + struct vkms_config_encoder *encoder_cfg; int n; =20 config =3D vkms_config_create(DEFAULT_DEVICE_NAME); @@ -78,6 +80,10 @@ struct vkms_config *vkms_config_default_create(bool enab= le_cursor, goto err_alloc; } =20 + encoder_cfg =3D vkms_config_add_encoder(config); + if (IS_ERR(encoder_cfg)) + goto err_alloc; + return config; =20 err_alloc: @@ -89,6 +95,7 @@ void vkms_config_destroy(struct vkms_config *config) { struct vkms_config_plane *plane_cfg, *plane_tmp; struct vkms_config_crtc *crtc_cfg, *crtc_tmp; + struct vkms_config_encoder *encoder_cfg, *encoder_tmp; =20 list_for_each_entry_safe(plane_cfg, plane_tmp, &config->planes, link) vkms_config_destroy_plane(plane_cfg); @@ -96,6 +103,9 @@ void vkms_config_destroy(struct vkms_config *config) list_for_each_entry_safe(crtc_cfg, crtc_tmp, &config->crtcs, link) vkms_config_destroy_crtc(config, crtc_cfg); =20 + list_for_each_entry_safe(encoder_cfg, encoder_tmp, &config->encoders, lin= k) + vkms_config_destroy_encoder(config, encoder_cfg); + kfree_const(config->dev_name); kfree(config); } @@ -154,6 +164,33 @@ struct vkms_config_crtc **vkms_config_get_crtcs(const = struct vkms_config *config return array; } =20 +struct vkms_config_encoder **vkms_config_get_encoders(const struct vkms_co= nfig *config, + size_t *out_length) +{ + struct vkms_config_encoder **array; + struct vkms_config_encoder *encoder_cfg; + size_t length; + int n =3D 0; + + length =3D list_count_nodes((struct list_head *)&config->encoders); + 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); + + list_for_each_entry(encoder_cfg, &config->encoders, link) { + array[n] =3D encoder_cfg; + n++; + } + + *out_length =3D length; + return array; +} + static bool valid_plane_number(struct vkms_config *config) { size_t n_planes; @@ -238,6 +275,19 @@ static bool valid_crtc_number(struct vkms_config *conf= ig) return true; } =20 +static bool valid_encoder_number(struct vkms_config *config) +{ + size_t n_encoders; + + n_encoders =3D list_count_nodes(&config->encoders); + if (n_encoders <=3D 0 || n_encoders >=3D 32) { + pr_err("The number of encoders must be between 1 and 31\n"); + return false; + } + + return true; +} + bool vkms_config_is_valid(struct vkms_config *config) { struct vkms_config_crtc *crtc_cfg; @@ -248,6 +298,9 @@ bool vkms_config_is_valid(struct vkms_config *config) if (!valid_crtc_number(config)) return false; =20 + if (!valid_encoder_number(config)) + return false; + if (!valid_plane_possible_crtcs(config)) return false; =20 @@ -267,6 +320,7 @@ static int vkms_config_show(struct seq_file *m, void *d= ata) const char *dev_name; struct vkms_config_plane *plane_cfg; struct vkms_config_crtc *crtc_cfg; + struct vkms_config_encoder *encoder_cfg; =20 dev_name =3D vkms_config_get_device_name((struct vkms_config *)vkmsdev->c= onfig); seq_printf(m, "dev_name=3D%s\n", dev_name); @@ -283,6 +337,10 @@ static int vkms_config_show(struct seq_file *m, void *= data) vkms_config_crtc_get_writeback(crtc_cfg)); } =20 + list_for_each_entry(encoder_cfg, &vkmsdev->config->encoders, link) { + seq_puts(m, "encoder\n"); + } + return 0; } =20 @@ -436,3 +494,23 @@ struct vkms_config_plane *vkms_config_crtc_cursor_plan= e(const struct vkms_config { return vkms_config_crtc_get_plane(config, crtc_cfg, DRM_PLANE_TYPE_CURSOR= ); } + +struct vkms_config_encoder *vkms_config_add_encoder(struct vkms_config *co= nfig) +{ + struct vkms_config_encoder *encoder_cfg; + + encoder_cfg =3D kzalloc(sizeof(*encoder_cfg), GFP_KERNEL); + if (!encoder_cfg) + return ERR_PTR(-ENOMEM); + + list_add_tail(&encoder_cfg->link, &config->encoders); + + return encoder_cfg; +} + +void vkms_config_destroy_encoder(struct vkms_config *config, + struct vkms_config_encoder *encoder_cfg) +{ + list_del(&encoder_cfg->link); + kfree(encoder_cfg); +} diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms= _config.h index 1f2e6c485d08..40774d0daeac 100644 --- a/drivers/gpu/drm/vkms/vkms_config.h +++ b/drivers/gpu/drm/vkms/vkms_config.h @@ -14,12 +14,14 @@ * @dev_name: Name of the device * @planes: List of planes configured for the device * @crtcs: List of CRTCs configured for the device + * @encoders: List of encoders configured for the device * @dev: Used to store the current VKMS device. Only set when the device i= s instantiated. */ struct vkms_config { const char *dev_name; struct list_head planes; struct list_head crtcs; + struct list_head encoders; struct vkms_device *dev; }; =20 @@ -64,6 +66,22 @@ struct vkms_config_crtc { struct vkms_output *crtc; }; =20 +/** + * struct vkms_config_encoder + * + * @link: Link to the others encoders in vkms_config + * @encoder: Internal usage. This pointer should never be considered as va= lid. + * It can be used to store a temporary reference to a VKMS encod= er + * during device creation. This pointer is not managed by the + * configuration and must be managed by other means. + */ +struct vkms_config_encoder { + struct list_head link; + + /* Internal usage */ + struct drm_encoder *encoder; +}; + /** * vkms_config_create() - Create a new VKMS configuration * @dev_name: Name of the device @@ -139,6 +157,19 @@ static inline size_t vkms_config_get_num_crtcs(struct = vkms_config *config) struct vkms_config_crtc **vkms_config_get_crtcs(const struct vkms_config *= config, size_t *out_length); =20 +/** + * vkms_config_get_encoders() - Return the array of encoders of the device + * @config: Configuration to get the 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_get_encoders(const struct vkms_co= nfig *config, + size_t *out_length); + /** * vkms_config_is_valid() - Validate a configuration * @config: Configuration to validate @@ -285,4 +316,22 @@ struct vkms_config_plane *vkms_config_crtc_primary_pla= ne(const struct vkms_confi struct vkms_config_plane *vkms_config_crtc_cursor_plane(const struct vkms_= config *config, struct vkms_config_crtc *crtc_cfg); =20 +/** + * vkms_config_add_encoder() - Add a new encoder configuration + * @config: Configuration to add the encoder to + * + * Returns: + * The new encoder configuration or an error. Call vkms_config_destroy_enc= oder() + * to free the returned encoder configuration. + */ +struct vkms_config_encoder *vkms_config_add_encoder(struct vkms_config *co= nfig); + +/** + * vkms_config_destroy_encoder() - Remove and free a encoder configuration + * @config: Configuration to remove the encoder from + * @encoder_cfg: Encoder configuration to destroy + */ +void vkms_config_destroy_encoder(struct vkms_config *config, + struct vkms_config_encoder *encoder_cfg); + #endif /* _VKMS_CONFIG_H_ */ --=20 2.48.1 From nobody Mon Feb 9 13:37:03 2026 Received: from mail-wm1-f41.google.com (mail-wm1-f41.google.com [209.85.128.41]) (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 B86CD1DE2A6 for ; Wed, 29 Jan 2025 11:01:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.41 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738148482; cv=none; b=TfrrO1wal6ckSQLe/0BvCrns6sCFPOfVcscHM3bKTZIo9Kuatj2tsNL30vtpeUmFgG/59b+WGwzl6RpIhjV9HKAOWagKCOKxoml3854beVK658QvrEzzrNa7NCk+NiABHZkqjqPaA8+fOtpn29ZEIoDt4bVOm1ztw8Q2VcCQIGI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738148482; c=relaxed/simple; bh=WcK3+2qaI5RkQ9dXgCr1e3FA6fR953Aus8J0mF4a6JA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Eno/qA+7GcnNwYIM+9Ga6lv1pDqYZVoqR7q9bIem3NNC9QaP/jRvgUzpVjEWmp1p0pWUll+aUPtjtxVbXvTk9LuLUjmDkrMf8/bHAoKCx+8WGs0Q0CkruTSvoMnRCjahlTKWTH+8OeLe4ms6UCe3l9sQt32zaHHfMmlnlO7N5Ng= 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=DYgV92PU; arc=none smtp.client-ip=209.85.128.41 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="DYgV92PU" Received: by mail-wm1-f41.google.com with SMTP id 5b1f17b1804b1-4361f65ca01so70275885e9.1 for ; Wed, 29 Jan 2025 03:01:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1738148478; x=1738753278; 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=3ctx3bBvh7dKYn9+bYFpGOwRx0uhS4Evu/DJfS35toY=; b=DYgV92PU09x8nulogQhLmWJpunyqT21IJMfFItVwqjXzKo7IfiDM5BIvvh23xRgwML bfyq2nPF3jFHFCdI0ZR/A6aWusu9E6Bj3K87GiYzRzqSgAsKg3eeV1EOa5DiwT0zqbCv Xy3e8CLgsSnSdkrnG6ewA+VWH5aJWChVIQf4zAG4C/uz1pfMHyNvBG+Ml9+N6QcmebLX j6cv3QF+VIf4mqmtxfCnIewGWDU3Vn5eZEbqn3ybPSC2TMbkXFXBfeJybdQCIFNCGH7N X9mFVsvpjbBjtmJBgFd8sVSYGedvI6SBJv2RdGMDaYBA7/PzPLKpy5SXryu8UlD9xZBF 717Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1738148478; x=1738753278; 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=3ctx3bBvh7dKYn9+bYFpGOwRx0uhS4Evu/DJfS35toY=; b=q4Bh6ElrlawgcAMtUmUNLObNTBaWwToa5CVUviSZI2YLxyn9x3g2Q2N/HkvRohnKp5 oIhyTL3+pbnG4lvbbPnp8eQ67tKy2OQJfxVcIdnpMm93S8/xYzJtOJ1Cd4pNplRCbkui loW3KcbORwvMwZJlBbFng5IDkA5rHn+LDTs+hEuxnhUzupoh5hoLczhl80vt3yn4Y4Z4 xXDRh+W56XgkTZdZSbJ5ybisjvTq1DTf9VNLhtYBpVUq2i83aPE5r23RbPnqIDnHlYo/ /34uo79BWG/5ReQIIUc2y2TyC0HX6MX0DtkVNOTGp5hedOXTww2QqqvzAIMCwutmbU6y DrXQ== X-Forwarded-Encrypted: i=1; AJvYcCUjs086KYtDvPkDKcgECURLyhxy/2wXpm0icVyWDs++QAAyT7NniRNzhg6+3X9qtoko57bxsI66LUc9Yxc=@vger.kernel.org X-Gm-Message-State: AOJu0Ywaz7+ihMHKswniNRET6igbLY5zAcIjJ0ZcTGUr2ycnPMp+Y3SW 15CwAozP0dMTgO9nSpkcl3/WllfSrhPVlccYTngms02lK1r+4wGm X-Gm-Gg: ASbGnct9wIQ8t/Y6MJEnaJjYNjk6nkXGtPWKdDkT8IJlzYYRWm8SkDCbT90cFUhqFrQ 05g20XujFbPrpJfduYSwzvhRdNw9MIkAJ1bXFHNTlRpVCBz4U7eHTYDXoQeCdp7FOOde2+Nkcrl 30vVBkiw9oGMsyoVCd3F8kVIKYth2J9UqQqDcutseBwkCzd2n4LZIiJVUxqepMH4AGCi6mVTYj6 tYbQ2WxRwY6CnIPp8LiRhSdUDtyULBohDKN3uLNlX/xivl9CGVAxLHllpKOzYB/yl7oH2WShTYY ECrRljg7FXOZaoRpp9EoHupKxgk= X-Google-Smtp-Source: AGHT+IGwOpnYkfxSC17PNmKgDXS/E15tZQhZiHk1BMlGNoe2KSpGP7el/jfnz4r9qDPjkJ51kbuApg== X-Received: by 2002:a05:600c:1d1e:b0:434:a90b:94fe with SMTP id 5b1f17b1804b1-438dc3c2608mr23253225e9.10.1738148477437; Wed, 29 Jan 2025 03:01:17 -0800 (PST) Received: from fedora.. ([94.73.37.161]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-38c2a176434sm16947113f8f.13.2025.01.29.03.01.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Jan 2025 03:01:17 -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 11/13] drm/vkms: Allow to attach encoders and CRTCs Date: Wed, 29 Jan 2025 12:00:57 +0100 Message-ID: <20250129110059.12199-12-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 CRTCs to the encoder configuration and helpers to attach and detach them. Now that the default configuration has its encoder and CRTC correctly attached, 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 | 112 ++++++++++++++++++ drivers/gpu/drm/vkms/vkms_config.c | 106 +++++++++++++++++ drivers/gpu/drm/vkms/vkms_config.h | 33 ++++++ drivers/gpu/drm/vkms/vkms_output.c | 64 +++++++--- 4 files changed, 299 insertions(+), 16 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 6c09363d9a96..27d44315c2de 100644 --- a/drivers/gpu/drm/vkms/tests/vkms_config_test.c +++ b/drivers/gpu/drm/vkms/tests/vkms_config_test.c @@ -244,6 +244,7 @@ static void vkms_config_test_valid_plane_type(struct ku= nit *test) struct vkms_config *config; struct vkms_config_plane *plane_cfg; struct vkms_config_crtc *crtc_cfg; + struct vkms_config_encoder *encoder_cfg; int err; =20 config =3D vkms_config_default_create(false, false, false); @@ -297,6 +298,9 @@ static void vkms_config_test_valid_plane_type(struct ku= nit *test) =20 /* Invalid: Second CRTC without primary plane */ crtc_cfg =3D vkms_config_add_crtc(config); + encoder_cfg =3D vkms_config_add_encoder(config); + err =3D vkms_config_encoder_attach_crtc(encoder_cfg, crtc_cfg); + KUNIT_EXPECT_EQ(test, err, 0); KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config)); =20 /* Valid: Second CRTC with a primary plane */ @@ -374,6 +378,51 @@ static void vkms_config_test_valid_encoder_number(stru= ct kunit *test) vkms_config_destroy(config); } =20 +static void vkms_config_test_valid_encoder_possible_crtcs(struct kunit *te= st) +{ + struct vkms_config *config; + struct vkms_config_plane *plane_cfg; + struct vkms_config_crtc *crtc_cfg1, *crtc_cfg2; + struct vkms_config_encoder *encoder_cfg; + int err; + + config =3D vkms_config_default_create(false, false, false); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config); + + crtc_cfg1 =3D list_first_entry(&config->crtcs, typeof(*crtc_cfg1), link); + + /* Invalid: Encoder without a possible CRTC */ + encoder_cfg =3D vkms_config_add_encoder(config); + KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config)); + + /* Valid: Second CRTC with shared encoder */ + crtc_cfg2 =3D vkms_config_add_crtc(config); + + plane_cfg =3D vkms_config_add_plane(config); + vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_PRIMARY); + err =3D vkms_config_plane_attach_crtc(plane_cfg, crtc_cfg2); + KUNIT_EXPECT_EQ(test, err, 0); + + err =3D vkms_config_encoder_attach_crtc(encoder_cfg, crtc_cfg1); + KUNIT_EXPECT_EQ(test, err, 0); + + err =3D vkms_config_encoder_attach_crtc(encoder_cfg, crtc_cfg2); + KUNIT_EXPECT_EQ(test, err, 0); + + KUNIT_EXPECT_TRUE(test, vkms_config_is_valid(config)); + + /* Invalid: Second CRTC without encoders */ + vkms_config_encoder_detach_crtc(encoder_cfg, crtc_cfg2); + KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config)); + + /* Valid: First CRTC with 2 possible encoder */ + vkms_config_destroy_plane(plane_cfg); + vkms_config_destroy_crtc(config, crtc_cfg2); + KUNIT_EXPECT_TRUE(test, vkms_config_is_valid(config)); + + vkms_config_destroy(config); +} + static void vkms_config_test_plane_attach_crtc(struct kunit *test) { struct vkms_config *config; @@ -496,6 +545,67 @@ static void vkms_config_test_plane_get_possible_crtcs(= struct kunit *test) vkms_config_destroy(config); } =20 +static void vkms_config_test_encoder_get_possible_crtcs(struct kunit *test) +{ + struct vkms_config *config; + struct vkms_config_encoder *encoder_cfg1, *encoder_cfg2; + struct vkms_config_crtc *crtc_cfg1, *crtc_cfg2; + struct vkms_config_crtc **array; + size_t length; + int err; + + config =3D vkms_config_create("test"); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config); + + encoder_cfg1 =3D vkms_config_add_encoder(config); + encoder_cfg2 =3D vkms_config_add_encoder(config); + crtc_cfg1 =3D vkms_config_add_crtc(config); + crtc_cfg2 =3D vkms_config_add_crtc(config); + + /* No possible CRTCs */ + array =3D vkms_config_encoder_get_possible_crtcs(encoder_cfg1, &length); + KUNIT_ASSERT_EQ(test, length, 0); + KUNIT_ASSERT_NULL(test, array); + + array =3D vkms_config_encoder_get_possible_crtcs(encoder_cfg2, &length); + KUNIT_ASSERT_EQ(test, length, 0); + KUNIT_ASSERT_NULL(test, array); + + /* Encoder 1 attached to CRTC 1 and 2 */ + err =3D vkms_config_encoder_attach_crtc(encoder_cfg1, crtc_cfg1); + KUNIT_EXPECT_EQ(test, err, 0); + err =3D vkms_config_encoder_attach_crtc(encoder_cfg1, crtc_cfg2); + KUNIT_EXPECT_EQ(test, err, 0); + + array =3D vkms_config_encoder_get_possible_crtcs(encoder_cfg1, &length); + KUNIT_ASSERT_EQ(test, length, 2); + KUNIT_ASSERT_PTR_EQ(test, array[0], crtc_cfg1); + KUNIT_ASSERT_PTR_EQ(test, array[1], crtc_cfg2); + kfree(array); + + array =3D vkms_config_encoder_get_possible_crtcs(encoder_cfg2, &length); + KUNIT_ASSERT_EQ(test, length, 0); + KUNIT_ASSERT_NULL(test, array); + + /* Encoder 1 attached to CRTC 1 and encoder 2 to CRTC 2 */ + vkms_config_encoder_detach_crtc(encoder_cfg1, crtc_cfg2); + + array =3D vkms_config_encoder_get_possible_crtcs(encoder_cfg1, &length); + KUNIT_ASSERT_EQ(test, length, 1); + KUNIT_ASSERT_PTR_EQ(test, array[0], crtc_cfg1); + kfree(array); + + err =3D vkms_config_encoder_attach_crtc(encoder_cfg2, crtc_cfg2); + KUNIT_EXPECT_EQ(test, err, 0); + + array =3D vkms_config_encoder_get_possible_crtcs(encoder_cfg2, &length); + KUNIT_ASSERT_EQ(test, length, 1); + KUNIT_ASSERT_PTR_EQ(test, array[0], crtc_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, @@ -508,8 +618,10 @@ static struct kunit_case vkms_config_test_cases[] =3D { KUNIT_CASE(vkms_config_test_valid_plane_possible_crtcs), KUNIT_CASE(vkms_config_test_valid_crtc_number), KUNIT_CASE(vkms_config_test_valid_encoder_number), + KUNIT_CASE(vkms_config_test_valid_encoder_possible_crtcs), 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), {} }; =20 diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms= _config.c index 75e72f9b5972..437a9980e9a8 100644 --- a/drivers/gpu/drm/vkms/vkms_config.c +++ b/drivers/gpu/drm/vkms/vkms_config.c @@ -84,6 +84,9 @@ struct vkms_config *vkms_config_default_create(bool enabl= e_cursor, if (IS_ERR(encoder_cfg)) goto err_alloc; =20 + if (vkms_config_encoder_attach_crtc(encoder_cfg, crtc_cfg)) + goto err_alloc; + return config; =20 err_alloc: @@ -288,6 +291,40 @@ static bool valid_encoder_number(struct vkms_config *c= onfig) return true; } =20 +static bool valid_encoder_possible_crtcs(struct vkms_config *config) +{ + struct vkms_config_crtc *crtc_cfg; + struct vkms_config_encoder *encoder_cfg; + + list_for_each_entry(encoder_cfg, &config->encoders, link) { + if (xa_empty(&encoder_cfg->possible_crtcs)) { + pr_err("All encoders must have at least one possible CRTC\n"); + return false; + } + } + + list_for_each_entry(crtc_cfg, &config->crtcs, link) { + bool crtc_has_encoder =3D false; + + list_for_each_entry(encoder_cfg, &config->encoders, link) { + struct vkms_config_crtc *possible_crtc; + unsigned long idx =3D 0; + + xa_for_each(&encoder_cfg->possible_crtcs, idx, possible_crtc) { + if (possible_crtc =3D=3D crtc_cfg) + crtc_has_encoder =3D true; + } + } + + if (!crtc_has_encoder) { + pr_err("All CRTCs must have at least one possible encoder\n"); + return false; + } + } + + return true; +} + bool vkms_config_is_valid(struct vkms_config *config) { struct vkms_config_crtc *crtc_cfg; @@ -309,6 +346,9 @@ bool vkms_config_is_valid(struct vkms_config *config) return false; } =20 + if (!valid_encoder_possible_crtcs(config)) + return false; + return true; } =20 @@ -454,10 +494,14 @@ void vkms_config_destroy_crtc(struct vkms_config *con= fig, struct vkms_config_crtc *crtc_cfg) { struct vkms_config_plane *plane_cfg; + struct vkms_config_encoder *encoder_cfg; =20 list_for_each_entry(plane_cfg, &config->planes, link) vkms_config_plane_detach_crtc(plane_cfg, crtc_cfg); =20 + list_for_each_entry(encoder_cfg, &config->encoders, link) + vkms_config_encoder_detach_crtc(encoder_cfg, crtc_cfg); + list_del(&crtc_cfg->link); kfree(crtc_cfg); } @@ -503,6 +547,8 @@ struct vkms_config_encoder *vkms_config_add_encoder(str= uct vkms_config *config) if (!encoder_cfg) return ERR_PTR(-ENOMEM); =20 + xa_init_flags(&encoder_cfg->possible_crtcs, XA_FLAGS_ALLOC); + list_add_tail(&encoder_cfg->link, &config->encoders); =20 return encoder_cfg; @@ -511,6 +557,66 @@ 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) { + xa_destroy(&encoder_cfg->possible_crtcs); list_del(&encoder_cfg->link); kfree(encoder_cfg); } + +int __must_check vkms_config_encoder_attach_crtc(struct vkms_config_encode= r *encoder_cfg, + struct vkms_config_crtc *crtc_cfg) +{ + struct vkms_config_crtc *possible_crtc; + unsigned long idx =3D 0; + u32 crtc_idx =3D 0; + + xa_for_each(&encoder_cfg->possible_crtcs, idx, possible_crtc) { + if (possible_crtc =3D=3D crtc_cfg) + return -EINVAL; + } + + return xa_alloc(&encoder_cfg->possible_crtcs, &crtc_idx, crtc_cfg, + xa_limit_32b, GFP_KERNEL); +} + +void vkms_config_encoder_detach_crtc(struct vkms_config_encoder *encoder_c= fg, + struct vkms_config_crtc *crtc_cfg) +{ + struct vkms_config_crtc *possible_crtc; + unsigned long idx =3D 0; + + xa_for_each(&encoder_cfg->possible_crtcs, idx, possible_crtc) { + if (possible_crtc =3D=3D crtc_cfg) + xa_erase(&encoder_cfg->possible_crtcs, idx); + } +} + +struct vkms_config_crtc ** +vkms_config_encoder_get_possible_crtcs(struct vkms_config_encoder *encoder= _cfg, + size_t *out_length) +{ + struct vkms_config_crtc **array; + struct vkms_config_crtc *possible_crtc; + unsigned long idx; + size_t length =3D 0; + int n =3D 0; + + xa_for_each(&encoder_cfg->possible_crtcs, idx, possible_crtc) + length++; + + if (length =3D=3D 0) { + *out_length =3D 0; + return NULL; + } + + array =3D kmalloc_array(length, sizeof(*array), GFP_KERNEL); + if (!array) + return ERR_PTR(-ENOMEM); + + xa_for_each(&encoder_cfg->possible_crtcs, idx, possible_crtc) { + array[n] =3D possible_crtc; + 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 40774d0daeac..5f4a33e113bf 100644 --- a/drivers/gpu/drm/vkms/vkms_config.h +++ b/drivers/gpu/drm/vkms/vkms_config.h @@ -70,6 +70,7 @@ struct vkms_config_crtc { * struct vkms_config_encoder * * @link: Link to the others encoders in vkms_config + * @possible_crtcs: Array of CRTCs that can be used with this encoder * @encoder: Internal usage. This pointer should never be considered as va= lid. * It can be used to store a temporary reference to a VKMS encod= er * during device creation. This pointer is not managed by the @@ -78,6 +79,8 @@ struct vkms_config_crtc { struct vkms_config_encoder { struct list_head link; =20 + struct xarray possible_crtcs; + /* Internal usage */ struct drm_encoder *encoder; }; @@ -334,4 +337,34 @@ 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); =20 +/** + * vkms_config_encoder_attach_crtc - Attach a encoder to a CRTC + * @encoder_cfg: Encoder to attach + * @crtc_cfg: CRTC to attach @encoder_cfg to + */ +int __must_check vkms_config_encoder_attach_crtc(struct vkms_config_encode= r *encoder_cfg, + struct vkms_config_crtc *crtc_cfg); + +/** + * vkms_config_encoder_detach_crtc - Detach a encoder from a CRTC + * @encoder_cfg: Encoder to detach + * @crtc_cfg: CRTC to detach @encoder_cfg from + */ +void vkms_config_encoder_detach_crtc(struct vkms_config_encoder *encoder_c= fg, + struct vkms_config_crtc *crtc_cfg); + +/** + * vkms_config_encoder_get_possible_crtcs() - Return the array of possible= CRTCs + * @encoder_cfg: Encoder to get the possible CRTCs 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_crtc ** +vkms_config_encoder_get_possible_crtcs(struct vkms_config_encoder *encoder= _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 427d0aad8901..9c3e00817add 100644 --- a/drivers/gpu/drm/vkms/vkms_output.c +++ b/drivers/gpu/drm/vkms/vkms_output.c @@ -9,11 +9,12 @@ int vkms_output_init(struct vkms_device *vkmsdev) { struct drm_device *dev =3D &vkmsdev->drm; struct vkms_connector *connector; - struct drm_encoder *encoder; 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; int ret =3D 0; int writeback; unsigned int n, i; @@ -28,6 +29,12 @@ int vkms_output_init(struct vkms_device *vkmsdev) goto err_free; } =20 + encoder_cfgs =3D vkms_config_get_encoders(vkmsdev->config, &n_encoders); + if (IS_ERR(encoder_cfgs)) { + ret =3D PTR_ERR(encoder_cfgs); + goto err_free; + } + for (n =3D 0; n < n_planes; n++) { struct vkms_config_plane *plane_cfg; enum drm_plane_type type; @@ -91,6 +98,44 @@ int vkms_output_init(struct vkms_device *vkmsdev) kfree(possible_crtcs); } =20 + for (n =3D 0; n < n_encoders; n++) { + struct vkms_config_encoder *encoder_cfg; + struct vkms_config_crtc **possible_crtcs; + size_t n_possible_crtcs; + + encoder_cfg =3D encoder_cfgs[n]; + + encoder_cfg->encoder =3D drmm_kzalloc(dev, sizeof(*encoder_cfg->encoder)= , GFP_KERNEL); + if (!encoder_cfg->encoder) { + DRM_ERROR("Failed to allocate encoder\n"); + ret =3D -ENOMEM; + goto err_free; + } + ret =3D drmm_encoder_init(dev, encoder_cfg->encoder, NULL, + DRM_MODE_ENCODER_VIRTUAL, NULL); + if (ret) { + DRM_ERROR("Failed to init encoder\n"); + goto err_free; + } + + possible_crtcs =3D vkms_config_encoder_get_possible_crtcs(encoder_cfg, + &n_possible_crtcs); + if (IS_ERR(possible_crtcs)) { + ret =3D PTR_ERR(possible_crtcs); + goto err_free; + } + + for (i =3D 0; i < n_possible_crtcs; i++) { + struct vkms_config_crtc *possible_crtc; + + possible_crtc =3D possible_crtcs[i]; + encoder_cfg->encoder->possible_crtcs |=3D + drm_crtc_mask(&possible_crtc->crtc->crtc); + } + + kfree(possible_crtcs); + } + connector =3D vkms_connector_init(vkmsdev); if (IS_ERR(connector)) { DRM_ERROR("Failed to init connector\n"); @@ -98,22 +143,8 @@ int vkms_output_init(struct vkms_device *vkmsdev) goto err_free; } =20 - encoder =3D drmm_kzalloc(dev, sizeof(*encoder), GFP_KERNEL); - if (!encoder) { - DRM_ERROR("Failed to allocate encoder\n"); - ret =3D -ENOMEM; - goto err_free; - } - ret =3D drmm_encoder_init(dev, encoder, NULL, - DRM_MODE_ENCODER_VIRTUAL, NULL); - if (ret) { - DRM_ERROR("Failed to init encoder\n"); - goto err_free; - } - encoder->possible_crtcs =3D drm_crtc_mask(&crtc_cfgs[0]->crtc->crtc); - /* Attach the encoder and the connector */ - ret =3D drm_connector_attach_encoder(&connector->base, encoder); + 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; @@ -124,6 +155,7 @@ int vkms_output_init(struct vkms_device *vkmsdev) err_free: kfree(plane_cfgs); kfree(crtc_cfgs); + kfree(encoder_cfgs); =20 return ret; } --=20 2.48.1 From nobody Mon Feb 9 13:37:03 2026 Received: from mail-wr1-f51.google.com (mail-wr1-f51.google.com [209.85.221.51]) (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 A3E4E1B6CE8 for ; Wed, 29 Jan 2025 11:01:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738148483; cv=none; b=CpOdrA0E+qDp/uyFvclQrR9MRVOIqnZZ3EUsydB0pWlGh52j7TsRZIsAsc5NELvcGXX4M/bgpXUahPd8Z3VevySDCehL34wdwNBaWW5CS++eHBbGQYxs5Xs9MYhHFt1hHw6IMvo+r0PfapTwljgnChkXjNHOsmn7eMWFwHThoXQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738148483; c=relaxed/simple; bh=bwkOgbSp2DlzaYVVLPsg1YWMggL4kTAYXaaduWdo1to=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=UKyMF4ss9B9kH6gYh7L1Tm2IfK88PtH6cCrQI+5DvmKnDLXq7Z/S7jIB2dLQTEsrJzp1muYNKYgHHINDsXzryjwDfC4eFryHaGYL4xbql7GzexAFX2dpCQh1A8M1jEou1UR3mNQS55h/uYmJNkPcVUZg4tpwf0j5xOtHd65uLmw= 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=mmmXFfFS; arc=none smtp.client-ip=209.85.221.51 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="mmmXFfFS" Received: by mail-wr1-f51.google.com with SMTP id ffacd0b85a97d-385e27c75f4so5825425f8f.2 for ; Wed, 29 Jan 2025 03:01:20 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1738148479; x=1738753279; 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=XUpkYP/tGsoAbjn0vsUGNcgy0Vg9vALDj5dfocC1jjo=; b=mmmXFfFSIW1heV/gXGnhfS/v2Lee4QCne1usNk2fNPn5WwX3wEKlyoyCzNMzcveEnd YcVHLyCf3RmJ9N7s2PiOi+R5Et+ONGOe8aQxwL+90cdwHDpugRPNFmOUE105wHSm94Rk L4UHZSaiW9caDng2U8LuhVGonsqBM4Q0WAbnV3fAdQ4RSw7B6iMpuYMGNC4O4SRDxHhT ChQd8dqVa0+X4aHuWS26hV/zW8V3C/VybsTw+l5p+GFgZxqVJ7hbYjj605xhwxLK6Xej XgVfL0DTmSk66xv8A+0TMx7k9G4PVswKNThYhEkHB9K0JeZUR4H/lQSqsexsBybFC2Yj u1SQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1738148479; x=1738753279; 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=XUpkYP/tGsoAbjn0vsUGNcgy0Vg9vALDj5dfocC1jjo=; b=AgpdgA8jc9hbBb0M14J4i4isNlPqHlHY8yfYqy+40ikoUtz3/Y/JexsKVEP2Fp0Gk/ c/uXeuYtcCn8Vg6aWfmSM6x208QY8tihd+z/f+ZkSDi5XCVIEAcnKp1NTVSzhivLy+Lq 80/LBwDyVCXcv4z/wCRs6ojCus9xp/Pb7cbByIYes3DkikLU4bvMLwPsSpl4CNd6NIGd bXc6Y0n9ZRGWkI2J387HWVfvcthitrowEJgVNy+Bhvw65lXHtwIhiZL99Q4TjzRNF4co n4hEehzmWPi8A/NqR3AShpRvXSORgR0OPsOhJ/2CGPG89/GeRjUop6EUUb3crAQBfofx eiVA== X-Forwarded-Encrypted: i=1; AJvYcCXHG68wJwozyKGdqSxAEENKCun/RUXGRmkjIgqQxLfIImY5Uz2wC9DS+9BkA8WXiCwNqmJc17TYN7ay3Is=@vger.kernel.org X-Gm-Message-State: AOJu0YwSbPiUTsQB3uUt/NTx+ZdRVm0WEJhBPJtG8wZDR0shLVJOelTW Oo2wdkdEk9MSjsudNz2lxhMBa3c2U4NQIk96NdJVYHPnrFO20VY+ X-Gm-Gg: ASbGncsDtdwr0y7/PubdWx2N3EOUiGIANAoQDZ+9eceT7CyU3SZllebiD62S+lmkN0R 02wDiPhO207UAJKu7/Ldk7tts/QMStdcWox531gkIsKQdAtppjQr39tuLjcG982p9R30jfzbigQ bG24Br3tfbXCRQwUyvNfVEVslNOX+Mx+EWAW45MlccoakwAZpweXx9iTBHrhCzxb6OCY/KGQ5Nq vFOVVUjWEXmvU0w5hqK1TBJlOgA/A69j2xVtkTbxJcPVToQ4pbi14FSIZXB7GXyTBy90T90Tb0h PmLWGwpoSUB1WXAu40JMCjlgeTM= X-Google-Smtp-Source: AGHT+IEt/RU5BgHN4IuQXOAUZYIJmz+x4OCgxOMAFdg/eovjklOwz0AsxWcDE4GbtSVBFa+HrggMRA== X-Received: by 2002:a5d:5988:0:b0:385:fd07:8616 with SMTP id ffacd0b85a97d-38c5167d80bmr2164396f8f.0.1738148478451; Wed, 29 Jan 2025 03:01:18 -0800 (PST) Received: from fedora.. ([94.73.37.161]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-38c2a176434sm16947113f8f.13.2025.01.29.03.01.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Jan 2025 03:01:17 -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 12/13] drm/vkms: Allow to configure multiple connectors Date: Wed, 29 Jan 2025 12:00:58 +0100 Message-ID: <20250129110059.12199-13-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 connectors to vkms_config and helper functions to add and remove as many connectors as wanted. Unlike planes, CRTCs and encoders, connectors can be added and removed once the device is created. To reflect it, add an "enabled" flag in the configuration and filter disabled connectors in the vkms_config_get_connectors() function. For the moment, changing the enabled status of the connector has no effect after the device is created, but a future patch will add this capability. For backwards compatibility, add one enabled connector to the default configuration. A future patch will allow to attach connectors and encoders, but for the moment there are no changes in the way the output is configured. Signed-off-by: Louis Chauvet Signed-off-by: Jos=C3=A9 Exp=C3=B3sito --- drivers/gpu/drm/vkms/tests/vkms_config_test.c | 84 +++++++++++++++++ drivers/gpu/drm/vkms/vkms_config.c | 93 +++++++++++++++++++ drivers/gpu/drm/vkms/vkms_config.h | 76 +++++++++++++++ drivers/gpu/drm/vkms/vkms_connector.c | 11 +++ 4 files changed, 264 insertions(+) diff --git a/drivers/gpu/drm/vkms/tests/vkms_config_test.c b/drivers/gpu/dr= m/vkms/tests/vkms_config_test.c index 27d44315c2de..40c385eedc1d 100644 --- a/drivers/gpu/drm/vkms/tests/vkms_config_test.c +++ b/drivers/gpu/drm/vkms/tests/vkms_config_test.c @@ -27,6 +27,7 @@ static void vkms_config_test_empty_config(struct kunit *t= est) KUNIT_EXPECT_TRUE(test, list_empty(&config->planes)); KUNIT_EXPECT_TRUE(test, list_empty(&config->crtcs)); KUNIT_EXPECT_TRUE(test, list_empty(&config->encoders)); + KUNIT_EXPECT_TRUE(test, list_empty(&config->connectors)); =20 KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config)); =20 @@ -52,6 +53,7 @@ static void vkms_config_test_default_config(struct kunit = *test) struct vkms_config *config; struct vkms_config_plane *plane_cfg; struct vkms_config_crtc *crtc_cfg; + struct vkms_config_connector *connector_cfg; int n_primaries =3D 0; int n_cursors =3D 0; int n_overlays =3D 0; @@ -103,6 +105,12 @@ static void vkms_config_test_default_config(struct kun= it *test) /* Encoders */ KUNIT_EXPECT_EQ(test, list_count_nodes(&config->encoders), 1); =20 + /* Connectors */ + KUNIT_EXPECT_EQ(test, list_count_nodes(&config->connectors), 1); + connector_cfg =3D list_first_entry(&config->connectors, + typeof(*connector_cfg), link); + KUNIT_EXPECT_TRUE(test, vkms_config_connector_is_enabled(connector_cfg)); + KUNIT_EXPECT_TRUE(test, vkms_config_is_valid(config)); =20 vkms_config_destroy(config); @@ -216,6 +224,47 @@ static void vkms_config_test_get_encoders(struct kunit= *test) vkms_config_destroy(config); } =20 +static void vkms_config_test_get_connectors(struct kunit *test) +{ + struct vkms_config *config; + struct vkms_config_connector *connector_cfg1, *connector_cfg2; + struct vkms_config_connector **array; + size_t length; + + config =3D vkms_config_create("test"); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config); + + array =3D vkms_config_get_connectors(config, &length); + KUNIT_ASSERT_EQ(test, length, 0); + KUNIT_ASSERT_NULL(test, array); + + connector_cfg1 =3D vkms_config_add_connector(config); + array =3D vkms_config_get_connectors(config, &length); + KUNIT_ASSERT_EQ(test, length, 0); + KUNIT_ASSERT_NULL(test, array); + + vkms_config_connector_set_enabled(connector_cfg1, true); + array =3D vkms_config_get_connectors(config, &length); + KUNIT_ASSERT_EQ(test, length, 1); + KUNIT_ASSERT_PTR_EQ(test, array[0], connector_cfg1); + kfree(array); + + connector_cfg2 =3D vkms_config_add_connector(config); + vkms_config_connector_set_enabled(connector_cfg2, true); + array =3D vkms_config_get_connectors(config, &length); + KUNIT_ASSERT_EQ(test, length, 2); + KUNIT_ASSERT_PTR_EQ(test, array[0], connector_cfg1); + KUNIT_ASSERT_PTR_EQ(test, array[1], connector_cfg2); + kfree(array); + + vkms_config_connector_set_enabled(connector_cfg1, false); + vkms_config_destroy_connector(connector_cfg2); + array =3D vkms_config_get_connectors(config, &length); + KUNIT_ASSERT_NULL(test, array); + + vkms_config_destroy(config); +} + static void vkms_config_test_valid_plane_number(struct kunit *test) { struct vkms_config *config; @@ -423,6 +472,39 @@ static void vkms_config_test_valid_encoder_possible_cr= tcs(struct kunit *test) vkms_config_destroy(config); } =20 +static void vkms_config_test_valid_connector_number(struct kunit *test) +{ + struct vkms_config *config; + struct vkms_config_connector *connector_cfg; + int n; + + config =3D vkms_config_default_create(false, false, false); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config); + + /* Valid: No connectors */ + connector_cfg =3D list_first_entry(&config->connectors, typeof(*connector= _cfg), link); + vkms_config_destroy_connector(connector_cfg); + KUNIT_EXPECT_TRUE(test, vkms_config_is_valid(config)); + + /* Valid: Only a disabled connector */ + connector_cfg =3D vkms_config_add_connector(config); + KUNIT_EXPECT_TRUE(test, vkms_config_is_valid(config)); + + /* Valid: The connector is enabled */ + vkms_config_connector_set_enabled(connector_cfg, true); + KUNIT_EXPECT_TRUE(test, vkms_config_is_valid(config)); + + /* Invalid: Too many connectors */ + for (n =3D 0; n <=3D 32; n++) { + connector_cfg =3D vkms_config_add_connector(config); + vkms_config_connector_set_enabled(connector_cfg, true); + } + + KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config)); + + vkms_config_destroy(config); +} + static void vkms_config_test_plane_attach_crtc(struct kunit *test) { struct vkms_config *config; @@ -613,12 +695,14 @@ static struct kunit_case vkms_config_test_cases[] =3D= { KUNIT_CASE(vkms_config_test_get_planes), KUNIT_CASE(vkms_config_test_get_crtcs), KUNIT_CASE(vkms_config_test_get_encoders), + KUNIT_CASE(vkms_config_test_get_connectors), KUNIT_CASE(vkms_config_test_valid_plane_number), KUNIT_CASE(vkms_config_test_valid_plane_type), KUNIT_CASE(vkms_config_test_valid_plane_possible_crtcs), KUNIT_CASE(vkms_config_test_valid_crtc_number), KUNIT_CASE(vkms_config_test_valid_encoder_number), KUNIT_CASE(vkms_config_test_valid_encoder_possible_crtcs), + KUNIT_CASE(vkms_config_test_valid_connector_number), 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), diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms= _config.c index 437a9980e9a8..e94e48fe3ad9 100644 --- a/drivers/gpu/drm/vkms/vkms_config.c +++ b/drivers/gpu/drm/vkms/vkms_config.c @@ -24,6 +24,7 @@ struct vkms_config *vkms_config_create(const char *dev_na= me) INIT_LIST_HEAD(&config->planes); INIT_LIST_HEAD(&config->crtcs); INIT_LIST_HEAD(&config->encoders); + INIT_LIST_HEAD(&config->connectors); =20 return config; } @@ -36,6 +37,7 @@ struct vkms_config *vkms_config_default_create(bool enabl= e_cursor, struct vkms_config_plane *plane_cfg; struct vkms_config_crtc *crtc_cfg; struct vkms_config_encoder *encoder_cfg; + struct vkms_config_connector *connector_cfg; int n; =20 config =3D vkms_config_create(DEFAULT_DEVICE_NAME); @@ -87,6 +89,11 @@ struct vkms_config *vkms_config_default_create(bool enab= le_cursor, if (vkms_config_encoder_attach_crtc(encoder_cfg, crtc_cfg)) goto err_alloc; =20 + connector_cfg =3D vkms_config_add_connector(config); + if (IS_ERR(connector_cfg)) + goto err_alloc; + vkms_config_connector_set_enabled(connector_cfg, true); + return config; =20 err_alloc: @@ -99,6 +106,7 @@ void vkms_config_destroy(struct vkms_config *config) struct vkms_config_plane *plane_cfg, *plane_tmp; struct vkms_config_crtc *crtc_cfg, *crtc_tmp; struct vkms_config_encoder *encoder_cfg, *encoder_tmp; + struct vkms_config_connector *connector_cfg, *connector_tmp; =20 list_for_each_entry_safe(plane_cfg, plane_tmp, &config->planes, link) vkms_config_destroy_plane(plane_cfg); @@ -109,6 +117,9 @@ void vkms_config_destroy(struct vkms_config *config) list_for_each_entry_safe(encoder_cfg, encoder_tmp, &config->encoders, lin= k) vkms_config_destroy_encoder(config, encoder_cfg); =20 + list_for_each_entry_safe(connector_cfg, connector_tmp, &config->connector= s, link) + vkms_config_destroy_connector(connector_cfg); + kfree_const(config->dev_name); kfree(config); } @@ -194,6 +205,39 @@ struct vkms_config_encoder **vkms_config_get_encoders(= const struct vkms_config * return array; } =20 +struct vkms_config_connector **vkms_config_get_connectors(const struct vkm= s_config *config, + size_t *out_length) +{ + struct vkms_config_connector **array; + struct vkms_config_connector *connector_cfg; + size_t length =3D 0; + int n =3D 0; + + list_for_each_entry(connector_cfg, &config->connectors, link) { + if (vkms_config_connector_is_enabled(connector_cfg)) + 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); + + list_for_each_entry(connector_cfg, &config->connectors, link) { + if (vkms_config_connector_is_enabled(connector_cfg)) { + array[n] =3D connector_cfg; + n++; + } + } + + *out_length =3D length; + return array; +} + static bool valid_plane_number(struct vkms_config *config) { size_t n_planes; @@ -325,6 +369,24 @@ static bool valid_encoder_possible_crtcs(struct vkms_c= onfig *config) return true; } =20 +static bool valid_connector_number(struct vkms_config *config) +{ + struct vkms_config_connector *connector_cfg; + size_t n_connectors =3D 0; + + list_for_each_entry(connector_cfg, &config->connectors, link) { + if (vkms_config_connector_is_enabled(connector_cfg)) + n_connectors++; + } + + if (n_connectors >=3D 32) { + pr_err("The number of connectors must be between 0 and 31\n"); + return false; + } + + return true; +} + bool vkms_config_is_valid(struct vkms_config *config) { struct vkms_config_crtc *crtc_cfg; @@ -338,6 +400,9 @@ bool vkms_config_is_valid(struct vkms_config *config) if (!valid_encoder_number(config)) return false; =20 + if (!valid_connector_number(config)) + return false; + if (!valid_plane_possible_crtcs(config)) return false; =20 @@ -361,6 +426,7 @@ static int vkms_config_show(struct seq_file *m, void *d= ata) struct vkms_config_plane *plane_cfg; struct vkms_config_crtc *crtc_cfg; struct vkms_config_encoder *encoder_cfg; + struct vkms_config_connector *connector_cfg; =20 dev_name =3D vkms_config_get_device_name((struct vkms_config *)vkmsdev->c= onfig); seq_printf(m, "dev_name=3D%s\n", dev_name); @@ -381,6 +447,12 @@ static int vkms_config_show(struct seq_file *m, void *= data) seq_puts(m, "encoder\n"); } =20 + list_for_each_entry(connector_cfg, &vkmsdev->config->connectors, link) { + seq_puts(m, "connector:\n"); + seq_printf(m, "\tenabled=3D%d\n", + vkms_config_connector_is_enabled(connector_cfg)); + } + return 0; } =20 @@ -620,3 +692,24 @@ vkms_config_encoder_get_possible_crtcs(struct vkms_con= fig_encoder *encoder_cfg, *out_length =3D length; return array; } + +struct vkms_config_connector *vkms_config_add_connector(struct vkms_config= *config) +{ + struct vkms_config_connector *connector_cfg; + + connector_cfg =3D kzalloc(sizeof(*connector_cfg), GFP_KERNEL); + if (!connector_cfg) + return ERR_PTR(-ENOMEM); + + vkms_config_connector_set_enabled(connector_cfg, false); + + list_add_tail(&connector_cfg->link, &config->connectors); + + return connector_cfg; +} + +void vkms_config_destroy_connector(struct vkms_config_connector *connector= _cfg) +{ + list_del(&connector_cfg->link); + kfree(connector_cfg); +} diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms= _config.h index 5f4a33e113bf..cc32aadfda8d 100644 --- a/drivers/gpu/drm/vkms/vkms_config.h +++ b/drivers/gpu/drm/vkms/vkms_config.h @@ -15,6 +15,7 @@ * @planes: List of planes configured for the device * @crtcs: List of CRTCs configured for the device * @encoders: List of encoders configured for the device + * @connectors: List of connectors configured for the device * @dev: Used to store the current VKMS device. Only set when the device i= s instantiated. */ struct vkms_config { @@ -22,6 +23,7 @@ struct vkms_config { struct list_head planes; struct list_head crtcs; struct list_head encoders; + struct list_head connectors; struct vkms_device *dev; }; =20 @@ -85,6 +87,27 @@ struct vkms_config_encoder { struct drm_encoder *encoder; }; =20 +/** + * struct vkms_config_connector + * + * @link: Link to the others connector in vkms_config + * @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. + * @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 + * configuration and must be managed by other means. + */ +struct vkms_config_connector { + struct list_head link; + + bool enabled; + + /* Internal usage */ + struct vkms_connector *connector; +}; + /** * vkms_config_create() - Create a new VKMS configuration * @dev_name: Name of the device @@ -173,6 +196,21 @@ struct vkms_config_crtc **vkms_config_get_crtcs(const = struct vkms_config *config struct vkms_config_encoder **vkms_config_get_encoders(const struct vkms_co= nfig *config, size_t *out_length); =20 +/** + * vkms_config_get_connectors() - Return the array of connectors of the de= vice + * @config: Configuration to get the connectors from + * @out_length: Length of the returned array + * + * Note that only enabled connectors are returned. + * + * 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_connector **vkms_config_get_connectors(const struct vkm= s_config *config, + size_t *out_length); + /** * vkms_config_is_valid() - Validate a configuration * @config: Configuration to validate @@ -367,4 +405,42 @@ struct vkms_config_crtc ** vkms_config_encoder_get_possible_crtcs(struct vkms_config_encoder *encoder= _cfg, size_t *out_length); =20 +/** + * vkms_config_add_connector() - Add a new connector configuration + * @config: Configuration to add the connector to + * + * Returns: + * The new connector configuration or an error. Call + * vkms_config_destroy_connector() to free the returned connector configur= ation. + */ +struct vkms_config_connector *vkms_config_add_connector(struct vkms_config= *config); + +/** + * vkms_config_destroy_connector() - Remove and free a connector configura= tion + * @connector_cfg: Connector configuration to destroy + */ +void vkms_config_destroy_connector(struct vkms_config_connector *connector= _cfg); + +/** + * vkms_config_connector_is_enabled() - If the connector is part of the de= vice + * @connector_cfg: The connector + */ +static inline bool +vkms_config_connector_is_enabled(struct vkms_config_connector *connector_c= fg) +{ + return connector_cfg->enabled; +} + +/** + * vkms_config_connector_set_enabled() - If the connector is part of the d= evice + * @crtc_cfg: Target connector + * @enabled: Add or remove the connector + */ +static inline void +vkms_config_connector_set_enabled(struct vkms_config_connector *connector_= cfg, + bool enabled) +{ + connector_cfg->enabled =3D enabled; +} + #endif /* _VKMS_CONFIG_H_ */ diff --git a/drivers/gpu/drm/vkms/vkms_connector.c b/drivers/gpu/drm/vkms/v= kms_connector.c index ab8b52a84151..48b10cba322a 100644 --- a/drivers/gpu/drm/vkms/vkms_connector.c +++ b/drivers/gpu/drm/vkms/vkms_connector.c @@ -25,8 +25,19 @@ static int vkms_conn_get_modes(struct drm_connector *con= nector) return count; } =20 +static struct drm_encoder *vkms_conn_best_encoder(struct drm_connector *co= nnector) +{ + struct drm_encoder *encoder; + + drm_connector_for_each_possible_encoder(connector, encoder) + return encoder; + + return NULL; +} + static const struct drm_connector_helper_funcs vkms_conn_helper_funcs =3D { .get_modes =3D vkms_conn_get_modes, + .best_encoder =3D vkms_conn_best_encoder, }; =20 struct vkms_connector *vkms_connector_init(struct vkms_device *vkmsdev) --=20 2.48.1 From nobody Mon Feb 9 13:37:03 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