From nobody Thu Dec 18 10:36:55 2025 Received: from mail-wr1-f47.google.com (mail-wr1-f47.google.com [209.85.221.47]) (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 773ED23717F for ; Tue, 18 Feb 2025 10:12:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.47 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739873546; cv=none; b=fCo9i3XCviFX6FCwd5pxBLkuGJYZta2NUp+Saf3gr0SmSiMejzWcinl8x4LSSr2JvwXjJ9xvTgNcD8Uo4WCAOh7WbjtAPduN2QnaXFXbcwEFU/qGTTxxzpwOF0stTAruPaXsFgeb/bBSQ6v0a8pEkl31oGBqht21g6w6soNN1G8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739873546; c=relaxed/simple; bh=sC9Zaw3ndAVo+oHrEyc64S6eUMv2Ld/tFQLViNUAGL8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=hdLl7yeyDfOLhdGkvzpyBrg88rDT+srSLQ+4k0NJfGRIvSrGF80ba79SobzIZNQ2/jDDJ4GhyUEE3beSxKO/pcCanvyE4XnGfx//0opV0hG19zm02WumDiu98PRukD2ZdL0iLMRP+TTaKMu+eAKO1Jzdad0R9s7O+C/KGVf60oU= 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=XnEDtJQi; arc=none smtp.client-ip=209.85.221.47 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="XnEDtJQi" Received: by mail-wr1-f47.google.com with SMTP id ffacd0b85a97d-38f31f7732dso2046156f8f.1 for ; Tue, 18 Feb 2025 02:12:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1739873543; x=1740478343; 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=T6WlJ6G+D4bbUKndbktll+9YSW21OZOtswUdeB6r15c=; b=XnEDtJQiCfwK0XSMEHFJ33aO7ptB/DwT6DsqoVJnnfVBxalPInh9M3duFN0gJ7iP5E y8mPZj9fPVhyitAOLLvVR3j+9EDAugz17yUGKMaWcSp5xOv9Z2kLeYGMJwqCqpPtqBDO e/xIKhu5nvaT8WjNaxiZ9lzc2/NY8zH0eQQFfZ1J3FTUGlSGZ99OUU3W6rTBjUPMpG5H vswrHnZmCFOl3G+ViPnFbokqxopTQbEyhYwUSLcXk0+Mly86iIjCJjC4HAyBYvIYgMFy uS3Z0qGfv6FQUrl2XZ2rIEVNF66fkVfnXMwbUG8EL3yOoiXbOjKRkZJFtpl9/aoC0BWH Gbkw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1739873543; x=1740478343; 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=T6WlJ6G+D4bbUKndbktll+9YSW21OZOtswUdeB6r15c=; b=KViYEYcCYKSqVaIn5LWzaXv2zNh34hiqvHO62hq4UMBaYwfngJLDR/tEVTJYkN/wAr ckbQl2gIUoeyGX1uoPGigpCqccdna3O9pLfHagMn0yWbRzdaf3sJ9UBl71u6KM9sII1G skAPCMPC+jSwoDEhNKDes0G7Eo//Ww3tCADVWw3pDg8vLtZKPJcbwPZrl2qhbfftudNa jfxAQaMAIkVCGp8An1PBoZY6wRMNiwCyUdmW6s0KeiGKAEXCqGyLUYbKs55/PS3MCW/H EPhwPTsfiwBlsfA/eHprYxHNMUNAgKDHBIx+xOqEmjPanCnyL8PfxLayWxAeTmwTrxWT Cqaw== X-Forwarded-Encrypted: i=1; AJvYcCUYFhLyTS+uyuRWxOa0chd1cXXvVBN1/iSPbK7GzOgFjrP5bT58GslTw9lRK0XQ1b6ZUqn9Y7rB474r0j8=@vger.kernel.org X-Gm-Message-State: AOJu0YyvHkHlVApsYJfLz3i6xgrFIB1VSaQKdSKUysNRnRD3LVrEJptI Nb7chBsqz3fUSqJJ1oRrLuEX67ckslwwHQZfi03lAcUlwrUpzAxu X-Gm-Gg: ASbGncve5MIfxuGY3uO4fw1zeTv9dQieQeOkuo2Hok8nOrr+BU70aBS2r9JqF5+PGH1 o4AISW3x8o0KjhQ4F/isYu+7h7DOm/as0PqkJAU1FvZyR+RKT3456wFUs48zWooujM10Tn/D4qS jTXBRnW2HhJ2pQBwyV3MMuvxQ9EyrJyWzQ06u8BOifFpqBeJWtgnmvvS3xpwzPdtltZmDkpDtDi dHlt03FG4oN8grftieaLBG9UdF60fPyHGGF9Poqx9BQqhxPKaZf1kl5W26k3oYVbbDN2sWmGU0S fhf7V88AWk7t0O/4yA== X-Google-Smtp-Source: AGHT+IEEW0iAE4qEj9av2UeE33E//jpTafczPlcz+BtPwrsJYFsIUM8ZKgX34LtrMnVDl4nvC1vyPQ== X-Received: by 2002:adf:b34b:0:b0:38f:3e0a:ca6a with SMTP id ffacd0b85a97d-38f3e0acb08mr5579751f8f.2.1739873542277; Tue, 18 Feb 2025 02:12:22 -0800 (PST) Received: from fedora.. ([213.94.27.232]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-38f259d5e92sm14749720f8f.66.2025.02.18.02.12.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Feb 2025 02:12:21 -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 v4 01/14] drm/vkms: Extract vkms_connector header Date: Tue, 18 Feb 2025 11:12:01 +0100 Message-ID: <20250218101214.5790-2-jose.exposito89@gmail.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250218101214.5790-1-jose.exposito89@gmail.com> References: <20250218101214.5790-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. Reviewed-by: Louis Chauvet Signed-off-by: Jos=C3=A9 Exp=C3=B3sito --- drivers/gpu/drm/vkms/Makefile | 3 +- drivers/gpu/drm/vkms/vkms_connector.c | 50 +++++++++++++++++++++++++++ drivers/gpu/drm/vkms/vkms_connector.h | 17 +++++++++ drivers/gpu/drm/vkms/vkms_output.c | 41 +++------------------- 4 files changed, 73 insertions(+), 38 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..fc97f265dea6 --- /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 drm_connector *vkms_connector_init(struct vkms_device *vkmsdev) +{ + struct drm_device *dev =3D &vkmsdev->drm; + struct drm_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, &vkms_connector_funcs, + DRM_MODE_CONNECTOR_VIRTUAL, NULL); + if (ret) + return ERR_PTR(ret); + + drm_connector_helper_add(connector, &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..beb5ebe09155 --- /dev/null +++ b/drivers/gpu/drm/vkms/vkms_connector.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#ifndef _VKMS_CONNECTOR_H_ +#define _VKMS_CONNECTOR_H_ + +#include "vkms_drv.h" + +/** + * vkms_connector_init() - Initialize a connector + * @vkmsdev: VKMS device containing the connector + * + * Returns: + * The connector or an error on failure. + */ +struct drm_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..b01c3e9289d0 100644 --- a/drivers/gpu/drm/vkms/vkms_output.c +++ b/drivers/gpu/drm/vkms/vkms_output.c @@ -1,32 +1,8 @@ // 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) { @@ -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"); --=20 2.48.1 From nobody Thu Dec 18 10:36:55 2025 Received: from mail-wr1-f47.google.com (mail-wr1-f47.google.com [209.85.221.47]) (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 E9DA6237176 for ; Tue, 18 Feb 2025 10:12:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.47 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739873548; cv=none; b=BWJ+J+T6yPQHLsZYeyBsBPIKG/hebLQ/OJCiuAf7ilFxN75uBwkGx4HVVwynt5u/FWiQXEVwCYBWbnb1FLsU8+F5Cd9hBwZpfU0or75v9Z/Nd9u0QTmZ5Bv31xpidi+DfKSf0tBnFE4va7sCGnjSPPs5WHHV9QmE53XPnqFdrrw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739873548; c=relaxed/simple; bh=NqKUzI9Kmgs9z+WBxXu0/bcQz0rhTTeF+BXogLGULSU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=CdVJClMBGkyQRzbQ7zJOo4EE2t5jo8IZz5RWezmaKegwDxrx9WRX6oIEOrLGwCjTGHkGSi2hlvJ30IqTPdLcXthGV+dBiyOeIAQvPBRf/M+nn9F2jnaCIwqZuyUQYdhHc9bhyMhsacFXK3X1TKzUxG+6bgZENq9ND9i9CiU1FSY= 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=ShM86nat; arc=none smtp.client-ip=209.85.221.47 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="ShM86nat" Received: by mail-wr1-f47.google.com with SMTP id ffacd0b85a97d-38f2f391864so2269105f8f.3 for ; Tue, 18 Feb 2025 02:12:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1739873543; x=1740478343; 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=prbaD9EEGSsUeJKiTeBVWVOJfwbyTxNyFRLpyPWOntc=; b=ShM86nat1qWXdAvrFmMUG21IrCMhdSGWzWJM8BVJwlUebgmBKU7gvZtXrsoQR8VS7S RJSnqpaWLMKWTQGA2DADjEBrJlAa5G+wyfzzt3E4ij35GhNg0dtTHNvgq0s/Cmp9VxN5 pe7zS+vTzdjoXXDawPg8rB05ngDEG+h4f/UBAWFpkoTAj6Eqgcm0Y2rPC4ZWld1gUslB NHmhjkxR5yKkTLoz86PLpdTByxtOSQ+UujcUqn2ebThpJMmCLF2RiqMBWhZElICwOcv2 m6iHhYO81rC5m5f+WTTOqwaYrqsmPsi7aCYWjcXUUClmrTyvkFifyB4R1NBplgcQtPVD TZuQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1739873543; x=1740478343; 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=prbaD9EEGSsUeJKiTeBVWVOJfwbyTxNyFRLpyPWOntc=; b=Ht1zgJ3spe2WePAJysE13uCYBrqMYcuq1g6MVrfEqKKGnvWT6PHmIvzRjdB9MtV6I2 DDDTWLx+Fo9YC287CMxedA9P8ZFUY4qhO+R8JHXz0C6i9E8SotzdWNtnBjKWZsdeRnxl VB83rLx8GRRhE1K3tpGh4htubx4UeUBf8O9xkIfydmOM4qIyU2ovFmjwkAHzONuW2Y4p WrfOaBKiGdWie9QTkr8yVm4Y4zleQbKy8Rfqzvlua6phqJnHloMnfiQ4JzoBhiZeQN3y RaBVxXjDImd9h8puWZnFc9NkN5Jhip5hNSWQrickQK7vwYC84EdARnB3bSN1xdyFKm5i LDGA== X-Forwarded-Encrypted: i=1; AJvYcCUXuxp4VZZ2AgiB5h72ZvxU0q60ISofP4veaeCOSBH4het9hnIaWLc1K59zl12+BT3rTP9j9HKWw8UZFQE=@vger.kernel.org X-Gm-Message-State: AOJu0Yxhx4e0UAfuBxaQo1gobIdaAjs5xsA3zOj4NfntFuldOBs9F+db hsxA32jPO5bqPmFkiWJ9n6TYlphUZxUpFvoNlKuEtKUy9DU9Mi7/ X-Gm-Gg: ASbGncuGu1u90ATxKl/6deraz3ncvh+gdgObWQx7+rs91CJVN97jpLqQ0vUpPJvqPaY AdeCt0g2Z9X6gIEGIB4StFsl04QURWoEmiCctXAGG9vGqqcBqMVz7miyovth6Phdl1KmqtJU28I H4AjrrR4y8DXNx4djFvbWlwh66Pkq16EVMneKlRcymz3iTDKAyraH2RCQi705jpo+JzYzWbkC5t Jg3KLhpg3YLLiuygvnGq9WY/utiLWAmtKIh+IymWQG3TBX1hZjNLDws4aecradlGetpB0lgK2Gl +XEx4VB7TKNY03fDeQ== X-Google-Smtp-Source: AGHT+IFbin/USp6H333KqF9l8q+i0XsBIi470gaQiS/hfbI+WonrzTOhvv1P6C8lRFRMzjHR/pnPIQ== X-Received: by 2002:a05:6000:1a8e:b0:38f:260f:b319 with SMTP id ffacd0b85a97d-38f33f533edmr11356657f8f.44.1739873543136; Tue, 18 Feb 2025 02:12:23 -0800 (PST) Received: from fedora.. ([213.94.27.232]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-38f259d5e92sm14749720f8f.66.2025.02.18.02.12.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Feb 2025 02:12:22 -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 v4 02/14] drm/vkms: Create vkms_connector struct Date: Tue, 18 Feb 2025 11:12:02 +0100 Message-ID: <20250218101214.5790-3-jose.exposito89@gmail.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250218101214.5790-1-jose.exposito89@gmail.com> References: <20250218101214.5790-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 Create a structure wrapping the drm_connector. Reviewed-by: Louis Chauvet Signed-off-by: Jos=C3=A9 Exp=C3=B3sito --- drivers/gpu/drm/vkms/vkms_connector.c | 8 ++++---- drivers/gpu/drm/vkms/vkms_connector.h | 11 ++++++++++- drivers/gpu/drm/vkms/vkms_output.c | 4 ++-- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/vkms/vkms_connector.c b/drivers/gpu/drm/vkms/v= kms_connector.c index fc97f265dea6..ab8b52a84151 100644 --- a/drivers/gpu/drm/vkms/vkms_connector.c +++ b/drivers/gpu/drm/vkms/vkms_connector.c @@ -29,22 +29,22 @@ static const struct drm_connector_helper_funcs vkms_con= n_helper_funcs =3D { .get_modes =3D vkms_conn_get_modes, }; =20 -struct drm_connector *vkms_connector_init(struct vkms_device *vkmsdev) +struct vkms_connector *vkms_connector_init(struct vkms_device *vkmsdev) { struct drm_device *dev =3D &vkmsdev->drm; - struct drm_connector *connector; + struct vkms_connector *connector; int ret; =20 connector =3D drmm_kzalloc(dev, sizeof(*connector), GFP_KERNEL); if (!connector) return ERR_PTR(-ENOMEM); =20 - ret =3D drmm_connector_init(dev, connector, &vkms_connector_funcs, + ret =3D drmm_connector_init(dev, &connector->base, &vkms_connector_funcs, DRM_MODE_CONNECTOR_VIRTUAL, NULL); if (ret) return ERR_PTR(ret); =20 - drm_connector_helper_add(connector, &vkms_conn_helper_funcs); + drm_connector_helper_add(&connector->base, &vkms_conn_helper_funcs); =20 return connector; } diff --git a/drivers/gpu/drm/vkms/vkms_connector.h b/drivers/gpu/drm/vkms/v= kms_connector.h index beb5ebe09155..c9149c1b7af0 100644 --- a/drivers/gpu/drm/vkms/vkms_connector.h +++ b/drivers/gpu/drm/vkms/vkms_connector.h @@ -5,6 +5,15 @@ =20 #include "vkms_drv.h" =20 +/** + * 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 @@ -12,6 +21,6 @@ * Returns: * The connector or an error on failure. */ -struct drm_connector *vkms_connector_init(struct vkms_device *vkmsdev); +struct vkms_connector *vkms_connector_init(struct vkms_device *vkmsdev); =20 #endif /* _VKMS_CONNECTOR_H_ */ diff --git a/drivers/gpu/drm/vkms/vkms_output.c b/drivers/gpu/drm/vkms/vkms= _output.c index b01c3e9289d0..4b5abe159add 100644 --- a/drivers/gpu/drm/vkms/vkms_output.c +++ b/drivers/gpu/drm/vkms/vkms_output.c @@ -7,7 +7,7 @@ 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; @@ -69,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 Thu Dec 18 10:36:55 2025 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 5031A23644A for ; Tue, 18 Feb 2025 10:12:26 +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=1739873548; cv=none; b=DqkVUaY9meifdB31pxEfmYpquniqYuFQ2G5J+R0ZiY5N55yAXyvrCEHiya9xUs/xDiY8GGtvTxDlJnsgBFgIacO+3YLUPAhOZa7LdyteV+Uzt+ptPxIWDb1E1Ov4OGNM34xV/UVOaWH0XSCnasqxyOH2sjDDwSlQZKJ5pAs12Ds= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739873548; c=relaxed/simple; bh=u4vCOB9rAzLsNQV6nXfUhASxHEQbm+Ekq7VBBUVcZyM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=n0QhMPEjHTuOzQ28c0IPC8FvnsL8OgmigeRgjqi53ynj6r61dvJt0DKVItGqeS62CyOEPCo8evXIKESJxgjL7zpnfn2VjDzjNvtBQEY5gRJDCmlBlrxqXrI7Ueakgt+BMaS4AIY0Z0oIhA1YLnnu5PfYmV1fInBxsIii8/aPbsc= 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=b8ERg8ui; 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="b8ERg8ui" Received: by mail-wr1-f44.google.com with SMTP id ffacd0b85a97d-38f2f783e4dso2853543f8f.3 for ; Tue, 18 Feb 2025 02:12:25 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1739873544; x=1740478344; 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=XyJ4zhCFR8HQ/P+sh2alNxUJOEd+yUChQD9LZjyxME0=; b=b8ERg8uiSVaz94GqwBvhgrUbNUEanX6dfDx7ILtcdsxJAEZix5voQ+kaipjz14zmbe bj5qT2p86fhG7iJoa+87i1vob9X7KTE1tvQ2hrsTlkxh4ex/yPzUCauWjSZIen2MxU8H nOTvIZ/0sefzAsDyZmcwgVU+NzBEtuNhDzyTq8qq2/Y4oQpfWkOWmwWSXlUXGCyubLyk YG9BzqFmqPZxvNDQc8bRqABXrATI4CZLnYNGvevPB1rvcWRyN40KN8w89gb4tZEAjBHB vEqQ5FEqQXz8aVdPf22kirfVlrkazd6Da8CeGHyMmR97sCrpO8C0z/OMzrml55+0xNTm 5neg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1739873544; x=1740478344; 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=XyJ4zhCFR8HQ/P+sh2alNxUJOEd+yUChQD9LZjyxME0=; b=gVJyi2VikVyWX+8UpNDATXZhajCtGsUqB0Xc7fn0Lg+f+W9GM6QkwUruNk8BWu/mRl kSSu8t2i9EwMQC75yFRmm6FfPIWgi1517E511jJdGZdoX0VAbuspdOmC8OABa6Blcpvh VpvgyMgWWX73RcecpTtSpUhDPvi5ixW/Pu6mLhMzfeAVVjZO1Da3MSm5aZDmy4iikD2x BPiTpxtMqf0HrYhICV5p1FWXXkz4SPB9T82qZe50iUTJb1DMT8ZPg/JeZU/mg3jj5jWf Os+racpzr7+s2ZP0qRjhiMr2pv1zpjJjreb1WHlCXAMw7Qei4w7ApqTlK7YJNr403EvW /PBQ== X-Forwarded-Encrypted: i=1; AJvYcCU7v5oO03UPaJx5j370ApPw7x5/VyQDGLuFfHVFfGdhAHx5/JOnw8XV3UScggTa9X7KsdRFavtDdUAkN8A=@vger.kernel.org X-Gm-Message-State: AOJu0YwpAzAgXzmu5TPNGKI8a6G/S0I0lOmjpsx7wzdAiyRadv9NeBWV sM3iLqFwtgqbyZcMrXQFYWhZwiATbAkNlHFbzZpjkqLnjOFZenNF X-Gm-Gg: ASbGnctLEbbrILcaElXyX/pGWLO6L+BC2SvOg/q2HzuqXEY//jeuMd8WHhkhw/Jos6e hwF7TcZL9NY7PmkkLjmDNrhq/XoFuixlX5cQEUl6bI+Rxps2LbgPkl0DiTuI3xo8UWkECIscTtC dYNWsZbbPFF3rtCOLT6uo2J5uRW37587ds+M7ZQNr9o9X28mQPfAK9L7KlH5P/ng1cVKsE5GHaG d/GcN6pqLK7GYYuO2MOis31x8uV/SdLLd+JYmMq4hE6eYLFNyWpzyDyB2dqWTH4FyH84pxhdovJ ZK/9KI3+8GlA+7Z0fw== X-Google-Smtp-Source: AGHT+IFC2iZ3b86dmZHVNKNjYIDDceABsmu1t7eFO+6DJG0rTP5rcTEl6DAhwD/VfnPs4aPOLeh59g== X-Received: by 2002:a05:6000:1864:b0:38f:3888:33bc with SMTP id ffacd0b85a97d-38f388836bamr11398807f8f.10.1739873544100; Tue, 18 Feb 2025 02:12:24 -0800 (PST) Received: from fedora.. ([213.94.27.232]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-38f259d5e92sm14749720f8f.66.2025.02.18.02.12.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Feb 2025 02:12:23 -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 v4 03/14] drm/vkms: Add KUnit test scaffolding Date: Tue, 18 Feb 2025 11:12:03 +0100 Message-ID: <20250218101214.5790-4-jose.exposito89@gmail.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250218101214.5790-1-jose.exposito89@gmail.com> References: <20250218101214.5790-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 Reviewed-by: Louis Chauvet Co-developed-by: Arthur Grillo Signed-off-by: Arthur Grillo Co-developed-by: Louis Chauvet Signed-off-by: Louis Chauvet Signed-off-by: Jos=C3=A9 Exp=C3=B3sito --- 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 | 19 +++++++++++++++++++ 5 files changed, 42 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..3c02f928ffe6 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_TEST + 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..c23eee2f3df4 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_TEST) +=3D tests/ diff --git a/drivers/gpu/drm/vkms/tests/.kunitconfig b/drivers/gpu/drm/vkms= /tests/.kunitconfig new file mode 100644 index 000000000000..6a2d87068edc --- /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_TEST=3Dy diff --git a/drivers/gpu/drm/vkms/tests/Makefile b/drivers/gpu/drm/vkms/tes= ts/Makefile new file mode 100644 index 000000000000..9ded37b67a46 --- /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_TEST) +=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..1177e62e19cb --- /dev/null +++ b/drivers/gpu/drm/vkms/tests/vkms_config_test.c @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include + +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 Thu Dec 18 10:36:55 2025 Received: from mail-wr1-f54.google.com (mail-wr1-f54.google.com [209.85.221.54]) (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 C213723875D for ; Tue, 18 Feb 2025 10:12:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739873548; cv=none; b=eSraGf0UeQdfct/TArdamm5t6X6J0yv4Ccvt9bqWqIOUK/sIkJns1XrCMx36ca4zvk06jwvVb85nCQvE+DqbiXkN+6hrZE8IrsGg/idg61f6c8C4Q9KwziJ32qHbUmgmtlpyTMSBONL3oEKMVmAo7ZkoAwrJ+JDjtXWRXoO/8QQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739873548; c=relaxed/simple; bh=lE2dcBc64Q45pDXeulBAcyc2a1SFMDFApIAknsuoPPg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=q7mTcIewWCPfhLYnlAKGXiiWor1BqCP0IuSscBVEoCepZEImtHoVDjM2pi3+ud9he+uopNU0/R5hA7WJTHMEQ3NkmWlO7r1VDZA8ziTe4sIxulYY7eMhxdPR0twX0TPrEJ1FsaNVG7ToHwD6axUggXAEUrXwyFWMA3nQnCiE4fE= 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=PrKoZfDE; arc=none smtp.client-ip=209.85.221.54 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="PrKoZfDE" Received: by mail-wr1-f54.google.com with SMTP id ffacd0b85a97d-38dd9b3419cso2765903f8f.0 for ; Tue, 18 Feb 2025 02:12:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1739873545; x=1740478345; 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=LmDfaEOjc70HjJgnj7sLGaZRyHuUKTvYVGnXm2VRbiY=; b=PrKoZfDE4csk0Zgx5H8W9wNKE9PctYr/KSO0XWQHsqr/nQLPCrXGfDMj5LQL5NGz4O RkLWBFCv5IZCd/hDa7a0UKfHlrkuj4njHoIkaXm3TSaWmiUDVdDDY9+c01C5nfOxszqr vshabRgAhRAuuoL/tWw9d7gcGvW8WVjOJDzWvTDSh3WYUh2F069IJuGQD7vcd4Op5fyl sYq16ErKUkUXRcKV5LdltitHoEWNoZOryyzEBcb6aXt56sswkdnqO46ke5obVOdWt+gr e8EWij4s6gtlhd8aatWPbOhyQ1qTjZK9LocCnrT80f+ES+S1pAvWc9yPWQsB0lHr40my TY2Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1739873545; x=1740478345; 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=LmDfaEOjc70HjJgnj7sLGaZRyHuUKTvYVGnXm2VRbiY=; b=uIeq3BBJgfhPsyEBuxESsztQrfSTj8m+Tqg31Fv3uoICB1fzXaKcNoktrXQO1yhA+e LA3cWMKjeHJIVANOf/zKYxBomgAOzeduyFXW8Okwj5lrhhm26wtdkebIMOs93yKYXDpY 8Sdx7dIzVFRDJNAfeItn1LTE05qoHU/Q0ESMJSgpZ8O6fqzCHRKsiYTX8NDBdCkCVs7Z ct1BedQ+RZjGBBbOeQl+k6NqQGXsZMmvItc0lwm62rOF8oPlhVRdJJBuiUVCY1o3Wo3b vm7rk+vcdVb/TmRfBqKSdFmv18afEo2pLlaQZlbb4rK78d+Xx5arB+ONzDdlKUj+UrFx 2yHg== X-Forwarded-Encrypted: i=1; AJvYcCVTveFniZvB+l+cAoeE3deRzvpJ2R5jtTA3pNcnlDnqv2KH3qIGTozZe/DNnrOQ2WIkV3Itgdt104qVpYs=@vger.kernel.org X-Gm-Message-State: AOJu0YxzQcvrIwTExYCgo1qZgjyQXSkPPyG1uJpUbviLDBNQwgtxCj77 q6nGkjk0NFHKWPmnm5kyOuwNyefTK19v2rk+BjoIjpH1dXsEO9U+ X-Gm-Gg: ASbGnctMFbf037aDQCDJNbvGfI2pzxG0uEzmXDhf4FZIO1qVXfBjdm/AIex/G3Hf28Z 6i4kFzNd+hwoDPFakPjt2fyPbEzYWXd5EZGy60LXBkS/uEkfT+s7tH7bKhgoGdp0WFAS9d/bXJg GuRJAwyYmPe2faZNzOYObjC5JVbrAl04FOd77EXG0E55ptOiMXlA3UudsCyQyRQNtpotYXTkSCh SgR4Y4hbX73uyIBXJijyR9U3seUzJGBycOUZLl1pQm7tfkhaOvZK30P47LGBJdgPi+8iOJ3Mtk8 1mjFGvoRVa9SHYWOSQ== X-Google-Smtp-Source: AGHT+IFmXSGkB4xpAzaHAsX4XcGtZCuBZxviDINWjxwvydlcFSLk0TMWD+DRz0g9pVwMGJ2kObvZXw== X-Received: by 2002:a05:6000:1863:b0:38f:4263:9d62 with SMTP id ffacd0b85a97d-38f42639e66mr6729434f8f.27.1739873545011; Tue, 18 Feb 2025 02:12:25 -0800 (PST) Received: from fedora.. ([213.94.27.232]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-38f259d5e92sm14749720f8f.66.2025.02.18.02.12.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Feb 2025 02:12:24 -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 v4 04/14] drm/vkms: Extract vkms_config header Date: Tue, 18 Feb 2025 11:12:04 +0100 Message-ID: <20250218101214.5790-5-jose.exposito89@gmail.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250218101214.5790-1-jose.exposito89@gmail.com> References: <20250218101214.5790-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. Reviewed-by: Louis Chauvet Co-developed-by: Louis Chauvet Signed-off-by: Louis Chauvet Signed-off-by: Jos=C3=A9 Exp=C3=B3sito --- drivers/gpu/drm/vkms/Makefile | 3 +- drivers/gpu/drm/vkms/tests/vkms_config_test.c | 13 +++++ drivers/gpu/drm/vkms/vkms_config.c | 50 +++++++++++++++++++ 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, 121 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 c23eee2f3df4..d657865e573f 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_TEST) +=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 1177e62e19cb..a7060504f3dc 100644 --- a/drivers/gpu/drm/vkms/tests/vkms_config_test.c +++ b/drivers/gpu/drm/vkms/tests/vkms_config_test.c @@ -2,9 +2,22 @@ =20 #include =20 +#include "../vkms_config.h" + 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..42caa421876e --- /dev/null +++ b/drivers/gpu/drm/vkms/vkms_config.c @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include + +#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; +} +EXPORT_SYMBOL_IF_KUNIT(vkms_config_create); + +void vkms_config_destroy(struct vkms_config *config) +{ + kfree(config); +} +EXPORT_SYMBOL_IF_KUNIT(vkms_config_destroy); + +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 b6de91134a22..37de0658e6ee 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 config->cursor =3D enable_cursor; config->writeback =3D enable_writeback; @@ -241,7 +221,7 @@ static int __init vkms_init(void) =20 ret =3D vkms_create(config); if (ret) { - kfree(config); + vkms_config_destroy(config); return ret; } =20 @@ -275,7 +255,7 @@ static void __exit vkms_exit(void) return; =20 vkms_destroy(default_config); - 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 Thu Dec 18 10:36:55 2025 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 A74E923956D for ; Tue, 18 Feb 2025 10:12:28 +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=1739873550; cv=none; b=tWbauNGNm1GhzDK2jz40sEap0vNTYO5g50SyMAY1U+o5tPzpLdOG6+HONkRY/P/8DCJ7Dd/vhf0vKoycQ6FEzKj9E8db+6z46UpyZdIO+eCXrfiUr+fyWkH25yPVQLwbZVWig/b7w8m2ufLgvd17k9DMEhLa1FyGnXFe/udvkns= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739873550; c=relaxed/simple; bh=ECz5X7I3+CKYQXuInRYoI309iDJXr8+oXd0YASKhnBw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=NctWA0Z0qBHi1cj2ycIHTZHUEwSwYapNfmwc5QTk0/qbPy0u0bKw+Z8LYTaoeV0gCnpmY7rH2XPA17OSwIuw5aryGGw3HZENtoQHfyztcQ76GzAGlW0bjqHtmhh0FSPBvGj5+ulgMSYk1ZVTgMjbvO8BaEsIwV7M/VHZga+W9Yk= 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=SupFqq6R; 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="SupFqq6R" Received: by mail-wr1-f44.google.com with SMTP id ffacd0b85a97d-38f3486062eso2252178f8f.0 for ; Tue, 18 Feb 2025 02:12:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1739873547; x=1740478347; 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=an4ZlObHhfs530zfnSQ9jtNvfBOIXbJcmgdk2xLIJkM=; b=SupFqq6RzZ1VqyY40ipA5RnBExCJUC24BJK0JBkECQxElRnCzwIfJmryKeYgnIl6FE 1DiqwrsffTLOp3J2G1okJmjcj3Z8HscLQxh3yZN+uALH23DMIHjp/bo5bUkhzPhU1Ust SRNyKhKsU0X6Xng8TIewNrnARYdX5oeoJJIW3DuSqzINWzfFIJSku3qmOW7cYza+nnha vyBVo1x4uTkrLZSLJsog2rcOvh2cgNiUMVE8W60QDunY3FvH3uhb03AHEip6hvkAbfiJ Rxq37fT8/KZ9699Me+mmp7C5TtASSlKGah7WjR1GREkDaOSfqhe5f0/BxRifJ8gez/Ie XCwA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1739873547; x=1740478347; 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=an4ZlObHhfs530zfnSQ9jtNvfBOIXbJcmgdk2xLIJkM=; b=KJeO/yow41zWjkwpvHwrZGWuKBoYcTLxUq/bWle1SNuW6VDaFvXj/hKSWy5qqrVQYK tigxH2TG5RhP5XkkYvjnxdxRT60/p9LVeIzm9YWO3iKWEZUFHLFqRiZpQPL+Xvpi/5/F Qki/6s27yDP8GMtPGz1ZFwTKhj1xWM0N+x/MZlgbPmf5EbqO/ImITLMqBIg6yhoNsbEA niIRr79m3N8bb4NMq3mjKMAx5kEIL2002p94pIVeeXaQzaUvOlBzOF4AnqGuxLy9D8Fd NQnY7pEMdSJdzQ5uVpS5aio6jGrUUlDYBD2Vrvfe6CGRLPNIgc809w73CH7SpBNL+Yz7 RjnQ== X-Forwarded-Encrypted: i=1; AJvYcCWI9g3z+AjhkaE3eSZx8rPqoxnSXG2ZkpzBSkOIsccmpuhIDK0EFbK86pCxaXTxedaHxSRc+rZbDJ9GS4I=@vger.kernel.org X-Gm-Message-State: AOJu0YxpYauEIbsYHQ7aeKGMWDflWa+zn8ADIpDBPvrJXqwjcs9ZhCPM QxMSXbT8OyAj6eb1aTLx6J3zo32D2R+D/YUd/iAEQOW8d4tQ8q4sOYPWfc7k X-Gm-Gg: ASbGnctaEDeYGcz/Nisjb0Eno1r/1DRCjrE0lu1825kZaiKCMATJ+OWR0RQ0j/553UF baEje2JnUkugMNIFxV2WodOsJn1RsRptBiRKaYc9blQG9BPszvO1ygsw7B81iusqlLEc1DGU2z9 Kyw8uysPTeLPndRX8YUmkxZcId1I2ElCag7sgrmYqYgj5KMSIOevQIdAi8x3uefQ3ABNsxHIKMp MV4Hr+J0xj396NUuSBd+2c3pJD4ABEanypgpYujTdycps44HqJJEyGfYvMZ5X1lf0T4B9P6XbtD lSOgWuUf65EpdfkBGQ== X-Google-Smtp-Source: AGHT+IGJxHESmAAuUrG/TzfS69sJTg+tzboHhcOfguDL/BJgytBJbYzlmkjBEB91eQfNa8ZNIOKnVA== X-Received: by 2002:a5d:64c2:0:b0:38f:470c:932e with SMTP id ffacd0b85a97d-38f470c9576mr5637822f8f.29.1739873546478; Tue, 18 Feb 2025 02:12:26 -0800 (PST) Received: from fedora.. ([213.94.27.232]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-38f259d5e92sm14749720f8f.66.2025.02.18.02.12.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Feb 2025 02:12:25 -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 v4 05/14] drm/vkms: Move default_config creation to its own function Date: Tue, 18 Feb 2025 11:12:05 +0100 Message-ID: <20250218101214.5790-6-jose.exposito89@gmail.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250218101214.5790-1-jose.exposito89@gmail.com> References: <20250218101214.5790-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. Reviewed-by: Louis Chauvet Co-developed-by: Louis Chauvet Signed-off-by: Louis Chauvet Signed-off-by: Jos=C3=A9 Exp=C3=B3sito --- drivers/gpu/drm/vkms/tests/vkms_config_test.c | 38 +++++++++++++++++++ drivers/gpu/drm/vkms/vkms_config.c | 18 +++++++++ drivers/gpu/drm/vkms/vkms_config.h | 14 +++++++ drivers/gpu/drm/vkms/vkms_drv.c | 6 +-- 4 files changed, 71 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 42caa421876e..0af8e6dc0a01 100644 --- a/drivers/gpu/drm/vkms/vkms_config.c +++ b/drivers/gpu/drm/vkms/vkms_config.c @@ -20,6 +20,24 @@ struct vkms_config *vkms_config_create(void) } EXPORT_SYMBOL_IF_KUNIT(vkms_config_create); =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; +} +EXPORT_SYMBOL_IF_KUNIT(vkms_config_default_create); + 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 37de0658e6ee..582d5825f42b 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.c +++ b/drivers/gpu/drm/vkms/vkms_drv.c @@ -211,14 +211,10 @@ 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 - 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 Thu Dec 18 10:36:55 2025 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 664452397BF for ; Tue, 18 Feb 2025 10:12:29 +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=1739873551; cv=none; b=eO6WxY3m5yEaSBik3naXjBgiAZNAf0mnAWO9sKb3Lg1xZx0dzK2p6peX6KDItObcoalnSs4NzIJYLgrE9fPOQiAI4oKtNB1cVeyMYQkHyAjijjtk4lIAbuEWM+tmLVH63F61nD6LH0+evvJJ/78q56NIieCJh8B4vgoGWbcCVc0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739873551; c=relaxed/simple; bh=FO0iiUXRhkoGigFFgbjCarBeopu2pFAvqYIozSc40SQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=nGElSoeOEkY2xp7dmIaYRRlbw9AhWTpTHABVm0woF0YNT27+j66EiHBoSPti510x7rz5PSL5aKPF1p/vGdM2aAFx53Qb5aH7jnFkrAASW0ZNdQzyDGCsnMeNWukZf6v6Bo00EHDDPVO/Z2h3E7mgYdCkUOb63ZVJT/N8llo8jOM= 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=fNCzgaCX; 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="fNCzgaCX" Received: by mail-wm1-f46.google.com with SMTP id 5b1f17b1804b1-4396d2e32b7so22257975e9.0 for ; Tue, 18 Feb 2025 02:12:29 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1739873547; x=1740478347; 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=TJKka9BGXo5aWskaWZaSFDrSIvgDMiHYo6XxF9H8dkw=; b=fNCzgaCXD/fXRaX8ZycrDrh8//KYsErmoSb1NXi8R/uj3NX9/XF6qoech4zK20XZ9z Z50iwv8LcArAL2ve5WDG/n6kf+srdpbNps6sjh72iFxBFoDyCZlGQaG9nAHoaA0AE9HE pncRqdsNU3nszetk+ULrTTOLB/871jZkyBnMDB2uKwO4GiydNqPUHbHC3IaiobYvvOQ5 fXoytbECaD3t5nAjR3i/uWNlDMaCaoJ4WQWv/aDJpq4NQe31YuLKyByd8RJmSlwUh16D 2pMtCvYyJQy9rx3MPDAbM4mP28y7kUIkXgGQEDs2QYZVMy/fBBCzbe505fdTFl73+CEW 1H+g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1739873547; x=1740478347; 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=TJKka9BGXo5aWskaWZaSFDrSIvgDMiHYo6XxF9H8dkw=; b=wU3T5fEkQ1aPu1QhPmHdLgRMCQ+MjFZgUpceG7t802kyMCeXIPfBj1A4wpRpLJ0G/C vfJ5Y0mqQAHmn0rqyoNmU1B9lBissfO8hFPTYJrO1fL/7bvcTyaNkdFvRNY8nqDr9/eM 6ilaLmS2DgeNfT5zJH1Xrf+HWUqfcGSP17BL4bnw5cTaIjB+smU+8W7CIVGMV8EIzpkT xm71d1gXtA3fVZHgjB0wudZEHaOJjG2eyQhAihrE3hecUTMFvRLxtQzyNBvWlrDEpVC8 Ge7Lzwz0sNUJr9AAGfwkiPR4uboEx6Mlrp0RKf219cMnxfnVDD7/hASVy4NkgneqZx23 c02g== X-Forwarded-Encrypted: i=1; AJvYcCV1/6Fh/YrTMh6W8+CbjqmZMQBgjAe+7iZ3Q+In25D9eBqNi2mXLuMn0tbDqjqIXpjT5uKCwynXbS3O5Vc=@vger.kernel.org X-Gm-Message-State: AOJu0Yx/xgrECdtMENi91Snu2QjXDK8qK8Yrk3emm7jiyBSJLVZCLQ+C o4IyQz/ChVW5TUmLC2jkw/gJf1tCK9qG8coDMZE4FRXU5oUdm/d4 X-Gm-Gg: ASbGncv/ZNn8ssNQKGgeHzZgfk28CCXzCtG11+JSPNB7rfF9yGr650ZyxfZ0sWTXGF5 ATYMeSslwzD/roCV20Z4vDMqHUAKWBPXW0O/lDevk+lJ1jilbsdUxf6A1R4Taiya0jHrvNfJj9l LAkU7jugY2gWHSQ+ZVU5ffnVR0jzbEBUfypBzX0HjWl8jfitIyv2zhNyyDIioZoVMNZpLjJmzpU ToyS2ZLM11cBPm0JLmTWlOXJ4yG9uojAl/TlFi+OH/51fepjnqY1hrHo7+Bb1Re4Xk8/3mZ+GGK SilKl4EknM7vjCtAgw== X-Google-Smtp-Source: AGHT+IGWzSNr3kxbNV50jtbq0xbVL8YqiJgdejwz9FCOvAxbLEogzuxer5MPdYZcMn4JCJdbLY2+eg== X-Received: by 2002:a5d:5a11:0:b0:38f:32a7:b6f3 with SMTP id ffacd0b85a97d-38f33f4b858mr9937330f8f.40.1739873547398; Tue, 18 Feb 2025 02:12:27 -0800 (PST) Received: from fedora.. ([213.94.27.232]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-38f259d5e92sm14749720f8f.66.2025.02.18.02.12.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Feb 2025 02:12:27 -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 v4 06/14] drm/vkms: Set device name from vkms_config Date: Tue, 18 Feb 2025 11:12:06 +0100 Message-ID: <20250218101214.5790-7-jose.exposito89@gmail.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250218101214.5790-1-jose.exposito89@gmail.com> References: <20250218101214.5790-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. Reviewed-by: Louis Chauvet Signed-off-by: Jos=C3=A9 Exp=C3=B3sito --- 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 | 18 +++++++++++++++++- drivers/gpu/drm/vkms/vkms_drv.c | 4 +++- drivers/gpu/drm/vkms/vkms_drv.h | 2 ++ 5 files changed, 40 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..92798590051b 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 lifetimes */ + 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 0af8e6dc0a01..9fb08d94a351 100644 --- a/drivers/gpu/drm/vkms/vkms_config.c +++ b/drivers/gpu/drm/vkms/vkms_config.c @@ -8,7 +8,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 @@ -16,6 +16,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; } EXPORT_SYMBOL_IF_KUNIT(vkms_config_create); @@ -26,7 +32,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 @@ -40,6 +46,7 @@ EXPORT_SYMBOL_IF_KUNIT(vkms_config_default_create); =20 void vkms_config_destroy(struct vkms_config *config) { + kfree_const(config->dev_name); kfree(config); } EXPORT_SYMBOL_IF_KUNIT(vkms_config_destroy); @@ -49,7 +56,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..fcaa909fb2e0 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,19 @@ 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 + * + * Returns: + * The device name. Only valid while @config is valid. + */ +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 582d5825f42b..ba977ef09b2b 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 Thu Dec 18 10:36:55 2025 Received: from mail-wr1-f48.google.com (mail-wr1-f48.google.com [209.85.221.48]) (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 DDF0323BFA3 for ; Tue, 18 Feb 2025 10:12:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739873552; cv=none; b=k03lVChn61aO+KtGl1Nv/of0tNRXNr2wn5oGi0u/3MqmOBK6rcUbheMIbn+/PAMG525EU0f1pkLXHGNgLEGG4ZkumNG1TUXSAFhU4VZZvAMTb6XPGyrj12dtH+IodbT7hxZkwykhmb9rIlZw0cfB2atT8DoeY32Jl7ecVeq8914= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739873552; c=relaxed/simple; bh=ezbRlCRRih7ztNQfSrHs4WhtoVlP3GIc2Vb1QT7R4sI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=f3877hCaHTe7Is/Ba311asjUek7gCBkAAjSioSS9z6vdwSffzSeAqz9OF+BMt4Injt1KIkP0GxiJRQZNB5HFoy/U6nPXmXAXAInXWqsc3sy2Iy1GPbaqVCVkq+sHwNRH1v2X1tJNybNyd4mFizK3QmwxLzx4vHWdiFj5pij21LM= 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=Mkuhy+09; arc=none smtp.client-ip=209.85.221.48 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="Mkuhy+09" Received: by mail-wr1-f48.google.com with SMTP id ffacd0b85a97d-38f325ddbc2so2476403f8f.1 for ; Tue, 18 Feb 2025 02:12:29 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1739873548; x=1740478348; 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=vG84qkV7BJECjcnd+fwOr4EF0zkS6sxDafqd+tmcLZs=; b=Mkuhy+094D2Gcr/p8q9NNFuZl7JHGzKHA1pmzOOLaM4BWPelZ05eP4/ri+00QqwB42 EqOqPp8btyPdUWMUsG104CmPQ+hsAR1CpTB0FpDIoUDyeJJf4VdbepPYiB3CSgf4D+D0 ozb1zEg/5IZRy/ZUw06T+7/lISKhcE+co5lnAaLiFND8NHPqVP6Ua88t3BUrO0WfMTLd 4OtMaRs4cNvMUQi1nfcAseyQwvpCxk0PswRYmFNvnEwl/Twpis7tpDaVkPIn+lEVqfsn ND/3tvIVnTrlOxxYX92WVsXDZxe+4uh12w5ZIns9dIsm2KWhqdr/fo1jTIudLZKnkAg8 THRA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1739873548; x=1740478348; 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=vG84qkV7BJECjcnd+fwOr4EF0zkS6sxDafqd+tmcLZs=; b=VnW9jnKjx4UCTiJmjINMzaJeYob62AmebLQ7zh/7zg/JMwUO3uC1Ud7qouGH/sbuN/ KZnFlMWW8Idf9vNl+TstPCcoH6lhdfCw6hYb5Z41HdhvXTm45ubwnakhR5KUJI75pSSW CrdptOOSqLUBZJg0K8S2qcQnWVStElaGqpb1H0h6jSGvC4Gvue2hlFcJs3sAN2RRLJXG GA1rOqQhBJNLDET4S21awWXRMbsFGl584BQ3oZaqJBjsZkM4DDdEcDelorJaIM9ah2HV Ir0zR5ULCAUq+9r0jghjuPuQThlIfWQDwmrH+uI0PX/kQvwf4lJkWwzcFAUXup012IsK tYCw== X-Forwarded-Encrypted: i=1; AJvYcCWUZYGpbv6sJ9onEU/3iWay/ieiENvZ2uOglbXJgfrKDdeTvDkUI7jxYavZc2VW4inlRk+7Ul5d+/qdMy8=@vger.kernel.org X-Gm-Message-State: AOJu0YzdJolcXjr8phgAgT6nmbj5xUVfRta8+/GiodPRBmCmJEPacK1V DOHY7NHrgCEv3xlMTdp9OEK/mNLCwyFD7Zt4VdwNP4tz9p6ncVQd X-Gm-Gg: ASbGncuClNvzLr74+RiJbL9oaJmlqJMQfqmBxOCYWP3kHXqEPVLeuBx5ZUPSFDc/q5I Q/0mDV6W+AZbqfhHVjODBYr+twtf1XLfLdGWe9DvAKOLF3ZZsjt5qK85geTIlAWiXv/oaVJDm19 bkwzTD+6VA94TdHakM35ZruAp4TgHlaRYVWSiYbMIn6NZM88b8nOsb/Hw1x0jOND+h3F9RAqExO SxKDNsElXrunFM7YZP8+vIj9agJEuZTg8gxHUdsIw2EgYSxhDv4nS96I632z7UMVDH3QcwYP/y4 CPNL+JmElfRTDQ4k+w== X-Google-Smtp-Source: AGHT+IFbaa0meB3wBm+TDHc5jyul6WCWSeakV99m+tb4BZHPtJ5c4WpsT4IWxy5+wWc8KfJM1qrkAw== X-Received: by 2002:a5d:64a3:0:b0:38f:50bd:ad11 with SMTP id ffacd0b85a97d-38f50bdadd5mr2178759f8f.5.1739873548145; Tue, 18 Feb 2025 02:12:28 -0800 (PST) Received: from fedora.. ([213.94.27.232]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-38f259d5e92sm14749720f8f.66.2025.02.18.02.12.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Feb 2025 02:12:27 -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 v4 07/14] drm/vkms: Add a validation function for VKMS configuration Date: Tue, 18 Feb 2025 11:12:07 +0100 Message-ID: <20250218101214.5790-8-jose.exposito89@gmail.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250218101214.5790-1-jose.exposito89@gmail.com> References: <20250218101214.5790-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. Reviewed-by: Louis Chauvet Signed-off-by: Louis Chauvet Co-developed-by: Jos=C3=A9 Exp=C3=B3sito Signed-off-by: Jos=C3=A9 Exp=C3=B3sito --- drivers/gpu/drm/vkms/tests/vkms_config_test.c | 2 ++ drivers/gpu/drm/vkms/vkms_config.c | 6 ++++++ drivers/gpu/drm/vkms/vkms_config.h | 10 ++++++++++ drivers/gpu/drm/vkms/vkms_output.c | 3 +++ 4 files changed, 21 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 92798590051b..6e07139d261c 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 9fb08d94a351..d1947537834c 100644 --- a/drivers/gpu/drm/vkms/vkms_config.c +++ b/drivers/gpu/drm/vkms/vkms_config.c @@ -51,6 +51,12 @@ void vkms_config_destroy(struct vkms_config *config) } EXPORT_SYMBOL_IF_KUNIT(vkms_config_destroy); =20 +bool vkms_config_is_valid(const struct vkms_config *config) +{ + return true; +} +EXPORT_SYMBOL_IF_KUNIT(vkms_config_is_valid); + 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 fcaa909fb2e0..31c758631c37 100644 --- a/drivers/gpu/drm/vkms/vkms_config.h +++ b/drivers/gpu/drm/vkms/vkms_config.h @@ -67,6 +67,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(const struct vkms_config *config); + /** * vkms_config_register_debugfs() - Register a debugfs file to show the de= vice's * configuration diff --git a/drivers/gpu/drm/vkms/vkms_output.c b/drivers/gpu/drm/vkms/vkms= _output.c index 068a7f87ecec..414cc933af41 100644 --- a/drivers/gpu/drm/vkms/vkms_output.c +++ b/drivers/gpu/drm/vkms/vkms_output.c @@ -16,6 +16,9 @@ int vkms_output_init(struct vkms_device *vkmsdev) int writeback; unsigned int n; =20 + if (!vkms_config_is_valid(vkmsdev->config)) + return -EINVAL; + /* * Initialize used plane. One primary plane is required to perform the co= mposition. * --=20 2.48.1 From nobody Thu Dec 18 10:36:55 2025 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 D0E3D239595 for ; Tue, 18 Feb 2025 10:12:31 +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=1739873554; cv=none; b=ecDXxKtq9Lo8I/BGNJPAR3SViFUi0y7cfLR+VJoGORo5w5r/6aGOtsa3qbi7p2zeO1Fw2CsxoS+PNIdj9l8paGwQ/5MiKzBQO9SaRzLzk3NSjfnOT0hh9l+T5wV6h7FlsDSNAqMFYMu7EZVH3CV+iix+KSYwYAZp5h5/tLeFxEA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739873554; c=relaxed/simple; bh=huf2dr0rnrn+qSAiniwyzYfjmcDfzmFX9b8o7j22qsw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=ghTf8CGDuktFX4jhPFZwjIGp3zhIsJ4m5LtFqNI2v0RbxS63A9F7M1sx54QUPMXp3G6ImXsyAvcIKS038EVGIVRDr1vx9X5QL9FHsp8dpWh8yRlsc8goqE3K8O0xbydAitv+R1e7YDTsLGLmcAWnbBy314TIZJNudDoW+NJClaU= 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=KI3BwauH; 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="KI3BwauH" Received: by mail-wr1-f50.google.com with SMTP id ffacd0b85a97d-38f2b7ce2e5so2096193f8f.2 for ; Tue, 18 Feb 2025 02:12:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1739873550; x=1740478350; 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=8sp3iHvZITaZ2UTkf5VLRrARO1d57llPyzlqb0Su9fc=; b=KI3BwauHIh0VhO3qXkhf9p7Q4Bb7kZTDr83fiATyTRiYLDXsp2dYVGd7CgvjUgvzLG tYe2toJREmTfgh4IpWaEuic8EniNRit21Vo5yBN1HrwwVguRzgtqLNOAmZ0AQTV4a8Da kFgr3xr+WhtBeC5pW6Roha1R3yFH66YIWFwpJM4459RkWRkw240OUGm87Aac6cBxoDmv 4fa9HukyY24Te6TmhZlED0n03HN5UQGugNVkepk0/z6b3LmQsf9n8AwfFL9F74PapYHR DCHKjpb/JT01z/CT058XijqHmPD1EUnmltjKJ+Zqi7mBUS9wvQOlU73qFmYqFmcoBquI FiJg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1739873550; x=1740478350; 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=8sp3iHvZITaZ2UTkf5VLRrARO1d57llPyzlqb0Su9fc=; b=laMofhyWPck0ddv0qGkdF4ptKTclynXMNqd+pRQE3qZXB6whIR0BVvUbt16azZ2BoQ dZ8mNxug9Zc8b0pDZJyDiR3u5znBrmXhvC9sxio0+G+FnvXBu7iGE0imif9eSkccFknJ fYxkxcm4dUh9rdLbOwczy48PpfsdQhxq9zolxFYGGHfyDDL/Lvsjn3ohoCkbI5cl8dCk agCEfLWVUu2QLCo7u1y1XHrDuIy9inbc27PZ3DV8psdL34liVV2a+xJ2IpNE9ct0Sa+3 BtPZw+vUdbRIniUKC/xFke41HvFh/6p75iCByz+bjtsOPcPThHBHCQrMLCe6owLPxx5U YYzQ== X-Forwarded-Encrypted: i=1; AJvYcCUc3cNTClqBb5t++9Ke9zKy8KmFe3PQlI/n87ybA+cBT+MYxPonr8ViKzhKjQKvvd6GKz5SyCcClY9SyOI=@vger.kernel.org X-Gm-Message-State: AOJu0Yy33yDmaXdpnRxre1B5y79zJHBXG2jL+Epp0b4TnqQCrarntyKp 48G8qGN28NbFj93zqX3shuZOlrrM6OiTW0jnQF0vkbR8LEpFJoP0 X-Gm-Gg: ASbGncsI+c5kWiDZWgsa/c03jgNzy659S/S/HkTbrK/tCdAKOG+6OQbPDtJTWSkKs1Y KpNTbQYwRhqqF9YVBTLDd/Q+UX35v50kK9kIaeweHy8xBTwNPJk/9ZElztwp/m8N4l7c71z2NRV LM4s985HoxQuL6I2iz2ycyd6/U2TfCgvtRsEcNQ5imYjjvDeoEsoeRkup14vLDVDFT2ttc1Pk/w 5H/rtUdJt85TUu1jgW/8f8nFtpyKLpZXY/sUVCfA1FOKauUL1GjyONP151ZrUmZQ4zgYjO6fsyd EcCFF3L/1eQSS6u94g== X-Google-Smtp-Source: AGHT+IG3UBFjjpNjfCkciQmHx67BD5Kxu4AYnE3/HFdgtuwzCgXp79IVB1vN+tAEgJYejdIjkM9LKA== X-Received: by 2002:a05:6000:1b02:b0:38f:2bee:e112 with SMTP id ffacd0b85a97d-38f341708a2mr11199986f8f.45.1739873549512; Tue, 18 Feb 2025 02:12:29 -0800 (PST) Received: from fedora.. ([213.94.27.232]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-38f259d5e92sm14749720f8f.66.2025.02.18.02.12.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Feb 2025 02:12:28 -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 v4 08/14] drm/vkms: Allow to configure multiple planes Date: Tue, 18 Feb 2025 11:12:08 +0100 Message-ID: <20250218101214.5790-9-jose.exposito89@gmail.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250218101214.5790-1-jose.exposito89@gmail.com> References: <20250218101214.5790-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. Reviewed-by: Louis Chauvet Co-developed-by: Louis Chauvet Signed-off-by: Louis Chauvet Signed-off-by: Jos=C3=A9 Exp=C3=B3sito --- .clang-format | 1 + drivers/gpu/drm/vkms/tests/vkms_config_test.c | 161 +++++++++++++++++- drivers/gpu/drm/vkms/vkms_config.c | 127 +++++++++++++- drivers/gpu/drm/vkms/vkms_config.h | 75 +++++++- drivers/gpu/drm/vkms/vkms_output.c | 42 ++--- 5 files changed, 370 insertions(+), 36 deletions(-) diff --git a/.clang-format b/.clang-format index fe1aa1a30d40..c585d2a5b395 100644 --- a/.clang-format +++ b/.clang-format @@ -690,6 +690,7 @@ ForEachMacros: - 'v4l2_m2m_for_each_src_buf' - 'v4l2_m2m_for_each_src_buf_safe' - 'virtio_device_for_each_vq' + - 'vkms_config_for_each_plane' - 'while_for_each_ftrace_op' - 'xa_for_each' - 'xa_for_each_marked' diff --git a/drivers/gpu/drm/vkms/tests/vkms_config_test.c b/drivers/gpu/dr= m/vkms/tests/vkms_config_test.c index 6e07139d261c..116db01ba8a0 100644 --- a/drivers/gpu/drm/vkms/tests/vkms_config_test.c +++ b/drivers/gpu/drm/vkms/tests/vkms_config_test.c @@ -6,6 +6,27 @@ =20 MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING"); =20 +static size_t vkms_config_get_num_planes(struct vkms_config *config) +{ + struct vkms_config_plane *plane_cfg; + size_t count =3D 0; + + vkms_config_for_each_plane(config, plane_cfg) + count++; + + return count; +} + +static struct vkms_config_plane *get_first_plane(struct vkms_config *confi= g) +{ + struct vkms_config_plane *plane_cfg; + + vkms_config_for_each_plane(config, plane_cfg) + return plane_cfg; + + return NULL; +} + struct default_config_case { bool enable_cursor; bool enable_writeback; @@ -24,6 +45,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_EQ(test, vkms_config_get_num_planes(config), 0); + + KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config)); + vkms_config_destroy(config); } =20 @@ -44,16 +69,145 @@ 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 */ + vkms_config_for_each_plane(config, plane_cfg) { + 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_cfg; + struct vkms_config_plane *plane_cfg1, *plane_cfg2; + int n_planes =3D 0; + + config =3D vkms_config_create("test"); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config); + + vkms_config_for_each_plane(config, plane_cfg) + n_planes++; + KUNIT_ASSERT_EQ(test, n_planes, 0); + + plane_cfg1 =3D vkms_config_create_plane(config); + vkms_config_for_each_plane(config, plane_cfg) { + n_planes++; + if (plane_cfg !=3D plane_cfg1) + KUNIT_FAIL(test, "Unexpected plane"); + } + KUNIT_ASSERT_EQ(test, n_planes, 1); + n_planes =3D 0; + + plane_cfg2 =3D vkms_config_create_plane(config); + vkms_config_for_each_plane(config, plane_cfg) { + n_planes++; + if (plane_cfg !=3D plane_cfg1 && plane_cfg !=3D plane_cfg2) + KUNIT_FAIL(test, "Unexpected plane"); + } + KUNIT_ASSERT_EQ(test, n_planes, 2); + n_planes =3D 0; + + vkms_config_destroy_plane(plane_cfg1); + vkms_config_for_each_plane(config, plane_cfg) { + n_planes++; + if (plane_cfg !=3D plane_cfg2) + KUNIT_FAIL(test, "Unexpected plane"); + } + KUNIT_ASSERT_EQ(test, n_planes, 1); + + vkms_config_destroy(config); +} + +static void vkms_config_test_invalid_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 get_first_plane(config); + 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_create_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 get_first_plane(config); + vkms_config_destroy_plane(plane_cfg); + + /* Invalid: No primary plane */ + plane_cfg =3D vkms_config_create_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_create_plane(config); + vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_PRIMARY); + plane_cfg =3D vkms_config_create_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_create_plane(config); + vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_CURSOR); + plane_cfg =3D vkms_config_create_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 +217,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_invalid_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 d1947537834c..3c3f5cf79058 100644 --- a/drivers/gpu/drm/vkms/vkms_config.c +++ b/drivers/gpu/drm/vkms/vkms_config.c @@ -22,6 +22,8 @@ struct vkms_config *vkms_config_create(const char *dev_na= me) return ERR_PTR(-ENOMEM); } =20 + INIT_LIST_HEAD(&config->planes); + return config; } EXPORT_SYMBOL_IF_KUNIT(vkms_config_create); @@ -31,28 +33,116 @@ 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_create_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_create_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_create_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); } EXPORT_SYMBOL_IF_KUNIT(vkms_config_default_create); =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); } EXPORT_SYMBOL_IF_KUNIT(vkms_config_destroy); =20 +static bool valid_plane_number(const struct vkms_config *config) +{ + struct drm_device *dev =3D config->dev ? &config->dev->drm : NULL; + size_t n_planes; + + n_planes =3D list_count_nodes((struct list_head *)&config->planes); + if (n_planes <=3D 0 || n_planes >=3D 32) { + drm_info(dev, "The number of planes must be between 1 and 31\n"); + return false; + } + + return true; +} + +static bool valid_plane_type(const struct vkms_config *config) +{ + struct drm_device *dev =3D config->dev ? &config->dev->drm : NULL; + struct vkms_config_plane *plane_cfg; + bool has_primary_plane =3D false; + bool has_cursor_plane =3D false; + + vkms_config_for_each_plane(config, plane_cfg) { + 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) { + drm_info(dev, "Multiple primary planes\n"); + return false; + } + + has_primary_plane =3D true; + } else if (type =3D=3D DRM_PLANE_TYPE_CURSOR) { + if (has_cursor_plane) { + drm_info(dev, "Multiple cursor planes\n"); + return false; + } + + has_cursor_plane =3D true; + } + } + + if (!has_primary_plane) { + drm_info(dev, "Primary plane not found\n"); + return false; + } + + return true; +} + bool vkms_config_is_valid(const struct vkms_config *config) { + if (!valid_plane_number(config)) + return false; + + if (!valid_plane_type(config)) + return false; + return true; } EXPORT_SYMBOL_IF_KUNIT(vkms_config_is_valid); @@ -63,12 +153,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); + + vkms_config_for_each_plane(vkmsdev->config, plane_cfg) { + seq_puts(m, "plane:\n"); + seq_printf(m, "\ttype=3D%d\n", + vkms_config_plane_get_type(plane_cfg)); + } =20 return 0; } @@ -82,3 +177,27 @@ 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_create_plane(struct vkms_config *con= fig) +{ + struct vkms_config_plane *plane_cfg; + + plane_cfg =3D kzalloc(sizeof(*plane_cfg), GFP_KERNEL); + if (!plane_cfg) + return ERR_PTR(-ENOMEM); + + plane_cfg->config =3D config; + vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_OVERLAY); + + list_add_tail(&plane_cfg->link, &config->planes); + + return plane_cfg; +} +EXPORT_SYMBOL_IF_KUNIT(vkms_config_create_plane); + +void vkms_config_destroy_plane(struct vkms_config_plane *plane_cfg) +{ + list_del(&plane_cfg->link); + kfree(plane_cfg); +} +EXPORT_SYMBOL_IF_KUNIT(vkms_config_destroy_plane); diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms= _config.h index 31c758631c37..613e98760640 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,46 @@ * * @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 + * @config: The vkms_config this plane belongs to + * @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; + struct vkms_config *config; + + enum drm_plane_type type; + + /* Internal usage */ + struct vkms_plane *plane; +}; + +/** + * vkms_config_for_each_plane - Iterate over the vkms_config planes + * @config: &struct vkms_config pointer + * @plane_cfg: &struct vkms_config_plane pointer used as cursor + */ +#define vkms_config_for_each_plane(config, plane_cfg) \ + list_for_each_entry((plane_cfg), &(config)->planes, link) + /** * vkms_config_create() - Create a new VKMS configuration * @dev_name: Name of the device @@ -84,4 +113,42 @@ bool vkms_config_is_valid(const struct vkms_config *con= fig); */ void vkms_config_register_debugfs(struct vkms_device *vkms_device); =20 +/** + * vkms_config_create_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_create_plane(struct vkms_config *con= fig); + +/** + * 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 414cc933af41..08ea691db299 100644 --- a/drivers/gpu/drm/vkms/vkms_output.c +++ b/drivers/gpu/drm/vkms/vkms_output.c @@ -11,28 +11,29 @@ 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; + struct vkms_plane *primary =3D NULL, *cursor =3D NULL; + struct vkms_config_plane *plane_cfg; int ret; int writeback; - unsigned int n; =20 if (!vkms_config_is_valid(vkmsdev->config)) return -EINVAL; =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); + vkms_config_for_each_plane(vkmsdev->config, plane_cfg) { + enum drm_plane_type type; =20 - if (vkmsdev->config->cursor) { - cursor =3D vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_CURSOR); - if (IS_ERR(cursor)) - return PTR_ERR(cursor); + 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"); + return PTR_ERR(plane_cfg->plane); + } + + 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, @@ -42,17 +43,6 @@ int vkms_output_init(struct vkms_device *vkmsdev) return PTR_ERR(output); } =20 - 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); - } - } - connector =3D vkms_connector_init(vkmsdev); if (IS_ERR(connector)) { DRM_ERROR("Failed to init connector\n"); --=20 2.48.1 From nobody Thu Dec 18 10:36:55 2025 Received: from mail-wr1-f53.google.com (mail-wr1-f53.google.com [209.85.221.53]) (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 61F5E23A993 for ; Tue, 18 Feb 2025 10:12:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739873554; cv=none; b=bOxdZusx7qA9/oRico7XChSDRGtSgUNCU2iK+kNYXekkKuYXOFVg3bhrskk4QZuHHl2h6l5h4GPvvf+Q8+7xVYIn239zpgUxjwn9QjqO+loUt75fDRwW0pd8SLaCQS+S79S1a4bsZvYXrXe+an6EEX7pZJQs7CCQC7+6yLFscn0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739873554; c=relaxed/simple; bh=JrteIYp5BHniGF3BfZ6Nx2vgzgS0uITKhAcetV/4j3Q=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=j0CyOXJALoK84AEpjVdz9fCrzOy/krjOoX1OrwPMX+pl6g+wPB2YhGnxb35JjbhwVyU7YBhlvNqTSI5MHlyn+zylMRrPegbqJisWvYEXZJ3IAu5lY5jNlq8DBMNlO8dBx4h/W2JgtEQWjfrYrXjxY/rtJstDoYbKCShBPkM2+r8= 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=QQpsaBXM; arc=none smtp.client-ip=209.85.221.53 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="QQpsaBXM" Received: by mail-wr1-f53.google.com with SMTP id ffacd0b85a97d-38f1e8efef5so2822800f8f.1 for ; Tue, 18 Feb 2025 02:12:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1739873550; x=1740478350; 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=g7PM6zrdnrOUlqVaTX6Gb4KKvYDoSsi4rkHPEyXeezU=; b=QQpsaBXMkTapFfdpQf5+WsJcaQm382pXTNJ1plxrs4+NUIwHnqkC24ucux0jU0iQ0m zHhI5fUeptkajxcRZ+GhQNQg/SMSb1pc2BS3Fe+6hiD0mWfWLthS+QjkMfXhvKJba+3w m2ooDUV5VIoVLzf96RI8ll/SqWhP4NfxmPkdJZ3Xjv6pGTvjlk2YMtPvNhYZgqqd5EAI 1Q83VGb+4W4hq1ZCbLMFEeNUA35MRlP2Cc96ztRpIl+j5XfS7jM0VIvmw0IX5ebu6V1X loK52/+Ake7skyCLsclniwk1WnkIOL6c+OWxmfy5KnUncZlpwOWgMmnVFTwDjCIUHExs q25w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1739873550; x=1740478350; 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=g7PM6zrdnrOUlqVaTX6Gb4KKvYDoSsi4rkHPEyXeezU=; b=FEP+XBMzWK9BNSYV92W/+2o13jAgC0Xjl5fw1BI9nZwfJDM0U4DZx8FoA4IKG9XbMQ 16Tp3S82/3cKPsKk4L/htgGolkGPBWsENE1WzfAWuQwiq7s0+YuRbGVzDfIKf3gmaCj7 SyYK+8rwxoH+YMJNExvZ6IM1dbj2Bh4eG1YvKq3qm+/IP/nMe2NlDKI0DSFGfwXPAIc0 u9tNMjY95EkqdWgfYKFch75UWzRYXIlOD73hAMOTdGJkIV0lyYaHI158BLJ07ycgaqmS /zZg7qSgLDkagOtTRfUXfdl3O5HCHuJIW7Hq+fxoqUYVEo+j3B5q0kGukOZmC80Q8tAY JXcA== X-Forwarded-Encrypted: i=1; AJvYcCVFrKPo9LbJaKJcePs6Tya0f2rx9oBai9MljvgIzRmj7jlrNS3eKOBfsQUr001VkpSXqhGVIinwIOrRxMs=@vger.kernel.org X-Gm-Message-State: AOJu0Yy4x6znAbNOS7XFLVLI//4ApY+SSNdabkND8XUN9CEW4qFS6ZUw Da9RVYfvaGwPOAfcjPu1MOjtZMzgDvg/Vgo/O/rvRGkwZ+3gPBd2 X-Gm-Gg: ASbGncvK+wGB5fG/WSL1xabYTDiMg8Iot08WDwQ0SFaZxRlquY0WF1zW/22SBtK3NZ9 VlsWPeJp0q3QCc3rxP6vSUyXWjFPnaQq9lhcYhlZfxTCCDAV7WKwTk/mf75DZ9ihOmS+LfjJ1G8 l6LpmA9ximEfkENi5iMi3cQrxcSWEJW0afF8woGxoDz75PzlBoE/jUX/GwKvNHJxUOzIPtt35sq XDpQMCwQcmj+VoT+U9awTjqjNx2xGb+1T+BSJlufGd7Zkna+mOYwvPbdLkBZiNp1aUjvgWJLzTh wWYC2TCQTEOrafggKg== X-Google-Smtp-Source: AGHT+IFzyH+cSQTx2cwyV6aD4CTwN0Tzy/I02hfI32Z6goKZXo1clWdpjl1Uf5CmtwD08iki6i0jFQ== X-Received: by 2002:a5d:638a:0:b0:38d:dfdc:52a2 with SMTP id ffacd0b85a97d-38f33f531e1mr10770784f8f.40.1739873550382; Tue, 18 Feb 2025 02:12:30 -0800 (PST) Received: from fedora.. ([213.94.27.232]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-38f259d5e92sm14749720f8f.66.2025.02.18.02.12.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Feb 2025 02:12:30 -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 v4 09/14] drm/vkms: Allow to configure multiple CRTCs Date: Tue, 18 Feb 2025 11:12:09 +0100 Message-ID: <20250218101214.5790-10-jose.exposito89@gmail.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250218101214.5790-1-jose.exposito89@gmail.com> References: <20250218101214.5790-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. Reviewed-by: Louis Chauvet Co-developed-by: Louis Chauvet Signed-off-by: Louis Chauvet Signed-off-by: Jos=C3=A9 Exp=C3=B3sito --- .clang-format | 1 + drivers/gpu/drm/vkms/tests/vkms_config_test.c | 83 ++++++++++++++++++- drivers/gpu/drm/vkms/vkms_config.c | 63 +++++++++++++- drivers/gpu/drm/vkms/vkms_config.h | 80 ++++++++++++++++++ 4 files changed, 222 insertions(+), 5 deletions(-) diff --git a/.clang-format b/.clang-format index c585d2a5b395..e7a901c3617d 100644 --- a/.clang-format +++ b/.clang-format @@ -690,6 +690,7 @@ ForEachMacros: - 'v4l2_m2m_for_each_src_buf' - 'v4l2_m2m_for_each_src_buf_safe' - 'virtio_device_for_each_vq' + - 'vkms_config_for_each_crtc' - 'vkms_config_for_each_plane' - 'while_for_each_ftrace_op' - 'xa_for_each' diff --git a/drivers/gpu/drm/vkms/tests/vkms_config_test.c b/drivers/gpu/dr= m/vkms/tests/vkms_config_test.c index 116db01ba8a0..104120c91c39 100644 --- a/drivers/gpu/drm/vkms/tests/vkms_config_test.c +++ b/drivers/gpu/drm/vkms/tests/vkms_config_test.c @@ -27,6 +27,16 @@ static struct vkms_config_plane *get_first_plane(struct = vkms_config *config) return NULL; } =20 +static struct vkms_config_crtc *get_first_crtc(struct vkms_config *config) +{ + struct vkms_config_crtc *crtc_cfg; + + vkms_config_for_each_crtc(config, crtc_cfg) + return crtc_cfg; + + return NULL; +} + struct default_config_case { bool enable_cursor; bool enable_writeback; @@ -46,6 +56,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_EQ(test, vkms_config_get_num_planes(config), 0); + KUNIT_EXPECT_EQ(test, vkms_config_get_num_crtcs(config), 0); =20 KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config)); =20 @@ -70,6 +81,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; @@ -79,8 +91,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 */ vkms_config_for_each_plane(config, plane_cfg) { switch (vkms_config_plane_get_type(plane_cfg)) { @@ -101,6 +111,13 @@ static void vkms_config_test_default_config(struct kun= it *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 */ + KUNIT_EXPECT_EQ(test, vkms_config_get_num_crtcs(config), 1); + + crtc_cfg =3D get_first_crtc(config); + 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); @@ -149,6 +166,43 @@ 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_cfg; + struct vkms_config_crtc *crtc_cfg1, *crtc_cfg2; + + config =3D vkms_config_create("test"); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config); + + KUNIT_ASSERT_EQ(test, vkms_config_get_num_crtcs(config), 0); + vkms_config_for_each_crtc(config, crtc_cfg) + KUNIT_FAIL(test, "Unexpected CRTC"); + + crtc_cfg1 =3D vkms_config_create_crtc(config); + KUNIT_ASSERT_EQ(test, vkms_config_get_num_crtcs(config), 1); + vkms_config_for_each_crtc(config, crtc_cfg) { + if (crtc_cfg !=3D crtc_cfg1) + KUNIT_FAIL(test, "Unexpected CRTC"); + } + + crtc_cfg2 =3D vkms_config_create_crtc(config); + KUNIT_ASSERT_EQ(test, vkms_config_get_num_crtcs(config), 2); + vkms_config_for_each_crtc(config, crtc_cfg) { + if (crtc_cfg !=3D crtc_cfg1 && crtc_cfg !=3D crtc_cfg2) + KUNIT_FAIL(test, "Unexpected CRTC"); + } + + vkms_config_destroy_crtc(config, crtc_cfg2); + KUNIT_ASSERT_EQ(test, vkms_config_get_num_crtcs(config), 1); + vkms_config_for_each_crtc(config, crtc_cfg) { + if (crtc_cfg !=3D crtc_cfg1) + KUNIT_FAIL(test, "Unexpected CRTC"); + } + + vkms_config_destroy(config); +} + static void vkms_config_test_invalid_plane_number(struct kunit *test) { struct vkms_config *config; @@ -213,13 +267,38 @@ static void vkms_config_test_valid_plane_type(struct = kunit *test) vkms_config_destroy(config); } =20 +static void vkms_config_test_invalid_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 get_first_crtc(config); + 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_create_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_invalid_plane_number), KUNIT_CASE(vkms_config_test_valid_plane_type), + KUNIT_CASE(vkms_config_test_invalid_crtc_number), {} }; =20 diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms= _config.c index 3c3f5cf79058..d195db770fae 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); =20 return config; } @@ -34,19 +35,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_create_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_create_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_create_plane(config); @@ -75,10 +80,14 @@ EXPORT_SYMBOL_IF_KUNIT(vkms_config_default_create); 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); } @@ -135,11 +144,28 @@ static bool valid_plane_type(const struct vkms_config= *config) return true; } =20 +static bool valid_crtc_number(const struct vkms_config *config) +{ + struct drm_device *dev =3D config->dev ? &config->dev->drm : NULL; + size_t n_crtcs; + + n_crtcs =3D list_count_nodes((struct list_head *)&config->crtcs); + if (n_crtcs <=3D 0 || n_crtcs >=3D 32) { + drm_info(dev, "The number of CRTCs must be between 1 and 31\n"); + return false; + } + + return true; +} + bool vkms_config_is_valid(const 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 @@ -154,10 +180,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 vkms_config_for_each_plane(vkmsdev->config, plane_cfg) { seq_puts(m, "plane:\n"); @@ -165,6 +191,12 @@ static int vkms_config_show(struct seq_file *m, void *= data) vkms_config_plane_get_type(plane_cfg)); } =20 + vkms_config_for_each_crtc(vkmsdev->config, crtc_cfg) { + seq_puts(m, "crtc:\n"); + seq_printf(m, "\twriteback=3D%d\n", + vkms_config_crtc_get_writeback(crtc_cfg)); + } + return 0; } =20 @@ -201,3 +233,28 @@ void vkms_config_destroy_plane(struct vkms_config_plan= e *plane_cfg) kfree(plane_cfg); } EXPORT_SYMBOL_IF_KUNIT(vkms_config_destroy_plane); + +struct vkms_config_crtc *vkms_config_create_crtc(struct vkms_config *confi= g) +{ + struct vkms_config_crtc *crtc_cfg; + + crtc_cfg =3D kzalloc(sizeof(*crtc_cfg), GFP_KERNEL); + if (!crtc_cfg) + return ERR_PTR(-ENOMEM); + + crtc_cfg->config =3D config; + vkms_config_crtc_set_writeback(crtc_cfg, false); + + list_add_tail(&crtc_cfg->link, &config->crtcs); + + return crtc_cfg; +} +EXPORT_SYMBOL_IF_KUNIT(vkms_config_create_crtc); + +void vkms_config_destroy_crtc(struct vkms_config *config, + struct vkms_config_crtc *crtc_cfg) +{ + list_del(&crtc_cfg->link); + kfree(crtc_cfg); +} +EXPORT_SYMBOL_IF_KUNIT(vkms_config_destroy_crtc); diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms= _config.h index 613e98760640..978418db84b9 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 @@ -45,6 +47,27 @@ struct vkms_config_plane { struct vkms_plane *plane; }; =20 +/** + * struct vkms_config_crtc + * + * @link: Link to the others CRTCs in vkms_config + * @config: The vkms_config this CRTC belongs to + * @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; + struct vkms_config *config; + + bool writeback; + + /* Internal usage */ + struct vkms_output *crtc; +}; + /** * vkms_config_for_each_plane - Iterate over the vkms_config planes * @config: &struct vkms_config pointer @@ -53,6 +76,14 @@ struct vkms_config_plane { #define vkms_config_for_each_plane(config, plane_cfg) \ list_for_each_entry((plane_cfg), &(config)->planes, link) =20 +/** + * vkms_config_for_each_crtc - Iterate over the vkms_config CRTCs + * @config: &struct vkms_config pointer + * @crtc_cfg: &struct vkms_config_crtc pointer used as cursor + */ +#define vkms_config_for_each_crtc(config, crtc_cfg) \ + list_for_each_entry((crtc_cfg), &(config)->crtcs, link) + /** * vkms_config_create() - Create a new VKMS configuration * @dev_name: Name of the device @@ -96,6 +127,15 @@ vkms_config_get_device_name(struct vkms_config *config) return config->dev_name; } =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_is_valid() - Validate a configuration * @config: Configuration to validate @@ -151,4 +191,44 @@ vkms_config_plane_set_type(struct vkms_config_plane *p= lane_cfg, plane_cfg->type =3D type; } =20 +/** + * vkms_config_create_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_create_crtc(struct vkms_config *confi= g); + +/** + * 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_ */ --=20 2.48.1 From nobody Thu Dec 18 10:36:55 2025 Received: from mail-wm1-f50.google.com (mail-wm1-f50.google.com [209.85.128.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 96DC823F296 for ; Tue, 18 Feb 2025 10:12:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739873556; cv=none; b=PJ+chp5kT4OjP2FHpb8jIMXHzcMGmQ20lkGg3MWsRoMtP38TBlrWy6uSy4x2oiVGRHPOfYO9DQumPVkbRutzQsRyAzxYk6JDkhdMgpoYr5cySbwWvYE0udtAw33KPQGzNULJamRrdvT/B8KkJY0MCLv5vLcJjUBnkXuR26nfZ0M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739873556; c=relaxed/simple; bh=a4ElrdpwVXpCQL7dKsThLcYntyabpDhRSXfRoVBxI/E=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=tW1OyTRZUDe4HEjYkrfx2ZieoSGAj/gVSG7XuMBkZdBaIFRFNMffvpUmuwuctGNimGJ8fM8o1SCLMHT6GvP+KbxiG3/FgAPm3U+c4qayFm1A/2NPkC5cKD1KctB5v4AniIfNprruAhGADK93FjyAspqZopR/1RDQdREIkKYcDcY= 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=HH4Dkvbd; arc=none smtp.client-ip=209.85.128.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="HH4Dkvbd" Received: by mail-wm1-f50.google.com with SMTP id 5b1f17b1804b1-43937cf2131so35085095e9.2 for ; Tue, 18 Feb 2025 02:12:33 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1739873552; x=1740478352; 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=Rfe2c/w4yYGc2jUSMRT4IzcezaRR9Jxw3SRE879VZ2w=; b=HH4Dkvbdou26C9YOCQdCFaekJtdDxI/uP/N/u79rMz99a7foll6Ye2Oh9Kzdojc7ef 4Uj5GzEFpiexkJgjhfjz/LFurvGo1KDlyL+D66sb1r0nw8/3w74n+CSHGvwcn6HwhB8p e9bZFh4NcYiFkH1jHTK15JBDv85yOJ23YD1BEQzWO1SBlElIhYAJ1fYx9jj/Oe4tPI1c tMIa+oFqJoWIXrwPg2B8954I9RJ1xiGAnJX+S9B0vStzE3wZ5P6bnrwzSRW/SzKOmlt8 ZIlE9g/qtuxnWrQ9ub+tG8oV3ne7LjjqkI/0YgjeWYwQzE/PRUan0kP2r7tvGqyASLzE S9XQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1739873552; x=1740478352; 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=Rfe2c/w4yYGc2jUSMRT4IzcezaRR9Jxw3SRE879VZ2w=; b=XDzHlw9ueEqXsclVq9YWRRk9H1nWK9oMrChKC0jtS5j8+0CntyV2PD/sGcofUYIa8+ g6RhLqSTR9cviwUszEAT02rmPo7UuP6CuiI/9ifeLScfBinbN1RdVTk3TYKxKG+uYDC1 ZOxrDF1PssyiWqvXW5/lltrtmdZoMvF3Rv7Gt/nNrdGrxG9d+/1fFlPqnq2dk9SkEB1O 92zIdcGksLHHmTcMT69h7K8ZtZGa+DTh7y677zX9/e0ZbTjSQH2KRyGltRTX9BmVunoM NWLC6syanTNDtpGR5j9YRsF+fLRjOEk4+eQUJnNDkttGBVHXSbCZEdBH4XYJScJsTHhb jW9w== X-Forwarded-Encrypted: i=1; AJvYcCW9XY4DXt3s6vJP3J+mxq8MuPF5Pq8nvGI2rtJzXt1rt8vEjHGM/s78ac2plfeRncqDzQn2VkoPH2pvTNY=@vger.kernel.org X-Gm-Message-State: AOJu0Yy741X5KseIdIvJv5/sMg2G5N2yfVz/y1+3rz34lkHwI20+Gc6X auXMi1rx/iIx46jr0AQ994Rvdgs6weW5oiImURl95tcFmq5w+WZo X-Gm-Gg: ASbGncuisQd4eyh6T5lHK1TMzm/GjP/rTZw/FJ4O++HSDN/hQVAWUKi0qcnXf2W/F7G ZBTaD0ZmsdTSxn/H0kW6NYmPcPKU+m+xmb8d5aBpSQKnzv8YF7+x33HAg5+wBDjl36iiCexK4eh T8MFjn99U6prXFvHCBaV8zBW4/meQza3xQNZwliwV+MH+AoIprzewynXKBO67cfXN8KH/wHmJUv K6e+end8JZmCoeED5wJXA5LyVjFgJpCt8U9yTz0sMV1+w/rgiiI3TY1iqaJoXxBpTXyjtsXTdft Ea4/rS4o8wmnTfAOWg== X-Google-Smtp-Source: AGHT+IFq19ppFLrzdssvti0OfQMaqZsLO7r8CXrtLyu5zD+ypnAc7vgPsZoR2nQ+w9y/vu8OEG333g== X-Received: by 2002:a05:600c:a384:b0:439:88bb:d017 with SMTP id 5b1f17b1804b1-43988bbd458mr55401175e9.6.1739873551564; Tue, 18 Feb 2025 02:12:31 -0800 (PST) Received: from fedora.. ([213.94.27.232]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-38f259d5e92sm14749720f8f.66.2025.02.18.02.12.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Feb 2025 02:12:30 -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 v4 10/14] drm/vkms: Allow to attach planes and CRTCs Date: Tue, 18 Feb 2025 11:12:10 +0100 Message-ID: <20250218101214.5790-11-jose.exposito89@gmail.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250218101214.5790-1-jose.exposito89@gmail.com> References: <20250218101214.5790-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. Reviewed-by: Louis Chauvet Co-developed-by: Louis Chauvet Signed-off-by: Louis Chauvet Signed-off-by: Jos=C3=A9 Exp=C3=B3sito --- .clang-format | 1 + drivers/gpu/drm/vkms/tests/vkms_config_test.c | 222 ++++++++++++++++++ drivers/gpu/drm/vkms/vkms_config.c | 154 ++++++++++-- drivers/gpu/drm/vkms/vkms_config.h | 59 ++++- drivers/gpu/drm/vkms/vkms_drv.c | 3 +- drivers/gpu/drm/vkms/vkms_output.c | 51 ++-- 6 files changed, 454 insertions(+), 36 deletions(-) diff --git a/.clang-format b/.clang-format index e7a901c3617d..6f944fa39841 100644 --- a/.clang-format +++ b/.clang-format @@ -692,6 +692,7 @@ ForEachMacros: - 'virtio_device_for_each_vq' - 'vkms_config_for_each_crtc' - 'vkms_config_for_each_plane' + - 'vkms_config_plane_for_each_possible_crtc' - 'while_for_each_ftrace_op' - 'xa_for_each' - 'xa_for_each_marked' diff --git a/drivers/gpu/drm/vkms/tests/vkms_config_test.c b/drivers/gpu/dr= m/vkms/tests/vkms_config_test.c index 104120c91c39..0997ea924ab7 100644 --- a/drivers/gpu/drm/vkms/tests/vkms_config_test.c +++ b/drivers/gpu/drm/vkms/tests/vkms_config_test.c @@ -118,6 +118,18 @@ static void vkms_config_test_default_config(struct kun= it *test) KUNIT_EXPECT_EQ(test, vkms_config_crtc_get_writeback(crtc_cfg), params->enable_writeback); =20 + vkms_config_for_each_plane(config, plane_cfg) { + struct vkms_config_crtc *possible_crtc; + int n_possible_crtcs =3D 0; + unsigned long idx =3D 0; + + vkms_config_plane_for_each_possible_crtc(plane_cfg, 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); @@ -230,6 +242,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); @@ -237,16 +251,26 @@ static void vkms_config_test_valid_plane_type(struct = kunit *test) plane_cfg =3D get_first_plane(config); vkms_config_destroy_plane(plane_cfg); =20 + crtc_cfg =3D get_first_crtc(config); + /* Invalid: No primary plane */ plane_cfg =3D vkms_config_create_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_create_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_create_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 */ @@ -256,14 +280,50 @@ static void vkms_config_test_valid_plane_type(struct = kunit *test) /* Invalid: Multiple cursor planes */ plane_cfg =3D vkms_config_create_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_create_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_create_crtc(config); + KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config)); + + /* Valid: Second CRTC with a primary plane */ + plane_cfg =3D vkms_config_create_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 get_first_plane(config); + crtc_cfg =3D get_first_crtc(config); + + /* 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 @@ -290,6 +350,164 @@ static void vkms_config_test_invalid_crtc_number(stru= ct kunit *test) vkms_config_destroy(config); } =20 +static void vkms_config_test_attach_different_configs(struct kunit *test) +{ + struct vkms_config *config1, *config2; + struct vkms_config_plane *plane_cfg1, *plane_cfg2; + struct vkms_config_crtc *crtc_cfg1, *crtc_cfg2; + int err; + + config1 =3D vkms_config_create("test1"); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config1); + + config2 =3D vkms_config_create("test2"); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config2); + + plane_cfg1 =3D vkms_config_create_plane(config1); + crtc_cfg1 =3D vkms_config_create_crtc(config1); + + plane_cfg2 =3D vkms_config_create_plane(config2); + crtc_cfg2 =3D vkms_config_create_crtc(config2); + + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_cfg1); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_cfg2); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_cfg1); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_cfg2); + + err =3D vkms_config_plane_attach_crtc(plane_cfg1, crtc_cfg2); + KUNIT_EXPECT_NE(test, err, 0); + err =3D vkms_config_plane_attach_crtc(plane_cfg2, crtc_cfg1); + KUNIT_EXPECT_NE(test, err, 0); + + vkms_config_destroy(config1); + vkms_config_destroy(config2); +} + +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_create_plane(config); + vkms_config_plane_set_type(overlay_cfg, DRM_PLANE_TYPE_OVERLAY); + primary_cfg =3D vkms_config_create_plane(config); + vkms_config_plane_set_type(primary_cfg, DRM_PLANE_TYPE_PRIMARY); + cursor_cfg =3D vkms_config_create_plane(config); + vkms_config_plane_set_type(cursor_cfg, DRM_PLANE_TYPE_CURSOR); + + crtc_cfg =3D vkms_config_create_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 *possible_crtc; + unsigned long idx =3D 0; + int n_crtcs =3D 0; + int err; + + config =3D vkms_config_create("test"); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config); + + plane_cfg1 =3D vkms_config_create_plane(config); + plane_cfg2 =3D vkms_config_create_plane(config); + crtc_cfg1 =3D vkms_config_create_crtc(config); + crtc_cfg2 =3D vkms_config_create_crtc(config); + + /* No possible CRTCs */ + vkms_config_plane_for_each_possible_crtc(plane_cfg1, idx, possible_crtc) + KUNIT_FAIL(test, "Unexpected possible CRTC"); + + vkms_config_plane_for_each_possible_crtc(plane_cfg2, idx, possible_crtc) + KUNIT_FAIL(test, "Unexpected possible CRTC"); + + /* 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); + + vkms_config_plane_for_each_possible_crtc(plane_cfg1, idx, possible_crtc) { + n_crtcs++; + if (possible_crtc !=3D crtc_cfg1 && possible_crtc !=3D crtc_cfg2) + KUNIT_FAIL(test, "Unexpected possible CRTC"); + } + KUNIT_ASSERT_EQ(test, n_crtcs, 2); + n_crtcs =3D 0; + + vkms_config_plane_for_each_possible_crtc(plane_cfg2, idx, possible_crtc) + KUNIT_FAIL(test, "Unexpected possible CRTC"); + + /* Plane 1 attached to CRTC 1 and plane 2 to CRTC 2 */ + vkms_config_plane_detach_crtc(plane_cfg1, crtc_cfg2); + vkms_config_plane_for_each_possible_crtc(plane_cfg1, idx, possible_crtc) { + n_crtcs++; + if (possible_crtc !=3D crtc_cfg1) + KUNIT_FAIL(test, "Unexpected possible CRTC"); + } + KUNIT_ASSERT_EQ(test, n_crtcs, 1); + n_crtcs =3D 0; + + err =3D vkms_config_plane_attach_crtc(plane_cfg2, crtc_cfg2); + KUNIT_EXPECT_EQ(test, err, 0); + vkms_config_plane_for_each_possible_crtc(plane_cfg2, idx, possible_crtc) { + n_crtcs++; + if (possible_crtc !=3D crtc_cfg2) + KUNIT_FAIL(test, "Unexpected possible CRTC"); + } + KUNIT_ASSERT_EQ(test, n_crtcs, 1); + + 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, @@ -298,7 +516,11 @@ static struct kunit_case vkms_config_test_cases[] =3D { KUNIT_CASE(vkms_config_test_get_crtcs), KUNIT_CASE(vkms_config_test_invalid_plane_number), KUNIT_CASE(vkms_config_test_valid_plane_type), + KUNIT_CASE(vkms_config_test_valid_plane_possible_crtcs), KUNIT_CASE(vkms_config_test_invalid_crtc_number), + KUNIT_CASE(vkms_config_test_attach_different_configs), + 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 d195db770fae..458385413648 100644 --- a/drivers/gpu/drm/vkms/vkms_config.c +++ b/drivers/gpu/drm/vkms/vkms_config.c @@ -52,13 +52,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_create_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 @@ -66,7 +73,11 @@ struct vkms_config *vkms_config_default_create(bool enab= le_cursor, plane_cfg =3D vkms_config_create_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; @@ -107,7 +118,8 @@ static bool valid_plane_number(const struct vkms_config= *config) return true; } =20 -static bool valid_plane_type(const struct vkms_config *config) +static bool valid_planes_for_crtc(const struct vkms_config *config, + struct vkms_config_crtc *crtc_cfg) { struct drm_device *dev =3D config->dev ? &config->dev->drm : NULL; struct vkms_config_plane *plane_cfg; @@ -115,24 +127,31 @@ static bool valid_plane_type(const struct vkms_config= *config) bool has_cursor_plane =3D false; =20 vkms_config_for_each_plane(config, plane_cfg) { + 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) { - drm_info(dev, "Multiple primary planes\n"); - return false; - } + vkms_config_plane_for_each_possible_crtc(plane_cfg, 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) { - drm_info(dev, "Multiple cursor planes\n"); - return false; - } + if (type =3D=3D DRM_PLANE_TYPE_PRIMARY) { + if (has_primary_plane) { + drm_info(dev, "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) { + drm_info(dev, "Multiple cursor planes\n"); + return false; + } + + has_cursor_plane =3D true; + } } } =20 @@ -144,6 +163,21 @@ static bool valid_plane_type(const struct vkms_config = *config) return true; } =20 +static bool valid_plane_possible_crtcs(const struct vkms_config *config) +{ + struct drm_device *dev =3D config->dev ? &config->dev->drm : NULL; + struct vkms_config_plane *plane_cfg; + + vkms_config_for_each_plane(config, plane_cfg) { + if (xa_empty(&plane_cfg->possible_crtcs)) { + drm_info(dev, "All planes must have at least one possible CRTC\n"); + return false; + } + } + + return true; +} + static bool valid_crtc_number(const struct vkms_config *config) { struct drm_device *dev =3D config->dev ? &config->dev->drm : NULL; @@ -160,15 +194,22 @@ static bool valid_crtc_number(const struct vkms_confi= g *config) =20 bool vkms_config_is_valid(const 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 + vkms_config_for_each_crtc(config, crtc_cfg) { + if (!valid_planes_for_crtc(config, crtc_cfg)) + return false; + } + return true; } EXPORT_SYMBOL_IF_KUNIT(vkms_config_is_valid); @@ -220,6 +261,7 @@ struct vkms_config_plane *vkms_config_create_plane(stru= ct vkms_config *config) =20 plane_cfg->config =3D config; 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 @@ -229,11 +271,45 @@ EXPORT_SYMBOL_IF_KUNIT(vkms_config_create_plane); =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); } EXPORT_SYMBOL_IF_KUNIT(vkms_config_destroy_plane); =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; + + if (plane_cfg->config !=3D crtc_cfg->config) + return -EINVAL; + + vkms_config_plane_for_each_possible_crtc(plane_cfg, idx, possible_crtc) { + if (possible_crtc =3D=3D crtc_cfg) + return -EEXIST; + } + + return xa_alloc(&plane_cfg->possible_crtcs, &crtc_idx, crtc_cfg, + xa_limit_32b, GFP_KERNEL); +} +EXPORT_SYMBOL_IF_KUNIT(vkms_config_plane_attach_crtc); + +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; + + vkms_config_plane_for_each_possible_crtc(plane_cfg, idx, possible_crtc) { + if (possible_crtc =3D=3D crtc_cfg) + xa_erase(&plane_cfg->possible_crtcs, idx); + } +} +EXPORT_SYMBOL_IF_KUNIT(vkms_config_plane_detach_crtc); + struct vkms_config_crtc *vkms_config_create_crtc(struct vkms_config *confi= g) { struct vkms_config_crtc *crtc_cfg; @@ -254,7 +330,57 @@ EXPORT_SYMBOL_IF_KUNIT(vkms_config_create_crtc); void vkms_config_destroy_crtc(struct vkms_config *config, struct vkms_config_crtc *crtc_cfg) { + struct vkms_config_plane *plane_cfg; + + vkms_config_for_each_plane(config, plane_cfg) + vkms_config_plane_detach_crtc(plane_cfg, crtc_cfg); + list_del(&crtc_cfg->link); kfree(crtc_cfg); } EXPORT_SYMBOL_IF_KUNIT(vkms_config_destroy_crtc); + +/** + * vkms_config_crtc_get_plane() - Return the first attached plane to a CRT= C with + * the specific type + * @config: Configuration containing the CRTC and the plane + * @crtc_cfg: Only find planes attached to this CRTC + * @type: Plane type to search + * + * Returns: + * The first plane found attached to @crtc_cfg with the type @type. + */ +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 =3D 0; + + vkms_config_for_each_plane(config, plane_cfg) { + current_type =3D vkms_config_plane_get_type(plane_cfg); + + vkms_config_plane_for_each_possible_crtc(plane_cfg, 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); +} +EXPORT_SYMBOL_IF_KUNIT(vkms_config_crtc_primary_plane); + +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= ); +} +EXPORT_SYMBOL_IF_KUNIT(vkms_config_crtc_cursor_plane); diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms= _config.h index 978418db84b9..ad303b34ee03 100644 --- a/drivers/gpu/drm/vkms/vkms_config.h +++ b/drivers/gpu/drm/vkms/vkms_config.h @@ -5,6 +5,7 @@ =20 #include #include +#include =20 #include "vkms_drv.h" =20 @@ -12,14 +13,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; @@ -32,6 +31,7 @@ struct vkms_config { * @config: The vkms_config this plane belongs to * @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 @@ -42,6 +42,7 @@ struct vkms_config_plane { struct vkms_config *config; =20 enum drm_plane_type type; + struct xarray possible_crtcs; =20 /* Internal usage */ struct vkms_plane *plane; @@ -84,6 +85,16 @@ struct vkms_config_crtc { #define vkms_config_for_each_crtc(config, crtc_cfg) \ list_for_each_entry((crtc_cfg), &(config)->crtcs, link) =20 +/** + * vkms_config_plane_for_each_possible_crtc - Iterate over the vkms_config= _plane + * possible CRTCs + * @plane_cfg: &struct vkms_config_plane pointer + * @idx: Index of the cursor + * @possible_crtc: &struct vkms_config_crtc pointer used as cursor + */ +#define vkms_config_plane_for_each_possible_crtc(plane_cfg, idx, possible_= crtc) \ + xa_for_each(&(plane_cfg)->possible_crtcs, idx, (possible_crtc)) + /** * vkms_config_create() - Create a new VKMS configuration * @dev_name: Name of the device @@ -191,6 +202,22 @@ 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_detach_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_create_crtc() - Add a new CRTC configuration * @config: Configuration to add the CRTC to @@ -231,4 +258,32 @@ 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 + * + * Note that, if multiple primary planes are found, the first one is retur= ned. + * In this case, the configuration will be invalid. See vkms_config_is_val= id(). + * + * 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 + * + * Note that, if multiple cursor planes are found, the first one is return= ed. + * In this case, the configuration will be invalid. See vkms_config_is_val= id(). + * + * 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_drv.c b/drivers/gpu/drm/vkms/vkms_dr= v.c index ba977ef09b2b..a24d1655f7b8 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; diff --git a/drivers/gpu/drm/vkms/vkms_output.c b/drivers/gpu/drm/vkms/vkms= _output.c index 08ea691db299..f63bc8e3014b 100644 --- a/drivers/gpu/drm/vkms/vkms_output.c +++ b/drivers/gpu/drm/vkms/vkms_output.c @@ -10,9 +10,8 @@ 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_cfg; + struct vkms_config_crtc *crtc_cfg; int ret; int writeback; =20 @@ -29,18 +28,37 @@ int vkms_output_init(struct vkms_device *vkmsdev) DRM_DEV_ERROR(dev->dev, "Failed to init vkms plane\n"); return PTR_ERR(plane_cfg->plane); } + } + + vkms_config_for_each_crtc(vkmsdev->config, crtc_cfg) { + struct vkms_config_plane *primary, *cursor; + + primary =3D vkms_config_crtc_primary_plane(vkmsdev->config, crtc_cfg); + cursor =3D vkms_config_crtc_cursor_plane(vkmsdev->config, crtc_cfg); =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; + 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"); + return PTR_ERR(crtc_cfg->crtc); + } + + /* 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"); - return PTR_ERR(output); + vkms_config_for_each_plane(vkmsdev->config, plane_cfg) { + struct vkms_config_crtc *possible_crtc; + unsigned long idx =3D 0; + + vkms_config_plane_for_each_possible_crtc(plane_cfg, idx, possible_crtc) { + plane_cfg->plane->base.possible_crtcs |=3D + drm_crtc_mask(&possible_crtc->crtc->crtc); + } } =20 connector =3D vkms_connector_init(vkmsdev); @@ -60,7 +78,9 @@ int vkms_output_init(struct vkms_device *vkmsdev) DRM_ERROR("Failed to init encoder\n"); return ret; } - encoder->possible_crtcs =3D drm_crtc_mask(&output->crtc); + + vkms_config_for_each_crtc(vkmsdev->config, crtc_cfg) + encoder->possible_crtcs =3D drm_crtc_mask(&crtc_cfg->crtc->crtc); =20 /* Attach the encoder and the connector */ ret =3D drm_connector_attach_encoder(&connector->base, encoder); @@ -69,13 +89,6 @@ int vkms_output_init(struct vkms_device *vkmsdev) return ret; } =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 return ret; --=20 2.48.1 From nobody Thu Dec 18 10:36:55 2025 Received: from mail-wm1-f53.google.com (mail-wm1-f53.google.com [209.85.128.53]) (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 3F05023AE79 for ; Tue, 18 Feb 2025 10:12:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739873558; cv=none; b=nTM5nZKKobuDRFjFXSiOby2PF/hhJSPRPGpexuVnoFjXvUdUyOdt4QIxrjBx9PowlQ+m0F4W02wjsL20rtAMBF/oxo4EtseO6j3ClWEfgLgpXSBP//42rpchvME2NWyPAjUj0tj3XYko0rl3yAJaSBWmT1xBY3h0TWgZ4yt/tiI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739873558; c=relaxed/simple; bh=nulajHEEERR1365r/TFxLjMyBU3+56+P2YeeYKvLVzo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=oIqMjZQDCLT9VmXHdLEQeEtvOr3n+sBGBncTNuE0eI8gkY3xsK1KbpoIxI5O83FFV78PMuF89Cc+VlGLz5RdmT68QVHKbyBm2/3kPv1XbNctaakeu1JgomUoTXWK442AJIGOgIU67coVbeSo2KAqPj8lMRbnK1Oa4+5SmRXmu4c= 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=cpZmlfPH; arc=none smtp.client-ip=209.85.128.53 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="cpZmlfPH" Received: by mail-wm1-f53.google.com with SMTP id 5b1f17b1804b1-4393dc02b78so35074755e9.3 for ; Tue, 18 Feb 2025 02:12:33 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1739873552; x=1740478352; 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=KBjVklZQ9OCwyQwOKI4fxIHrYYWEcFK9JsNbJ51zcI0=; b=cpZmlfPHbHNJwsviaf0dtrg0L8L8aqRHwcu7YssHDbPxGdHaU3MoNlIdqWkhCgMLO7 SXUhQj1nQfBOVxGlgJqmRsGQEkLwsPVBVplzZcDaffIMfMetWGgQM6Svkbb+ezX3zA1e 9ZpGzUsvkYNTaxvEcrBz9cQQzFZLBq5ESW8GP2MFD8W1yoI4H4X7V4l6rSxp5IY4CyD6 EISZ4ysiIySEXBAIIBqxQceBlFktDsvihNDs1LOsW0KYur08qyMu2TtntgBjsrzRNihz 22uTZPcC4Ec4qRZ4Y2guWYOCGpZ0/QNHtZrLlHvVZFY5yep7fmDachZixvd/FoblKKL7 aDrg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1739873552; x=1740478352; 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=KBjVklZQ9OCwyQwOKI4fxIHrYYWEcFK9JsNbJ51zcI0=; b=o1yBTCawXs5G7h88KZIGikcUbBEFuXSfq09gnGzuOx6FTNbJlncVHZXFmSVs0VtFT3 HufWohfiOQ4ZgVCO6n8GbCoMLZBhwWfF/+zP2RCG2/9elxtvl8OkHNymL314f6ZSYCSR RcF9bINmNk1u1N8lT81Q957f7yFzdLDYbNZRHH2i5ZCxh7/RUTNEXXy3D/hZptoubNbn xghiVygEBwQ+Kr6eAi0p9DSGYAi/uxGQ7yDBlVQf5ld3MpHDqOyzlATeY0x7Jy99qrSb QFsVHYYDDAKq/PTMVoPLaWd9fcFkkAWe1ht1/SsY61cl9LS5aOBBz7Y/rq+DKMeJZDlB H5lA== X-Forwarded-Encrypted: i=1; AJvYcCXaBLaYmZXA+ONejkPoFAL0dPokQaoWXu3gyivAs7GC2apn53QIQS2R2VASgualisKg5cHNiEXi39CJPro=@vger.kernel.org X-Gm-Message-State: AOJu0YzTILm228BfDEl6p01gssCvQVGgi7LC4LlLcQvsw3jMR3/Hrexu bjXUmP1Uv5BoaxGBPUyOw0V2ppfMClE8hejKGE/ctyjoKq+RxyZ3 X-Gm-Gg: ASbGncvQNT6ksELh37Lk/Q0/dLEKm5+JAMmM3lPZZO3beHGgTiIYIvWBameHRCmrsu6 Ya5I00/gZxmSAWu4pTTiOF0BRrrH9jjdktz/QZzcLoSYIX3n+xwuCna/1Y4PUa9S8Xqz97JFRq7 GGNd8icU9JIZ+M2ekj/wLOiRfPbO96rqQsQMtSxzEJ+u3AP6jPypNzxghkTBGHrKuh7tNOcXLiN PomiQ8p+nbLhAouyaWhjdqzYf5G4k70JNa3aAKLXv1KVCWSCuRcOwkgyBBlKJxDUJVF4w9TwC02 G3bVtncFEDr6bvjlEw== X-Google-Smtp-Source: AGHT+IHJC1ByGIX1z9OVlh16VS4LiaX4eyKthsNzPXOgFC97fhU0S3oxz12tutVqdaCqGewFseuBrg== X-Received: by 2002:a5d:59a7:0:b0:38f:3009:61d7 with SMTP id ffacd0b85a97d-38f33f11a04mr8854988f8f.4.1739873552409; Tue, 18 Feb 2025 02:12:32 -0800 (PST) Received: from fedora.. ([213.94.27.232]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-38f259d5e92sm14749720f8f.66.2025.02.18.02.12.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Feb 2025 02:12:32 -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 v4 11/14] drm/vkms: Allow to configure multiple encoders Date: Tue, 18 Feb 2025 11:12:11 +0100 Message-ID: <20250218101214.5790-12-jose.exposito89@gmail.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250218101214.5790-1-jose.exposito89@gmail.com> References: <20250218101214.5790-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. Reviewed-by: Louis Chauvet Co-developed-by: Louis Chauvet Signed-off-by: Louis Chauvet Signed-off-by: Jos=C3=A9 Exp=C3=B3sito --- .clang-format | 1 + drivers/gpu/drm/vkms/tests/vkms_config_test.c | 94 +++++++++++++++++++ drivers/gpu/drm/vkms/vkms_config.c | 54 +++++++++++ drivers/gpu/drm/vkms/vkms_config.h | 46 +++++++++ 4 files changed, 195 insertions(+) diff --git a/.clang-format b/.clang-format index 6f944fa39841..c355a2f58eed 100644 --- a/.clang-format +++ b/.clang-format @@ -691,6 +691,7 @@ ForEachMacros: - 'v4l2_m2m_for_each_src_buf_safe' - 'virtio_device_for_each_vq' - 'vkms_config_for_each_crtc' + - 'vkms_config_for_each_encoder' - 'vkms_config_for_each_plane' - 'vkms_config_plane_for_each_possible_crtc' - 'while_for_each_ftrace_op' diff --git a/drivers/gpu/drm/vkms/tests/vkms_config_test.c b/drivers/gpu/dr= m/vkms/tests/vkms_config_test.c index 0997ea924ab7..fa8b4f23cb49 100644 --- a/drivers/gpu/drm/vkms/tests/vkms_config_test.c +++ b/drivers/gpu/drm/vkms/tests/vkms_config_test.c @@ -17,6 +17,17 @@ static size_t vkms_config_get_num_planes(struct vkms_con= fig *config) return count; } =20 +static size_t vkms_config_get_num_encoders(struct vkms_config *config) +{ + struct vkms_config_encoder *encoder_cfg; + size_t count =3D 0; + + vkms_config_for_each_encoder(config, encoder_cfg) + count++; + + return count; +} + static struct vkms_config_plane *get_first_plane(struct vkms_config *confi= g) { struct vkms_config_plane *plane_cfg; @@ -37,6 +48,16 @@ static struct vkms_config_crtc *get_first_crtc(struct vk= ms_config *config) return NULL; } =20 +static struct vkms_config_encoder *get_first_encoder(struct vkms_config *c= onfig) +{ + struct vkms_config_encoder *encoder_cfg; + + vkms_config_for_each_encoder(config, encoder_cfg) + return encoder_cfg; + + return NULL; +} + struct default_config_case { bool enable_cursor; bool enable_writeback; @@ -57,6 +78,7 @@ static void vkms_config_test_empty_config(struct kunit *t= est) =20 KUNIT_EXPECT_EQ(test, vkms_config_get_num_planes(config), 0); KUNIT_EXPECT_EQ(test, vkms_config_get_num_crtcs(config), 0); + KUNIT_EXPECT_EQ(test, vkms_config_get_num_encoders(config), 0); =20 KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config)); =20 @@ -130,6 +152,9 @@ static void vkms_config_test_default_config(struct kuni= t *test) KUNIT_EXPECT_EQ(test, n_possible_crtcs, 1); } =20 + /* Encoders */ + KUNIT_EXPECT_EQ(test, vkms_config_get_num_encoders(config), 1); + KUNIT_EXPECT_TRUE(test, vkms_config_is_valid(config)); =20 vkms_config_destroy(config); @@ -215,6 +240,50 @@ 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_cfg; + struct vkms_config_encoder *encoder_cfg1, *encoder_cfg2; + int n_encoders =3D 0; + + config =3D vkms_config_create("test"); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config); + + vkms_config_for_each_encoder(config, encoder_cfg) + n_encoders++; + KUNIT_ASSERT_EQ(test, n_encoders, 0); + + encoder_cfg1 =3D vkms_config_create_encoder(config); + vkms_config_for_each_encoder(config, encoder_cfg) { + n_encoders++; + if (encoder_cfg !=3D encoder_cfg1) + KUNIT_FAIL(test, "Unexpected encoder"); + } + KUNIT_ASSERT_EQ(test, n_encoders, 1); + n_encoders =3D 0; + + encoder_cfg2 =3D vkms_config_create_encoder(config); + vkms_config_for_each_encoder(config, encoder_cfg) { + n_encoders++; + if (encoder_cfg !=3D encoder_cfg1 && encoder_cfg !=3D encoder_cfg2) + KUNIT_FAIL(test, "Unexpected encoder"); + } + KUNIT_ASSERT_EQ(test, n_encoders, 2); + n_encoders =3D 0; + + vkms_config_destroy_encoder(config, encoder_cfg2); + vkms_config_for_each_encoder(config, encoder_cfg) { + n_encoders++; + if (encoder_cfg !=3D encoder_cfg1) + KUNIT_FAIL(test, "Unexpected encoder"); + } + KUNIT_ASSERT_EQ(test, n_encoders, 1); + n_encoders =3D 0; + + vkms_config_destroy(config); +} + static void vkms_config_test_invalid_plane_number(struct kunit *test) { struct vkms_config *config; @@ -350,6 +419,29 @@ static void vkms_config_test_invalid_crtc_number(struc= t kunit *test) vkms_config_destroy(config); } =20 +static void vkms_config_test_invalid_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 get_first_encoder(config); + 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_create_encoder(config); + + KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config)); + + vkms_config_destroy(config); +} + static void vkms_config_test_attach_different_configs(struct kunit *test) { struct vkms_config *config1, *config2; @@ -514,10 +606,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_invalid_plane_number), KUNIT_CASE(vkms_config_test_valid_plane_type), KUNIT_CASE(vkms_config_test_valid_plane_possible_crtcs), KUNIT_CASE(vkms_config_test_invalid_crtc_number), + KUNIT_CASE(vkms_config_test_invalid_encoder_number), KUNIT_CASE(vkms_config_test_attach_different_configs), 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 458385413648..db8be054f6f4 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) =20 INIT_LIST_HEAD(&config->planes); INIT_LIST_HEAD(&config->crtcs); + INIT_LIST_HEAD(&config->encoders); =20 return config; } @@ -36,6 +37,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); @@ -80,6 +82,10 @@ struct vkms_config *vkms_config_default_create(bool enab= le_cursor, goto err_alloc; } =20 + encoder_cfg =3D vkms_config_create_encoder(config); + if (IS_ERR(encoder_cfg)) + goto err_alloc; + return config; =20 err_alloc: @@ -92,6 +98,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); @@ -99,6 +106,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); } @@ -192,6 +202,20 @@ static bool valid_crtc_number(const struct vkms_config= *config) return true; } =20 +static bool valid_encoder_number(const struct vkms_config *config) +{ + struct drm_device *dev =3D config->dev ? &config->dev->drm : NULL; + size_t n_encoders; + + n_encoders =3D list_count_nodes((struct list_head *)&config->encoders); + if (n_encoders <=3D 0 || n_encoders >=3D 32) { + drm_info(dev, "The number of encoders must be between 1 and 31\n"); + return false; + } + + return true; +} + bool vkms_config_is_valid(const struct vkms_config *config) { struct vkms_config_crtc *crtc_cfg; @@ -202,6 +226,9 @@ bool vkms_config_is_valid(const struct vkms_config *con= fig) if (!valid_crtc_number(config)) return false; =20 + if (!valid_encoder_number(config)) + return false; + if (!valid_plane_possible_crtcs(config)) return false; =20 @@ -222,6 +249,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); @@ -238,6 +266,9 @@ static int vkms_config_show(struct seq_file *m, void *d= ata) vkms_config_crtc_get_writeback(crtc_cfg)); } =20 + vkms_config_for_each_encoder(vkmsdev->config, encoder_cfg) + seq_puts(m, "encoder\n"); + return 0; } =20 @@ -384,3 +415,26 @@ 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= ); } EXPORT_SYMBOL_IF_KUNIT(vkms_config_crtc_cursor_plane); + +struct vkms_config_encoder *vkms_config_create_encoder(struct vkms_config = *config) +{ + struct vkms_config_encoder *encoder_cfg; + + encoder_cfg =3D kzalloc(sizeof(*encoder_cfg), GFP_KERNEL); + if (!encoder_cfg) + return ERR_PTR(-ENOMEM); + + encoder_cfg->config =3D config; + list_add_tail(&encoder_cfg->link, &config->encoders); + + return encoder_cfg; +} +EXPORT_SYMBOL_IF_KUNIT(vkms_config_create_encoder); + +void vkms_config_destroy_encoder(struct vkms_config *config, + struct vkms_config_encoder *encoder_cfg) +{ + list_del(&encoder_cfg->link); + kfree(encoder_cfg); +} +EXPORT_SYMBOL_IF_KUNIT(vkms_config_destroy_encoder); diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms= _config.h index ad303b34ee03..024cbed0e439 100644 --- a/drivers/gpu/drm/vkms/vkms_config.h +++ b/drivers/gpu/drm/vkms/vkms_config.h @@ -15,12 +15,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 @@ -69,6 +71,24 @@ struct vkms_config_crtc { struct vkms_output *crtc; }; =20 +/** + * struct vkms_config_encoder + * + * @link: Link to the others encoders in vkms_config + * @config: The vkms_config this CRTC belongs to + * @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; + struct vkms_config *config; + + /* Internal usage */ + struct drm_encoder *encoder; +}; + /** * vkms_config_for_each_plane - Iterate over the vkms_config planes * @config: &struct vkms_config pointer @@ -85,6 +105,14 @@ struct vkms_config_crtc { #define vkms_config_for_each_crtc(config, crtc_cfg) \ list_for_each_entry((crtc_cfg), &(config)->crtcs, link) =20 +/** + * vkms_config_for_each_encoder - Iterate over the vkms_config encoders + * @config: &struct vkms_config pointer + * @encoder_cfg: &struct vkms_config_encoder pointer used as cursor + */ +#define vkms_config_for_each_encoder(config, encoder_cfg) \ + list_for_each_entry((encoder_cfg), &(config)->encoders, link) + /** * vkms_config_plane_for_each_possible_crtc - Iterate over the vkms_config= _plane * possible CRTCs @@ -286,4 +314,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_create_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_create_encoder(struct vkms_config = *config); + +/** + * 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 Thu Dec 18 10:36:55 2025 Received: from mail-wr1-f46.google.com (mail-wr1-f46.google.com [209.85.221.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 20C1E2405E8 for ; Tue, 18 Feb 2025 10:12:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739873558; cv=none; b=lRiwryidI8P/jZTQ+5W890jQ26GRsS9JO8s/UuSUFkveuhjZn2/D6Dtm0qemOBqaxev9TS7rfBZ/lVJaiEm3kK3EcY67cIFNJ9oB3u/CNoOvy+Rp1CAYd2f3xfy/AnVSQZDrgHLOV/oYbYcZqLTOqkRP/2uvrqoXUqEw90CopPA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739873558; c=relaxed/simple; bh=VKouC1yHam4PYKIdm1UgvOuWvAtAfkCSnSnCSuP8yEU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=VqGQohIEa5BxssqWMZuMkv69/JKCrS+nQdCPdvSjo4zqAOv76vpi8Xq/mPXmp50FRXlKJigUy5cNR9C1dQr3rC02u46qyVImSU96pxufVyMcZIKJiHOBRtIV8/q4DpTTLnTwlnjEGpd+MhVEhLtUfwkRtQ8Zey7SXRwXktyOYVk= 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=K22OEZol; arc=none smtp.client-ip=209.85.221.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="K22OEZol" Received: by mail-wr1-f46.google.com with SMTP id ffacd0b85a97d-38f22fe8762so2649237f8f.2 for ; Tue, 18 Feb 2025 02:12:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1739873554; x=1740478354; 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=CnYiK1+icpg3ZrEtfUK020G2fBOmYV0BKtEcQQYSHs0=; b=K22OEZolVd5s0IlEHJWZO7tIt6TBRHMrz6hP+Nip5qzQ9cU/kYV+4UFHBvpXQ24TzR /sYNTAyCDk/qiBVF76wVWMZIrSErw12FkDu7/sX1tji9FjnxBV3PMLMzCEjX62GRNhR+ LM3zlXLhvP//4qb7m7kiyOxQp3PPd1adYPfYKXkVaps7VBf6kSDU/9cqA1M4vGvazQtG ZNqLlJ/iKKq2YRwSMD5PL8aFnmUWZBe9FihPrntOhE7DNW4ORUIvAIlF7VXTBPcYdZct O7vjiARDt5shvDup9a1csqvjoDja6hJ9wMLODGAts/sLSDqylI2cyOIdVYXRwVbDBMfb PlPA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1739873554; x=1740478354; 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=CnYiK1+icpg3ZrEtfUK020G2fBOmYV0BKtEcQQYSHs0=; b=IoY+nlkXlPp8XOwUvEzJwoE569zbDNDMKdOPwLg4gRyrUxfkkuHfYnsNGjspewjfgN D6dhpNDj9RoXgvnzesiXoFTLyL1GGvVyy6r0RmNgMZRiTP+JUc/01zIWOapezPIL+J9k QgtGS0to5EnzVjTEbK2x0G1aL9xuc3HJv8Vs/2ZAvfWt1ur8S2ytvph8RUmW1+RFwsDu hBZuufOrRqWElAkQLTZFIpbwk97ZE/2E9zmnRvC3r5zG+Fk4NMgh62EqdeqLT7WgPZoo 9JVQX5q6VjVy81+BawGKQxOJKO9ntwNZR2LuL1VxlB6vq9EK7jgc5oUOM9RZWvXOMdJH PCNQ== X-Forwarded-Encrypted: i=1; AJvYcCVaqes+wAGLNYDY/jl+bNCVJJhGq9ag8xjE0k1czyqB6qQYaaPexmjUxc1jlBZMQJE7gmD71M7nYvAh1eA=@vger.kernel.org X-Gm-Message-State: AOJu0YwVa+lNOOTYHR9smVsyiRMJnGZJ5dpQw63fS/Iu4MmxcaD7yyN4 d54uQy5wehOEOJ3d4MqxOm4aemkuZGH4jLVGVzUWpMeqHbY+8V+4 X-Gm-Gg: ASbGncv/cvwRQSwdNkFPlf4RilRKoOe+N8o4oEArCWOI4wtH2T7d4BsYp63huhMyjZa Wm6tgBZ/aDl/T8ufS/XljontvUI/Lfyn7IK0t3+gXZnnPzak/ntgVCLdweiobwtgiitlJprua6E QJW7flsTRK79ZHLRi7hTnxiQbAowAzu0a1MYJdYOMXSpPjeD9nGdnqsLWc8BB+dXIzbc4nN2g+8 TmXhfnChV0MtTysr2rgwvC9E2icYdz7iUL/zT60vioT60oluzTqejJaN546eJmiYUmWfv2RNtg5 ie/gBR9MKrCIoSQo3A== X-Google-Smtp-Source: AGHT+IG1ZmDjPTVP9m7Ze/D8DKfeL8z6cLrGwEJyuKNK1w3jBVvYy5CX24KspIt6i8rcja5vkrkxLw== X-Received: by 2002:a05:6000:400f:b0:38f:3ee5:fd36 with SMTP id ffacd0b85a97d-38f3ee5ff31mr7979577f8f.53.1739873554174; Tue, 18 Feb 2025 02:12:34 -0800 (PST) Received: from fedora.. ([213.94.27.232]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-38f259d5e92sm14749720f8f.66.2025.02.18.02.12.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Feb 2025 02:12:33 -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 v4 12/14] drm/vkms: Allow to attach encoders and CRTCs Date: Tue, 18 Feb 2025 11:12:12 +0100 Message-ID: <20250218101214.5790-13-jose.exposito89@gmail.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250218101214.5790-1-jose.exposito89@gmail.com> References: <20250218101214.5790-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. Reviewed-by: Louis Chauvet Co-developed-by: Louis Chauvet Signed-off-by: Louis Chauvet Signed-off-by: Jos=C3=A9 Exp=C3=B3sito --- .clang-format | 1 + drivers/gpu/drm/vkms/tests/vkms_config_test.c | 125 ++++++++++++++++++ drivers/gpu/drm/vkms/vkms_config.c | 82 ++++++++++++ drivers/gpu/drm/vkms/vkms_config.h | 29 ++++ drivers/gpu/drm/vkms/vkms_output.c | 49 ++++--- 5 files changed, 266 insertions(+), 20 deletions(-) diff --git a/.clang-format b/.clang-format index c355a2f58eed..5d21c0e4edbd 100644 --- a/.clang-format +++ b/.clang-format @@ -693,6 +693,7 @@ ForEachMacros: - 'vkms_config_for_each_crtc' - 'vkms_config_for_each_encoder' - 'vkms_config_for_each_plane' + - 'vkms_config_encoder_for_each_possible_crtc' - 'vkms_config_plane_for_each_possible_crtc' - 'while_for_each_ftrace_op' - 'xa_for_each' diff --git a/drivers/gpu/drm/vkms/tests/vkms_config_test.c b/drivers/gpu/dr= m/vkms/tests/vkms_config_test.c index fa8b4f23cb49..600f563dd0a8 100644 --- a/drivers/gpu/drm/vkms/tests/vkms_config_test.c +++ b/drivers/gpu/drm/vkms/tests/vkms_config_test.c @@ -312,6 +312,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); @@ -365,6 +366,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_create_crtc(config); + encoder_cfg =3D vkms_config_create_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 */ @@ -442,11 +446,57 @@ static void vkms_config_test_invalid_encoder_number(s= truct 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 get_first_crtc(config); + + /* Invalid: Encoder without a possible CRTC */ + encoder_cfg =3D vkms_config_create_encoder(config); + KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config)); + + /* Valid: Second CRTC with shared encoder */ + crtc_cfg2 =3D vkms_config_create_crtc(config); + + plane_cfg =3D vkms_config_create_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_attach_different_configs(struct kunit *test) { struct vkms_config *config1, *config2; struct vkms_config_plane *plane_cfg1, *plane_cfg2; struct vkms_config_crtc *crtc_cfg1, *crtc_cfg2; + struct vkms_config_encoder *encoder_cfg1, *encoder_cfg2; int err; =20 config1 =3D vkms_config_create("test1"); @@ -457,20 +507,29 @@ static void vkms_config_test_attach_different_configs= (struct kunit *test) =20 plane_cfg1 =3D vkms_config_create_plane(config1); crtc_cfg1 =3D vkms_config_create_crtc(config1); + encoder_cfg1 =3D vkms_config_create_encoder(config1); =20 plane_cfg2 =3D vkms_config_create_plane(config2); crtc_cfg2 =3D vkms_config_create_crtc(config2); + encoder_cfg2 =3D vkms_config_create_encoder(config2); =20 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_cfg1); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_cfg2); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_cfg1); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_cfg2); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, encoder_cfg1); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, encoder_cfg2); =20 err =3D vkms_config_plane_attach_crtc(plane_cfg1, crtc_cfg2); KUNIT_EXPECT_NE(test, err, 0); err =3D vkms_config_plane_attach_crtc(plane_cfg2, crtc_cfg1); KUNIT_EXPECT_NE(test, err, 0); =20 + err =3D vkms_config_encoder_attach_crtc(encoder_cfg1, crtc_cfg2); + KUNIT_EXPECT_NE(test, err, 0); + err =3D vkms_config_encoder_attach_crtc(encoder_cfg2, crtc_cfg1); + KUNIT_EXPECT_NE(test, err, 0); + vkms_config_destroy(config1); vkms_config_destroy(config2); } @@ -600,6 +659,70 @@ 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 *possible_crtc; + unsigned long idx =3D 0; + int n_crtcs =3D 0; + int err; + + config =3D vkms_config_create("test"); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config); + + encoder_cfg1 =3D vkms_config_create_encoder(config); + encoder_cfg2 =3D vkms_config_create_encoder(config); + crtc_cfg1 =3D vkms_config_create_crtc(config); + crtc_cfg2 =3D vkms_config_create_crtc(config); + + /* No possible CRTCs */ + vkms_config_encoder_for_each_possible_crtc(encoder_cfg1, idx, possible_cr= tc) + KUNIT_FAIL(test, "Unexpected possible CRTC"); + + vkms_config_encoder_for_each_possible_crtc(encoder_cfg2, idx, possible_cr= tc) + KUNIT_FAIL(test, "Unexpected possible CRTC"); + + /* 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); + + vkms_config_encoder_for_each_possible_crtc(encoder_cfg1, idx, possible_cr= tc) { + n_crtcs++; + if (possible_crtc !=3D crtc_cfg1 && possible_crtc !=3D crtc_cfg2) + KUNIT_FAIL(test, "Unexpected possible CRTC"); + } + KUNIT_ASSERT_EQ(test, n_crtcs, 2); + n_crtcs =3D 0; + + vkms_config_encoder_for_each_possible_crtc(encoder_cfg2, idx, possible_cr= tc) + KUNIT_FAIL(test, "Unexpected possible CRTC"); + + /* Encoder 1 attached to CRTC 1 and encoder 2 to CRTC 2 */ + vkms_config_encoder_detach_crtc(encoder_cfg1, crtc_cfg2); + vkms_config_encoder_for_each_possible_crtc(encoder_cfg1, idx, possible_cr= tc) { + n_crtcs++; + if (possible_crtc !=3D crtc_cfg1) + KUNIT_FAIL(test, "Unexpected possible CRTC"); + } + KUNIT_ASSERT_EQ(test, n_crtcs, 1); + n_crtcs =3D 0; + + err =3D vkms_config_encoder_attach_crtc(encoder_cfg2, crtc_cfg2); + KUNIT_EXPECT_EQ(test, err, 0); + vkms_config_encoder_for_each_possible_crtc(encoder_cfg2, idx, possible_cr= tc) { + n_crtcs++; + if (possible_crtc !=3D crtc_cfg2) + KUNIT_FAIL(test, "Unexpected possible CRTC"); + } + KUNIT_ASSERT_EQ(test, n_crtcs, 1); + + 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, @@ -612,9 +735,11 @@ static struct kunit_case vkms_config_test_cases[] =3D { KUNIT_CASE(vkms_config_test_valid_plane_possible_crtcs), KUNIT_CASE(vkms_config_test_invalid_crtc_number), KUNIT_CASE(vkms_config_test_invalid_encoder_number), + KUNIT_CASE(vkms_config_test_valid_encoder_possible_crtcs), KUNIT_CASE(vkms_config_test_attach_different_configs), 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 db8be054f6f4..17262a9c2567 100644 --- a/drivers/gpu/drm/vkms/vkms_config.c +++ b/drivers/gpu/drm/vkms/vkms_config.c @@ -86,6 +86,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: @@ -216,6 +219,42 @@ static bool valid_encoder_number(const struct vkms_con= fig *config) return true; } =20 +static bool valid_encoder_possible_crtcs(const struct vkms_config *config) +{ + struct drm_device *dev =3D config->dev ? &config->dev->drm : NULL; + struct vkms_config_crtc *crtc_cfg; + struct vkms_config_encoder *encoder_cfg; + + vkms_config_for_each_encoder(config, encoder_cfg) { + if (xa_empty(&encoder_cfg->possible_crtcs)) { + drm_info(dev, "All encoders must have at least one possible CRTC\n"); + return false; + } + } + + vkms_config_for_each_crtc(config, crtc_cfg) { + bool crtc_has_encoder =3D false; + + vkms_config_for_each_encoder(config, encoder_cfg) { + struct vkms_config_crtc *possible_crtc; + unsigned long idx =3D 0; + + vkms_config_encoder_for_each_possible_crtc(encoder_cfg, + idx, possible_crtc) { + if (possible_crtc =3D=3D crtc_cfg) + crtc_has_encoder =3D true; + } + } + + if (!crtc_has_encoder) { + drm_info(dev, "All CRTCs must have at least one possible encoder\n"); + return false; + } + } + + return true; +} + bool vkms_config_is_valid(const struct vkms_config *config) { struct vkms_config_crtc *crtc_cfg; @@ -237,6 +276,9 @@ bool vkms_config_is_valid(const struct vkms_config *con= fig) return false; } =20 + if (!valid_encoder_possible_crtcs(config)) + return false; + return true; } EXPORT_SYMBOL_IF_KUNIT(vkms_config_is_valid); @@ -362,10 +404,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 vkms_config_for_each_plane(config, plane_cfg) vkms_config_plane_detach_crtc(plane_cfg, crtc_cfg); =20 + vkms_config_for_each_encoder(config, encoder_cfg) + vkms_config_encoder_detach_crtc(encoder_cfg, crtc_cfg); + list_del(&crtc_cfg->link); kfree(crtc_cfg); } @@ -425,6 +471,8 @@ struct vkms_config_encoder *vkms_config_create_encoder(= struct vkms_config *confi return ERR_PTR(-ENOMEM); =20 encoder_cfg->config =3D config; + xa_init_flags(&encoder_cfg->possible_crtcs, XA_FLAGS_ALLOC); + list_add_tail(&encoder_cfg->link, &config->encoders); =20 return encoder_cfg; @@ -434,7 +482,41 @@ EXPORT_SYMBOL_IF_KUNIT(vkms_config_create_encoder); 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); } EXPORT_SYMBOL_IF_KUNIT(vkms_config_destroy_encoder); + +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; + + if (encoder_cfg->config !=3D crtc_cfg->config) + return -EINVAL; + + vkms_config_encoder_for_each_possible_crtc(encoder_cfg, idx, possible_crt= c) { + if (possible_crtc =3D=3D crtc_cfg) + return -EEXIST; + } + + return xa_alloc(&encoder_cfg->possible_crtcs, &crtc_idx, crtc_cfg, + xa_limit_32b, GFP_KERNEL); +} +EXPORT_SYMBOL_IF_KUNIT(vkms_config_encoder_attach_crtc); + +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; + + vkms_config_encoder_for_each_possible_crtc(encoder_cfg, idx, possible_crt= c) { + if (possible_crtc =3D=3D crtc_cfg) + xa_erase(&encoder_cfg->possible_crtcs, idx); + } +} +EXPORT_SYMBOL_IF_KUNIT(vkms_config_encoder_detach_crtc); diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms= _config.h index 024cbed0e439..3e5b2e407378 100644 --- a/drivers/gpu/drm/vkms/vkms_config.h +++ b/drivers/gpu/drm/vkms/vkms_config.h @@ -76,6 +76,7 @@ struct vkms_config_crtc { * * @link: Link to the others encoders in vkms_config * @config: The vkms_config this CRTC belongs to + * @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 @@ -85,6 +86,8 @@ struct vkms_config_encoder { struct list_head link; struct vkms_config *config; =20 + struct xarray possible_crtcs; + /* Internal usage */ struct drm_encoder *encoder; }; @@ -123,6 +126,16 @@ struct vkms_config_encoder { #define vkms_config_plane_for_each_possible_crtc(plane_cfg, idx, possible_= crtc) \ xa_for_each(&(plane_cfg)->possible_crtcs, idx, (possible_crtc)) =20 +/** + * vkms_config_encoder_for_each_possible_crtc - Iterate over the + * vkms_config_encoder possible CRTCs + * @encoder_cfg: &struct vkms_config_encoder pointer + * @idx: Index of the cursor + * @possible_crtc: &struct vkms_config_crtc pointer used as cursor + */ +#define vkms_config_encoder_for_each_possible_crtc(encoder_cfg, idx, possi= ble_crtc) \ + xa_for_each(&(encoder_cfg)->possible_crtcs, idx, (possible_crtc)) + /** * vkms_config_create() - Create a new VKMS configuration * @dev_name: Name of the device @@ -332,4 +345,20 @@ struct vkms_config_encoder *vkms_config_create_encoder= (struct vkms_config *confi 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); + #endif /* _VKMS_CONFIG_H_ */ diff --git a/drivers/gpu/drm/vkms/vkms_output.c b/drivers/gpu/drm/vkms/vkms= _output.c index f63bc8e3014b..8920d6b5d105 100644 --- a/drivers/gpu/drm/vkms/vkms_output.c +++ b/drivers/gpu/drm/vkms/vkms_output.c @@ -9,9 +9,9 @@ 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_cfg; struct vkms_config_crtc *crtc_cfg; + struct vkms_config_encoder *encoder_cfg; int ret; int writeback; =20 @@ -61,32 +61,41 @@ int vkms_output_init(struct vkms_device *vkmsdev) } } =20 + vkms_config_for_each_encoder(vkmsdev->config, encoder_cfg) { + struct vkms_config_crtc *possible_crtc; + unsigned long idx =3D 0; + + encoder_cfg->encoder =3D drmm_kzalloc(dev, sizeof(*encoder_cfg->encoder)= , GFP_KERNEL); + if (!encoder_cfg->encoder) { + DRM_ERROR("Failed to allocate encoder\n"); + return -ENOMEM; + } + ret =3D drmm_encoder_init(dev, encoder_cfg->encoder, NULL, + DRM_MODE_ENCODER_VIRTUAL, NULL); + if (ret) { + DRM_ERROR("Failed to init encoder\n"); + return ret; + } + + vkms_config_encoder_for_each_possible_crtc(encoder_cfg, idx, possible_cr= tc) { + encoder_cfg->encoder->possible_crtcs |=3D + drm_crtc_mask(&possible_crtc->crtc->crtc); + } + } + connector =3D vkms_connector_init(vkmsdev); if (IS_ERR(connector)) { DRM_ERROR("Failed to init connector\n"); return PTR_ERR(connector); } =20 - encoder =3D drmm_kzalloc(dev, sizeof(*encoder), GFP_KERNEL); - if (!encoder) { - DRM_ERROR("Failed to allocate encoder\n"); - return -ENOMEM; - } - ret =3D drmm_encoder_init(dev, encoder, NULL, - DRM_MODE_ENCODER_VIRTUAL, NULL); - if (ret) { - DRM_ERROR("Failed to init encoder\n"); - return ret; - } - - vkms_config_for_each_crtc(vkmsdev->config, crtc_cfg) - encoder->possible_crtcs =3D drm_crtc_mask(&crtc_cfg->crtc->crtc); - /* Attach the encoder and the connector */ - ret =3D drm_connector_attach_encoder(&connector->base, encoder); - if (ret) { - DRM_ERROR("Failed to attach connector to encoder\n"); - return ret; + vkms_config_for_each_encoder(vkmsdev->config, encoder_cfg) { + ret =3D drm_connector_attach_encoder(&connector->base, encoder_cfg->enco= der); + if (ret) { + DRM_ERROR("Failed to attach connector to encoder\n"); + return ret; + } } =20 drm_mode_config_reset(dev); --=20 2.48.1 From nobody Thu Dec 18 10:36:55 2025 Received: from mail-wr1-f53.google.com (mail-wr1-f53.google.com [209.85.221.53]) (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 0313823F28F for ; Tue, 18 Feb 2025 10:12:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739873559; cv=none; b=kfbT7p0TYJ7zNbxQe3Q6HvSs+T++8yUleFwGzpb5xImIYxlY+KIMZ1Vi71WwNcuU7vykrB+8+iySoVBEv2Z/WRbiFMNjjFNhHBc1KX1M6YV50w/muV+IObnoAKJbj2eIQUH8hUVv/aeRfI1JMECjbOvurKs83MKuFmhmTJkHZPE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739873559; c=relaxed/simple; bh=XZQ+Q8A5Y0liE+1KUSzLWzwiz+Hyqy4l7o8jyzBR74k=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=c+dUavZuI4XF50RRMQgYzV1XO0OKQM5IDOmU0OurwpMaqkNHYadr3IoSHvcJscxKD4D5B4xtbC19wk2B4Pc2FaVfzLthkaWx6BR/iXpIq8149ce0gQYXeEK2MOs9Bn9Ju9TDmOsWsnHF0uQqpLtrpysBFE/dKQZsCYKwO+xhItg= 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=OHIvjfeG; arc=none smtp.client-ip=209.85.221.53 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="OHIvjfeG" Received: by mail-wr1-f53.google.com with SMTP id ffacd0b85a97d-388cae9eb9fso2673229f8f.3 for ; Tue, 18 Feb 2025 02:12:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1739873555; x=1740478355; 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=okm3LTa2KT6tlsIpTZr55gU34qeQ+5Qm8WrnAeHUzZI=; b=OHIvjfeGwbBwsXMHLK5hrbeA6AY3Rz53G/qg9h9eqjVEISRRhYdmifeS0Kc6JSqiET q8jC/t3nnhx7ZDvReFTFSVgEiHJIrpEW+0641Wk1ZtsRjiUKw3QfpZOdomKgVmEXpt9I ar0kVDwM3oAMLhnwqBfMsls1jEbAAQ9TUTBl8x+wDJ7VCKT8VBs/0Yf5lITOu4HK9+/M tFzij2Br2lEzSTPzm0ug6NWt9utuXv/ZlbYnYwxc9BAYAA8G3A1RL4KTwo9Evc+8kuhm e2RFApOw/rKJfoNwNrbsqxHAyu0XBVS877Qjs4W7cmabyeT/44F/sHGYYr7sJk6nAiZ0 atPA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1739873555; x=1740478355; 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=okm3LTa2KT6tlsIpTZr55gU34qeQ+5Qm8WrnAeHUzZI=; b=QB1slZN6zsC48hflAsartetTjd6ZEJomHbGs+Ukn9X/2ZvMpLO+ZF7oZmVrwDVO7n2 6vVN0i75RblRnyB0VD2GzoSAJIJF/q63vOsL0AQuKdNC3sgYw+4WsnSxUWsPl1Mku5ci rV9xuq3Fi2cHjJk5sQPbIUk7nxX0o78V1fXUPP3BD+GiniG7JzcSuUjYBpIfaA2dElQ7 HkOmpoPt5wuBWsJBaBzFGSMHdxKgkJ0+UouewYPGXyyHHFOCv2BuzuIkC9fWydhvzTkA s8Q7PzTt9mkUtYQD9P4msMp8Am2CVcLNQfzV3sNQb4GR5cBoP7TeFMQ+MfkBNhibrrxh mD6Q== X-Forwarded-Encrypted: i=1; AJvYcCUa7yJ0JZzBTTR89kNXjD4QGHsUU8BVxkgCW5v6b8gbUaDG1ScHY7ljL6Ecpr3j1qFbCisxk0s2UiEMFxM=@vger.kernel.org X-Gm-Message-State: AOJu0Yy5w9sJ9RPY/UMUGob6E0NAbBFrcAsY1Y0QJprYi2JAdkuhE644 jv/RTWY0BE+4o3q/x6CqHeyL+Qdcg6BxHE32RwPaZcKLCRPCdX1O X-Gm-Gg: ASbGncswTaTJhHPpwk1nyL32pDvXBNJoQHPcSf5xgoR5CObj/RD6MI2Rcz66hb4vk6o LvsAsQeYfAwQI2/iycqBJUWlhO143EcKg9S9MVrF/T5TY3RZFBqJzhYm8MU0jdEVeNLbgm5IEpA xFKRtFljERKsh9vOWDOXD1TDEV8vMwlyfVEAysbUt2NtTpXTy8Hfgzhhvz8Y+HDTdMUbZfcsS0k A3QfqI2wLW0R1K2X2EAPbAJsTpaCJUbVy9PyTw3wsqfL9sn26mN7UpMowbPQg4NQm0AwXOYVgvm tGu7IYKlQ23Fa31xbw== X-Google-Smtp-Source: AGHT+IFgN14jNIkd2URH9+9+nkuganTWAHpMTMupwnaZtTOP8R57T4kb08yf4d0Y+iofqeCmGB/kSA== X-Received: by 2002:a5d:5f4e:0:b0:385:f220:f798 with SMTP id ffacd0b85a97d-38f33f3737amr11282812f8f.6.1739873555058; Tue, 18 Feb 2025 02:12:35 -0800 (PST) Received: from fedora.. ([213.94.27.232]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-38f259d5e92sm14749720f8f.66.2025.02.18.02.12.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Feb 2025 02:12:34 -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 v4 13/14] drm/vkms: Allow to configure multiple connectors Date: Tue, 18 Feb 2025 11:12:13 +0100 Message-ID: <20250218101214.5790-14-jose.exposito89@gmail.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250218101214.5790-1-jose.exposito89@gmail.com> References: <20250218101214.5790-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. 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. Reviewed-by: Louis Chauvet Co-developed-by: Louis Chauvet Signed-off-by: Louis Chauvet Signed-off-by: Jos=C3=A9 Exp=C3=B3sito --- .clang-format | 1 + drivers/gpu/drm/vkms/tests/vkms_config_test.c | 95 +++++++++++++++++++ drivers/gpu/drm/vkms/vkms_config.c | 54 +++++++++++ drivers/gpu/drm/vkms/vkms_config.h | 44 +++++++++ drivers/gpu/drm/vkms/vkms_connector.c | 11 +++ 5 files changed, 205 insertions(+) diff --git a/.clang-format b/.clang-format index 5d21c0e4edbd..ca49832993c5 100644 --- a/.clang-format +++ b/.clang-format @@ -690,6 +690,7 @@ ForEachMacros: - 'v4l2_m2m_for_each_src_buf' - 'v4l2_m2m_for_each_src_buf_safe' - 'virtio_device_for_each_vq' + - 'vkms_config_for_each_connector' - 'vkms_config_for_each_crtc' - 'vkms_config_for_each_encoder' - 'vkms_config_for_each_plane' diff --git a/drivers/gpu/drm/vkms/tests/vkms_config_test.c b/drivers/gpu/dr= m/vkms/tests/vkms_config_test.c index 600f563dd0a8..610bcde3e018 100644 --- a/drivers/gpu/drm/vkms/tests/vkms_config_test.c +++ b/drivers/gpu/drm/vkms/tests/vkms_config_test.c @@ -28,6 +28,17 @@ static size_t vkms_config_get_num_encoders(struct vkms_c= onfig *config) return count; } =20 +static size_t vkms_config_get_num_connectors(struct vkms_config *config) +{ + struct vkms_config_connector *connector_cfg; + size_t count =3D 0; + + vkms_config_for_each_connector(config, connector_cfg) + count++; + + return count; +} + static struct vkms_config_plane *get_first_plane(struct vkms_config *confi= g) { struct vkms_config_plane *plane_cfg; @@ -58,6 +69,16 @@ static struct vkms_config_encoder *get_first_encoder(str= uct vkms_config *config) return NULL; } =20 +static struct vkms_config_connector *get_first_connector(struct vkms_confi= g *config) +{ + struct vkms_config_connector *connector_cfg; + + vkms_config_for_each_connector(config, connector_cfg) + return connector_cfg; + + return NULL; +} + struct default_config_case { bool enable_cursor; bool enable_writeback; @@ -79,6 +100,7 @@ static void vkms_config_test_empty_config(struct kunit *= test) KUNIT_EXPECT_EQ(test, vkms_config_get_num_planes(config), 0); KUNIT_EXPECT_EQ(test, vkms_config_get_num_crtcs(config), 0); KUNIT_EXPECT_EQ(test, vkms_config_get_num_encoders(config), 0); + KUNIT_EXPECT_EQ(test, vkms_config_get_num_connectors(config), 0); =20 KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config)); =20 @@ -155,6 +177,9 @@ static void vkms_config_test_default_config(struct kuni= t *test) /* Encoders */ KUNIT_EXPECT_EQ(test, vkms_config_get_num_encoders(config), 1); =20 + /* Connectors */ + KUNIT_EXPECT_EQ(test, vkms_config_get_num_connectors(config), 1); + KUNIT_EXPECT_TRUE(test, vkms_config_is_valid(config)); =20 vkms_config_destroy(config); @@ -284,6 +309,51 @@ 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_cfg; + struct vkms_config_connector *connector_cfg1, *connector_cfg2; + int n_connectors =3D 0; + + config =3D vkms_config_create("test"); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config); + + vkms_config_for_each_connector(config, connector_cfg) + n_connectors++; + KUNIT_ASSERT_EQ(test, n_connectors, 0); + + connector_cfg1 =3D vkms_config_create_connector(config); + vkms_config_for_each_connector(config, connector_cfg) { + n_connectors++; + if (connector_cfg !=3D connector_cfg1) + KUNIT_FAIL(test, "Unexpected connector"); + } + KUNIT_ASSERT_EQ(test, n_connectors, 1); + n_connectors =3D 0; + + connector_cfg2 =3D vkms_config_create_connector(config); + vkms_config_for_each_connector(config, connector_cfg) { + n_connectors++; + if (connector_cfg !=3D connector_cfg1 && + connector_cfg !=3D connector_cfg2) + KUNIT_FAIL(test, "Unexpected connector"); + } + KUNIT_ASSERT_EQ(test, n_connectors, 2); + n_connectors =3D 0; + + vkms_config_destroy_connector(connector_cfg2); + vkms_config_for_each_connector(config, connector_cfg) { + n_connectors++; + if (connector_cfg !=3D connector_cfg1) + KUNIT_FAIL(test, "Unexpected connector"); + } + KUNIT_ASSERT_EQ(test, n_connectors, 1); + n_connectors =3D 0; + + vkms_config_destroy(config); +} + static void vkms_config_test_invalid_plane_number(struct kunit *test) { struct vkms_config *config; @@ -491,6 +561,29 @@ static void vkms_config_test_valid_encoder_possible_cr= tcs(struct kunit *test) vkms_config_destroy(config); } =20 +static void vkms_config_test_invalid_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); + + /* Invalid: No connectors */ + connector_cfg =3D get_first_connector(config); + vkms_config_destroy_connector(connector_cfg); + KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config)); + + /* Invalid: Too many connectors */ + for (n =3D 0; n <=3D 32; n++) + connector_cfg =3D vkms_config_create_connector(config); + + KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config)); + + vkms_config_destroy(config); +} + static void vkms_config_test_attach_different_configs(struct kunit *test) { struct vkms_config *config1, *config2; @@ -730,12 +823,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_invalid_plane_number), KUNIT_CASE(vkms_config_test_valid_plane_type), KUNIT_CASE(vkms_config_test_valid_plane_possible_crtcs), KUNIT_CASE(vkms_config_test_invalid_crtc_number), KUNIT_CASE(vkms_config_test_invalid_encoder_number), KUNIT_CASE(vkms_config_test_valid_encoder_possible_crtcs), + KUNIT_CASE(vkms_config_test_invalid_connector_number), KUNIT_CASE(vkms_config_test_attach_different_configs), 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 17262a9c2567..fbbdee6068ce 100644 --- a/drivers/gpu/drm/vkms/vkms_config.c +++ b/drivers/gpu/drm/vkms/vkms_config.c @@ -25,6 +25,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; } @@ -38,6 +39,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); @@ -89,6 +91,10 @@ 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_create_connector(config); + if (IS_ERR(connector_cfg)) + goto err_alloc; + return config; =20 err_alloc: @@ -102,6 +108,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); @@ -112,6 +119,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); } @@ -255,6 +265,20 @@ static bool valid_encoder_possible_crtcs(const struct = vkms_config *config) return true; } =20 +static bool valid_connector_number(const struct vkms_config *config) +{ + struct drm_device *dev =3D config->dev ? &config->dev->drm : NULL; + size_t n_connectors; + + n_connectors =3D list_count_nodes((struct list_head *)&config->connectors= ); + if (n_connectors <=3D 0 || n_connectors >=3D 32) { + drm_info(dev, "The number of connectors must be between 1 and 31\n"); + return false; + } + + return true; +} + bool vkms_config_is_valid(const struct vkms_config *config) { struct vkms_config_crtc *crtc_cfg; @@ -268,6 +292,9 @@ bool vkms_config_is_valid(const struct vkms_config *con= fig) if (!valid_encoder_number(config)) return false; =20 + if (!valid_connector_number(config)) + return false; + if (!valid_plane_possible_crtcs(config)) return false; =20 @@ -292,6 +319,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); @@ -311,6 +339,9 @@ static int vkms_config_show(struct seq_file *m, void *d= ata) vkms_config_for_each_encoder(vkmsdev->config, encoder_cfg) seq_puts(m, "encoder\n"); =20 + vkms_config_for_each_connector(vkmsdev->config, connector_cfg) + seq_puts(m, "connector\n"); + return 0; } =20 @@ -520,3 +551,26 @@ void vkms_config_encoder_detach_crtc(struct vkms_confi= g_encoder *encoder_cfg, } } EXPORT_SYMBOL_IF_KUNIT(vkms_config_encoder_detach_crtc); + +struct vkms_config_connector *vkms_config_create_connector(struct vkms_con= fig *config) +{ + struct vkms_config_connector *connector_cfg; + + connector_cfg =3D kzalloc(sizeof(*connector_cfg), GFP_KERNEL); + if (!connector_cfg) + return ERR_PTR(-ENOMEM); + + connector_cfg->config =3D config; + + list_add_tail(&connector_cfg->link, &config->connectors); + + return connector_cfg; +} +EXPORT_SYMBOL_IF_KUNIT(vkms_config_create_connector); + +void vkms_config_destroy_connector(struct vkms_config_connector *connector= _cfg) +{ + list_del(&connector_cfg->link); + kfree(connector_cfg); +} +EXPORT_SYMBOL_IF_KUNIT(vkms_config_destroy_connector); diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms= _config.h index 3e5b2e407378..73562c894102 100644 --- a/drivers/gpu/drm/vkms/vkms_config.h +++ b/drivers/gpu/drm/vkms/vkms_config.h @@ -16,6 +16,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 { @@ -23,6 +24,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 @@ -92,6 +94,24 @@ struct vkms_config_encoder { struct drm_encoder *encoder; }; =20 +/** + * struct vkms_config_connector + * + * @link: Link to the others connector in vkms_config + * @config: The vkms_config this connector belongs to + * @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; + struct vkms_config *config; + + /* Internal usage */ + struct vkms_connector *connector; +}; + /** * vkms_config_for_each_plane - Iterate over the vkms_config planes * @config: &struct vkms_config pointer @@ -116,6 +136,14 @@ struct vkms_config_encoder { #define vkms_config_for_each_encoder(config, encoder_cfg) \ list_for_each_entry((encoder_cfg), &(config)->encoders, link) =20 +/** + * vkms_config_for_each_connector - Iterate over the vkms_config connectors + * @config: &struct vkms_config pointer + * @connector_cfg: &struct vkms_config_connector pointer used as cursor + */ +#define vkms_config_for_each_connector(config, connector_cfg) \ + list_for_each_entry((connector_cfg), &(config)->connectors, link) + /** * vkms_config_plane_for_each_possible_crtc - Iterate over the vkms_config= _plane * possible CRTCs @@ -361,4 +389,20 @@ int __must_check vkms_config_encoder_attach_crtc(struc= t vkms_config_encoder *enc void vkms_config_encoder_detach_crtc(struct vkms_config_encoder *encoder_c= fg, struct vkms_config_crtc *crtc_cfg); =20 +/** + * vkms_config_create_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_create_connector(struct vkms_con= fig *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); + #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 Thu Dec 18 10:36:55 2025 Received: from mail-wr1-f47.google.com (mail-wr1-f47.google.com [209.85.221.47]) (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 1385F23AE7D for ; Tue, 18 Feb 2025 10:12:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.47 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739873560; cv=none; b=CQp5cOnBzgzcjpE0AxPXv1ZLGdgRDrrLTqmsCnBBbjIB3KAuQI2dmBLsAL8veqa4puuWyBhgkN+f+39fkwVDDNI31h3AVWo8Jt9416PmjORhdSlo6xJc4JLj/6LnGMh43kqR5w21KVr+XF7PMN1dhoAJQcu1PMRPAj1nUxdkY98= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739873560; c=relaxed/simple; bh=Yq28pqHTePQp7L+t1SrFXFbJAQm7/bMZO8hygotWTW4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Pp+Pp6Zcp7QZmLm1eE1HHykiVcX+DCLEjWFSv1GXMwMUgtn9vh+RjzcmyrO1mne4ESZmxdJGknoRpiSF7eC765vN6ioRUmOTw2Mx13Rc/CB8NDVOcyTYNar02fCo1e0UVE/olq2pTm4wSOBzKOR79LCXGOJIg+TJbrXLVWM8Ezg= 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=ic93PRDT; arc=none smtp.client-ip=209.85.221.47 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="ic93PRDT" Received: by mail-wr1-f47.google.com with SMTP id ffacd0b85a97d-38f325dd9e6so1681464f8f.1 for ; Tue, 18 Feb 2025 02:12:37 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1739873556; x=1740478356; 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=h+xCFrURTppY63NVOBwqa8Qg4TsqZlxYnGgiayzWMgE=; b=ic93PRDTQUdXI85z/G0UCX4jtayNpM4LrrMKkGLkygED2v0TsiyziYtfmrMfVVkHXJ gs8j3419U+xTjwAt3ENc0ljlp3LjyUUOdCR+ps7/TcJcw8/NYoRECvMhQrjOykCRljpC Ew/m3ZObMazVuAXmyH/OcJp31T2n2UKALT/4KimqEPAbQmCrdWt/1xP5LrPwohttbVMS qNndeybSX5/Hib4i/nr43NiXECuivabEssj8QtxNt32lhTpE6EPdfp6U5ce4tD9AN2qe LG6GtSpuB00Ki4GAOGLWhLsnMVS+gy23NrcYfDd9tMA5Zyij5pTFleW9KoecQIVdtgpw +Imw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1739873556; x=1740478356; 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=h+xCFrURTppY63NVOBwqa8Qg4TsqZlxYnGgiayzWMgE=; b=eqSrEs6fo19dMYcyIt3BRf3TWoLMOFG5NvJ0yUiIlEaTtXSO0tOGjKLpocEFWRJRbo ywG10RUFuI7j7Lr4DNKi96Iw7LhHfj2G4DteUNLeDrg7iVxdY7SIZMyAayvoH5oaR0xw 5UXtHL9T+RIZmCGP+lfdwCNQaMcCYJHqa4jxCxqCrHDCg2YTkeTHMNNt6ezzfnDufidz ghXE5AVkpXqulkvFt6PQktcezc2fCt0w4woiTMZQ7NfZtajUJK6+B1FJsYHWjInt9ov/ DtFgC3RhzOdvNKOSQafP4K6NWHGiP8uBcv83SgMIRQh8ZKp/Kivbdvfto9cobhsYH7jd 9hKg== X-Forwarded-Encrypted: i=1; AJvYcCWnit7NI2WDuAMUCXs9XRhEccColGm+cGDzJrUgLJfUdNQLSVx20yGYdRd/FkIcv4idB9PKqmncexgVg9M=@vger.kernel.org X-Gm-Message-State: AOJu0YzWDAGBbbq/d0ynduGy3IcwqwonZNdcMCCu0U0TNWqRUpU76TQF 4BTpfH1OXpl+bu8qZFjwby44v4jiwKrPV1dJhH/eWRwW1spIosba X-Gm-Gg: ASbGncufKeZA4s2m8qELzgYhrnD1SWCEbSrndrUeU5j7YXNOmLoXo+VlJknglqRLI07 uGdp3k4AmlHF9cYESQPOvrYomAPY955ZAuzXs1RC2gDWTxj/vzGjaBVjN9FeS1XpRSQfPXV071Z AJNSwqoZCaNicK4Q1z5yFmt1rNIdYzLJSIAB8ATKtP1oIQLC6g8CMWgo6I2OD2y+qOJkp1ovJ2f oHru9gZ4GSp1F1/VjQC45yOQiWNz6phQLXcRqKI26rton1BGgikKQJqkb7FSy2SgNHu8Hi2Tiiy gI+Jpiz78nFSz+ba7w== X-Google-Smtp-Source: AGHT+IH1fgM5ly1pG4PQnHCQHvU2qjuyGPQ9TH5SuTOagsYNNt7IikoLHxrhYwZdCW6vd8EuNSSdpQ== X-Received: by 2002:a5d:598b:0:b0:38f:4e6e:22 with SMTP id ffacd0b85a97d-38f4e6e01a3mr4986452f8f.48.1739873556184; Tue, 18 Feb 2025 02:12:36 -0800 (PST) Received: from fedora.. ([213.94.27.232]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-38f259d5e92sm14749720f8f.66.2025.02.18.02.12.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Feb 2025 02:12:35 -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 v4 14/14] drm/vkms: Allow to attach connectors and encoders Date: Tue, 18 Feb 2025 11:12:14 +0100 Message-ID: <20250218101214.5790-15-jose.exposito89@gmail.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250218101214.5790-1-jose.exposito89@gmail.com> References: <20250218101214.5790-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. Reviewed-by: Louis Chauvet Co-developed-by: Louis Chauvet Signed-off-by: Louis Chauvet Signed-off-by: Jos=C3=A9 Exp=C3=B3sito --- .clang-format | 1 + drivers/gpu/drm/vkms/tests/vkms_config_test.c | 102 ++++++++++++++++++ drivers/gpu/drm/vkms/vkms_config.c | 64 +++++++++++ drivers/gpu/drm/vkms/vkms_config.h | 29 +++++ drivers/gpu/drm/vkms/vkms_output.c | 33 +++--- 5 files changed, 216 insertions(+), 13 deletions(-) diff --git a/.clang-format b/.clang-format index ca49832993c5..7630990aa07a 100644 --- a/.clang-format +++ b/.clang-format @@ -694,6 +694,7 @@ ForEachMacros: - 'vkms_config_for_each_crtc' - 'vkms_config_for_each_encoder' - 'vkms_config_for_each_plane' + - 'vkms_config_connector_for_each_possible_encoder' - 'vkms_config_encoder_for_each_possible_crtc' - 'vkms_config_plane_for_each_possible_crtc' - 'while_for_each_ftrace_op' diff --git a/drivers/gpu/drm/vkms/tests/vkms_config_test.c b/drivers/gpu/dr= m/vkms/tests/vkms_config_test.c index 610bcde3e018..ff4566cf9925 100644 --- a/drivers/gpu/drm/vkms/tests/vkms_config_test.c +++ b/drivers/gpu/drm/vkms/tests/vkms_config_test.c @@ -584,12 +584,32 @@ static void vkms_config_test_invalid_connector_number= (struct kunit *test) vkms_config_destroy(config); } =20 +static void vkms_config_test_valid_connector_possible_encoders(struct kuni= t *test) +{ + struct vkms_config *config; + struct vkms_config_encoder *encoder_cfg; + struct vkms_config_connector *connector_cfg; + + config =3D vkms_config_default_create(false, false, false); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config); + + encoder_cfg =3D get_first_encoder(config); + connector_cfg =3D get_first_connector(config); + + /* Invalid: Connector without a possible encoder */ + vkms_config_connector_detach_encoder(connector_cfg, encoder_cfg); + KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config)); + + vkms_config_destroy(config); +} + static void vkms_config_test_attach_different_configs(struct kunit *test) { struct vkms_config *config1, *config2; struct vkms_config_plane *plane_cfg1, *plane_cfg2; struct vkms_config_crtc *crtc_cfg1, *crtc_cfg2; struct vkms_config_encoder *encoder_cfg1, *encoder_cfg2; + struct vkms_config_connector *connector_cfg1, *connector_cfg2; int err; =20 config1 =3D vkms_config_create("test1"); @@ -601,10 +621,12 @@ static void vkms_config_test_attach_different_configs= (struct kunit *test) plane_cfg1 =3D vkms_config_create_plane(config1); crtc_cfg1 =3D vkms_config_create_crtc(config1); encoder_cfg1 =3D vkms_config_create_encoder(config1); + connector_cfg1 =3D vkms_config_create_connector(config1); =20 plane_cfg2 =3D vkms_config_create_plane(config2); crtc_cfg2 =3D vkms_config_create_crtc(config2); encoder_cfg2 =3D vkms_config_create_encoder(config2); + connector_cfg2 =3D vkms_config_create_connector(config2); =20 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_cfg1); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_cfg2); @@ -612,6 +634,8 @@ static void vkms_config_test_attach_different_configs(s= truct kunit *test) KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_cfg2); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, encoder_cfg1); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, encoder_cfg2); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, connector_cfg1); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, connector_cfg2); =20 err =3D vkms_config_plane_attach_crtc(plane_cfg1, crtc_cfg2); KUNIT_EXPECT_NE(test, err, 0); @@ -623,6 +647,11 @@ static void vkms_config_test_attach_different_configs(= struct kunit *test) err =3D vkms_config_encoder_attach_crtc(encoder_cfg2, crtc_cfg1); KUNIT_EXPECT_NE(test, err, 0); =20 + err =3D vkms_config_connector_attach_encoder(connector_cfg1, encoder_cfg2= ); + KUNIT_EXPECT_NE(test, err, 0); + err =3D vkms_config_connector_attach_encoder(connector_cfg2, encoder_cfg1= ); + KUNIT_EXPECT_NE(test, err, 0); + vkms_config_destroy(config1); vkms_config_destroy(config2); } @@ -816,6 +845,77 @@ 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 *possible_encoder; + unsigned long idx =3D 0; + int n_encoders =3D 0; + int err; + + config =3D vkms_config_create("test"); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config); + + connector_cfg1 =3D vkms_config_create_connector(config); + connector_cfg2 =3D vkms_config_create_connector(config); + encoder_cfg1 =3D vkms_config_create_encoder(config); + encoder_cfg2 =3D vkms_config_create_encoder(config); + + /* No possible encoders */ + vkms_config_connector_for_each_possible_encoder(connector_cfg1, idx, + possible_encoder) + KUNIT_FAIL(test, "Unexpected possible encoder"); + + vkms_config_connector_for_each_possible_encoder(connector_cfg2, idx, + possible_encoder) + KUNIT_FAIL(test, "Unexpected possible encoder"); + + /* 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); + + vkms_config_connector_for_each_possible_encoder(connector_cfg1, idx, + possible_encoder) { + n_encoders++; + if (possible_encoder !=3D encoder_cfg1 && + possible_encoder !=3D encoder_cfg2) + KUNIT_FAIL(test, "Unexpected possible encoder"); + } + KUNIT_ASSERT_EQ(test, n_encoders, 2); + n_encoders =3D 0; + + vkms_config_connector_for_each_possible_encoder(connector_cfg2, idx, + possible_encoder) + KUNIT_FAIL(test, "Unexpected possible encoder"); + + /* Connector 1 attached to encoder 1 and connector 2 to encoder 2 */ + vkms_config_connector_detach_encoder(connector_cfg1, encoder_cfg2); + vkms_config_connector_for_each_possible_encoder(connector_cfg1, idx, + possible_encoder) { + n_encoders++; + if (possible_encoder !=3D encoder_cfg1) + KUNIT_FAIL(test, "Unexpected possible encoder"); + } + KUNIT_ASSERT_EQ(test, n_encoders, 1); + n_encoders =3D 0; + + err =3D vkms_config_connector_attach_encoder(connector_cfg2, encoder_cfg2= ); + KUNIT_EXPECT_EQ(test, err, 0); + vkms_config_connector_for_each_possible_encoder(connector_cfg2, idx, + possible_encoder) { + n_encoders++; + if (possible_encoder !=3D encoder_cfg2) + KUNIT_FAIL(test, "Unexpected possible encoder"); + } + KUNIT_ASSERT_EQ(test, n_encoders, 1); + + 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, @@ -831,10 +931,12 @@ static struct kunit_case vkms_config_test_cases[] =3D= { KUNIT_CASE(vkms_config_test_invalid_encoder_number), KUNIT_CASE(vkms_config_test_valid_encoder_possible_crtcs), KUNIT_CASE(vkms_config_test_invalid_connector_number), + KUNIT_CASE(vkms_config_test_valid_connector_possible_encoders), KUNIT_CASE(vkms_config_test_attach_different_configs), 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 fbbdee6068ce..a1df5659b0fb 100644 --- a/drivers/gpu/drm/vkms/vkms_config.c +++ b/drivers/gpu/drm/vkms/vkms_config.c @@ -95,6 +95,9 @@ struct vkms_config *vkms_config_default_create(bool enabl= e_cursor, if (IS_ERR(connector_cfg)) goto err_alloc; =20 + if (vkms_config_connector_attach_encoder(connector_cfg, encoder_cfg)) + goto err_alloc; + return config; =20 err_alloc: @@ -279,6 +282,22 @@ static bool valid_connector_number(const struct vkms_c= onfig *config) return true; } =20 +static bool valid_connector_possible_encoders(const struct vkms_config *co= nfig) +{ + struct drm_device *dev =3D config->dev ? &config->dev->drm : NULL; + struct vkms_config_connector *connector_cfg; + + vkms_config_for_each_connector(config, connector_cfg) { + if (xa_empty(&connector_cfg->possible_encoders)) { + drm_info(dev, + "All connectors must have at least one possible encoder\n"); + return false; + } + } + + return true; +} + bool vkms_config_is_valid(const struct vkms_config *config) { struct vkms_config_crtc *crtc_cfg; @@ -306,6 +325,9 @@ bool vkms_config_is_valid(const struct vkms_config *con= fig) if (!valid_encoder_possible_crtcs(config)) return false; =20 + if (!valid_connector_possible_encoders(config)) + return false; + return true; } EXPORT_SYMBOL_IF_KUNIT(vkms_config_is_valid); @@ -513,6 +535,11 @@ EXPORT_SYMBOL_IF_KUNIT(vkms_config_create_encoder); void vkms_config_destroy_encoder(struct vkms_config *config, struct vkms_config_encoder *encoder_cfg) { + struct vkms_config_connector *connector_cfg; + + vkms_config_for_each_connector(config, connector_cfg) + vkms_config_connector_detach_encoder(connector_cfg, encoder_cfg); + xa_destroy(&encoder_cfg->possible_crtcs); list_del(&encoder_cfg->link); kfree(encoder_cfg); @@ -561,6 +588,7 @@ struct vkms_config_connector *vkms_config_create_connec= tor(struct vkms_config *c return ERR_PTR(-ENOMEM); =20 connector_cfg->config =3D config; + xa_init_flags(&connector_cfg->possible_encoders, XA_FLAGS_ALLOC); =20 list_add_tail(&connector_cfg->link, &config->connectors); =20 @@ -570,7 +598,43 @@ EXPORT_SYMBOL_IF_KUNIT(vkms_config_create_connector); =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); } EXPORT_SYMBOL_IF_KUNIT(vkms_config_destroy_connector); + +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; + + if (connector_cfg->config !=3D encoder_cfg->config) + return -EINVAL; + + vkms_config_connector_for_each_possible_encoder(connector_cfg, idx, + possible_encoder) { + if (possible_encoder =3D=3D encoder_cfg) + return -EEXIST; + } + + return xa_alloc(&connector_cfg->possible_encoders, &encoder_idx, + encoder_cfg, xa_limit_32b, GFP_KERNEL); +} +EXPORT_SYMBOL_IF_KUNIT(vkms_config_connector_attach_encoder); + +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; + + vkms_config_connector_for_each_possible_encoder(connector_cfg, idx, + possible_encoder) { + if (possible_encoder =3D=3D encoder_cfg) + xa_erase(&connector_cfg->possible_encoders, idx); + } +} +EXPORT_SYMBOL_IF_KUNIT(vkms_config_connector_detach_encoder); diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms= _config.h index 73562c894102..0118e3f99706 100644 --- a/drivers/gpu/drm/vkms/vkms_config.h +++ b/drivers/gpu/drm/vkms/vkms_config.h @@ -99,6 +99,7 @@ struct vkms_config_encoder { * * @link: Link to the others connector in vkms_config * @config: The vkms_config this connector belongs to + * @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 @@ -108,6 +109,8 @@ struct vkms_config_connector { struct list_head link; struct vkms_config *config; =20 + struct xarray possible_encoders; + /* Internal usage */ struct vkms_connector *connector; }; @@ -164,6 +167,16 @@ struct vkms_config_connector { #define vkms_config_encoder_for_each_possible_crtc(encoder_cfg, idx, possi= ble_crtc) \ xa_for_each(&(encoder_cfg)->possible_crtcs, idx, (possible_crtc)) =20 +/** + * vkms_config_connector_for_each_possible_encoder - Iterate over the + * vkms_config_connector possible encoders + * @connector_cfg: &struct vkms_config_connector pointer + * @idx: Index of the cursor + * @possible_encoder: &struct vkms_config_encoder pointer used as cursor + */ +#define vkms_config_connector_for_each_possible_encoder(connector_cfg, idx= , possible_encoder) \ + xa_for_each(&(connector_cfg)->possible_encoders, idx, (possible_encoder)) + /** * vkms_config_create() - Create a new VKMS configuration * @dev_name: Name of the device @@ -405,4 +418,20 @@ struct vkms_config_connector *vkms_config_create_conne= ctor(struct vkms_config *c */ void vkms_config_destroy_connector(struct vkms_config_connector *connector= _cfg); =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); + #endif /* _VKMS_CONFIG_H_ */ diff --git a/drivers/gpu/drm/vkms/vkms_output.c b/drivers/gpu/drm/vkms/vkms= _output.c index 8920d6b5d105..8d7ca0cdd79f 100644 --- a/drivers/gpu/drm/vkms/vkms_output.c +++ b/drivers/gpu/drm/vkms/vkms_output.c @@ -8,10 +8,10 @@ int vkms_output_init(struct vkms_device *vkmsdev) { struct drm_device *dev =3D &vkmsdev->drm; - struct vkms_connector *connector; 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 ret; int writeback; =20 @@ -83,22 +83,29 @@ int vkms_output_init(struct vkms_device *vkmsdev) } } =20 - connector =3D vkms_connector_init(vkmsdev); - if (IS_ERR(connector)) { - DRM_ERROR("Failed to init connector\n"); - return PTR_ERR(connector); - } + vkms_config_for_each_connector(vkmsdev->config, connector_cfg) { + struct vkms_config_encoder *possible_encoder; + unsigned long idx =3D 0; =20 - /* Attach the encoder and the connector */ - vkms_config_for_each_encoder(vkmsdev->config, encoder_cfg) { - ret =3D drm_connector_attach_encoder(&connector->base, encoder_cfg->enco= der); - if (ret) { - DRM_ERROR("Failed to attach connector to encoder\n"); - return ret; + connector_cfg->connector =3D vkms_connector_init(vkmsdev); + if (IS_ERR(connector_cfg->connector)) { + DRM_ERROR("Failed to init connector\n"); + return PTR_ERR(connector_cfg->connector); + } + + vkms_config_connector_for_each_possible_encoder(connector_cfg, + idx, + possible_encoder) { + ret =3D drm_connector_attach_encoder(&connector_cfg->connector->base, + possible_encoder->encoder); + if (ret) { + DRM_ERROR("Failed to attach connector to encoder\n"); + return ret; + } } } =20 drm_mode_config_reset(dev); =20 - return ret; + return 0; } --=20 2.48.1