drm/i915: Change i915_request power well handling
authorVille Syrjälä <ville.syrjala@linux.intel.com>
Mon, 16 Sep 2013 14:38:27 +0000 (17:38 +0300)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Fri, 20 Sep 2013 21:48:44 +0000 (23:48 +0200)
Reorganize the internal i915_request power well handling to use the
reference count just like everyone else. This way all we need to do is
check the reference count and we know whether the power well needs to be
enabled of disabled.

v2: Split he intel_display_power_{get,put} change to another patch.
    Add intel_resume_power_well() to make sure we enable the power
    well on resume

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_pm.c

index b85354f9440b2c0fbd0667ee932acfe92c547321..f1f11d10e48533b5c9e4b3e3ef0128ef05254639 100644 (file)
@@ -764,6 +764,7 @@ extern bool intel_display_power_enabled(struct drm_device *dev,
                                        enum intel_display_power_domain domain);
 extern void intel_init_power_well(struct drm_device *dev);
 extern void intel_set_power_well(struct drm_device *dev, bool enable);
+extern void intel_resume_power_well(struct drm_device *dev);
 extern void intel_enable_gt_powersave(struct drm_device *dev);
 extern void intel_disable_gt_powersave(struct drm_device *dev);
 extern void ironlake_teardown_rc6(struct drm_device *dev);
index 0d7e2d324f1ba77a2512b7d73dba31eee4a8a35d..609c936d1dfe7cba1647b85ff4a60db30a5f1af4 100644 (file)
@@ -5354,8 +5354,7 @@ void i915_request_power_well(void)
                return;
 
        spin_lock_irq(&hsw_pwr->lock);
-       if (!hsw_pwr->count++ &&
-                       !hsw_pwr->i915_request)
+       if (!hsw_pwr->count++)
                __intel_set_power_well(hsw_pwr->device, true);
        spin_unlock_irq(&hsw_pwr->lock);
 }
@@ -5369,8 +5368,7 @@ void i915_release_power_well(void)
 
        spin_lock_irq(&hsw_pwr->lock);
        WARN_ON(!hsw_pwr->count);
-       if (!--hsw_pwr->count &&
-                      !hsw_pwr->i915_request)
+       if (!--hsw_pwr->count)
                __intel_set_power_well(hsw_pwr->device, false);
        spin_unlock_irq(&hsw_pwr->lock);
 }
@@ -5406,15 +5404,41 @@ void intel_set_power_well(struct drm_device *dev, bool enable)
                return;
 
        spin_lock_irq(&power_well->lock);
+
+       /*
+        * This function will only ever contribute one
+        * to the power well reference count. i915_request
+        * is what tracks whether we have or have not
+        * added the one to the reference count.
+        */
+       if (power_well->i915_request == enable)
+               goto out;
+
        power_well->i915_request = enable;
 
-       /* only reject "disable" power well request */
-       if (power_well->count && !enable) {
-               spin_unlock_irq(&power_well->lock);
-               return;
+       if (enable) {
+               if (!power_well->count++)
+                       __intel_set_power_well(dev, true);
+       } else {
+               WARN_ON(!power_well->count);
+               if (!--power_well->count)
+                       __intel_set_power_well(dev, false);
        }
 
-       __intel_set_power_well(dev, enable);
+ out:
+       spin_unlock_irq(&power_well->lock);
+}
+
+void intel_resume_power_well(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct i915_power_well *power_well = &dev_priv->power_well;
+
+       if (!HAS_POWER_WELL(dev))
+               return;
+
+       spin_lock_irq(&power_well->lock);
+       __intel_set_power_well(dev, power_well->count > 0);
        spin_unlock_irq(&power_well->lock);
 }
 
@@ -5433,6 +5457,7 @@ void intel_init_power_well(struct drm_device *dev)
 
        /* For now, we need the power well to be always enabled. */
        intel_set_power_well(dev, true);
+       intel_resume_power_well(dev);
 
        /* We're taking over the BIOS, so clear any requests made by it since
         * the driver is in charge now. */