Re: [Intel-gfx] [PATCH] drm/i915: Avoid busy-spinning on VLV_GLTC_PW_STATUS mmio
On Fri, Apr 21, 2017 at 02:00:40PM +0100, Chris Wilson wrote: > 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: 880275a04ec0 task.stack: c92d8000 > [ 62.034936] RIP: 0010:__intel_wait_for_register_fw+0x77/0x1a0 [i915] > [ 62.034937] RSP: 0018:c92dbc38 EFLAGS: 0082 > [ 62.034939] RAX: c90003530094 RBX: 00130094 RCX: > 0001 > [ 62.034940] RDX: 00a1 RSI: 88027fd15e58 RDI: > > [ 62.034941] RBP: c92dbc78 R08: 0002 R09: > > [ 62.034942] R10: c92dbc18 R11: 880276429dd0 R12: > 8802707c > [ 62.034943] R13: 00a0 R14: R15: > fffefc10 > [ 62.034945] FS: () GS:88027fd0() > knlGS: > [ 62.034945] CS: 0010 DS: ES: CR0: 80050033 > [ 62.034947] CR2: 7ffd3cd98ff8 CR3: 000274c19000 CR4: > 001006e0 > [ 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()") > > 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> Cc: Tvrtko Ursulin > Cc: Ville Syrjälä > Cc: Tomi Sarvela > --- > drivers/gpu/drm/i915/i915_drv.c | 39 +-- > 1 file changed, 17 insertions(+), 22 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c > index e4f902f61e57..89b517c478e8 100644 > --- a/drivers/gpu/drm/i915/i915_drv.c > +++ b/drivers/gpu/drm/i915/i915_drv.c > @@ -2179,6 +2179,17 @@ static void vlv_restore_gunit_s0ix_state(struct > drm_i915_private *dev_priv) > I915_WRITE(VLV_GUNIT_CLOCK_GATE2, s->clock_gate_dis2); > } > > +static int vlv_wait_for_pw_status(struct drm_i915_private *dev_priv, > + u32 mask, u32 val) > +{ > + /* The HW does not like us polling for PW_STATUS frequently, so > + * use the sleeping loop rather than risk the busy spin within > + * intel_wait_for_register(). > + */ > + return wait_for((I915_READ_NOTRACE(VLV_GTLC_PW_STATUS) & mask) == val, > + 3); > +} > + > int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool force_on) > { > u32 val; > @@ -2208,7 +2219,7 @@ int vlv_force_gfx_clock(struct drm_i915_private > *dev_priv, bool force_on) > static int vlv_allow_gt_wake(struct drm_i915_private *dev_priv, bool allow) > { > u32 val; > - int err = 0; > + int err; > > val = I915_READ(VLV_GTLC_WAKE_CTRL); > val &= ~VLV_GTLC_ALLOWWAKEREQ; > @@ -2217,45 +2228,29 @@ static int vlv_allow_gt_wake(struct drm_i915_private > *dev_priv, bool allow) > I915_WRITE(VLV_GTLC_WAKE_CTRL, val); > POSTING_READ(VLV_GTLC_WAKE_CTRL); > > - err = intel_wait_for_register(dev_priv, > - VLV_GTLC_PW_STATUS, > - VLV_GTLC_ALLOWWAKEACK, > - allow, > - 1); > + err = vlv_wait_for_pw_status(dev_priv, VLV_GTLC_ALLOWWAKEACK, allow); Looks a bit funny to wait for a boolean. Maybe 'allow ? VLV_GTLC_ALLOWWAKEACK : 0' to make this a little less confusing? > if (err) >
[Intel-gfx] [PATCH] 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: 880275a04ec0 task.stack: c92d8000 [ 62.034936] RIP: 0010:__intel_wait_for_register_fw+0x77/0x1a0 [i915] [ 62.034937] RSP: 0018:c92dbc38 EFLAGS: 0082 [ 62.034939] RAX: c90003530094 RBX: 00130094 RCX: 0001 [ 62.034940] RDX: 00a1 RSI: 88027fd15e58 RDI: [ 62.034941] RBP: c92dbc78 R08: 0002 R09: [ 62.034942] R10: c92dbc18 R11: 880276429dd0 R12: 8802707c [ 62.034943] R13: 00a0 R14: R15: fffefc10 [ 62.034945] FS: () GS:88027fd0() knlGS: [ 62.034945] CS: 0010 DS: ES: CR0: 80050033 [ 62.034947] CR2: 7ffd3cd98ff8 CR3: 000274c19000 CR4: 001006e0 [ 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()") 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 WilsonCc: Tvrtko Ursulin Cc: Ville Syrjälä Cc: Tomi Sarvela --- drivers/gpu/drm/i915/i915_drv.c | 39 +-- 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index e4f902f61e57..89b517c478e8 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -2179,6 +2179,17 @@ static void vlv_restore_gunit_s0ix_state(struct drm_i915_private *dev_priv) I915_WRITE(VLV_GUNIT_CLOCK_GATE2, s->clock_gate_dis2); } +static int vlv_wait_for_pw_status(struct drm_i915_private *dev_priv, + u32 mask, u32 val) +{ + /* The HW does not like us polling for PW_STATUS frequently, so +* use the sleeping loop rather than risk the busy spin within +* intel_wait_for_register(). +*/ + return wait_for((I915_READ_NOTRACE(VLV_GTLC_PW_STATUS) & mask) == val, + 3); +} + int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool force_on) { u32 val; @@ -2208,7 +2219,7 @@ int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool force_on) static int vlv_allow_gt_wake(struct drm_i915_private *dev_priv, bool allow) { u32 val; - int err = 0; + int err; val = I915_READ(VLV_GTLC_WAKE_CTRL); val &= ~VLV_GTLC_ALLOWWAKEREQ; @@ -2217,45 +2228,29 @@ static int vlv_allow_gt_wake(struct drm_i915_private *dev_priv, bool allow) I915_WRITE(VLV_GTLC_WAKE_CTRL, val); POSTING_READ(VLV_GTLC_WAKE_CTRL); - err = intel_wait_for_register(dev_priv, - VLV_GTLC_PW_STATUS, - VLV_GTLC_ALLOWWAKEACK, - allow, - 1); + err = vlv_wait_for_pw_status(dev_priv, VLV_GTLC_ALLOWWAKEACK, allow); if (err) DRM_ERROR("timeout disabling GT waking\n"); return err; } -static int vlv_wait_for_gt_wells(struct drm_i915_private *dev_priv, -bool wait_for_on) +static void vlv_wait_for_gt_wells(struct drm_i915_private *dev_priv, + bool wait_for_on) { u32 mask; u32 val; -