Blob Blame History Raw
From: Deepak Rawat <drawat@vmware.com>
Date: Tue, 16 Jan 2018 08:24:17 +0100
Subject: drm/vmwgfx: Avoid iterating over display unit if crtc is available
Git-commit: 91e9f352cd1b79772b4883fd31e04655d4a97318
Patch-mainline: v4.17-rc1
References: FATE#326289 FATE#326079 FATE#326049 FATE#322398 FATE#326166

In case of page flip there is no need to iterate over all display unit
in the function "vmw_kms_helper_dirty". If crtc is available then
dirty commands is performed on that crtc only.

Signed-off-by: Deepak Rawat <drawat@vmware.com>
Reviewed-by: Sinclair Yeh <syeh@vmware.com>
Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
Acked-by: Petr Tesarik <ptesarik@suse.com>
---
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.c  |   31 +++++++++++++++++++------------
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.h  |   17 ++++++++++++-----
 drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c |   19 ++++++++++++++-----
 drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c |   15 +++++++++++----
 4 files changed, 56 insertions(+), 26 deletions(-)

--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -887,11 +887,11 @@ static int vmw_framebuffer_surface_dirty
 	if (dev_priv->active_display_unit == vmw_du_screen_object)
 		ret = vmw_kms_sou_do_surface_dirty(dev_priv, &vfbs->base,
 						   clips, NULL, NULL, 0, 0,
-						   num_clips, inc, NULL);
+						   num_clips, inc, NULL, NULL);
 	else
 		ret = vmw_kms_stdu_surface_dirty(dev_priv, &vfbs->base,
 						 clips, NULL, NULL, 0, 0,
-						 num_clips, inc, NULL);
+						 num_clips, inc, NULL, NULL);
 
 	vmw_fifo_flush(dev_priv, false);
 	ttm_read_unlock(&dev_priv->reservation_sem);
@@ -927,11 +927,12 @@ int vmw_kms_readback(struct vmw_private
 	switch (dev_priv->active_display_unit) {
 	case vmw_du_screen_object:
 		return vmw_kms_sou_readback(dev_priv, file_priv, vfb,
-					    user_fence_rep, vclips, num_clips);
+					    user_fence_rep, vclips, num_clips,
+					    NULL);
 	case vmw_du_screen_target:
 		return vmw_kms_stdu_dma(dev_priv, file_priv, vfb,
 					user_fence_rep, NULL, vclips, num_clips,
-					1, false, true);
+					1, false, true, NULL);
 	default:
 		WARN_ONCE(true,
 			  "Readback called with invalid display system.\n");
@@ -1089,12 +1090,12 @@ static int vmw_framebuffer_dmabuf_dirty(
 	case vmw_du_screen_target:
 		ret = vmw_kms_stdu_dma(dev_priv, NULL, &vfbd->base, NULL,
 				       clips, NULL, num_clips, increment,
-				       true, true);
+				       true, true, NULL);
 		break;
 	case vmw_du_screen_object:
 		ret = vmw_kms_sou_do_dmabuf_dirty(dev_priv, &vfbd->base,
 						  clips, NULL, num_clips,
-						  increment, true, NULL);
+						  increment, true, NULL, NULL);
 		break;
 	case vmw_du_legacy:
 		ret = vmw_kms_ldu_do_dmabuf_dirty(dev_priv, &vfbd->base, 0, 0,
@@ -1580,7 +1581,7 @@ static int vmw_kms_generic_present(struc
 {
 	return vmw_kms_sou_do_surface_dirty(dev_priv, vfb, NULL, clips,
 					    &surface->res, destX, destY,
-					    num_clips, 1, NULL);
+					    num_clips, 1, NULL, NULL);
 }
 
 
@@ -1599,7 +1600,7 @@ int vmw_kms_present(struct vmw_private *
 	case vmw_du_screen_target:
 		ret = vmw_kms_stdu_surface_dirty(dev_priv, vfb, NULL, clips,
 						 &surface->res, destX, destY,
-						 num_clips, 1, NULL);
+						 num_clips, 1, NULL, NULL);
 		break;
 	case vmw_du_screen_object:
 		ret = vmw_kms_generic_present(dev_priv, file_priv, vfb, surface,
@@ -2327,10 +2328,16 @@ int vmw_kms_helper_dirty(struct vmw_priv
 
 	dirty->dev_priv = dev_priv;
 
-	list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list, head) {
-		if (crtc->primary->fb != &framebuffer->base)
-			continue;
-		units[num_units++] = vmw_crtc_to_du(crtc);
+	/* If crtc is passed, no need to iterate over other display units */
+	if (dirty->crtc) {
+		units[num_units++] = vmw_crtc_to_du(dirty->crtc);
+	} else {
+		list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list,
+				    head) {
+			if (crtc->primary->fb != &framebuffer->base)
+				continue;
+			units[num_units++] = vmw_crtc_to_du(crtc);
+		}
 	}
 
 	for (k = 0; k < num_units; k++) {
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
@@ -50,6 +50,7 @@
  * @unit: The current display unit. Set up by the helper before a call to @clip.
  * @cmd: The allocated fifo space. Set up by the helper before the first @clip
  * call.
+ * @crtc: The crtc for which to build dirty commands.
  * @num_hits: Number of clip rect commands for this display unit.
  * Cleared by the helper before the first @clip call. Updated by the @clip
  * callback.
@@ -71,6 +72,7 @@ struct vmw_kms_dirty {
 	struct vmw_private *dev_priv;
 	struct vmw_display_unit *unit;
 	void *cmd;
+	struct drm_crtc *crtc;
 	u32 num_hits;
 	s32 fb_x;
 	s32 fb_y;
@@ -404,20 +406,23 @@ int vmw_kms_sou_do_surface_dirty(struct
 				 s32 dest_x,
 				 s32 dest_y,
 				 unsigned num_clips, int inc,
-				 struct vmw_fence_obj **out_fence);
+				 struct vmw_fence_obj **out_fence,
+				 struct drm_crtc *crtc);
 int vmw_kms_sou_do_dmabuf_dirty(struct vmw_private *dev_priv,
 				struct vmw_framebuffer *framebuffer,
 				struct drm_clip_rect *clips,
 				struct drm_vmw_rect *vclips,
 				unsigned num_clips, int increment,
 				bool interruptible,
-				struct vmw_fence_obj **out_fence);
+				struct vmw_fence_obj **out_fence,
+				struct drm_crtc *crtc);
 int vmw_kms_sou_readback(struct vmw_private *dev_priv,
 			 struct drm_file *file_priv,
 			 struct vmw_framebuffer *vfb,
 			 struct drm_vmw_fence_rep __user *user_fence_rep,
 			 struct drm_vmw_rect *vclips,
-			 uint32_t num_clips);
+			 uint32_t num_clips,
+			 struct drm_crtc *crtc);
 
 /*
  * Screen Target Display Unit functions - vmwgfx_stdu.c
@@ -431,7 +436,8 @@ int vmw_kms_stdu_surface_dirty(struct vm
 			       s32 dest_x,
 			       s32 dest_y,
 			       unsigned num_clips, int inc,
-			       struct vmw_fence_obj **out_fence);
+			       struct vmw_fence_obj **out_fence,
+			       struct drm_crtc *crtc);
 int vmw_kms_stdu_dma(struct vmw_private *dev_priv,
 		     struct drm_file *file_priv,
 		     struct vmw_framebuffer *vfb,
@@ -441,7 +447,8 @@ int vmw_kms_stdu_dma(struct vmw_private
 		     uint32_t num_clips,
 		     int increment,
 		     bool to_surface,
-		     bool interruptible);
+		     bool interruptible,
+		     struct drm_crtc *crtc);
 
 int vmw_kms_set_config(struct drm_mode_set *set,
 		       struct drm_modeset_acquire_ctx *ctx);
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
@@ -341,11 +341,11 @@ static int vmw_sou_crtc_page_flip(struct
 	if (vfb->dmabuf)
 		ret = vmw_kms_sou_do_dmabuf_dirty(dev_priv, vfb,
 						  NULL, &vclips, 1, 1,
-						  true, &fence);
+						  true, &fence, crtc);
 	else
 		ret = vmw_kms_sou_do_surface_dirty(dev_priv, vfb,
 						   NULL, &vclips, NULL,
-						   0, 0, 1, 1, &fence);
+						   0, 0, 1, 1, &fence, crtc);
 
 
 	if (ret != 0)
@@ -892,6 +892,7 @@ static void vmw_sou_surface_clip(struct
  * @out_fence: If non-NULL, will return a ref-counted pointer to a
  * struct vmw_fence_obj. The returned fence pointer may be NULL in which
  * case the device has already synchronized.
+ * @crtc: If crtc is passed, perform surface dirty on that crtc only.
  *
  * Returns 0 on success, negative error code on failure. -ERESTARTSYS if
  * interrupted.
@@ -904,7 +905,8 @@ int vmw_kms_sou_do_surface_dirty(struct
 				 s32 dest_x,
 				 s32 dest_y,
 				 unsigned num_clips, int inc,
-				 struct vmw_fence_obj **out_fence)
+				 struct vmw_fence_obj **out_fence,
+				 struct drm_crtc *crtc)
 {
 	struct vmw_framebuffer_surface *vfbs =
 		container_of(framebuffer, typeof(*vfbs), base);
@@ -924,6 +926,7 @@ int vmw_kms_sou_do_surface_dirty(struct
 	sdirty.base.dev_priv = dev_priv;
 	sdirty.base.fifo_reserve_size = sizeof(struct vmw_kms_sou_dirty_cmd) +
 	  sizeof(SVGASignedRect) * num_clips;
+	sdirty.base.crtc = crtc;
 
 	sdirty.sid = srf->id;
 	sdirty.left = sdirty.top = S32_MAX;
@@ -995,6 +998,7 @@ static void vmw_sou_dmabuf_clip(struct v
  * @out_fence: If non-NULL, will return a ref-counted pointer to a
  * struct vmw_fence_obj. The returned fence pointer may be NULL in which
  * case the device has already synchronized.
+ * @crtc: If crtc is passed, perform dmabuf dirty on that crtc only.
  *
  * Returns 0 on success, negative error code on failure. -ERESTARTSYS if
  * interrupted.
@@ -1005,7 +1009,8 @@ int vmw_kms_sou_do_dmabuf_dirty(struct v
 				struct drm_vmw_rect *vclips,
 				unsigned num_clips, int increment,
 				bool interruptible,
-				struct vmw_fence_obj **out_fence)
+				struct vmw_fence_obj **out_fence,
+				struct drm_crtc *crtc)
 {
 	struct vmw_dma_buffer *buf =
 		container_of(framebuffer, struct vmw_framebuffer_dmabuf,
@@ -1022,6 +1027,7 @@ int vmw_kms_sou_do_dmabuf_dirty(struct v
 	if (unlikely(ret != 0))
 		goto out_revert;
 
+	dirty.crtc = crtc;
 	dirty.fifo_commit = vmw_sou_dmabuf_fifo_commit;
 	dirty.clip = vmw_sou_dmabuf_clip;
 	dirty.fifo_reserve_size = sizeof(struct vmw_kms_sou_dmabuf_blit) *
@@ -1093,6 +1099,7 @@ static void vmw_sou_readback_clip(struct
  * Must be set to non-NULL if @file_priv is non-NULL.
  * @vclips: Array of clip rects.
  * @num_clips: Number of clip rects in @vclips.
+ * @crtc: If crtc is passed, readback on that crtc only.
  *
  * Returns 0 on success, negative error code on failure. -ERESTARTSYS if
  * interrupted.
@@ -1102,7 +1109,8 @@ int vmw_kms_sou_readback(struct vmw_priv
 			 struct vmw_framebuffer *vfb,
 			 struct drm_vmw_fence_rep __user *user_fence_rep,
 			 struct drm_vmw_rect *vclips,
-			 uint32_t num_clips)
+			 uint32_t num_clips,
+			 struct drm_crtc *crtc)
 {
 	struct vmw_dma_buffer *buf =
 		container_of(vfb, struct vmw_framebuffer_dmabuf, base)->buffer;
@@ -1117,6 +1125,7 @@ int vmw_kms_sou_readback(struct vmw_priv
 	if (unlikely(ret != 0))
 		goto out_revert;
 
+	dirty.crtc = crtc;
 	dirty.fifo_commit = vmw_sou_readback_fifo_commit;
 	dirty.clip = vmw_sou_readback_clip;
 	dirty.fifo_reserve_size = sizeof(struct vmw_kms_sou_readback_blit) *
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
@@ -530,10 +530,10 @@ static int vmw_stdu_crtc_page_flip(struc
 
 	if (vfb->dmabuf)
 		ret = vmw_kms_stdu_dma(dev_priv, NULL, vfb, NULL, NULL, &vclips,
-				       1, 1, true, false);
+				       1, 1, true, false, crtc);
 	else
 		ret = vmw_kms_stdu_surface_dirty(dev_priv, vfb, NULL, &vclips,
-						 NULL, 0, 0, 1, 1, NULL);
+						 NULL, 0, 0, 1, 1, NULL, crtc);
 	if (ret) {
 		DRM_ERROR("Page flip update error %d.\n", ret);
 		return ret;
@@ -802,6 +802,7 @@ out_cleanup:
  * @to_surface: Whether to DMA to the screen target system as opposed to
  * from the screen target system.
  * @interruptible: Whether to perform waits interruptible if possible.
+ * @crtc: If crtc is passed, perform stdu dma on that crtc only.
  *
  * If DMA-ing till the screen target system, the function will also notify
  * the screen target system that a bounding box of the cliprects has been
@@ -818,7 +819,8 @@ int vmw_kms_stdu_dma(struct vmw_private
 		     uint32_t num_clips,
 		     int increment,
 		     bool to_surface,
-		     bool interruptible)
+		     bool interruptible,
+		     struct drm_crtc *crtc)
 {
 	struct vmw_dma_buffer *buf =
 		container_of(vfb, struct vmw_framebuffer_dmabuf, base)->buffer;
@@ -852,6 +854,8 @@ int vmw_kms_stdu_dma(struct vmw_private
 		ddirty.base.fifo_reserve_size = 0;
 	}
 
+	ddirty.base.crtc = crtc;
+
 	ret = vmw_kms_helper_dirty(dev_priv, vfb, clips, vclips,
 				   0, 0, num_clips, increment, &ddirty.base);
 	vmw_kms_helper_buffer_finish(dev_priv, file_priv, buf, NULL,
@@ -963,6 +967,7 @@ static void vmw_kms_stdu_surface_fifo_co
  * @out_fence: If non-NULL, will return a ref-counted pointer to a
  * struct vmw_fence_obj. The returned fence pointer may be NULL in which
  * case the device has already synchronized.
+ * @crtc: If crtc is passed, perform surface dirty on that crtc only.
  *
  * Returns 0 on success, negative error code on failure. -ERESTARTSYS if
  * interrupted.
@@ -975,7 +980,8 @@ int vmw_kms_stdu_surface_dirty(struct vm
 			       s32 dest_x,
 			       s32 dest_y,
 			       unsigned num_clips, int inc,
-			       struct vmw_fence_obj **out_fence)
+			       struct vmw_fence_obj **out_fence,
+			       struct drm_crtc *crtc)
 {
 	struct vmw_framebuffer_surface *vfbs =
 		container_of(framebuffer, typeof(*vfbs), base);
@@ -1001,6 +1007,7 @@ int vmw_kms_stdu_surface_dirty(struct vm
 	sdirty.base.fifo_reserve_size = sizeof(struct vmw_stdu_surface_copy) +
 		sizeof(SVGA3dCopyBox) * num_clips +
 		sizeof(struct vmw_stdu_update);
+	sdirty.base.crtc = crtc;
 	sdirty.sid = srf->id;
 	sdirty.left = sdirty.top = S32_MAX;
 	sdirty.right = sdirty.bottom = S32_MIN;