diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 65 |
1 files changed, 29 insertions, 36 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index da68ccfd5aa9..1f79d1d51ea7 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6960,6 +6960,7 @@ static void hsw_disable_lcpll(struct drm_i915_private *dev_priv, static void hsw_restore_lcpll(struct drm_i915_private *dev_priv) { uint32_t val; + unsigned long irqflags; val = I915_READ(LCPLL_CTL); @@ -6967,9 +6968,22 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv) LCPLL_POWER_DOWN_ALLOW)) == LCPLL_PLL_LOCK) return; - /* Make sure we're not on PC8 state before disabling PC8, otherwise - * we'll hang the machine! */ - gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL); + /* + * Make sure we're not on PC8 state before disabling PC8, otherwise + * we'll hang the machine. To prevent PC8 state, just enable force_wake. + * + * The other problem is that hsw_restore_lcpll() is called as part of + * the runtime PM resume sequence, so we can't just call + * gen6_gt_force_wake_get() because that function calls + * intel_runtime_pm_get(), and we can't change the runtime PM refcount + * while we are on the resume sequence. So to solve this problem we have + * to call special forcewake code that doesn't touch runtime PM and + * doesn't enable the forcewake delayed work. + */ + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); + if (dev_priv->uncore.forcewake_count++ == 0) + dev_priv->uncore.funcs.force_wake_get(dev_priv, FORCEWAKE_ALL); + spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); if (val & LCPLL_POWER_DOWN_ALLOW) { val &= ~LCPLL_POWER_DOWN_ALLOW; @@ -7003,14 +7017,20 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv) DRM_ERROR("Switching back to LCPLL failed\n"); } - gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL); + /* See the big comment above. */ + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); + if (--dev_priv->uncore.forcewake_count == 0) + dev_priv->uncore.funcs.force_wake_put(dev_priv, FORCEWAKE_ALL); + spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } -static void __hsw_do_enable_pc8(struct drm_i915_private *dev_priv) +void __hsw_do_enable_pc8(struct drm_i915_private *dev_priv) { struct drm_device *dev = dev_priv->dev; uint32_t val; + WARN_ON(!HAS_PC8(dev)); + DRM_DEBUG_KMS("Enabling package C8+\n"); dev_priv->pc8.enabled = true; @@ -7026,22 +7046,6 @@ static void __hsw_do_enable_pc8(struct drm_i915_private *dev_priv) hsw_disable_lcpll(dev_priv, true, true); } -void hsw_enable_pc8_work(struct work_struct *__work) -{ - struct drm_i915_private *dev_priv = - container_of(to_delayed_work(__work), struct drm_i915_private, - pc8.enable_work); - struct drm_device *dev = dev_priv->dev; - - WARN_ON(!HAS_PC8(dev)); - - if (dev_priv->pc8.enabled) - return; - - __hsw_do_enable_pc8(dev_priv); - intel_runtime_pm_put(dev_priv); -} - static void __hsw_enable_package_c8(struct drm_i915_private *dev_priv) { WARN_ON(!mutex_is_locked(&dev_priv->pc8.lock)); @@ -7052,15 +7056,16 @@ static void __hsw_enable_package_c8(struct drm_i915_private *dev_priv) if (dev_priv->pc8.disable_count != 0) return; - schedule_delayed_work(&dev_priv->pc8.enable_work, - msecs_to_jiffies(i915.pc8_timeout)); + intel_runtime_pm_put(dev_priv); } -static void __hsw_do_disable_package_c8(struct drm_i915_private *dev_priv) +void __hsw_do_disable_pc8(struct drm_i915_private *dev_priv) { struct drm_device *dev = dev_priv->dev; uint32_t val; + WARN_ON(!HAS_PC8(dev)); + DRM_DEBUG_KMS("Disabling package C8+\n"); hsw_restore_lcpll(dev_priv); @@ -7083,8 +7088,6 @@ static void __hsw_do_disable_package_c8(struct drm_i915_private *dev_priv) static void __hsw_disable_package_c8(struct drm_i915_private *dev_priv) { - struct drm_device *dev = dev_priv->dev; - WARN_ON(!mutex_is_locked(&dev_priv->pc8.lock)); WARN(dev_priv->pc8.disable_count < 0, "pc8.disable_count: %d\n", dev_priv->pc8.disable_count); @@ -7093,14 +7096,7 @@ static void __hsw_disable_package_c8(struct drm_i915_private *dev_priv) if (dev_priv->pc8.disable_count != 1) return; - WARN_ON(!HAS_PC8(dev)); - - cancel_delayed_work_sync(&dev_priv->pc8.enable_work); - if (!dev_priv->pc8.enabled) - return; - intel_runtime_pm_get(dev_priv); - __hsw_do_disable_package_c8(dev_priv); } void hsw_enable_package_c8(struct drm_i915_private *dev_priv) @@ -7158,9 +7154,6 @@ static void hsw_update_package_c8(struct drm_device *dev) if (!HAS_PC8(dev_priv->dev)) return; - if (!i915.enable_pc8) - return; - mutex_lock(&dev_priv->pc8.lock); allow = hsw_can_enable_package_c8(dev_priv); |