From: Paulo Zanoni <paulo.r.zanoni@xxxxxxxxx> It is possible that, by the time we run i915_drm_freeze(), delayed_resume_work was already queued but did not run yet. If it still didn't run after intel_runtime_pm_disable_interrupts(), by the time it runs it will try to change the interrupt registers with the interrupts already disabled, which will trigger a WARN. We can reliably reproduce this with the pm_rpm system-suspend test case. In order to avoid the probelm, we flush the work and put the necessary resources in case the work was already scheduled. Another thing I tried was to move the intel_suspend_gt_powersave() call to before intel_runtime_pm_disable_interrupts(), but since that function needs to be called after the interrupts are already disabled, due to dev_priv->rps.work, this strategy didn't work. Testcase: igt/pm_rpm/system-suspend Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=80517 Signed-off-by: Paulo Zanoni <paulo.r.zanoni@xxxxxxxxx> --- drivers/gpu/drm/i915/i915_drv.c | 2 ++ drivers/gpu/drm/i915/intel_drv.h | 1 + drivers/gpu/drm/i915/intel_pm.c | 8 ++++++++ 3 files changed, 11 insertions(+) Now the maintainers and reviewers can choose if they prefer the "cancel" or the "flush" version of the patch. diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 6eb45ac..dad7e8b 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -520,6 +520,8 @@ static int i915_drm_freeze(struct drm_device *dev) return error; } + intel_cancel_rps_resume_work(dev_priv); + intel_runtime_pm_disable_interrupts(dev); dev_priv->enable_hotplug_processing = false; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 5f7c7bd..b122b12 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -993,6 +993,7 @@ void intel_enable_gt_powersave(struct drm_device *dev); void intel_disable_gt_powersave(struct drm_device *dev); void intel_suspend_gt_powersave(struct drm_device *dev); void intel_reset_gt_powersave(struct drm_device *dev); +void intel_cancel_rps_resume_work(struct drm_i915_private *dev_priv); void ironlake_teardown_rc6(struct drm_device *dev); void gen6_update_ring_freq(struct drm_device *dev); void gen6_rps_idle(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index a90fdbd..664099f 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4911,6 +4911,14 @@ void intel_disable_gt_powersave(struct drm_device *dev) } } +/* This function needs to put/clear any resources that the + * rps.delayed_resume_work function puts/clears. */ +void intel_cancel_rps_resume_work(struct drm_i915_private *dev_priv) +{ + if (cancel_delayed_work_sync(&dev_priv->rps.delayed_resume_work)) + intel_runtime_pm_put(dev_priv); +} + static void intel_gen6_powersave_work(struct work_struct *work) { struct drm_i915_private *dev_priv = -- 2.0.0 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx