aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/i915_irq.c
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2012-08-09 10:46:01 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2012-08-09 15:53:52 -0400
commit9270388e184fddb83e3b69c6b7f5b523c070e53d (patch)
tree10286bc3872461b729bd817c995190970aafcdb4 /drivers/gpu/drm/i915/i915_irq.c
parent73edd18f610b6dd900cc3a180919dc643fff8513 (diff)
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.c12
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)
296 drm_helper_hpd_irq_event(dev); 296 drm_helper_hpd_irq_event(dev);
297} 297}
298 298
299/* defined intel_pm.c */
300extern spinlock_t mchdev_lock;
301
299static void ironlake_handle_rps_change(struct drm_device *dev) 302static void ironlake_handle_rps_change(struct drm_device *dev)
300{ 303{
301 drm_i915_private_t *dev_priv = dev->dev_private; 304 drm_i915_private_t *dev_priv = dev->dev_private;
302 u32 busy_up, busy_down, max_avg, min_avg; 305 u32 busy_up, busy_down, max_avg, min_avg;
303 u8 new_delay = dev_priv->cur_delay; 306 u8 new_delay;
307 unsigned long flags;
308
309 spin_lock_irqsave(&mchdev_lock, flags);
304 310
305 I915_WRITE16(MEMINTRSTS, I915_READ(MEMINTRSTS)); 311 I915_WRITE16(MEMINTRSTS, I915_READ(MEMINTRSTS));
306 312
313 new_delay = dev_priv->cur_delay;
314
307 I915_WRITE16(MEMINTRSTS, MEMINT_EVAL_CHG); 315 I915_WRITE16(MEMINTRSTS, MEMINT_EVAL_CHG);
308 busy_up = I915_READ(RCPREVBSYTUPAVG); 316 busy_up = I915_READ(RCPREVBSYTUPAVG);
309 busy_down = I915_READ(RCPREVBSYTDNAVG); 317 busy_down = I915_READ(RCPREVBSYTDNAVG);
@@ -326,6 +334,8 @@ static void ironlake_handle_rps_change(struct drm_device *dev)
326 if (ironlake_set_drps(dev, new_delay)) 334 if (ironlake_set_drps(dev, new_delay))
327 dev_priv->cur_delay = new_delay; 335 dev_priv->cur_delay = new_delay;
328 336
337 spin_unlock_irqrestore(&mchdev_lock, flags);
338
329 return; 339 return;
330} 340}
331 341