Currently a tiled frame buffer to be scanned out is always installed
with a fence, leading to fence starvation on gen9lp virtualization
use case where graphics stacks of service and guest OSes compete for
fences.

By design, this fence is always needed by i965-(GEN4-) platforms.
For GEN4 and above, the fence is only required when the frame buffer
compression is enabled.

Changes are made to follow graphics hardware design principles.

Signed-off-by: Guang Bai <guang....@intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 44 +++++++++++++++++++++++++++---------
 drivers/gpu/drm/i915/intel_drv.h     |  4 +++-
 drivers/gpu/drm/i915/intel_fbc.c     |  2 +-
 drivers/gpu/drm/i915/intel_fbdev.c   |  3 ++-
 4 files changed, 39 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index 3dbf5ed..59004f5 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2068,7 +2068,8 @@ static unsigned int intel_surf_alignment(const struct 
drm_framebuffer *fb,
 }
 
 struct i915_vma *
-intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, unsigned int rotation)
+intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, unsigned int rotation,
+                       struct drm_plane *plane, enum pipe pipe)
 {
        struct drm_device *dev = fb->dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
@@ -2076,6 +2077,8 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, 
unsigned int rotation)
        struct i915_ggtt_view view;
        struct i915_vma *vma;
        u32 alignment;
+       bool needs_fence = false;
+       struct intel_plane *intel_plane;
 
        WARN_ON(!mutex_is_locked(&dev->struct_mutex));
 
@@ -2105,13 +2108,19 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, 
unsigned int rotation)
        vma = i915_gem_object_pin_to_display_plane(obj, alignment, &view);
        if (IS_ERR(vma))
                goto err;
+       /*
+        * Install the fence for pre-i965(GEN4-) tiled frame buffers all the
+        * time but only do it for i965(GEN4) and beyond when the frame buffer
+        * compression is enabled during boot up or runtime.
+        */
+       intel_plane = to_intel_plane(plane);
+       if (INTEL_GEN(dev_priv) < 4 || (intel_fbc_can_enable(dev_priv) &&
+               (pipe == PIPE_A) && intel_plane &&
+               (intel_plane->id == PLANE_PRIMARY)))
+               needs_fence = true;
 
        if (i915_vma_is_map_and_fenceable(vma)) {
-               /* Install a fence for tiled scan-out. Pre-i965 always needs a
-                * fence, whereas 965+ only requires a fence if using
-                * framebuffer compression.  For simplicity, we always, when
-                * possible, install a fence as the cost is not that onerous.
-                *
+               /*
                 * If we fail to fence the tiled scanout, then either the
                 * modeset will reject the change (which is highly unlikely as
                 * the affected systems, all but one, do not have unmappable
@@ -2123,7 +2132,16 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, 
unsigned int rotation)
                 * something and try to run the system in a "less than optimal"
                 * mode that matches the user configuration.
                 */
-               i915_vma_pin_fence(vma);
+               if (needs_fence)
+                       i915_vma_pin_fence(vma);
+               else if (vma->fence)
+                       /*
+                        * For a reused fence, increase its ref count even if
+                        * it's not pinned to maintain the count consistancy.
+                        * This is because the count is unconditionally 
+                        * decreased when the fence is unpinned.
+                        */
+                       vma->fence->pin_count++;
        }
 
        i915_vma_get(vma);
@@ -2808,7 +2826,8 @@ intel_find_initial_plane_obj(struct intel_crtc 
*intel_crtc,
 valid_fb:
        mutex_lock(&dev->struct_mutex);
        intel_state->vma =
-               intel_pin_and_fence_fb_obj(fb, primary->state->rotation);
+               intel_pin_and_fence_fb_obj(fb, primary->state->rotation,
+                                       primary, intel_crtc->pipe);
        mutex_unlock(&dev->struct_mutex);
        if (IS_ERR(intel_state->vma)) {
                DRM_ERROR("failed to pin boot fb on pipe %d: %li\n",
@@ -12711,8 +12730,9 @@ intel_prepare_plane_fb(struct drm_plane *plane,
                ret = i915_gem_object_attach_phys(obj, align);
        } else {
                struct i915_vma *vma;
-
-               vma = intel_pin_and_fence_fb_obj(fb, new_state->rotation);
+               struct intel_crtc *temp_crtc = to_intel_crtc(new_state->crtc);
+               vma = intel_pin_and_fence_fb_obj(fb, new_state->rotation,
+                                               plane, temp_crtc->pipe);
                if (!IS_ERR(vma))
                        to_intel_plane_state(new_state)->vma = vma;
                else
@@ -13128,7 +13148,9 @@ intel_legacy_cursor_update(struct drm_plane *plane,
                        goto out_unlock;
                }
        } else {
-               vma = intel_pin_and_fence_fb_obj(fb, new_plane_state->rotation);
+               struct intel_crtc *temp_crtc = to_intel_crtc(crtc);
+               vma = intel_pin_and_fence_fb_obj(fb, new_plane_state->rotation,
+                                               plane, temp_crtc->pipe);
                if (IS_ERR(vma)) {
                        DRM_DEBUG_KMS("failed to pin object\n");
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 898064e..7d98e069 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1503,7 +1503,8 @@ void intel_release_load_detect_pipe(struct drm_connector 
*connector,
                                    struct intel_load_detect_pipe *old,
                                    struct drm_modeset_acquire_ctx *ctx);
 struct i915_vma *
-intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, unsigned int rotation);
+intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, unsigned int rotation,
+                          struct drm_plane *plane, enum pipe pipe);
 void intel_unpin_fb_vma(struct i915_vma *vma);
 struct drm_framebuffer *
 intel_framebuffer_create(struct drm_i915_gem_object *obj,
@@ -1759,6 +1760,7 @@ void intel_fbc_flush(struct drm_i915_private *dev_priv,
                     unsigned int frontbuffer_bits, enum fb_op_origin origin);
 void intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv);
 void intel_fbc_handle_fifo_underrun_irq(struct drm_i915_private *dev_priv);
+bool intel_fbc_can_enable(struct drm_i915_private *dev_priv);
 
 /* intel_hdmi.c */
 void intel_hdmi_init(struct drm_i915_private *dev_priv, i915_reg_t hdmi_reg,
diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
index d7d1ac7..6c9d704 100644
--- a/drivers/gpu/drm/i915/intel_fbc.c
+++ b/drivers/gpu/drm/i915/intel_fbc.c
@@ -862,7 +862,7 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc)
        return true;
 }
 
-static bool intel_fbc_can_enable(struct drm_i915_private *dev_priv)
+bool intel_fbc_can_enable(struct drm_i915_private *dev_priv)
 {
        struct intel_fbc *fbc = &dev_priv->fbc;
 
diff --git a/drivers/gpu/drm/i915/intel_fbdev.c 
b/drivers/gpu/drm/i915/intel_fbdev.c
index da48af1..ef04c7e 100644
--- a/drivers/gpu/drm/i915/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/intel_fbdev.c
@@ -211,7 +211,8 @@ static int intelfb_create(struct drm_fb_helper *helper,
         * This also validates that any existing fb inherited from the
         * BIOS is suitable for own access.
         */
-       vma = intel_pin_and_fence_fb_obj(&ifbdev->fb->base, DRM_MODE_ROTATE_0);
+       vma = intel_pin_and_fence_fb_obj(&ifbdev->fb->base, DRM_MODE_ROTATE_0,
+                                        NULL, INVALID_PIPE);
        if (IS_ERR(vma)) {
                ret = PTR_ERR(vma);
                goto out_unlock;
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to