diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2017-04-21 09:58:15 -0400 |
---|---|---|
committer | Jani Nikula <jani.nikula@intel.com> | 2017-04-26 09:28:42 -0400 |
commit | 96dabe99cae8a1b5fc645f213eeac928541d3899 (patch) | |
tree | 3cd7a7caadffa6e6c566298e5dddfb5d5a8c3f68 | |
parent | b162d47e142581bfae356d9474856c972c40adbe (diff) |
drm/i915: Avoid busy-spinning on VLV_GLTC_PW_STATUS mmio
The busy-spin, as the first stage of intel_wait_for_register(), is
currently under suspicion for causing:
[ 62.034926] NMI watchdog: Watchdog detected hard LOCKUP on cpu 1
[ 62.034928] Modules linked in: i2c_dev i915 intel_gtt drm_kms_helper prime_numbers
[ 62.034932] CPU: 1 PID: 183 Comm: kworker/1:2 Not tainted 4.11.0-rc7+ #471
[ 62.034933] Hardware name: / , BIOS PYBSWCEL.86A.0027.2015.0507.1758 05/07/2015
[ 62.034934] Workqueue: pm pm_runtime_work
[ 62.034936] task: ffff880275a04ec0 task.stack: ffffc900002d8000
[ 62.034936] RIP: 0010:__intel_wait_for_register_fw+0x77/0x1a0 [i915]
[ 62.034937] RSP: 0018:ffffc900002dbc38 EFLAGS: 00000082
[ 62.034939] RAX: ffffc90003530094 RBX: 0000000000130094 RCX: 0000000000000001
[ 62.034940] RDX: 00000000000000a1 RSI: ffff88027fd15e58 RDI: 0000000000000000
[ 62.034941] RBP: ffffc900002dbc78 R08: 0000000000000002 R09: 0000000000000000
[ 62.034942] R10: ffffc900002dbc18 R11: ffff880276429dd0 R12: ffff8802707c0000
[ 62.034943] R13: 00000000000000a0 R14: 0000000000000000 R15: 00000000fffefc10
[ 62.034945] FS: 0000000000000000(0000) GS:ffff88027fd00000(0000) knlGS:0000000000000000
[ 62.034945] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 62.034947] CR2: 00007ffd3cd98ff8 CR3: 0000000274c19000 CR4: 00000000001006e0
[ 62.034947] Call Trace:
[ 62.034948] intel_wait_for_register+0x77/0x140 [i915]
[ 62.034949] vlv_suspend_complete+0x23/0x5b0 [i915]
[ 62.034950] intel_runtime_suspend+0x16c/0x2a0 [i915]
[ 62.034950] pci_pm_runtime_suspend+0x50/0x180
[ 62.034951] ? pci_pm_runtime_resume+0xa0/0xa0
[ 62.034952] __rpm_callback+0xc5/0x210
[ 62.034953] rpm_callback+0x1f/0x80
[ 62.034953] ? pci_pm_runtime_resume+0xa0/0xa0
[ 62.034954] rpm_suspend+0x118/0x580
[ 62.034955] pm_runtime_work+0x64/0x90
[ 62.034956] process_one_work+0x1bb/0x3e0
[ 62.034956] worker_thread+0x46/0x4f0
[ 62.034957] ? __schedule+0x18b/0x610
[ 62.034958] kthread+0xff/0x140
[ 62.034958] ? process_one_work+0x3e0/0x3e0
[ 62.034959] ? kthread_create_on_node+
and related hard lockups in CI for byt and bsw.
Note this effectively reverts commits 41ce405e6894 and b27366958869
("drm/i915: Convert wait_for(I915_READ(reg)) to intel_wait_for_register()")
v2: Convert bool allow into a u32 mask for clarity and repeat the
comment on vlv rc6 timing to justify the 3ms timeout used for the wait (Ville)
Fixes: 41ce405e6894 ("drm/i915: Convert wait_for(I915_READ(reg)) to intel_wait_for_register()")
Fixes: b27366958869 ("drm/i915: Convert wait_for(I915_READ(reg)) to intel_wait_for_register()")
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=100718
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Tomi Sarvela <tomi.p.sarvela@intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20170421135815.11897-1-chris@chris-wilson.co.uk
Tested-by: Tomi Sarvela <tomi.p.sarvela@intel.com>
(cherry picked from commit 3dd14c04d77d7d702de5aa7157df4cc9417329f3)
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.c | 46 |
1 files changed, 24 insertions, 22 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index c616b4e755bc..1aa26d5f1779 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c | |||
@@ -2177,6 +2177,20 @@ static void vlv_restore_gunit_s0ix_state(struct drm_i915_private *dev_priv) | |||
2177 | I915_WRITE(VLV_GUNIT_CLOCK_GATE2, s->clock_gate_dis2); | 2177 | I915_WRITE(VLV_GUNIT_CLOCK_GATE2, s->clock_gate_dis2); |
2178 | } | 2178 | } |
2179 | 2179 | ||
2180 | static int vlv_wait_for_pw_status(struct drm_i915_private *dev_priv, | ||
2181 | u32 mask, u32 val) | ||
2182 | { | ||
2183 | /* The HW does not like us polling for PW_STATUS frequently, so | ||
2184 | * use the sleeping loop rather than risk the busy spin within | ||
2185 | * intel_wait_for_register(). | ||
2186 | * | ||
2187 | * Transitioning between RC6 states should be at most 2ms (see | ||
2188 | * valleyview_enable_rps) so use a 3ms timeout. | ||
2189 | */ | ||
2190 | return wait_for((I915_READ_NOTRACE(VLV_GTLC_PW_STATUS) & mask) == val, | ||
2191 | 3); | ||
2192 | } | ||
2193 | |||
2180 | int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool force_on) | 2194 | int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool force_on) |
2181 | { | 2195 | { |
2182 | u32 val; | 2196 | u32 val; |
@@ -2205,8 +2219,9 @@ int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool force_on) | |||
2205 | 2219 | ||
2206 | static int vlv_allow_gt_wake(struct drm_i915_private *dev_priv, bool allow) | 2220 | static int vlv_allow_gt_wake(struct drm_i915_private *dev_priv, bool allow) |
2207 | { | 2221 | { |
2222 | u32 mask; | ||
2208 | u32 val; | 2223 | u32 val; |
2209 | int err = 0; | 2224 | int err; |
2210 | 2225 | ||
2211 | val = I915_READ(VLV_GTLC_WAKE_CTRL); | 2226 | val = I915_READ(VLV_GTLC_WAKE_CTRL); |
2212 | val &= ~VLV_GTLC_ALLOWWAKEREQ; | 2227 | val &= ~VLV_GTLC_ALLOWWAKEREQ; |
@@ -2215,45 +2230,32 @@ static int vlv_allow_gt_wake(struct drm_i915_private *dev_priv, bool allow) | |||
2215 | I915_WRITE(VLV_GTLC_WAKE_CTRL, val); | 2230 | I915_WRITE(VLV_GTLC_WAKE_CTRL, val); |
2216 | POSTING_READ(VLV_GTLC_WAKE_CTRL); | 2231 | POSTING_READ(VLV_GTLC_WAKE_CTRL); |
2217 | 2232 | ||
2218 | err = intel_wait_for_register(dev_priv, | 2233 | mask = VLV_GTLC_ALLOWWAKEACK; |
2219 | VLV_GTLC_PW_STATUS, | 2234 | val = allow ? mask : 0; |
2220 | VLV_GTLC_ALLOWWAKEACK, | 2235 | |
2221 | allow, | 2236 | err = vlv_wait_for_pw_status(dev_priv, mask, val); |
2222 | 1); | ||
2223 | if (err) | 2237 | if (err) |
2224 | DRM_ERROR("timeout disabling GT waking\n"); | 2238 | DRM_ERROR("timeout disabling GT waking\n"); |
2225 | 2239 | ||
2226 | return err; | 2240 | return err; |
2227 | } | 2241 | } |
2228 | 2242 | ||
2229 | static int vlv_wait_for_gt_wells(struct drm_i915_private *dev_priv, | 2243 | static void vlv_wait_for_gt_wells(struct drm_i915_private *dev_priv, |
2230 | bool wait_for_on) | 2244 | bool wait_for_on) |
2231 | { | 2245 | { |
2232 | u32 mask; | 2246 | u32 mask; |
2233 | u32 val; | 2247 | u32 val; |
2234 | int err; | ||
2235 | 2248 | ||
2236 | mask = VLV_GTLC_PW_MEDIA_STATUS_MASK | VLV_GTLC_PW_RENDER_STATUS_MASK; | 2249 | mask = VLV_GTLC_PW_MEDIA_STATUS_MASK | VLV_GTLC_PW_RENDER_STATUS_MASK; |
2237 | val = wait_for_on ? mask : 0; | 2250 | val = wait_for_on ? mask : 0; |
2238 | if ((I915_READ(VLV_GTLC_PW_STATUS) & mask) == val) | ||
2239 | return 0; | ||
2240 | |||
2241 | DRM_DEBUG_KMS("waiting for GT wells to go %s (%08x)\n", | ||
2242 | onoff(wait_for_on), | ||
2243 | I915_READ(VLV_GTLC_PW_STATUS)); | ||
2244 | 2251 | ||
2245 | /* | 2252 | /* |
2246 | * RC6 transitioning can be delayed up to 2 msec (see | 2253 | * RC6 transitioning can be delayed up to 2 msec (see |
2247 | * valleyview_enable_rps), use 3 msec for safety. | 2254 | * valleyview_enable_rps), use 3 msec for safety. |
2248 | */ | 2255 | */ |
2249 | err = intel_wait_for_register(dev_priv, | 2256 | if (vlv_wait_for_pw_status(dev_priv, mask, val)) |
2250 | VLV_GTLC_PW_STATUS, mask, val, | ||
2251 | 3); | ||
2252 | if (err) | ||
2253 | DRM_ERROR("timeout waiting for GT wells to go %s\n", | 2257 | DRM_ERROR("timeout waiting for GT wells to go %s\n", |
2254 | onoff(wait_for_on)); | 2258 | onoff(wait_for_on)); |
2255 | |||
2256 | return err; | ||
2257 | } | 2259 | } |
2258 | 2260 | ||
2259 | static void vlv_check_no_gt_access(struct drm_i915_private *dev_priv) | 2261 | static void vlv_check_no_gt_access(struct drm_i915_private *dev_priv) |
@@ -2274,7 +2276,7 @@ static int vlv_suspend_complete(struct drm_i915_private *dev_priv) | |||
2274 | * Bspec defines the following GT well on flags as debug only, so | 2276 | * Bspec defines the following GT well on flags as debug only, so |
2275 | * don't treat them as hard failures. | 2277 | * don't treat them as hard failures. |
2276 | */ | 2278 | */ |
2277 | (void)vlv_wait_for_gt_wells(dev_priv, false); | 2279 | vlv_wait_for_gt_wells(dev_priv, false); |
2278 | 2280 | ||
2279 | mask = VLV_GTLC_RENDER_CTX_EXISTS | VLV_GTLC_MEDIA_CTX_EXISTS; | 2281 | mask = VLV_GTLC_RENDER_CTX_EXISTS | VLV_GTLC_MEDIA_CTX_EXISTS; |
2280 | WARN_ON((I915_READ(VLV_GTLC_WAKE_CTRL) & mask) != mask); | 2282 | WARN_ON((I915_READ(VLV_GTLC_WAKE_CTRL) & mask) != mask); |