Commit b5144075 authored by Jani Nikula's avatar Jani Nikula Committed by Daniel Vetter

drm/i915: fix FORCEWAKE posting reads

We stopped reading FORCEWAKE for posting reads in

commit 8dee3eea
Author: Ben Widawsky <ben@bwidawsk.net>
Date:   Sat Sep 1 22:59:50 2012 -0700

    drm/i915: Never read FORCEWAKE

and started using something from the same cacheline instead. On the
bug reporter's machine this broke entering rc6 states after a
suspend/resume cycle. It turns out reading ECOBUS as posting read
worked fine, while GTFIFODBG did not, preventing RC6 states after
suspend/resume per the bug report referenced below. It's not entirely
clear why, but clearly GTFIFODBG was nowhere near the same cacheline
or address range as FORCEWAKE.

Trying out various registers for posting reads showed that all tested
registers for which NEEDS_FORCE_WAKE() (in i915_drv.c) returns true
work. Conversely, most (but not quite all) registers for which
NEEDS_FORCE_WAKE() returns false do not work. Details in the referenced
bug.

Based on the above, add posting reads on ECOBUS where GTFIFODBG was
previously relied on.

In true cargo cult spirit, add posting reads for FORCEWAKE_VLV writes as
well, but instead of ECOBUS, use FORCEWAKE_ACK_VLV which is in the same
address range as FORCEWAKE_VLV.

v2: Add more details to the commit message. No functional changes.

Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=52411Reported-and-tested-by: default avatarAlexander Bersenev <bay@hackerdom.ru>
CC: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: default avatarJani Nikula <jani.nikula@intel.com>
Reviewed-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Cc: stable@vger.kernel.org
[danvet: add cc: stable and make the commit message a bit clearer that
this is a regression fix and what exactly broke.]
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 262b6d36
...@@ -4250,7 +4250,8 @@ static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) ...@@ -4250,7 +4250,8 @@ static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
static void __gen6_gt_force_wake_mt_reset(struct drm_i915_private *dev_priv) static void __gen6_gt_force_wake_mt_reset(struct drm_i915_private *dev_priv)
{ {
I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(0xffff)); I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(0xffff));
POSTING_READ(ECOBUS); /* something from same cacheline, but !FORCEWAKE */ /* something from same cacheline, but !FORCEWAKE_MT */
POSTING_READ(ECOBUS);
} }
static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv) static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv)
...@@ -4267,7 +4268,8 @@ static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv) ...@@ -4267,7 +4268,8 @@ static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv)
DRM_ERROR("Timed out waiting for forcewake old ack to clear.\n"); DRM_ERROR("Timed out waiting for forcewake old ack to clear.\n");
I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL)); I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL));
POSTING_READ(ECOBUS); /* something from same cacheline, but !FORCEWAKE */ /* something from same cacheline, but !FORCEWAKE_MT */
POSTING_READ(ECOBUS);
if (wait_for_atomic((I915_READ_NOTRACE(forcewake_ack) & 1), if (wait_for_atomic((I915_READ_NOTRACE(forcewake_ack) & 1),
FORCEWAKE_ACK_TIMEOUT_MS)) FORCEWAKE_ACK_TIMEOUT_MS))
...@@ -4304,14 +4306,16 @@ void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv) ...@@ -4304,14 +4306,16 @@ void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv)
static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
{ {
I915_WRITE_NOTRACE(FORCEWAKE, 0); I915_WRITE_NOTRACE(FORCEWAKE, 0);
/* gen6_gt_check_fifodbg doubles as the POSTING_READ */ /* something from same cacheline, but !FORCEWAKE */
POSTING_READ(ECOBUS);
gen6_gt_check_fifodbg(dev_priv); gen6_gt_check_fifodbg(dev_priv);
} }
static void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv) static void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv)
{ {
I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL)); I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL));
/* gen6_gt_check_fifodbg doubles as the POSTING_READ */ /* something from same cacheline, but !FORCEWAKE_MT */
POSTING_READ(ECOBUS);
gen6_gt_check_fifodbg(dev_priv); gen6_gt_check_fifodbg(dev_priv);
} }
...@@ -4351,6 +4355,8 @@ int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv) ...@@ -4351,6 +4355,8 @@ int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv)
static void vlv_force_wake_reset(struct drm_i915_private *dev_priv) static void vlv_force_wake_reset(struct drm_i915_private *dev_priv)
{ {
I915_WRITE_NOTRACE(FORCEWAKE_VLV, _MASKED_BIT_DISABLE(0xffff)); I915_WRITE_NOTRACE(FORCEWAKE_VLV, _MASKED_BIT_DISABLE(0xffff));
/* something from same cacheline, but !FORCEWAKE_VLV */
POSTING_READ(FORCEWAKE_ACK_VLV);
} }
static void vlv_force_wake_get(struct drm_i915_private *dev_priv) static void vlv_force_wake_get(struct drm_i915_private *dev_priv)
...@@ -4371,7 +4377,8 @@ static void vlv_force_wake_get(struct drm_i915_private *dev_priv) ...@@ -4371,7 +4377,8 @@ static void vlv_force_wake_get(struct drm_i915_private *dev_priv)
static void vlv_force_wake_put(struct drm_i915_private *dev_priv) static void vlv_force_wake_put(struct drm_i915_private *dev_priv)
{ {
I915_WRITE_NOTRACE(FORCEWAKE_VLV, _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL)); I915_WRITE_NOTRACE(FORCEWAKE_VLV, _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL));
/* The below doubles as a POSTING_READ */ /* something from same cacheline, but !FORCEWAKE_VLV */
POSTING_READ(FORCEWAKE_ACK_VLV);
gen6_gt_check_fifodbg(dev_priv); gen6_gt_check_fifodbg(dev_priv);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment