diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2012-08-09 18:46:01 +0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2012-08-09 23:53:52 +0400 |
commit | 9270388e184fddb83e3b69c6b7f5b523c070e53d (patch) | |
tree | 10286bc3872461b729bd817c995190970aafcdb4 /drivers/gpu/drm/i915/i915_irq.c | |
parent | 73edd18f610b6dd900cc3a180919dc643fff8513 (diff) | |
download | linux-9270388e184fddb83e3b69c6b7f5b523c070e53d.tar.xz |
drm/i915: fix up ilk drps/ips locking
We change the drps/ips sw/hw state from different callers: Our own irq
handler, the external intel-ips module and from process context. Most
of these callers don't take any lock at all.
Protect everything by making the mchdev_lock irqsave and grabbing it in
all relevant callsites. Note that we have to convert a few sleeps in the
drps enable/disable code to delays, but alas, I'm not volunteering to
restructure the code around a few work items.
For paranoia add a spin_locked assert to ironlake_set_drps, too.
v2: Move one access inside the lock protection. Caught by the
dev_priv->ips mass-rename ...
v3: Resolve rebase conflict.
Reviewed-by: Damien Lespiau <damien.lespiau@intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/i915_irq.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 12 |
1 files changed, 11 insertions, 1 deletions
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 3e203da61c69..d15ea50f5854 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -296,14 +296,22 @@ static void i915_hotplug_work_func(struct work_struct *work) drm_helper_hpd_irq_event(dev); } +/* defined intel_pm.c */ +extern spinlock_t mchdev_lock; + static void ironlake_handle_rps_change(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; u32 busy_up, busy_down, max_avg, min_avg; - u8 new_delay = dev_priv->cur_delay; + u8 new_delay; + unsigned long flags; + + spin_lock_irqsave(&mchdev_lock, flags); I915_WRITE16(MEMINTRSTS, I915_READ(MEMINTRSTS)); + new_delay = dev_priv->cur_delay; + I915_WRITE16(MEMINTRSTS, MEMINT_EVAL_CHG); busy_up = I915_READ(RCPREVBSYTUPAVG); busy_down = I915_READ(RCPREVBSYTDNAVG); @@ -326,6 +334,8 @@ static void ironlake_handle_rps_change(struct drm_device *dev) if (ironlake_set_drps(dev, new_delay)) dev_priv->cur_delay = new_delay; + spin_unlock_irqrestore(&mchdev_lock, flags); + return; } |