public inbox for intel-gfx@lists.freedesktop.org
 help / color / mirror / Atom feed
* [PATCH 00/26] Yet another FBC series, v2
@ 2015-10-27 16:50 Paulo Zanoni
  2015-10-27 16:50 ` [PATCH 01/26] drm/i915: change no_fbc_reason from enum to string Paulo Zanoni
                   ` (25 more replies)
  0 siblings, 26 replies; 44+ messages in thread
From: Paulo Zanoni @ 2015-10-27 16:50 UTC (permalink / raw)
  To: intel-gfx

Hi

This series contains the 18 patches I sent last week + some new ones requested
by the reviewers. Many of those 18 patches changed due to rebasing and the
requested changes to the commit messages, so I figured it would be better to
just create a new email thread for the new stuff. As far as I know, every review
request is implemented here.

Thanks Chris for the reviews so far!
Paulo

Paulo Zanoni (26):
  drm/i915: change no_fbc_reason from enum to string
  drm/i915: don't stop+start FBC at every flip
  drm/i915: rename intel_fbc_nuke to intel_fbc_recompress
  drm/i915: only nuke FBC when a drawing operation triggers a flush
  drm/i915: extract fbc_on_pipe_a_only()
  drm/i915: remove unnecessary check for crtc->primary->fb
  drm/i915: extract crtc_is_valid() on the FBC code
  drm/i915: set dev_priv->fbc.crtc before scheduling the enable work
  drm/i915: use struct intel_crtc *crtc at __intel_fbc_update()
  drm/i915: fix the __intel_fbc_update() comments
  drm/i915: pass the crtc as an argument to intel_fbc_update()
  drm/i915: don't disable_fbc() if FBC is already disabled
  drm/i915: introduce is_active/activate/deactivate to the FBC
    terminology
  drm/i915: refactor FBC deactivation at init
  drm/i915: introduce intel_fbc_{enable,disable}
  drm/i915: remove too-frequent FBC debug message
  drm/i915: fix the CFB size check
  drm/i915: alloc/free the FBC CFB during enable/disable
  drm/i915: move adjusted_mode checks from fbc_update to fbc_enable
  drm/i915: move clock frequency checks from fbc_update to fbc_enable
  drm/i915: check for FBC planes in the same place as the pipes
  drm/i915: clarify that checking the FB stride for CFB is intentional
  drm/i915: use a single intel_fbc_work struct
  drm/i915: wait for a vblank instead of 50ms when enabling FBC
  drm/i915: remove in_dbg_master check from intel_fbc.c
  drm/i915: kill fbc.uncompressed_size

 drivers/gpu/drm/i915/i915_debugfs.c      |   4 +-
 drivers/gpu/drm/i915/i915_drv.h          |  41 +-
 drivers/gpu/drm/i915/i915_reg.h          |   3 +
 drivers/gpu/drm/i915/intel_display.c     |  25 +-
 drivers/gpu/drm/i915/intel_drv.h         |   9 +-
 drivers/gpu/drm/i915/intel_fbc.c         | 842 +++++++++++++++++--------------
 drivers/gpu/drm/i915/intel_frontbuffer.c |   1 +
 drivers/gpu/drm/i915/intel_pm.c          |   2 +-
 8 files changed, 509 insertions(+), 418 deletions(-)

-- 
2.6.1

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

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH 01/26] drm/i915: change no_fbc_reason from enum to string
  2015-10-27 16:50 [PATCH 00/26] Yet another FBC series, v2 Paulo Zanoni
@ 2015-10-27 16:50 ` Paulo Zanoni
  2015-10-27 16:50 ` [PATCH 02/26] drm/i915: don't stop+start FBC at every flip Paulo Zanoni
                   ` (24 subsequent siblings)
  25 siblings, 0 replies; 44+ messages in thread
From: Paulo Zanoni @ 2015-10-27 16:50 UTC (permalink / raw)
  To: intel-gfx

I wanted to add yet another check to intel_fbc_update() and realized
I would need to create yet another enum no_fbc_reason case. So I
remembered this patch series that Damien wrote a long time ago and
nobody ever reviewed, so I decided to reimplement it since the code
changed a lot since then.

Credits-to: Damien Lespiau <damien.lespiau@intel.com>
Cc: Damien Lespiau <damien.lespiau@intel.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c |  2 +-
 drivers/gpu/drm/i915/i915_drv.h     | 19 +--------
 drivers/gpu/drm/i915/intel_drv.h    |  1 -
 drivers/gpu/drm/i915/intel_fbc.c    | 77 +++++++++----------------------------
 4 files changed, 20 insertions(+), 79 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 89ba549..fbde0a4 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1640,7 +1640,7 @@ static int i915_fbc_status(struct seq_file *m, void *unused)
 		seq_puts(m, "FBC enabled\n");
 	else
 		seq_printf(m, "FBC disabled: %s\n",
-			  intel_no_fbc_reason_str(dev_priv->fbc.no_fbc_reason));
+			   dev_priv->fbc.no_fbc_reason);
 
 	if (INTEL_INFO(dev_priv)->gen >= 7)
 		seq_printf(m, "Compressing: %s\n",
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index b408ebf..ee14962 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -923,24 +923,7 @@ struct i915_fbc {
 		struct drm_framebuffer *fb;
 	} *fbc_work;
 
-	enum no_fbc_reason {
-		FBC_OK, /* FBC is enabled */
-		FBC_UNSUPPORTED, /* FBC is not supported by this chipset */
-		FBC_NO_OUTPUT, /* no outputs enabled to compress */
-		FBC_STOLEN_TOO_SMALL, /* not enough space for buffers */
-		FBC_UNSUPPORTED_MODE, /* interlace or doublescanned mode */
-		FBC_MODE_TOO_LARGE, /* mode too large for compression */
-		FBC_BAD_PLANE, /* fbc not supported on plane */
-		FBC_NOT_TILED, /* buffer not tiled */
-		FBC_MULTIPLE_PIPES, /* more than one pipe active */
-		FBC_MODULE_PARAM,
-		FBC_CHIP_DEFAULT, /* disabled by default on this chip */
-		FBC_ROTATION, /* rotation is not supported */
-		FBC_IN_DBG_MASTER, /* kernel debugger is active */
-		FBC_BAD_STRIDE, /* stride is not supported */
-		FBC_PIXEL_RATE, /* pixel rate is too big */
-		FBC_PIXEL_FORMAT /* pixel format is invalid */
-	} no_fbc_reason;
+	const char *no_fbc_reason;
 
 	bool (*fbc_enabled)(struct drm_i915_private *dev_priv);
 	void (*enable_fbc)(struct intel_crtc *crtc);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 1a3bbdc..08847d0 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1305,7 +1305,6 @@ void intel_fbc_invalidate(struct drm_i915_private *dev_priv,
 			  enum fb_op_origin origin);
 void intel_fbc_flush(struct drm_i915_private *dev_priv,
 		     unsigned int frontbuffer_bits, enum fb_op_origin origin);
-const char *intel_no_fbc_reason_str(enum no_fbc_reason reason);
 void intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv);
 
 /* intel_hdmi.c */
diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
index cf47352..d9d7e54 100644
--- a/drivers/gpu/drm/i915/intel_fbc.c
+++ b/drivers/gpu/drm/i915/intel_fbc.c
@@ -471,55 +471,14 @@ void intel_fbc_disable_crtc(struct intel_crtc *crtc)
 	mutex_unlock(&dev_priv->fbc.lock);
 }
 
-const char *intel_no_fbc_reason_str(enum no_fbc_reason reason)
-{
-	switch (reason) {
-	case FBC_OK:
-		return "FBC enabled but currently disabled in hardware";
-	case FBC_UNSUPPORTED:
-		return "unsupported by this chipset";
-	case FBC_NO_OUTPUT:
-		return "no output";
-	case FBC_STOLEN_TOO_SMALL:
-		return "not enough stolen memory";
-	case FBC_UNSUPPORTED_MODE:
-		return "mode incompatible with compression";
-	case FBC_MODE_TOO_LARGE:
-		return "mode too large for compression";
-	case FBC_BAD_PLANE:
-		return "FBC unsupported on plane";
-	case FBC_NOT_TILED:
-		return "framebuffer not tiled or fenced";
-	case FBC_MULTIPLE_PIPES:
-		return "more than one pipe active";
-	case FBC_MODULE_PARAM:
-		return "disabled per module param";
-	case FBC_CHIP_DEFAULT:
-		return "disabled per chip default";
-	case FBC_ROTATION:
-		return "rotation unsupported";
-	case FBC_IN_DBG_MASTER:
-		return "Kernel debugger is active";
-	case FBC_BAD_STRIDE:
-		return "framebuffer stride not supported";
-	case FBC_PIXEL_RATE:
-		return "pixel rate is too big";
-	case FBC_PIXEL_FORMAT:
-		return "pixel format is invalid";
-	default:
-		MISSING_CASE(reason);
-		return "unknown reason";
-	}
-}
-
 static void set_no_fbc_reason(struct drm_i915_private *dev_priv,
-			      enum no_fbc_reason reason)
+			      const char *reason)
 {
 	if (dev_priv->fbc.no_fbc_reason == reason)
 		return;
 
 	dev_priv->fbc.no_fbc_reason = reason;
-	DRM_DEBUG_KMS("Disabling FBC: %s\n", intel_no_fbc_reason_str(reason));
+	DRM_DEBUG_KMS("Disabling FBC: %s\n", reason);
 }
 
 static struct drm_crtc *intel_fbc_find_crtc(struct drm_i915_private *dev_priv)
@@ -862,12 +821,12 @@ static void __intel_fbc_update(struct drm_i915_private *dev_priv)
 		i915.enable_fbc = 0;
 
 	if (i915.enable_fbc < 0) {
-		set_no_fbc_reason(dev_priv, FBC_CHIP_DEFAULT);
+		set_no_fbc_reason(dev_priv, "disabled per chip default");
 		goto out_disable;
 	}
 
 	if (!i915.enable_fbc) {
-		set_no_fbc_reason(dev_priv, FBC_MODULE_PARAM);
+		set_no_fbc_reason(dev_priv, "disabled per module param");
 		goto out_disable;
 	}
 
@@ -882,12 +841,12 @@ static void __intel_fbc_update(struct drm_i915_private *dev_priv)
 	 */
 	crtc = intel_fbc_find_crtc(dev_priv);
 	if (!crtc) {
-		set_no_fbc_reason(dev_priv, FBC_NO_OUTPUT);
+		set_no_fbc_reason(dev_priv, "no output");
 		goto out_disable;
 	}
 
 	if (!multiple_pipes_ok(dev_priv)) {
-		set_no_fbc_reason(dev_priv, FBC_MULTIPLE_PIPES);
+		set_no_fbc_reason(dev_priv, "more than one pipe active");
 		goto out_disable;
 	}
 
@@ -898,18 +857,18 @@ static void __intel_fbc_update(struct drm_i915_private *dev_priv)
 
 	if ((adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) ||
 	    (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)) {
-		set_no_fbc_reason(dev_priv, FBC_UNSUPPORTED_MODE);
+		set_no_fbc_reason(dev_priv, "incompatible mode");
 		goto out_disable;
 	}
 
 	if (!intel_fbc_hw_tracking_covers_screen(intel_crtc)) {
-		set_no_fbc_reason(dev_priv, FBC_MODE_TOO_LARGE);
+		set_no_fbc_reason(dev_priv, "mode too large for compression");
 		goto out_disable;
 	}
 
 	if ((INTEL_INFO(dev_priv)->gen < 4 || HAS_DDI(dev_priv)) &&
 	    intel_crtc->plane != PLANE_A) {
-		set_no_fbc_reason(dev_priv, FBC_BAD_PLANE);
+		set_no_fbc_reason(dev_priv, "FBC unsupported on plane");
 		goto out_disable;
 	}
 
@@ -918,28 +877,28 @@ static void __intel_fbc_update(struct drm_i915_private *dev_priv)
 	 */
 	if (obj->tiling_mode != I915_TILING_X ||
 	    obj->fence_reg == I915_FENCE_REG_NONE) {
-		set_no_fbc_reason(dev_priv, FBC_NOT_TILED);
+		set_no_fbc_reason(dev_priv, "framebuffer not tiled or fenced");
 		goto out_disable;
 	}
 	if (INTEL_INFO(dev_priv)->gen <= 4 && !IS_G4X(dev_priv) &&
 	    crtc->primary->state->rotation != BIT(DRM_ROTATE_0)) {
-		set_no_fbc_reason(dev_priv, FBC_ROTATION);
+		set_no_fbc_reason(dev_priv, "rotation unsupported");
 		goto out_disable;
 	}
 
 	if (!stride_is_valid(dev_priv, fb->pitches[0])) {
-		set_no_fbc_reason(dev_priv, FBC_BAD_STRIDE);
+		set_no_fbc_reason(dev_priv, "framebuffer stride not supported");
 		goto out_disable;
 	}
 
 	if (!pixel_format_is_valid(fb)) {
-		set_no_fbc_reason(dev_priv, FBC_PIXEL_FORMAT);
+		set_no_fbc_reason(dev_priv, "pixel format is invalid");
 		goto out_disable;
 	}
 
 	/* If the kernel debugger is active, always disable compression */
 	if (in_dbg_master()) {
-		set_no_fbc_reason(dev_priv, FBC_IN_DBG_MASTER);
+		set_no_fbc_reason(dev_priv, "Kernel debugger is active");
 		goto out_disable;
 	}
 
@@ -947,12 +906,12 @@ static void __intel_fbc_update(struct drm_i915_private *dev_priv)
 	if ((IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) &&
 	    ilk_pipe_pixel_rate(intel_crtc->config) >=
 	    dev_priv->cdclk_freq * 95 / 100) {
-		set_no_fbc_reason(dev_priv, FBC_PIXEL_RATE);
+		set_no_fbc_reason(dev_priv, "pixel rate is too big");
 		goto out_disable;
 	}
 
 	if (intel_fbc_setup_cfb(intel_crtc)) {
-		set_no_fbc_reason(dev_priv, FBC_STOLEN_TOO_SMALL);
+		set_no_fbc_reason(dev_priv, "not enough stolen memory");
 		goto out_disable;
 	}
 
@@ -995,7 +954,7 @@ static void __intel_fbc_update(struct drm_i915_private *dev_priv)
 	}
 
 	intel_fbc_schedule_enable(intel_crtc);
-	dev_priv->fbc.no_fbc_reason = FBC_OK;
+	dev_priv->fbc.no_fbc_reason = "FBC enabled (not necessarily active)\n";
 	return;
 
 out_disable:
@@ -1088,7 +1047,7 @@ void intel_fbc_init(struct drm_i915_private *dev_priv)
 
 	if (!HAS_FBC(dev_priv)) {
 		dev_priv->fbc.enabled = false;
-		dev_priv->fbc.no_fbc_reason = FBC_UNSUPPORTED;
+		dev_priv->fbc.no_fbc_reason = "unsupported by this chipset";
 		return;
 	}
 
-- 
2.6.1

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

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 02/26] drm/i915: don't stop+start FBC at every flip
  2015-10-27 16:50 [PATCH 00/26] Yet another FBC series, v2 Paulo Zanoni
  2015-10-27 16:50 ` [PATCH 01/26] drm/i915: change no_fbc_reason from enum to string Paulo Zanoni
@ 2015-10-27 16:50 ` Paulo Zanoni
  2015-10-27 18:32   ` Ville Syrjälä
  2015-10-27 19:50   ` Chris Wilson
  2015-10-27 16:50 ` [PATCH 03/26] drm/i915: rename intel_fbc_nuke to intel_fbc_recompress Paulo Zanoni
                   ` (23 subsequent siblings)
  25 siblings, 2 replies; 44+ messages in thread
From: Paulo Zanoni @ 2015-10-27 16:50 UTC (permalink / raw)
  To: intel-gfx

The hardware already takes care of disabling and recompressing FBC
when we do a page flip, so all we need to do is to update the fence
registers and move on.

One of the important things to notice is that on the pre-gen6
platforms the fence is programmed on the FBC control register and the
documentation says we can't update the control register while FBC is
enabled. This would basically mean we'd have to to disable+enable FBC
at every flip in order to make sure the hardware tracking still works,
which doesn't seem to make too much sense. So I sent an email to the
hardware team requesting some clarification. The information I got was
this:

"I don't think any hardware is latching on to 0x100100, 0x100104, or
the old fence number in FBC_CTL. Instructions against changing on the
fly would be to simplify testing and ensure you don't miss any
invalidation that happened right at that time."

So I guess we're fine for flips. But I can't really say I tested FBC
on these ancient platforms - nor that I'll ever propose enabling FBC
by default on them exactly because of problems like these.

v2: Add comment at flush() (Chris).

Testcase: igt/kms_frontbuffer_tracking/fbc*-fliptrack
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h          |   1 +
 drivers/gpu/drm/i915/i915_reg.h          |   3 +
 drivers/gpu/drm/i915/intel_display.c     |   1 -
 drivers/gpu/drm/i915/intel_drv.h         |   2 +
 drivers/gpu/drm/i915/intel_fbc.c         | 103 ++++++++++++++++++++++++++++++-
 drivers/gpu/drm/i915/intel_frontbuffer.c |   1 +
 6 files changed, 108 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index ee14962..77da500 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -928,6 +928,7 @@ struct i915_fbc {
 	bool (*fbc_enabled)(struct drm_i915_private *dev_priv);
 	void (*enable_fbc)(struct intel_crtc *crtc);
 	void (*disable_fbc)(struct drm_i915_private *dev_priv);
+	void (*flip_prepare)(struct drm_i915_private *dev_priv);
 };
 
 /**
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 8942532..3d598a2 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -2028,6 +2028,7 @@ enum skl_disp_power_wells {
 #define   FBC_CTL_C3_IDLE	(1<<13)
 #define   FBC_CTL_STRIDE_SHIFT	(5)
 #define   FBC_CTL_FENCENO_SHIFT	(0)
+#define   FBC_CTL_FENCENO_MASK	0xF
 #define FBC_COMMAND		0x0320c
 #define   FBC_CMD_COMPRESS	(1<<0)
 #define FBC_STATUS		0x03210
@@ -2064,6 +2065,7 @@ enum skl_disp_power_wells {
 #define   DPFC_CTL_LIMIT_1X	(0<<6)
 #define   DPFC_CTL_LIMIT_2X	(1<<6)
 #define   DPFC_CTL_LIMIT_4X	(2<<6)
+#define   DPFC_CTL_FENCE_MASK	0xF
 #define DPFC_RECOMP_CTL		0x320c
 #define   DPFC_RECOMP_STALL_EN	(1<<27)
 #define   DPFC_RECOMP_STALL_WM_SHIFT (16)
@@ -2086,6 +2088,7 @@ enum skl_disp_power_wells {
 #define   FBC_CTL_FALSE_COLOR	(1<<10)
 /* The bit 28-8 is reserved */
 #define   DPFC_RESERVED		(0x1FFFFF00)
+#define   ILK_DPFC_FENCE_MASK	0xF
 #define ILK_DPFC_RECOMP_CTL	0x4320c
 #define ILK_DPFC_STATUS		0x43210
 #define ILK_DPFC_FENCE_YOFF	0x43218
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index bc1907e..d9378c3 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -11502,7 +11502,6 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
 			  to_intel_plane(primary)->frontbuffer_bit);
 	mutex_unlock(&dev->struct_mutex);
 
-	intel_fbc_disable_crtc(intel_crtc);
 	intel_frontbuffer_flip_prepare(dev,
 				       to_intel_plane(primary)->frontbuffer_bit);
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 08847d0..9065a8f 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1305,6 +1305,8 @@ void intel_fbc_invalidate(struct drm_i915_private *dev_priv,
 			  enum fb_op_origin origin);
 void intel_fbc_flush(struct drm_i915_private *dev_priv,
 		     unsigned int frontbuffer_bits, enum fb_op_origin origin);
+void intel_fbc_flip_prepare(struct drm_i915_private *dev_priv,
+			    unsigned int frontbuffer_bits);
 void intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv);
 
 /* intel_hdmi.c */
diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
index d9d7e54..62f158b 100644
--- a/drivers/gpu/drm/i915/intel_fbc.c
+++ b/drivers/gpu/drm/i915/intel_fbc.c
@@ -82,6 +82,22 @@ static void i8xx_fbc_disable(struct drm_i915_private *dev_priv)
 	DRM_DEBUG_KMS("disabled FBC\n");
 }
 
+static void i8xx_fbc_flip_prepare(struct drm_i915_private *dev_priv)
+{
+	struct intel_crtc *crtc = dev_priv->fbc.crtc;
+	struct drm_framebuffer *fb = crtc->base.primary->fb;
+	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
+	uint32_t val;
+
+	/* Although the documentation suggests we can't change DPFC_CONTROL
+	 * while compression is enabled, the hardware guys said that updating
+	 * the fence register bits during a flip is fine. */
+	val = I915_READ(FBC_CONTROL);
+	val &= ~FBC_CTL_FENCENO_MASK;
+	val |= obj->fence_reg;
+	I915_WRITE(FBC_CONTROL, val);
+}
+
 static void i8xx_fbc_enable(struct intel_crtc *crtc)
 {
 	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
@@ -161,6 +177,22 @@ static void g4x_fbc_enable(struct intel_crtc *crtc)
 	DRM_DEBUG_KMS("enabled fbc on plane %c\n", plane_name(crtc->plane));
 }
 
+static void g4x_fbc_flip_prepare(struct drm_i915_private *dev_priv)
+{
+	struct intel_crtc *crtc = dev_priv->fbc.crtc;
+	struct drm_framebuffer *fb = crtc->base.primary->fb;
+	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
+	uint32_t val;
+
+	/* Although the documentation suggests we can't change DPFC_CONTROL
+	 * while compression is enabled, the hardware guys said that updating
+	 * the fence register bits during a flip is fine. */
+	val = I915_READ(DPFC_CONTROL);
+	val &= ~DPFC_CTL_FENCE_MASK;
+	val |= obj->fence_reg;
+	I915_WRITE(DPFC_CONTROL, val);
+}
+
 static void g4x_fbc_disable(struct drm_i915_private *dev_priv)
 {
 	u32 dpfc_ctl;
@@ -236,6 +268,31 @@ static void ilk_fbc_enable(struct intel_crtc *crtc)
 	DRM_DEBUG_KMS("enabled fbc on plane %c\n", plane_name(crtc->plane));
 }
 
+static void ilk_fbc_flip_prepare(struct drm_i915_private *dev_priv)
+{
+	struct intel_crtc *crtc = dev_priv->fbc.crtc;
+	struct drm_framebuffer *fb = crtc->base.primary->fb;
+	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
+	uint32_t val;
+
+	/* Although the documentation suggests we can't change DPFC_CONTROL
+	 * while compression is enabled, the hardware guys said that updating
+	 * the fence register bits during a flip is fine. */
+	val = I915_READ(ILK_DPFC_CONTROL);
+	val &= ~ILK_DPFC_FENCE_MASK;
+	val |= obj->fence_reg;
+	I915_WRITE(ILK_DPFC_CONTROL, val);
+}
+
+static void snb_fbc_flip_prepare(struct drm_i915_private *dev_priv)
+{
+	struct intel_crtc *crtc = dev_priv->fbc.crtc;
+	struct drm_framebuffer *fb = crtc->base.primary->fb;
+	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
+
+	I915_WRITE(SNB_DPFC_CTL_SA, SNB_CPU_FENCE_ENABLE | obj->fence_reg);
+}
+
 static void ilk_fbc_disable(struct drm_i915_private *dev_priv)
 {
 	u32 dpfc_ctl;
@@ -1021,13 +1078,48 @@ void intel_fbc_flush(struct drm_i915_private *dev_priv,
 	if (origin == ORIGIN_GTT)
 		return;
 
+	/* Hardware tracking already recompresses the CFB (nuke) for us if FBC
+	 * is enabled and we do a page flip, so we can safely ignore it here.
+	 * FBC may be disabled in case we got an invalidate() before the
+	 * flush(), so we'll still have to check that case below. */
+	if (origin == ORIGIN_FLIP && dev_priv->fbc.enabled)
+		return;
+
 	mutex_lock(&dev_priv->fbc.lock);
 
 	dev_priv->fbc.busy_bits &= ~frontbuffer_bits;
 
 	if (!dev_priv->fbc.busy_bits) {
-		__intel_fbc_disable(dev_priv);
-		__intel_fbc_update(dev_priv);
+		if (origin == ORIGIN_FLIP) {
+			__intel_fbc_update(dev_priv);
+		} else {
+			__intel_fbc_disable(dev_priv);
+			__intel_fbc_update(dev_priv);
+		}
+	}
+
+	mutex_unlock(&dev_priv->fbc.lock);
+}
+
+void intel_fbc_flip_prepare(struct drm_i915_private *dev_priv,
+			    unsigned int frontbuffer_bits)
+{
+	unsigned int fbc_bits;
+
+	if (!fbc_supported(dev_priv))
+		return;
+
+	mutex_lock(&dev_priv->fbc.lock);
+
+	if (dev_priv->fbc.enabled) {
+		fbc_bits = INTEL_FRONTBUFFER_PRIMARY(dev_priv->fbc.crtc->pipe);
+		if (fbc_bits & frontbuffer_bits)
+			dev_priv->fbc.flip_prepare(dev_priv);
+	} else if (dev_priv->fbc.fbc_work) {
+		fbc_bits = INTEL_FRONTBUFFER_PRIMARY(
+				dev_priv->fbc.fbc_work->crtc->pipe);
+		if (fbc_bits & frontbuffer_bits)
+			__intel_fbc_disable(dev_priv);
 	}
 
 	mutex_unlock(&dev_priv->fbc.lock);
@@ -1063,18 +1155,25 @@ void intel_fbc_init(struct drm_i915_private *dev_priv)
 		dev_priv->fbc.fbc_enabled = ilk_fbc_enabled;
 		dev_priv->fbc.enable_fbc = gen7_fbc_enable;
 		dev_priv->fbc.disable_fbc = ilk_fbc_disable;
+		dev_priv->fbc.flip_prepare = snb_fbc_flip_prepare;
 	} else if (INTEL_INFO(dev_priv)->gen >= 5) {
 		dev_priv->fbc.fbc_enabled = ilk_fbc_enabled;
 		dev_priv->fbc.enable_fbc = ilk_fbc_enable;
 		dev_priv->fbc.disable_fbc = ilk_fbc_disable;
+		if (INTEL_INFO(dev_priv)->gen == 5)
+			dev_priv->fbc.flip_prepare = ilk_fbc_flip_prepare;
+		else
+			dev_priv->fbc.flip_prepare = snb_fbc_flip_prepare;
 	} else if (IS_GM45(dev_priv)) {
 		dev_priv->fbc.fbc_enabled = g4x_fbc_enabled;
 		dev_priv->fbc.enable_fbc = g4x_fbc_enable;
 		dev_priv->fbc.disable_fbc = g4x_fbc_disable;
+		dev_priv->fbc.flip_prepare = g4x_fbc_flip_prepare;
 	} else {
 		dev_priv->fbc.fbc_enabled = i8xx_fbc_enabled;
 		dev_priv->fbc.enable_fbc = i8xx_fbc_enable;
 		dev_priv->fbc.disable_fbc = i8xx_fbc_disable;
+		dev_priv->fbc.flip_prepare = i8xx_fbc_flip_prepare;
 
 		/* This value was pulled out of someone's hat */
 		I915_WRITE(FBC_CONTROL, 500 << FBC_CTL_INTERVAL_SHIFT);
diff --git a/drivers/gpu/drm/i915/intel_frontbuffer.c b/drivers/gpu/drm/i915/intel_frontbuffer.c
index ac85357..31a1ad3 100644
--- a/drivers/gpu/drm/i915/intel_frontbuffer.c
+++ b/drivers/gpu/drm/i915/intel_frontbuffer.c
@@ -192,6 +192,7 @@ void intel_frontbuffer_flip_prepare(struct drm_device *dev,
 	mutex_unlock(&dev_priv->fb_tracking.lock);
 
 	intel_psr_single_frame_update(dev, frontbuffer_bits);
+	intel_fbc_flip_prepare(dev_priv, frontbuffer_bits);
 }
 
 /**
-- 
2.6.1

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

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 03/26] drm/i915: rename intel_fbc_nuke to intel_fbc_recompress
  2015-10-27 16:50 [PATCH 00/26] Yet another FBC series, v2 Paulo Zanoni
  2015-10-27 16:50 ` [PATCH 01/26] drm/i915: change no_fbc_reason from enum to string Paulo Zanoni
  2015-10-27 16:50 ` [PATCH 02/26] drm/i915: don't stop+start FBC at every flip Paulo Zanoni
@ 2015-10-27 16:50 ` Paulo Zanoni
  2015-10-27 16:50 ` [PATCH 04/26] drm/i915: only nuke FBC when a drawing operation triggers a flush Paulo Zanoni
                   ` (22 subsequent siblings)
  25 siblings, 0 replies; 44+ messages in thread
From: Paulo Zanoni @ 2015-10-27 16:50 UTC (permalink / raw)
  To: intel-gfx

Although the term "nuke" is part of the FBC spec, it's not very
intuitive, so let's rename it to make it easier for people that are
not familiar with the spec.

Requested-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_fbc.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
index 62f158b..ac87136 100644
--- a/drivers/gpu/drm/i915/intel_fbc.c
+++ b/drivers/gpu/drm/i915/intel_fbc.c
@@ -214,7 +214,8 @@ static bool g4x_fbc_enabled(struct drm_i915_private *dev_priv)
 	return I915_READ(DPFC_CONTROL) & DPFC_CTL_EN;
 }
 
-static void intel_fbc_nuke(struct drm_i915_private *dev_priv)
+/* This funcion forces a CFB recompression through the nuke operation. */
+static void intel_fbc_recompress(struct drm_i915_private *dev_priv)
 {
 	I915_WRITE(MSG_FBC_REND_STATE, FBC_REND_NUKE);
 	POSTING_READ(MSG_FBC_REND_STATE);
@@ -263,7 +264,7 @@ static void ilk_fbc_enable(struct intel_crtc *crtc)
 		I915_WRITE(DPFC_CPU_FENCE_OFFSET, y_offset);
 	}
 
-	intel_fbc_nuke(dev_priv);
+	intel_fbc_recompress(dev_priv);
 
 	DRM_DEBUG_KMS("enabled fbc on plane %c\n", plane_name(crtc->plane));
 }
@@ -367,7 +368,7 @@ static void gen7_fbc_enable(struct intel_crtc *crtc)
 		   SNB_CPU_FENCE_ENABLE | obj->fence_reg);
 	I915_WRITE(DPFC_CPU_FENCE_OFFSET, get_crtc_fence_y_offset(crtc));
 
-	intel_fbc_nuke(dev_priv);
+	intel_fbc_recompress(dev_priv);
 
 	DRM_DEBUG_KMS("enabled fbc on plane %c\n", plane_name(crtc->plane));
 }
-- 
2.6.1

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

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 04/26] drm/i915: only nuke FBC when a drawing operation triggers a flush
  2015-10-27 16:50 [PATCH 00/26] Yet another FBC series, v2 Paulo Zanoni
                   ` (2 preceding siblings ...)
  2015-10-27 16:50 ` [PATCH 03/26] drm/i915: rename intel_fbc_nuke to intel_fbc_recompress Paulo Zanoni
@ 2015-10-27 16:50 ` Paulo Zanoni
  2015-10-27 16:50 ` [PATCH 05/26] drm/i915: extract fbc_on_pipe_a_only() Paulo Zanoni
                   ` (21 subsequent siblings)
  25 siblings, 0 replies; 44+ messages in thread
From: Paulo Zanoni @ 2015-10-27 16:50 UTC (permalink / raw)
  To: intel-gfx

There's no need to stop and restart FBC: a nuke should be fine. The
specific check for ORIGIN_FLIP is not needed anymore since we have an
early return for the ORIGIN_FLIP && dev_priv->fbc.enabled case.

v2: Make it simpler (Chris).

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_fbc.c | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
index ac87136..7d8e996 100644
--- a/drivers/gpu/drm/i915/intel_fbc.c
+++ b/drivers/gpu/drm/i915/intel_fbc.c
@@ -1091,12 +1091,10 @@ void intel_fbc_flush(struct drm_i915_private *dev_priv,
 	dev_priv->fbc.busy_bits &= ~frontbuffer_bits;
 
 	if (!dev_priv->fbc.busy_bits) {
-		if (origin == ORIGIN_FLIP) {
-			__intel_fbc_update(dev_priv);
-		} else {
-			__intel_fbc_disable(dev_priv);
+		if (dev_priv->fbc.enabled)
+			intel_fbc_recompress(dev_priv);
+		else
 			__intel_fbc_update(dev_priv);
-		}
 	}
 
 	mutex_unlock(&dev_priv->fbc.lock);
-- 
2.6.1

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

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 05/26] drm/i915: extract fbc_on_pipe_a_only()
  2015-10-27 16:50 [PATCH 00/26] Yet another FBC series, v2 Paulo Zanoni
                   ` (3 preceding siblings ...)
  2015-10-27 16:50 ` [PATCH 04/26] drm/i915: only nuke FBC when a drawing operation triggers a flush Paulo Zanoni
@ 2015-10-27 16:50 ` Paulo Zanoni
  2015-10-29 12:05   ` Maarten Lankhorst
  2015-10-27 16:50 ` [PATCH 06/26] drm/i915: remove unnecessary check for crtc->primary->fb Paulo Zanoni
                   ` (20 subsequent siblings)
  25 siblings, 1 reply; 44+ messages in thread
From: Paulo Zanoni @ 2015-10-27 16:50 UTC (permalink / raw)
  To: intel-gfx

Make the code easier to read.

Suggested-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_fbc.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
index 7d8e996..4d6ebc7 100644
--- a/drivers/gpu/drm/i915/intel_fbc.c
+++ b/drivers/gpu/drm/i915/intel_fbc.c
@@ -46,6 +46,11 @@ static inline bool fbc_supported(struct drm_i915_private *dev_priv)
 	return dev_priv->fbc.enable_fbc != NULL;
 }
 
+static inline bool fbc_on_pipe_a_only(struct drm_i915_private *dev_priv)
+{
+	return IS_HASWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 8;
+}
+
 /*
  * In some platforms where the CRTC's x:0/y:0 coordinates doesn't match the
  * frontbuffer's x:0/y:0 coordinates we lie to the hardware about the plane's
@@ -543,10 +548,6 @@ static struct drm_crtc *intel_fbc_find_crtc(struct drm_i915_private *dev_priv)
 {
 	struct drm_crtc *crtc = NULL, *tmp_crtc;
 	enum pipe pipe;
-	bool pipe_a_only = false;
-
-	if (IS_HASWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 8)
-		pipe_a_only = true;
 
 	for_each_pipe(dev_priv, pipe) {
 		tmp_crtc = dev_priv->pipe_to_crtc_mapping[pipe];
@@ -555,7 +556,7 @@ static struct drm_crtc *intel_fbc_find_crtc(struct drm_i915_private *dev_priv)
 		    to_intel_plane_state(tmp_crtc->primary->state)->visible)
 			crtc = tmp_crtc;
 
-		if (pipe_a_only)
+		if (fbc_on_pipe_a_only(dev_priv))
 			break;
 	}
 
@@ -1146,7 +1147,7 @@ void intel_fbc_init(struct drm_i915_private *dev_priv)
 		dev_priv->fbc.possible_framebuffer_bits |=
 				INTEL_FRONTBUFFER_PRIMARY(pipe);
 
-		if (IS_HASWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 8)
+		if (fbc_on_pipe_a_only(dev_priv))
 			break;
 	}
 
-- 
2.6.1

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

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 06/26] drm/i915: remove unnecessary check for crtc->primary->fb
  2015-10-27 16:50 [PATCH 00/26] Yet another FBC series, v2 Paulo Zanoni
                   ` (4 preceding siblings ...)
  2015-10-27 16:50 ` [PATCH 05/26] drm/i915: extract fbc_on_pipe_a_only() Paulo Zanoni
@ 2015-10-27 16:50 ` Paulo Zanoni
  2015-10-27 16:50 ` [PATCH 07/26] drm/i915: extract crtc_is_valid() on the FBC code Paulo Zanoni
                   ` (19 subsequent siblings)
  25 siblings, 0 replies; 44+ messages in thread
From: Paulo Zanoni @ 2015-10-27 16:50 UTC (permalink / raw)
  To: intel-gfx

We already check if the CRTC is visible, and it shouldn't be possible
to have a visible CRTC without an FB.

This was noticed by both Chris and Ville on different ocasions.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_fbc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
index 4d6ebc7..18479bc 100644
--- a/drivers/gpu/drm/i915/intel_fbc.c
+++ b/drivers/gpu/drm/i915/intel_fbc.c
@@ -560,7 +560,7 @@ static struct drm_crtc *intel_fbc_find_crtc(struct drm_i915_private *dev_priv)
 			break;
 	}
 
-	if (!crtc || crtc->primary->fb == NULL)
+	if (!crtc)
 		return NULL;
 
 	return crtc;
-- 
2.6.1

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

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 07/26] drm/i915: extract crtc_is_valid() on the FBC code
  2015-10-27 16:50 [PATCH 00/26] Yet another FBC series, v2 Paulo Zanoni
                   ` (5 preceding siblings ...)
  2015-10-27 16:50 ` [PATCH 06/26] drm/i915: remove unnecessary check for crtc->primary->fb Paulo Zanoni
@ 2015-10-27 16:50 ` Paulo Zanoni
  2015-10-27 16:50 ` [PATCH 08/26] drm/i915: set dev_priv->fbc.crtc before scheduling the enable work Paulo Zanoni
                   ` (18 subsequent siblings)
  25 siblings, 0 replies; 44+ messages in thread
From: Paulo Zanoni @ 2015-10-27 16:50 UTC (permalink / raw)
  To: intel-gfx

We're going to kill intel_fbc_find_crtc(), that's why a big part of
the logic moved from intel_fbc_find_crtc() to crtc_is_valid().

v2:
  - Rebase due to pipe_a_only change.
  - Split the multiline conditional (Chris).

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_fbc.c | 22 +++++++++++++++++-----
 1 file changed, 17 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
index 18479bc..c513e4d 100644
--- a/drivers/gpu/drm/i915/intel_fbc.c
+++ b/drivers/gpu/drm/i915/intel_fbc.c
@@ -544,6 +544,22 @@ static void set_no_fbc_reason(struct drm_i915_private *dev_priv,
 	DRM_DEBUG_KMS("Disabling FBC: %s\n", reason);
 }
 
+static bool crtc_is_valid(struct intel_crtc *crtc)
+{
+	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
+
+	if (fbc_on_pipe_a_only(dev_priv) && crtc->pipe != PIPE_A)
+		return false;
+
+	if (!intel_crtc_active(&crtc->base))
+		return false;
+
+	if (!to_intel_plane_state(crtc->base.primary->state)->visible)
+		return false;
+
+	return true;
+}
+
 static struct drm_crtc *intel_fbc_find_crtc(struct drm_i915_private *dev_priv)
 {
 	struct drm_crtc *crtc = NULL, *tmp_crtc;
@@ -552,12 +568,8 @@ static struct drm_crtc *intel_fbc_find_crtc(struct drm_i915_private *dev_priv)
 	for_each_pipe(dev_priv, pipe) {
 		tmp_crtc = dev_priv->pipe_to_crtc_mapping[pipe];
 
-		if (intel_crtc_active(tmp_crtc) &&
-		    to_intel_plane_state(tmp_crtc->primary->state)->visible)
+		if (crtc_is_valid(to_intel_crtc(tmp_crtc)))
 			crtc = tmp_crtc;
-
-		if (fbc_on_pipe_a_only(dev_priv))
-			break;
 	}
 
 	if (!crtc)
-- 
2.6.1

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

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 08/26] drm/i915: set dev_priv->fbc.crtc before scheduling the enable work
  2015-10-27 16:50 [PATCH 00/26] Yet another FBC series, v2 Paulo Zanoni
                   ` (6 preceding siblings ...)
  2015-10-27 16:50 ` [PATCH 07/26] drm/i915: extract crtc_is_valid() on the FBC code Paulo Zanoni
@ 2015-10-27 16:50 ` Paulo Zanoni
  2015-10-27 16:50 ` [PATCH 09/26] drm/i915: use struct intel_crtc *crtc at __intel_fbc_update() Paulo Zanoni
                   ` (17 subsequent siblings)
  25 siblings, 0 replies; 44+ messages in thread
From: Paulo Zanoni @ 2015-10-27 16:50 UTC (permalink / raw)
  To: intel-gfx

This thing where we need to get the crtc either from the work
structure or the fbc structure itself is confusing and unnecessary.
Set fbc.crtc right when scheduling the enable work so we can always
use it.

The problem is not what gets passed and how to retrieve it. The
problem is that when we're in the other parts of the code we always
have to keep in mind that if FBC is already enabled we have to get the
CRTC from place A, if FBC is scheduled we have to get the CRTC from
place B, and if it's disabled there's no CRTC. Having a single place
to retrieve the CRTC from allows us to treat the "is enabled" and "is
scheduled" cases as the same case, reducing the mistake surface. I
guess I should add this to the commit message.

Besides the immediate advantages, this is also going to make one of
the next commits much simpler. And even later, when we introduce
enable/disable + activate/deactivate, this will be even simpler as
we'll set the CRTC at enable time. So all the
activate/deactivate/update code can just look at the single CRTC
variable regardless of the current state.

v2: Improve commit message (Chris).

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h  |  1 -
 drivers/gpu/drm/i915/intel_fbc.c | 25 ++++++++++---------------
 2 files changed, 10 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 77da500..6d7b42d 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -919,7 +919,6 @@ struct i915_fbc {
 
 	struct intel_fbc_work {
 		struct delayed_work work;
-		struct intel_crtc *crtc;
 		struct drm_framebuffer *fb;
 	} *fbc_work;
 
diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
index c513e4d..96d502e 100644
--- a/drivers/gpu/drm/i915/intel_fbc.c
+++ b/drivers/gpu/drm/i915/intel_fbc.c
@@ -391,14 +391,13 @@ bool intel_fbc_enabled(struct drm_i915_private *dev_priv)
 	return dev_priv->fbc.enabled;
 }
 
-static void intel_fbc_enable(struct intel_crtc *crtc,
-			     const struct drm_framebuffer *fb)
+static void intel_fbc_enable(const struct drm_framebuffer *fb)
 {
-	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
+	struct drm_i915_private *dev_priv = fb->dev->dev_private;
+	struct intel_crtc *crtc = dev_priv->fbc.crtc;
 
 	dev_priv->fbc.enable_fbc(crtc);
 
-	dev_priv->fbc.crtc = crtc;
 	dev_priv->fbc.fb_id = fb->base.id;
 	dev_priv->fbc.y = crtc->base.y;
 }
@@ -408,8 +407,8 @@ static void intel_fbc_work_fn(struct work_struct *__work)
 	struct intel_fbc_work *work =
 		container_of(to_delayed_work(__work),
 			     struct intel_fbc_work, work);
-	struct drm_i915_private *dev_priv = work->crtc->base.dev->dev_private;
-	struct drm_framebuffer *crtc_fb = work->crtc->base.primary->fb;
+	struct drm_i915_private *dev_priv = work->fb->dev->dev_private;
+	struct drm_framebuffer *crtc_fb = dev_priv->fbc.crtc->base.primary->fb;
 
 	mutex_lock(&dev_priv->fbc.lock);
 	if (work == dev_priv->fbc.fbc_work) {
@@ -417,7 +416,7 @@ static void intel_fbc_work_fn(struct work_struct *__work)
 		 * the prior work.
 		 */
 		if (crtc_fb == work->fb)
-			intel_fbc_enable(work->crtc, work->fb);
+			intel_fbc_enable(work->fb);
 
 		dev_priv->fbc.fbc_work = NULL;
 	}
@@ -459,15 +458,15 @@ static void intel_fbc_schedule_enable(struct intel_crtc *crtc)
 	WARN_ON(!mutex_is_locked(&dev_priv->fbc.lock));
 
 	intel_fbc_cancel_work(dev_priv);
+	dev_priv->fbc.crtc = crtc;
 
 	work = kzalloc(sizeof(*work), GFP_KERNEL);
 	if (work == NULL) {
 		DRM_ERROR("Failed to allocate FBC work structure\n");
-		intel_fbc_enable(crtc, crtc->base.primary->fb);
+		intel_fbc_enable(crtc->base.primary->fb);
 		return;
 	}
 
-	work->crtc = crtc;
 	work->fb = crtc->base.primary->fb;
 	INIT_DELAYED_WORK(&work->work, intel_fbc_work_fn);
 
@@ -1067,11 +1066,8 @@ void intel_fbc_invalidate(struct drm_i915_private *dev_priv,
 
 	mutex_lock(&dev_priv->fbc.lock);
 
-	if (dev_priv->fbc.enabled)
+	if (dev_priv->fbc.enabled || dev_priv->fbc.fbc_work)
 		fbc_bits = INTEL_FRONTBUFFER_PRIMARY(dev_priv->fbc.crtc->pipe);
-	else if (dev_priv->fbc.fbc_work)
-		fbc_bits = INTEL_FRONTBUFFER_PRIMARY(
-					dev_priv->fbc.fbc_work->crtc->pipe);
 	else
 		fbc_bits = dev_priv->fbc.possible_framebuffer_bits;
 
@@ -1128,8 +1124,7 @@ void intel_fbc_flip_prepare(struct drm_i915_private *dev_priv,
 		if (fbc_bits & frontbuffer_bits)
 			dev_priv->fbc.flip_prepare(dev_priv);
 	} else if (dev_priv->fbc.fbc_work) {
-		fbc_bits = INTEL_FRONTBUFFER_PRIMARY(
-				dev_priv->fbc.fbc_work->crtc->pipe);
+		fbc_bits = INTEL_FRONTBUFFER_PRIMARY(dev_priv->fbc.crtc->pipe);
 		if (fbc_bits & frontbuffer_bits)
 			__intel_fbc_disable(dev_priv);
 	}
-- 
2.6.1

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

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 09/26] drm/i915: use struct intel_crtc *crtc at __intel_fbc_update()
  2015-10-27 16:50 [PATCH 00/26] Yet another FBC series, v2 Paulo Zanoni
                   ` (7 preceding siblings ...)
  2015-10-27 16:50 ` [PATCH 08/26] drm/i915: set dev_priv->fbc.crtc before scheduling the enable work Paulo Zanoni
@ 2015-10-27 16:50 ` Paulo Zanoni
  2015-10-27 16:50 ` [PATCH 10/26] drm/i915: fix the __intel_fbc_update() comments Paulo Zanoni
                   ` (16 subsequent siblings)
  25 siblings, 0 replies; 44+ messages in thread
From: Paulo Zanoni @ 2015-10-27 16:50 UTC (permalink / raw)
  To: intel-gfx

This change was part of the commit that makes intel_fbc_update()
receive an intel_crtc as argument instead of dev_priv, but since it
was polluting the diff with too many chunks I decided to move it to
its own commit.

It seems that our developers are favoring having this instead of the
old combination drm_crtc *crtc + intel_crtc *intel_crtc, and on the
mentioned commit we'll get rid of the drm_crtc variable, so let's do
an intermediate commit with the rename, so on the next commit we'll
have just struct intel_crtc *crtc.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_fbc.c | 30 +++++++++++++++---------------
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
index 96d502e..06bdc27 100644
--- a/drivers/gpu/drm/i915/intel_fbc.c
+++ b/drivers/gpu/drm/i915/intel_fbc.c
@@ -878,8 +878,8 @@ static bool intel_fbc_hw_tracking_covers_screen(struct intel_crtc *crtc)
  */
 static void __intel_fbc_update(struct drm_i915_private *dev_priv)
 {
-	struct drm_crtc *crtc = NULL;
-	struct intel_crtc *intel_crtc;
+	struct drm_crtc *drm_crtc = NULL;
+	struct intel_crtc *crtc;
 	struct drm_framebuffer *fb;
 	struct drm_i915_gem_object *obj;
 	const struct drm_display_mode *adjusted_mode;
@@ -909,8 +909,8 @@ static void __intel_fbc_update(struct drm_i915_private *dev_priv)
 	 *   - new fb is too large to fit in compressed buffer
 	 *   - going to an unsupported config (interlace, pixel multiply, etc.)
 	 */
-	crtc = intel_fbc_find_crtc(dev_priv);
-	if (!crtc) {
+	drm_crtc = intel_fbc_find_crtc(dev_priv);
+	if (!drm_crtc) {
 		set_no_fbc_reason(dev_priv, "no output");
 		goto out_disable;
 	}
@@ -920,10 +920,10 @@ static void __intel_fbc_update(struct drm_i915_private *dev_priv)
 		goto out_disable;
 	}
 
-	intel_crtc = to_intel_crtc(crtc);
-	fb = crtc->primary->fb;
+	crtc = to_intel_crtc(drm_crtc);
+	fb = crtc->base.primary->fb;
 	obj = intel_fb_obj(fb);
-	adjusted_mode = &intel_crtc->config->base.adjusted_mode;
+	adjusted_mode = &crtc->config->base.adjusted_mode;
 
 	if ((adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) ||
 	    (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)) {
@@ -931,13 +931,13 @@ static void __intel_fbc_update(struct drm_i915_private *dev_priv)
 		goto out_disable;
 	}
 
-	if (!intel_fbc_hw_tracking_covers_screen(intel_crtc)) {
+	if (!intel_fbc_hw_tracking_covers_screen(crtc)) {
 		set_no_fbc_reason(dev_priv, "mode too large for compression");
 		goto out_disable;
 	}
 
 	if ((INTEL_INFO(dev_priv)->gen < 4 || HAS_DDI(dev_priv)) &&
-	    intel_crtc->plane != PLANE_A) {
+	    crtc->plane != PLANE_A) {
 		set_no_fbc_reason(dev_priv, "FBC unsupported on plane");
 		goto out_disable;
 	}
@@ -951,7 +951,7 @@ static void __intel_fbc_update(struct drm_i915_private *dev_priv)
 		goto out_disable;
 	}
 	if (INTEL_INFO(dev_priv)->gen <= 4 && !IS_G4X(dev_priv) &&
-	    crtc->primary->state->rotation != BIT(DRM_ROTATE_0)) {
+	    crtc->base.primary->state->rotation != BIT(DRM_ROTATE_0)) {
 		set_no_fbc_reason(dev_priv, "rotation unsupported");
 		goto out_disable;
 	}
@@ -974,13 +974,13 @@ static void __intel_fbc_update(struct drm_i915_private *dev_priv)
 
 	/* WaFbcExceedCdClockThreshold:hsw,bdw */
 	if ((IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) &&
-	    ilk_pipe_pixel_rate(intel_crtc->config) >=
+	    ilk_pipe_pixel_rate(crtc->config) >=
 	    dev_priv->cdclk_freq * 95 / 100) {
 		set_no_fbc_reason(dev_priv, "pixel rate is too big");
 		goto out_disable;
 	}
 
-	if (intel_fbc_setup_cfb(intel_crtc)) {
+	if (intel_fbc_setup_cfb(crtc)) {
 		set_no_fbc_reason(dev_priv, "not enough stolen memory");
 		goto out_disable;
 	}
@@ -990,9 +990,9 @@ static void __intel_fbc_update(struct drm_i915_private *dev_priv)
 	 * cannot be unpinned (and have its GTT offset and fence revoked)
 	 * without first being decoupled from the scanout and FBC disabled.
 	 */
-	if (dev_priv->fbc.crtc == intel_crtc &&
+	if (dev_priv->fbc.crtc == crtc &&
 	    dev_priv->fbc.fb_id == fb->base.id &&
-	    dev_priv->fbc.y == crtc->y)
+	    dev_priv->fbc.y == crtc->base.y)
 		return;
 
 	if (intel_fbc_enabled(dev_priv)) {
@@ -1023,7 +1023,7 @@ static void __intel_fbc_update(struct drm_i915_private *dev_priv)
 		__intel_fbc_disable(dev_priv);
 	}
 
-	intel_fbc_schedule_enable(intel_crtc);
+	intel_fbc_schedule_enable(crtc);
 	dev_priv->fbc.no_fbc_reason = "FBC enabled (not necessarily active)\n";
 	return;
 
-- 
2.6.1

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

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 10/26] drm/i915: fix the __intel_fbc_update() comments
  2015-10-27 16:50 [PATCH 00/26] Yet another FBC series, v2 Paulo Zanoni
                   ` (8 preceding siblings ...)
  2015-10-27 16:50 ` [PATCH 09/26] drm/i915: use struct intel_crtc *crtc at __intel_fbc_update() Paulo Zanoni
@ 2015-10-27 16:50 ` Paulo Zanoni
  2015-10-27 16:50 ` [PATCH 11/26] drm/i915: pass the crtc as an argument to intel_fbc_update() Paulo Zanoni
                   ` (15 subsequent siblings)
  25 siblings, 0 replies; 44+ messages in thread
From: Paulo Zanoni @ 2015-10-27 16:50 UTC (permalink / raw)
  To: intel-gfx

Don't try to list in comments the cases where we should enable or
disable FBC: it varies a lot with the hardware generations and the
code should be the documentation. Also notice that there's already a
huge gap between the comments and what's in the code.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_fbc.c | 26 ++------------------------
 1 file changed, 2 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
index 06bdc27..1b39037 100644
--- a/drivers/gpu/drm/i915/intel_fbc.c
+++ b/drivers/gpu/drm/i915/intel_fbc.c
@@ -861,20 +861,8 @@ static bool intel_fbc_hw_tracking_covers_screen(struct intel_crtc *crtc)
  * __intel_fbc_update - enable/disable FBC as needed, unlocked
  * @dev_priv: i915 device instance
  *
- * Set up the framebuffer compression hardware at mode set time.  We
- * enable it if possible:
- *   - plane A only (on pre-965)
- *   - no pixel mulitply/line duplication
- *   - no alpha buffer discard
- *   - no dual wide
- *   - framebuffer <= max_hdisplay in width, max_vdisplay in height
- *
- * We can't assume that any compression will take place (worst case),
- * so the compressed buffer has to be the same size as the uncompressed
- * one.  It also must reside (along with the line length buffer) in
- * stolen memory.
- *
- * We need to enable/disable FBC on a global basis.
+ * This function completely reevaluates the status of FBC, then enables,
+ * disables or maintains it on the same state.
  */
 static void __intel_fbc_update(struct drm_i915_private *dev_priv)
 {
@@ -886,7 +874,6 @@ static void __intel_fbc_update(struct drm_i915_private *dev_priv)
 
 	WARN_ON(!mutex_is_locked(&dev_priv->fbc.lock));
 
-	/* disable framebuffer compression in vGPU */
 	if (intel_vgpu_active(dev_priv->dev))
 		i915.enable_fbc = 0;
 
@@ -900,15 +887,6 @@ static void __intel_fbc_update(struct drm_i915_private *dev_priv)
 		goto out_disable;
 	}
 
-	/*
-	 * If FBC is already on, we just have to verify that we can
-	 * keep it that way...
-	 * Need to disable if:
-	 *   - more than one pipe is active
-	 *   - changing FBC params (stride, fence, mode)
-	 *   - new fb is too large to fit in compressed buffer
-	 *   - going to an unsupported config (interlace, pixel multiply, etc.)
-	 */
 	drm_crtc = intel_fbc_find_crtc(dev_priv);
 	if (!drm_crtc) {
 		set_no_fbc_reason(dev_priv, "no output");
-- 
2.6.1

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

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 11/26] drm/i915: pass the crtc as an argument to intel_fbc_update()
  2015-10-27 16:50 [PATCH 00/26] Yet another FBC series, v2 Paulo Zanoni
                   ` (9 preceding siblings ...)
  2015-10-27 16:50 ` [PATCH 10/26] drm/i915: fix the __intel_fbc_update() comments Paulo Zanoni
@ 2015-10-27 16:50 ` Paulo Zanoni
  2015-10-27 16:50 ` [PATCH 12/26] drm/i915: don't disable_fbc() if FBC is already disabled Paulo Zanoni
                   ` (14 subsequent siblings)
  25 siblings, 0 replies; 44+ messages in thread
From: Paulo Zanoni @ 2015-10-27 16:50 UTC (permalink / raw)
  To: intel-gfx

There's no need to reevaluate the status of every single crtc when a
single crtc changes its state.

With this, we're cutting the case where due to a change in pipe B,
intel_fbc_update() is called, then intel_fbc_find_crtc() concludes FBC
should be enabled on pipe A, then it completely rechecks the state of
pipe A only to conclude FBC should remain enabled on pipe A. If any
change on pipe A triggers a need to recompute whether FBC is valid on
pipe A, then at some point someone is going to call
intel_fbc_update(PIPE_A).

The addition of intel_fbc_deactivate() is necessary so we keep track
of the previously selected CRTC when we do invalidate/flush. We're
also going to continue the enable/disable/activate/deactivate concept
in the next patches.

v2: Rebase.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_display.c |  3 +-
 drivers/gpu/drm/i915/intel_drv.h     |  2 +-
 drivers/gpu/drm/i915/intel_fbc.c     | 68 +++++++++++++++---------------------
 3 files changed, 31 insertions(+), 42 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index d9378c3..820ad1e 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -4778,7 +4778,6 @@ static void intel_post_plane_update(struct intel_crtc *crtc)
 {
 	struct intel_crtc_atomic_commit *atomic = &crtc->atomic;
 	struct drm_device *dev = crtc->base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	if (atomic->wait_vblank)
 		intel_wait_for_vblank(dev, crtc->pipe);
@@ -4792,7 +4791,7 @@ static void intel_post_plane_update(struct intel_crtc *crtc)
 		intel_update_watermarks(&crtc->base);
 
 	if (atomic->update_fbc)
-		intel_fbc_update(dev_priv);
+		intel_fbc_update(crtc);
 
 	if (atomic->post_enable_primary)
 		intel_post_enable_primary(&crtc->base);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 9065a8f..b463bae 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1296,7 +1296,7 @@ static inline void intel_fbdev_restore_mode(struct drm_device *dev)
 
 /* intel_fbc.c */
 bool intel_fbc_enabled(struct drm_i915_private *dev_priv);
-void intel_fbc_update(struct drm_i915_private *dev_priv);
+void intel_fbc_update(struct intel_crtc *crtc);
 void intel_fbc_init(struct drm_i915_private *dev_priv);
 void intel_fbc_disable(struct drm_i915_private *dev_priv);
 void intel_fbc_disable_crtc(struct intel_crtc *crtc);
diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
index 1b39037..6b952ee 100644
--- a/drivers/gpu/drm/i915/intel_fbc.c
+++ b/drivers/gpu/drm/i915/intel_fbc.c
@@ -488,13 +488,18 @@ static void intel_fbc_schedule_enable(struct intel_crtc *crtc)
 	schedule_delayed_work(&work->work, msecs_to_jiffies(50));
 }
 
-static void __intel_fbc_disable(struct drm_i915_private *dev_priv)
+static void intel_fbc_deactivate(struct drm_i915_private *dev_priv)
 {
 	WARN_ON(!mutex_is_locked(&dev_priv->fbc.lock));
 
 	intel_fbc_cancel_work(dev_priv);
 
 	dev_priv->fbc.disable_fbc(dev_priv);
+}
+
+static void __intel_fbc_disable(struct drm_i915_private *dev_priv)
+{
+	intel_fbc_deactivate(dev_priv);
 	dev_priv->fbc.crtc = NULL;
 }
 
@@ -559,24 +564,6 @@ static bool crtc_is_valid(struct intel_crtc *crtc)
 	return true;
 }
 
-static struct drm_crtc *intel_fbc_find_crtc(struct drm_i915_private *dev_priv)
-{
-	struct drm_crtc *crtc = NULL, *tmp_crtc;
-	enum pipe pipe;
-
-	for_each_pipe(dev_priv, pipe) {
-		tmp_crtc = dev_priv->pipe_to_crtc_mapping[pipe];
-
-		if (crtc_is_valid(to_intel_crtc(tmp_crtc)))
-			crtc = tmp_crtc;
-	}
-
-	if (!crtc)
-		return NULL;
-
-	return crtc;
-}
-
 static bool multiple_pipes_ok(struct drm_i915_private *dev_priv)
 {
 	enum pipe pipe;
@@ -859,21 +846,28 @@ static bool intel_fbc_hw_tracking_covers_screen(struct intel_crtc *crtc)
 
 /**
  * __intel_fbc_update - enable/disable FBC as needed, unlocked
- * @dev_priv: i915 device instance
+ * @crtc: the CRTC that triggered the update
  *
  * This function completely reevaluates the status of FBC, then enables,
  * disables or maintains it on the same state.
  */
-static void __intel_fbc_update(struct drm_i915_private *dev_priv)
+static void __intel_fbc_update(struct intel_crtc *crtc)
 {
-	struct drm_crtc *drm_crtc = NULL;
-	struct intel_crtc *crtc;
+	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
 	struct drm_framebuffer *fb;
 	struct drm_i915_gem_object *obj;
 	const struct drm_display_mode *adjusted_mode;
 
 	WARN_ON(!mutex_is_locked(&dev_priv->fbc.lock));
 
+	if (!multiple_pipes_ok(dev_priv)) {
+		set_no_fbc_reason(dev_priv, "more than one pipe active");
+		goto out_disable;
+	}
+
+	if (dev_priv->fbc.crtc != NULL && dev_priv->fbc.crtc != crtc)
+		return;
+
 	if (intel_vgpu_active(dev_priv->dev))
 		i915.enable_fbc = 0;
 
@@ -887,18 +881,11 @@ static void __intel_fbc_update(struct drm_i915_private *dev_priv)
 		goto out_disable;
 	}
 
-	drm_crtc = intel_fbc_find_crtc(dev_priv);
-	if (!drm_crtc) {
+	if (!crtc_is_valid(crtc)) {
 		set_no_fbc_reason(dev_priv, "no output");
 		goto out_disable;
 	}
 
-	if (!multiple_pipes_ok(dev_priv)) {
-		set_no_fbc_reason(dev_priv, "more than one pipe active");
-		goto out_disable;
-	}
-
-	crtc = to_intel_crtc(drm_crtc);
 	fb = crtc->base.primary->fb;
 	obj = intel_fb_obj(fb);
 	adjusted_mode = &crtc->config->base.adjusted_mode;
@@ -970,7 +957,8 @@ static void __intel_fbc_update(struct drm_i915_private *dev_priv)
 	 */
 	if (dev_priv->fbc.crtc == crtc &&
 	    dev_priv->fbc.fb_id == fb->base.id &&
-	    dev_priv->fbc.y == crtc->base.y)
+	    dev_priv->fbc.y == crtc->base.y &&
+	    dev_priv->fbc.enabled)
 		return;
 
 	if (intel_fbc_enabled(dev_priv)) {
@@ -1016,17 +1004,19 @@ out_disable:
 
 /*
  * intel_fbc_update - enable/disable FBC as needed
- * @dev_priv: i915 device instance
+ * @crtc: the CRTC that triggered the update
  *
  * This function reevaluates the overall state and enables or disables FBC.
  */
-void intel_fbc_update(struct drm_i915_private *dev_priv)
+void intel_fbc_update(struct intel_crtc *crtc)
 {
+	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
+
 	if (!fbc_supported(dev_priv))
 		return;
 
 	mutex_lock(&dev_priv->fbc.lock);
-	__intel_fbc_update(dev_priv);
+	__intel_fbc_update(crtc);
 	mutex_unlock(&dev_priv->fbc.lock);
 }
 
@@ -1052,7 +1042,7 @@ void intel_fbc_invalidate(struct drm_i915_private *dev_priv,
 	dev_priv->fbc.busy_bits |= (fbc_bits & frontbuffer_bits);
 
 	if (dev_priv->fbc.busy_bits)
-		__intel_fbc_disable(dev_priv);
+		intel_fbc_deactivate(dev_priv);
 
 	mutex_unlock(&dev_priv->fbc.lock);
 }
@@ -1077,11 +1067,11 @@ void intel_fbc_flush(struct drm_i915_private *dev_priv,
 
 	dev_priv->fbc.busy_bits &= ~frontbuffer_bits;
 
-	if (!dev_priv->fbc.busy_bits) {
+	if (!dev_priv->fbc.busy_bits && dev_priv->fbc.crtc) {
 		if (dev_priv->fbc.enabled)
 			intel_fbc_recompress(dev_priv);
 		else
-			__intel_fbc_update(dev_priv);
+			__intel_fbc_update(dev_priv->fbc.crtc);
 	}
 
 	mutex_unlock(&dev_priv->fbc.lock);
@@ -1104,7 +1094,7 @@ void intel_fbc_flip_prepare(struct drm_i915_private *dev_priv,
 	} else if (dev_priv->fbc.fbc_work) {
 		fbc_bits = INTEL_FRONTBUFFER_PRIMARY(dev_priv->fbc.crtc->pipe);
 		if (fbc_bits & frontbuffer_bits)
-			__intel_fbc_disable(dev_priv);
+			intel_fbc_deactivate(dev_priv);
 	}
 
 	mutex_unlock(&dev_priv->fbc.lock);
-- 
2.6.1

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

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 12/26] drm/i915: don't disable_fbc() if FBC is already disabled
  2015-10-27 16:50 [PATCH 00/26] Yet another FBC series, v2 Paulo Zanoni
                   ` (10 preceding siblings ...)
  2015-10-27 16:50 ` [PATCH 11/26] drm/i915: pass the crtc as an argument to intel_fbc_update() Paulo Zanoni
@ 2015-10-27 16:50 ` Paulo Zanoni
  2015-10-27 16:50 ` [PATCH 13/26] drm/i915: introduce is_active/activate/deactivate to the FBC terminology Paulo Zanoni
                   ` (13 subsequent siblings)
  25 siblings, 0 replies; 44+ messages in thread
From: Paulo Zanoni @ 2015-10-27 16:50 UTC (permalink / raw)
  To: intel-gfx

If FBC is disabled we will still call intel_fbc_invalidate(), and as a
result we may call intel_fbc_deactivate(), which will try to touch
registers.

I'm pretty sure I saw this happen on a runtime suspended device, and
I'm almost sure I was running igt/pm_rpm. It produced the "you touched
registers while the device is suspended" WARNs. But this was some time
ago and I can't remember exactly which conditions were necessary to
reproduce the problem.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_fbc.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
index 6b952ee..80d881f 100644
--- a/drivers/gpu/drm/i915/intel_fbc.c
+++ b/drivers/gpu/drm/i915/intel_fbc.c
@@ -494,7 +494,8 @@ static void intel_fbc_deactivate(struct drm_i915_private *dev_priv)
 
 	intel_fbc_cancel_work(dev_priv);
 
-	dev_priv->fbc.disable_fbc(dev_priv);
+	if (dev_priv->fbc.enabled)
+		dev_priv->fbc.disable_fbc(dev_priv);
 }
 
 static void __intel_fbc_disable(struct drm_i915_private *dev_priv)
-- 
2.6.1

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

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 13/26] drm/i915: introduce is_active/activate/deactivate to the FBC terminology
  2015-10-27 16:50 [PATCH 00/26] Yet another FBC series, v2 Paulo Zanoni
                   ` (11 preceding siblings ...)
  2015-10-27 16:50 ` [PATCH 12/26] drm/i915: don't disable_fbc() if FBC is already disabled Paulo Zanoni
@ 2015-10-27 16:50 ` Paulo Zanoni
  2015-10-27 16:50 ` [PATCH 14/26] drm/i915: refactor FBC deactivation at init Paulo Zanoni
                   ` (12 subsequent siblings)
  25 siblings, 0 replies; 44+ messages in thread
From: Paulo Zanoni @ 2015-10-27 16:50 UTC (permalink / raw)
  To: intel-gfx

The long term goal is to have enable/disable as the higher level
functions and activate/deactivate as the lower level functions, just
like we do for PSR and for the CRTC. This way, we'll run enable and
disable once per modeset, while update, activate and deactivate will
be run many times. With this, we can move the checks and code that
need to run only once per modeset to enable(), making the code simpler
and possibly a little faster.

This patch is just the first step on the conversion: it starts by
converting the current low level functions from enable/disable to
activate/deactivate. This patch by itself has no benefits other than
making review and rebase easier. Please see the next patches for more
details on the conversion.

v2:
  - Rebase.
  - Improve commit message (Chris).

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c  |   2 +-
 drivers/gpu/drm/i915/i915_drv.h      |  10 ++-
 drivers/gpu/drm/i915/intel_display.c |   4 +-
 drivers/gpu/drm/i915/intel_drv.h     |   2 +-
 drivers/gpu/drm/i915/intel_fbc.c     | 116 +++++++++++++++++------------------
 drivers/gpu/drm/i915/intel_pm.c      |   2 +-
 6 files changed, 67 insertions(+), 69 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index fbde0a4..1d6bb95 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1636,7 +1636,7 @@ static int i915_fbc_status(struct seq_file *m, void *unused)
 	intel_runtime_pm_get(dev_priv);
 	mutex_lock(&dev_priv->fbc.lock);
 
-	if (intel_fbc_enabled(dev_priv))
+	if (intel_fbc_is_active(dev_priv))
 		seq_puts(m, "FBC enabled\n");
 	else
 		seq_printf(m, "FBC disabled: %s\n",
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 6d7b42d..d4326e3 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -913,9 +913,7 @@ struct i915_fbc {
 
 	bool false_color;
 
-	/* Tracks whether the HW is actually enabled, not whether the feature is
-	 * possible. */
-	bool enabled;
+	bool active;
 
 	struct intel_fbc_work {
 		struct delayed_work work;
@@ -924,9 +922,9 @@ struct i915_fbc {
 
 	const char *no_fbc_reason;
 
-	bool (*fbc_enabled)(struct drm_i915_private *dev_priv);
-	void (*enable_fbc)(struct intel_crtc *crtc);
-	void (*disable_fbc)(struct drm_i915_private *dev_priv);
+	bool (*is_active)(struct drm_i915_private *dev_priv);
+	void (*activate)(struct intel_crtc *crtc);
+	void (*deactivate)(struct drm_i915_private *dev_priv);
 	void (*flip_prepare)(struct drm_i915_private *dev_priv);
 };
 
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 820ad1e..2392f47 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3173,8 +3173,8 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	if (dev_priv->fbc.disable_fbc)
-		dev_priv->fbc.disable_fbc(dev_priv);
+	if (dev_priv->fbc.deactivate)
+		dev_priv->fbc.deactivate(dev_priv);
 
 	dev_priv->display.update_primary_plane(crtc, fb, x, y);
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index b463bae..0debbe9 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1295,7 +1295,7 @@ static inline void intel_fbdev_restore_mode(struct drm_device *dev)
 #endif
 
 /* intel_fbc.c */
-bool intel_fbc_enabled(struct drm_i915_private *dev_priv);
+bool intel_fbc_is_active(struct drm_i915_private *dev_priv);
 void intel_fbc_update(struct intel_crtc *crtc);
 void intel_fbc_init(struct drm_i915_private *dev_priv);
 void intel_fbc_disable(struct drm_i915_private *dev_priv);
diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
index 80d881f..6f020fc 100644
--- a/drivers/gpu/drm/i915/intel_fbc.c
+++ b/drivers/gpu/drm/i915/intel_fbc.c
@@ -43,7 +43,7 @@
 
 static inline bool fbc_supported(struct drm_i915_private *dev_priv)
 {
-	return dev_priv->fbc.enable_fbc != NULL;
+	return dev_priv->fbc.activate != NULL;
 }
 
 static inline bool fbc_on_pipe_a_only(struct drm_i915_private *dev_priv)
@@ -64,11 +64,11 @@ static unsigned int get_crtc_fence_y_offset(struct intel_crtc *crtc)
 	return crtc->base.y - crtc->adjusted_y;
 }
 
-static void i8xx_fbc_disable(struct drm_i915_private *dev_priv)
+static void i8xx_fbc_deactivate(struct drm_i915_private *dev_priv)
 {
 	u32 fbc_ctl;
 
-	dev_priv->fbc.enabled = false;
+	dev_priv->fbc.active = false;
 
 	/* Disable compression */
 	fbc_ctl = I915_READ(FBC_CONTROL);
@@ -84,7 +84,7 @@ static void i8xx_fbc_disable(struct drm_i915_private *dev_priv)
 		return;
 	}
 
-	DRM_DEBUG_KMS("disabled FBC\n");
+	DRM_DEBUG_KMS("deactivated FBC\n");
 }
 
 static void i8xx_fbc_flip_prepare(struct drm_i915_private *dev_priv)
@@ -103,7 +103,7 @@ static void i8xx_fbc_flip_prepare(struct drm_i915_private *dev_priv)
 	I915_WRITE(FBC_CONTROL, val);
 }
 
-static void i8xx_fbc_enable(struct intel_crtc *crtc)
+static void i8xx_fbc_activate(struct intel_crtc *crtc)
 {
 	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
 	struct drm_framebuffer *fb = crtc->base.primary->fb;
@@ -112,7 +112,7 @@ static void i8xx_fbc_enable(struct intel_crtc *crtc)
 	int i;
 	u32 fbc_ctl;
 
-	dev_priv->fbc.enabled = true;
+	dev_priv->fbc.active = true;
 
 	/* Note: fbc.threshold == 1 for i8xx */
 	cfb_pitch = dev_priv->fbc.uncompressed_size / FBC_LL_SIZE;
@@ -149,23 +149,23 @@ static void i8xx_fbc_enable(struct intel_crtc *crtc)
 	fbc_ctl |= obj->fence_reg;
 	I915_WRITE(FBC_CONTROL, fbc_ctl);
 
-	DRM_DEBUG_KMS("enabled FBC, pitch %d, yoff %d, plane %c\n",
+	DRM_DEBUG_KMS("activated FBC, pitch %d, yoff %d, plane %c\n",
 		      cfb_pitch, crtc->base.y, plane_name(crtc->plane));
 }
 
-static bool i8xx_fbc_enabled(struct drm_i915_private *dev_priv)
+static bool i8xx_fbc_is_active(struct drm_i915_private *dev_priv)
 {
 	return I915_READ(FBC_CONTROL) & FBC_CTL_EN;
 }
 
-static void g4x_fbc_enable(struct intel_crtc *crtc)
+static void g4x_fbc_activate(struct intel_crtc *crtc)
 {
 	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
 	struct drm_framebuffer *fb = crtc->base.primary->fb;
 	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
 	u32 dpfc_ctl;
 
-	dev_priv->fbc.enabled = true;
+	dev_priv->fbc.active = true;
 
 	dpfc_ctl = DPFC_CTL_PLANE(crtc->plane) | DPFC_SR_EN;
 	if (drm_format_plane_cpp(fb->pixel_format, 0) == 2)
@@ -179,7 +179,7 @@ static void g4x_fbc_enable(struct intel_crtc *crtc)
 	/* enable it... */
 	I915_WRITE(DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN);
 
-	DRM_DEBUG_KMS("enabled fbc on plane %c\n", plane_name(crtc->plane));
+	DRM_DEBUG_KMS("activated fbc on plane %c\n", plane_name(crtc->plane));
 }
 
 static void g4x_fbc_flip_prepare(struct drm_i915_private *dev_priv)
@@ -198,11 +198,11 @@ static void g4x_fbc_flip_prepare(struct drm_i915_private *dev_priv)
 	I915_WRITE(DPFC_CONTROL, val);
 }
 
-static void g4x_fbc_disable(struct drm_i915_private *dev_priv)
+static void g4x_fbc_deactivate(struct drm_i915_private *dev_priv)
 {
 	u32 dpfc_ctl;
 
-	dev_priv->fbc.enabled = false;
+	dev_priv->fbc.active = false;
 
 	/* Disable compression */
 	dpfc_ctl = I915_READ(DPFC_CONTROL);
@@ -210,11 +210,11 @@ static void g4x_fbc_disable(struct drm_i915_private *dev_priv)
 		dpfc_ctl &= ~DPFC_CTL_EN;
 		I915_WRITE(DPFC_CONTROL, dpfc_ctl);
 
-		DRM_DEBUG_KMS("disabled FBC\n");
+		DRM_DEBUG_KMS("deactivated FBC\n");
 	}
 }
 
-static bool g4x_fbc_enabled(struct drm_i915_private *dev_priv)
+static bool g4x_fbc_is_active(struct drm_i915_private *dev_priv)
 {
 	return I915_READ(DPFC_CONTROL) & DPFC_CTL_EN;
 }
@@ -226,7 +226,7 @@ static void intel_fbc_recompress(struct drm_i915_private *dev_priv)
 	POSTING_READ(MSG_FBC_REND_STATE);
 }
 
-static void ilk_fbc_enable(struct intel_crtc *crtc)
+static void ilk_fbc_activate(struct intel_crtc *crtc)
 {
 	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
 	struct drm_framebuffer *fb = crtc->base.primary->fb;
@@ -235,7 +235,7 @@ static void ilk_fbc_enable(struct intel_crtc *crtc)
 	int threshold = dev_priv->fbc.threshold;
 	unsigned int y_offset;
 
-	dev_priv->fbc.enabled = true;
+	dev_priv->fbc.active = true;
 
 	dpfc_ctl = DPFC_CTL_PLANE(crtc->plane);
 	if (drm_format_plane_cpp(fb->pixel_format, 0) == 2)
@@ -271,7 +271,7 @@ static void ilk_fbc_enable(struct intel_crtc *crtc)
 
 	intel_fbc_recompress(dev_priv);
 
-	DRM_DEBUG_KMS("enabled fbc on plane %c\n", plane_name(crtc->plane));
+	DRM_DEBUG_KMS("activated fbc on plane %c\n", plane_name(crtc->plane));
 }
 
 static void ilk_fbc_flip_prepare(struct drm_i915_private *dev_priv)
@@ -299,11 +299,11 @@ static void snb_fbc_flip_prepare(struct drm_i915_private *dev_priv)
 	I915_WRITE(SNB_DPFC_CTL_SA, SNB_CPU_FENCE_ENABLE | obj->fence_reg);
 }
 
-static void ilk_fbc_disable(struct drm_i915_private *dev_priv)
+static void ilk_fbc_deactivate(struct drm_i915_private *dev_priv)
 {
 	u32 dpfc_ctl;
 
-	dev_priv->fbc.enabled = false;
+	dev_priv->fbc.active = false;
 
 	/* Disable compression */
 	dpfc_ctl = I915_READ(ILK_DPFC_CONTROL);
@@ -311,16 +311,16 @@ static void ilk_fbc_disable(struct drm_i915_private *dev_priv)
 		dpfc_ctl &= ~DPFC_CTL_EN;
 		I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl);
 
-		DRM_DEBUG_KMS("disabled FBC\n");
+		DRM_DEBUG_KMS("deactivated FBC\n");
 	}
 }
 
-static bool ilk_fbc_enabled(struct drm_i915_private *dev_priv)
+static bool ilk_fbc_is_active(struct drm_i915_private *dev_priv)
 {
 	return I915_READ(ILK_DPFC_CONTROL) & DPFC_CTL_EN;
 }
 
-static void gen7_fbc_enable(struct intel_crtc *crtc)
+static void gen7_fbc_activate(struct intel_crtc *crtc)
 {
 	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
 	struct drm_framebuffer *fb = crtc->base.primary->fb;
@@ -328,7 +328,7 @@ static void gen7_fbc_enable(struct intel_crtc *crtc)
 	u32 dpfc_ctl;
 	int threshold = dev_priv->fbc.threshold;
 
-	dev_priv->fbc.enabled = true;
+	dev_priv->fbc.active = true;
 
 	dpfc_ctl = 0;
 	if (IS_IVYBRIDGE(dev_priv))
@@ -375,28 +375,28 @@ static void gen7_fbc_enable(struct intel_crtc *crtc)
 
 	intel_fbc_recompress(dev_priv);
 
-	DRM_DEBUG_KMS("enabled fbc on plane %c\n", plane_name(crtc->plane));
+	DRM_DEBUG_KMS("activated fbc on plane %c\n", plane_name(crtc->plane));
 }
 
 /**
- * intel_fbc_enabled - Is FBC enabled?
+ * intel_fbc_is_active - Is FBC active?
  * @dev_priv: i915 device instance
  *
  * This function is used to verify the current state of FBC.
  * FIXME: This should be tracked in the plane config eventually
  *        instead of queried at runtime for most callers.
  */
-bool intel_fbc_enabled(struct drm_i915_private *dev_priv)
+bool intel_fbc_is_active(struct drm_i915_private *dev_priv)
 {
-	return dev_priv->fbc.enabled;
+	return dev_priv->fbc.active;
 }
 
-static void intel_fbc_enable(const struct drm_framebuffer *fb)
+static void intel_fbc_activate(const struct drm_framebuffer *fb)
 {
 	struct drm_i915_private *dev_priv = fb->dev->dev_private;
 	struct intel_crtc *crtc = dev_priv->fbc.crtc;
 
-	dev_priv->fbc.enable_fbc(crtc);
+	dev_priv->fbc.activate(crtc);
 
 	dev_priv->fbc.fb_id = fb->base.id;
 	dev_priv->fbc.y = crtc->base.y;
@@ -416,7 +416,7 @@ static void intel_fbc_work_fn(struct work_struct *__work)
 		 * the prior work.
 		 */
 		if (crtc_fb == work->fb)
-			intel_fbc_enable(work->fb);
+			intel_fbc_activate(work->fb);
 
 		dev_priv->fbc.fbc_work = NULL;
 	}
@@ -432,7 +432,7 @@ static void intel_fbc_cancel_work(struct drm_i915_private *dev_priv)
 	if (dev_priv->fbc.fbc_work == NULL)
 		return;
 
-	DRM_DEBUG_KMS("cancelling pending FBC enable\n");
+	DRM_DEBUG_KMS("cancelling pending FBC activation\n");
 
 	/* Synchronisation is provided by struct_mutex and checking of
 	 * dev_priv->fbc.fbc_work, so we can perform the cancellation
@@ -450,7 +450,7 @@ static void intel_fbc_cancel_work(struct drm_i915_private *dev_priv)
 	dev_priv->fbc.fbc_work = NULL;
 }
 
-static void intel_fbc_schedule_enable(struct intel_crtc *crtc)
+static void intel_fbc_schedule_activation(struct intel_crtc *crtc)
 {
 	struct intel_fbc_work *work;
 	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
@@ -463,7 +463,7 @@ static void intel_fbc_schedule_enable(struct intel_crtc *crtc)
 	work = kzalloc(sizeof(*work), GFP_KERNEL);
 	if (work == NULL) {
 		DRM_ERROR("Failed to allocate FBC work structure\n");
-		intel_fbc_enable(crtc->base.primary->fb);
+		intel_fbc_activate(crtc->base.primary->fb);
 		return;
 	}
 
@@ -494,8 +494,8 @@ static void intel_fbc_deactivate(struct drm_i915_private *dev_priv)
 
 	intel_fbc_cancel_work(dev_priv);
 
-	if (dev_priv->fbc.enabled)
-		dev_priv->fbc.disable_fbc(dev_priv);
+	if (dev_priv->fbc.active)
+		dev_priv->fbc.deactivate(dev_priv);
 }
 
 static void __intel_fbc_disable(struct drm_i915_private *dev_priv)
@@ -959,10 +959,10 @@ static void __intel_fbc_update(struct intel_crtc *crtc)
 	if (dev_priv->fbc.crtc == crtc &&
 	    dev_priv->fbc.fb_id == fb->base.id &&
 	    dev_priv->fbc.y == crtc->base.y &&
-	    dev_priv->fbc.enabled)
+	    dev_priv->fbc.active)
 		return;
 
-	if (intel_fbc_enabled(dev_priv)) {
+	if (intel_fbc_is_active(dev_priv)) {
 		/* We update FBC along two paths, after changing fb/crtc
 		 * configuration (modeswitching) and after page-flipping
 		 * finishes. For the latter, we know that not only did
@@ -990,13 +990,13 @@ static void __intel_fbc_update(struct intel_crtc *crtc)
 		__intel_fbc_disable(dev_priv);
 	}
 
-	intel_fbc_schedule_enable(crtc);
+	intel_fbc_schedule_activation(crtc);
 	dev_priv->fbc.no_fbc_reason = "FBC enabled (not necessarily active)\n";
 	return;
 
 out_disable:
 	/* Multiple disables should be harmless */
-	if (intel_fbc_enabled(dev_priv)) {
+	if (intel_fbc_is_active(dev_priv)) {
 		DRM_DEBUG_KMS("unsupported config, disabling FBC\n");
 		__intel_fbc_disable(dev_priv);
 	}
@@ -1035,7 +1035,7 @@ void intel_fbc_invalidate(struct drm_i915_private *dev_priv,
 
 	mutex_lock(&dev_priv->fbc.lock);
 
-	if (dev_priv->fbc.enabled || dev_priv->fbc.fbc_work)
+	if (dev_priv->fbc.active || dev_priv->fbc.fbc_work)
 		fbc_bits = INTEL_FRONTBUFFER_PRIMARY(dev_priv->fbc.crtc->pipe);
 	else
 		fbc_bits = dev_priv->fbc.possible_framebuffer_bits;
@@ -1061,7 +1061,7 @@ void intel_fbc_flush(struct drm_i915_private *dev_priv,
 	 * is enabled and we do a page flip, so we can safely ignore it here.
 	 * FBC may be disabled in case we got an invalidate() before the
 	 * flush(), so we'll still have to check that case below. */
-	if (origin == ORIGIN_FLIP && dev_priv->fbc.enabled)
+	if (origin == ORIGIN_FLIP && dev_priv->fbc.active)
 		return;
 
 	mutex_lock(&dev_priv->fbc.lock);
@@ -1069,7 +1069,7 @@ void intel_fbc_flush(struct drm_i915_private *dev_priv,
 	dev_priv->fbc.busy_bits &= ~frontbuffer_bits;
 
 	if (!dev_priv->fbc.busy_bits && dev_priv->fbc.crtc) {
-		if (dev_priv->fbc.enabled)
+		if (dev_priv->fbc.active)
 			intel_fbc_recompress(dev_priv);
 		else
 			__intel_fbc_update(dev_priv->fbc.crtc);
@@ -1088,7 +1088,7 @@ void intel_fbc_flip_prepare(struct drm_i915_private *dev_priv,
 
 	mutex_lock(&dev_priv->fbc.lock);
 
-	if (dev_priv->fbc.enabled) {
+	if (dev_priv->fbc.active) {
 		fbc_bits = INTEL_FRONTBUFFER_PRIMARY(dev_priv->fbc.crtc->pipe);
 		if (fbc_bits & frontbuffer_bits)
 			dev_priv->fbc.flip_prepare(dev_priv);
@@ -1114,7 +1114,7 @@ void intel_fbc_init(struct drm_i915_private *dev_priv)
 	mutex_init(&dev_priv->fbc.lock);
 
 	if (!HAS_FBC(dev_priv)) {
-		dev_priv->fbc.enabled = false;
+		dev_priv->fbc.active = false;
 		dev_priv->fbc.no_fbc_reason = "unsupported by this chipset";
 		return;
 	}
@@ -1128,32 +1128,32 @@ void intel_fbc_init(struct drm_i915_private *dev_priv)
 	}
 
 	if (INTEL_INFO(dev_priv)->gen >= 7) {
-		dev_priv->fbc.fbc_enabled = ilk_fbc_enabled;
-		dev_priv->fbc.enable_fbc = gen7_fbc_enable;
-		dev_priv->fbc.disable_fbc = ilk_fbc_disable;
+		dev_priv->fbc.is_active = ilk_fbc_is_active;
+		dev_priv->fbc.activate = gen7_fbc_activate;
+		dev_priv->fbc.deactivate = ilk_fbc_deactivate;
 		dev_priv->fbc.flip_prepare = snb_fbc_flip_prepare;
 	} else if (INTEL_INFO(dev_priv)->gen >= 5) {
-		dev_priv->fbc.fbc_enabled = ilk_fbc_enabled;
-		dev_priv->fbc.enable_fbc = ilk_fbc_enable;
-		dev_priv->fbc.disable_fbc = ilk_fbc_disable;
+		dev_priv->fbc.is_active = ilk_fbc_is_active;
+		dev_priv->fbc.activate = ilk_fbc_activate;
+		dev_priv->fbc.deactivate = ilk_fbc_deactivate;
 		if (INTEL_INFO(dev_priv)->gen == 5)
 			dev_priv->fbc.flip_prepare = ilk_fbc_flip_prepare;
 		else
 			dev_priv->fbc.flip_prepare = snb_fbc_flip_prepare;
 	} else if (IS_GM45(dev_priv)) {
-		dev_priv->fbc.fbc_enabled = g4x_fbc_enabled;
-		dev_priv->fbc.enable_fbc = g4x_fbc_enable;
-		dev_priv->fbc.disable_fbc = g4x_fbc_disable;
+		dev_priv->fbc.is_active = g4x_fbc_is_active;
+		dev_priv->fbc.activate = g4x_fbc_activate;
+		dev_priv->fbc.deactivate = g4x_fbc_deactivate;
 		dev_priv->fbc.flip_prepare = g4x_fbc_flip_prepare;
 	} else {
-		dev_priv->fbc.fbc_enabled = i8xx_fbc_enabled;
-		dev_priv->fbc.enable_fbc = i8xx_fbc_enable;
-		dev_priv->fbc.disable_fbc = i8xx_fbc_disable;
+		dev_priv->fbc.is_active = i8xx_fbc_is_active;
+		dev_priv->fbc.activate = i8xx_fbc_activate;
+		dev_priv->fbc.deactivate = i8xx_fbc_deactivate;
 		dev_priv->fbc.flip_prepare = i8xx_fbc_flip_prepare;
 
 		/* This value was pulled out of someone's hat */
 		I915_WRITE(FBC_CONTROL, 500 << FBC_CTL_INTERVAL_SHIFT);
 	}
 
-	dev_priv->fbc.enabled = dev_priv->fbc.fbc_enabled(dev_priv);
+	dev_priv->fbc.active = dev_priv->fbc.is_active(dev_priv);
 }
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 0fb0459..277dcac 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2422,7 +2422,7 @@ static void ilk_wm_merge(struct drm_device *dev,
 	 * enabled sometime later.
 	 */
 	if (IS_GEN5(dev) && !merged->fbc_wm_enabled &&
-	    intel_fbc_enabled(dev_priv)) {
+	    intel_fbc_is_active(dev_priv)) {
 		for (level = 2; level <= max_level; level++) {
 			struct intel_wm_level *wm = &merged->wm[level];
 
-- 
2.6.1

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

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 14/26] drm/i915: refactor FBC deactivation at init
  2015-10-27 16:50 [PATCH 00/26] Yet another FBC series, v2 Paulo Zanoni
                   ` (12 preceding siblings ...)
  2015-10-27 16:50 ` [PATCH 13/26] drm/i915: introduce is_active/activate/deactivate to the FBC terminology Paulo Zanoni
@ 2015-10-27 16:50 ` Paulo Zanoni
  2015-10-27 16:50 ` [PATCH 15/26] drm/i915: introduce intel_fbc_{enable, disable} Paulo Zanoni
                   ` (11 subsequent siblings)
  25 siblings, 0 replies; 44+ messages in thread
From: Paulo Zanoni @ 2015-10-27 16:50 UTC (permalink / raw)
  To: intel-gfx

Make sure we deactivate FBC at intel_fbc_init(), so we can remove the
call from intel_display.c.

v2: Keep/improve the comment (Chris).

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 3 ---
 drivers/gpu/drm/i915/intel_fbc.c     | 8 ++++++--
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 2392f47..d1a5648 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -14948,9 +14948,6 @@ void intel_modeset_init(struct drm_device *dev)
 	i915_disable_vga(dev);
 	intel_setup_outputs(dev);
 
-	/* Just in case the BIOS is doing something questionable. */
-	intel_fbc_disable(dev_priv);
-
 	drm_modeset_lock_all(dev);
 	intel_modeset_setup_hw_state(dev);
 	drm_modeset_unlock_all(dev);
diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
index 6f020fc..643871d 100644
--- a/drivers/gpu/drm/i915/intel_fbc.c
+++ b/drivers/gpu/drm/i915/intel_fbc.c
@@ -1112,9 +1112,9 @@ void intel_fbc_init(struct drm_i915_private *dev_priv)
 	enum pipe pipe;
 
 	mutex_init(&dev_priv->fbc.lock);
+	dev_priv->fbc.active = false;
 
 	if (!HAS_FBC(dev_priv)) {
-		dev_priv->fbc.active = false;
 		dev_priv->fbc.no_fbc_reason = "unsupported by this chipset";
 		return;
 	}
@@ -1155,5 +1155,9 @@ void intel_fbc_init(struct drm_i915_private *dev_priv)
 		I915_WRITE(FBC_CONTROL, 500 << FBC_CTL_INTERVAL_SHIFT);
 	}
 
-	dev_priv->fbc.active = dev_priv->fbc.is_active(dev_priv);
+	/* We still don't have any sort of hardware state readout for FBC, so
+	 * disable it in case the BIOS enabled it to make sure software matches
+	 * the hardware state. */
+	if (dev_priv->fbc.is_active(dev_priv))
+		dev_priv->fbc.deactivate(dev_priv);
 }
-- 
2.6.1

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

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 15/26] drm/i915: introduce intel_fbc_{enable, disable}
  2015-10-27 16:50 [PATCH 00/26] Yet another FBC series, v2 Paulo Zanoni
                   ` (13 preceding siblings ...)
  2015-10-27 16:50 ` [PATCH 14/26] drm/i915: refactor FBC deactivation at init Paulo Zanoni
@ 2015-10-27 16:50 ` Paulo Zanoni
  2015-10-27 16:50 ` [PATCH 16/26] drm/i915: remove too-frequent FBC debug message Paulo Zanoni
                   ` (10 subsequent siblings)
  25 siblings, 0 replies; 44+ messages in thread
From: Paulo Zanoni @ 2015-10-27 16:50 UTC (permalink / raw)
  To: intel-gfx

The goal is to call FBC enable/disable only once per modeset, while
activate/deactivate/update will be called multiple times.

The enable() function will be responsible for deciding if a CRTC will
have FBC on it and then it will "lock" FBC on this CRTC: it won't be
possible to change FBC's CRTC until disable(). With this, all checks
and resource acquisition that only need to be done once per modeset
can be moved from update() to enable(). And then the update(),
activate() and deactivate() code will also get simpler since they
won't need to worry about the CRTC being changed.

The disable() function will do the reverse operation of enable(). One
of its features is that it should only be called while the pipe is
already off. This guarantees that FBC is stopped and nothing is
using the CFB.

With this, the activate() and deactivate() functions just start and
temporarily stop FBC. They are the ones touching the hardware enable
bit, so HW state reflects dev_priv->crtc.active.

The last function remaining is update(). A lot of times I thought
about renaming update() to activate() or try_to_activate() since it's
called when we want to activate FBC. The thing is that update() may
not only decide to activate FBC, but also deactivate or keep it on the
same state, so I'll leave this name for now.

Moving code to enable() and disable() will also help in case we decide
to move FBC to pipe_config or something else later.

THe current patch only puts the very basic code on enable() and
disable(). The next commits will take care of moving more stuff from
update() to the new functions.

v2:
  - Rebase.
  - Improve commit message (Chris).

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h      |   1 +
 drivers/gpu/drm/i915/intel_display.c |  14 ++-
 drivers/gpu/drm/i915/intel_drv.h     |   2 +
 drivers/gpu/drm/i915/intel_fbc.c     | 196 +++++++++++++++++++++++++----------
 4 files changed, 156 insertions(+), 57 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index d4326e3..a9434d1 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -913,6 +913,7 @@ struct i915_fbc {
 
 	bool false_color;
 
+	bool enabled;
 	bool active;
 
 	struct intel_fbc_work {
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index d1a5648..5f95531 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -4809,7 +4809,7 @@ static void intel_pre_plane_update(struct intel_crtc *crtc)
 		intel_crtc_wait_for_pending_flips(&crtc->base);
 
 	if (atomic->disable_fbc)
-		intel_fbc_disable_crtc(crtc);
+		intel_fbc_deactivate(crtc);
 
 	if (crtc->atomic.disable_ips)
 		hsw_disable_ips(crtc);
@@ -4910,6 +4910,8 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 
 	if (HAS_PCH_CPT(dev))
 		cpt_verify_modeset(dev, intel_crtc->pipe);
+
+	intel_fbc_enable(intel_crtc);
 }
 
 /* IPS only exists on ULT machines and is tied to pipe A. */
@@ -5012,6 +5014,8 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
 		intel_wait_for_vblank(dev, hsw_workaround_pipe);
 		intel_wait_for_vblank(dev, hsw_workaround_pipe);
 	}
+
+	intel_fbc_enable(intel_crtc);
 }
 
 static void ironlake_pfit_disable(struct intel_crtc *crtc, bool force)
@@ -5078,6 +5082,8 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
 
 		ironlake_fdi_pll_disable(intel_crtc);
 	}
+
+	intel_fbc_disable_crtc(intel_crtc);
 }
 
 static void haswell_crtc_disable(struct drm_crtc *crtc)
@@ -5124,6 +5130,8 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
 	for_each_encoder_on_crtc(dev, crtc, encoder)
 		if (encoder->post_disable)
 			encoder->post_disable(encoder);
+
+	intel_fbc_disable_crtc(intel_crtc);
 }
 
 static void i9xx_pfit_enable(struct intel_crtc *crtc)
@@ -6183,6 +6191,8 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
 
 	for_each_encoder_on_crtc(dev, crtc, encoder)
 		encoder->enable(encoder);
+
+	intel_fbc_enable(intel_crtc);
 }
 
 static void i9xx_pfit_disable(struct intel_crtc *crtc)
@@ -6245,6 +6255,8 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
 
 	if (!IS_GEN2(dev))
 		intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
+
+	intel_fbc_disable_crtc(intel_crtc);
 }
 
 static void intel_crtc_disable_noatomic(struct drm_crtc *crtc)
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 0debbe9..eef98a2 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1296,8 +1296,10 @@ static inline void intel_fbdev_restore_mode(struct drm_device *dev)
 
 /* intel_fbc.c */
 bool intel_fbc_is_active(struct drm_i915_private *dev_priv);
+void intel_fbc_deactivate(struct intel_crtc *crtc);
 void intel_fbc_update(struct intel_crtc *crtc);
 void intel_fbc_init(struct drm_i915_private *dev_priv);
+void intel_fbc_enable(struct intel_crtc *crtc);
 void intel_fbc_disable(struct drm_i915_private *dev_priv);
 void intel_fbc_disable_crtc(struct intel_crtc *crtc);
 void intel_fbc_invalidate(struct drm_i915_private *dev_priv,
diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
index 643871d..53ca151 100644
--- a/drivers/gpu/drm/i915/intel_fbc.c
+++ b/drivers/gpu/drm/i915/intel_fbc.c
@@ -458,7 +458,6 @@ static void intel_fbc_schedule_activation(struct intel_crtc *crtc)
 	WARN_ON(!mutex_is_locked(&dev_priv->fbc.lock));
 
 	intel_fbc_cancel_work(dev_priv);
-	dev_priv->fbc.crtc = crtc;
 
 	work = kzalloc(sizeof(*work), GFP_KERNEL);
 	if (work == NULL) {
@@ -488,7 +487,7 @@ static void intel_fbc_schedule_activation(struct intel_crtc *crtc)
 	schedule_delayed_work(&work->work, msecs_to_jiffies(50));
 }
 
-static void intel_fbc_deactivate(struct drm_i915_private *dev_priv)
+static void __intel_fbc_deactivate(struct drm_i915_private *dev_priv)
 {
 	WARN_ON(!mutex_is_locked(&dev_priv->fbc.lock));
 
@@ -498,35 +497,13 @@ static void intel_fbc_deactivate(struct drm_i915_private *dev_priv)
 		dev_priv->fbc.deactivate(dev_priv);
 }
 
-static void __intel_fbc_disable(struct drm_i915_private *dev_priv)
-{
-	intel_fbc_deactivate(dev_priv);
-	dev_priv->fbc.crtc = NULL;
-}
-
-/**
- * intel_fbc_disable - disable FBC
- * @dev_priv: i915 device instance
- *
- * This function disables FBC.
- */
-void intel_fbc_disable(struct drm_i915_private *dev_priv)
-{
-	if (!fbc_supported(dev_priv))
-		return;
-
-	mutex_lock(&dev_priv->fbc.lock);
-	__intel_fbc_disable(dev_priv);
-	mutex_unlock(&dev_priv->fbc.lock);
-}
-
 /*
- * intel_fbc_disable_crtc - disable FBC if it's associated with crtc
+ * intel_fbc_deactivate - deactivate FBC if it's associated with crtc
  * @crtc: the CRTC
  *
- * This function disables FBC if it's associated with the provided CRTC.
+ * This function deactivates FBC if it's associated with the provided CRTC.
  */
-void intel_fbc_disable_crtc(struct intel_crtc *crtc)
+void intel_fbc_deactivate(struct intel_crtc *crtc)
 {
 	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
 
@@ -535,7 +512,7 @@ void intel_fbc_disable_crtc(struct intel_crtc *crtc)
 
 	mutex_lock(&dev_priv->fbc.lock);
 	if (dev_priv->fbc.crtc == crtc)
-		__intel_fbc_disable(dev_priv);
+		__intel_fbc_deactivate(dev_priv);
 	mutex_unlock(&dev_priv->fbc.lock);
 }
 
@@ -549,13 +526,18 @@ static void set_no_fbc_reason(struct drm_i915_private *dev_priv,
 	DRM_DEBUG_KMS("Disabling FBC: %s\n", reason);
 }
 
-static bool crtc_is_valid(struct intel_crtc *crtc)
+static bool crtc_can_fbc(struct intel_crtc *crtc)
 {
 	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
 
 	if (fbc_on_pipe_a_only(dev_priv) && crtc->pipe != PIPE_A)
 		return false;
 
+	return true;
+}
+
+static bool crtc_is_valid(struct intel_crtc *crtc)
+{
 	if (!intel_crtc_active(&crtc->base))
 		return false;
 
@@ -846,11 +828,11 @@ static bool intel_fbc_hw_tracking_covers_screen(struct intel_crtc *crtc)
 }
 
 /**
- * __intel_fbc_update - enable/disable FBC as needed, unlocked
+ * __intel_fbc_update - activate/deactivate FBC as needed, unlocked
  * @crtc: the CRTC that triggered the update
  *
- * This function completely reevaluates the status of FBC, then enables,
- * disables or maintains it on the same state.
+ * This function completely reevaluates the status of FBC, then activates,
+ * deactivates or maintains it on the same state.
  */
 static void __intel_fbc_update(struct intel_crtc *crtc)
 {
@@ -866,22 +848,9 @@ static void __intel_fbc_update(struct intel_crtc *crtc)
 		goto out_disable;
 	}
 
-	if (dev_priv->fbc.crtc != NULL && dev_priv->fbc.crtc != crtc)
+	if (!dev_priv->fbc.enabled || dev_priv->fbc.crtc != crtc)
 		return;
 
-	if (intel_vgpu_active(dev_priv->dev))
-		i915.enable_fbc = 0;
-
-	if (i915.enable_fbc < 0) {
-		set_no_fbc_reason(dev_priv, "disabled per chip default");
-		goto out_disable;
-	}
-
-	if (!i915.enable_fbc) {
-		set_no_fbc_reason(dev_priv, "disabled per module param");
-		goto out_disable;
-	}
-
 	if (!crtc_is_valid(crtc)) {
 		set_no_fbc_reason(dev_priv, "no output");
 		goto out_disable;
@@ -986,8 +955,8 @@ static void __intel_fbc_update(struct intel_crtc *crtc)
 		 * disabling paths we do need to wait for a vblank at
 		 * some point. And we wait before enabling FBC anyway.
 		 */
-		DRM_DEBUG_KMS("disabling active FBC for update\n");
-		__intel_fbc_disable(dev_priv);
+		DRM_DEBUG_KMS("deactivating FBC for update\n");
+		__intel_fbc_deactivate(dev_priv);
 	}
 
 	intel_fbc_schedule_activation(crtc);
@@ -997,17 +966,17 @@ static void __intel_fbc_update(struct intel_crtc *crtc)
 out_disable:
 	/* Multiple disables should be harmless */
 	if (intel_fbc_is_active(dev_priv)) {
-		DRM_DEBUG_KMS("unsupported config, disabling FBC\n");
-		__intel_fbc_disable(dev_priv);
+		DRM_DEBUG_KMS("unsupported config, deactivating FBC\n");
+		__intel_fbc_deactivate(dev_priv);
 	}
 	__intel_fbc_cleanup_cfb(dev_priv);
 }
 
 /*
- * intel_fbc_update - enable/disable FBC as needed
+ * intel_fbc_update - activate/deactivate FBC as needed
  * @crtc: the CRTC that triggered the update
  *
- * This function reevaluates the overall state and enables or disables FBC.
+ * This function reevaluates the overall state and activates or deactivates FBC.
  */
 void intel_fbc_update(struct intel_crtc *crtc)
 {
@@ -1035,7 +1004,7 @@ void intel_fbc_invalidate(struct drm_i915_private *dev_priv,
 
 	mutex_lock(&dev_priv->fbc.lock);
 
-	if (dev_priv->fbc.active || dev_priv->fbc.fbc_work)
+	if (dev_priv->fbc.enabled)
 		fbc_bits = INTEL_FRONTBUFFER_PRIMARY(dev_priv->fbc.crtc->pipe);
 	else
 		fbc_bits = dev_priv->fbc.possible_framebuffer_bits;
@@ -1043,7 +1012,7 @@ void intel_fbc_invalidate(struct drm_i915_private *dev_priv,
 	dev_priv->fbc.busy_bits |= (fbc_bits & frontbuffer_bits);
 
 	if (dev_priv->fbc.busy_bits)
-		intel_fbc_deactivate(dev_priv);
+		__intel_fbc_deactivate(dev_priv);
 
 	mutex_unlock(&dev_priv->fbc.lock);
 }
@@ -1068,7 +1037,7 @@ void intel_fbc_flush(struct drm_i915_private *dev_priv,
 
 	dev_priv->fbc.busy_bits &= ~frontbuffer_bits;
 
-	if (!dev_priv->fbc.busy_bits && dev_priv->fbc.crtc) {
+	if (!dev_priv->fbc.busy_bits && dev_priv->fbc.enabled) {
 		if (dev_priv->fbc.active)
 			intel_fbc_recompress(dev_priv);
 		else
@@ -1095,9 +1064,123 @@ void intel_fbc_flip_prepare(struct drm_i915_private *dev_priv,
 	} else if (dev_priv->fbc.fbc_work) {
 		fbc_bits = INTEL_FRONTBUFFER_PRIMARY(dev_priv->fbc.crtc->pipe);
 		if (fbc_bits & frontbuffer_bits)
-			intel_fbc_deactivate(dev_priv);
+			__intel_fbc_deactivate(dev_priv);
+	}
+
+	mutex_unlock(&dev_priv->fbc.lock);
+}
+
+/**
+ * intel_fbc_enable: tries to enable FBC on the CRTC
+ * @crtc: the CRTC
+ *
+ * This function checks if it's possible to enable FBC on the following CRTC,
+ * then enables it. Notice that it doesn't activate FBC.
+ */
+void intel_fbc_enable(struct intel_crtc *crtc)
+{
+	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
+
+	if (!fbc_supported(dev_priv))
+		return;
+
+	mutex_lock(&dev_priv->fbc.lock);
+
+	if (dev_priv->fbc.enabled) {
+		WARN_ON(dev_priv->fbc.crtc == crtc);
+		goto out;
 	}
 
+	WARN_ON(dev_priv->fbc.active);
+	WARN_ON(dev_priv->fbc.crtc != NULL);
+
+	if (intel_vgpu_active(dev_priv->dev)) {
+		set_no_fbc_reason(dev_priv, "VGPU is active");
+		goto out;
+	}
+
+	if (i915.enable_fbc < 0) {
+		set_no_fbc_reason(dev_priv, "disabled per chip default");
+		goto out;
+	}
+
+	if (!i915.enable_fbc) {
+		set_no_fbc_reason(dev_priv, "disabled per module param");
+		goto out;
+	}
+
+	if (!crtc_can_fbc(crtc)) {
+		set_no_fbc_reason(dev_priv, "no enabled pipes can have FBC");
+		goto out;
+	}
+
+	DRM_DEBUG_KMS("Enabling FBC on pipe %c\n", pipe_name(crtc->pipe));
+	dev_priv->fbc.no_fbc_reason = "FBC enabled but not active yet\n";
+
+	dev_priv->fbc.enabled = true;
+	dev_priv->fbc.crtc = crtc;
+out:
+	mutex_unlock(&dev_priv->fbc.lock);
+}
+
+/**
+ * __intel_fbc_disable - disable FBC
+ * @dev_priv: i915 device instance
+ *
+ * This is the low level function that actually disables FBC. Callers should
+ * grab the FBC lock.
+ */
+static void __intel_fbc_disable(struct drm_i915_private *dev_priv)
+{
+	struct intel_crtc *crtc = dev_priv->fbc.crtc;
+
+	WARN_ON(!mutex_is_locked(&dev_priv->fbc.lock));
+	WARN_ON(!dev_priv->fbc.enabled);
+	WARN_ON(dev_priv->fbc.active);
+	assert_pipe_disabled(dev_priv, crtc->pipe);
+
+	DRM_DEBUG_KMS("Disabling FBC on pipe %c\n", pipe_name(crtc->pipe));
+
+	dev_priv->fbc.enabled = false;
+	dev_priv->fbc.crtc = NULL;
+}
+
+/**
+ * intel_fbc_disable_crtc - disable FBC if it's associated with crtc
+ * @crtc: the CRTC
+ *
+ * This function disables FBC if it's associated with the provided CRTC.
+ */
+void intel_fbc_disable_crtc(struct intel_crtc *crtc)
+{
+	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
+
+	if (!fbc_supported(dev_priv))
+		return;
+
+	mutex_lock(&dev_priv->fbc.lock);
+	if (dev_priv->fbc.crtc == crtc) {
+		WARN_ON(!dev_priv->fbc.enabled);
+		WARN_ON(dev_priv->fbc.active);
+		__intel_fbc_disable(dev_priv);
+	}
+	mutex_unlock(&dev_priv->fbc.lock);
+}
+
+/**
+ * intel_fbc_disable - globally disable FBC
+ * @dev_priv: i915 device instance
+ *
+ * This function disables FBC regardless of which CRTC is associated with it.
+ */
+void intel_fbc_disable(struct drm_i915_private *dev_priv)
+{
+	if (!fbc_supported(dev_priv))
+		return;
+
+	mutex_lock(&dev_priv->fbc.lock);
+	if (dev_priv->fbc.enabled)
+		__intel_fbc_disable(dev_priv);
 	mutex_unlock(&dev_priv->fbc.lock);
 }
 
@@ -1112,6 +1195,7 @@ void intel_fbc_init(struct drm_i915_private *dev_priv)
 	enum pipe pipe;
 
 	mutex_init(&dev_priv->fbc.lock);
+	dev_priv->fbc.enabled = false;
 	dev_priv->fbc.active = false;
 
 	if (!HAS_FBC(dev_priv)) {
-- 
2.6.1

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

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 16/26] drm/i915: remove too-frequent FBC debug message
  2015-10-27 16:50 [PATCH 00/26] Yet another FBC series, v2 Paulo Zanoni
                   ` (14 preceding siblings ...)
  2015-10-27 16:50 ` [PATCH 15/26] drm/i915: introduce intel_fbc_{enable, disable} Paulo Zanoni
@ 2015-10-27 16:50 ` Paulo Zanoni
  2015-10-27 16:50 ` [PATCH 17/26] drm/i915: fix the CFB size check Paulo Zanoni
                   ` (9 subsequent siblings)
  25 siblings, 0 replies; 44+ messages in thread
From: Paulo Zanoni @ 2015-10-27 16:50 UTC (permalink / raw)
  To: intel-gfx

If we run igt/kms_frontbuffer_tracking, this message will appear
thousands of times, eating a significant part of our dmesg buffer.
It's part of the expected FBC behavior, so let's just silence it.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_fbc.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
index 53ca151..17f098d 100644
--- a/drivers/gpu/drm/i915/intel_fbc.c
+++ b/drivers/gpu/drm/i915/intel_fbc.c
@@ -432,8 +432,6 @@ static void intel_fbc_cancel_work(struct drm_i915_private *dev_priv)
 	if (dev_priv->fbc.fbc_work == NULL)
 		return;
 
-	DRM_DEBUG_KMS("cancelling pending FBC activation\n");
-
 	/* Synchronisation is provided by struct_mutex and checking of
 	 * dev_priv->fbc.fbc_work, so we can perform the cancellation
 	 * entirely asynchronously.
-- 
2.6.1

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

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 17/26] drm/i915: fix the CFB size check
  2015-10-27 16:50 [PATCH 00/26] Yet another FBC series, v2 Paulo Zanoni
                   ` (15 preceding siblings ...)
  2015-10-27 16:50 ` [PATCH 16/26] drm/i915: remove too-frequent FBC debug message Paulo Zanoni
@ 2015-10-27 16:50 ` Paulo Zanoni
  2015-10-27 16:50 ` [PATCH 18/26] drm/i915: alloc/free the FBC CFB during enable/disable Paulo Zanoni
                   ` (8 subsequent siblings)
  25 siblings, 0 replies; 44+ messages in thread
From: Paulo Zanoni @ 2015-10-27 16:50 UTC (permalink / raw)
  To: intel-gfx

In function find_compression_threshold() we try to over-allocate CFB
space in order to reudce reallocations and fragmentation, and we're
not considering that at the CFB size check. Consider it.

There is also a longer-term plan to kill
dev_priv->fbc.uncompressed_size, but this will come later.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_fbc.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
index 17f098d..29d61d1 100644
--- a/drivers/gpu/drm/i915/intel_fbc.c
+++ b/drivers/gpu/drm/i915/intel_fbc.c
@@ -743,7 +743,8 @@ static int intel_fbc_setup_cfb(struct intel_crtc *crtc)
 	size = intel_fbc_calculate_cfb_size(crtc);
 	cpp = drm_format_plane_cpp(fb->pixel_format, 0);
 
-	if (size <= dev_priv->fbc.uncompressed_size)
+	if (dev_priv->fbc.compressed_fb.allocated &&
+	    size <= dev_priv->fbc.compressed_fb.size * dev_priv->fbc.threshold)
 		return 0;
 
 	/* Release any current block */
-- 
2.6.1

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

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 18/26] drm/i915: alloc/free the FBC CFB during enable/disable
  2015-10-27 16:50 [PATCH 00/26] Yet another FBC series, v2 Paulo Zanoni
                   ` (16 preceding siblings ...)
  2015-10-27 16:50 ` [PATCH 17/26] drm/i915: fix the CFB size check Paulo Zanoni
@ 2015-10-27 16:50 ` Paulo Zanoni
  2015-10-27 16:50 ` [PATCH 19/26] drm/i915: move adjusted_mode checks from fbc_update to fbc_enable Paulo Zanoni
                   ` (7 subsequent siblings)
  25 siblings, 0 replies; 44+ messages in thread
From: Paulo Zanoni @ 2015-10-27 16:50 UTC (permalink / raw)
  To: intel-gfx

One of the problems with the current code is that it frees the CFB and
releases its drm_mm node as soon as we flip FBC's enable bit. This is
bad because after we disbale FBC the hardware may still use the CFB
for the rest of the frame, so in theory we should only release the
drm_mm node one frame after we disable FBC. Otherwise, a stolen memory
allocation done right after an FBC disable may result in either
corrupted memory for the new owner of that memory region or corrupted
screen/underruns in case the new owner changes it while the hardware
is still reading it. This case is not exactly easy to reproduce since
we currently don't do a lot of stolen memory allocations, but I see
patches on the mailing list trying to expose stolen memory to user
space, so races will be possible.

I thought about three different approaches to solve this, and they all
have downsides.

The first approach would be to simply use multiple drm_mm nodes and
freeing the unused ones only after a frame has passed. The problem
with this approach is that since stolen memory is rather small,
there's a risk we just won't be able to allocate a new CFB from stolen
if the previous one was not freed yet. This could happen in case we
quickly disable FBC from pipe A and decide to enable it on pipe B, or
just if we change pipe A's fb stride while FBC is enabled.

The second approach would be similar to the first one, but maintaining
a single drm_mm node and keeping track of when it can be reused. This
would remove the disadvantage of not having enough space for two
nodes, but would create the new problem where we may not be able to
enable FBC at the point intel_fbc_update() is called, so we would have
to add more code to retry updating FBC after the time has passed. And
that can quickly get too complex since we can get invalidate, flush,
flip_prepare, disable and other calls in the middle of the wait.

Both solutions above - and also the current code - have the problem
that we unnecessarily free+realloc FBC during invalidate+flush
operations even if the CFB size doesn't change.

The third option would be to move the allocation/deallocation to
enable/disable. This makes sure that the pipe is always disabled when
we allocate/deallocate the CFB, so there's no risk that the FBC
hardware may read or write to the memory right after it is freed from
drm_mm. The downside is that it is possible for user space to change
the buffer stride without triggering a disable/enable - only
deactivate/activate -, so we'll have to handle this case somehow, even
though it is uncommon - see igt's kms_frontbuffer_tracking test,
fbc-stridechange subtest. It could be possible to implement a way to
free+alloc the CFB during said stride change, but it would involve a
lot of book-keeping - exactly as mentioned above - just for a rare
case, so for now I'll keep it simple and just deactivate FBC. Besides,
we may not even need to disable FBC since we do CFB over-allocation.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_fbc.c | 132 ++++++++++++++++++++-------------------
 1 file changed, 68 insertions(+), 64 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
index 29d61d1..0ba25b9 100644
--- a/drivers/gpu/drm/i915/intel_fbc.c
+++ b/drivers/gpu/drm/i915/intel_fbc.c
@@ -64,6 +64,45 @@ static unsigned int get_crtc_fence_y_offset(struct intel_crtc *crtc)
 	return crtc->base.y - crtc->adjusted_y;
 }
 
+/*
+ * For SKL+, the plane source size used by the hardware is based on the value we
+ * write to the PLANE_SIZE register. For BDW-, the hardware looks at the value
+ * we wrote to PIPESRC.
+ */
+static void intel_fbc_get_plane_source_size(struct intel_crtc *crtc,
+					    int *width, int *height)
+{
+	struct intel_plane_state *plane_state =
+			to_intel_plane_state(crtc->base.primary->state);
+	int w, h;
+
+	if (intel_rotation_90_or_270(plane_state->base.rotation)) {
+		w = drm_rect_height(&plane_state->src) >> 16;
+		h = drm_rect_width(&plane_state->src) >> 16;
+	} else {
+		w = drm_rect_width(&plane_state->src) >> 16;
+		h = drm_rect_height(&plane_state->src) >> 16;
+	}
+
+	if (width)
+		*width = w;
+	if (height)
+		*height = h;
+}
+
+static int intel_fbc_calculate_cfb_size(struct intel_crtc *crtc,
+					struct drm_framebuffer *fb)
+{
+	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
+	int lines;
+
+	intel_fbc_get_plane_source_size(crtc, NULL, &lines);
+	if (INTEL_INFO(dev_priv)->gen >= 7)
+		lines = min(lines, 2048);
+
+	return lines * fb->pitches[0];
+}
+
 static void i8xx_fbc_deactivate(struct drm_i915_private *dev_priv)
 {
 	u32 fbc_ctl;
@@ -614,11 +653,17 @@ again:
 	}
 }
 
-static int intel_fbc_alloc_cfb(struct drm_i915_private *dev_priv, int size,
-			       int fb_cpp)
+static int intel_fbc_alloc_cfb(struct intel_crtc *crtc)
 {
+	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
+	struct drm_framebuffer *fb = crtc->base.primary->state->fb;
 	struct drm_mm_node *uninitialized_var(compressed_llb);
-	int ret;
+	int size, fb_cpp, ret;
+
+	WARN_ON(dev_priv->fbc.compressed_fb.allocated);
+
+	size = intel_fbc_calculate_cfb_size(crtc, fb);
+	fb_cpp = drm_format_plane_cpp(fb->pixel_format, 0);
 
 	ret = find_compression_threshold(dev_priv, &dev_priv->fbc.compressed_fb,
 					 size, fb_cpp);
@@ -695,64 +740,6 @@ void intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv)
 	mutex_unlock(&dev_priv->fbc.lock);
 }
 
-/*
- * For SKL+, the plane source size used by the hardware is based on the value we
- * write to the PLANE_SIZE register. For BDW-, the hardware looks at the value
- * we wrote to PIPESRC.
- */
-static void intel_fbc_get_plane_source_size(struct intel_crtc *crtc,
-					    int *width, int *height)
-{
-	struct intel_plane_state *plane_state =
-			to_intel_plane_state(crtc->base.primary->state);
-	int w, h;
-
-	if (intel_rotation_90_or_270(plane_state->base.rotation)) {
-		w = drm_rect_height(&plane_state->src) >> 16;
-		h = drm_rect_width(&plane_state->src) >> 16;
-	} else {
-		w = drm_rect_width(&plane_state->src) >> 16;
-		h = drm_rect_height(&plane_state->src) >> 16;
-	}
-
-	if (width)
-		*width = w;
-	if (height)
-		*height = h;
-}
-
-static int intel_fbc_calculate_cfb_size(struct intel_crtc *crtc)
-{
-	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
-	struct drm_framebuffer *fb = crtc->base.primary->fb;
-	int lines;
-
-	intel_fbc_get_plane_source_size(crtc, NULL, &lines);
-	if (INTEL_INFO(dev_priv)->gen >= 7)
-		lines = min(lines, 2048);
-
-	return lines * fb->pitches[0];
-}
-
-static int intel_fbc_setup_cfb(struct intel_crtc *crtc)
-{
-	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
-	struct drm_framebuffer *fb = crtc->base.primary->fb;
-	int size, cpp;
-
-	size = intel_fbc_calculate_cfb_size(crtc);
-	cpp = drm_format_plane_cpp(fb->pixel_format, 0);
-
-	if (dev_priv->fbc.compressed_fb.allocated &&
-	    size <= dev_priv->fbc.compressed_fb.size * dev_priv->fbc.threshold)
-		return 0;
-
-	/* Release any current block */
-	__intel_fbc_cleanup_cfb(dev_priv);
-
-	return intel_fbc_alloc_cfb(dev_priv, size, cpp);
-}
-
 static bool stride_is_valid(struct drm_i915_private *dev_priv,
 			    unsigned int stride)
 {
@@ -914,8 +901,19 @@ static void __intel_fbc_update(struct intel_crtc *crtc)
 		goto out_disable;
 	}
 
-	if (intel_fbc_setup_cfb(crtc)) {
-		set_no_fbc_reason(dev_priv, "not enough stolen memory");
+	/* It is possible for the required CFB size change without a
+	 * crtc->disable + crtc->enable since it is possible to change the
+	 * stride without triggering a full modeset. Since we try to
+	 * over-allocate the CFB, there's a chance we may keep FBC enabled even
+	 * if this happens, but if we exceed the current CFB size we'll have to
+	 * disable FBC. Notice that it would be possible to disable FBC, wait
+	 * for a frame, free the stolen node, then try to reenable FBC in case
+	 * we didn't get any invalidate/deactivate calls, but this would require
+	 * a lot of tracking just for a case we expect to be uncommon, so we
+	 * just don't have this code for now. */
+	if (intel_fbc_calculate_cfb_size(crtc, fb) >
+	    dev_priv->fbc.compressed_fb.size * dev_priv->fbc.threshold) {
+		set_no_fbc_reason(dev_priv, "CFB requirements changed");
 		goto out_disable;
 	}
 
@@ -968,7 +966,6 @@ out_disable:
 		DRM_DEBUG_KMS("unsupported config, deactivating FBC\n");
 		__intel_fbc_deactivate(dev_priv);
 	}
-	__intel_fbc_cleanup_cfb(dev_priv);
 }
 
 /*
@@ -1113,6 +1110,11 @@ void intel_fbc_enable(struct intel_crtc *crtc)
 		goto out;
 	}
 
+	if (intel_fbc_alloc_cfb(crtc)) {
+		set_no_fbc_reason(dev_priv, "not enough stolen memory");
+		goto out;
+	}
+
 	DRM_DEBUG_KMS("Enabling FBC on pipe %c\n", pipe_name(crtc->pipe));
 	dev_priv->fbc.no_fbc_reason = "FBC enabled but not active yet\n";
 
@@ -1140,6 +1142,8 @@ static void __intel_fbc_disable(struct drm_i915_private *dev_priv)
 
 	DRM_DEBUG_KMS("Disabling FBC on pipe %c\n", pipe_name(crtc->pipe));
 
+	__intel_fbc_cleanup_cfb(dev_priv);
+
 	dev_priv->fbc.enabled = false;
 	dev_priv->fbc.crtc = NULL;
 }
-- 
2.6.1

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

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 19/26] drm/i915: move adjusted_mode checks from fbc_update to fbc_enable
  2015-10-27 16:50 [PATCH 00/26] Yet another FBC series, v2 Paulo Zanoni
                   ` (17 preceding siblings ...)
  2015-10-27 16:50 ` [PATCH 18/26] drm/i915: alloc/free the FBC CFB during enable/disable Paulo Zanoni
@ 2015-10-27 16:50 ` Paulo Zanoni
  2015-10-29 12:59   ` Maarten Lankhorst
  2015-10-27 16:50 ` [PATCH 20/26] drm/i915: move clock frequency " Paulo Zanoni
                   ` (6 subsequent siblings)
  25 siblings, 1 reply; 44+ messages in thread
From: Paulo Zanoni @ 2015-10-27 16:50 UTC (permalink / raw)
  To: intel-gfx

These things can't change without a full modeset.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_fbc.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
index 0ba25b9..6aa9af8 100644
--- a/drivers/gpu/drm/i915/intel_fbc.c
+++ b/drivers/gpu/drm/i915/intel_fbc.c
@@ -825,7 +825,6 @@ static void __intel_fbc_update(struct intel_crtc *crtc)
 	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
 	struct drm_framebuffer *fb;
 	struct drm_i915_gem_object *obj;
-	const struct drm_display_mode *adjusted_mode;
 
 	WARN_ON(!mutex_is_locked(&dev_priv->fbc.lock));
 
@@ -844,13 +843,6 @@ static void __intel_fbc_update(struct intel_crtc *crtc)
 
 	fb = crtc->base.primary->fb;
 	obj = intel_fb_obj(fb);
-	adjusted_mode = &crtc->config->base.adjusted_mode;
-
-	if ((adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) ||
-	    (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)) {
-		set_no_fbc_reason(dev_priv, "incompatible mode");
-		goto out_disable;
-	}
 
 	if (!intel_fbc_hw_tracking_covers_screen(crtc)) {
 		set_no_fbc_reason(dev_priv, "mode too large for compression");
@@ -1076,6 +1068,8 @@ void intel_fbc_flip_prepare(struct drm_i915_private *dev_priv,
 void intel_fbc_enable(struct intel_crtc *crtc)
 {
 	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
+	const struct drm_display_mode *adjusted_mode =
+					&crtc->config->base.adjusted_mode;
 
 	if (!fbc_supported(dev_priv))
 		return;
@@ -1110,6 +1104,12 @@ void intel_fbc_enable(struct intel_crtc *crtc)
 		goto out;
 	}
 
+	if ((adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) ||
+	    (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)) {
+		set_no_fbc_reason(dev_priv, "incompatible mode");
+		goto out;
+	}
+
 	if (intel_fbc_alloc_cfb(crtc)) {
 		set_no_fbc_reason(dev_priv, "not enough stolen memory");
 		goto out;
-- 
2.6.1

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

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 20/26] drm/i915: move clock frequency checks from fbc_update to fbc_enable
  2015-10-27 16:50 [PATCH 00/26] Yet another FBC series, v2 Paulo Zanoni
                   ` (18 preceding siblings ...)
  2015-10-27 16:50 ` [PATCH 19/26] drm/i915: move adjusted_mode checks from fbc_update to fbc_enable Paulo Zanoni
@ 2015-10-27 16:50 ` Paulo Zanoni
  2015-10-27 16:50 ` [PATCH 21/26] drm/i915: check for FBC planes in the same place as the pipes Paulo Zanoni
                   ` (5 subsequent siblings)
  25 siblings, 0 replies; 44+ messages in thread
From: Paulo Zanoni @ 2015-10-27 16:50 UTC (permalink / raw)
  To: intel-gfx

These also can't change without a full modeset.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_fbc.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
index 6aa9af8..a9f133a 100644
--- a/drivers/gpu/drm/i915/intel_fbc.c
+++ b/drivers/gpu/drm/i915/intel_fbc.c
@@ -885,14 +885,6 @@ static void __intel_fbc_update(struct intel_crtc *crtc)
 		goto out_disable;
 	}
 
-	/* WaFbcExceedCdClockThreshold:hsw,bdw */
-	if ((IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) &&
-	    ilk_pipe_pixel_rate(crtc->config) >=
-	    dev_priv->cdclk_freq * 95 / 100) {
-		set_no_fbc_reason(dev_priv, "pixel rate is too big");
-		goto out_disable;
-	}
-
 	/* It is possible for the required CFB size change without a
 	 * crtc->disable + crtc->enable since it is possible to change the
 	 * stride without triggering a full modeset. Since we try to
@@ -1110,6 +1102,14 @@ void intel_fbc_enable(struct intel_crtc *crtc)
 		goto out;
 	}
 
+	/* WaFbcExceedCdClockThreshold:hsw,bdw */
+	if ((IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) &&
+	    ilk_pipe_pixel_rate(crtc->config) >=
+	    dev_priv->cdclk_freq * 95 / 100) {
+		set_no_fbc_reason(dev_priv, "pixel rate is too big");
+		goto out;
+	}
+
 	if (intel_fbc_alloc_cfb(crtc)) {
 		set_no_fbc_reason(dev_priv, "not enough stolen memory");
 		goto out;
-- 
2.6.1

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

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 21/26] drm/i915: check for FBC planes in the same place as the pipes
  2015-10-27 16:50 [PATCH 00/26] Yet another FBC series, v2 Paulo Zanoni
                   ` (19 preceding siblings ...)
  2015-10-27 16:50 ` [PATCH 20/26] drm/i915: move clock frequency " Paulo Zanoni
@ 2015-10-27 16:50 ` Paulo Zanoni
  2015-10-27 16:50 ` [PATCH 22/26] drm/i915: clarify that checking the FB stride for CFB is intentional Paulo Zanoni
                   ` (4 subsequent siblings)
  25 siblings, 0 replies; 44+ messages in thread
From: Paulo Zanoni @ 2015-10-27 16:50 UTC (permalink / raw)
  To: intel-gfx

This moves the pre-gen4 check from update() to enable(). The HAS_DDI
in the original code is not needed since only gen 2/3 have the plane
swapping code.

v2: Rebase.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_fbc.c | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
index a9f133a..01807c5 100644
--- a/drivers/gpu/drm/i915/intel_fbc.c
+++ b/drivers/gpu/drm/i915/intel_fbc.c
@@ -570,6 +570,9 @@ static bool crtc_can_fbc(struct intel_crtc *crtc)
 	if (fbc_on_pipe_a_only(dev_priv) && crtc->pipe != PIPE_A)
 		return false;
 
+	if (INTEL_INFO(dev_priv)->gen < 4 && crtc->plane != PLANE_A)
+		return false;
+
 	return true;
 }
 
@@ -849,12 +852,6 @@ static void __intel_fbc_update(struct intel_crtc *crtc)
 		goto out_disable;
 	}
 
-	if ((INTEL_INFO(dev_priv)->gen < 4 || HAS_DDI(dev_priv)) &&
-	    crtc->plane != PLANE_A) {
-		set_no_fbc_reason(dev_priv, "FBC unsupported on plane");
-		goto out_disable;
-	}
-
 	/* The use of a CPU fence is mandatory in order to detect writes
 	 * by the CPU to the scanout and trigger updates to the FBC.
 	 */
-- 
2.6.1

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

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 22/26] drm/i915: clarify that checking the FB stride for CFB is intentional
  2015-10-27 16:50 [PATCH 00/26] Yet another FBC series, v2 Paulo Zanoni
                   ` (20 preceding siblings ...)
  2015-10-27 16:50 ` [PATCH 21/26] drm/i915: check for FBC planes in the same place as the pipes Paulo Zanoni
@ 2015-10-27 16:50 ` Paulo Zanoni
  2015-10-27 16:50 ` [PATCH 23/26] drm/i915: use a single intel_fbc_work struct Paulo Zanoni
                   ` (3 subsequent siblings)
  25 siblings, 0 replies; 44+ messages in thread
From: Paulo Zanoni @ 2015-10-27 16:50 UTC (permalink / raw)
  To: intel-gfx

Daniel was looking at this code and asked about whether fb->pitches[0]
is correct, then he suggested we should a comment to make sure it is
actually intentional.

For more information on the CFB size calculation, please see the
commit message of:

commit c4ffd40908c30a33291227920e921f6b45b9e8f7
Author: Paulo Zanoni <paulo.r.zanoni@intel.com>
Date:   Thu Oct 1 19:55:57 2015 -0300
    drm/i915: fix CFB size calculation

Requested-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_fbc.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
index 01807c5..4bb2323 100644
--- a/drivers/gpu/drm/i915/intel_fbc.c
+++ b/drivers/gpu/drm/i915/intel_fbc.c
@@ -100,6 +100,7 @@ static int intel_fbc_calculate_cfb_size(struct intel_crtc *crtc,
 	if (INTEL_INFO(dev_priv)->gen >= 7)
 		lines = min(lines, 2048);
 
+	/* Hardware needs the full buffer stride, not just the active area. */
 	return lines * fb->pitches[0];
 }
 
-- 
2.6.1

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

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 23/26] drm/i915: use a single intel_fbc_work struct
  2015-10-27 16:50 [PATCH 00/26] Yet another FBC series, v2 Paulo Zanoni
                   ` (21 preceding siblings ...)
  2015-10-27 16:50 ` [PATCH 22/26] drm/i915: clarify that checking the FB stride for CFB is intentional Paulo Zanoni
@ 2015-10-27 16:50 ` Paulo Zanoni
  2015-10-27 20:29   ` Chris Wilson
  2015-10-27 16:50 ` [PATCH 24/26] drm/i915: wait for a vblank instead of 50ms when enabling FBC Paulo Zanoni
                   ` (2 subsequent siblings)
  25 siblings, 1 reply; 44+ messages in thread
From: Paulo Zanoni @ 2015-10-27 16:50 UTC (permalink / raw)
  To: intel-gfx

This was already on my TODO list, and was requested both by Chris and
Ville, for different reasons. The advantages are avoiding a frequent
malloc/free pair, and the locality of having the work structure
embedded in dev_priv. The maximum used memory is also smaller since
previously we could have multiple allocated intel_fbc_work structs at
the same time, and now we'll always have a single one - the one
embedded on dev_priv. Of course, we're now using a little more memory
on the cases where there's nothing scheduled.

The biggest challenge here is to keep everything synchronized the way
it was before.

Currently, when we try to activate FBC, we allocate a new
intel_fbc_work structure. Then later when we conclude we must delay
the FBC activation a little more, we allocate a new intel_fbc_work
struct, and then adjust dev_priv->fbc.fbc_work to point to the new
struct. So when the old work runs - at intel_fbc_work_fn() - it will
check that dev_priv->fbc.fbc_work points to something else, so it does
nothing. Everything is also protected by fbc.lock.

Just cancelling the old delayed work doesn't work because we might
just cancel it after the work function already started to run, but
while it is still waiting to grab fbc.lock. That's why we use the
"dev_priv->fbc.fbc_work == work" check described in the paragraph
above.

So now that we have a single work struct we have to introduce a new
way to synchronize everything. So we're making the work function a
normal work instead of a delayed work, and it will be responsible for
sleeping the appropriate amount of time itself. This way, after it
wakes up it can grab the lock, ask "were we delayed or cancelled?" and
then go back to sleep, enable FBC or give up.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h  |   6 ++-
 drivers/gpu/drm/i915/intel_fbc.c | 108 +++++++++++++++++----------------------
 2 files changed, 52 insertions(+), 62 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index a9434d1..fdbe068 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -917,9 +917,11 @@ struct i915_fbc {
 	bool active;
 
 	struct intel_fbc_work {
-		struct delayed_work work;
+		bool scheduled;
+		struct work_struct work;
 		struct drm_framebuffer *fb;
-	} *fbc_work;
+		unsigned long enable_jiffies;
+	} work;
 
 	const char *no_fbc_reason;
 
diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
index 4bb2323..a7192dd 100644
--- a/drivers/gpu/drm/i915/intel_fbc.c
+++ b/drivers/gpu/drm/i915/intel_fbc.c
@@ -444,85 +444,71 @@ static void intel_fbc_activate(const struct drm_framebuffer *fb)
 
 static void intel_fbc_work_fn(struct work_struct *__work)
 {
-	struct intel_fbc_work *work =
-		container_of(to_delayed_work(__work),
-			     struct intel_fbc_work, work);
-	struct drm_i915_private *dev_priv = work->fb->dev->dev_private;
-	struct drm_framebuffer *crtc_fb = dev_priv->fbc.crtc->base.primary->fb;
+	struct drm_i915_private *dev_priv =
+		container_of(__work, struct drm_i915_private, fbc.work.work);
+	struct intel_fbc_work *work = &dev_priv->fbc.work;
+	struct intel_crtc *crtc = dev_priv->fbc.crtc;
+	unsigned long delay_jiffies = msecs_to_jiffies(50);
+
+retry:
+	/* Delay the actual enabling to let pageflipping cease and the
+	 * display to settle before starting the compression. Note that
+	 * this delay also serves a second purpose: it allows for a
+	 * vblank to pass after disabling the FBC before we attempt
+	 * to modify the control registers.
+	 *
+	 * A more complicated solution would involve tracking vblanks
+	 * following the termination of the page-flipping sequence
+	 * and indeed performing the enable as a co-routine and not
+	 * waiting synchronously upon the vblank.
+	 *
+	 * WaFbcWaitForVBlankBeforeEnable:ilk,snb
+	 */
+	wait_remaining_ms_from_jiffies(work->enable_jiffies, delay_jiffies);
 
 	mutex_lock(&dev_priv->fbc.lock);
-	if (work == dev_priv->fbc.fbc_work) {
-		/* Double check that we haven't switched fb without cancelling
-		 * the prior work.
-		 */
-		if (crtc_fb == work->fb)
-			intel_fbc_activate(work->fb);
 
-		dev_priv->fbc.fbc_work = NULL;
+	/* Were we cancelled? */
+	if (!work->scheduled)
+		goto out;
+
+	/* Were we delayed again while this function was sleeping? */
+	if (time_after(work->enable_jiffies + delay_jiffies, jiffies)) {
+		mutex_unlock(&dev_priv->fbc.lock);
+		goto retry;
 	}
-	mutex_unlock(&dev_priv->fbc.lock);
 
-	kfree(work);
+	if (crtc->base.primary->fb == work->fb)
+		intel_fbc_activate(work->fb);
+
+	work->scheduled = false;
+
+out:
+	mutex_unlock(&dev_priv->fbc.lock);
 }
 
 static void intel_fbc_cancel_work(struct drm_i915_private *dev_priv)
 {
 	WARN_ON(!mutex_is_locked(&dev_priv->fbc.lock));
-
-	if (dev_priv->fbc.fbc_work == NULL)
-		return;
-
-	/* Synchronisation is provided by struct_mutex and checking of
-	 * dev_priv->fbc.fbc_work, so we can perform the cancellation
-	 * entirely asynchronously.
-	 */
-	if (cancel_delayed_work(&dev_priv->fbc.fbc_work->work))
-		/* tasklet was killed before being run, clean up */
-		kfree(dev_priv->fbc.fbc_work);
-
-	/* Mark the work as no longer wanted so that if it does
-	 * wake-up (because the work was already running and waiting
-	 * for our mutex), it will discover that is no longer
-	 * necessary to run.
-	 */
-	dev_priv->fbc.fbc_work = NULL;
+	dev_priv->fbc.work.scheduled = false;
 }
 
 static void intel_fbc_schedule_activation(struct intel_crtc *crtc)
 {
-	struct intel_fbc_work *work;
 	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
+	struct intel_fbc_work *work = &dev_priv->fbc.work;
 
 	WARN_ON(!mutex_is_locked(&dev_priv->fbc.lock));
 
-	intel_fbc_cancel_work(dev_priv);
-
-	work = kzalloc(sizeof(*work), GFP_KERNEL);
-	if (work == NULL) {
-		DRM_ERROR("Failed to allocate FBC work structure\n");
-		intel_fbc_activate(crtc->base.primary->fb);
-		return;
-	}
-
+	/* It is useless to call intel_fbc_cancel_work() in this function since
+	 * we're not releasing fbc.lock, so it won't have an opportunigy to grab
+	 * it to discover that it was cancelled. So we just update the expected
+	 * jiffy count. */
 	work->fb = crtc->base.primary->fb;
-	INIT_DELAYED_WORK(&work->work, intel_fbc_work_fn);
+	work->scheduled = true;
+	work->enable_jiffies = jiffies;
 
-	dev_priv->fbc.fbc_work = work;
-
-	/* Delay the actual enabling to let pageflipping cease and the
-	 * display to settle before starting the compression. Note that
-	 * this delay also serves a second purpose: it allows for a
-	 * vblank to pass after disabling the FBC before we attempt
-	 * to modify the control registers.
-	 *
-	 * A more complicated solution would involve tracking vblanks
-	 * following the termination of the page-flipping sequence
-	 * and indeed performing the enable as a co-routine and not
-	 * waiting synchronously upon the vblank.
-	 *
-	 * WaFbcWaitForVBlankBeforeEnable:ilk,snb
-	 */
-	schedule_delayed_work(&work->work, msecs_to_jiffies(50));
+	schedule_work(&work->work);
 }
 
 static void __intel_fbc_deactivate(struct drm_i915_private *dev_priv)
@@ -1039,7 +1025,7 @@ void intel_fbc_flip_prepare(struct drm_i915_private *dev_priv,
 		fbc_bits = INTEL_FRONTBUFFER_PRIMARY(dev_priv->fbc.crtc->pipe);
 		if (fbc_bits & frontbuffer_bits)
 			dev_priv->fbc.flip_prepare(dev_priv);
-	} else if (dev_priv->fbc.fbc_work) {
+	} else if (dev_priv->fbc.work.scheduled) {
 		fbc_bits = INTEL_FRONTBUFFER_PRIMARY(dev_priv->fbc.crtc->pipe);
 		if (fbc_bits & frontbuffer_bits)
 			__intel_fbc_deactivate(dev_priv);
@@ -1195,9 +1181,11 @@ void intel_fbc_init(struct drm_i915_private *dev_priv)
 {
 	enum pipe pipe;
 
+	INIT_WORK(&dev_priv->fbc.work.work, intel_fbc_work_fn);
 	mutex_init(&dev_priv->fbc.lock);
 	dev_priv->fbc.enabled = false;
 	dev_priv->fbc.active = false;
+	dev_priv->fbc.work.scheduled = false;
 
 	if (!HAS_FBC(dev_priv)) {
 		dev_priv->fbc.no_fbc_reason = "unsupported by this chipset";
-- 
2.6.1

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

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 24/26] drm/i915: wait for a vblank instead of 50ms when enabling FBC
  2015-10-27 16:50 [PATCH 00/26] Yet another FBC series, v2 Paulo Zanoni
                   ` (22 preceding siblings ...)
  2015-10-27 16:50 ` [PATCH 23/26] drm/i915: use a single intel_fbc_work struct Paulo Zanoni
@ 2015-10-27 16:50 ` Paulo Zanoni
  2015-10-27 16:50 ` [PATCH 25/26] drm/i915: remove in_dbg_master check from intel_fbc.c Paulo Zanoni
  2015-10-27 16:50 ` [PATCH 26/26] drm/i915: kill fbc.uncompressed_size Paulo Zanoni
  25 siblings, 0 replies; 44+ messages in thread
From: Paulo Zanoni @ 2015-10-27 16:50 UTC (permalink / raw)
  To: intel-gfx

Instead of waiting for 50ms, just wait until the next vblank, since
it's the minimum requirement.

This moves PC7 residency on my specific BDW machine running Cinnamon
from 60-70% to 84-89%. Without FBC, I get 20-25%. I'm using a
3200x1800 eDP panel.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h  |  2 +-
 drivers/gpu/drm/i915/intel_fbc.c | 12 +++---------
 2 files changed, 4 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index fdbe068..784ce2e 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -918,9 +918,9 @@ struct i915_fbc {
 
 	struct intel_fbc_work {
 		bool scheduled;
+		u32 scheduled_vblank;
 		struct work_struct work;
 		struct drm_framebuffer *fb;
-		unsigned long enable_jiffies;
 	} work;
 
 	const char *no_fbc_reason;
diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
index a7192dd..cbdf2f3 100644
--- a/drivers/gpu/drm/i915/intel_fbc.c
+++ b/drivers/gpu/drm/i915/intel_fbc.c
@@ -448,7 +448,6 @@ static void intel_fbc_work_fn(struct work_struct *__work)
 		container_of(__work, struct drm_i915_private, fbc.work.work);
 	struct intel_fbc_work *work = &dev_priv->fbc.work;
 	struct intel_crtc *crtc = dev_priv->fbc.crtc;
-	unsigned long delay_jiffies = msecs_to_jiffies(50);
 
 retry:
 	/* Delay the actual enabling to let pageflipping cease and the
@@ -457,14 +456,9 @@ retry:
 	 * vblank to pass after disabling the FBC before we attempt
 	 * to modify the control registers.
 	 *
-	 * A more complicated solution would involve tracking vblanks
-	 * following the termination of the page-flipping sequence
-	 * and indeed performing the enable as a co-routine and not
-	 * waiting synchronously upon the vblank.
-	 *
 	 * WaFbcWaitForVBlankBeforeEnable:ilk,snb
 	 */
-	wait_remaining_ms_from_jiffies(work->enable_jiffies, delay_jiffies);
+	intel_wait_for_vblank(dev_priv->dev, crtc->pipe);
 
 	mutex_lock(&dev_priv->fbc.lock);
 
@@ -473,7 +467,7 @@ retry:
 		goto out;
 
 	/* Were we delayed again while this function was sleeping? */
-	if (time_after(work->enable_jiffies + delay_jiffies, jiffies)) {
+	if (drm_crtc_vblank_get(&crtc->base) == work->scheduled_vblank) {
 		mutex_unlock(&dev_priv->fbc.lock);
 		goto retry;
 	}
@@ -506,7 +500,7 @@ static void intel_fbc_schedule_activation(struct intel_crtc *crtc)
 	 * jiffy count. */
 	work->fb = crtc->base.primary->fb;
 	work->scheduled = true;
-	work->enable_jiffies = jiffies;
+	work->scheduled_vblank = drm_crtc_vblank_count(&crtc->base);
 
 	schedule_work(&work->work);
 }
-- 
2.6.1

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

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 25/26] drm/i915: remove in_dbg_master check from intel_fbc.c
  2015-10-27 16:50 [PATCH 00/26] Yet another FBC series, v2 Paulo Zanoni
                   ` (23 preceding siblings ...)
  2015-10-27 16:50 ` [PATCH 24/26] drm/i915: wait for a vblank instead of 50ms when enabling FBC Paulo Zanoni
@ 2015-10-27 16:50 ` Paulo Zanoni
  2015-10-27 16:50 ` [PATCH 26/26] drm/i915: kill fbc.uncompressed_size Paulo Zanoni
  25 siblings, 0 replies; 44+ messages in thread
From: Paulo Zanoni @ 2015-10-27 16:50 UTC (permalink / raw)
  To: intel-gfx; +Cc: Daniel Vetter, Jason Wessel

From our maintainer Daniel Vetter a few days ago:
  "Oh dear this is dead code. kdbg uses the fbcon, which always uses
  untiled, which means fbc will never be enabled. Also we have 0 users
  and 0 test coverage for kdbg on top of i915 (Jesse implemented it
  for fun years back). Imo just remove all this code."

Adding to what Daniel said: for kgdboc's KMS support,
intel_pipe_set_base_atomic() already manually disables FBC, so we
won't do the in_dbg_master() check there. This is essentially a revert
of:

commit c924b934d0cd14a4559611da91f28f59acebe32a
Author: Jason Wessel <jason.wessel@windriver.com>
Date:   Thu Aug 5 09:22:32 2010 -0500
    i915: when kgdb is active display compression should be off

Besides, it is not clear what is the exact problem caused by FBC, and
why other features such as PSR, DRRS, IPS and RPM are not also
checking for in_dbg_master(). IMHO we should either remove the code as
suggested by Daniel or we add some nice comments explaining why is FBC
so special.

Cc: Jason Wessel <jason.wessel@windriver.com>
Cc: Jesse Barnes <jbarnes@virtuousgeek.org>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_fbc.c | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
index cbdf2f3..ba31359 100644
--- a/drivers/gpu/drm/i915/intel_fbc.c
+++ b/drivers/gpu/drm/i915/intel_fbc.c
@@ -857,12 +857,6 @@ static void __intel_fbc_update(struct intel_crtc *crtc)
 		goto out_disable;
 	}
 
-	/* If the kernel debugger is active, always disable compression */
-	if (in_dbg_master()) {
-		set_no_fbc_reason(dev_priv, "Kernel debugger is active");
-		goto out_disable;
-	}
-
 	/* It is possible for the required CFB size change without a
 	 * crtc->disable + crtc->enable since it is possible to change the
 	 * stride without triggering a full modeset. Since we try to
-- 
2.6.1

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

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 26/26] drm/i915: kill fbc.uncompressed_size
  2015-10-27 16:50 [PATCH 00/26] Yet another FBC series, v2 Paulo Zanoni
                   ` (24 preceding siblings ...)
  2015-10-27 16:50 ` [PATCH 25/26] drm/i915: remove in_dbg_master check from intel_fbc.c Paulo Zanoni
@ 2015-10-27 16:50 ` Paulo Zanoni
  25 siblings, 0 replies; 44+ messages in thread
From: Paulo Zanoni @ 2015-10-27 16:50 UTC (permalink / raw)
  To: intel-gfx

Directly call intel_fbc_calculate_cfb_size() in the only place that
actually needs it, and use the proper check before removing the stolen
node. IMHO, this change makes our code easier to understand.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h  |  1 -
 drivers/gpu/drm/i915/intel_fbc.c | 13 ++++---------
 2 files changed, 4 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 784ce2e..0acc090 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -900,7 +900,6 @@ struct i915_fbc {
 	/* This is always the inner lock when overlapping with struct_mutex and
 	 * it's the outer lock when overlapping with stolen_lock. */
 	struct mutex lock;
-	unsigned long uncompressed_size;
 	unsigned threshold;
 	unsigned int fb_id;
 	unsigned int possible_framebuffer_bits;
diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
index ba31359..27c42e7 100644
--- a/drivers/gpu/drm/i915/intel_fbc.c
+++ b/drivers/gpu/drm/i915/intel_fbc.c
@@ -155,7 +155,7 @@ static void i8xx_fbc_activate(struct intel_crtc *crtc)
 	dev_priv->fbc.active = true;
 
 	/* Note: fbc.threshold == 1 for i8xx */
-	cfb_pitch = dev_priv->fbc.uncompressed_size / FBC_LL_SIZE;
+	cfb_pitch = intel_fbc_calculate_cfb_size(crtc, fb) / FBC_LL_SIZE;
 	if (fb->pitches[0] < cfb_pitch)
 		cfb_pitch = fb->pitches[0];
 
@@ -682,8 +682,6 @@ static int intel_fbc_alloc_cfb(struct intel_crtc *crtc)
 			   dev_priv->mm.stolen_base + compressed_llb->start);
 	}
 
-	dev_priv->fbc.uncompressed_size = size;
-
 	DRM_DEBUG_KMS("reserved %llu bytes of contiguous stolen space for FBC, threshold: %d\n",
 		      dev_priv->fbc.compressed_fb.size,
 		      dev_priv->fbc.threshold);
@@ -700,18 +698,15 @@ err_llb:
 
 static void __intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv)
 {
-	if (dev_priv->fbc.uncompressed_size == 0)
-		return;
-
-	i915_gem_stolen_remove_node(dev_priv, &dev_priv->fbc.compressed_fb);
+	if (dev_priv->fbc.compressed_fb.allocated)
+		i915_gem_stolen_remove_node(dev_priv,
+					    &dev_priv->fbc.compressed_fb);
 
 	if (dev_priv->fbc.compressed_llb) {
 		i915_gem_stolen_remove_node(dev_priv,
 					    dev_priv->fbc.compressed_llb);
 		kfree(dev_priv->fbc.compressed_llb);
 	}
-
-	dev_priv->fbc.uncompressed_size = 0;
 }
 
 void intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv)
-- 
2.6.1

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

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* Re: [PATCH 02/26] drm/i915: don't stop+start FBC at every flip
  2015-10-27 16:50 ` [PATCH 02/26] drm/i915: don't stop+start FBC at every flip Paulo Zanoni
@ 2015-10-27 18:32   ` Ville Syrjälä
  2015-10-28 16:56     ` Zanoni, Paulo R
  2015-10-27 19:50   ` Chris Wilson
  1 sibling, 1 reply; 44+ messages in thread
From: Ville Syrjälä @ 2015-10-27 18:32 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx

On Tue, Oct 27, 2015 at 02:50:04PM -0200, Paulo Zanoni wrote:
> The hardware already takes care of disabling and recompressing FBC
> when we do a page flip, so all we need to do is to update the fence
> registers and move on.
> 
> One of the important things to notice is that on the pre-gen6
> platforms the fence is programmed on the FBC control register and the
> documentation says we can't update the control register while FBC is
> enabled. This would basically mean we'd have to to disable+enable FBC
> at every flip in order to make sure the hardware tracking still works,
> which doesn't seem to make too much sense. So I sent an email to the
> hardware team requesting some clarification. The information I got was
> this:
> 
> "I don't think any hardware is latching on to 0x100100, 0x100104, or
> the old fence number in FBC_CTL. Instructions against changing on the
> fly would be to simplify testing and ensure you don't miss any
> invalidation that happened right at that time."
> 
> So I guess we're fine for flips. But I can't really say I tested FBC
> on these ancient platforms - nor that I'll ever propose enabling FBC
> by default on them exactly because of problems like these.

Yeah, I did this in my patches too, and IIRC it seemed to work just fine
back then.

> 
> v2: Add comment at flush() (Chris).
> 
> Testcase: igt/kms_frontbuffer_tracking/fbc*-fliptrack
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.h          |   1 +
>  drivers/gpu/drm/i915/i915_reg.h          |   3 +
>  drivers/gpu/drm/i915/intel_display.c     |   1 -
>  drivers/gpu/drm/i915/intel_drv.h         |   2 +
>  drivers/gpu/drm/i915/intel_fbc.c         | 103 ++++++++++++++++++++++++++++++-
>  drivers/gpu/drm/i915/intel_frontbuffer.c |   1 +
>  6 files changed, 108 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index ee14962..77da500 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -928,6 +928,7 @@ struct i915_fbc {
>  	bool (*fbc_enabled)(struct drm_i915_private *dev_priv);
>  	void (*enable_fbc)(struct intel_crtc *crtc);
>  	void (*disable_fbc)(struct drm_i915_private *dev_priv);
> +	void (*flip_prepare)(struct drm_i915_private *dev_priv);
>  };
>  
>  /**
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 8942532..3d598a2 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -2028,6 +2028,7 @@ enum skl_disp_power_wells {
>  #define   FBC_CTL_C3_IDLE	(1<<13)
>  #define   FBC_CTL_STRIDE_SHIFT	(5)
>  #define   FBC_CTL_FENCENO_SHIFT	(0)
> +#define   FBC_CTL_FENCENO_MASK	0xF

It's only three bits on gen2. But bit 3 is MBZ and there are only 8
fence registers on those platforms, so this is OK.

>  #define FBC_COMMAND		0x0320c
>  #define   FBC_CMD_COMPRESS	(1<<0)
>  #define FBC_STATUS		0x03210
> @@ -2064,6 +2065,7 @@ enum skl_disp_power_wells {
>  #define   DPFC_CTL_LIMIT_1X	(0<<6)
>  #define   DPFC_CTL_LIMIT_2X	(1<<6)
>  #define   DPFC_CTL_LIMIT_4X	(2<<6)
> +#define   DPFC_CTL_FENCE_MASK	0xF
>  #define DPFC_RECOMP_CTL		0x320c
>  #define   DPFC_RECOMP_STALL_EN	(1<<27)
>  #define   DPFC_RECOMP_STALL_WM_SHIFT (16)
> @@ -2086,6 +2088,7 @@ enum skl_disp_power_wells {
>  #define   FBC_CTL_FALSE_COLOR	(1<<10)
>  /* The bit 28-8 is reserved */
>  #define   DPFC_RESERVED		(0x1FFFFF00)
> +#define   ILK_DPFC_FENCE_MASK	0xF
>  #define ILK_DPFC_RECOMP_CTL	0x4320c
>  #define ILK_DPFC_STATUS		0x43210
>  #define ILK_DPFC_FENCE_YOFF	0x43218
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index bc1907e..d9378c3 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -11502,7 +11502,6 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
>  			  to_intel_plane(primary)->frontbuffer_bit);
>  	mutex_unlock(&dev->struct_mutex);
>  
> -	intel_fbc_disable_crtc(intel_crtc);
>  	intel_frontbuffer_flip_prepare(dev,
>  				       to_intel_plane(primary)->frontbuffer_bit);
>  
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 08847d0..9065a8f 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1305,6 +1305,8 @@ void intel_fbc_invalidate(struct drm_i915_private *dev_priv,
>  			  enum fb_op_origin origin);
>  void intel_fbc_flush(struct drm_i915_private *dev_priv,
>  		     unsigned int frontbuffer_bits, enum fb_op_origin origin);
> +void intel_fbc_flip_prepare(struct drm_i915_private *dev_priv,
> +			    unsigned int frontbuffer_bits);
>  void intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv);
>  
>  /* intel_hdmi.c */
> diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
> index d9d7e54..62f158b 100644
> --- a/drivers/gpu/drm/i915/intel_fbc.c
> +++ b/drivers/gpu/drm/i915/intel_fbc.c
> @@ -82,6 +82,22 @@ static void i8xx_fbc_disable(struct drm_i915_private *dev_priv)
>  	DRM_DEBUG_KMS("disabled FBC\n");
>  }
>  
> +static void i8xx_fbc_flip_prepare(struct drm_i915_private *dev_priv)
> +{
> +	struct intel_crtc *crtc = dev_priv->fbc.crtc;
> +	struct drm_framebuffer *fb = crtc->base.primary->fb;
> +	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
> +	uint32_t val;
> +
> +	/* Although the documentation suggests we can't change DPFC_CONTROL
> +	 * while compression is enabled, the hardware guys said that updating
> +	 * the fence register bits during a flip is fine. */
> +	val = I915_READ(FBC_CONTROL);
> +	val &= ~FBC_CTL_FENCENO_MASK;
> +	val |= obj->fence_reg;
> +	I915_WRITE(FBC_CONTROL, val);
> +}

IIRC I just called the enable function to reconstruct the entire
register contents to avoid code duplication. But maybe that's not
possible without reowrking the fbc state handling entirely
(which I had done).

> +
>  static void i8xx_fbc_enable(struct intel_crtc *crtc)
>  {
>  	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
> @@ -161,6 +177,22 @@ static void g4x_fbc_enable(struct intel_crtc *crtc)
>  	DRM_DEBUG_KMS("enabled fbc on plane %c\n", plane_name(crtc->plane));
>  }
>  
> +static void g4x_fbc_flip_prepare(struct drm_i915_private *dev_priv)
> +{
> +	struct intel_crtc *crtc = dev_priv->fbc.crtc;
> +	struct drm_framebuffer *fb = crtc->base.primary->fb;
> +	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
> +	uint32_t val;
> +
> +	/* Although the documentation suggests we can't change DPFC_CONTROL
> +	 * while compression is enabled, the hardware guys said that updating
> +	 * the fence register bits during a flip is fine. */
> +	val = I915_READ(DPFC_CONTROL);
> +	val &= ~DPFC_CTL_FENCE_MASK;
> +	val |= obj->fence_reg;
> +	I915_WRITE(DPFC_CONTROL, val);
> +}
> +
>  static void g4x_fbc_disable(struct drm_i915_private *dev_priv)
>  {
>  	u32 dpfc_ctl;
> @@ -236,6 +268,31 @@ static void ilk_fbc_enable(struct intel_crtc *crtc)
>  	DRM_DEBUG_KMS("enabled fbc on plane %c\n", plane_name(crtc->plane));
>  }
>  
> +static void ilk_fbc_flip_prepare(struct drm_i915_private *dev_priv)
> +{
> +	struct intel_crtc *crtc = dev_priv->fbc.crtc;
> +	struct drm_framebuffer *fb = crtc->base.primary->fb;
> +	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
> +	uint32_t val;
> +
> +	/* Although the documentation suggests we can't change DPFC_CONTROL
> +	 * while compression is enabled, the hardware guys said that updating
> +	 * the fence register bits during a flip is fine. */
> +	val = I915_READ(ILK_DPFC_CONTROL);
> +	val &= ~ILK_DPFC_FENCE_MASK;
> +	val |= obj->fence_reg;
> +	I915_WRITE(ILK_DPFC_CONTROL, val);
> +}
> +
> +static void snb_fbc_flip_prepare(struct drm_i915_private *dev_priv)
> +{
> +	struct intel_crtc *crtc = dev_priv->fbc.crtc;
> +	struct drm_framebuffer *fb = crtc->base.primary->fb;
> +	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
> +
> +	I915_WRITE(SNB_DPFC_CTL_SA, SNB_CPU_FENCE_ENABLE | obj->fence_reg);
> +}
> +
>  static void ilk_fbc_disable(struct drm_i915_private *dev_priv)
>  {
>  	u32 dpfc_ctl;
> @@ -1021,13 +1078,48 @@ void intel_fbc_flush(struct drm_i915_private *dev_priv,
>  	if (origin == ORIGIN_GTT)
>  		return;
>  
> +	/* Hardware tracking already recompresses the CFB (nuke) for us if FBC
> +	 * is enabled and we do a page flip, so we can safely ignore it here.
> +	 * FBC may be disabled in case we got an invalidate() before the
> +	 * flush(), so we'll still have to check that case below. */
> +	if (origin == ORIGIN_FLIP && dev_priv->fbc.enabled)
> +		return;
> +
>  	mutex_lock(&dev_priv->fbc.lock);
>  
>  	dev_priv->fbc.busy_bits &= ~frontbuffer_bits;
>  
>  	if (!dev_priv->fbc.busy_bits) {
> -		__intel_fbc_disable(dev_priv);
> -		__intel_fbc_update(dev_priv);
> +		if (origin == ORIGIN_FLIP) {
> +			__intel_fbc_update(dev_priv);
> +		} else {
> +			__intel_fbc_disable(dev_priv);
> +			__intel_fbc_update(dev_priv);
> +		}
> +	}
> +
> +	mutex_unlock(&dev_priv->fbc.lock);
> +}
> +
> +void intel_fbc_flip_prepare(struct drm_i915_private *dev_priv,
> +			    unsigned int frontbuffer_bits)
> +{
> +	unsigned int fbc_bits;
> +
> +	if (!fbc_supported(dev_priv))
> +		return;
> +
> +	mutex_lock(&dev_priv->fbc.lock);
> +
> +	if (dev_priv->fbc.enabled) {
> +		fbc_bits = INTEL_FRONTBUFFER_PRIMARY(dev_priv->fbc.crtc->pipe);

primary->frontbuffer_bit would seem better.

> +		if (fbc_bits & frontbuffer_bits)
> +			dev_priv->fbc.flip_prepare(dev_priv);

You would still have to disable+reenable if you need to eg. reallocate
the compressed buffer, of if the new fb isn't suitable for fbc, or maybe
if you need to change anything else in the control register.

What I had was:
"
static bool intel_fbc_need_reinit(struct intel_crtc *crtc)
{
	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
	struct drm_framebuffer *fb = crtc->base.primary->fb;
	struct drm_i915_gem_object *obj = to_intel_framebuffer(fb)->obj;

	return crtc != dev_priv->fbc.crtc ||
	       obj->base.size > dev_priv->fbc.size ||
	       drm_format_plane_cpp(fb->pixel_format, 0) !=
	       drm_format_plane_cpp(dev_priv->fbc.pixel_format, 0) ||
	       fb->pitches[0] != dev_priv->fbc.pitch;
}
intel_fbc_pre_page_flip()
{
	...
	intel_fbc_update_pending_score(crtc);

	/*
	 * If fbc was already possible we can update immediately,
	 * otherwise we will wait until the flip is finished.
	 */
	if (crtc->fbc.score != 0)
		crtc->fbc.score = crtc->fbc.pending_score;

	/*
	 * Disable fbc if we're not (yet) capable, or if
	 * we just need a full disable+enable reinit.
	 */
	if (crtc->fbc.score == 0 || intel_fbc_need_reinit(crtc))
		__intel_fbc_disable(crtc);
	...
}
"

> +	} else if (dev_priv->fbc.fbc_work) {
> +		fbc_bits = INTEL_FRONTBUFFER_PRIMARY(
> +				dev_priv->fbc.fbc_work->crtc->pipe);
> +		if (fbc_bits & frontbuffer_bits)
> +			__intel_fbc_disable(dev_priv);
>  	}
>  
>  	mutex_unlock(&dev_priv->fbc.lock);
> @@ -1063,18 +1155,25 @@ void intel_fbc_init(struct drm_i915_private *dev_priv)
>  		dev_priv->fbc.fbc_enabled = ilk_fbc_enabled;
>  		dev_priv->fbc.enable_fbc = gen7_fbc_enable;
>  		dev_priv->fbc.disable_fbc = ilk_fbc_disable;
> +		dev_priv->fbc.flip_prepare = snb_fbc_flip_prepare;
>  	} else if (INTEL_INFO(dev_priv)->gen >= 5) {
>  		dev_priv->fbc.fbc_enabled = ilk_fbc_enabled;
>  		dev_priv->fbc.enable_fbc = ilk_fbc_enable;
>  		dev_priv->fbc.disable_fbc = ilk_fbc_disable;
> +		if (INTEL_INFO(dev_priv)->gen == 5)
> +			dev_priv->fbc.flip_prepare = ilk_fbc_flip_prepare;
> +		else
> +			dev_priv->fbc.flip_prepare = snb_fbc_flip_prepare;
>  	} else if (IS_GM45(dev_priv)) {
>  		dev_priv->fbc.fbc_enabled = g4x_fbc_enabled;
>  		dev_priv->fbc.enable_fbc = g4x_fbc_enable;
>  		dev_priv->fbc.disable_fbc = g4x_fbc_disable;
> +		dev_priv->fbc.flip_prepare = g4x_fbc_flip_prepare;
>  	} else {
>  		dev_priv->fbc.fbc_enabled = i8xx_fbc_enabled;
>  		dev_priv->fbc.enable_fbc = i8xx_fbc_enable;
>  		dev_priv->fbc.disable_fbc = i8xx_fbc_disable;
> +		dev_priv->fbc.flip_prepare = i8xx_fbc_flip_prepare;
>  
>  		/* This value was pulled out of someone's hat */
>  		I915_WRITE(FBC_CONTROL, 500 << FBC_CTL_INTERVAL_SHIFT);
> diff --git a/drivers/gpu/drm/i915/intel_frontbuffer.c b/drivers/gpu/drm/i915/intel_frontbuffer.c
> index ac85357..31a1ad3 100644
> --- a/drivers/gpu/drm/i915/intel_frontbuffer.c
> +++ b/drivers/gpu/drm/i915/intel_frontbuffer.c
> @@ -192,6 +192,7 @@ void intel_frontbuffer_flip_prepare(struct drm_device *dev,
>  	mutex_unlock(&dev_priv->fb_tracking.lock);
>  
>  	intel_psr_single_frame_update(dev, frontbuffer_bits);
> +	intel_fbc_flip_prepare(dev_priv, frontbuffer_bits);
>  }
>  
>  /**
> -- 
> 2.6.1
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 02/26] drm/i915: don't stop+start FBC at every flip
  2015-10-27 16:50 ` [PATCH 02/26] drm/i915: don't stop+start FBC at every flip Paulo Zanoni
  2015-10-27 18:32   ` Ville Syrjälä
@ 2015-10-27 19:50   ` Chris Wilson
  2015-10-28 16:58     ` Zanoni, Paulo R
  1 sibling, 1 reply; 44+ messages in thread
From: Chris Wilson @ 2015-10-27 19:50 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx

On Tue, Oct 27, 2015 at 02:50:04PM -0200, Paulo Zanoni wrote:
> @@ -1021,13 +1078,48 @@ void intel_fbc_flush(struct drm_i915_private *dev_priv,
>  	if (origin == ORIGIN_GTT)
>  		return;
>  
> +	/* Hardware tracking already recompresses the CFB (nuke) for us if FBC
> +	 * is enabled and we do a page flip, so we can safely ignore it here.
> +	 * FBC may be disabled in case we got an invalidate() before the
> +	 * flush(), so we'll still have to check that case below. */

I feel like I understand what is going on a bit better now, thanks!

> +	if (origin == ORIGIN_FLIP && dev_priv->fbc.enabled)
> +		return;
> +
>  	mutex_lock(&dev_priv->fbc.lock);
>  
>  	dev_priv->fbc.busy_bits &= ~frontbuffer_bits;
>  
>  	if (!dev_priv->fbc.busy_bits) {
> -		__intel_fbc_disable(dev_priv);
> -		__intel_fbc_update(dev_priv);
> +		if (origin == ORIGIN_FLIP) {

Note this test here is redundant.

We know that for an origin == FLIP to be here, FBC is disabled and
calling intel_fbc_disable() is then a no-op.

So it turns out that the origin two lines of disable(); update() works
just as well. Or is there some later patch that tweaks this branch
further?
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 23/26] drm/i915: use a single intel_fbc_work struct
  2015-10-27 16:50 ` [PATCH 23/26] drm/i915: use a single intel_fbc_work struct Paulo Zanoni
@ 2015-10-27 20:29   ` Chris Wilson
  2015-10-28 17:24     ` Zanoni, Paulo R
  0 siblings, 1 reply; 44+ messages in thread
From: Chris Wilson @ 2015-10-27 20:29 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx

On Tue, Oct 27, 2015 at 02:50:25PM -0200, Paulo Zanoni wrote:
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index a9434d1..fdbe068 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -917,9 +917,11 @@ struct i915_fbc {
>  	bool active;
>  
>  	struct intel_fbc_work {
> -		struct delayed_work work;
> +		bool scheduled;

Ah, I found this confusingly named. scheduled implied to me that you
wanted work_pending(), but you just want to asynchronously cancel the
fbc worker. Just bool cancel? Or bool active? Though now I've come full
circle and suggest bool scheduled. So

/* Track whether the FBC worker has already been queued,
 * or asynchronously cancel the worker whilst it waits
 * before activation.
 */

What happens then if we quickly queue, cancel and want to requeue? The
schedule_work() fails as the task is already pending, but the scheduled
flag gets reset, so it just works. Perfect.

> +		struct work_struct work;
>  		struct drm_framebuffer *fb;

Hmm, don't we actually need to take references on the fb we schedule for
activation? Since we already account for that the crtc->fb may be
changed between queuing the work and executing it, for extra paranoia we
should ensure that we have a reference in work->fb. (long standing bug,
might as well fix it before we see it in the wild, time for another
kms-flip race!)

I think I've covered the basic issues with changing the type of worker
and it looks fine,
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 02/26] drm/i915: don't stop+start FBC at every flip
  2015-10-27 18:32   ` Ville Syrjälä
@ 2015-10-28 16:56     ` Zanoni, Paulo R
  2015-10-28 17:20       ` Ville Syrjälä
  0 siblings, 1 reply; 44+ messages in thread
From: Zanoni, Paulo R @ 2015-10-28 16:56 UTC (permalink / raw)
  To: ville.syrjala@linux.intel.com; +Cc: intel-gfx@lists.freedesktop.org

Em Ter, 2015-10-27 às 20:32 +0200, Ville Syrjälä escreveu:
> On Tue, Oct 27, 2015 at 02:50:04PM -0200, Paulo Zanoni wrote:
> > The hardware already takes care of disabling and recompressing FBC
> > when we do a page flip, so all we need to do is to update the fence
> > registers and move on.
> > 
> > One of the important things to notice is that on the pre-gen6
> > platforms the fence is programmed on the FBC control register and
> > the
> > documentation says we can't update the control register while FBC
> > is
> > enabled. This would basically mean we'd have to to disable+enable
> > FBC
> > at every flip in order to make sure the hardware tracking still
> > works,
> > which doesn't seem to make too much sense. So I sent an email to
> > the
> > hardware team requesting some clarification. The information I got
> > was
> > this:
> > 
> > "I don't think any hardware is latching on to 0x100100, 0x100104,
> > or
> > the old fence number in FBC_CTL. Instructions against changing on
> > the
> > fly would be to simplify testing and ensure you don't miss any
> > invalidation that happened right at that time."
> > 
> > So I guess we're fine for flips. But I can't really say I tested
> > FBC
> > on these ancient platforms - nor that I'll ever propose enabling
> > FBC
> > by default on them exactly because of problems like these.
> 
> Yeah, I did this in my patches too, and IIRC it seemed to work just
> fine
> back then.
> 
> > 
> > v2: Add comment at flush() (Chris).
> > 
> > Testcase: igt/kms_frontbuffer_tracking/fbc*-fliptrack
> > Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> > ---
> >  drivers/gpu/drm/i915/i915_drv.h          |   1 +
> >  drivers/gpu/drm/i915/i915_reg.h          |   3 +
> >  drivers/gpu/drm/i915/intel_display.c     |   1 -
> >  drivers/gpu/drm/i915/intel_drv.h         |   2 +
> >  drivers/gpu/drm/i915/intel_fbc.c         | 103
> > ++++++++++++++++++++++++++++++-
> >  drivers/gpu/drm/i915/intel_frontbuffer.c |   1 +
> >  6 files changed, 108 insertions(+), 3 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/i915_drv.h
> > b/drivers/gpu/drm/i915/i915_drv.h
> > index ee14962..77da500 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.h
> > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > @@ -928,6 +928,7 @@ struct i915_fbc {
> >  	bool (*fbc_enabled)(struct drm_i915_private *dev_priv);
> >  	void (*enable_fbc)(struct intel_crtc *crtc);
> >  	void (*disable_fbc)(struct drm_i915_private *dev_priv);
> > +	void (*flip_prepare)(struct drm_i915_private *dev_priv);
> >  };
> >  
> >  /**
> > diff --git a/drivers/gpu/drm/i915/i915_reg.h
> > b/drivers/gpu/drm/i915/i915_reg.h
> > index 8942532..3d598a2 100644
> > --- a/drivers/gpu/drm/i915/i915_reg.h
> > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > @@ -2028,6 +2028,7 @@ enum skl_disp_power_wells {
> >  #define   FBC_CTL_C3_IDLE	(1<<13)
> >  #define   FBC_CTL_STRIDE_SHIFT	(5)
> >  #define   FBC_CTL_FENCENO_SHIFT	(0)
> > +#define   FBC_CTL_FENCENO_MASK	0xF
> 
> It's only three bits on gen2. But bit 3 is MBZ and there are only 8
> fence registers on those platforms, so this is OK.
> 
> >  #define FBC_COMMAND		0x0320c
> >  #define   FBC_CMD_COMPRESS	(1<<0)
> >  #define FBC_STATUS		0x03210
> > @@ -2064,6 +2065,7 @@ enum skl_disp_power_wells {
> >  #define   DPFC_CTL_LIMIT_1X	(0<<6)
> >  #define   DPFC_CTL_LIMIT_2X	(1<<6)
> >  #define   DPFC_CTL_LIMIT_4X	(2<<6)
> > +#define   DPFC_CTL_FENCE_MASK	0xF
> >  #define DPFC_RECOMP_CTL		0x320c
> >  #define   DPFC_RECOMP_STALL_EN	(1<<27)
> >  #define   DPFC_RECOMP_STALL_WM_SHIFT (16)
> > @@ -2086,6 +2088,7 @@ enum skl_disp_power_wells {
> >  #define   FBC_CTL_FALSE_COLOR	(1<<10)
> >  /* The bit 28-8 is reserved */
> >  #define   DPFC_RESERVED		(0x1FFFFF00)
> > +#define   ILK_DPFC_FENCE_MASK	0xF
> >  #define ILK_DPFC_RECOMP_CTL	0x4320c
> >  #define ILK_DPFC_STATUS		0x43210
> >  #define ILK_DPFC_FENCE_YOFF	0x43218
> > diff --git a/drivers/gpu/drm/i915/intel_display.c
> > b/drivers/gpu/drm/i915/intel_display.c
> > index bc1907e..d9378c3 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -11502,7 +11502,6 @@ static int intel_crtc_page_flip(struct
> > drm_crtc *crtc,
> >  			  to_intel_plane(primary)-
> > >frontbuffer_bit);
> >  	mutex_unlock(&dev->struct_mutex);
> >  
> > -	intel_fbc_disable_crtc(intel_crtc);
> >  	intel_frontbuffer_flip_prepare(dev,
> >  				       to_intel_plane(primary)-
> > >frontbuffer_bit);
> >  
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h
> > b/drivers/gpu/drm/i915/intel_drv.h
> > index 08847d0..9065a8f 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -1305,6 +1305,8 @@ void intel_fbc_invalidate(struct
> > drm_i915_private *dev_priv,
> >  			  enum fb_op_origin origin);
> >  void intel_fbc_flush(struct drm_i915_private *dev_priv,
> >  		     unsigned int frontbuffer_bits, enum
> > fb_op_origin origin);
> > +void intel_fbc_flip_prepare(struct drm_i915_private *dev_priv,
> > +			    unsigned int frontbuffer_bits);
> >  void intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv);
> >  
> >  /* intel_hdmi.c */
> > diff --git a/drivers/gpu/drm/i915/intel_fbc.c
> > b/drivers/gpu/drm/i915/intel_fbc.c
> > index d9d7e54..62f158b 100644
> > --- a/drivers/gpu/drm/i915/intel_fbc.c
> > +++ b/drivers/gpu/drm/i915/intel_fbc.c
> > @@ -82,6 +82,22 @@ static void i8xx_fbc_disable(struct
> > drm_i915_private *dev_priv)
> >  	DRM_DEBUG_KMS("disabled FBC\n");
> >  }
> >  
> > +static void i8xx_fbc_flip_prepare(struct drm_i915_private
> > *dev_priv)
> > +{
> > +	struct intel_crtc *crtc = dev_priv->fbc.crtc;
> > +	struct drm_framebuffer *fb = crtc->base.primary->fb;
> > +	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
> > +	uint32_t val;
> > +
> > +	/* Although the documentation suggests we can't change
> > DPFC_CONTROL
> > +	 * while compression is enabled, the hardware guys said
> > that updating
> > +	 * the fence register bits during a flip is fine. */
> > +	val = I915_READ(FBC_CONTROL);
> > +	val &= ~FBC_CTL_FENCENO_MASK;
> > +	val |= obj->fence_reg;
> > +	I915_WRITE(FBC_CONTROL, val);
> > +}
> 
> IIRC I just called the enable function to reconstruct the entire
> register contents to avoid code duplication. But maybe that's not
> possible without reowrking the fbc state handling entirely
> (which I had done).
> > +
> >  static void i8xx_fbc_enable(struct intel_crtc *crtc)
> >  {
> >  	struct drm_i915_private *dev_priv = crtc->base.dev-
> > >dev_private;
> > @@ -161,6 +177,22 @@ static void g4x_fbc_enable(struct intel_crtc
> > *crtc)
> >  	DRM_DEBUG_KMS("enabled fbc on plane %c\n",
> > plane_name(crtc->plane));
> >  }
> >  
> > +static void g4x_fbc_flip_prepare(struct drm_i915_private
> > *dev_priv)
> > +{
> > +	struct intel_crtc *crtc = dev_priv->fbc.crtc;
> > +	struct drm_framebuffer *fb = crtc->base.primary->fb;
> > +	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
> > +	uint32_t val;
> > +
> > +	/* Although the documentation suggests we can't change
> > DPFC_CONTROL
> > +	 * while compression is enabled, the hardware guys said
> > that updating
> > +	 * the fence register bits during a flip is fine. */
> > +	val = I915_READ(DPFC_CONTROL);
> > +	val &= ~DPFC_CTL_FENCE_MASK;
> > +	val |= obj->fence_reg;
> > +	I915_WRITE(DPFC_CONTROL, val);
> > +}
> > +
> >  static void g4x_fbc_disable(struct drm_i915_private *dev_priv)
> >  {
> >  	u32 dpfc_ctl;
> > @@ -236,6 +268,31 @@ static void ilk_fbc_enable(struct intel_crtc
> > *crtc)
> >  	DRM_DEBUG_KMS("enabled fbc on plane %c\n",
> > plane_name(crtc->plane));
> >  }
> >  
> > +static void ilk_fbc_flip_prepare(struct drm_i915_private
> > *dev_priv)
> > +{
> > +	struct intel_crtc *crtc = dev_priv->fbc.crtc;
> > +	struct drm_framebuffer *fb = crtc->base.primary->fb;
> > +	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
> > +	uint32_t val;
> > +
> > +	/* Although the documentation suggests we can't change
> > DPFC_CONTROL
> > +	 * while compression is enabled, the hardware guys said
> > that updating
> > +	 * the fence register bits during a flip is fine. */
> > +	val = I915_READ(ILK_DPFC_CONTROL);
> > +	val &= ~ILK_DPFC_FENCE_MASK;
> > +	val |= obj->fence_reg;
> > +	I915_WRITE(ILK_DPFC_CONTROL, val);
> > +}
> > +
> > +static void snb_fbc_flip_prepare(struct drm_i915_private
> > *dev_priv)
> > +{
> > +	struct intel_crtc *crtc = dev_priv->fbc.crtc;
> > +	struct drm_framebuffer *fb = crtc->base.primary->fb;
> > +	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
> > +
> > +	I915_WRITE(SNB_DPFC_CTL_SA, SNB_CPU_FENCE_ENABLE | obj-
> > >fence_reg);
> > +}
> > +
> >  static void ilk_fbc_disable(struct drm_i915_private *dev_priv)
> >  {
> >  	u32 dpfc_ctl;
> > @@ -1021,13 +1078,48 @@ void intel_fbc_flush(struct
> > drm_i915_private *dev_priv,
> >  	if (origin == ORIGIN_GTT)
> >  		return;
> >  
> > +	/* Hardware tracking already recompresses the CFB (nuke)
> > for us if FBC
> > +	 * is enabled and we do a page flip, so we can safely
> > ignore it here.
> > +	 * FBC may be disabled in case we got an invalidate()
> > before the
> > +	 * flush(), so we'll still have to check that case below.
> > */
> > +	if (origin == ORIGIN_FLIP && dev_priv->fbc.enabled)
> > +		return;
> > +
> >  	mutex_lock(&dev_priv->fbc.lock);
> >  
> >  	dev_priv->fbc.busy_bits &= ~frontbuffer_bits;
> >  
> >  	if (!dev_priv->fbc.busy_bits) {
> > -		__intel_fbc_disable(dev_priv);
> > -		__intel_fbc_update(dev_priv);
> > +		if (origin == ORIGIN_FLIP) {
> > +			__intel_fbc_update(dev_priv);
> > +		} else {
> > +			__intel_fbc_disable(dev_priv);
> > +			__intel_fbc_update(dev_priv);
> > +		}
> > +	}
> > +
> > +	mutex_unlock(&dev_priv->fbc.lock);
> > +}
> > +
> > +void intel_fbc_flip_prepare(struct drm_i915_private *dev_priv,
> > +			    unsigned int frontbuffer_bits)
> > +{
> > +	unsigned int fbc_bits;
> > +
> > +	if (!fbc_supported(dev_priv))
> > +		return;
> > +
> > +	mutex_lock(&dev_priv->fbc.lock);
> > +
> > +	if (dev_priv->fbc.enabled) {
> > +		fbc_bits = INTEL_FRONTBUFFER_PRIMARY(dev_priv-
> > >fbc.crtc->pipe);
> 
> primary->frontbuffer_bit would seem better.

Why?

> 
> > +		if (fbc_bits & frontbuffer_bits)
> > +			dev_priv->fbc.flip_prepare(dev_priv);
> 
> You would still have to disable+reenable if you need to eg.
> reallocate
> the compressed buffer, of if the new fb isn't suitable for fbc, or
> maybe
> if you need to change anything else in the control register.

Yes, but as far as I understand the frontbuffer tracking, this case
won't happen here. I'm assuming we'll always go through
intel_fbc_update() on these cases.

> 
> What I had was:
> "
> static bool intel_fbc_need_reinit(struct intel_crtc *crtc)
> {
> 	struct drm_i915_private *dev_priv = crtc->base.dev-
> >dev_private;
> 	struct drm_framebuffer *fb = crtc->base.primary->fb;
> 	struct drm_i915_gem_object *obj = to_intel_framebuffer(fb)-
> >obj;
> 
> 	return crtc != dev_priv->fbc.crtc ||
> 	       obj->base.size > dev_priv->fbc.size ||
> 	       drm_format_plane_cpp(fb->pixel_format, 0) !=
> 	       drm_format_plane_cpp(dev_priv->fbc.pixel_format, 0) ||
> 	       fb->pitches[0] != dev_priv->fbc.pitch;
> }
> intel_fbc_pre_page_flip()
> {
> 	...
> 	intel_fbc_update_pending_score(crtc);
> 
> 	/*
> 	 * If fbc was already possible we can update immediately,
> 	 * otherwise we will wait until the flip is finished.
> 	 */
> 	if (crtc->fbc.score != 0)
> 		crtc->fbc.score = crtc->fbc.pending_score;
> 
> 	/*
> 	 * Disable fbc if we're not (yet) capable, or if
> 	 * we just need a full disable+enable reinit.
> 	 */
> 	if (crtc->fbc.score == 0 || intel_fbc_need_reinit(crtc))
> 		__intel_fbc_disable(crtc);
> 	...
> }
> "
> 
> > +	} else if (dev_priv->fbc.fbc_work) {
> > +		fbc_bits = INTEL_FRONTBUFFER_PRIMARY(
> > +				dev_priv->fbc.fbc_work->crtc-
> > >pipe);
> > +		if (fbc_bits & frontbuffer_bits)
> > +			__intel_fbc_disable(dev_priv);
> >  	}
> >  
> >  	mutex_unlock(&dev_priv->fbc.lock);
> > @@ -1063,18 +1155,25 @@ void intel_fbc_init(struct drm_i915_private
> > *dev_priv)
> >  		dev_priv->fbc.fbc_enabled = ilk_fbc_enabled;
> >  		dev_priv->fbc.enable_fbc = gen7_fbc_enable;
> >  		dev_priv->fbc.disable_fbc = ilk_fbc_disable;
> > +		dev_priv->fbc.flip_prepare = snb_fbc_flip_prepare;
> >  	} else if (INTEL_INFO(dev_priv)->gen >= 5) {
> >  		dev_priv->fbc.fbc_enabled = ilk_fbc_enabled;
> >  		dev_priv->fbc.enable_fbc = ilk_fbc_enable;
> >  		dev_priv->fbc.disable_fbc = ilk_fbc_disable;
> > +		if (INTEL_INFO(dev_priv)->gen == 5)
> > +			dev_priv->fbc.flip_prepare =
> > ilk_fbc_flip_prepare;
> > +		else
> > +			dev_priv->fbc.flip_prepare =
> > snb_fbc_flip_prepare;
> >  	} else if (IS_GM45(dev_priv)) {
> >  		dev_priv->fbc.fbc_enabled = g4x_fbc_enabled;
> >  		dev_priv->fbc.enable_fbc = g4x_fbc_enable;
> >  		dev_priv->fbc.disable_fbc = g4x_fbc_disable;
> > +		dev_priv->fbc.flip_prepare = g4x_fbc_flip_prepare;
> >  	} else {
> >  		dev_priv->fbc.fbc_enabled = i8xx_fbc_enabled;
> >  		dev_priv->fbc.enable_fbc = i8xx_fbc_enable;
> >  		dev_priv->fbc.disable_fbc = i8xx_fbc_disable;
> > +		dev_priv->fbc.flip_prepare =
> > i8xx_fbc_flip_prepare;
> >  
> >  		/* This value was pulled out of someone's hat */
> >  		I915_WRITE(FBC_CONTROL, 500 <<
> > FBC_CTL_INTERVAL_SHIFT);
> > diff --git a/drivers/gpu/drm/i915/intel_frontbuffer.c
> > b/drivers/gpu/drm/i915/intel_frontbuffer.c
> > index ac85357..31a1ad3 100644
> > --- a/drivers/gpu/drm/i915/intel_frontbuffer.c
> > +++ b/drivers/gpu/drm/i915/intel_frontbuffer.c
> > @@ -192,6 +192,7 @@ void intel_frontbuffer_flip_prepare(struct
> > drm_device *dev,
> >  	mutex_unlock(&dev_priv->fb_tracking.lock);
> >  
> >  	intel_psr_single_frame_update(dev, frontbuffer_bits);
> > +	intel_fbc_flip_prepare(dev_priv, frontbuffer_bits);
> >  }
> >  
> >  /**
> > -- 
> > 2.6.1
> > 
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 02/26] drm/i915: don't stop+start FBC at every flip
  2015-10-27 19:50   ` Chris Wilson
@ 2015-10-28 16:58     ` Zanoni, Paulo R
  0 siblings, 0 replies; 44+ messages in thread
From: Zanoni, Paulo R @ 2015-10-28 16:58 UTC (permalink / raw)
  To: chris@chris-wilson.co.uk; +Cc: intel-gfx@lists.freedesktop.org

Em Ter, 2015-10-27 às 19:50 +0000, Chris Wilson escreveu:
> On Tue, Oct 27, 2015 at 02:50:04PM -0200, Paulo Zanoni wrote:
> > @@ -1021,13 +1078,48 @@ void intel_fbc_flush(struct
> > drm_i915_private *dev_priv,
> >  	if (origin == ORIGIN_GTT)
> >  		return;
> >  
> > +	/* Hardware tracking already recompresses the CFB (nuke)
> > for us if FBC
> > +	 * is enabled and we do a page flip, so we can safely
> > ignore it here.
> > +	 * FBC may be disabled in case we got an invalidate()
> > before the
> > +	 * flush(), so we'll still have to check that case below.
> > */
> 
> I feel like I understand what is going on a bit better now, thanks!
> 
> > +	if (origin == ORIGIN_FLIP && dev_priv->fbc.enabled)
> > +		return;
> > +
> >  	mutex_lock(&dev_priv->fbc.lock);
> >  
> >  	dev_priv->fbc.busy_bits &= ~frontbuffer_bits;
> >  
> >  	if (!dev_priv->fbc.busy_bits) {
> > -		__intel_fbc_disable(dev_priv);
> > -		__intel_fbc_update(dev_priv);
> > +		if (origin == ORIGIN_FLIP) {
> 
> Note this test here is redundant.
> 
> We know that for an origin == FLIP to be here, FBC is disabled and
> calling intel_fbc_disable() is then a no-op.
> 
> So it turns out that the origin two lines of disable(); update()
> works
> just as well. Or is there some later patch that tweaks this branch
> further?

Right, you commented about this on the patch that is currently 04/26 an
I only fixed it there.

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

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 02/26] drm/i915: don't stop+start FBC at every flip
  2015-10-28 16:56     ` Zanoni, Paulo R
@ 2015-10-28 17:20       ` Ville Syrjälä
  2015-10-29 12:05         ` Maarten Lankhorst
  2015-10-29 17:30         ` Ville Syrjälä
  0 siblings, 2 replies; 44+ messages in thread
From: Ville Syrjälä @ 2015-10-28 17:20 UTC (permalink / raw)
  To: Zanoni, Paulo R; +Cc: intel-gfx@lists.freedesktop.org

On Wed, Oct 28, 2015 at 04:56:39PM +0000, Zanoni, Paulo R wrote:
> Em Ter, 2015-10-27 às 20:32 +0200, Ville Syrjälä escreveu:
> > On Tue, Oct 27, 2015 at 02:50:04PM -0200, Paulo Zanoni wrote:
> > > The hardware already takes care of disabling and recompressing FBC
> > > when we do a page flip, so all we need to do is to update the fence
> > > registers and move on.
> > > 
> > > One of the important things to notice is that on the pre-gen6
> > > platforms the fence is programmed on the FBC control register and
> > > the
> > > documentation says we can't update the control register while FBC
> > > is
> > > enabled. This would basically mean we'd have to to disable+enable
> > > FBC
> > > at every flip in order to make sure the hardware tracking still
> > > works,
> > > which doesn't seem to make too much sense. So I sent an email to
> > > the
> > > hardware team requesting some clarification. The information I got
> > > was
> > > this:
> > > 
> > > "I don't think any hardware is latching on to 0x100100, 0x100104,
> > > or
> > > the old fence number in FBC_CTL. Instructions against changing on
> > > the
> > > fly would be to simplify testing and ensure you don't miss any
> > > invalidation that happened right at that time."
> > > 
> > > So I guess we're fine for flips. But I can't really say I tested
> > > FBC
> > > on these ancient platforms - nor that I'll ever propose enabling
> > > FBC
> > > by default on them exactly because of problems like these.
> > 
> > Yeah, I did this in my patches too, and IIRC it seemed to work just
> > fine
> > back then.
> > 
> > > 
> > > v2: Add comment at flush() (Chris).
> > > 
> > > Testcase: igt/kms_frontbuffer_tracking/fbc*-fliptrack
> > > Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> > > ---
> > >  drivers/gpu/drm/i915/i915_drv.h          |   1 +
> > >  drivers/gpu/drm/i915/i915_reg.h          |   3 +
> > >  drivers/gpu/drm/i915/intel_display.c     |   1 -
> > >  drivers/gpu/drm/i915/intel_drv.h         |   2 +
> > >  drivers/gpu/drm/i915/intel_fbc.c         | 103
> > > ++++++++++++++++++++++++++++++-
> > >  drivers/gpu/drm/i915/intel_frontbuffer.c |   1 +
> > >  6 files changed, 108 insertions(+), 3 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/i915/i915_drv.h
> > > b/drivers/gpu/drm/i915/i915_drv.h
> > > index ee14962..77da500 100644
> > > --- a/drivers/gpu/drm/i915/i915_drv.h
> > > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > > @@ -928,6 +928,7 @@ struct i915_fbc {
> > >  	bool (*fbc_enabled)(struct drm_i915_private *dev_priv);
> > >  	void (*enable_fbc)(struct intel_crtc *crtc);
> > >  	void (*disable_fbc)(struct drm_i915_private *dev_priv);
> > > +	void (*flip_prepare)(struct drm_i915_private *dev_priv);
> > >  };
> > >  
> > >  /**
> > > diff --git a/drivers/gpu/drm/i915/i915_reg.h
> > > b/drivers/gpu/drm/i915/i915_reg.h
> > > index 8942532..3d598a2 100644
> > > --- a/drivers/gpu/drm/i915/i915_reg.h
> > > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > > @@ -2028,6 +2028,7 @@ enum skl_disp_power_wells {
> > >  #define   FBC_CTL_C3_IDLE	(1<<13)
> > >  #define   FBC_CTL_STRIDE_SHIFT	(5)
> > >  #define   FBC_CTL_FENCENO_SHIFT	(0)
> > > +#define   FBC_CTL_FENCENO_MASK	0xF
> > 
> > It's only three bits on gen2. But bit 3 is MBZ and there are only 8
> > fence registers on those platforms, so this is OK.
> > 
> > >  #define FBC_COMMAND		0x0320c
> > >  #define   FBC_CMD_COMPRESS	(1<<0)
> > >  #define FBC_STATUS		0x03210
> > > @@ -2064,6 +2065,7 @@ enum skl_disp_power_wells {
> > >  #define   DPFC_CTL_LIMIT_1X	(0<<6)
> > >  #define   DPFC_CTL_LIMIT_2X	(1<<6)
> > >  #define   DPFC_CTL_LIMIT_4X	(2<<6)
> > > +#define   DPFC_CTL_FENCE_MASK	0xF
> > >  #define DPFC_RECOMP_CTL		0x320c
> > >  #define   DPFC_RECOMP_STALL_EN	(1<<27)
> > >  #define   DPFC_RECOMP_STALL_WM_SHIFT (16)
> > > @@ -2086,6 +2088,7 @@ enum skl_disp_power_wells {
> > >  #define   FBC_CTL_FALSE_COLOR	(1<<10)
> > >  /* The bit 28-8 is reserved */
> > >  #define   DPFC_RESERVED		(0x1FFFFF00)
> > > +#define   ILK_DPFC_FENCE_MASK	0xF
> > >  #define ILK_DPFC_RECOMP_CTL	0x4320c
> > >  #define ILK_DPFC_STATUS		0x43210
> > >  #define ILK_DPFC_FENCE_YOFF	0x43218
> > > diff --git a/drivers/gpu/drm/i915/intel_display.c
> > > b/drivers/gpu/drm/i915/intel_display.c
> > > index bc1907e..d9378c3 100644
> > > --- a/drivers/gpu/drm/i915/intel_display.c
> > > +++ b/drivers/gpu/drm/i915/intel_display.c
> > > @@ -11502,7 +11502,6 @@ static int intel_crtc_page_flip(struct
> > > drm_crtc *crtc,
> > >  			  to_intel_plane(primary)-
> > > >frontbuffer_bit);
> > >  	mutex_unlock(&dev->struct_mutex);
> > >  
> > > -	intel_fbc_disable_crtc(intel_crtc);
> > >  	intel_frontbuffer_flip_prepare(dev,
> > >  				       to_intel_plane(primary)-
> > > >frontbuffer_bit);
> > >  
> > > diff --git a/drivers/gpu/drm/i915/intel_drv.h
> > > b/drivers/gpu/drm/i915/intel_drv.h
> > > index 08847d0..9065a8f 100644
> > > --- a/drivers/gpu/drm/i915/intel_drv.h
> > > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > > @@ -1305,6 +1305,8 @@ void intel_fbc_invalidate(struct
> > > drm_i915_private *dev_priv,
> > >  			  enum fb_op_origin origin);
> > >  void intel_fbc_flush(struct drm_i915_private *dev_priv,
> > >  		     unsigned int frontbuffer_bits, enum
> > > fb_op_origin origin);
> > > +void intel_fbc_flip_prepare(struct drm_i915_private *dev_priv,
> > > +			    unsigned int frontbuffer_bits);
> > >  void intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv);
> > >  
> > >  /* intel_hdmi.c */
> > > diff --git a/drivers/gpu/drm/i915/intel_fbc.c
> > > b/drivers/gpu/drm/i915/intel_fbc.c
> > > index d9d7e54..62f158b 100644
> > > --- a/drivers/gpu/drm/i915/intel_fbc.c
> > > +++ b/drivers/gpu/drm/i915/intel_fbc.c
> > > @@ -82,6 +82,22 @@ static void i8xx_fbc_disable(struct
> > > drm_i915_private *dev_priv)
> > >  	DRM_DEBUG_KMS("disabled FBC\n");
> > >  }
> > >  
> > > +static void i8xx_fbc_flip_prepare(struct drm_i915_private
> > > *dev_priv)
> > > +{
> > > +	struct intel_crtc *crtc = dev_priv->fbc.crtc;
> > > +	struct drm_framebuffer *fb = crtc->base.primary->fb;
> > > +	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
> > > +	uint32_t val;
> > > +
> > > +	/* Although the documentation suggests we can't change
> > > DPFC_CONTROL
> > > +	 * while compression is enabled, the hardware guys said
> > > that updating
> > > +	 * the fence register bits during a flip is fine. */
> > > +	val = I915_READ(FBC_CONTROL);
> > > +	val &= ~FBC_CTL_FENCENO_MASK;
> > > +	val |= obj->fence_reg;
> > > +	I915_WRITE(FBC_CONTROL, val);
> > > +}
> > 
> > IIRC I just called the enable function to reconstruct the entire
> > register contents to avoid code duplication. But maybe that's not
> > possible without reowrking the fbc state handling entirely
> > (which I had done).
> > > +
> > >  static void i8xx_fbc_enable(struct intel_crtc *crtc)
> > >  {
> > >  	struct drm_i915_private *dev_priv = crtc->base.dev-
> > > >dev_private;
> > > @@ -161,6 +177,22 @@ static void g4x_fbc_enable(struct intel_crtc
> > > *crtc)
> > >  	DRM_DEBUG_KMS("enabled fbc on plane %c\n",
> > > plane_name(crtc->plane));
> > >  }
> > >  
> > > +static void g4x_fbc_flip_prepare(struct drm_i915_private
> > > *dev_priv)
> > > +{
> > > +	struct intel_crtc *crtc = dev_priv->fbc.crtc;
> > > +	struct drm_framebuffer *fb = crtc->base.primary->fb;
> > > +	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
> > > +	uint32_t val;
> > > +
> > > +	/* Although the documentation suggests we can't change
> > > DPFC_CONTROL
> > > +	 * while compression is enabled, the hardware guys said
> > > that updating
> > > +	 * the fence register bits during a flip is fine. */
> > > +	val = I915_READ(DPFC_CONTROL);
> > > +	val &= ~DPFC_CTL_FENCE_MASK;
> > > +	val |= obj->fence_reg;
> > > +	I915_WRITE(DPFC_CONTROL, val);
> > > +}
> > > +
> > >  static void g4x_fbc_disable(struct drm_i915_private *dev_priv)
> > >  {
> > >  	u32 dpfc_ctl;
> > > @@ -236,6 +268,31 @@ static void ilk_fbc_enable(struct intel_crtc
> > > *crtc)
> > >  	DRM_DEBUG_KMS("enabled fbc on plane %c\n",
> > > plane_name(crtc->plane));
> > >  }
> > >  
> > > +static void ilk_fbc_flip_prepare(struct drm_i915_private
> > > *dev_priv)
> > > +{
> > > +	struct intel_crtc *crtc = dev_priv->fbc.crtc;
> > > +	struct drm_framebuffer *fb = crtc->base.primary->fb;
> > > +	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
> > > +	uint32_t val;
> > > +
> > > +	/* Although the documentation suggests we can't change
> > > DPFC_CONTROL
> > > +	 * while compression is enabled, the hardware guys said
> > > that updating
> > > +	 * the fence register bits during a flip is fine. */
> > > +	val = I915_READ(ILK_DPFC_CONTROL);
> > > +	val &= ~ILK_DPFC_FENCE_MASK;
> > > +	val |= obj->fence_reg;
> > > +	I915_WRITE(ILK_DPFC_CONTROL, val);
> > > +}
> > > +
> > > +static void snb_fbc_flip_prepare(struct drm_i915_private
> > > *dev_priv)
> > > +{
> > > +	struct intel_crtc *crtc = dev_priv->fbc.crtc;
> > > +	struct drm_framebuffer *fb = crtc->base.primary->fb;
> > > +	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
> > > +
> > > +	I915_WRITE(SNB_DPFC_CTL_SA, SNB_CPU_FENCE_ENABLE | obj-
> > > >fence_reg);
> > > +}
> > > +
> > >  static void ilk_fbc_disable(struct drm_i915_private *dev_priv)
> > >  {
> > >  	u32 dpfc_ctl;
> > > @@ -1021,13 +1078,48 @@ void intel_fbc_flush(struct
> > > drm_i915_private *dev_priv,
> > >  	if (origin == ORIGIN_GTT)
> > >  		return;
> > >  
> > > +	/* Hardware tracking already recompresses the CFB (nuke)
> > > for us if FBC
> > > +	 * is enabled and we do a page flip, so we can safely
> > > ignore it here.
> > > +	 * FBC may be disabled in case we got an invalidate()
> > > before the
> > > +	 * flush(), so we'll still have to check that case below.
> > > */
> > > +	if (origin == ORIGIN_FLIP && dev_priv->fbc.enabled)
> > > +		return;
> > > +
> > >  	mutex_lock(&dev_priv->fbc.lock);
> > >  
> > >  	dev_priv->fbc.busy_bits &= ~frontbuffer_bits;
> > >  
> > >  	if (!dev_priv->fbc.busy_bits) {
> > > -		__intel_fbc_disable(dev_priv);
> > > -		__intel_fbc_update(dev_priv);
> > > +		if (origin == ORIGIN_FLIP) {
> > > +			__intel_fbc_update(dev_priv);
> > > +		} else {
> > > +			__intel_fbc_disable(dev_priv);
> > > +			__intel_fbc_update(dev_priv);
> > > +		}
> > > +	}
> > > +
> > > +	mutex_unlock(&dev_priv->fbc.lock);
> > > +}
> > > +
> > > +void intel_fbc_flip_prepare(struct drm_i915_private *dev_priv,
> > > +			    unsigned int frontbuffer_bits)
> > > +{
> > > +	unsigned int fbc_bits;
> > > +
> > > +	if (!fbc_supported(dev_priv))
> > > +		return;
> > > +
> > > +	mutex_lock(&dev_priv->fbc.lock);
> > > +
> > > +	if (dev_priv->fbc.enabled) {
> > > +		fbc_bits = INTEL_FRONTBUFFER_PRIMARY(dev_priv-
> > > >fbc.crtc->pipe);
> > 
> > primary->frontbuffer_bit would seem better.
> 
> Why?

Why not? It's there already stashed away for you to use. No need to
sprinkle these INTEL_FRONTBUFFER... things all over the place.

> 
> > 
> > > +		if (fbc_bits & frontbuffer_bits)
> > > +			dev_priv->fbc.flip_prepare(dev_priv);
> > 
> > You would still have to disable+reenable if you need to eg.
> > reallocate
> > the compressed buffer, of if the new fb isn't suitable for fbc, or
> > maybe
> > if you need to change anything else in the control register.
> 
> Yes, but as far as I understand the frontbuffer tracking, this case
> won't happen here. I'm assuming we'll always go through
> intel_fbc_update() on these cases.

Perhaps, but more by luck than by design. With the setplane and atomic
APIs there's no difference between a page flip and other plane updates.
So if you want to take advantage of the hw flip nuke, you would need to
check how the plane state is going to change, and based on that decide
whether a fence update is enough or disable+re-enable is needed. And in
fact I don't see any fbc_disable before the flip, just an fbc_update
after the fact. So seems to me the disable really should be in your
flip_prepare hook in this case. And in fact the whole flip_prepare
thing isn't even called from the setplane/atomic path.

> 
> > 
> > What I had was:
> > "
> > static bool intel_fbc_need_reinit(struct intel_crtc *crtc)
> > {
> > 	struct drm_i915_private *dev_priv = crtc->base.dev-
> > >dev_private;
> > 	struct drm_framebuffer *fb = crtc->base.primary->fb;
> > 	struct drm_i915_gem_object *obj = to_intel_framebuffer(fb)-
> > >obj;
> > 
> > 	return crtc != dev_priv->fbc.crtc ||
> > 	       obj->base.size > dev_priv->fbc.size ||
> > 	       drm_format_plane_cpp(fb->pixel_format, 0) !=
> > 	       drm_format_plane_cpp(dev_priv->fbc.pixel_format, 0) ||
> > 	       fb->pitches[0] != dev_priv->fbc.pitch;
> > }
> > intel_fbc_pre_page_flip()
> > {
> > 	...
> > 	intel_fbc_update_pending_score(crtc);
> > 
> > 	/*
> > 	 * If fbc was already possible we can update immediately,
> > 	 * otherwise we will wait until the flip is finished.
> > 	 */
> > 	if (crtc->fbc.score != 0)
> > 		crtc->fbc.score = crtc->fbc.pending_score;
> > 
> > 	/*
> > 	 * Disable fbc if we're not (yet) capable, or if
> > 	 * we just need a full disable+enable reinit.
> > 	 */
> > 	if (crtc->fbc.score == 0 || intel_fbc_need_reinit(crtc))
> > 		__intel_fbc_disable(crtc);
> > 	...
> > }
> > "
> > 
> > > +	} else if (dev_priv->fbc.fbc_work) {
> > > +		fbc_bits = INTEL_FRONTBUFFER_PRIMARY(
> > > +				dev_priv->fbc.fbc_work->crtc-
> > > >pipe);
> > > +		if (fbc_bits & frontbuffer_bits)
> > > +			__intel_fbc_disable(dev_priv);
> > >  	}
> > >  
> > >  	mutex_unlock(&dev_priv->fbc.lock);
> > > @@ -1063,18 +1155,25 @@ void intel_fbc_init(struct drm_i915_private
> > > *dev_priv)
> > >  		dev_priv->fbc.fbc_enabled = ilk_fbc_enabled;
> > >  		dev_priv->fbc.enable_fbc = gen7_fbc_enable;
> > >  		dev_priv->fbc.disable_fbc = ilk_fbc_disable;
> > > +		dev_priv->fbc.flip_prepare = snb_fbc_flip_prepare;
> > >  	} else if (INTEL_INFO(dev_priv)->gen >= 5) {
> > >  		dev_priv->fbc.fbc_enabled = ilk_fbc_enabled;
> > >  		dev_priv->fbc.enable_fbc = ilk_fbc_enable;
> > >  		dev_priv->fbc.disable_fbc = ilk_fbc_disable;
> > > +		if (INTEL_INFO(dev_priv)->gen == 5)
> > > +			dev_priv->fbc.flip_prepare =
> > > ilk_fbc_flip_prepare;
> > > +		else
> > > +			dev_priv->fbc.flip_prepare =
> > > snb_fbc_flip_prepare;
> > >  	} else if (IS_GM45(dev_priv)) {
> > >  		dev_priv->fbc.fbc_enabled = g4x_fbc_enabled;
> > >  		dev_priv->fbc.enable_fbc = g4x_fbc_enable;
> > >  		dev_priv->fbc.disable_fbc = g4x_fbc_disable;
> > > +		dev_priv->fbc.flip_prepare = g4x_fbc_flip_prepare;
> > >  	} else {
> > >  		dev_priv->fbc.fbc_enabled = i8xx_fbc_enabled;
> > >  		dev_priv->fbc.enable_fbc = i8xx_fbc_enable;
> > >  		dev_priv->fbc.disable_fbc = i8xx_fbc_disable;
> > > +		dev_priv->fbc.flip_prepare =
> > > i8xx_fbc_flip_prepare;
> > >  
> > >  		/* This value was pulled out of someone's hat */
> > >  		I915_WRITE(FBC_CONTROL, 500 <<
> > > FBC_CTL_INTERVAL_SHIFT);
> > > diff --git a/drivers/gpu/drm/i915/intel_frontbuffer.c
> > > b/drivers/gpu/drm/i915/intel_frontbuffer.c
> > > index ac85357..31a1ad3 100644
> > > --- a/drivers/gpu/drm/i915/intel_frontbuffer.c
> > > +++ b/drivers/gpu/drm/i915/intel_frontbuffer.c
> > > @@ -192,6 +192,7 @@ void intel_frontbuffer_flip_prepare(struct
> > > drm_device *dev,
> > >  	mutex_unlock(&dev_priv->fb_tracking.lock);
> > >  
> > >  	intel_psr_single_frame_update(dev, frontbuffer_bits);
> > > +	intel_fbc_flip_prepare(dev_priv, frontbuffer_bits);
> > >  }
> > >  
> > >  /**
> > > -- 
> > > 2.6.1
> > > 
> > > _______________________________________________
> > > Intel-gfx mailing list
> > > Intel-gfx@lists.freedesktop.org
> > > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> > 

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 23/26] drm/i915: use a single intel_fbc_work struct
  2015-10-27 20:29   ` Chris Wilson
@ 2015-10-28 17:24     ` Zanoni, Paulo R
  2015-10-28 17:40       ` chris
  0 siblings, 1 reply; 44+ messages in thread
From: Zanoni, Paulo R @ 2015-10-28 17:24 UTC (permalink / raw)
  To: chris@chris-wilson.co.uk; +Cc: intel-gfx@lists.freedesktop.org

Em Ter, 2015-10-27 às 20:29 +0000, Chris Wilson escreveu:
> On Tue, Oct 27, 2015 at 02:50:25PM -0200, Paulo Zanoni wrote:
> > diff --git a/drivers/gpu/drm/i915/i915_drv.h
> > b/drivers/gpu/drm/i915/i915_drv.h
> > index a9434d1..fdbe068 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.h
> > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > @@ -917,9 +917,11 @@ struct i915_fbc {
> >  	bool active;
> >  
> >  	struct intel_fbc_work {
> > -		struct delayed_work work;
> > +		bool scheduled;
> 
> Ah, I found this confusingly named. scheduled implied to me that you
> wanted work_pending(), but you just want to asynchronously cancel the
> fbc worker. Just bool cancel? Or bool active? Though now I've come
> full
> circle and suggest bool scheduled. So

I agree 'bool scheduled' is not the perfect name. I thought about
renaming it to 'bool cancel' many times. I'm willing to change in case
someone requests it, but my understanding is that the paragraph above
is not asking for a rename.

> 
> /* Track whether the FBC worker has already been queued,
>  * or asynchronously cancel the worker whilst it waits
>  * before activation.
>  */

I can add this, although if someone suggests a better name we may not
need it :)

> 
> What happens then if we quickly queue, cancel and want to requeue?
> The
> schedule_work() fails as the task is already pending, but the
> scheduled
> flag gets reset, so it just works. Perfect.

/me is confused.

This case should work since everything is done with fbc.lock grabbed.


> > +		struct work_struct work;
> >  		struct drm_framebuffer *fb;
> 
> Hmm, don't we actually need to take references on the fb we schedule
> for
> activation? Since we already account for that the crtc->fb may be
> changed between queuing the work and executing it, for extra paranoia
> we
> should ensure that we have a reference in work->fb. (long standing
> bug,
> might as well fix it before we see it in the wild, time for another
> kms-flip race!)

I'm not super familiar with this area, so I have to ask: what bad
things can happen if we don't have a reference on work->fb?

We're just comparing pointers here, so if work->fb is not referenced by
the CRTC we won't do anything with it. If work->fb is referenced by the
CRTC, it will already have a reference, right?

I'm also not 100% sure if it's even possible to have crtc->fb != work-
>fb without anything else canceling the work thread, so I just kept the
old code around for now.

> 
> I think I've covered the basic issues with changing the type of
> worker
> and it looks fine,
> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
> -Chris

Thanks!

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

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 23/26] drm/i915: use a single intel_fbc_work struct
  2015-10-28 17:24     ` Zanoni, Paulo R
@ 2015-10-28 17:40       ` chris
  0 siblings, 0 replies; 44+ messages in thread
From: chris @ 2015-10-28 17:40 UTC (permalink / raw)
  To: Zanoni, Paulo R; +Cc: intel-gfx@lists.freedesktop.org

On Wed, Oct 28, 2015 at 05:24:18PM +0000, Zanoni, Paulo R wrote:
> Em Ter, 2015-10-27 às 20:29 +0000, Chris Wilson escreveu:
> > On Tue, Oct 27, 2015 at 02:50:25PM -0200, Paulo Zanoni wrote:
> > > diff --git a/drivers/gpu/drm/i915/i915_drv.h
> > > b/drivers/gpu/drm/i915/i915_drv.h
> > > index a9434d1..fdbe068 100644
> > > --- a/drivers/gpu/drm/i915/i915_drv.h
> > > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > > @@ -917,9 +917,11 @@ struct i915_fbc {
> > >  	bool active;
> > >  
> > >  	struct intel_fbc_work {
> > > -		struct delayed_work work;
> > > +		bool scheduled;
> > 
> > Ah, I found this confusingly named. scheduled implied to me that you
> > wanted work_pending(), but you just want to asynchronously cancel the
> > fbc worker. Just bool cancel? Or bool active? Though now I've come
> > full
> > circle and suggest bool scheduled. So
> 
> I agree 'bool scheduled' is not the perfect name. I thought about
> renaming it to 'bool cancel' many times. I'm willing to change in case
> someone requests it, but my understanding is that the paragraph above
> is not asking for a rename.
> 
> > 
> > /* Track whether the FBC worker has already been queued,
> >  * or asynchronously cancel the worker whilst it waits
> >  * before activation.
> >  */
> 
> I can add this, although if someone suggests a better name we may not
> need it :)

Even if we do rename the variable, we might as well keep the comment. I
think it's a reasonably succinct description of why that bool should
exist.

> > 
> > What happens then if we quickly queue, cancel and want to requeue?
> > The
> > schedule_work() fails as the task is already pending, but the
> > scheduled
> > flag gets reset, so it just works. Perfect.
> 
> /me is confused.
> 
> This case should work since everything is done with fbc.lock grabbed.

I was just thinking about the case where the bool scheduled=false but
the work was still queued, and you then wanted to reschedule it. It
works just fine, the original work item remains queued and gets
reactivated correctly

(I was trying to find a flaw in the code and decided that it wasn't a
flaw at all, at which point I was happy!)
 
> 
> > > +		struct work_struct work;
> > >  		struct drm_framebuffer *fb;
> > 
> > Hmm, don't we actually need to take references on the fb we schedule
> > for
> > activation? Since we already account for that the crtc->fb may be
> > changed between queuing the work and executing it, for extra paranoia
> > we
> > should ensure that we have a reference in work->fb. (long standing
> > bug,
> > might as well fix it before we see it in the wild, time for another
> > kms-flip race!)
> 
> I'm not super familiar with this area, so I have to ask: what bad
> things can happen if we don't have a reference on work->fb?

The worst depends on the locking - if we borrow the reference and
operate on work->fb == crtc->fb without the right lock, that can blow
up. Otherwise, as just use work->fb as a pointer, it is possible for the
fb to unref'ed and reallocated without us noticing and for us to then
incorrectly schedule the fbc (unless you can demonstrate that the
work->fb is guarded by the fbc.lock + bool scheduled).

> We're just comparing pointers here, so if work->fb is not referenced by
> the CRTC we won't do anything with it. If work->fb is referenced by the
> CRTC, it will already have a reference, right?
> 
> I'm also not 100% sure if it's even possible to have crtc->fb != work-
> >fb without anything else canceling the work thread, so I just kept the
> old code around for now.

Indeed, I'm not sure if it is possible but (a) we should check that we
do have sufficient locks to prevent crtc->fb disappearing, and (b)
verify that when crtc->fb is changed the work is cancelled. As a bonus,
document that work->fb is just a pointer whose validity is guarded by
bool scheduled (or whatever). Or even better, having just completed (a)
+ (b), you can drop the drm_framebuffer pointer from the work item
entirely and rely on crtc->fb.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 02/26] drm/i915: don't stop+start FBC at every flip
  2015-10-28 17:20       ` Ville Syrjälä
@ 2015-10-29 12:05         ` Maarten Lankhorst
  2015-10-29 17:30         ` Ville Syrjälä
  1 sibling, 0 replies; 44+ messages in thread
From: Maarten Lankhorst @ 2015-10-29 12:05 UTC (permalink / raw)
  To: Ville Syrjälä, Zanoni, Paulo R; +Cc: intel-gfx@lists.freedesktop.org

Op 28-10-15 om 18:20 schreef Ville Syrjälä:
> On Wed, Oct 28, 2015 at 04:56:39PM +0000, Zanoni, Paulo R wrote:
>> Em Ter, 2015-10-27 às 20:32 +0200, Ville Syrjälä escreveu:
>>> On Tue, Oct 27, 2015 at 02:50:04PM -0200, Paulo Zanoni wrote:
>>>> The hardware already takes care of disabling and recompressing FBC
>>>> when we do a page flip, so all we need to do is to update the fence
>>>> registers and move on.
>>>>
>>>> One of the important things to notice is that on the pre-gen6
>>>> platforms the fence is programmed on the FBC control register and
>>>> the
>>>> documentation says we can't update the control register while FBC
>>>> is
>>>> enabled. This would basically mean we'd have to to disable+enable
>>>> FBC
>>>> at every flip in order to make sure the hardware tracking still
>>>> works,
>>>> which doesn't seem to make too much sense. So I sent an email to
>>>> the
>>>> hardware team requesting some clarification. The information I got
>>>> was
>>>> this:
>>>>
>>>> "I don't think any hardware is latching on to 0x100100, 0x100104,
>>>> or
>>>> the old fence number in FBC_CTL. Instructions against changing on
>>>> the
>>>> fly would be to simplify testing and ensure you don't miss any
>>>> invalidation that happened right at that time."
>>>>
>>>> So I guess we're fine for flips. But I can't really say I tested
>>>> FBC
>>>> on these ancient platforms - nor that I'll ever propose enabling
>>>> FBC
>>>> by default on them exactly because of problems like these.
>>> Yeah, I did this in my patches too, and IIRC it seemed to work just
>>> fine
>>> back then.
>>>
>>>> v2: Add comment at flush() (Chris).
>>>>
>>>> Testcase: igt/kms_frontbuffer_tracking/fbc*-fliptrack
>>>> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
>>>> ---
>>>>  drivers/gpu/drm/i915/i915_drv.h          |   1 +
>>>>  drivers/gpu/drm/i915/i915_reg.h          |   3 +
>>>>  drivers/gpu/drm/i915/intel_display.c     |   1 -
>>>>  drivers/gpu/drm/i915/intel_drv.h         |   2 +
>>>>  drivers/gpu/drm/i915/intel_fbc.c         | 103
>>>> ++++++++++++++++++++++++++++++-
>>>>  drivers/gpu/drm/i915/intel_frontbuffer.c |   1 +
>>>>  6 files changed, 108 insertions(+), 3 deletions(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/i915/i915_drv.h
>>>> b/drivers/gpu/drm/i915/i915_drv.h
>>>> index ee14962..77da500 100644
>>>> --- a/drivers/gpu/drm/i915/i915_drv.h
>>>> +++ b/drivers/gpu/drm/i915/i915_drv.h
>>>> @@ -928,6 +928,7 @@ struct i915_fbc {
>>>>  	bool (*fbc_enabled)(struct drm_i915_private *dev_priv);
>>>>  	void (*enable_fbc)(struct intel_crtc *crtc);
>>>>  	void (*disable_fbc)(struct drm_i915_private *dev_priv);
>>>> +	void (*flip_prepare)(struct drm_i915_private *dev_priv);
>>>>  };
>>>>  
>>>>  /**
>>>> diff --git a/drivers/gpu/drm/i915/i915_reg.h
>>>> b/drivers/gpu/drm/i915/i915_reg.h
>>>> index 8942532..3d598a2 100644
>>>> --- a/drivers/gpu/drm/i915/i915_reg.h
>>>> +++ b/drivers/gpu/drm/i915/i915_reg.h
>>>> @@ -2028,6 +2028,7 @@ enum skl_disp_power_wells {
>>>>  #define   FBC_CTL_C3_IDLE	(1<<13)
>>>>  #define   FBC_CTL_STRIDE_SHIFT	(5)
>>>>  #define   FBC_CTL_FENCENO_SHIFT	(0)
>>>> +#define   FBC_CTL_FENCENO_MASK	0xF
>>> It's only three bits on gen2. But bit 3 is MBZ and there are only 8
>>> fence registers on those platforms, so this is OK.
>>>
>>>>  #define FBC_COMMAND		0x0320c
>>>>  #define   FBC_CMD_COMPRESS	(1<<0)
>>>>  #define FBC_STATUS		0x03210
>>>> @@ -2064,6 +2065,7 @@ enum skl_disp_power_wells {
>>>>  #define   DPFC_CTL_LIMIT_1X	(0<<6)
>>>>  #define   DPFC_CTL_LIMIT_2X	(1<<6)
>>>>  #define   DPFC_CTL_LIMIT_4X	(2<<6)
>>>> +#define   DPFC_CTL_FENCE_MASK	0xF
>>>>  #define DPFC_RECOMP_CTL		0x320c
>>>>  #define   DPFC_RECOMP_STALL_EN	(1<<27)
>>>>  #define   DPFC_RECOMP_STALL_WM_SHIFT (16)
>>>> @@ -2086,6 +2088,7 @@ enum skl_disp_power_wells {
>>>>  #define   FBC_CTL_FALSE_COLOR	(1<<10)
>>>>  /* The bit 28-8 is reserved */
>>>>  #define   DPFC_RESERVED		(0x1FFFFF00)
>>>> +#define   ILK_DPFC_FENCE_MASK	0xF
>>>>  #define ILK_DPFC_RECOMP_CTL	0x4320c
>>>>  #define ILK_DPFC_STATUS		0x43210
>>>>  #define ILK_DPFC_FENCE_YOFF	0x43218
>>>> diff --git a/drivers/gpu/drm/i915/intel_display.c
>>>> b/drivers/gpu/drm/i915/intel_display.c
>>>> index bc1907e..d9378c3 100644
>>>> --- a/drivers/gpu/drm/i915/intel_display.c
>>>> +++ b/drivers/gpu/drm/i915/intel_display.c
>>>> @@ -11502,7 +11502,6 @@ static int intel_crtc_page_flip(struct
>>>> drm_crtc *crtc,
>>>>  			  to_intel_plane(primary)-
>>>>> frontbuffer_bit);
>>>>  	mutex_unlock(&dev->struct_mutex);
>>>>  
>>>> -	intel_fbc_disable_crtc(intel_crtc);
>>>>  	intel_frontbuffer_flip_prepare(dev,
>>>>  				       to_intel_plane(primary)-
>>>>> frontbuffer_bit);
>>>>  
>>>> diff --git a/drivers/gpu/drm/i915/intel_drv.h
>>>> b/drivers/gpu/drm/i915/intel_drv.h
>>>> index 08847d0..9065a8f 100644
>>>> --- a/drivers/gpu/drm/i915/intel_drv.h
>>>> +++ b/drivers/gpu/drm/i915/intel_drv.h
>>>> @@ -1305,6 +1305,8 @@ void intel_fbc_invalidate(struct
>>>> drm_i915_private *dev_priv,
>>>>  			  enum fb_op_origin origin);
>>>>  void intel_fbc_flush(struct drm_i915_private *dev_priv,
>>>>  		     unsigned int frontbuffer_bits, enum
>>>> fb_op_origin origin);
>>>> +void intel_fbc_flip_prepare(struct drm_i915_private *dev_priv,
>>>> +			    unsigned int frontbuffer_bits);
>>>>  void intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv);
>>>>  
>>>>  /* intel_hdmi.c */
>>>> diff --git a/drivers/gpu/drm/i915/intel_fbc.c
>>>> b/drivers/gpu/drm/i915/intel_fbc.c
>>>> index d9d7e54..62f158b 100644
>>>> --- a/drivers/gpu/drm/i915/intel_fbc.c
>>>> +++ b/drivers/gpu/drm/i915/intel_fbc.c
>>>> @@ -82,6 +82,22 @@ static void i8xx_fbc_disable(struct
>>>> drm_i915_private *dev_priv)
>>>>  	DRM_DEBUG_KMS("disabled FBC\n");
>>>>  }
>>>>  
>>>> +static void i8xx_fbc_flip_prepare(struct drm_i915_private
>>>> *dev_priv)
>>>> +{
>>>> +	struct intel_crtc *crtc = dev_priv->fbc.crtc;
>>>> +	struct drm_framebuffer *fb = crtc->base.primary->fb;
>>>> +	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
>>>> +	uint32_t val;
>>>> +
>>>> +	/* Although the documentation suggests we can't change
>>>> DPFC_CONTROL
>>>> +	 * while compression is enabled, the hardware guys said
>>>> that updating
>>>> +	 * the fence register bits during a flip is fine. */
>>>> +	val = I915_READ(FBC_CONTROL);
>>>> +	val &= ~FBC_CTL_FENCENO_MASK;
>>>> +	val |= obj->fence_reg;
>>>> +	I915_WRITE(FBC_CONTROL, val);
>>>> +}
>>> IIRC I just called the enable function to reconstruct the entire
>>> register contents to avoid code duplication. But maybe that's not
>>> possible without reowrking the fbc state handling entirely
>>> (which I had done).
>>>> +
>>>>  static void i8xx_fbc_enable(struct intel_crtc *crtc)
>>>>  {
>>>>  	struct drm_i915_private *dev_priv = crtc->base.dev-
>>>>> dev_private;
>>>> @@ -161,6 +177,22 @@ static void g4x_fbc_enable(struct intel_crtc
>>>> *crtc)
>>>>  	DRM_DEBUG_KMS("enabled fbc on plane %c\n",
>>>> plane_name(crtc->plane));
>>>>  }
>>>>  
>>>> +static void g4x_fbc_flip_prepare(struct drm_i915_private
>>>> *dev_priv)
>>>> +{
>>>> +	struct intel_crtc *crtc = dev_priv->fbc.crtc;
>>>> +	struct drm_framebuffer *fb = crtc->base.primary->fb;
>>>> +	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
>>>> +	uint32_t val;
>>>> +
>>>> +	/* Although the documentation suggests we can't change
>>>> DPFC_CONTROL
>>>> +	 * while compression is enabled, the hardware guys said
>>>> that updating
>>>> +	 * the fence register bits during a flip is fine. */
>>>> +	val = I915_READ(DPFC_CONTROL);
>>>> +	val &= ~DPFC_CTL_FENCE_MASK;
>>>> +	val |= obj->fence_reg;
>>>> +	I915_WRITE(DPFC_CONTROL, val);
>>>> +}
>>>> +
>>>>  static void g4x_fbc_disable(struct drm_i915_private *dev_priv)
>>>>  {
>>>>  	u32 dpfc_ctl;
>>>> @@ -236,6 +268,31 @@ static void ilk_fbc_enable(struct intel_crtc
>>>> *crtc)
>>>>  	DRM_DEBUG_KMS("enabled fbc on plane %c\n",
>>>> plane_name(crtc->plane));
>>>>  }
>>>>  
>>>> +static void ilk_fbc_flip_prepare(struct drm_i915_private
>>>> *dev_priv)
>>>> +{
>>>> +	struct intel_crtc *crtc = dev_priv->fbc.crtc;
>>>> +	struct drm_framebuffer *fb = crtc->base.primary->fb;
>>>> +	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
>>>> +	uint32_t val;
>>>> +
>>>> +	/* Although the documentation suggests we can't change
>>>> DPFC_CONTROL
>>>> +	 * while compression is enabled, the hardware guys said
>>>> that updating
>>>> +	 * the fence register bits during a flip is fine. */
>>>> +	val = I915_READ(ILK_DPFC_CONTROL);
>>>> +	val &= ~ILK_DPFC_FENCE_MASK;
>>>> +	val |= obj->fence_reg;
>>>> +	I915_WRITE(ILK_DPFC_CONTROL, val);
>>>> +}
>>>> +
>>>> +static void snb_fbc_flip_prepare(struct drm_i915_private
>>>> *dev_priv)
>>>> +{
>>>> +	struct intel_crtc *crtc = dev_priv->fbc.crtc;
>>>> +	struct drm_framebuffer *fb = crtc->base.primary->fb;
>>>> +	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
>>>> +
>>>> +	I915_WRITE(SNB_DPFC_CTL_SA, SNB_CPU_FENCE_ENABLE | obj-
>>>>> fence_reg);
>>>> +}
>>>> +
>>>>  static void ilk_fbc_disable(struct drm_i915_private *dev_priv)
>>>>  {
>>>>  	u32 dpfc_ctl;
>>>> @@ -1021,13 +1078,48 @@ void intel_fbc_flush(struct
>>>> drm_i915_private *dev_priv,
>>>>  	if (origin == ORIGIN_GTT)
>>>>  		return;
>>>>  
>>>> +	/* Hardware tracking already recompresses the CFB (nuke)
>>>> for us if FBC
>>>> +	 * is enabled and we do a page flip, so we can safely
>>>> ignore it here.
>>>> +	 * FBC may be disabled in case we got an invalidate()
>>>> before the
>>>> +	 * flush(), so we'll still have to check that case below.
>>>> */
>>>> +	if (origin == ORIGIN_FLIP && dev_priv->fbc.enabled)
>>>> +		return;
>>>> +
>>>>  	mutex_lock(&dev_priv->fbc.lock);
>>>>  
>>>>  	dev_priv->fbc.busy_bits &= ~frontbuffer_bits;
>>>>  
>>>>  	if (!dev_priv->fbc.busy_bits) {
>>>> -		__intel_fbc_disable(dev_priv);
>>>> -		__intel_fbc_update(dev_priv);
>>>> +		if (origin == ORIGIN_FLIP) {
>>>> +			__intel_fbc_update(dev_priv);
>>>> +		} else {
>>>> +			__intel_fbc_disable(dev_priv);
>>>> +			__intel_fbc_update(dev_priv);
>>>> +		}
>>>> +	}
>>>> +
>>>> +	mutex_unlock(&dev_priv->fbc.lock);
>>>> +}
>>>> +
>>>> +void intel_fbc_flip_prepare(struct drm_i915_private *dev_priv,
>>>> +			    unsigned int frontbuffer_bits)
>>>> +{
>>>> +	unsigned int fbc_bits;
>>>> +
>>>> +	if (!fbc_supported(dev_priv))
>>>> +		return;
>>>> +
>>>> +	mutex_lock(&dev_priv->fbc.lock);
>>>> +
>>>> +	if (dev_priv->fbc.enabled) {
>>>> +		fbc_bits = INTEL_FRONTBUFFER_PRIMARY(dev_priv-
>>>>> fbc.crtc->pipe);
>>> primary->frontbuffer_bit would seem better.
>> Why?
> Why not? It's there already stashed away for you to use. No need to
> sprinkle these INTEL_FRONTBUFFER... things all over the place.
>
>>>> +		if (fbc_bits & frontbuffer_bits)
>>>> +			dev_priv->fbc.flip_prepare(dev_priv);
>>> You would still have to disable+reenable if you need to eg.
>>> reallocate
>>> the compressed buffer, of if the new fb isn't suitable for fbc, or
>>> maybe
>>> if you need to change anything else in the control register.
>> Yes, but as far as I understand the frontbuffer tracking, this case
>> won't happen here. I'm assuming we'll always go through
>> intel_fbc_update() on these cases.
> Perhaps, but more by luck than by design. With the setplane and atomic
> APIs there's no difference between a page flip and other plane updates.
> So if you want to take advantage of the hw flip nuke, you would need to
> check how the plane state is going to change, and based on that decide
> whether a fence update is enough or disable+re-enable is needed. And in
> fact I don't see any fbc_disable before the flip, just an fbc_update
> after the fact. So seems to me the disable really should be in your
> flip_prepare hook in this case. And in fact the whole flip_prepare
> thing isn't even called from the setplane/atomic path.
I'm working on fixing that, but that still requires a few more patches until page_flip and atomic_commit are unified. :-)

If it's useful we could do a simple patch to do the same in atomic commit. I'm moving fb_bits to crtc_state anyway.

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

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 05/26] drm/i915: extract fbc_on_pipe_a_only()
  2015-10-27 16:50 ` [PATCH 05/26] drm/i915: extract fbc_on_pipe_a_only() Paulo Zanoni
@ 2015-10-29 12:05   ` Maarten Lankhorst
  2015-10-29 15:55     ` Zanoni, Paulo R
  0 siblings, 1 reply; 44+ messages in thread
From: Maarten Lankhorst @ 2015-10-29 12:05 UTC (permalink / raw)
  To: Paulo Zanoni, intel-gfx

Op 27-10-15 om 17:50 schreef Paulo Zanoni:
> Make the code easier to read.
>
> Suggested-by: Chris Wilson <chris@chris-wilson.co.uk>
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_fbc.c | 13 +++++++------
>  1 file changed, 7 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
> index 7d8e996..4d6ebc7 100644
> --- a/drivers/gpu/drm/i915/intel_fbc.c
> +++ b/drivers/gpu/drm/i915/intel_fbc.c
> @@ -46,6 +46,11 @@ static inline bool fbc_supported(struct drm_i915_private *dev_priv)
>  	return dev_priv->fbc.enable_fbc != NULL;
>  }
>  
> +static inline bool fbc_on_pipe_a_only(struct drm_i915_private *dev_priv)
> +{
> +	return IS_HASWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 8;
> +}
This check is duplicated in __intel_fbc_update, which also seems to say < gen4 doesn't support it but that's not mentioned here.

I would say use possible_framebuffer_bits and remove this extra check here in the future.

I'll probably rework this later though, so this is fine with me for now.
>  /*
>   * In some platforms where the CRTC's x:0/y:0 coordinates doesn't match the
>   * frontbuffer's x:0/y:0 coordinates we lie to the hardware about the plane's
> @@ -543,10 +548,6 @@ static struct drm_crtc *intel_fbc_find_crtc(struct drm_i915_private *dev_priv)
>  {
>  	struct drm_crtc *crtc = NULL, *tmp_crtc;
>  	enum pipe pipe;
> -	bool pipe_a_only = false;
> -
> -	if (IS_HASWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 8)
> -		pipe_a_only = true;
>  
>  	for_each_pipe(dev_priv, pipe) {
>  		tmp_crtc = dev_priv->pipe_to_crtc_mapping[pipe];
> @@ -555,7 +556,7 @@ static struct drm_crtc *intel_fbc_find_crtc(struct drm_i915_private *dev_priv)
>  		    to_intel_plane_state(tmp_crtc->primary->state)->visible)
>  			crtc = tmp_crtc;
>  
> -		if (pipe_a_only)
> +		if (fbc_on_pipe_a_only(dev_priv))
>  			break;
>  	}
>  
> @@ -1146,7 +1147,7 @@ void intel_fbc_init(struct drm_i915_private *dev_priv)
>  		dev_priv->fbc.possible_framebuffer_bits |=
>  				INTEL_FRONTBUFFER_PRIMARY(pipe);
>  
> -		if (IS_HASWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 8)
> +		if (fbc_on_pipe_a_only(dev_priv))
>  			break;
>  	}
>  

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

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 19/26] drm/i915: move adjusted_mode checks from fbc_update to fbc_enable
  2015-10-27 16:50 ` [PATCH 19/26] drm/i915: move adjusted_mode checks from fbc_update to fbc_enable Paulo Zanoni
@ 2015-10-29 12:59   ` Maarten Lankhorst
  2015-10-29 17:58     ` Zanoni, Paulo R
  0 siblings, 1 reply; 44+ messages in thread
From: Maarten Lankhorst @ 2015-10-29 12:59 UTC (permalink / raw)
  To: Paulo Zanoni, intel-gfx

Op 27-10-15 om 17:50 schreef Paulo Zanoni:
> These things can't change without a full modeset.
False! Fastset can update parameters too. Although I don't think it currently prevents DBLSCAN updates,
so maybe make sure cfb enable/disable is called when updating pipe too?
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_fbc.c | 16 ++++++++--------
>  1 file changed, 8 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
> index 0ba25b9..6aa9af8 100644
> --- a/drivers/gpu/drm/i915/intel_fbc.c
> +++ b/drivers/gpu/drm/i915/intel_fbc.c
> @@ -825,7 +825,6 @@ static void __intel_fbc_update(struct intel_crtc *crtc)
>  	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
>  	struct drm_framebuffer *fb;
>  	struct drm_i915_gem_object *obj;
> -	const struct drm_display_mode *adjusted_mode;
>  
>  	WARN_ON(!mutex_is_locked(&dev_priv->fbc.lock));
>  
> @@ -844,13 +843,6 @@ static void __intel_fbc_update(struct intel_crtc *crtc)
>  
>  	fb = crtc->base.primary->fb;
>  	obj = intel_fb_obj(fb);
> -	adjusted_mode = &crtc->config->base.adjusted_mode;
> -
> -	if ((adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) ||
> -	    (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)) {
> -		set_no_fbc_reason(dev_priv, "incompatible mode");
> -		goto out_disable;
> -	}
>  
>  	if (!intel_fbc_hw_tracking_covers_screen(crtc)) {
>  		set_no_fbc_reason(dev_priv, "mode too large for compression");
> @@ -1076,6 +1068,8 @@ void intel_fbc_flip_prepare(struct drm_i915_private *dev_priv,
>  void intel_fbc_enable(struct intel_crtc *crtc)
>  {
>  	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
> +	const struct drm_display_mode *adjusted_mode =
> +					&crtc->config->base.adjusted_mode;
>  
>  	if (!fbc_supported(dev_priv))
>  		return;
> @@ -1110,6 +1104,12 @@ void intel_fbc_enable(struct intel_crtc *crtc)
>  		goto out;
>  	}
>  
> +	if ((adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) ||
> +	    (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)) {
> +		set_no_fbc_reason(dev_priv, "incompatible mode");
> +		goto out;
> +	}
> +
>  	if (intel_fbc_alloc_cfb(crtc)) {
>  		set_no_fbc_reason(dev_priv, "not enough stolen memory");
>  		goto out;

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

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 05/26] drm/i915: extract fbc_on_pipe_a_only()
  2015-10-29 12:05   ` Maarten Lankhorst
@ 2015-10-29 15:55     ` Zanoni, Paulo R
  0 siblings, 0 replies; 44+ messages in thread
From: Zanoni, Paulo R @ 2015-10-29 15:55 UTC (permalink / raw)
  To: intel-gfx@lists.freedesktop.org,
	maarten.lankhorst@linux.intel.com

Em Qui, 2015-10-29 às 13:05 +0100, Maarten Lankhorst escreveu:
> Op 27-10-15 om 17:50 schreef Paulo Zanoni:
> > Make the code easier to read.
> > 
> > Suggested-by: Chris Wilson <chris@chris-wilson.co.uk>
> > Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_fbc.c | 13 +++++++------
> >  1 file changed, 7 insertions(+), 6 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_fbc.c
> > b/drivers/gpu/drm/i915/intel_fbc.c
> > index 7d8e996..4d6ebc7 100644
> > --- a/drivers/gpu/drm/i915/intel_fbc.c
> > +++ b/drivers/gpu/drm/i915/intel_fbc.c
> > @@ -46,6 +46,11 @@ static inline bool fbc_supported(struct
> > drm_i915_private *dev_priv)
> >  	return dev_priv->fbc.enable_fbc != NULL;
> >  }
> >  
> > +static inline bool fbc_on_pipe_a_only(struct drm_i915_private
> > *dev_priv)
> > +{
> > +	return IS_HASWELL(dev_priv) || INTEL_INFO(dev_priv)->gen
> > >= 8;
> > +}
> This check is duplicated in __intel_fbc_update, which also seems to
> say < gen4 doesn't support it but that's not mentioned here.
> 
> I would say use possible_framebuffer_bits and remove this extra check
> here in the future.


Pipes != planes on gen < 4. I think your suggestion is related to patch
21/26

> 
> I'll probably rework this later though, so this is fine with me for
> now.
> >  /*
> >   * In some platforms where the CRTC's x:0/y:0 coordinates doesn't
> > match the
> >   * frontbuffer's x:0/y:0 coordinates we lie to the hardware about
> > the plane's
> > @@ -543,10 +548,6 @@ static struct drm_crtc
> > *intel_fbc_find_crtc(struct drm_i915_private *dev_priv)
> >  {
> >  	struct drm_crtc *crtc = NULL, *tmp_crtc;
> >  	enum pipe pipe;
> > -	bool pipe_a_only = false;
> > -
> > -	if (IS_HASWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >=
> > 8)
> > -		pipe_a_only = true;
> >  
> >  	for_each_pipe(dev_priv, pipe) {
> >  		tmp_crtc = dev_priv->pipe_to_crtc_mapping[pipe];
> > @@ -555,7 +556,7 @@ static struct drm_crtc
> > *intel_fbc_find_crtc(struct drm_i915_private *dev_priv)
> >  		    to_intel_plane_state(tmp_crtc->primary-
> > >state)->visible)
> >  			crtc = tmp_crtc;
> >  
> > -		if (pipe_a_only)
> > +		if (fbc_on_pipe_a_only(dev_priv))
> >  			break;
> >  	}
> >  
> > @@ -1146,7 +1147,7 @@ void intel_fbc_init(struct drm_i915_private
> > *dev_priv)
> >  		dev_priv->fbc.possible_framebuffer_bits |=
> >  				INTEL_FRONTBUFFER_PRIMARY(pipe);
> >  
> > -		if (IS_HASWELL(dev_priv) || INTEL_INFO(dev_priv)-
> > >gen >= 8)
> > +		if (fbc_on_pipe_a_only(dev_priv))
> >  			break;
> >  	}
> >  
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 02/26] drm/i915: don't stop+start FBC at every flip
  2015-10-28 17:20       ` Ville Syrjälä
  2015-10-29 12:05         ` Maarten Lankhorst
@ 2015-10-29 17:30         ` Ville Syrjälä
  2015-10-29 17:52           ` Zanoni, Paulo R
  1 sibling, 1 reply; 44+ messages in thread
From: Ville Syrjälä @ 2015-10-29 17:30 UTC (permalink / raw)
  To: Zanoni, Paulo R; +Cc: intel-gfx@lists.freedesktop.org

On Wed, Oct 28, 2015 at 07:20:12PM +0200, Ville Syrjälä wrote:
> On Wed, Oct 28, 2015 at 04:56:39PM +0000, Zanoni, Paulo R wrote:
> > Em Ter, 2015-10-27 às 20:32 +0200, Ville Syrjälä escreveu:
> > > On Tue, Oct 27, 2015 at 02:50:04PM -0200, Paulo Zanoni wrote:
> > > > The hardware already takes care of disabling and recompressing FBC
> > > > when we do a page flip, so all we need to do is to update the fence
> > > > registers and move on.
> > > > 
> > > > One of the important things to notice is that on the pre-gen6
> > > > platforms the fence is programmed on the FBC control register and
> > > > the
> > > > documentation says we can't update the control register while FBC
> > > > is
> > > > enabled. This would basically mean we'd have to to disable+enable
> > > > FBC
> > > > at every flip in order to make sure the hardware tracking still
> > > > works,
> > > > which doesn't seem to make too much sense. So I sent an email to
> > > > the
> > > > hardware team requesting some clarification. The information I got
> > > > was
> > > > this:
> > > > 
> > > > "I don't think any hardware is latching on to 0x100100, 0x100104,
> > > > or
> > > > the old fence number in FBC_CTL. Instructions against changing on
> > > > the
> > > > fly would be to simplify testing and ensure you don't miss any
> > > > invalidation that happened right at that time."
> > > > 
> > > > So I guess we're fine for flips. But I can't really say I tested
> > > > FBC
> > > > on these ancient platforms - nor that I'll ever propose enabling
> > > > FBC
> > > > by default on them exactly because of problems like these.
> > > 
> > > Yeah, I did this in my patches too, and IIRC it seemed to work just
> > > fine
> > > back then.
> > > 
> > > > 
> > > > v2: Add comment at flush() (Chris).
> > > > 
> > > > Testcase: igt/kms_frontbuffer_tracking/fbc*-fliptrack
> > > > Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> > > > ---
> > > >  drivers/gpu/drm/i915/i915_drv.h          |   1 +
> > > >  drivers/gpu/drm/i915/i915_reg.h          |   3 +
> > > >  drivers/gpu/drm/i915/intel_display.c     |   1 -
> > > >  drivers/gpu/drm/i915/intel_drv.h         |   2 +
> > > >  drivers/gpu/drm/i915/intel_fbc.c         | 103
> > > > ++++++++++++++++++++++++++++++-
> > > >  drivers/gpu/drm/i915/intel_frontbuffer.c |   1 +
> > > >  6 files changed, 108 insertions(+), 3 deletions(-)
> > > > 
> > > > diff --git a/drivers/gpu/drm/i915/i915_drv.h
> > > > b/drivers/gpu/drm/i915/i915_drv.h
> > > > index ee14962..77da500 100644
> > > > --- a/drivers/gpu/drm/i915/i915_drv.h
> > > > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > > > @@ -928,6 +928,7 @@ struct i915_fbc {
> > > >  	bool (*fbc_enabled)(struct drm_i915_private *dev_priv);
> > > >  	void (*enable_fbc)(struct intel_crtc *crtc);
> > > >  	void (*disable_fbc)(struct drm_i915_private *dev_priv);
> > > > +	void (*flip_prepare)(struct drm_i915_private *dev_priv);
> > > >  };
> > > >  
> > > >  /**
> > > > diff --git a/drivers/gpu/drm/i915/i915_reg.h
> > > > b/drivers/gpu/drm/i915/i915_reg.h
> > > > index 8942532..3d598a2 100644
> > > > --- a/drivers/gpu/drm/i915/i915_reg.h
> > > > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > > > @@ -2028,6 +2028,7 @@ enum skl_disp_power_wells {
> > > >  #define   FBC_CTL_C3_IDLE	(1<<13)
> > > >  #define   FBC_CTL_STRIDE_SHIFT	(5)
> > > >  #define   FBC_CTL_FENCENO_SHIFT	(0)
> > > > +#define   FBC_CTL_FENCENO_MASK	0xF
> > > 
> > > It's only three bits on gen2. But bit 3 is MBZ and there are only 8
> > > fence registers on those platforms, so this is OK.
> > > 
> > > >  #define FBC_COMMAND		0x0320c
> > > >  #define   FBC_CMD_COMPRESS	(1<<0)
> > > >  #define FBC_STATUS		0x03210
> > > > @@ -2064,6 +2065,7 @@ enum skl_disp_power_wells {
> > > >  #define   DPFC_CTL_LIMIT_1X	(0<<6)
> > > >  #define   DPFC_CTL_LIMIT_2X	(1<<6)
> > > >  #define   DPFC_CTL_LIMIT_4X	(2<<6)
> > > > +#define   DPFC_CTL_FENCE_MASK	0xF
> > > >  #define DPFC_RECOMP_CTL		0x320c
> > > >  #define   DPFC_RECOMP_STALL_EN	(1<<27)
> > > >  #define   DPFC_RECOMP_STALL_WM_SHIFT (16)
> > > > @@ -2086,6 +2088,7 @@ enum skl_disp_power_wells {
> > > >  #define   FBC_CTL_FALSE_COLOR	(1<<10)
> > > >  /* The bit 28-8 is reserved */
> > > >  #define   DPFC_RESERVED		(0x1FFFFF00)
> > > > +#define   ILK_DPFC_FENCE_MASK	0xF
> > > >  #define ILK_DPFC_RECOMP_CTL	0x4320c
> > > >  #define ILK_DPFC_STATUS		0x43210
> > > >  #define ILK_DPFC_FENCE_YOFF	0x43218
> > > > diff --git a/drivers/gpu/drm/i915/intel_display.c
> > > > b/drivers/gpu/drm/i915/intel_display.c
> > > > index bc1907e..d9378c3 100644
> > > > --- a/drivers/gpu/drm/i915/intel_display.c
> > > > +++ b/drivers/gpu/drm/i915/intel_display.c
> > > > @@ -11502,7 +11502,6 @@ static int intel_crtc_page_flip(struct
> > > > drm_crtc *crtc,
> > > >  			  to_intel_plane(primary)-
> > > > >frontbuffer_bit);
> > > >  	mutex_unlock(&dev->struct_mutex);
> > > >  
> > > > -	intel_fbc_disable_crtc(intel_crtc);
> > > >  	intel_frontbuffer_flip_prepare(dev,
> > > >  				       to_intel_plane(primary)-
> > > > >frontbuffer_bit);
> > > >  
> > > > diff --git a/drivers/gpu/drm/i915/intel_drv.h
> > > > b/drivers/gpu/drm/i915/intel_drv.h
> > > > index 08847d0..9065a8f 100644
> > > > --- a/drivers/gpu/drm/i915/intel_drv.h
> > > > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > > > @@ -1305,6 +1305,8 @@ void intel_fbc_invalidate(struct
> > > > drm_i915_private *dev_priv,
> > > >  			  enum fb_op_origin origin);
> > > >  void intel_fbc_flush(struct drm_i915_private *dev_priv,
> > > >  		     unsigned int frontbuffer_bits, enum
> > > > fb_op_origin origin);
> > > > +void intel_fbc_flip_prepare(struct drm_i915_private *dev_priv,
> > > > +			    unsigned int frontbuffer_bits);
> > > >  void intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv);
> > > >  
> > > >  /* intel_hdmi.c */
> > > > diff --git a/drivers/gpu/drm/i915/intel_fbc.c
> > > > b/drivers/gpu/drm/i915/intel_fbc.c
> > > > index d9d7e54..62f158b 100644
> > > > --- a/drivers/gpu/drm/i915/intel_fbc.c
> > > > +++ b/drivers/gpu/drm/i915/intel_fbc.c
> > > > @@ -82,6 +82,22 @@ static void i8xx_fbc_disable(struct
> > > > drm_i915_private *dev_priv)
> > > >  	DRM_DEBUG_KMS("disabled FBC\n");
> > > >  }
> > > >  
> > > > +static void i8xx_fbc_flip_prepare(struct drm_i915_private
> > > > *dev_priv)
> > > > +{
> > > > +	struct intel_crtc *crtc = dev_priv->fbc.crtc;
> > > > +	struct drm_framebuffer *fb = crtc->base.primary->fb;
> > > > +	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
> > > > +	uint32_t val;
> > > > +
> > > > +	/* Although the documentation suggests we can't change
> > > > DPFC_CONTROL
> > > > +	 * while compression is enabled, the hardware guys said
> > > > that updating
> > > > +	 * the fence register bits during a flip is fine. */
> > > > +	val = I915_READ(FBC_CONTROL);
> > > > +	val &= ~FBC_CTL_FENCENO_MASK;
> > > > +	val |= obj->fence_reg;
> > > > +	I915_WRITE(FBC_CONTROL, val);
> > > > +}
> > > 
> > > IIRC I just called the enable function to reconstruct the entire
> > > register contents to avoid code duplication. But maybe that's not
> > > possible without reowrking the fbc state handling entirely
> > > (which I had done).
> > > > +
> > > >  static void i8xx_fbc_enable(struct intel_crtc *crtc)
> > > >  {
> > > >  	struct drm_i915_private *dev_priv = crtc->base.dev-
> > > > >dev_private;
> > > > @@ -161,6 +177,22 @@ static void g4x_fbc_enable(struct intel_crtc
> > > > *crtc)
> > > >  	DRM_DEBUG_KMS("enabled fbc on plane %c\n",
> > > > plane_name(crtc->plane));
> > > >  }
> > > >  
> > > > +static void g4x_fbc_flip_prepare(struct drm_i915_private
> > > > *dev_priv)
> > > > +{
> > > > +	struct intel_crtc *crtc = dev_priv->fbc.crtc;
> > > > +	struct drm_framebuffer *fb = crtc->base.primary->fb;
> > > > +	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
> > > > +	uint32_t val;
> > > > +
> > > > +	/* Although the documentation suggests we can't change
> > > > DPFC_CONTROL
> > > > +	 * while compression is enabled, the hardware guys said
> > > > that updating
> > > > +	 * the fence register bits during a flip is fine. */
> > > > +	val = I915_READ(DPFC_CONTROL);
> > > > +	val &= ~DPFC_CTL_FENCE_MASK;
> > > > +	val |= obj->fence_reg;
> > > > +	I915_WRITE(DPFC_CONTROL, val);
> > > > +}
> > > > +
> > > >  static void g4x_fbc_disable(struct drm_i915_private *dev_priv)
> > > >  {
> > > >  	u32 dpfc_ctl;
> > > > @@ -236,6 +268,31 @@ static void ilk_fbc_enable(struct intel_crtc
> > > > *crtc)
> > > >  	DRM_DEBUG_KMS("enabled fbc on plane %c\n",
> > > > plane_name(crtc->plane));
> > > >  }
> > > >  
> > > > +static void ilk_fbc_flip_prepare(struct drm_i915_private
> > > > *dev_priv)
> > > > +{
> > > > +	struct intel_crtc *crtc = dev_priv->fbc.crtc;
> > > > +	struct drm_framebuffer *fb = crtc->base.primary->fb;
> > > > +	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
> > > > +	uint32_t val;
> > > > +
> > > > +	/* Although the documentation suggests we can't change
> > > > DPFC_CONTROL
> > > > +	 * while compression is enabled, the hardware guys said
> > > > that updating
> > > > +	 * the fence register bits during a flip is fine. */
> > > > +	val = I915_READ(ILK_DPFC_CONTROL);
> > > > +	val &= ~ILK_DPFC_FENCE_MASK;
> > > > +	val |= obj->fence_reg;
> > > > +	I915_WRITE(ILK_DPFC_CONTROL, val);
> > > > +}
> > > > +
> > > > +static void snb_fbc_flip_prepare(struct drm_i915_private
> > > > *dev_priv)
> > > > +{
> > > > +	struct intel_crtc *crtc = dev_priv->fbc.crtc;
> > > > +	struct drm_framebuffer *fb = crtc->base.primary->fb;
> > > > +	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
> > > > +
> > > > +	I915_WRITE(SNB_DPFC_CTL_SA, SNB_CPU_FENCE_ENABLE | obj-
> > > > >fence_reg);
> > > > +}
> > > > +
> > > >  static void ilk_fbc_disable(struct drm_i915_private *dev_priv)
> > > >  {
> > > >  	u32 dpfc_ctl;
> > > > @@ -1021,13 +1078,48 @@ void intel_fbc_flush(struct
> > > > drm_i915_private *dev_priv,
> > > >  	if (origin == ORIGIN_GTT)
> > > >  		return;
> > > >  
> > > > +	/* Hardware tracking already recompresses the CFB (nuke)
> > > > for us if FBC
> > > > +	 * is enabled and we do a page flip, so we can safely
> > > > ignore it here.
> > > > +	 * FBC may be disabled in case we got an invalidate()
> > > > before the
> > > > +	 * flush(), so we'll still have to check that case below.
> > > > */
> > > > +	if (origin == ORIGIN_FLIP && dev_priv->fbc.enabled)
> > > > +		return;
> > > > +
> > > >  	mutex_lock(&dev_priv->fbc.lock);
> > > >  
> > > >  	dev_priv->fbc.busy_bits &= ~frontbuffer_bits;
> > > >  
> > > >  	if (!dev_priv->fbc.busy_bits) {
> > > > -		__intel_fbc_disable(dev_priv);
> > > > -		__intel_fbc_update(dev_priv);
> > > > +		if (origin == ORIGIN_FLIP) {
> > > > +			__intel_fbc_update(dev_priv);
> > > > +		} else {
> > > > +			__intel_fbc_disable(dev_priv);
> > > > +			__intel_fbc_update(dev_priv);
> > > > +		}
> > > > +	}
> > > > +
> > > > +	mutex_unlock(&dev_priv->fbc.lock);
> > > > +}
> > > > +
> > > > +void intel_fbc_flip_prepare(struct drm_i915_private *dev_priv,
> > > > +			    unsigned int frontbuffer_bits)
> > > > +{
> > > > +	unsigned int fbc_bits;
> > > > +
> > > > +	if (!fbc_supported(dev_priv))
> > > > +		return;
> > > > +
> > > > +	mutex_lock(&dev_priv->fbc.lock);
> > > > +
> > > > +	if (dev_priv->fbc.enabled) {
> > > > +		fbc_bits = INTEL_FRONTBUFFER_PRIMARY(dev_priv-
> > > > >fbc.crtc->pipe);
> > > 
> > > primary->frontbuffer_bit would seem better.
> > 
> > Why?
> 
> Why not? It's there already stashed away for you to use. No need to
> sprinkle these INTEL_FRONTBUFFER... things all over the place.
> 
> > 
> > > 
> > > > +		if (fbc_bits & frontbuffer_bits)
> > > > +			dev_priv->fbc.flip_prepare(dev_priv);
> > > 
> > > You would still have to disable+reenable if you need to eg.
> > > reallocate
> > > the compressed buffer, of if the new fb isn't suitable for fbc, or
> > > maybe
> > > if you need to change anything else in the control register.
> > 
> > Yes, but as far as I understand the frontbuffer tracking, this case
> > won't happen here. I'm assuming we'll always go through
> > intel_fbc_update() on these cases.
> 
> Perhaps, but more by luck than by design. With the setplane and atomic
> APIs there's no difference between a page flip and other plane updates.
> So if you want to take advantage of the hw flip nuke, you would need to
> check how the plane state is going to change, and based on that decide
> whether a fence update is enough or disable+re-enable is needed. And in
> fact I don't see any fbc_disable before the flip, just an fbc_update
> after the fact. So seems to me the disable really should be in your
> flip_prepare hook in this case. And in fact the whole flip_prepare
> thing isn't even called from the setplane/atomic path.

Oh and another related scenario also came to mind. Consider for example
the follow sequence of events:

1. fbc enabled on pipe A
2. flip scheduled on pipe A which requires fbc to be disabled
   -> fbc gets disabled
4. modeset on pipe B calls fbc_update
   -> fbc gets re-enabled on pipe A before the flip has finished, oops!

So we also need something to keep fbc reliably disabled until the
flip has occured.

> 
> > 
> > > 
> > > What I had was:
> > > "
> > > static bool intel_fbc_need_reinit(struct intel_crtc *crtc)
> > > {
> > > 	struct drm_i915_private *dev_priv = crtc->base.dev-
> > > >dev_private;
> > > 	struct drm_framebuffer *fb = crtc->base.primary->fb;
> > > 	struct drm_i915_gem_object *obj = to_intel_framebuffer(fb)-
> > > >obj;
> > > 
> > > 	return crtc != dev_priv->fbc.crtc ||
> > > 	       obj->base.size > dev_priv->fbc.size ||
> > > 	       drm_format_plane_cpp(fb->pixel_format, 0) !=
> > > 	       drm_format_plane_cpp(dev_priv->fbc.pixel_format, 0) ||
> > > 	       fb->pitches[0] != dev_priv->fbc.pitch;
> > > }
> > > intel_fbc_pre_page_flip()
> > > {
> > > 	...
> > > 	intel_fbc_update_pending_score(crtc);
> > > 
> > > 	/*
> > > 	 * If fbc was already possible we can update immediately,
> > > 	 * otherwise we will wait until the flip is finished.
> > > 	 */
> > > 	if (crtc->fbc.score != 0)
> > > 		crtc->fbc.score = crtc->fbc.pending_score;
> > > 
> > > 	/*
> > > 	 * Disable fbc if we're not (yet) capable, or if
> > > 	 * we just need a full disable+enable reinit.
> > > 	 */
> > > 	if (crtc->fbc.score == 0 || intel_fbc_need_reinit(crtc))
> > > 		__intel_fbc_disable(crtc);
> > > 	...
> > > }
> > > "
> > > 
> > > > +	} else if (dev_priv->fbc.fbc_work) {
> > > > +		fbc_bits = INTEL_FRONTBUFFER_PRIMARY(
> > > > +				dev_priv->fbc.fbc_work->crtc-
> > > > >pipe);
> > > > +		if (fbc_bits & frontbuffer_bits)
> > > > +			__intel_fbc_disable(dev_priv);
> > > >  	}
> > > >  
> > > >  	mutex_unlock(&dev_priv->fbc.lock);
> > > > @@ -1063,18 +1155,25 @@ void intel_fbc_init(struct drm_i915_private
> > > > *dev_priv)
> > > >  		dev_priv->fbc.fbc_enabled = ilk_fbc_enabled;
> > > >  		dev_priv->fbc.enable_fbc = gen7_fbc_enable;
> > > >  		dev_priv->fbc.disable_fbc = ilk_fbc_disable;
> > > > +		dev_priv->fbc.flip_prepare = snb_fbc_flip_prepare;
> > > >  	} else if (INTEL_INFO(dev_priv)->gen >= 5) {
> > > >  		dev_priv->fbc.fbc_enabled = ilk_fbc_enabled;
> > > >  		dev_priv->fbc.enable_fbc = ilk_fbc_enable;
> > > >  		dev_priv->fbc.disable_fbc = ilk_fbc_disable;
> > > > +		if (INTEL_INFO(dev_priv)->gen == 5)
> > > > +			dev_priv->fbc.flip_prepare =
> > > > ilk_fbc_flip_prepare;
> > > > +		else
> > > > +			dev_priv->fbc.flip_prepare =
> > > > snb_fbc_flip_prepare;
> > > >  	} else if (IS_GM45(dev_priv)) {
> > > >  		dev_priv->fbc.fbc_enabled = g4x_fbc_enabled;
> > > >  		dev_priv->fbc.enable_fbc = g4x_fbc_enable;
> > > >  		dev_priv->fbc.disable_fbc = g4x_fbc_disable;
> > > > +		dev_priv->fbc.flip_prepare = g4x_fbc_flip_prepare;
> > > >  	} else {
> > > >  		dev_priv->fbc.fbc_enabled = i8xx_fbc_enabled;
> > > >  		dev_priv->fbc.enable_fbc = i8xx_fbc_enable;
> > > >  		dev_priv->fbc.disable_fbc = i8xx_fbc_disable;
> > > > +		dev_priv->fbc.flip_prepare =
> > > > i8xx_fbc_flip_prepare;
> > > >  
> > > >  		/* This value was pulled out of someone's hat */
> > > >  		I915_WRITE(FBC_CONTROL, 500 <<
> > > > FBC_CTL_INTERVAL_SHIFT);
> > > > diff --git a/drivers/gpu/drm/i915/intel_frontbuffer.c
> > > > b/drivers/gpu/drm/i915/intel_frontbuffer.c
> > > > index ac85357..31a1ad3 100644
> > > > --- a/drivers/gpu/drm/i915/intel_frontbuffer.c
> > > > +++ b/drivers/gpu/drm/i915/intel_frontbuffer.c
> > > > @@ -192,6 +192,7 @@ void intel_frontbuffer_flip_prepare(struct
> > > > drm_device *dev,
> > > >  	mutex_unlock(&dev_priv->fb_tracking.lock);
> > > >  
> > > >  	intel_psr_single_frame_update(dev, frontbuffer_bits);
> > > > +	intel_fbc_flip_prepare(dev_priv, frontbuffer_bits);
> > > >  }
> > > >  
> > > >  /**
> > > > -- 
> > > > 2.6.1
> > > > 
> > > > _______________________________________________
> > > > Intel-gfx mailing list
> > > > Intel-gfx@lists.freedesktop.org
> > > > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> > > 
> 
> -- 
> Ville Syrjälä
> Intel OTC
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 02/26] drm/i915: don't stop+start FBC at every flip
  2015-10-29 17:30         ` Ville Syrjälä
@ 2015-10-29 17:52           ` Zanoni, Paulo R
  2015-10-29 18:14             ` Ville Syrjälä
  0 siblings, 1 reply; 44+ messages in thread
From: Zanoni, Paulo R @ 2015-10-29 17:52 UTC (permalink / raw)
  To: ville.syrjala@linux.intel.com; +Cc: intel-gfx@lists.freedesktop.org

Em Qui, 2015-10-29 às 19:30 +0200, Ville Syrjälä escreveu:
> On Wed, Oct 28, 2015 at 07:20:12PM +0200, Ville Syrjälä wrote:
> > On Wed, Oct 28, 2015 at 04:56:39PM +0000, Zanoni, Paulo R wrote:
> > > Em Ter, 2015-10-27 às 20:32 +0200, Ville Syrjälä escreveu:
> > > > On Tue, Oct 27, 2015 at 02:50:04PM -0200, Paulo Zanoni wrote:
> > > > > The hardware already takes care of disabling and
> > > > > recompressing FBC
> > > > > when we do a page flip, so all we need to do is to update the
> > > > > fence
> > > > > registers and move on.
> > > > > 
> > > > > One of the important things to notice is that on the pre-gen6
> > > > > platforms the fence is programmed on the FBC control register
> > > > > and
> > > > > the
> > > > > documentation says we can't update the control register while
> > > > > FBC
> > > > > is
> > > > > enabled. This would basically mean we'd have to to
> > > > > disable+enable
> > > > > FBC
> > > > > at every flip in order to make sure the hardware tracking
> > > > > still
> > > > > works,
> > > > > which doesn't seem to make too much sense. So I sent an email
> > > > > to
> > > > > the
> > > > > hardware team requesting some clarification. The information
> > > > > I got
> > > > > was
> > > > > this:
> > > > > 
> > > > > "I don't think any hardware is latching on to 0x100100,
> > > > > 0x100104,
> > > > > or
> > > > > the old fence number in FBC_CTL. Instructions against
> > > > > changing on
> > > > > the
> > > > > fly would be to simplify testing and ensure you don't miss
> > > > > any
> > > > > invalidation that happened right at that time."
> > > > > 
> > > > > So I guess we're fine for flips. But I can't really say I
> > > > > tested
> > > > > FBC
> > > > > on these ancient platforms - nor that I'll ever propose
> > > > > enabling
> > > > > FBC
> > > > > by default on them exactly because of problems like these.
> > > > 
> > > > Yeah, I did this in my patches too, and IIRC it seemed to work
> > > > just
> > > > fine
> > > > back then.
> > > > 
> > > > > 
> > > > > v2: Add comment at flush() (Chris).
> > > > > 
> > > > > Testcase: igt/kms_frontbuffer_tracking/fbc*-fliptrack
> > > > > Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> > > > > ---
> > > > >  drivers/gpu/drm/i915/i915_drv.h          |   1 +
> > > > >  drivers/gpu/drm/i915/i915_reg.h          |   3 +
> > > > >  drivers/gpu/drm/i915/intel_display.c     |   1 -
> > > > >  drivers/gpu/drm/i915/intel_drv.h         |   2 +
> > > > >  drivers/gpu/drm/i915/intel_fbc.c         | 103
> > > > > ++++++++++++++++++++++++++++++-
> > > > >  drivers/gpu/drm/i915/intel_frontbuffer.c |   1 +
> > > > >  6 files changed, 108 insertions(+), 3 deletions(-)
> > > > > 
> > > > > diff --git a/drivers/gpu/drm/i915/i915_drv.h
> > > > > b/drivers/gpu/drm/i915/i915_drv.h
> > > > > index ee14962..77da500 100644
> > > > > --- a/drivers/gpu/drm/i915/i915_drv.h
> > > > > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > > > > @@ -928,6 +928,7 @@ struct i915_fbc {
> > > > >  	bool (*fbc_enabled)(struct drm_i915_private
> > > > > *dev_priv);
> > > > >  	void (*enable_fbc)(struct intel_crtc *crtc);
> > > > >  	void (*disable_fbc)(struct drm_i915_private
> > > > > *dev_priv);
> > > > > +	void (*flip_prepare)(struct drm_i915_private
> > > > > *dev_priv);
> > > > >  };
> > > > >  
> > > > >  /**
> > > > > diff --git a/drivers/gpu/drm/i915/i915_reg.h
> > > > > b/drivers/gpu/drm/i915/i915_reg.h
> > > > > index 8942532..3d598a2 100644
> > > > > --- a/drivers/gpu/drm/i915/i915_reg.h
> > > > > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > > > > @@ -2028,6 +2028,7 @@ enum skl_disp_power_wells {
> > > > >  #define   FBC_CTL_C3_IDLE	(1<<13)
> > > > >  #define   FBC_CTL_STRIDE_SHIFT	(5)
> > > > >  #define   FBC_CTL_FENCENO_SHIFT	(0)
> > > > > +#define   FBC_CTL_FENCENO_MASK	0xF
> > > > 
> > > > It's only three bits on gen2. But bit 3 is MBZ and there are
> > > > only 8
> > > > fence registers on those platforms, so this is OK.
> > > > 
> > > > >  #define FBC_COMMAND		0x0320c
> > > > >  #define   FBC_CMD_COMPRESS	(1<<0)
> > > > >  #define FBC_STATUS		0x03210
> > > > > @@ -2064,6 +2065,7 @@ enum skl_disp_power_wells {
> > > > >  #define   DPFC_CTL_LIMIT_1X	(0<<6)
> > > > >  #define   DPFC_CTL_LIMIT_2X	(1<<6)
> > > > >  #define   DPFC_CTL_LIMIT_4X	(2<<6)
> > > > > +#define   DPFC_CTL_FENCE_MASK	0xF
> > > > >  #define DPFC_RECOMP_CTL		0x320c
> > > > >  #define   DPFC_RECOMP_STALL_EN	(1<<27)
> > > > >  #define   DPFC_RECOMP_STALL_WM_SHIFT (16)
> > > > > @@ -2086,6 +2088,7 @@ enum skl_disp_power_wells {
> > > > >  #define   FBC_CTL_FALSE_COLOR	(1<<10)
> > > > >  /* The bit 28-8 is reserved */
> > > > >  #define   DPFC_RESERVED		(0x1FFFFF00)
> > > > > +#define   ILK_DPFC_FENCE_MASK	0xF
> > > > >  #define ILK_DPFC_RECOMP_CTL	0x4320c
> > > > >  #define ILK_DPFC_STATUS		0x43210
> > > > >  #define ILK_DPFC_FENCE_YOFF	0x43218
> > > > > diff --git a/drivers/gpu/drm/i915/intel_display.c
> > > > > b/drivers/gpu/drm/i915/intel_display.c
> > > > > index bc1907e..d9378c3 100644
> > > > > --- a/drivers/gpu/drm/i915/intel_display.c
> > > > > +++ b/drivers/gpu/drm/i915/intel_display.c
> > > > > @@ -11502,7 +11502,6 @@ static int
> > > > > intel_crtc_page_flip(struct
> > > > > drm_crtc *crtc,
> > > > >  			  to_intel_plane(primary)-
> > > > > > frontbuffer_bit);
> > > > >  	mutex_unlock(&dev->struct_mutex);
> > > > >  
> > > > > -	intel_fbc_disable_crtc(intel_crtc);
> > > > >  	intel_frontbuffer_flip_prepare(dev,
> > > > >  				       to_intel_plane(primar
> > > > > y)-
> > > > > > frontbuffer_bit);
> > > > >  
> > > > > diff --git a/drivers/gpu/drm/i915/intel_drv.h
> > > > > b/drivers/gpu/drm/i915/intel_drv.h
> > > > > index 08847d0..9065a8f 100644
> > > > > --- a/drivers/gpu/drm/i915/intel_drv.h
> > > > > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > > > > @@ -1305,6 +1305,8 @@ void intel_fbc_invalidate(struct
> > > > > drm_i915_private *dev_priv,
> > > > >  			  enum fb_op_origin origin);
> > > > >  void intel_fbc_flush(struct drm_i915_private *dev_priv,
> > > > >  		     unsigned int frontbuffer_bits, enum
> > > > > fb_op_origin origin);
> > > > > +void intel_fbc_flip_prepare(struct drm_i915_private
> > > > > *dev_priv,
> > > > > +			    unsigned int frontbuffer_bits);
> > > > >  void intel_fbc_cleanup_cfb(struct drm_i915_private
> > > > > *dev_priv);
> > > > >  
> > > > >  /* intel_hdmi.c */
> > > > > diff --git a/drivers/gpu/drm/i915/intel_fbc.c
> > > > > b/drivers/gpu/drm/i915/intel_fbc.c
> > > > > index d9d7e54..62f158b 100644
> > > > > --- a/drivers/gpu/drm/i915/intel_fbc.c
> > > > > +++ b/drivers/gpu/drm/i915/intel_fbc.c
> > > > > @@ -82,6 +82,22 @@ static void i8xx_fbc_disable(struct
> > > > > drm_i915_private *dev_priv)
> > > > >  	DRM_DEBUG_KMS("disabled FBC\n");
> > > > >  }
> > > > >  
> > > > > +static void i8xx_fbc_flip_prepare(struct drm_i915_private
> > > > > *dev_priv)
> > > > > +{
> > > > > +	struct intel_crtc *crtc = dev_priv->fbc.crtc;
> > > > > +	struct drm_framebuffer *fb = crtc->base.primary->fb;
> > > > > +	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
> > > > > +	uint32_t val;
> > > > > +
> > > > > +	/* Although the documentation suggests we can't
> > > > > change
> > > > > DPFC_CONTROL
> > > > > +	 * while compression is enabled, the hardware guys
> > > > > said
> > > > > that updating
> > > > > +	 * the fence register bits during a flip is fine. */
> > > > > +	val = I915_READ(FBC_CONTROL);
> > > > > +	val &= ~FBC_CTL_FENCENO_MASK;
> > > > > +	val |= obj->fence_reg;
> > > > > +	I915_WRITE(FBC_CONTROL, val);
> > > > > +}
> > > > 
> > > > IIRC I just called the enable function to reconstruct the
> > > > entire
> > > > register contents to avoid code duplication. But maybe that's
> > > > not
> > > > possible without reowrking the fbc state handling entirely
> > > > (which I had done).
> > > > > +
> > > > >  static void i8xx_fbc_enable(struct intel_crtc *crtc)
> > > > >  {
> > > > >  	struct drm_i915_private *dev_priv = crtc->base.dev-
> > > > > > dev_private;
> > > > > @@ -161,6 +177,22 @@ static void g4x_fbc_enable(struct
> > > > > intel_crtc
> > > > > *crtc)
> > > > >  	DRM_DEBUG_KMS("enabled fbc on plane %c\n",
> > > > > plane_name(crtc->plane));
> > > > >  }
> > > > >  
> > > > > +static void g4x_fbc_flip_prepare(struct drm_i915_private
> > > > > *dev_priv)
> > > > > +{
> > > > > +	struct intel_crtc *crtc = dev_priv->fbc.crtc;
> > > > > +	struct drm_framebuffer *fb = crtc->base.primary->fb;
> > > > > +	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
> > > > > +	uint32_t val;
> > > > > +
> > > > > +	/* Although the documentation suggests we can't
> > > > > change
> > > > > DPFC_CONTROL
> > > > > +	 * while compression is enabled, the hardware guys
> > > > > said
> > > > > that updating
> > > > > +	 * the fence register bits during a flip is fine. */
> > > > > +	val = I915_READ(DPFC_CONTROL);
> > > > > +	val &= ~DPFC_CTL_FENCE_MASK;
> > > > > +	val |= obj->fence_reg;
> > > > > +	I915_WRITE(DPFC_CONTROL, val);
> > > > > +}
> > > > > +
> > > > >  static void g4x_fbc_disable(struct drm_i915_private
> > > > > *dev_priv)
> > > > >  {
> > > > >  	u32 dpfc_ctl;
> > > > > @@ -236,6 +268,31 @@ static void ilk_fbc_enable(struct
> > > > > intel_crtc
> > > > > *crtc)
> > > > >  	DRM_DEBUG_KMS("enabled fbc on plane %c\n",
> > > > > plane_name(crtc->plane));
> > > > >  }
> > > > >  
> > > > > +static void ilk_fbc_flip_prepare(struct drm_i915_private
> > > > > *dev_priv)
> > > > > +{
> > > > > +	struct intel_crtc *crtc = dev_priv->fbc.crtc;
> > > > > +	struct drm_framebuffer *fb = crtc->base.primary->fb;
> > > > > +	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
> > > > > +	uint32_t val;
> > > > > +
> > > > > +	/* Although the documentation suggests we can't
> > > > > change
> > > > > DPFC_CONTROL
> > > > > +	 * while compression is enabled, the hardware guys
> > > > > said
> > > > > that updating
> > > > > +	 * the fence register bits during a flip is fine. */
> > > > > +	val = I915_READ(ILK_DPFC_CONTROL);
> > > > > +	val &= ~ILK_DPFC_FENCE_MASK;
> > > > > +	val |= obj->fence_reg;
> > > > > +	I915_WRITE(ILK_DPFC_CONTROL, val);
> > > > > +}
> > > > > +
> > > > > +static void snb_fbc_flip_prepare(struct drm_i915_private
> > > > > *dev_priv)
> > > > > +{
> > > > > +	struct intel_crtc *crtc = dev_priv->fbc.crtc;
> > > > > +	struct drm_framebuffer *fb = crtc->base.primary->fb;
> > > > > +	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
> > > > > +
> > > > > +	I915_WRITE(SNB_DPFC_CTL_SA, SNB_CPU_FENCE_ENABLE |
> > > > > obj-
> > > > > > fence_reg);
> > > > > +}
> > > > > +
> > > > >  static void ilk_fbc_disable(struct drm_i915_private
> > > > > *dev_priv)
> > > > >  {
> > > > >  	u32 dpfc_ctl;
> > > > > @@ -1021,13 +1078,48 @@ void intel_fbc_flush(struct
> > > > > drm_i915_private *dev_priv,
> > > > >  	if (origin == ORIGIN_GTT)
> > > > >  		return;
> > > > >  
> > > > > +	/* Hardware tracking already recompresses the CFB
> > > > > (nuke)
> > > > > for us if FBC
> > > > > +	 * is enabled and we do a page flip, so we can
> > > > > safely
> > > > > ignore it here.
> > > > > +	 * FBC may be disabled in case we got an
> > > > > invalidate()
> > > > > before the
> > > > > +	 * flush(), so we'll still have to check that case
> > > > > below.
> > > > > */
> > > > > +	if (origin == ORIGIN_FLIP && dev_priv->fbc.enabled)
> > > > > +		return;
> > > > > +
> > > > >  	mutex_lock(&dev_priv->fbc.lock);
> > > > >  
> > > > >  	dev_priv->fbc.busy_bits &= ~frontbuffer_bits;
> > > > >  
> > > > >  	if (!dev_priv->fbc.busy_bits) {
> > > > > -		__intel_fbc_disable(dev_priv);
> > > > > -		__intel_fbc_update(dev_priv);
> > > > > +		if (origin == ORIGIN_FLIP) {
> > > > > +			__intel_fbc_update(dev_priv);
> > > > > +		} else {
> > > > > +			__intel_fbc_disable(dev_priv);
> > > > > +			__intel_fbc_update(dev_priv);
> > > > > +		}
> > > > > +	}
> > > > > +
> > > > > +	mutex_unlock(&dev_priv->fbc.lock);
> > > > > +}
> > > > > +
> > > > > +void intel_fbc_flip_prepare(struct drm_i915_private
> > > > > *dev_priv,
> > > > > +			    unsigned int frontbuffer_bits)
> > > > > +{
> > > > > +	unsigned int fbc_bits;
> > > > > +
> > > > > +	if (!fbc_supported(dev_priv))
> > > > > +		return;
> > > > > +
> > > > > +	mutex_lock(&dev_priv->fbc.lock);
> > > > > +
> > > > > +	if (dev_priv->fbc.enabled) {
> > > > > +		fbc_bits =
> > > > > INTEL_FRONTBUFFER_PRIMARY(dev_priv-
> > > > > > fbc.crtc->pipe);
> > > > 
> > > > primary->frontbuffer_bit would seem better.
> > > 
> > > Why?
> > 
> > Why not? It's there already stashed away for you to use. No need to
> > sprinkle these INTEL_FRONTBUFFER... things all over the place.
> > 
> > > 
> > > > 
> > > > > +		if (fbc_bits & frontbuffer_bits)
> > > > > +			dev_priv-
> > > > > >fbc.flip_prepare(dev_priv);
> > > > 
> > > > You would still have to disable+reenable if you need to eg.
> > > > reallocate
> > > > the compressed buffer, of if the new fb isn't suitable for fbc,
> > > > or
> > > > maybe
> > > > if you need to change anything else in the control register.
> > > 
> > > Yes, but as far as I understand the frontbuffer tracking, this
> > > case
> > > won't happen here. I'm assuming we'll always go through
> > > intel_fbc_update() on these cases.
> > 
> > Perhaps, but more by luck than by design. With the setplane and
> > atomic
> > APIs there's no difference between a page flip and other plane
> > updates.

I am aware that some code paths are not the same as the full modeset
path, but there is still difference from the plain pageflip IOCTL. And
so far I have seen intel_fbc_update() being called everywhere, so this
should prevent the problems you seem to be pointing. Can you please
point a specific case that would break here involving a single pipe?
Multiple pipes are discussed below. 

I've been trying to analyze what you said and convert this to a proper
IGT subtest, but I just can't see the bug here. Please be a little more
specific on your description, like you just did for the multi-pipe
case.

> > So if you want to take advantage of the hw flip nuke, you would
> > need to
> > check how the plane state is going to change, and based on that
> > decide
> > whether a fence update is enough or disable+re-enable is needed.
> > And in
> > fact I don't see any fbc_disable before the flip, just an
> > fbc_update
> > after the fact. So seems to me the disable really should be in your
> > flip_prepare hook in this case

The flip_prepare hook is only for cases where the disable+update is not
needed since we're taking advantage of the HW tracking.

Besides, update() without a previous disable() is fine.

> > . And in fact the whole flip_prepare
> > thing isn't even called from the setplane/atomic path.

If update() is called we don't need flip_prepare() since flip_prepare()
is only for the fast path where we just update the fence.

> 
> Oh and another related scenario also came to mind. Consider for
> example
> the follow sequence of events:
> 
> 1. fbc enabled on pipe A
> 2. flip scheduled on pipe A which requires fbc to be disabled
>    -> fbc gets disabled
> 4. modeset on pipe B calls fbc_update
>    -> fbc gets re-enabled on pipe A before the flip has finished,
> oops!

If we have FBC disabled on pipe A before the pipe B modeset, then pipe
B calls fbc_update(), I just can't see how FBC may get re-enabled on
pipe A. Can you please elaborate more?


I know we should avoid regressions in the middle of the series, but as
a side-comment, the multi-pipe scenario changes even more later in the
series at the point where we introduce
enable/disable+activate/deactivate. So we'd only get FBC on pipe B if
we get a ilk_crtc_disable(pipe_a) first.

Besides, my plan here is to enable FBC only on HSW+, and these
platforms restrict FBC to pipe A. Of course I'm trying to not introduce
any new bugs, but I also think we shouldn't block patches just because
some ILK-IVB bug was not addressed.

> 
> So we also need something to keep fbc reliably disabled until the
> flip has occured.
> 
> > 
> > > 
> > > > 
> > > > What I had was:
> > > > "
> > > > static bool intel_fbc_need_reinit(struct intel_crtc *crtc)
> > > > {
> > > > 	struct drm_i915_private *dev_priv = crtc->base.dev-
> > > > > dev_private;
> > > > 	struct drm_framebuffer *fb = crtc->base.primary->fb;
> > > > 	struct drm_i915_gem_object *obj =
> > > > to_intel_framebuffer(fb)-
> > > > > obj;
> > > > 
> > > > 	return crtc != dev_priv->fbc.crtc ||
> > > > 	       obj->base.size > dev_priv->fbc.size ||
> > > > 	       drm_format_plane_cpp(fb->pixel_format, 0) !=
> > > > 	       drm_format_plane_cpp(dev_priv->fbc.pixel_format, 
> > > > 0) ||
> > > > 	       fb->pitches[0] != dev_priv->fbc.pitch;
> > > > }
> > > > intel_fbc_pre_page_flip()
> > > > {
> > > > 	...
> > > > 	intel_fbc_update_pending_score(crtc);
> > > > 
> > > > 	/*
> > > > 	 * If fbc was already possible we can update
> > > > immediately,
> > > > 	 * otherwise we will wait until the flip is finished.
> > > > 	 */
> > > > 	if (crtc->fbc.score != 0)
> > > > 		crtc->fbc.score = crtc->fbc.pending_score;
> > > > 
> > > > 	/*
> > > > 	 * Disable fbc if we're not (yet) capable, or if
> > > > 	 * we just need a full disable+enable reinit.
> > > > 	 */
> > > > 	if (crtc->fbc.score == 0 ||
> > > > intel_fbc_need_reinit(crtc))
> > > > 		__intel_fbc_disable(crtc);
> > > > 	...
> > > > }
> > > > "
> > > > 
> > > > > +	} else if (dev_priv->fbc.fbc_work) {
> > > > > +		fbc_bits = INTEL_FRONTBUFFER_PRIMARY(
> > > > > +				dev_priv->fbc.fbc_work-
> > > > > >crtc-
> > > > > > pipe);
> > > > > +		if (fbc_bits & frontbuffer_bits)
> > > > > +			__intel_fbc_disable(dev_priv);
> > > > >  	}
> > > > >  
> > > > >  	mutex_unlock(&dev_priv->fbc.lock);
> > > > > @@ -1063,18 +1155,25 @@ void intel_fbc_init(struct
> > > > > drm_i915_private
> > > > > *dev_priv)
> > > > >  		dev_priv->fbc.fbc_enabled = ilk_fbc_enabled;
> > > > >  		dev_priv->fbc.enable_fbc = gen7_fbc_enable;
> > > > >  		dev_priv->fbc.disable_fbc = ilk_fbc_disable;
> > > > > +		dev_priv->fbc.flip_prepare =
> > > > > snb_fbc_flip_prepare;
> > > > >  	} else if (INTEL_INFO(dev_priv)->gen >= 5) {
> > > > >  		dev_priv->fbc.fbc_enabled = ilk_fbc_enabled;
> > > > >  		dev_priv->fbc.enable_fbc = ilk_fbc_enable;
> > > > >  		dev_priv->fbc.disable_fbc = ilk_fbc_disable;
> > > > > +		if (INTEL_INFO(dev_priv)->gen == 5)
> > > > > +			dev_priv->fbc.flip_prepare =
> > > > > ilk_fbc_flip_prepare;
> > > > > +		else
> > > > > +			dev_priv->fbc.flip_prepare =
> > > > > snb_fbc_flip_prepare;
> > > > >  	} else if (IS_GM45(dev_priv)) {
> > > > >  		dev_priv->fbc.fbc_enabled = g4x_fbc_enabled;
> > > > >  		dev_priv->fbc.enable_fbc = g4x_fbc_enable;
> > > > >  		dev_priv->fbc.disable_fbc = g4x_fbc_disable;
> > > > > +		dev_priv->fbc.flip_prepare =
> > > > > g4x_fbc_flip_prepare;
> > > > >  	} else {
> > > > >  		dev_priv->fbc.fbc_enabled =
> > > > > i8xx_fbc_enabled;
> > > > >  		dev_priv->fbc.enable_fbc = i8xx_fbc_enable;
> > > > >  		dev_priv->fbc.disable_fbc =
> > > > > i8xx_fbc_disable;
> > > > > +		dev_priv->fbc.flip_prepare =
> > > > > i8xx_fbc_flip_prepare;
> > > > >  
> > > > >  		/* This value was pulled out of someone's
> > > > > hat */
> > > > >  		I915_WRITE(FBC_CONTROL, 500 <<
> > > > > FBC_CTL_INTERVAL_SHIFT);
> > > > > diff --git a/drivers/gpu/drm/i915/intel_frontbuffer.c
> > > > > b/drivers/gpu/drm/i915/intel_frontbuffer.c
> > > > > index ac85357..31a1ad3 100644
> > > > > --- a/drivers/gpu/drm/i915/intel_frontbuffer.c
> > > > > +++ b/drivers/gpu/drm/i915/intel_frontbuffer.c
> > > > > @@ -192,6 +192,7 @@ void
> > > > > intel_frontbuffer_flip_prepare(struct
> > > > > drm_device *dev,
> > > > >  	mutex_unlock(&dev_priv->fb_tracking.lock);
> > > > >  
> > > > >  	intel_psr_single_frame_update(dev,
> > > > > frontbuffer_bits);
> > > > > +	intel_fbc_flip_prepare(dev_priv, frontbuffer_bits);
> > > > >  }
> > > > >  
> > > > >  /**
> > > > > -- 
> > > > > 2.6.1
> > > > > 
> > > > > _______________________________________________
> > > > > Intel-gfx mailing list
> > > > > Intel-gfx@lists.freedesktop.org
> > > > > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> > > > 
> > 
> > -- 
> > Ville Syrjälä
> > Intel OTC
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 19/26] drm/i915: move adjusted_mode checks from fbc_update to fbc_enable
  2015-10-29 12:59   ` Maarten Lankhorst
@ 2015-10-29 17:58     ` Zanoni, Paulo R
  2015-11-02  8:53       ` Maarten Lankhorst
  0 siblings, 1 reply; 44+ messages in thread
From: Zanoni, Paulo R @ 2015-10-29 17:58 UTC (permalink / raw)
  To: intel-gfx@lists.freedesktop.org,
	maarten.lankhorst@linux.intel.com

Em Qui, 2015-10-29 às 13:59 +0100, Maarten Lankhorst escreveu:
> Op 27-10-15 om 17:50 schreef Paulo Zanoni:
> > These things can't change without a full modeset.
> False! Fastset can update parameters too. Although I don't think it
> currently prevents DBLSCAN updates,
> so maybe make sure cfb enable/disable is called when updating pipe
> too?

You mean that if we change for an interlaced (or double-scanned) to a
non-interlaced (or non-double-scanned) mode we won't get
crtc_disable+crtc_enable? That's surprising. I'll take a better look
here and try to write a test case. Is this just through some specific
API (like drmModeSetPlane)?

I'm trying to get test cases for every single bug I discover or
introduce.

> > Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_fbc.c | 16 ++++++++--------
> >  1 file changed, 8 insertions(+), 8 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_fbc.c
> > b/drivers/gpu/drm/i915/intel_fbc.c
> > index 0ba25b9..6aa9af8 100644
> > --- a/drivers/gpu/drm/i915/intel_fbc.c
> > +++ b/drivers/gpu/drm/i915/intel_fbc.c
> > @@ -825,7 +825,6 @@ static void __intel_fbc_update(struct
> > intel_crtc *crtc)
> >  	struct drm_i915_private *dev_priv = crtc->base.dev-
> > >dev_private;
> >  	struct drm_framebuffer *fb;
> >  	struct drm_i915_gem_object *obj;
> > -	const struct drm_display_mode *adjusted_mode;
> >  
> >  	WARN_ON(!mutex_is_locked(&dev_priv->fbc.lock));
> >  
> > @@ -844,13 +843,6 @@ static void __intel_fbc_update(struct
> > intel_crtc *crtc)
> >  
> >  	fb = crtc->base.primary->fb;
> >  	obj = intel_fb_obj(fb);
> > -	adjusted_mode = &crtc->config->base.adjusted_mode;
> > -
> > -	if ((adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) ||
> > -	    (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)) {
> > -		set_no_fbc_reason(dev_priv, "incompatible mode");
> > -		goto out_disable;
> > -	}
> >  
> >  	if (!intel_fbc_hw_tracking_covers_screen(crtc)) {
> >  		set_no_fbc_reason(dev_priv, "mode too large for
> > compression");
> > @@ -1076,6 +1068,8 @@ void intel_fbc_flip_prepare(struct
> > drm_i915_private *dev_priv,
> >  void intel_fbc_enable(struct intel_crtc *crtc)
> >  {
> >  	struct drm_i915_private *dev_priv = crtc->base.dev-
> > >dev_private;
> > +	const struct drm_display_mode *adjusted_mode =
> > +					&crtc->config-
> > >base.adjusted_mode;
> >  
> >  	if (!fbc_supported(dev_priv))
> >  		return;
> > @@ -1110,6 +1104,12 @@ void intel_fbc_enable(struct intel_crtc
> > *crtc)
> >  		goto out;
> >  	}
> >  
> > +	if ((adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) ||
> > +	    (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)) {
> > +		set_no_fbc_reason(dev_priv, "incompatible mode");
> > +		goto out;
> > +	}
> > +
> >  	if (intel_fbc_alloc_cfb(crtc)) {
> >  		set_no_fbc_reason(dev_priv, "not enough stolen
> > memory");
> >  		goto out;
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 02/26] drm/i915: don't stop+start FBC at every flip
  2015-10-29 17:52           ` Zanoni, Paulo R
@ 2015-10-29 18:14             ` Ville Syrjälä
  0 siblings, 0 replies; 44+ messages in thread
From: Ville Syrjälä @ 2015-10-29 18:14 UTC (permalink / raw)
  To: Zanoni, Paulo R; +Cc: intel-gfx@lists.freedesktop.org

On Thu, Oct 29, 2015 at 05:52:26PM +0000, Zanoni, Paulo R wrote:
> Em Qui, 2015-10-29 às 19:30 +0200, Ville Syrjälä escreveu:
> > On Wed, Oct 28, 2015 at 07:20:12PM +0200, Ville Syrjälä wrote:
> > > On Wed, Oct 28, 2015 at 04:56:39PM +0000, Zanoni, Paulo R wrote:
> > > > Em Ter, 2015-10-27 às 20:32 +0200, Ville Syrjälä escreveu:
> > > > > On Tue, Oct 27, 2015 at 02:50:04PM -0200, Paulo Zanoni wrote:
> > > > > > The hardware already takes care of disabling and
> > > > > > recompressing FBC
> > > > > > when we do a page flip, so all we need to do is to update the
> > > > > > fence
> > > > > > registers and move on.
> > > > > > 
> > > > > > One of the important things to notice is that on the pre-gen6
> > > > > > platforms the fence is programmed on the FBC control register
> > > > > > and
> > > > > > the
> > > > > > documentation says we can't update the control register while
> > > > > > FBC
> > > > > > is
> > > > > > enabled. This would basically mean we'd have to to
> > > > > > disable+enable
> > > > > > FBC
> > > > > > at every flip in order to make sure the hardware tracking
> > > > > > still
> > > > > > works,
> > > > > > which doesn't seem to make too much sense. So I sent an email
> > > > > > to
> > > > > > the
> > > > > > hardware team requesting some clarification. The information
> > > > > > I got
> > > > > > was
> > > > > > this:
> > > > > > 
> > > > > > "I don't think any hardware is latching on to 0x100100,
> > > > > > 0x100104,
> > > > > > or
> > > > > > the old fence number in FBC_CTL. Instructions against
> > > > > > changing on
> > > > > > the
> > > > > > fly would be to simplify testing and ensure you don't miss
> > > > > > any
> > > > > > invalidation that happened right at that time."
> > > > > > 
> > > > > > So I guess we're fine for flips. But I can't really say I
> > > > > > tested
> > > > > > FBC
> > > > > > on these ancient platforms - nor that I'll ever propose
> > > > > > enabling
> > > > > > FBC
> > > > > > by default on them exactly because of problems like these.
> > > > > 
> > > > > Yeah, I did this in my patches too, and IIRC it seemed to work
> > > > > just
> > > > > fine
> > > > > back then.
> > > > > 
> > > > > > 
> > > > > > v2: Add comment at flush() (Chris).
> > > > > > 
> > > > > > Testcase: igt/kms_frontbuffer_tracking/fbc*-fliptrack
> > > > > > Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> > > > > > ---
> > > > > >  drivers/gpu/drm/i915/i915_drv.h          |   1 +
> > > > > >  drivers/gpu/drm/i915/i915_reg.h          |   3 +
> > > > > >  drivers/gpu/drm/i915/intel_display.c     |   1 -
> > > > > >  drivers/gpu/drm/i915/intel_drv.h         |   2 +
> > > > > >  drivers/gpu/drm/i915/intel_fbc.c         | 103
> > > > > > ++++++++++++++++++++++++++++++-
> > > > > >  drivers/gpu/drm/i915/intel_frontbuffer.c |   1 +
> > > > > >  6 files changed, 108 insertions(+), 3 deletions(-)
> > > > > > 
> > > > > > diff --git a/drivers/gpu/drm/i915/i915_drv.h
> > > > > > b/drivers/gpu/drm/i915/i915_drv.h
> > > > > > index ee14962..77da500 100644
> > > > > > --- a/drivers/gpu/drm/i915/i915_drv.h
> > > > > > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > > > > > @@ -928,6 +928,7 @@ struct i915_fbc {
> > > > > >  	bool (*fbc_enabled)(struct drm_i915_private
> > > > > > *dev_priv);
> > > > > >  	void (*enable_fbc)(struct intel_crtc *crtc);
> > > > > >  	void (*disable_fbc)(struct drm_i915_private
> > > > > > *dev_priv);
> > > > > > +	void (*flip_prepare)(struct drm_i915_private
> > > > > > *dev_priv);
> > > > > >  };
> > > > > >  
> > > > > >  /**
> > > > > > diff --git a/drivers/gpu/drm/i915/i915_reg.h
> > > > > > b/drivers/gpu/drm/i915/i915_reg.h
> > > > > > index 8942532..3d598a2 100644
> > > > > > --- a/drivers/gpu/drm/i915/i915_reg.h
> > > > > > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > > > > > @@ -2028,6 +2028,7 @@ enum skl_disp_power_wells {
> > > > > >  #define   FBC_CTL_C3_IDLE	(1<<13)
> > > > > >  #define   FBC_CTL_STRIDE_SHIFT	(5)
> > > > > >  #define   FBC_CTL_FENCENO_SHIFT	(0)
> > > > > > +#define   FBC_CTL_FENCENO_MASK	0xF
> > > > > 
> > > > > It's only three bits on gen2. But bit 3 is MBZ and there are
> > > > > only 8
> > > > > fence registers on those platforms, so this is OK.
> > > > > 
> > > > > >  #define FBC_COMMAND		0x0320c
> > > > > >  #define   FBC_CMD_COMPRESS	(1<<0)
> > > > > >  #define FBC_STATUS		0x03210
> > > > > > @@ -2064,6 +2065,7 @@ enum skl_disp_power_wells {
> > > > > >  #define   DPFC_CTL_LIMIT_1X	(0<<6)
> > > > > >  #define   DPFC_CTL_LIMIT_2X	(1<<6)
> > > > > >  #define   DPFC_CTL_LIMIT_4X	(2<<6)
> > > > > > +#define   DPFC_CTL_FENCE_MASK	0xF
> > > > > >  #define DPFC_RECOMP_CTL		0x320c
> > > > > >  #define   DPFC_RECOMP_STALL_EN	(1<<27)
> > > > > >  #define   DPFC_RECOMP_STALL_WM_SHIFT (16)
> > > > > > @@ -2086,6 +2088,7 @@ enum skl_disp_power_wells {
> > > > > >  #define   FBC_CTL_FALSE_COLOR	(1<<10)
> > > > > >  /* The bit 28-8 is reserved */
> > > > > >  #define   DPFC_RESERVED		(0x1FFFFF00)
> > > > > > +#define   ILK_DPFC_FENCE_MASK	0xF
> > > > > >  #define ILK_DPFC_RECOMP_CTL	0x4320c
> > > > > >  #define ILK_DPFC_STATUS		0x43210
> > > > > >  #define ILK_DPFC_FENCE_YOFF	0x43218
> > > > > > diff --git a/drivers/gpu/drm/i915/intel_display.c
> > > > > > b/drivers/gpu/drm/i915/intel_display.c
> > > > > > index bc1907e..d9378c3 100644
> > > > > > --- a/drivers/gpu/drm/i915/intel_display.c
> > > > > > +++ b/drivers/gpu/drm/i915/intel_display.c
> > > > > > @@ -11502,7 +11502,6 @@ static int
> > > > > > intel_crtc_page_flip(struct
> > > > > > drm_crtc *crtc,
> > > > > >  			  to_intel_plane(primary)-
> > > > > > > frontbuffer_bit);
> > > > > >  	mutex_unlock(&dev->struct_mutex);
> > > > > >  
> > > > > > -	intel_fbc_disable_crtc(intel_crtc);
> > > > > >  	intel_frontbuffer_flip_prepare(dev,
> > > > > >  				       to_intel_plane(primar
> > > > > > y)-
> > > > > > > frontbuffer_bit);
> > > > > >  
> > > > > > diff --git a/drivers/gpu/drm/i915/intel_drv.h
> > > > > > b/drivers/gpu/drm/i915/intel_drv.h
> > > > > > index 08847d0..9065a8f 100644
> > > > > > --- a/drivers/gpu/drm/i915/intel_drv.h
> > > > > > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > > > > > @@ -1305,6 +1305,8 @@ void intel_fbc_invalidate(struct
> > > > > > drm_i915_private *dev_priv,
> > > > > >  			  enum fb_op_origin origin);
> > > > > >  void intel_fbc_flush(struct drm_i915_private *dev_priv,
> > > > > >  		     unsigned int frontbuffer_bits, enum
> > > > > > fb_op_origin origin);
> > > > > > +void intel_fbc_flip_prepare(struct drm_i915_private
> > > > > > *dev_priv,
> > > > > > +			    unsigned int frontbuffer_bits);
> > > > > >  void intel_fbc_cleanup_cfb(struct drm_i915_private
> > > > > > *dev_priv);
> > > > > >  
> > > > > >  /* intel_hdmi.c */
> > > > > > diff --git a/drivers/gpu/drm/i915/intel_fbc.c
> > > > > > b/drivers/gpu/drm/i915/intel_fbc.c
> > > > > > index d9d7e54..62f158b 100644
> > > > > > --- a/drivers/gpu/drm/i915/intel_fbc.c
> > > > > > +++ b/drivers/gpu/drm/i915/intel_fbc.c
> > > > > > @@ -82,6 +82,22 @@ static void i8xx_fbc_disable(struct
> > > > > > drm_i915_private *dev_priv)
> > > > > >  	DRM_DEBUG_KMS("disabled FBC\n");
> > > > > >  }
> > > > > >  
> > > > > > +static void i8xx_fbc_flip_prepare(struct drm_i915_private
> > > > > > *dev_priv)
> > > > > > +{
> > > > > > +	struct intel_crtc *crtc = dev_priv->fbc.crtc;
> > > > > > +	struct drm_framebuffer *fb = crtc->base.primary->fb;
> > > > > > +	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
> > > > > > +	uint32_t val;
> > > > > > +
> > > > > > +	/* Although the documentation suggests we can't
> > > > > > change
> > > > > > DPFC_CONTROL
> > > > > > +	 * while compression is enabled, the hardware guys
> > > > > > said
> > > > > > that updating
> > > > > > +	 * the fence register bits during a flip is fine. */
> > > > > > +	val = I915_READ(FBC_CONTROL);
> > > > > > +	val &= ~FBC_CTL_FENCENO_MASK;
> > > > > > +	val |= obj->fence_reg;
> > > > > > +	I915_WRITE(FBC_CONTROL, val);
> > > > > > +}
> > > > > 
> > > > > IIRC I just called the enable function to reconstruct the
> > > > > entire
> > > > > register contents to avoid code duplication. But maybe that's
> > > > > not
> > > > > possible without reowrking the fbc state handling entirely
> > > > > (which I had done).
> > > > > > +
> > > > > >  static void i8xx_fbc_enable(struct intel_crtc *crtc)
> > > > > >  {
> > > > > >  	struct drm_i915_private *dev_priv = crtc->base.dev-
> > > > > > > dev_private;
> > > > > > @@ -161,6 +177,22 @@ static void g4x_fbc_enable(struct
> > > > > > intel_crtc
> > > > > > *crtc)
> > > > > >  	DRM_DEBUG_KMS("enabled fbc on plane %c\n",
> > > > > > plane_name(crtc->plane));
> > > > > >  }
> > > > > >  
> > > > > > +static void g4x_fbc_flip_prepare(struct drm_i915_private
> > > > > > *dev_priv)
> > > > > > +{
> > > > > > +	struct intel_crtc *crtc = dev_priv->fbc.crtc;
> > > > > > +	struct drm_framebuffer *fb = crtc->base.primary->fb;
> > > > > > +	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
> > > > > > +	uint32_t val;
> > > > > > +
> > > > > > +	/* Although the documentation suggests we can't
> > > > > > change
> > > > > > DPFC_CONTROL
> > > > > > +	 * while compression is enabled, the hardware guys
> > > > > > said
> > > > > > that updating
> > > > > > +	 * the fence register bits during a flip is fine. */
> > > > > > +	val = I915_READ(DPFC_CONTROL);
> > > > > > +	val &= ~DPFC_CTL_FENCE_MASK;
> > > > > > +	val |= obj->fence_reg;
> > > > > > +	I915_WRITE(DPFC_CONTROL, val);
> > > > > > +}
> > > > > > +
> > > > > >  static void g4x_fbc_disable(struct drm_i915_private
> > > > > > *dev_priv)
> > > > > >  {
> > > > > >  	u32 dpfc_ctl;
> > > > > > @@ -236,6 +268,31 @@ static void ilk_fbc_enable(struct
> > > > > > intel_crtc
> > > > > > *crtc)
> > > > > >  	DRM_DEBUG_KMS("enabled fbc on plane %c\n",
> > > > > > plane_name(crtc->plane));
> > > > > >  }
> > > > > >  
> > > > > > +static void ilk_fbc_flip_prepare(struct drm_i915_private
> > > > > > *dev_priv)
> > > > > > +{
> > > > > > +	struct intel_crtc *crtc = dev_priv->fbc.crtc;
> > > > > > +	struct drm_framebuffer *fb = crtc->base.primary->fb;
> > > > > > +	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
> > > > > > +	uint32_t val;
> > > > > > +
> > > > > > +	/* Although the documentation suggests we can't
> > > > > > change
> > > > > > DPFC_CONTROL
> > > > > > +	 * while compression is enabled, the hardware guys
> > > > > > said
> > > > > > that updating
> > > > > > +	 * the fence register bits during a flip is fine. */
> > > > > > +	val = I915_READ(ILK_DPFC_CONTROL);
> > > > > > +	val &= ~ILK_DPFC_FENCE_MASK;
> > > > > > +	val |= obj->fence_reg;
> > > > > > +	I915_WRITE(ILK_DPFC_CONTROL, val);
> > > > > > +}
> > > > > > +
> > > > > > +static void snb_fbc_flip_prepare(struct drm_i915_private
> > > > > > *dev_priv)
> > > > > > +{
> > > > > > +	struct intel_crtc *crtc = dev_priv->fbc.crtc;
> > > > > > +	struct drm_framebuffer *fb = crtc->base.primary->fb;
> > > > > > +	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
> > > > > > +
> > > > > > +	I915_WRITE(SNB_DPFC_CTL_SA, SNB_CPU_FENCE_ENABLE |
> > > > > > obj-
> > > > > > > fence_reg);
> > > > > > +}
> > > > > > +
> > > > > >  static void ilk_fbc_disable(struct drm_i915_private
> > > > > > *dev_priv)
> > > > > >  {
> > > > > >  	u32 dpfc_ctl;
> > > > > > @@ -1021,13 +1078,48 @@ void intel_fbc_flush(struct
> > > > > > drm_i915_private *dev_priv,
> > > > > >  	if (origin == ORIGIN_GTT)
> > > > > >  		return;
> > > > > >  
> > > > > > +	/* Hardware tracking already recompresses the CFB
> > > > > > (nuke)
> > > > > > for us if FBC
> > > > > > +	 * is enabled and we do a page flip, so we can
> > > > > > safely
> > > > > > ignore it here.
> > > > > > +	 * FBC may be disabled in case we got an
> > > > > > invalidate()
> > > > > > before the
> > > > > > +	 * flush(), so we'll still have to check that case
> > > > > > below.
> > > > > > */
> > > > > > +	if (origin == ORIGIN_FLIP && dev_priv->fbc.enabled)
> > > > > > +		return;
> > > > > > +
> > > > > >  	mutex_lock(&dev_priv->fbc.lock);
> > > > > >  
> > > > > >  	dev_priv->fbc.busy_bits &= ~frontbuffer_bits;
> > > > > >  
> > > > > >  	if (!dev_priv->fbc.busy_bits) {
> > > > > > -		__intel_fbc_disable(dev_priv);
> > > > > > -		__intel_fbc_update(dev_priv);
> > > > > > +		if (origin == ORIGIN_FLIP) {
> > > > > > +			__intel_fbc_update(dev_priv);
> > > > > > +		} else {
> > > > > > +			__intel_fbc_disable(dev_priv);
> > > > > > +			__intel_fbc_update(dev_priv);
> > > > > > +		}
> > > > > > +	}
> > > > > > +
> > > > > > +	mutex_unlock(&dev_priv->fbc.lock);
> > > > > > +}
> > > > > > +
> > > > > > +void intel_fbc_flip_prepare(struct drm_i915_private
> > > > > > *dev_priv,
> > > > > > +			    unsigned int frontbuffer_bits)
> > > > > > +{
> > > > > > +	unsigned int fbc_bits;
> > > > > > +
> > > > > > +	if (!fbc_supported(dev_priv))
> > > > > > +		return;
> > > > > > +
> > > > > > +	mutex_lock(&dev_priv->fbc.lock);
> > > > > > +
> > > > > > +	if (dev_priv->fbc.enabled) {
> > > > > > +		fbc_bits =
> > > > > > INTEL_FRONTBUFFER_PRIMARY(dev_priv-
> > > > > > > fbc.crtc->pipe);
> > > > > 
> > > > > primary->frontbuffer_bit would seem better.
> > > > 
> > > > Why?
> > > 
> > > Why not? It's there already stashed away for you to use. No need to
> > > sprinkle these INTEL_FRONTBUFFER... things all over the place.
> > > 
> > > > 
> > > > > 
> > > > > > +		if (fbc_bits & frontbuffer_bits)
> > > > > > +			dev_priv-
> > > > > > >fbc.flip_prepare(dev_priv);
> > > > > 
> > > > > You would still have to disable+reenable if you need to eg.
> > > > > reallocate
> > > > > the compressed buffer, of if the new fb isn't suitable for fbc,
> > > > > or
> > > > > maybe
> > > > > if you need to change anything else in the control register.
> > > > 
> > > > Yes, but as far as I understand the frontbuffer tracking, this
> > > > case
> > > > won't happen here. I'm assuming we'll always go through
> > > > intel_fbc_update() on these cases.
> > > 
> > > Perhaps, but more by luck than by design. With the setplane and
> > > atomic
> > > APIs there's no difference between a page flip and other plane
> > > updates.
> 
> I am aware that some code paths are not the same as the full modeset
> path, but there is still difference from the plain pageflip IOCTL. And
> so far I have seen intel_fbc_update() being called everywhere, so this
> should prevent the problems you seem to be pointing. Can you please
> point a specific case that would break here involving a single pipe?
> Multiple pipes are discussed below. 
> 
> I've been trying to analyze what you said and convert this to a proper
> IGT subtest, but I just can't see the bug here. Please be a little more
> specific on your description, like you just did for the multi-pipe
> case.
> 
> > > So if you want to take advantage of the hw flip nuke, you would
> > > need to
> > > check how the plane state is going to change, and based on that
> > > decide
> > > whether a fence update is enough or disable+re-enable is needed.
> > > And in
> > > fact I don't see any fbc_disable before the flip, just an
> > > fbc_update
> > > after the fact. So seems to me the disable really should be in your
> > > flip_prepare hook in this case
> 
> The flip_prepare hook is only for cases where the disable+update is not
> needed since we're taking advantage of the HW tracking.

That may be OK for the legacy page flip path since we artifically
restrict what it can change. The setplane/atomic path can change
anything, so more checks are needed there to see if fbc needs to be
disabled or if the fence update is enough.

Oh, actually we do allow the page flip ioctl to change the tiling
mode, so you do need to take this into account even there.

> 
> Besides, update() without a previous disable() is fine.

Not if the flip already happened while fbc was still enabled and
configured based on the old plane state.

> 
> > > . And in fact the whole flip_prepare
> > > thing isn't even called from the setplane/atomic path.
> 
> If update() is called we don't need flip_prepare() since flip_prepare()
> is only for the fast path where we just update the fence.
> 
> > 
> > Oh and another related scenario also came to mind. Consider for
> > example
> > the follow sequence of events:
> > 
> > 1. fbc enabled on pipe A
> > 2. flip scheduled on pipe A which requires fbc to be disabled
> >    -> fbc gets disabled
> > 4. modeset on pipe B calls fbc_update
> >    -> fbc gets re-enabled on pipe A before the flip has finished,
> > oops!
> 
> If we have FBC disabled on pipe A before the pipe B modeset, then pipe
> B calls fbc_update(), I just can't see how FBC may get re-enabled on
> pipe A. Can you please elaborate more?

Last time I looked fbc_update() just went rummaging through all crtcs
and picked one of them. Maybe it no longer does that? Or maybe it still
disables fbc entirely when multiple pipes are active?

> 
> 
> I know we should avoid regressions in the middle of the series, but as
> a side-comment, the multi-pipe scenario changes even more later in the
> series at the point where we introduce
> enable/disable+activate/deactivate. So we'd only get FBC on pipe B if
> we get a ilk_crtc_disable(pipe_a) first.
> 
> Besides, my plan here is to enable FBC only on HSW+, and these
> platforms restrict FBC to pipe A. Of course I'm trying to not introduce
> any new bugs, but I also think we shouldn't block patches just because
> some ILK-IVB bug was not addressed.
> 
> > 
> > So we also need something to keep fbc reliably disabled until the
> > flip has occured.
> > 
> > > 
> > > > 
> > > > > 
> > > > > What I had was:
> > > > > "
> > > > > static bool intel_fbc_need_reinit(struct intel_crtc *crtc)
> > > > > {
> > > > > 	struct drm_i915_private *dev_priv = crtc->base.dev-
> > > > > > dev_private;
> > > > > 	struct drm_framebuffer *fb = crtc->base.primary->fb;
> > > > > 	struct drm_i915_gem_object *obj =
> > > > > to_intel_framebuffer(fb)-
> > > > > > obj;
> > > > > 
> > > > > 	return crtc != dev_priv->fbc.crtc ||
> > > > > 	       obj->base.size > dev_priv->fbc.size ||
> > > > > 	       drm_format_plane_cpp(fb->pixel_format, 0) !=
> > > > > 	       drm_format_plane_cpp(dev_priv->fbc.pixel_format, 
> > > > > 0) ||
> > > > > 	       fb->pitches[0] != dev_priv->fbc.pitch;
> > > > > }
> > > > > intel_fbc_pre_page_flip()
> > > > > {
> > > > > 	...
> > > > > 	intel_fbc_update_pending_score(crtc);
> > > > > 
> > > > > 	/*
> > > > > 	 * If fbc was already possible we can update
> > > > > immediately,
> > > > > 	 * otherwise we will wait until the flip is finished.
> > > > > 	 */
> > > > > 	if (crtc->fbc.score != 0)
> > > > > 		crtc->fbc.score = crtc->fbc.pending_score;
> > > > > 
> > > > > 	/*
> > > > > 	 * Disable fbc if we're not (yet) capable, or if
> > > > > 	 * we just need a full disable+enable reinit.
> > > > > 	 */
> > > > > 	if (crtc->fbc.score == 0 ||
> > > > > intel_fbc_need_reinit(crtc))
> > > > > 		__intel_fbc_disable(crtc);
> > > > > 	...
> > > > > }
> > > > > "
> > > > > 
> > > > > > +	} else if (dev_priv->fbc.fbc_work) {
> > > > > > +		fbc_bits = INTEL_FRONTBUFFER_PRIMARY(
> > > > > > +				dev_priv->fbc.fbc_work-
> > > > > > >crtc-
> > > > > > > pipe);
> > > > > > +		if (fbc_bits & frontbuffer_bits)
> > > > > > +			__intel_fbc_disable(dev_priv);
> > > > > >  	}
> > > > > >  
> > > > > >  	mutex_unlock(&dev_priv->fbc.lock);
> > > > > > @@ -1063,18 +1155,25 @@ void intel_fbc_init(struct
> > > > > > drm_i915_private
> > > > > > *dev_priv)
> > > > > >  		dev_priv->fbc.fbc_enabled = ilk_fbc_enabled;
> > > > > >  		dev_priv->fbc.enable_fbc = gen7_fbc_enable;
> > > > > >  		dev_priv->fbc.disable_fbc = ilk_fbc_disable;
> > > > > > +		dev_priv->fbc.flip_prepare =
> > > > > > snb_fbc_flip_prepare;
> > > > > >  	} else if (INTEL_INFO(dev_priv)->gen >= 5) {
> > > > > >  		dev_priv->fbc.fbc_enabled = ilk_fbc_enabled;
> > > > > >  		dev_priv->fbc.enable_fbc = ilk_fbc_enable;
> > > > > >  		dev_priv->fbc.disable_fbc = ilk_fbc_disable;
> > > > > > +		if (INTEL_INFO(dev_priv)->gen == 5)
> > > > > > +			dev_priv->fbc.flip_prepare =
> > > > > > ilk_fbc_flip_prepare;
> > > > > > +		else
> > > > > > +			dev_priv->fbc.flip_prepare =
> > > > > > snb_fbc_flip_prepare;
> > > > > >  	} else if (IS_GM45(dev_priv)) {
> > > > > >  		dev_priv->fbc.fbc_enabled = g4x_fbc_enabled;
> > > > > >  		dev_priv->fbc.enable_fbc = g4x_fbc_enable;
> > > > > >  		dev_priv->fbc.disable_fbc = g4x_fbc_disable;
> > > > > > +		dev_priv->fbc.flip_prepare =
> > > > > > g4x_fbc_flip_prepare;
> > > > > >  	} else {
> > > > > >  		dev_priv->fbc.fbc_enabled =
> > > > > > i8xx_fbc_enabled;
> > > > > >  		dev_priv->fbc.enable_fbc = i8xx_fbc_enable;
> > > > > >  		dev_priv->fbc.disable_fbc =
> > > > > > i8xx_fbc_disable;
> > > > > > +		dev_priv->fbc.flip_prepare =
> > > > > > i8xx_fbc_flip_prepare;
> > > > > >  
> > > > > >  		/* This value was pulled out of someone's
> > > > > > hat */
> > > > > >  		I915_WRITE(FBC_CONTROL, 500 <<
> > > > > > FBC_CTL_INTERVAL_SHIFT);
> > > > > > diff --git a/drivers/gpu/drm/i915/intel_frontbuffer.c
> > > > > > b/drivers/gpu/drm/i915/intel_frontbuffer.c
> > > > > > index ac85357..31a1ad3 100644
> > > > > > --- a/drivers/gpu/drm/i915/intel_frontbuffer.c
> > > > > > +++ b/drivers/gpu/drm/i915/intel_frontbuffer.c
> > > > > > @@ -192,6 +192,7 @@ void
> > > > > > intel_frontbuffer_flip_prepare(struct
> > > > > > drm_device *dev,
> > > > > >  	mutex_unlock(&dev_priv->fb_tracking.lock);
> > > > > >  
> > > > > >  	intel_psr_single_frame_update(dev,
> > > > > > frontbuffer_bits);
> > > > > > +	intel_fbc_flip_prepare(dev_priv, frontbuffer_bits);
> > > > > >  }
> > > > > >  
> > > > > >  /**
> > > > > > -- 
> > > > > > 2.6.1
> > > > > > 
> > > > > > _______________________________________________
> > > > > > Intel-gfx mailing list
> > > > > > Intel-gfx@lists.freedesktop.org
> > > > > > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> > > > > 
> > > 
> > > -- 
> > > Ville Syrjälä
> > > Intel OTC
> > > _______________________________________________
> > > Intel-gfx mailing list
> > > Intel-gfx@lists.freedesktop.org
> > > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> > 

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 19/26] drm/i915: move adjusted_mode checks from fbc_update to fbc_enable
  2015-10-29 17:58     ` Zanoni, Paulo R
@ 2015-11-02  8:53       ` Maarten Lankhorst
  0 siblings, 0 replies; 44+ messages in thread
From: Maarten Lankhorst @ 2015-11-02  8:53 UTC (permalink / raw)
  To: Zanoni, Paulo R, intel-gfx@lists.freedesktop.org

Op 29-10-15 om 18:58 schreef Zanoni, Paulo R:
> Em Qui, 2015-10-29 às 13:59 +0100, Maarten Lankhorst escreveu:
>> Op 27-10-15 om 17:50 schreef Paulo Zanoni:
>>> These things can't change without a full modeset.
>> False! Fastset can update parameters too. Although I don't think it
>> currently prevents DBLSCAN updates,
>> so maybe make sure cfb enable/disable is called when updating pipe
>> too?
> You mean that if we change for an interlaced (or double-scanned) to a
> non-interlaced (or non-double-scanned) mode we won't get
> crtc_disable+crtc_enable? That's surprising. I'll take a better look
> here and try to write a test case. Is this just through some specific
> API (like drmModeSetPlane)?
>
> I'm trying to get test cases for every single bug I discover or
> introduce.
>
Yeah if it does happen it's a bug though. :)

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

^ permalink raw reply	[flat|nested] 44+ messages in thread

end of thread, other threads:[~2015-11-02  8:53 UTC | newest]

Thread overview: 44+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-10-27 16:50 [PATCH 00/26] Yet another FBC series, v2 Paulo Zanoni
2015-10-27 16:50 ` [PATCH 01/26] drm/i915: change no_fbc_reason from enum to string Paulo Zanoni
2015-10-27 16:50 ` [PATCH 02/26] drm/i915: don't stop+start FBC at every flip Paulo Zanoni
2015-10-27 18:32   ` Ville Syrjälä
2015-10-28 16:56     ` Zanoni, Paulo R
2015-10-28 17:20       ` Ville Syrjälä
2015-10-29 12:05         ` Maarten Lankhorst
2015-10-29 17:30         ` Ville Syrjälä
2015-10-29 17:52           ` Zanoni, Paulo R
2015-10-29 18:14             ` Ville Syrjälä
2015-10-27 19:50   ` Chris Wilson
2015-10-28 16:58     ` Zanoni, Paulo R
2015-10-27 16:50 ` [PATCH 03/26] drm/i915: rename intel_fbc_nuke to intel_fbc_recompress Paulo Zanoni
2015-10-27 16:50 ` [PATCH 04/26] drm/i915: only nuke FBC when a drawing operation triggers a flush Paulo Zanoni
2015-10-27 16:50 ` [PATCH 05/26] drm/i915: extract fbc_on_pipe_a_only() Paulo Zanoni
2015-10-29 12:05   ` Maarten Lankhorst
2015-10-29 15:55     ` Zanoni, Paulo R
2015-10-27 16:50 ` [PATCH 06/26] drm/i915: remove unnecessary check for crtc->primary->fb Paulo Zanoni
2015-10-27 16:50 ` [PATCH 07/26] drm/i915: extract crtc_is_valid() on the FBC code Paulo Zanoni
2015-10-27 16:50 ` [PATCH 08/26] drm/i915: set dev_priv->fbc.crtc before scheduling the enable work Paulo Zanoni
2015-10-27 16:50 ` [PATCH 09/26] drm/i915: use struct intel_crtc *crtc at __intel_fbc_update() Paulo Zanoni
2015-10-27 16:50 ` [PATCH 10/26] drm/i915: fix the __intel_fbc_update() comments Paulo Zanoni
2015-10-27 16:50 ` [PATCH 11/26] drm/i915: pass the crtc as an argument to intel_fbc_update() Paulo Zanoni
2015-10-27 16:50 ` [PATCH 12/26] drm/i915: don't disable_fbc() if FBC is already disabled Paulo Zanoni
2015-10-27 16:50 ` [PATCH 13/26] drm/i915: introduce is_active/activate/deactivate to the FBC terminology Paulo Zanoni
2015-10-27 16:50 ` [PATCH 14/26] drm/i915: refactor FBC deactivation at init Paulo Zanoni
2015-10-27 16:50 ` [PATCH 15/26] drm/i915: introduce intel_fbc_{enable, disable} Paulo Zanoni
2015-10-27 16:50 ` [PATCH 16/26] drm/i915: remove too-frequent FBC debug message Paulo Zanoni
2015-10-27 16:50 ` [PATCH 17/26] drm/i915: fix the CFB size check Paulo Zanoni
2015-10-27 16:50 ` [PATCH 18/26] drm/i915: alloc/free the FBC CFB during enable/disable Paulo Zanoni
2015-10-27 16:50 ` [PATCH 19/26] drm/i915: move adjusted_mode checks from fbc_update to fbc_enable Paulo Zanoni
2015-10-29 12:59   ` Maarten Lankhorst
2015-10-29 17:58     ` Zanoni, Paulo R
2015-11-02  8:53       ` Maarten Lankhorst
2015-10-27 16:50 ` [PATCH 20/26] drm/i915: move clock frequency " Paulo Zanoni
2015-10-27 16:50 ` [PATCH 21/26] drm/i915: check for FBC planes in the same place as the pipes Paulo Zanoni
2015-10-27 16:50 ` [PATCH 22/26] drm/i915: clarify that checking the FB stride for CFB is intentional Paulo Zanoni
2015-10-27 16:50 ` [PATCH 23/26] drm/i915: use a single intel_fbc_work struct Paulo Zanoni
2015-10-27 20:29   ` Chris Wilson
2015-10-28 17:24     ` Zanoni, Paulo R
2015-10-28 17:40       ` chris
2015-10-27 16:50 ` [PATCH 24/26] drm/i915: wait for a vblank instead of 50ms when enabling FBC Paulo Zanoni
2015-10-27 16:50 ` [PATCH 25/26] drm/i915: remove in_dbg_master check from intel_fbc.c Paulo Zanoni
2015-10-27 16:50 ` [PATCH 26/26] drm/i915: kill fbc.uncompressed_size Paulo Zanoni

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox