|
@@ -204,6 +204,18 @@ static void vlv_force_wake_put(struct drm_i915_private *dev_priv)
|
|
|
gen6_gt_check_fifodbg(dev_priv);
|
|
|
}
|
|
|
|
|
|
+static void gen6_force_wake_work(struct work_struct *work)
|
|
|
+{
|
|
|
+ struct drm_i915_private *dev_priv =
|
|
|
+ container_of(work, typeof(*dev_priv), uncore.force_wake_work.work);
|
|
|
+ unsigned long irqflags;
|
|
|
+
|
|
|
+ spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
|
|
|
+ if (--dev_priv->uncore.forcewake_count == 0)
|
|
|
+ dev_priv->uncore.funcs.force_wake_put(dev_priv);
|
|
|
+ spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
|
|
|
+}
|
|
|
+
|
|
|
void intel_uncore_early_sanitize(struct drm_device *dev)
|
|
|
{
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
@@ -216,6 +228,9 @@ void intel_uncore_init(struct drm_device *dev)
|
|
|
{
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
|
+ INIT_DELAYED_WORK(&dev_priv->uncore.force_wake_work,
|
|
|
+ gen6_force_wake_work);
|
|
|
+
|
|
|
if (IS_VALLEYVIEW(dev)) {
|
|
|
dev_priv->uncore.funcs.force_wake_get = vlv_force_wake_get;
|
|
|
dev_priv->uncore.funcs.force_wake_put = vlv_force_wake_put;
|
|
@@ -261,6 +276,16 @@ void intel_uncore_init(struct drm_device *dev)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+void intel_uncore_fini(struct drm_device *dev)
|
|
|
+{
|
|
|
+ struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
+
|
|
|
+ flush_delayed_work(&dev_priv->uncore.force_wake_work);
|
|
|
+
|
|
|
+ /* Paranoia: make sure we have disabled everything before we exit. */
|
|
|
+ intel_uncore_sanitize(dev);
|
|
|
+}
|
|
|
+
|
|
|
static void intel_uncore_forcewake_reset(struct drm_device *dev)
|
|
|
{
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
@@ -306,8 +331,12 @@ void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
|
|
|
unsigned long irqflags;
|
|
|
|
|
|
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
|
|
|
- if (--dev_priv->uncore.forcewake_count == 0)
|
|
|
- dev_priv->uncore.funcs.force_wake_put(dev_priv);
|
|
|
+ if (--dev_priv->uncore.forcewake_count == 0) {
|
|
|
+ dev_priv->uncore.forcewake_count++;
|
|
|
+ mod_delayed_work(dev_priv->wq,
|
|
|
+ &dev_priv->uncore.force_wake_work,
|
|
|
+ 1);
|
|
|
+ }
|
|
|
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
|
|
|
}
|
|
|
|