diff mbox

[1/7] drm/vmwgfx: Avoid iterating over display unit if crtc is available

Message ID 1516109674-10087-2-git-send-email-thellstrom@vmware.com (mailing list archive)
State New, archived
Headers show

Commit Message

Thomas Hellstrom Jan. 16, 2018, 1:34 p.m. UTC
From: Deepak Rawat <drawat@vmware.com>

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>
Reviewed-by: Thomas Hellstrom <thellstrom@vmware.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(-)
diff mbox

Patch

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index a2a93d7..cc98e01 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -900,11 +900,11 @@  static int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer,
 	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);
@@ -940,11 +940,12 @@  int vmw_kms_readback(struct vmw_private *dev_priv,
 	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");
@@ -1102,12 +1103,12 @@  static int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer,
 	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,
@@ -1593,7 +1594,7 @@  static int vmw_kms_generic_present(struct vmw_private *dev_priv,
 {
 	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);
 }
 
 
@@ -1612,7 +1613,7 @@  int vmw_kms_present(struct vmw_private *dev_priv,
 	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,
@@ -2340,10 +2341,16 @@  int vmw_kms_helper_dirty(struct vmw_private *dev_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++) {
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
index ff9c838..70a7be2 100644
--- 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;
@@ -398,20 +400,23 @@  int vmw_kms_sou_do_surface_dirty(struct vmw_private *dev_priv,
 				 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
@@ -425,7 +430,8 @@  int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv,
 			       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,
@@ -435,7 +441,8 @@  int vmw_kms_stdu_dma(struct vmw_private *dev_priv,
 		     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);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
index bc5f602..21f4019 100644
--- 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 drm_crtc *crtc,
 	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 vmw_kms_dirty *dirty)
  * @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 vmw_private *dev_priv,
 				 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);
@@ -923,6 +925,7 @@  int vmw_kms_sou_do_surface_dirty(struct vmw_private *dev_priv,
 	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;
@@ -994,6 +997,7 @@  static void vmw_sou_dmabuf_clip(struct vmw_kms_dirty *dirty)
  * @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.
@@ -1004,7 +1008,8 @@  int vmw_kms_sou_do_dmabuf_dirty(struct vmw_private *dev_priv,
 				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,
@@ -1021,6 +1026,7 @@  int vmw_kms_sou_do_dmabuf_dirty(struct vmw_private *dev_priv,
 	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) *
@@ -1092,6 +1098,7 @@  static void vmw_sou_readback_clip(struct vmw_kms_dirty *dirty)
  * 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.
@@ -1101,7 +1108,8 @@  int vmw_kms_sou_readback(struct vmw_private *dev_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;
@@ -1116,6 +1124,7 @@  int vmw_kms_sou_readback(struct vmw_private *dev_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) *
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
index 90b5437..b2f7db6 100644
--- 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(struct drm_crtc *crtc,
 
 	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;
@@ -793,6 +793,7 @@  static void vmw_stdu_dmabuf_cpu_commit(struct vmw_kms_dirty *dirty)
  * @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
@@ -809,7 +810,8 @@  int vmw_kms_stdu_dma(struct vmw_private *dev_priv,
 		     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;
@@ -843,6 +845,8 @@  int vmw_kms_stdu_dma(struct vmw_private *dev_priv,
 		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,
@@ -954,6 +958,7 @@  static void vmw_kms_stdu_surface_fifo_commit(struct vmw_kms_dirty *dirty)
  * @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.
@@ -966,7 +971,8 @@  int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv,
 			       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);
@@ -991,6 +997,7 @@  int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv,
 	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;