summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2011-09-08 14:00:22 +0200
committerEugeni Dodonov <eugeni.dodonov@intel.com>2012-02-08 18:23:15 -0200
commit91c17b44d207ce5b72863f794f316495103b654f (patch)
tree55035bda004d4624ba99b4eab4b5cb5ed9349dfa
parentd350ffb7767acccb37313e51890ac9ca44359270 (diff)
drm/i915: properly cancel rps_work on module unload v2
The rps disabling code wasn't properly cancelling outstanding work items. Also add a comment that explains why we're not racing with the work item that could unmask interrupts - that piece of code confused me quite a bit. v2: Ben Widawsky pointed out that the first patch would deadlock (and a few lesser problems). All corrected. Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Reviewed-by: Ben Widawsky <ben@bwidawsk.net> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Keith Packard <keithp@keithp.com> Signed-off-by: Eugeni Dodonov <eugeni.dodonov@intel.com>
-rw-r--r--drivers/gpu/drm/i915/intel_display.c5
1 files changed, 5 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 837afcd36aa..448baf7e1b3 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -7693,6 +7693,10 @@ void gen6_disable_rps(struct drm_device *dev)
I915_WRITE(GEN6_RPNSWREQ, 1 << 31);
I915_WRITE(GEN6_PMINTRMSK, 0xffffffff);
I915_WRITE(GEN6_PMIER, 0);
+ /* Complete PM interrupt masking here doesn't race with the rps work
+ * item again unmasking PM interrupts because that is using a different
+ * register (PMIMR) to mask PM interrupts. The only risk is in leaving
+ * stale bits in PMIIR and PMIMR which gen6_enable_rps will clean up. */
spin_lock_irq(&dev_priv->rps_lock);
dev_priv->pm_iir = 0;
@@ -8704,6 +8708,7 @@ void intel_modeset_cleanup(struct drm_device *dev)
* enqueue unpin/hotplug work. */
drm_irq_uninstall(dev);
cancel_work_sync(&dev_priv->hotplug_work);
+ cancel_work_sync(&dev_priv->rps_work);
/* flush any delayed tasks or pending work */
flush_scheduled_work();