diff mbox

drm/i915: fix overlay on i830M

Message ID 1350903355-2102-1-git-send-email-daniel.vetter@ffwll.ch (mailing list archive)
State New, archived
Headers show

Commit Message

Daniel Vetter Oct. 22, 2012, 10:55 a.m. UTC
The overlay on the i830M has a peculiar failure mode: It works the
first time around after boot-up, but consistenly hangs the second time
it's used.

Chris Wilson has dug out a nice errata:

"1.5.12 Clock Gating Disable for Display Register
Address Offset:	06200h–06203h

"Bit 3
Ovrunit Clock Gating Disable.
0 = Clock gating controlled by unit enabling logic
1 = Disable clock gating function
DevALM Errata ALM049: Overlay Clock Gating Must be Disabled:  Overlay
& L2 Cache clock gating must be disabled in order to prevent device
hangs when turning off overlay.SW must turn off Ovrunit clock gating
(6200h) and L2 Cache clock gating (C8h)."

Now I've nowhere found that 0xc8 register and hence couldn't apply the
l2 cache workaround. But I've remembered that part of the magic that
the OVERLAY_ON/OFF commands are supposed to do is to rearrange cache
allocations so that the overlay scaler has some scratch space.

And while pondering how that could explain the hang the 2nd time we
enable the overlay, I've remembered that the old ums overlay code did
_not_ issue the OVERLAY_OFF cmd.

And indeed, disabling the OFF cmd results in the overlay working
flawlessly, so I guess we can workaround the lack of the above
workaround by simply never disabling the overlay engine once it's
enabled.

v2: Add a comment in the code.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=47827
Cc: stable@vger.kernel.org
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_overlay.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

Comments

Daniel Vetter Oct. 23, 2012, 9:12 a.m. UTC | #1
On Mon, Oct 22, 2012 at 12:55:55PM +0200, Daniel Vetter wrote:
> The overlay on the i830M has a peculiar failure mode: It works the
> first time around after boot-up, but consistenly hangs the second time
> it's used.
> 
> Chris Wilson has dug out a nice errata:
> 
> "1.5.12 Clock Gating Disable for Display Register
> Address Offset:	06200h–06203h
> 
> "Bit 3
> Ovrunit Clock Gating Disable.
> 0 = Clock gating controlled by unit enabling logic
> 1 = Disable clock gating function
> DevALM Errata ALM049: Overlay Clock Gating Must be Disabled:  Overlay
> & L2 Cache clock gating must be disabled in order to prevent device
> hangs when turning off overlay.SW must turn off Ovrunit clock gating
> (6200h) and L2 Cache clock gating (C8h)."
> 
> Now I've nowhere found that 0xc8 register and hence couldn't apply the
> l2 cache workaround. But I've remembered that part of the magic that
> the OVERLAY_ON/OFF commands are supposed to do is to rearrange cache
> allocations so that the overlay scaler has some scratch space.
> 
> And while pondering how that could explain the hang the 2nd time we
> enable the overlay, I've remembered that the old ums overlay code did
> _not_ issue the OVERLAY_OFF cmd.
> 
> And indeed, disabling the OFF cmd results in the overlay working
> flawlessly, so I guess we can workaround the lack of the above
> workaround by simply never disabling the overlay engine once it's
> enabled.
> 
> v2: Add a comment in the code.
> 
> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=47827
> Cc: stable@vger.kernel.org
> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>

Tested-by: Rhys <rhyspuk@gmail.com>

> ---
>  drivers/gpu/drm/i915/intel_overlay.c | 14 +++++++++++---
>  1 file changed, 11 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c
> index 555912f..e3b095f 100644
> --- a/drivers/gpu/drm/i915/intel_overlay.c
> +++ b/drivers/gpu/drm/i915/intel_overlay.c
> @@ -342,9 +342,17 @@ static int intel_overlay_off(struct intel_overlay *overlay)
>  	intel_ring_emit(ring, flip_addr);
>  	intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
>  	/* turn overlay off */
> -	intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
> -	intel_ring_emit(ring, flip_addr);
> -	intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
> +	if (IS_I830(dev)) {
> +		/* Workaround: Don't disable the overlay fully, since otherwise
> +		 * it dies on the next OVERLAY_ON cmd. */
> +		intel_ring_emit(ring, MI_NOOP);
> +		intel_ring_emit(ring, MI_NOOP);
> +		intel_ring_emit(ring, MI_NOOP);
> +	} else {
> +		intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
> +		intel_ring_emit(ring, flip_addr);
> +		intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
> +	}
>  	intel_ring_advance(ring);
>  
>  	return intel_overlay_do_wait_request(overlay, intel_overlay_off_tail);
> -- 
> 1.7.11.4
>
Chris Wilson Oct. 23, 2012, 9:56 a.m. UTC | #2
On Tue, 23 Oct 2012 11:12:02 +0200, Daniel Vetter <daniel@ffwll.ch> wrote:
> On Mon, Oct 22, 2012 at 12:55:55PM +0200, Daniel Vetter wrote:
> > The overlay on the i830M has a peculiar failure mode: It works the
> > first time around after boot-up, but consistenly hangs the second time
> > it's used.
> > 
> > Chris Wilson has dug out a nice errata:
> > 
> > "1.5.12 Clock Gating Disable for Display Register
> > Address Offset:	06200h–06203h
> > 
> > "Bit 3
> > Ovrunit Clock Gating Disable.
> > 0 = Clock gating controlled by unit enabling logic
> > 1 = Disable clock gating function
> > DevALM Errata ALM049: Overlay Clock Gating Must be Disabled:  Overlay
> > & L2 Cache clock gating must be disabled in order to prevent device
> > hangs when turning off overlay.SW must turn off Ovrunit clock gating
> > (6200h) and L2 Cache clock gating (C8h)."
> > 
> > Now I've nowhere found that 0xc8 register and hence couldn't apply the
> > l2 cache workaround. But I've remembered that part of the magic that
> > the OVERLAY_ON/OFF commands are supposed to do is to rearrange cache
> > allocations so that the overlay scaler has some scratch space.
> > 
> > And while pondering how that could explain the hang the 2nd time we
> > enable the overlay, I've remembered that the old ums overlay code did
> > _not_ issue the OVERLAY_OFF cmd.
> > 
> > And indeed, disabling the OFF cmd results in the overlay working
> > flawlessly, so I guess we can workaround the lack of the above
> > workaround by simply never disabling the overlay engine once it's
> > enabled.
> > 
> > v2: Add a comment in the code.
> > 
> > Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=47827
> > Cc: stable@vger.kernel.org
> > Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> 
> Tested-by: Rhys <rhyspuk@gmail.com>

If you care to mention that you are not turning off the old w/a in case
it has further side-effects,

Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
-Chris
Daniel Vetter Oct. 23, 2012, 10:59 a.m. UTC | #3
On Tue, Oct 23, 2012 at 10:56:46AM +0100, Chris Wilson wrote:
> On Tue, 23 Oct 2012 11:12:02 +0200, Daniel Vetter <daniel@ffwll.ch> wrote:
> > On Mon, Oct 22, 2012 at 12:55:55PM +0200, Daniel Vetter wrote:
> > > The overlay on the i830M has a peculiar failure mode: It works the
> > > first time around after boot-up, but consistenly hangs the second time
> > > it's used.
> > > 
> > > Chris Wilson has dug out a nice errata:
> > > 
> > > "1.5.12 Clock Gating Disable for Display Register
> > > Address Offset:	06200h–06203h
> > > 
> > > "Bit 3
> > > Ovrunit Clock Gating Disable.
> > > 0 = Clock gating controlled by unit enabling logic
> > > 1 = Disable clock gating function
> > > DevALM Errata ALM049: Overlay Clock Gating Must be Disabled:  Overlay
> > > & L2 Cache clock gating must be disabled in order to prevent device
> > > hangs when turning off overlay.SW must turn off Ovrunit clock gating
> > > (6200h) and L2 Cache clock gating (C8h)."
> > > 
> > > Now I've nowhere found that 0xc8 register and hence couldn't apply the
> > > l2 cache workaround. But I've remembered that part of the magic that
> > > the OVERLAY_ON/OFF commands are supposed to do is to rearrange cache
> > > allocations so that the overlay scaler has some scratch space.
> > > 
> > > And while pondering how that could explain the hang the 2nd time we
> > > enable the overlay, I've remembered that the old ums overlay code did
> > > _not_ issue the OVERLAY_OFF cmd.
> > > 
> > > And indeed, disabling the OFF cmd results in the overlay working
> > > flawlessly, so I guess we can workaround the lack of the above
> > > workaround by simply never disabling the overlay engine once it's
> > > enabled.
> > > 
> > > v2: Add a comment in the code.
> > > 
> > > Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=47827
> > > Cc: stable@vger.kernel.org
> > > Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> > 
> > Tested-by: Rhys <rhyspuk@gmail.com>
> 
> If you care to mention that you are not turning off the old w/a in case
> it has further side-effects,
> 
> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>

Small note about the existing w/a added to the commit message and patch
merged to -fixes. Thanks for the review.
-Daniel
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c
index 555912f..e3b095f 100644
--- a/drivers/gpu/drm/i915/intel_overlay.c
+++ b/drivers/gpu/drm/i915/intel_overlay.c
@@ -342,9 +342,17 @@  static int intel_overlay_off(struct intel_overlay *overlay)
 	intel_ring_emit(ring, flip_addr);
 	intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
 	/* turn overlay off */
-	intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
-	intel_ring_emit(ring, flip_addr);
-	intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
+	if (IS_I830(dev)) {
+		/* Workaround: Don't disable the overlay fully, since otherwise
+		 * it dies on the next OVERLAY_ON cmd. */
+		intel_ring_emit(ring, MI_NOOP);
+		intel_ring_emit(ring, MI_NOOP);
+		intel_ring_emit(ring, MI_NOOP);
+	} else {
+		intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
+		intel_ring_emit(ring, flip_addr);
+		intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
+	}
 	intel_ring_advance(ring);
 
 	return intel_overlay_do_wait_request(overlay, intel_overlay_off_tail);