From 91e9f352cd1b79772b4883fd31e04655d4a97318 Mon Sep 17 00:00:00 2001 From: Deepak Rawat Date: Tue, 16 Jan 2018 08:24:17 +0100 Subject: [PATCH] drm/vmwgfx: Avoid iterating over display unit if crtc is available 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 Reviewed-by: Sinclair Yeh Signed-off-by: Thomas Hellstrom --- 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 --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 34ecc27fc30a..53392d64ca03 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -888,11 +888,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); @@ -928,11 +928,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"); @@ -1090,12 +1091,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, @@ -1581,7 +1582,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); } @@ -1600,7 +1601,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, @@ -2328,10 +2329,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 cd9da2dd79af..42b0f1589d3f 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 63a4cd794b73..a17f6c70fc38 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 b68d74888ab1..c22bf80d4ddd 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; @@ -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 *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; @@ -852,6 +854,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, @@ -963,6 +967,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. @@ -975,7 +980,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); @@ -1000,6 +1006,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;