diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2012-08-09 10:46:01 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2012-08-09 15:53:52 -0400 |
commit | 9270388e184fddb83e3b69c6b7f5b523c070e53d (patch) | |
tree | 10286bc3872461b729bd817c995190970aafcdb4 /drivers/gpu/drm/i915/i915_irq.c | |
parent | 73edd18f610b6dd900cc3a180919dc643fff8513 (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.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) | |||
296 | drm_helper_hpd_irq_event(dev); | 296 | drm_helper_hpd_irq_event(dev); |
297 | } | 297 | } |
298 | 298 | ||
299 | /* defined intel_pm.c */ | ||
300 | extern spinlock_t mchdev_lock; | ||
301 | |||
299 | static void ironlake_handle_rps_change(struct drm_device *dev) | 302 | static 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 | ||