[PATCH 5/5] drm/i915: Defer the FBC w/a invalidation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hook into the frontbuffer write and delayed flush mechanism to avoid
having to send the FBC w/a on every batch, and instead just send the
w/a whenever we update the scanout.

Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/i915_drv.h            |  1 +
 drivers/gpu/drm/i915/i915_gem.c            |  2 +-
 drivers/gpu/drm/i915/i915_gem_execbuffer.c |  2 +-
 drivers/gpu/drm/i915/intel_display.c       | 30 ++++++++++++++++++------------
 drivers/gpu/drm/i915/intel_drv.h           |  4 ++--
 drivers/gpu/drm/i915/intel_pm.c            |  2 ++
 drivers/gpu/drm/i915/intel_ringbuffer.c    |  9 +++------
 drivers/gpu/drm/i915/intel_ringbuffer.h    |  2 +-
 8 files changed, 29 insertions(+), 23 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 1257e0e..7dc76bf 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1070,6 +1070,7 @@ typedef struct drm_i915_private {
 
 	unsigned long cfb_size;
 	unsigned int cfb_fb;
+	bool cfb_enabled;
 	enum plane cfb_plane;
 	int cfb_y;
 	struct intel_fbc_work *fbc_work;
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 6661adb..707a55e 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -3323,7 +3323,7 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write)
 		obj->dirty = 1;
 
 		if (obj->pin_count && !list_empty(&obj->fb_list))
-			intel_mark_fb_busy(obj, NULL);
+			intel_mark_fb_busy(obj);
 	}
 
 	trace_i915_gem_object_change_domain(obj,
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index dabd9af..c6a02d7 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -786,7 +786,7 @@ i915_gem_execbuffer_move_to_active(struct list_head *objects,
 			obj->dirty = 1;
 			obj->last_write_seqno = intel_ring_get_seqno(ring);
 			if (obj->pin_count && !list_empty(&obj->fb_list))
-				intel_mark_fb_busy(obj, ring);
+				intel_mark_fb_busy(obj);
 		}
 
 		trace_i915_gem_object_change_domain(obj, old_read, old_write);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index be60f12..9a90aa5 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -7108,6 +7108,14 @@ static void intel_display_refresh(struct work_struct *work)
 		if (!fb->refresh_pending)
 			continue;
 
+		if (fb->fbc_dirty) {
+			flush |= RING_FBC;
+			if (fb->obj->ring)
+				rings |= 1 << fb->obj->ring->id;
+			intel_update_fbc(dev);
+			fb->fbc_dirty = false;
+		}
+
 		if (fb->refresh_mode == REFRESH_NONE)
 			i915_gem_release_mmap(fb->obj);
 		fb->obj->base.write_domain &= ~I915_GEM_DOMAIN_GTT;
@@ -7129,10 +7137,10 @@ static void intel_display_refresh(struct work_struct *work)
 	mutex_unlock(&dev->struct_mutex);
 }
 
-static void __intel_mark_fb_busy(struct intel_framebuffer *fb,
-				 struct intel_ring_buffer *ring)
+static void __intel_mark_fb_busy(struct intel_framebuffer *fb)
 {
 	struct drm_device *dev = fb->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_crtc *crtc;
 	bool refresh = false;
 
@@ -7149,14 +7157,13 @@ static void __intel_mark_fb_busy(struct intel_framebuffer *fb,
 
 	refresh = false;
 
-	if (ring && intel_fbc_enabled(dev)) {
-		ring->fbc_dirty = true;
+	if (dev_priv->cfb_enabled) {
+		intel_disable_fbc(dev);
+		fb->fbc_dirty = true;
 		refresh = true;
 	}
 
 	if (refresh) {
-		struct drm_i915_private *dev_priv = dev->dev_private;
-
 		fb->refresh_pending = true;
 		queue_delayed_work(dev_priv->wq,
 				   &dev_priv->display_refresh_work,
@@ -7164,8 +7171,7 @@ static void __intel_mark_fb_busy(struct intel_framebuffer *fb,
 	}
 }
 
-void intel_mark_fb_busy(struct drm_i915_gem_object *obj,
-			struct intel_ring_buffer *ring)
+void intel_mark_fb_busy(struct drm_i915_gem_object *obj)
 {
 	struct intel_framebuffer *fb;
 
@@ -7173,7 +7179,7 @@ void intel_mark_fb_busy(struct drm_i915_gem_object *obj,
 		if (fb->refresh_mode == REFRESH_USER)
 			continue;
 
-		__intel_mark_fb_busy(fb, NULL);
+		__intel_mark_fb_busy(fb);
 	}
 }
 
@@ -7622,8 +7628,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
 	if (ret)
 		goto cleanup_pending;
 
-	intel_disable_fbc(dev);
-	intel_mark_fb_busy(obj, NULL);
+	intel_mark_fb_busy(obj);
 	mutex_unlock(&dev->struct_mutex);
 
 	trace_i915_flip_request(intel_crtc->plane, obj);
@@ -9151,7 +9156,7 @@ static int intel_user_framebuffer_dirty(struct drm_framebuffer *fb,
 	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
 
 	if (intel_fb->refresh_mode == REFRESH_USER)
-		__intel_mark_fb_busy(intel_fb, NULL);
+		__intel_mark_fb_busy(intel_fb);
 
 	return 0;
 }
@@ -9267,6 +9272,7 @@ int intel_framebuffer_init(struct drm_device *dev,
 	intel_fb->powersave = true;
 	intel_fb->refresh_mode = REFRESH_NONE;
 	intel_fb->refresh_pending = false;
+	intel_fb->fbc_dirty = false;
 
 	ret = drm_framebuffer_init(dev, &intel_fb->base, &intel_fb_funcs);
 	if (ret) {
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 9f32949..01957bf 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -107,6 +107,7 @@ struct intel_framebuffer {
 #define REFRESH_NONE 0
 #define REFRESH_USER 1
 	unsigned refresh_pending:1;
+	unsigned fbc_dirty:1;
 	struct list_head obj_list;
 };
 
@@ -585,8 +586,7 @@ extern bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg,
 extern void intel_dvo_init(struct drm_device *dev);
 extern void intel_tv_init(struct drm_device *dev);
 extern void intel_mark_busy(struct drm_device *dev);
-extern void intel_mark_fb_busy(struct drm_i915_gem_object *obj,
-			       struct intel_ring_buffer *ring);
+extern void intel_mark_fb_busy(struct drm_i915_gem_object *obj);
 extern void intel_mark_idle(struct drm_device *dev);
 extern void intel_lvds_init(struct drm_device *dev);
 extern bool intel_is_dual_link_lvds(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 2f6150b..711cdd0 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -347,6 +347,7 @@ static void intel_fbc_work_fn(struct work_struct *__work)
 
 static void intel_cancel_fbc_work(struct drm_i915_private *dev_priv)
 {
+	dev_priv->cfb_enabled = false;
 	if (dev_priv->fbc_work == NULL)
 		return;
 
@@ -379,6 +380,7 @@ void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
 
 	intel_cancel_fbc_work(dev_priv);
 
+	dev_priv->cfb_enabled = true;
 	work = kzalloc(sizeof *work, GFP_KERNEL);
 	if (work == NULL) {
 		DRM_ERROR("Failed to allocate FBC work structure\n");
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 601e1eb..1383267 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -278,12 +278,10 @@ static int gen7_ring_fbc_flush(struct intel_ring_buffer *ring, u32 value)
 {
 	int ret;
 
-	if (!ring->fbc_dirty)
-		return 0;
-
 	ret = intel_ring_begin(ring, 4);
 	if (ret)
 		return ret;
+
 	intel_ring_emit(ring, MI_NOOP);
 	/* WaFbcNukeOn3DBlt:ivb/hsw */
 	intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
@@ -291,7 +289,6 @@ static int gen7_ring_fbc_flush(struct intel_ring_buffer *ring, u32 value)
 	intel_ring_emit(ring, value);
 	intel_ring_advance(ring);
 
-	ring->fbc_dirty = false;
 	return 0;
 }
 
@@ -353,7 +350,7 @@ gen7_render_ring_flush(struct intel_ring_buffer *ring, u32 action)
 		intel_ring_advance(ring);
 	}
 
-	if (action & RING_FLUSH)
+	if (action & RING_FBC)
 		return gen7_ring_fbc_flush(ring, FBC_REND_NUKE);
 
 	return 0;
@@ -1737,7 +1734,7 @@ static int gen6_ring_flush(struct intel_ring_buffer *ring, u32 action)
 		intel_ring_advance(ring);
 	}
 
-	if (IS_GEN7(dev) && action & RING_FLUSH)
+	if (IS_GEN7(dev) && action & RING_FBC)
 		return gen7_ring_fbc_flush(ring, FBC_REND_CACHE_CLEAN);
 
 	return 0;
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 5066b3b..c91a4b1 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -96,6 +96,7 @@ struct  intel_ring_buffer {
 				  u32 action);
 #define RING_FLUSH	0x1
 #define RING_INVALIDATE 0x2
+#define RING_FBC	0x4
 
 	int		(*add_request)(struct intel_ring_buffer *ring);
 	/* Some chipsets are not quite as coherent as advertised and need
@@ -146,7 +147,6 @@ struct  intel_ring_buffer {
 	 */
 	u32 outstanding_lazy_request;
 	bool gpu_caches_dirty;
-	bool fbc_dirty;
 
 	wait_queue_head_t irq_queue;
 
-- 
1.8.3.1



[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux