lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20240814-google-remove-crtc-index-from-parameter-v1-12-6e179abf9fd4@bootlin.com>
Date: Wed, 14 Aug 2024 16:36:34 +0200
From: Louis Chauvet <louis.chauvet@...tlin.com>
To: Rodrigo Siqueira <rodrigosiqueiramelo@...il.com>, 
 Melissa Wen <melissa.srw@...il.com>, 
 MaĆ­ra Canal <mairacanal@...eup.net>, 
 Haneen Mohammed <hamohammed.sa@...il.com>, Daniel Vetter <daniel@...ll.ch>, 
 Maarten Lankhorst <maarten.lankhorst@...ux.intel.com>, 
 Maxime Ripard <mripard@...nel.org>, Thomas Zimmermann <tzimmermann@...e.de>, 
 David Airlie <airlied@...il.com>
Cc: dri-devel@...ts.freedesktop.org, arthurgrillo@...eup.net, 
 linux-kernel@...r.kernel.org, jeremie.dautheribes@...tlin.com, 
 miquel.raynal@...tlin.com, thomas.petazzoni@...tlin.com, 
 seanpaul@...gle.com, nicolejadeyee@...gle.com, 
 Louis Chauvet <louis.chauvet@...tlin.com>
Subject: [PATCH RFC 12/15] drm/vkms: Add configuration for CRTCs and
 encoders

The current VKMS driver can only uses one CRTC and one encoder. This patch
introduce in the same time CRTC and encoders as they are tighly linked.

Signed-off-by: Louis Chauvet <louis.chauvet@...tlin.com>
---
 drivers/gpu/drm/vkms/vkms_config.c | 266 +++++++++++++++++++++++++++++++++----
 drivers/gpu/drm/vkms/vkms_config.h | 102 +++++++++++++-
 drivers/gpu/drm/vkms/vkms_crtc.c   |  20 ++-
 drivers/gpu/drm/vkms/vkms_crtc.h   |   3 +-
 drivers/gpu/drm/vkms/vkms_drv.c    |  87 ++++++------
 5 files changed, 405 insertions(+), 73 deletions(-)

diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms_config.c
index e9e30974523a..fcd4a128c21b 100644
--- a/drivers/gpu/drm/vkms/vkms_config.c
+++ b/drivers/gpu/drm/vkms/vkms_config.c
@@ -14,6 +14,8 @@ struct vkms_config *vkms_config_create(void)
 		return ERR_PTR(-ENOMEM);
 
 	INIT_LIST_HEAD(&config->planes);
+	INIT_LIST_HEAD(&config->crtcs);
+	INIT_LIST_HEAD(&config->encoders);
 
 	return config;
 }
@@ -22,12 +24,24 @@ struct vkms_config *vkms_config_alloc_default(bool enable_writeback, bool enable
 					      bool enable_cursor)
 {
 	struct vkms_config_plane *plane;
+	struct vkms_config_encoder *encoder;
+	struct vkms_config_crtc *crtc;
 	struct vkms_config *vkms_config = vkms_config_create();
 
 	if (IS_ERR(vkms_config))
 		return vkms_config;
 
-	vkms_config->writeback = enable_writeback;
+	crtc = vkms_config_create_crtc(vkms_config);
+	if (!crtc)
+		goto err_alloc;
+	crtc->writeback = enable_writeback;
+
+	encoder = vkms_config_create_encoder(vkms_config);
+	if (!encoder)
+		goto err_alloc;
+
+	if (vkms_config_encoder_attach_crtc(encoder, crtc))
+		goto err_alloc;
 
 	plane = vkms_config_create_plane(vkms_config);
 	if (!plane)
@@ -39,6 +53,9 @@ struct vkms_config *vkms_config_alloc_default(bool enable_writeback, bool enable
 		goto err_alloc;
 	sprintf(plane->name, "primary");
 
+	if (vkms_config_plane_attach_crtc(plane, crtc))
+		goto err_alloc;
+
 	if (enable_overlay) {
 		for (int i = 0; i < NUM_OVERLAY_PLANES; i++) {
 			plane = vkms_config_create_plane(vkms_config);
@@ -49,6 +66,9 @@ struct vkms_config *vkms_config_alloc_default(bool enable_writeback, bool enable
 			if (!plane->name)
 				goto err_alloc;
 			snprintf(plane->name, 10, "plane-%d", i);
+
+			if (vkms_config_plane_attach_crtc(plane, crtc))
+				goto err_alloc;
 		}
 	}
 	if (enable_cursor) {
@@ -60,6 +80,9 @@ struct vkms_config *vkms_config_alloc_default(bool enable_writeback, bool enable
 		if (!plane->name)
 			goto err_alloc;
 		sprintf(plane->name, "cursor");
+
+		if (vkms_config_plane_attach_crtc(plane, crtc))
+			goto err_alloc;
 	}
 
 	return vkms_config;
@@ -89,38 +112,196 @@ struct vkms_config_plane *vkms_config_create_plane(struct vkms_config *vkms_conf
 	vkms_config_overlay->supported_color_range = BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
 						     BIT(DRM_COLOR_YCBCR_FULL_RANGE);
 	vkms_config_overlay->default_color_range = DRM_COLOR_YCBCR_FULL_RANGE;
+	xa_init_flags(&vkms_config_overlay->possible_crtcs, XA_FLAGS_ALLOC);
 
 	list_add(&vkms_config_overlay->link, &vkms_config->planes);
 
 	return vkms_config_overlay;
 }
 
-void vkms_config_delete_plane(struct vkms_config_plane *vkms_config_overlay)
+struct vkms_config_crtc *vkms_config_create_crtc(struct vkms_config *vkms_config)
 {
-	if (!vkms_config_overlay)
+	if (!vkms_config)
+		return NULL;
+
+	struct vkms_config_crtc *vkms_config_crtc = kzalloc(sizeof(*vkms_config_crtc),
+							    GFP_KERNEL);
+
+	if (!vkms_config_crtc)
+		return NULL;
+
+	list_add(&vkms_config_crtc->link, &vkms_config->crtcs);
+	xa_init_flags(&vkms_config_crtc->possible_planes, XA_FLAGS_ALLOC);
+	xa_init_flags(&vkms_config_crtc->possible_encoders, XA_FLAGS_ALLOC);
+
+	return vkms_config_crtc;
+}
+
+struct vkms_config_encoder *vkms_config_create_encoder(struct vkms_config *vkms_config)
+{
+	if (!vkms_config)
+		return NULL;
+
+	struct vkms_config_encoder *vkms_config_encoder = kzalloc(sizeof(*vkms_config_encoder),
+								  GFP_KERNEL);
+
+	if (!vkms_config_encoder)
+		return NULL;
+
+	list_add(&vkms_config_encoder->link, &vkms_config->encoders);
+	xa_init_flags(&vkms_config_encoder->possible_crtcs, XA_FLAGS_ALLOC);
+
+	return vkms_config_encoder;
+}
+
+void vkms_config_delete_plane(struct vkms_config_plane *vkms_config_plane,
+			      struct vkms_config *vkms_config)
+{
+	struct vkms_config_crtc *crtc_config;
+	struct vkms_config_plane *plane;
+
+	if (!vkms_config_plane)
+		return;
+	list_del(&vkms_config_plane->link);
+	xa_destroy(&vkms_config_plane->possible_crtcs);
+
+	list_for_each_entry(crtc_config, &vkms_config->crtcs, link) {
+		unsigned long idx = 0;
+
+		xa_for_each(&crtc_config->possible_planes, idx, plane) {
+			if (plane == vkms_config_plane)
+				xa_erase(&crtc_config->possible_planes, idx);
+		}
+	}
+
+	kfree(vkms_config_plane->name);
+	kfree(vkms_config_plane);
+}
+
+void vkms_config_delete_crtc(struct vkms_config_crtc *vkms_config_crtc,
+			     struct vkms_config *vkms_config)
+{
+	struct vkms_config_crtc *crtc_config;
+	struct vkms_config_plane *plane_config;
+	struct vkms_config_encoder *encoder_config;
+
+	if (!vkms_config_crtc)
+		return;
+	list_del(&vkms_config_crtc->link);
+	xa_destroy(&vkms_config_crtc->possible_planes);
+	xa_destroy(&vkms_config_crtc->possible_encoders);
+
+	list_for_each_entry(plane_config, &vkms_config->planes, link) {
+		unsigned long idx = 0;
+
+		xa_for_each(&plane_config->possible_crtcs, idx, crtc_config) {
+			if (crtc_config == vkms_config_crtc)
+				xa_erase(&plane_config->possible_crtcs, idx);
+		}
+	}
+
+	list_for_each_entry(encoder_config, &vkms_config->encoders, link) {
+		unsigned long idx = 0;
+
+		xa_for_each(&encoder_config->possible_crtcs, idx, crtc_config) {
+			if (crtc_config == vkms_config_crtc)
+				xa_erase(&encoder_config->possible_crtcs, idx);
+		}
+	}
+
+	kfree(vkms_config_crtc);
+}
+
+void vkms_config_delete_encoder(struct vkms_config_encoder *vkms_config_encoder,
+				struct vkms_config *vkms_config)
+{
+	if (!vkms_config_encoder)
 		return;
-	list_del(&vkms_config_overlay->link);
-	kfree(vkms_config_overlay->name);
-	kfree(vkms_config_overlay);
+	list_del(&vkms_config_encoder->link);
+	xa_destroy(&vkms_config_encoder->possible_crtcs);
+
+	struct vkms_config_crtc *crtc_config;
+	struct vkms_config_encoder *encoder;
+
+	list_for_each_entry(crtc_config, &vkms_config->crtcs, link) {
+		unsigned long idx = 0;
+
+		xa_for_each(&crtc_config->possible_encoders, idx, encoder) {
+			if (encoder == vkms_config_encoder)
+				xa_erase(&crtc_config->possible_encoders, idx);
+		}
+	}
+
+	kfree(vkms_config_encoder);
 }
 
 void vkms_config_destroy(struct vkms_config *config)
 {
 	struct vkms_config_plane *vkms_config_plane, *tmp_plane;
+	struct vkms_config_encoder *vkms_config_encoder, *tmp_encoder;
+	struct vkms_config_crtc *vkms_config_crtc, *tmp_crtc;
+
 
 	list_for_each_entry_safe(vkms_config_plane, tmp_plane, &config->planes, link) {
-		vkms_config_delete_plane(vkms_config_plane);
+		vkms_config_delete_plane(vkms_config_plane, config);
+	}
+	list_for_each_entry_safe(vkms_config_encoder, tmp_encoder, &config->encoders, link) {
+		vkms_config_delete_encoder(vkms_config_encoder, config);
+	}
+	list_for_each_entry_safe(vkms_config_crtc, tmp_crtc, &config->crtcs, link) {
+		vkms_config_delete_crtc(vkms_config_crtc, config);
 	}
 
 	kfree(config);
 }
 
+int __must_check vkms_config_plane_attach_crtc(struct vkms_config_plane *vkms_config_plane,
+					       struct vkms_config_crtc *vkms_config_crtc)
+{
+	u32 crtc_idx, encoder_idx;
+	int ret;
+
+	ret = xa_alloc(&vkms_config_plane->possible_crtcs, &crtc_idx, vkms_config_crtc,
+		       xa_limit_32b, GFP_KERNEL);
+	if (ret)
+		return ret;
+
+	ret = xa_alloc(&vkms_config_crtc->possible_planes, &encoder_idx, vkms_config_plane,
+		       xa_limit_32b, GFP_KERNEL);
+	if (ret) {
+		xa_erase(&vkms_config_plane->possible_crtcs, crtc_idx);
+		return ret;
+	}
+
+	return ret;
+}
+
+int __must_check vkms_config_encoder_attach_crtc(struct vkms_config_encoder *vkms_config_encoder,
+						 struct vkms_config_crtc *vkms_config_crtc)
+{
+	u32 crtc_idx, encoder_idx;
+	int ret;
+
+	ret = xa_alloc(&vkms_config_encoder->possible_crtcs, &crtc_idx, vkms_config_crtc,
+		       xa_limit_32b, GFP_KERNEL);
+	if (ret)
+		return ret;
+
+	ret = xa_alloc(&vkms_config_crtc->possible_encoders, &encoder_idx, vkms_config_encoder,
+		       xa_limit_32b, GFP_KERNEL);
+	if (ret) {
+		xa_erase(&vkms_config_encoder->possible_crtcs, crtc_idx);
+		return ret;
+	}
+
+	return ret;
+}
+
 bool vkms_config_is_valid(struct vkms_config *config)
 {
 	struct vkms_config_plane *config_plane;
-
-	bool has_cursor = false;
-	bool has_primary = false;
+	struct vkms_config_crtc *config_crtc;
+	struct vkms_config_encoder *config_encoder;
 
 	list_for_each_entry(config_plane, &config->planes, link) {
 		// Default rotation not in supported rotations
@@ -141,22 +322,47 @@ bool vkms_config_is_valid(struct vkms_config *config)
 		    BIT(config_plane->default_color_range))
 			return false;
 
-		if (config_plane->type == DRM_PLANE_TYPE_PRIMARY) {
-			// Multiple primary planes for only one CRTC
-			if (has_primary)
-				return false;
-			has_primary = true;
-		}
-		if (config_plane->type == DRM_PLANE_TYPE_CURSOR) {
-			// Multiple cursor planes for only one CRTC
-			if (has_cursor)
-				return false;
-			has_cursor = true;
-		}
+		// No CRTC linked to this plane
+		if (xa_empty(&config_plane->possible_crtcs))
+			return false;
+	}
+
+	list_for_each_entry(config_encoder, &config->encoders, link) {
+		// No CRTC linked to this encoder
+		if (xa_empty(&config_encoder->possible_crtcs))
+			return false;
 	}
 
-	if (!has_primary)
-		return false;
+	list_for_each_entry(config_crtc, &config->crtcs, link) {
+		bool has_primary = false;
+		bool has_cursor = false;
+		unsigned long idx = 0;
+
+		// No encoder attached to this CRTC
+		if (xa_empty(&config_crtc->possible_encoders))
+			return false;
+
+		xa_for_each(&config_crtc->possible_planes, idx, config_plane) {
+			if (config_plane->type == DRM_PLANE_TYPE_PRIMARY) {
+				// Multiple primary planes for only one CRTC
+				if (has_primary)
+					return false;
+
+				has_primary = true;
+			}
+			if (config_plane->type == DRM_PLANE_TYPE_CURSOR) {
+				// Multiple cursor planes for only one CRTC
+				if (has_cursor)
+					return false;
+
+				has_cursor = true;
+			}
+		}
+
+		// No primary plane for this CRTC
+		if (!has_primary)
+			return false;
+	}
 
 	return true;
 }
@@ -167,8 +373,9 @@ static int vkms_config_show(struct seq_file *m, void *data)
 	struct drm_device *dev = entry->dev;
 	struct vkms_device *vkmsdev = drm_device_to_vkms_device(dev);
 	struct vkms_config_plane *config_plane;
+	struct vkms_config_crtc *config_crtc;
+	struct vkms_config_encoder *config_encoder;
 
-	seq_printf(m, "writeback=%d\n", vkmsdev->config->writeback);
 	list_for_each_entry(config_plane, &vkmsdev->config->planes, link) {
 		seq_puts(m, "plane:\n");
 		seq_printf(m, "\tname: %s\n", config_plane->name);
@@ -185,6 +392,15 @@ static int vkms_config_show(struct seq_file *m, void *data)
 			   config_plane->default_color_range);
 	}
 
+	list_for_each_entry(config_encoder, &vkmsdev->config->encoders, link) {
+		seq_puts(m, "encoder:\n");
+	}
+
+	list_for_each_entry(config_crtc, &vkmsdev->config->crtcs, link) {
+		seq_puts(m, "crtc:\n");
+		seq_printf(m, "\twriteback: %d\n", config_crtc->writeback);
+	}
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms_config.h
index d668aeab9d26..8f247fc09373 100644
--- a/drivers/gpu/drm/vkms/vkms_config.h
+++ b/drivers/gpu/drm/vkms/vkms_config.h
@@ -9,16 +9,59 @@
 /**
  * struct vkms_config - General configuration for VKMS driver
  *
- * @writeback: If true, a writeback buffer can be attached to the CRTC
  * @planes: List of planes configured for this device. They are created by the function
  *          vkms_config_create_plane().
+ * @crtcs: List of crtcs configured for this device. They are created by the function
+ *         vkms_config_create_crtc().
+ * @encoders: List of encoders configured for this device. They are created by the function
+ *            vkms_config_create_encoder().
  * @dev: Used to store the current vkms device. Only set when the device is instancied.
  */
 struct vkms_config {
-	bool writeback;
 	struct vkms_device *dev;
 
 	struct list_head planes;
+	struct list_head crtcs;
+	struct list_head encoders;
+};
+
+/**
+ * struct vkms_config_crtc
+ *
+ * @link: Link to the others CRTCs
+ * @possible_planes: List of planes that can be used with this CRTC
+ * @possible_encoders: List of encoders that can be used with this 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 during device creation. This pointer is
+ *         not managed by the configuration and must be managed by other means.
+ */
+struct vkms_config_crtc {
+	struct list_head link;
+
+	bool writeback;
+	struct xarray possible_planes;
+	struct xarray possible_encoders;
+
+	/* Internal usage */
+	struct vkms_crtc *crtc;
+};
+
+/**
+ * struct vkms_config_encoder
+ *
+ * @link: Link to the others encoders
+ * @possible_crtcs: List of CRTC that can be used with this encoder
+ * @encoder: Internal usage. This pointer should never be considered as valid. It can be used to
+ *         store a temporary reference to a vkms encoder 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 xarray possible_crtcs;
+
+	/* Internal usage */
+	struct drm_encoder *encoder;
 };
 
 /**
@@ -34,6 +77,7 @@ struct vkms_config {
  * @supported_color_encoding: Color encoding that this plane will support
  * @default_color_range: Default color range that should be used by this plane
  * @supported_color_range: Color range that this plane will support
+ * @possible_crtcs: List of CRTC that can be used with this plane.
  * @plane: Internal usage. This pointer should never be considered as valid. It can be used to
  *         store a temporary reference to a vkms plane during device creation. This pointer is
  *         not managed by the configuration and must be managed by other means.
@@ -50,6 +94,7 @@ struct vkms_config_plane {
 	enum drm_color_range default_color_range;
 	unsigned int supported_color_range;
 
+	struct xarray possible_crtcs;
 	/* Internal usage */
 	struct vkms_plane *plane;
 };
@@ -84,14 +129,63 @@ bool vkms_config_is_valid(struct vkms_config *vkms_config);
  */
 struct vkms_config_plane *vkms_config_create_plane(struct vkms_config *vkms_config);
 
+/**
+ * vkms_config_create_crtc() - Create a crtc configuration
+ *
+ * This will allocate and add a new crtc configuration to @vkms_config.
+ * @vkms_config: Configuration where to insert new crtc configuration
+ */
+struct vkms_config_crtc *vkms_config_create_crtc(struct vkms_config *vkms_config);
+
+/**
+ * vkms_config_create_encoder() - Create an encoder configuration
+ *
+ * This will allocate and add a new encoder configuration to @vkms_config.
+ * @vkms_config: Configuration where to insert new encoder configuration
+ */
+struct vkms_config_encoder *vkms_config_create_encoder(struct vkms_config *vkms_config);
+
+int __must_check vkms_config_plane_attach_crtc(struct vkms_config_plane *vkms_config_plane,
+					       struct vkms_config_crtc *vkms_config_crtc);
+int __must_check vkms_config_encoder_attach_crtc(struct vkms_config_encoder *vkms_config_encoder,
+						 struct vkms_config_crtc *vkms_config_crtc);
+
 /**
  * vkms_config_delete_plane() - Remove a plane configuration and frees its memory
  *
  * This will delete a plane configuration from the parent configuration. This will NOT
- * cleanup and frees the vkms_plane that can be stored in @vkms_config_plane.
+ * cleanup and frees the vkms_plane that can be stored in @vkms_config_plane. It will also remove
+ * any reference to this plane in @vkms_config.
+ *
  * @vkms_config_plane: Plane configuration to cleanup
+ * @vkms_config: Parent configuration
+ */
+void vkms_config_delete_plane(struct vkms_config_plane *vkms_config_plane,
+			      struct vkms_config *vkms_config);
+/**
+ * vkms_config_delete_crtc() - Remove a CRTC configuration and frees its memory
+ *
+ * This will delete a CRTC configuration from the parent configuration. This will NOT
+ * cleanup and frees the vkms_crtc that can be stored in @vkms_config_crtc. It will also remove
+ * any reference to this CRTC in @vkms_config.
+ *
+ * @vkms_config_crtc: Plane configuration to cleanup
+ * @vkms_config: Parent configuration
+ */
+void vkms_config_delete_crtc(struct vkms_config_crtc *vkms_config_crtc,
+			     struct vkms_config *vkms_config);
+/**
+ * vkms_config_delete_encoder() - Remove an encoder configuration and frees its memory
+ *
+ * This will delete an encoder configuration from the parent configuration. This will NOT
+ * cleanup and frees the vkms_encoder that can be stored in @vkms_config_encoder. It will also
+ * remove any reference to this CRTC in @vkms_config.
+ *
+ * @vkms_config_encoder: Plane configuration to cleanup
+ * @vkms_config: Parent configuration
  */
-void vkms_config_delete_plane(struct vkms_config_plane *vkms_config_plane);
+void vkms_config_delete_encoder(struct vkms_config_encoder *vkms_config_encoder,
+				struct vkms_config *vkms_config);
 
 /**
  * vkms_config_alloc_default() - Allocate the configuration for the default device
diff --git a/drivers/gpu/drm/vkms/vkms_crtc.c b/drivers/gpu/drm/vkms/vkms_crtc.c
index 6f6d3118b2f2..654238dbba7f 100644
--- a/drivers/gpu/drm/vkms/vkms_crtc.c
+++ b/drivers/gpu/drm/vkms/vkms_crtc.c
@@ -281,9 +281,17 @@ static void vkms_crtc_destroy_workqueue(struct drm_device *dev, void *raw_vkms_c
 	destroy_workqueue(vkms_crtc->composer_workq);
 }
 
+static void vkms_crtc_cleanup_writeback_connector(struct drm_device *dev, void *data)
+{
+	struct vkms_crtc *vkms_crtc = data;
+
+	drm_writeback_connector_cleanup(&vkms_crtc->wb_connector);
+}
+
 struct vkms_crtc *vkms_crtc_init(struct vkms_device *vkmsdev,
 				 struct drm_plane *primary,
-				 struct drm_plane *cursor)
+				 struct drm_plane *cursor,
+				 struct vkms_config_crtc *config)
 {
 	struct drm_device *dev = &vkmsdev->drm;
 	struct vkms_crtc *vkms_crtc;
@@ -317,5 +325,15 @@ struct vkms_crtc *vkms_crtc_init(struct vkms_device *vkmsdev,
 	if (ret)
 		return ERR_PTR(ret);
 
+	if (config->writeback) {
+		ret = vkms_enable_writeback_connector(vkmsdev, vkms_crtc);
+		if (ret)
+			return ERR_PTR(ret);
+		ret = drmm_add_action_or_reset(&vkmsdev->drm, vkms_crtc_cleanup_writeback_connector,
+					       vkms_crtc);
+		if (ret)
+			return ERR_PTR(ret);
+	}
+
 	return vkms_crtc;
 }
diff --git a/drivers/gpu/drm/vkms/vkms_crtc.h b/drivers/gpu/drm/vkms/vkms_crtc.h
index dde28884a0a5..a271e95f1cfe 100644
--- a/drivers/gpu/drm/vkms/vkms_crtc.h
+++ b/drivers/gpu/drm/vkms/vkms_crtc.h
@@ -86,5 +86,6 @@ struct vkms_crtc {
  */
 struct vkms_crtc *vkms_crtc_init(struct vkms_device *vkmsdev,
 				 struct drm_plane *primary,
-				 struct drm_plane *cursor);
+				 struct drm_plane *cursor,
+				 struct vkms_config_crtc *config);
 #endif //_VKMS_CRTC_H
diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c
index 403006a0bb61..6deff5099322 100644
--- a/drivers/gpu/drm/vkms/vkms_drv.c
+++ b/drivers/gpu/drm/vkms/vkms_drv.c
@@ -153,13 +153,12 @@ static const struct drm_connector_helper_funcs vkms_conn_helper_funcs = {
 
 static int vkms_output_init(struct vkms_device *vkmsdev)
 {
-	struct vkms_config_plane *config_plane;
+	struct vkms_config_encoder *config_encoder;
 	struct drm_device *dev = &vkmsdev->drm;
+	struct vkms_config_plane *config_plane;
+	struct vkms_config_crtc *config_crtc;
 	struct drm_connector *connector;
-	struct drm_encoder *encoder;
-	struct vkms_crtc *crtc;
-	struct drm_plane *plane;
-	struct vkms_plane *primary, *cursor = NULL;
+	unsigned long idx;
 	int ret;
 	int writeback;
 
@@ -169,22 +168,30 @@ static int vkms_output_init(struct vkms_device *vkmsdev)
 			ret = PTR_ERR(config_plane->plane);
 			return ret;
 		}
-
-		if (config_plane->type == DRM_PLANE_TYPE_PRIMARY)
-			primary = config_plane->plane;
-		else if (config_plane->type == DRM_PLANE_TYPE_CURSOR)
-			cursor = config_plane->plane;
 	}
 
-	/* [1]: Initialize the crtc component */
-	crtc = vkms_crtc_init(vkmsdev, &primary->base,
-			      cursor ? &cursor->base : NULL);
-	if (IS_ERR(crtc))
-		return PTR_ERR(crtc);
+	list_for_each_entry(config_crtc, &vkmsdev->config->crtcs, link) {
+		struct drm_plane *primary = NULL, *cursor = NULL;
+
+		xa_for_each(&config_crtc->possible_planes, idx, config_plane) {
+			if (config_plane->type == DRM_PLANE_TYPE_PRIMARY)
+				primary = &config_plane->plane->base;
+			else if (config_plane->type == DRM_PLANE_TYPE_CURSOR)
+				cursor = &config_plane->plane->base;
+		}
+
+		config_crtc->crtc = vkms_crtc_init(vkmsdev, primary, cursor, config_crtc);
 
-	/* Enable the output's CRTC for all the planes */
-	drm_for_each_plane(plane, &vkmsdev->drm) {
-		plane->possible_crtcs |= drm_crtc_mask(&crtc->base);
+		if (IS_ERR(config_crtc->crtc)) {
+			ret = PTR_ERR(config_crtc->crtc);
+			return ret;
+		}
+	}
+
+	list_for_each_entry(config_crtc, &vkmsdev->config->crtcs, link) {
+		xa_for_each(&config_crtc->possible_planes, idx, config_plane) {
+			config_plane->plane->base.possible_crtcs |= drm_crtc_mask(&config_crtc->crtc->base);
+		}
 	}
 
 	/* Initialize the connector component */
@@ -201,32 +208,28 @@ static int vkms_output_init(struct vkms_device *vkmsdev)
 
 	drm_connector_helper_add(connector, &vkms_conn_helper_funcs);
 
-	/* Initialize the encoder component */
-	encoder = drmm_kzalloc(&vkmsdev->drm, sizeof(*encoder), GFP_KERNEL);
-	if (!encoder)
-		return -ENOMEM;
-
-	ret = drmm_encoder_init(dev, encoder, &vkms_encoder_funcs,
-				DRM_MODE_ENCODER_VIRTUAL, NULL);
-	if (ret) {
-		DRM_ERROR("Failed to init encoder\n");
-		return ret;
-	}
-
-	encoder->possible_crtcs = drm_crtc_mask(&crtc->base);
 
-	/* Attach the encoder and the connector */
-	ret = drm_connector_attach_encoder(connector, encoder);
-	if (ret) {
-		DRM_ERROR("Failed to attach connector to encoder\n");
-		return ret;
-	}
+	list_for_each_entry(config_encoder, &vkmsdev->config->encoders, link) {
+		config_encoder->encoder = drmm_kzalloc(&vkmsdev->drm,
+						       sizeof(*config_encoder->encoder),
+						       GFP_KERNEL);
+		if (!config_encoder->encoder)
+			return -ENOMEM;
+		ret = drmm_encoder_init(dev, config_encoder->encoder, &vkms_encoder_funcs,
+					DRM_MODE_ENCODER_VIRTUAL, NULL);
+		if (ret) {
+			DRM_ERROR("Failed to init encoder\n");
+			return ret;
+		}
 
-	/* Initialize the writeback component */
-	if (vkmsdev->config->writeback) {
-		writeback = vkms_enable_writeback_connector(vkmsdev, crtc);
-		if (writeback)
-			DRM_ERROR("Failed to init writeback connector\n");
+		xa_for_each(&config_encoder->possible_crtcs, idx, config_crtc) {
+			config_encoder->encoder->possible_crtcs |= drm_crtc_mask(&config_crtc->crtc->base);
+		}
+		if (IS_ERR(config_encoder->encoder))
+			return PTR_ERR(config_encoder->encoder);
+		ret = drm_connector_attach_encoder(connector, config_encoder->encoder);
+		if (ret)
+			return ret;
 	}
 
 	drm_mode_config_reset(dev);

-- 
2.44.2


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ