All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] drm/i915: Fix vblank timestamp/frame counter jumps on gen2
@ 2017-11-13 15:32 Ville Syrjala
  2017-11-13 15:32 ` [PATCH 2/2] drm/i915: Wait for pipe to start on i830 as well Ville Syrjala
                   ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: Ville Syrjala @ 2017-11-13 15:32 UTC (permalink / raw)
  To: intel-gfx; +Cc: stable, Daniel Vetter

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Previously I was under the impression that the scanline counter
reads 0 when the pipe is off. Turns out that's not correct, and
instead the scanline counter simply stops when the pipe stops, and
it retains it's last value until the pipe starts up again, at which
point the scanline counter jumps to vblank start.

These jumps can cause the timestamp to jump backwards by one frame.
Since we use the timestamps to guesstimage also the frame counter
value on gen2, that would cause the frame counter to also jump
backwards, which leads to a massice difference from the previous value.
The end result is that flips/vblank events don't appear to complete as
they're stuck waiting for the frame counter to catch up to that massive
difference.

Fix the problem properly by actually making sure the scanline counter
has started to move before we assume that it's safe to enable vblank
processing.

Cc: stable@vger.kernel.org
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Fixes: b7792d8b54cc ("drm/i915: Wait for pipe to start before sampling vblank timestamps on gen2")
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 34 ++++++++++++++++++++++------------
 1 file changed, 22 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 0ebf3f283b87..810b1147a0ac 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -998,7 +998,8 @@ enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv,
 	return crtc->config->cpu_transcoder;
 }
 
-static bool pipe_dsl_stopped(struct drm_i915_private *dev_priv, enum pipe pipe)
+static bool pipe_dsl_stopped(struct drm_i915_private *dev_priv,
+			     enum pipe pipe, bool stopped)
 {
 	i915_reg_t reg = PIPEDSL(pipe);
 	u32 line1, line2;
@@ -1013,7 +1014,7 @@ static bool pipe_dsl_stopped(struct drm_i915_private *dev_priv, enum pipe pipe)
 	msleep(5);
 	line2 = I915_READ(reg) & line_mask;
 
-	return line1 == line2;
+	return (line1 == line2) == stopped;
 }
 
 /*
@@ -1048,11 +1049,21 @@ static void intel_wait_for_pipe_off(struct intel_crtc *crtc)
 			WARN(1, "pipe_off wait timed out\n");
 	} else {
 		/* Wait for the display line to settle */
-		if (wait_for(pipe_dsl_stopped(dev_priv, pipe), 100))
+		if (wait_for(pipe_dsl_stopped(dev_priv, pipe, true), 100))
 			WARN(1, "pipe_off wait timed out\n");
 	}
 }
 
+static void intel_wait_for_pipe_on(struct intel_crtc *crtc)
+{
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+	enum pipe pipe = crtc->pipe;
+
+	/* Wait for the display line to start moving */
+	if (wait_for(pipe_dsl_stopped(dev_priv, pipe, false), 100))
+		WARN(1, "pipe_on wait timed out\n");
+}
+
 /* Only for pre-ILK configs */
 void assert_pll(struct drm_i915_private *dev_priv,
 		enum pipe pipe, bool state)
@@ -1935,15 +1946,14 @@ static void intel_enable_pipe(struct intel_crtc *crtc)
 	POSTING_READ(reg);
 
 	/*
-	 * Until the pipe starts DSL will read as 0, which would cause
-	 * an apparent vblank timestamp jump, which messes up also the
-	 * frame count when it's derived from the timestamps. So let's
-	 * wait for the pipe to start properly before we call
-	 * drm_crtc_vblank_on()
+	 * Until the pipe starts DSL can give a bogus value, which cause
+	 * an apparent vblank timestamp jump when the DSL resets to its
+	 * proper value, which messes up also the frame count when it's
+	 * derived from the timestamps. So let's wait for the pipe to
+	 * start properly before we call drm_crtc_vblank_on()
 	 */
-	if (dev->max_vblank_count == 0 &&
-	    wait_for(intel_get_crtc_scanline(crtc) != crtc->scanline_offset, 50))
-		DRM_ERROR("pipe %c didn't start\n", pipe_name(pipe));
+	if (dev->max_vblank_count == 0)
+		intel_wait_for_pipe_on(crtc);
 }
 
 /**
@@ -14707,7 +14717,7 @@ void i830_disable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe)
 	I915_WRITE(PIPECONF(pipe), 0);
 	POSTING_READ(PIPECONF(pipe));
 
-	if (wait_for(pipe_dsl_stopped(dev_priv, pipe), 100))
+	if (wait_for(pipe_dsl_stopped(dev_priv, pipe, true), 100))
 		DRM_ERROR("pipe %c off wait timed out\n", pipe_name(pipe));
 
 	I915_WRITE(DPLL(pipe), DPLL_VGA_MODE_DIS);
-- 
2.13.6

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

* [PATCH 2/2] drm/i915: Wait for pipe to start on i830 as well
  2017-11-13 15:32 [PATCH 1/2] drm/i915: Fix vblank timestamp/frame counter jumps on gen2 Ville Syrjala
@ 2017-11-13 15:32 ` Ville Syrjala
  2017-11-13 21:05   ` Chris Wilson
  2017-11-13 16:13 ` ✓ Fi.CI.BAT: success for series starting with [1/2] drm/i915: Fix vblank timestamp/frame counter jumps on gen2 Patchwork
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 8+ messages in thread
From: Ville Syrjala @ 2017-11-13 15:32 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

We should make sure the pipe has fully started when we enable it from
the i830 "power well". Otherwise theoretically i830 could also hit
problems with vblank timestamps jumping around (since we skip the
wait during modeset on i830). Additionally moving planes between the
pipes etc. might not work correctly until both pipes are actually up and
running.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 810b1147a0ac..467f72df9db3 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -14704,6 +14704,9 @@ void i830_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe)
 
 	I915_WRITE(PIPECONF(pipe), PIPECONF_ENABLE | PIPECONF_PROGRESSIVE);
 	POSTING_READ(PIPECONF(pipe));
+
+	if (wait_for(pipe_dsl_stopped(dev_priv, pipe, false), 100))
+		DRM_ERROR("pipe %c on wait timed out\n", pipe_name(pipe));
 }
 
 void i830_disable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe)
-- 
2.13.6

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

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

* ✓ Fi.CI.BAT: success for series starting with [1/2] drm/i915: Fix vblank timestamp/frame counter jumps on gen2
  2017-11-13 15:32 [PATCH 1/2] drm/i915: Fix vblank timestamp/frame counter jumps on gen2 Ville Syrjala
  2017-11-13 15:32 ` [PATCH 2/2] drm/i915: Wait for pipe to start on i830 as well Ville Syrjala
@ 2017-11-13 16:13 ` Patchwork
  2017-11-13 17:00 ` ✓ Fi.CI.IGT: " Patchwork
  2017-11-13 21:03 ` [Intel-gfx] [PATCH 1/2] " Chris Wilson
  3 siblings, 0 replies; 8+ messages in thread
From: Patchwork @ 2017-11-13 16:13 UTC (permalink / raw)
  To: Ville Syrjala; +Cc: intel-gfx

== Series Details ==

Series: series starting with [1/2] drm/i915: Fix vblank timestamp/frame counter jumps on gen2
URL   : https://patchwork.freedesktop.org/series/33723/
State : success

== Summary ==

Series 33723v1 series starting with [1/2] drm/i915: Fix vblank timestamp/frame counter jumps on gen2
https://patchwork.freedesktop.org/api/1.0/series/33723/revisions/1/mbox/

Test chamelium:
        Subgroup dp-crc-fast:
                fail       -> PASS       (fi-kbl-7500u) fdo#102514
Test kms_pipe_crc_basic:
        Subgroup suspend-read-crc-pipe-b:
                incomplete -> PASS       (fi-snb-2520m) fdo#103713
                incomplete -> PASS       (fi-kbl-7560u) fdo#103706 +1
Test vgem_basic:
        Subgroup dmabuf-export:
                pass       -> INCOMPLETE (fi-byt-n2820) fdo#103714
        Subgroup unload:
                notrun     -> INCOMPLETE (fi-snb-2520m) fdo#103702 +1

fdo#102514 https://bugs.freedesktop.org/show_bug.cgi?id=102514
fdo#103713 https://bugs.freedesktop.org/show_bug.cgi?id=103713
fdo#103706 https://bugs.freedesktop.org/show_bug.cgi?id=103706
fdo#103714 https://bugs.freedesktop.org/show_bug.cgi?id=103714
fdo#103702 https://bugs.freedesktop.org/show_bug.cgi?id=103702

fi-bdw-5557u     total:285  pass:263  dwarn:0   dfail:1   fail:0   skip:20 
fi-bdw-gvtdvm    total:285  pass:260  dwarn:0   dfail:1   fail:0   skip:23 
fi-blb-e6850     total:285  pass:218  dwarn:1   dfail:1   fail:0   skip:64 
fi-bsw-n3050     total:285  pass:238  dwarn:0   dfail:1   fail:0   skip:45 
fi-bwr-2160      total:285  pass:178  dwarn:0   dfail:1   fail:0   skip:105
fi-bxt-dsi       total:285  pass:254  dwarn:0   dfail:1   fail:0   skip:29 
fi-bxt-j4205     total:278  pass:248  dwarn:0   dfail:1   fail:0   skip:28 
fi-byt-j1900     total:285  pass:249  dwarn:0   dfail:1   fail:0   skip:34 
fi-byt-n2820     total:278  pass:238  dwarn:0   dfail:1   fail:0   skip:38 
fi-elk-e7500     total:285  pass:224  dwarn:0   dfail:1   fail:0   skip:59 
fi-gdg-551       total:285  pass:174  dwarn:0   dfail:1   fail:1   skip:108
fi-glk-1         total:285  pass:256  dwarn:0   dfail:1   fail:0   skip:27 
fi-hsw-4770      total:285  pass:257  dwarn:0   dfail:1   fail:0   skip:26 
fi-hsw-4770r     total:285  pass:257  dwarn:0   dfail:1   fail:0   skip:26 
fi-ilk-650       total:285  pass:223  dwarn:0   dfail:1   fail:0   skip:60 
fi-ivb-3520m     total:285  pass:255  dwarn:0   dfail:1   fail:0   skip:28 
fi-ivb-3770      total:285  pass:255  dwarn:0   dfail:1   fail:0   skip:28 
fi-kbl-7500u     total:285  pass:259  dwarn:1   dfail:1   fail:0   skip:23 
fi-kbl-7560u     total:285  pass:265  dwarn:0   dfail:1   fail:0   skip:18 
fi-kbl-7567u     total:285  pass:264  dwarn:0   dfail:1   fail:0   skip:19 
fi-kbl-r         total:285  pass:257  dwarn:0   dfail:1   fail:0   skip:26 
fi-pnv-d510      total:285  pass:217  dwarn:1   dfail:1   fail:0   skip:65 
fi-skl-6260u     total:285  pass:264  dwarn:0   dfail:1   fail:0   skip:19 
fi-skl-6600u     total:285  pass:257  dwarn:0   dfail:1   fail:0   skip:26 
fi-skl-6700hq    total:285  pass:258  dwarn:0   dfail:1   fail:0   skip:25 
fi-skl-6700k     total:285  pass:260  dwarn:0   dfail:1   fail:0   skip:23 
fi-skl-6770hq    total:285  pass:264  dwarn:0   dfail:1   fail:0   skip:19 
fi-skl-gvtdvm    total:285  pass:261  dwarn:0   dfail:1   fail:0   skip:22 
fi-snb-2520m     total:285  pass:245  dwarn:0   dfail:1   fail:0   skip:38 
fi-snb-2600      total:285  pass:244  dwarn:0   dfail:1   fail:0   skip:39 
Blacklisted hosts:
fi-cfl-s         total:285  pass:252  dwarn:0   dfail:1   fail:0   skip:31 
fi-cnl-y failed to connect after reboot
fi-glk-dsi failed to connect after reboot

9a81c142768eb620a24b02a136716a44c304563f drm-tip: 2017y-11m-13d-11h-44m-54s UTC integration manifest
549205ad6192 drm/i915: Wait for pipe to start on i830 as well
a8dd076b98e1 drm/i915: Fix vblank timestamp/frame counter jumps on gen2

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_7095/
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* ✓ Fi.CI.IGT: success for series starting with [1/2] drm/i915: Fix vblank timestamp/frame counter jumps on gen2
  2017-11-13 15:32 [PATCH 1/2] drm/i915: Fix vblank timestamp/frame counter jumps on gen2 Ville Syrjala
  2017-11-13 15:32 ` [PATCH 2/2] drm/i915: Wait for pipe to start on i830 as well Ville Syrjala
  2017-11-13 16:13 ` ✓ Fi.CI.BAT: success for series starting with [1/2] drm/i915: Fix vblank timestamp/frame counter jumps on gen2 Patchwork
@ 2017-11-13 17:00 ` Patchwork
  2017-11-13 21:03 ` [Intel-gfx] [PATCH 1/2] " Chris Wilson
  3 siblings, 0 replies; 8+ messages in thread
From: Patchwork @ 2017-11-13 17:00 UTC (permalink / raw)
  To: Ville Syrjala; +Cc: intel-gfx

== Series Details ==

Series: series starting with [1/2] drm/i915: Fix vblank timestamp/frame counter jumps on gen2
URL   : https://patchwork.freedesktop.org/series/33723/
State : success

== Summary ==

Test vgem_basic:
        Subgroup debugfs:
                dmesg-fail -> INCOMPLETE (shard-hsw) fdo#103703
Test drv_module_reload:
        Subgroup basic-reload:
                pass       -> DMESG-WARN (shard-hsw) fdo#102707 +1

fdo#103703 https://bugs.freedesktop.org/show_bug.cgi?id=103703
fdo#102707 https://bugs.freedesktop.org/show_bug.cgi?id=102707

shard-hsw        total:2513 pass:1434 dwarn:3   dfail:1   fail:8   skip:1066 time:9260s
Blacklisted hosts:
shard-apl        total:2514 pass:1581 dwarn:3   dfail:2   fail:21  skip:906 time:12887s
shard-kbl        total:2499 pass:1655 dwarn:13  dfail:2   fail:24  skip:803 time:10261s
shard-snb        total:2471 pass:1158 dwarn:2   dfail:2   fail:11  skip:1297 time:7347s

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_7095/shards.html
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [Intel-gfx] [PATCH 1/2] drm/i915: Fix vblank timestamp/frame counter jumps on gen2
  2017-11-13 15:32 [PATCH 1/2] drm/i915: Fix vblank timestamp/frame counter jumps on gen2 Ville Syrjala
                   ` (2 preceding siblings ...)
  2017-11-13 17:00 ` ✓ Fi.CI.IGT: " Patchwork
@ 2017-11-13 21:03 ` Chris Wilson
  2017-11-13 21:32     ` Ville Syrjälä
  3 siblings, 1 reply; 8+ messages in thread
From: Chris Wilson @ 2017-11-13 21:03 UTC (permalink / raw)
  To: Ville Syrjala, intel-gfx; +Cc: Daniel Vetter, stable

Quoting Ville Syrjala (2017-11-13 15:32:14)
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Previously I was under the impression that the scanline counter
> reads 0 when the pipe is off. Turns out that's not correct, and
> instead the scanline counter simply stops when the pipe stops, and
> it retains it's last value until the pipe starts up again, at which
> point the scanline counter jumps to vblank start.
> 
> These jumps can cause the timestamp to jump backwards by one frame.
> Since we use the timestamps to guesstimage also the frame counter
> value on gen2, that would cause the frame counter to also jump
> backwards, which leads to a massice difference from the previous value.
> The end result is that flips/vblank events don't appear to complete as
> they're stuck waiting for the frame counter to catch up to that massive
> difference.
> 
> Fix the problem properly by actually making sure the scanline counter
> has started to move before we assume that it's safe to enable vblank
> processing.
> 
> Cc: stable@vger.kernel.org
> Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> Fixes: b7792d8b54cc ("drm/i915: Wait for pipe to start before sampling vblank timestamps on gen2")
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 34 ++++++++++++++++++++++------------
>  1 file changed, 22 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 0ebf3f283b87..810b1147a0ac 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -998,7 +998,8 @@ enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv,
>         return crtc->config->cpu_transcoder;
>  }
>  
> -static bool pipe_dsl_stopped(struct drm_i915_private *dev_priv, enum pipe pipe)
> +static bool pipe_dsl_stopped(struct drm_i915_private *dev_priv,
> +                            enum pipe pipe, bool stopped)
>  {
>         i915_reg_t reg = PIPEDSL(pipe);
>         u32 line1, line2;
> @@ -1013,7 +1014,7 @@ static bool pipe_dsl_stopped(struct drm_i915_private *dev_priv, enum pipe pipe)
>         msleep(5);
>         line2 = I915_READ(reg) & line_mask;
>  
> -       return line1 == line2;
> +       return (line1 == line2) == stopped;
>  }
>  
>  /*
> @@ -1048,11 +1049,21 @@ static void intel_wait_for_pipe_off(struct intel_crtc *crtc)
>                         WARN(1, "pipe_off wait timed out\n");
>         } else {
>                 /* Wait for the display line to settle */
> -               if (wait_for(pipe_dsl_stopped(dev_priv, pipe), 100))
> +               if (wait_for(pipe_dsl_stopped(dev_priv, pipe, true), 100))
>                         WARN(1, "pipe_off wait timed out\n");
>         }
>  }
>  
> +static void intel_wait_for_pipe_on(struct intel_crtc *crtc)
> +{
> +       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> +       enum pipe pipe = crtc->pipe;
> +
> +       /* Wait for the display line to start moving */
> +       if (wait_for(pipe_dsl_stopped(dev_priv, pipe, false), 100))
> +               WARN(1, "pipe_on wait timed out\n");

3 wait_for(pipe_dsl_stopped()), please make a function to only have one
expansion of that macro :)

> +}
> +
>  /* Only for pre-ILK configs */
>  void assert_pll(struct drm_i915_private *dev_priv,
>                 enum pipe pipe, bool state)
> @@ -1935,15 +1946,14 @@ static void intel_enable_pipe(struct intel_crtc *crtc)
>         POSTING_READ(reg);
>  
>         /*
> -        * Until the pipe starts DSL will read as 0, which would cause
> -        * an apparent vblank timestamp jump, which messes up also the
> -        * frame count when it's derived from the timestamps. So let's
> -        * wait for the pipe to start properly before we call
> -        * drm_crtc_vblank_on()
> +        * Until the pipe starts DSL can give a bogus value, which cause
> +        * an apparent vblank timestamp jump when the DSL resets to its
> +        * proper value, which messes up also the frame count when it's
> +        * derived from the timestamps. So let's wait for the pipe to
> +        * start properly before we call drm_crtc_vblank_on()
>          */
> -       if (dev->max_vblank_count == 0 &&
> -           wait_for(intel_get_crtc_scanline(crtc) != crtc->scanline_offset, 50))
> -               DRM_ERROR("pipe %c didn't start\n", pipe_name(pipe));
> +       if (dev->max_vblank_count == 0)
> +               intel_wait_for_pipe_on(crtc);
>  }
>  
>  /**
> @@ -14707,7 +14717,7 @@ void i830_disable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe)
>         I915_WRITE(PIPECONF(pipe), 0);
>         POSTING_READ(PIPECONF(pipe));
>  
> -       if (wait_for(pipe_dsl_stopped(dev_priv, pipe), 100))
> +       if (wait_for(pipe_dsl_stopped(dev_priv, pipe, true), 100))
>                 DRM_ERROR("pipe %c off wait timed out\n", pipe_name(pipe));

Is there a reason why we couldn't use intel_wait_for_pipe_off() here, it
gives the clearer symmetry to intel_wait_for_pipe_on()?

Other than nitpicks, the code does what it says on the tin, and it's
pretty convincing in its argument,
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
-Chris

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

* Re: [PATCH 2/2] drm/i915: Wait for pipe to start on i830 as well
  2017-11-13 15:32 ` [PATCH 2/2] drm/i915: Wait for pipe to start on i830 as well Ville Syrjala
@ 2017-11-13 21:05   ` Chris Wilson
  0 siblings, 0 replies; 8+ messages in thread
From: Chris Wilson @ 2017-11-13 21:05 UTC (permalink / raw)
  To: Ville Syrjala, intel-gfx

Quoting Ville Syrjala (2017-11-13 15:32:15)
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> We should make sure the pipe has fully started when we enable it from
> the i830 "power well". Otherwise theoretically i830 could also hit
> problems with vblank timestamps jumping around (since we skip the
> wait during modeset on i830). Additionally moving planes between the
> pipes etc. might not work correctly until both pipes are actually up and
> running.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 810b1147a0ac..467f72df9db3 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -14704,6 +14704,9 @@ void i830_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe)
>  
>         I915_WRITE(PIPECONF(pipe), PIPECONF_ENABLE | PIPECONF_PROGRESSIVE);
>         POSTING_READ(PIPECONF(pipe));
> +
> +       if (wait_for(pipe_dsl_stopped(dev_priv, pipe, false), 100))
> +               DRM_ERROR("pipe %c on wait timed out\n", pipe_name(pipe));

This seems to fit in the with the pattern of wait for vblank after
enabling, but more refined (i.e. don't wait for the whole frame, just
wait for the frame to start scanning out).

Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>

Why not intel_wait_for_pipe_on() here?
-Chris
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [Intel-gfx] [PATCH 1/2] drm/i915: Fix vblank timestamp/frame counter jumps on gen2
  2017-11-13 21:03 ` [Intel-gfx] [PATCH 1/2] " Chris Wilson
@ 2017-11-13 21:32     ` Ville Syrjälä
  0 siblings, 0 replies; 8+ messages in thread
From: Ville Syrjälä @ 2017-11-13 21:32 UTC (permalink / raw)
  To: Chris Wilson; +Cc: intel-gfx, Daniel Vetter, stable

On Mon, Nov 13, 2017 at 09:03:34PM +0000, Chris Wilson wrote:
> Quoting Ville Syrjala (2017-11-13 15:32:14)
> > From: Ville Syrj�l� <ville.syrjala@linux.intel.com>
> > 
> > Previously I was under the impression that the scanline counter
> > reads 0 when the pipe is off. Turns out that's not correct, and
> > instead the scanline counter simply stops when the pipe stops, and
> > it retains it's last value until the pipe starts up again, at which
> > point the scanline counter jumps to vblank start.
> > 
> > These jumps can cause the timestamp to jump backwards by one frame.
> > Since we use the timestamps to guesstimage also the frame counter
> > value on gen2, that would cause the frame counter to also jump
> > backwards, which leads to a massice difference from the previous value.
> > The end result is that flips/vblank events don't appear to complete as
> > they're stuck waiting for the frame counter to catch up to that massive
> > difference.
> > 
> > Fix the problem properly by actually making sure the scanline counter
> > has started to move before we assume that it's safe to enable vblank
> > processing.
> > 
> > Cc: stable@vger.kernel.org
> > Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> > Fixes: b7792d8b54cc ("drm/i915: Wait for pipe to start before sampling vblank timestamps on gen2")
> > Signed-off-by: Ville Syrj�l� <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_display.c | 34 ++++++++++++++++++++++------------
> >  1 file changed, 22 insertions(+), 12 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index 0ebf3f283b87..810b1147a0ac 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -998,7 +998,8 @@ enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv,
> >         return crtc->config->cpu_transcoder;
> >  }
> >  
> > -static bool pipe_dsl_stopped(struct drm_i915_private *dev_priv, enum pipe pipe)
> > +static bool pipe_dsl_stopped(struct drm_i915_private *dev_priv,
> > +                            enum pipe pipe, bool stopped)
> >  {
> >         i915_reg_t reg = PIPEDSL(pipe);
> >         u32 line1, line2;
> > @@ -1013,7 +1014,7 @@ static bool pipe_dsl_stopped(struct drm_i915_private *dev_priv, enum pipe pipe)
> >         msleep(5);
> >         line2 = I915_READ(reg) & line_mask;
> >  
> > -       return line1 == line2;
> > +       return (line1 == line2) == stopped;
> >  }
> >  
> >  /*
> > @@ -1048,11 +1049,21 @@ static void intel_wait_for_pipe_off(struct intel_crtc *crtc)
> >                         WARN(1, "pipe_off wait timed out\n");
> >         } else {
> >                 /* Wait for the display line to settle */
> > -               if (wait_for(pipe_dsl_stopped(dev_priv, pipe), 100))
> > +               if (wait_for(pipe_dsl_stopped(dev_priv, pipe, true), 100))
> >                         WARN(1, "pipe_off wait timed out\n");
> >         }
> >  }
> >  
> > +static void intel_wait_for_pipe_on(struct intel_crtc *crtc)
> > +{
> > +       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> > +       enum pipe pipe = crtc->pipe;
> > +
> > +       /* Wait for the display line to start moving */
> > +       if (wait_for(pipe_dsl_stopped(dev_priv, pipe, false), 100))
> > +               WARN(1, "pipe_on wait timed out\n");
> 
> 3 wait_for(pipe_dsl_stopped()), please make a function to only have one
> expansion of that macro :)
> 
> > +}
> > +
> >  /* Only for pre-ILK configs */
> >  void assert_pll(struct drm_i915_private *dev_priv,
> >                 enum pipe pipe, bool state)
> > @@ -1935,15 +1946,14 @@ static void intel_enable_pipe(struct intel_crtc *crtc)
> >         POSTING_READ(reg);
> >  
> >         /*
> > -        * Until the pipe starts DSL will read as 0, which would cause
> > -        * an apparent vblank timestamp jump, which messes up also the
> > -        * frame count when it's derived from the timestamps. So let's
> > -        * wait for the pipe to start properly before we call
> > -        * drm_crtc_vblank_on()
> > +        * Until the pipe starts DSL can give a bogus value, which cause
> > +        * an apparent vblank timestamp jump when the DSL resets to its
> > +        * proper value, which messes up also the frame count when it's
> > +        * derived from the timestamps. So let's wait for the pipe to
> > +        * start properly before we call drm_crtc_vblank_on()
> >          */
> > -       if (dev->max_vblank_count == 0 &&
> > -           wait_for(intel_get_crtc_scanline(crtc) != crtc->scanline_offset, 50))
> > -               DRM_ERROR("pipe %c didn't start\n", pipe_name(pipe));
> > +       if (dev->max_vblank_count == 0)
> > +               intel_wait_for_pipe_on(crtc);
> >  }
> >  
> >  /**
> > @@ -14707,7 +14717,7 @@ void i830_disable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe)
> >         I915_WRITE(PIPECONF(pipe), 0);
> >         POSTING_READ(PIPECONF(pipe));
> >  
> > -       if (wait_for(pipe_dsl_stopped(dev_priv, pipe), 100))
> > +       if (wait_for(pipe_dsl_stopped(dev_priv, pipe, true), 100))
> >                 DRM_ERROR("pipe %c off wait timed out\n", pipe_name(pipe));
> 
> Is there a reason why we couldn't use intel_wait_for_pipe_off() here, it
> gives the clearer symmetry to intel_wait_for_pipe_on()?

In theory we could. However if we're being pedantic wait_for_pipe_off()
should be passed a crtc state since it wants to get at the
cpu_transcoder. It's not actually a problem on gen2 since we would
never take that codepath. However it feels a bit ugly.

What I could do is try to refactor these into a nicer form for the
case where we don't have the crtc state, and then handle the
cpu_transcoder case somewhere a bit higher up.

> 
> Other than nitpicks, the code does what it says on the tin, and it's
> pretty convincing in its argument,
> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
> -Chris

-- 
Ville Syrj�l�
Intel OTC

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

* Re: [Intel-gfx] [PATCH 1/2] drm/i915: Fix vblank timestamp/frame counter jumps on gen2
@ 2017-11-13 21:32     ` Ville Syrjälä
  0 siblings, 0 replies; 8+ messages in thread
From: Ville Syrjälä @ 2017-11-13 21:32 UTC (permalink / raw)
  To: Chris Wilson; +Cc: intel-gfx, Daniel Vetter, stable

On Mon, Nov 13, 2017 at 09:03:34PM +0000, Chris Wilson wrote:
> Quoting Ville Syrjala (2017-11-13 15:32:14)
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > 
> > Previously I was under the impression that the scanline counter
> > reads 0 when the pipe is off. Turns out that's not correct, and
> > instead the scanline counter simply stops when the pipe stops, and
> > it retains it's last value until the pipe starts up again, at which
> > point the scanline counter jumps to vblank start.
> > 
> > These jumps can cause the timestamp to jump backwards by one frame.
> > Since we use the timestamps to guesstimage also the frame counter
> > value on gen2, that would cause the frame counter to also jump
> > backwards, which leads to a massice difference from the previous value.
> > The end result is that flips/vblank events don't appear to complete as
> > they're stuck waiting for the frame counter to catch up to that massive
> > difference.
> > 
> > Fix the problem properly by actually making sure the scanline counter
> > has started to move before we assume that it's safe to enable vblank
> > processing.
> > 
> > Cc: stable@vger.kernel.org
> > Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> > Fixes: b7792d8b54cc ("drm/i915: Wait for pipe to start before sampling vblank timestamps on gen2")
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_display.c | 34 ++++++++++++++++++++++------------
> >  1 file changed, 22 insertions(+), 12 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index 0ebf3f283b87..810b1147a0ac 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -998,7 +998,8 @@ enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv,
> >         return crtc->config->cpu_transcoder;
> >  }
> >  
> > -static bool pipe_dsl_stopped(struct drm_i915_private *dev_priv, enum pipe pipe)
> > +static bool pipe_dsl_stopped(struct drm_i915_private *dev_priv,
> > +                            enum pipe pipe, bool stopped)
> >  {
> >         i915_reg_t reg = PIPEDSL(pipe);
> >         u32 line1, line2;
> > @@ -1013,7 +1014,7 @@ static bool pipe_dsl_stopped(struct drm_i915_private *dev_priv, enum pipe pipe)
> >         msleep(5);
> >         line2 = I915_READ(reg) & line_mask;
> >  
> > -       return line1 == line2;
> > +       return (line1 == line2) == stopped;
> >  }
> >  
> >  /*
> > @@ -1048,11 +1049,21 @@ static void intel_wait_for_pipe_off(struct intel_crtc *crtc)
> >                         WARN(1, "pipe_off wait timed out\n");
> >         } else {
> >                 /* Wait for the display line to settle */
> > -               if (wait_for(pipe_dsl_stopped(dev_priv, pipe), 100))
> > +               if (wait_for(pipe_dsl_stopped(dev_priv, pipe, true), 100))
> >                         WARN(1, "pipe_off wait timed out\n");
> >         }
> >  }
> >  
> > +static void intel_wait_for_pipe_on(struct intel_crtc *crtc)
> > +{
> > +       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> > +       enum pipe pipe = crtc->pipe;
> > +
> > +       /* Wait for the display line to start moving */
> > +       if (wait_for(pipe_dsl_stopped(dev_priv, pipe, false), 100))
> > +               WARN(1, "pipe_on wait timed out\n");
> 
> 3 wait_for(pipe_dsl_stopped()), please make a function to only have one
> expansion of that macro :)
> 
> > +}
> > +
> >  /* Only for pre-ILK configs */
> >  void assert_pll(struct drm_i915_private *dev_priv,
> >                 enum pipe pipe, bool state)
> > @@ -1935,15 +1946,14 @@ static void intel_enable_pipe(struct intel_crtc *crtc)
> >         POSTING_READ(reg);
> >  
> >         /*
> > -        * Until the pipe starts DSL will read as 0, which would cause
> > -        * an apparent vblank timestamp jump, which messes up also the
> > -        * frame count when it's derived from the timestamps. So let's
> > -        * wait for the pipe to start properly before we call
> > -        * drm_crtc_vblank_on()
> > +        * Until the pipe starts DSL can give a bogus value, which cause
> > +        * an apparent vblank timestamp jump when the DSL resets to its
> > +        * proper value, which messes up also the frame count when it's
> > +        * derived from the timestamps. So let's wait for the pipe to
> > +        * start properly before we call drm_crtc_vblank_on()
> >          */
> > -       if (dev->max_vblank_count == 0 &&
> > -           wait_for(intel_get_crtc_scanline(crtc) != crtc->scanline_offset, 50))
> > -               DRM_ERROR("pipe %c didn't start\n", pipe_name(pipe));
> > +       if (dev->max_vblank_count == 0)
> > +               intel_wait_for_pipe_on(crtc);
> >  }
> >  
> >  /**
> > @@ -14707,7 +14717,7 @@ void i830_disable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe)
> >         I915_WRITE(PIPECONF(pipe), 0);
> >         POSTING_READ(PIPECONF(pipe));
> >  
> > -       if (wait_for(pipe_dsl_stopped(dev_priv, pipe), 100))
> > +       if (wait_for(pipe_dsl_stopped(dev_priv, pipe, true), 100))
> >                 DRM_ERROR("pipe %c off wait timed out\n", pipe_name(pipe));
> 
> Is there a reason why we couldn't use intel_wait_for_pipe_off() here, it
> gives the clearer symmetry to intel_wait_for_pipe_on()?

In theory we could. However if we're being pedantic wait_for_pipe_off()
should be passed a crtc state since it wants to get at the
cpu_transcoder. It's not actually a problem on gen2 since we would
never take that codepath. However it feels a bit ugly.

What I could do is try to refactor these into a nicer form for the
case where we don't have the crtc state, and then handle the
cpu_transcoder case somewhere a bit higher up.

> 
> Other than nitpicks, the code does what it says on the tin, and it's
> pretty convincing in its argument,
> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
> -Chris

-- 
Ville Syrjälä
Intel OTC

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

end of thread, other threads:[~2017-11-13 21:32 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-11-13 15:32 [PATCH 1/2] drm/i915: Fix vblank timestamp/frame counter jumps on gen2 Ville Syrjala
2017-11-13 15:32 ` [PATCH 2/2] drm/i915: Wait for pipe to start on i830 as well Ville Syrjala
2017-11-13 21:05   ` Chris Wilson
2017-11-13 16:13 ` ✓ Fi.CI.BAT: success for series starting with [1/2] drm/i915: Fix vblank timestamp/frame counter jumps on gen2 Patchwork
2017-11-13 17:00 ` ✓ Fi.CI.IGT: " Patchwork
2017-11-13 21:03 ` [Intel-gfx] [PATCH 1/2] " Chris Wilson
2017-11-13 21:32   ` Ville Syrjälä
2017-11-13 21:32     ` Ville Syrjälä

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.