drm/i915: Error checks in gen6_set_rps
authorBen Widawsky <ben@bwidawsk.net>
Sat, 8 Sep 2012 02:43:42 +0000 (19:43 -0700)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Thu, 20 Sep 2012 12:23:01 +0000 (14:23 +0200)
With the new "standardized" sysfs interfaces we need to be a bit more
careful about setting the RPS values.

Because the sysfs code and the rps workqueue can run at the same time,
if the sysfs setter wins the race to the mutex, the workqueue can come
in and set a value which is out of range (ie. we're no longer protecting
by RPINTLIM).

I was not able to actually make this error occur in testing.

Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/intel_pm.c

index dd49046bccd101b74e3a328b18ef281997cd01f9..d9151264d91428cbe2e50bc1d9e6b5107979a2d9 100644 (file)
@@ -382,7 +382,13 @@ static void gen6_pm_rps_work(struct work_struct *work)
        else
                new_delay = dev_priv->rps.cur_delay - 1;
 
-       gen6_set_rps(dev_priv->dev, new_delay);
+       /* sysfs frequency interfaces may have snuck in while servicing the
+        * interrupt
+        */
+       if (!(new_delay > dev_priv->rps.max_delay ||
+             new_delay < dev_priv->rps.min_delay)) {
+               gen6_set_rps(dev_priv->dev, new_delay);
+       }
 
        mutex_unlock(&dev_priv->dev->struct_mutex);
 }
index 4e86037ae6b4b992c01545a7a1ae488d88179842..82ca172831c50d0c333793c0616a18e8657bb623 100644 (file)
@@ -2324,6 +2324,8 @@ void gen6_set_rps(struct drm_device *dev, u8 val)
        u32 limits = gen6_rps_limits(dev_priv, &val);
 
        WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+       WARN_ON(val > dev_priv->rps.max_delay);
+       WARN_ON(val < dev_priv->rps.min_delay);
 
        if (val == dev_priv->rps.cur_delay)
                return;