.disable_power_well = 1,
        .enable_ips = 1,
        .fastboot = 0,
-       .enable_pc8 = 1,
-       .pc8_timeout = 5000,
        .prefault_disable = 0,
        .reset = true,
        .invert_brightness = 0,
 MODULE_PARM_DESC(fastboot,
        "Try to skip unnecessary mode sets at boot time (default: false)");
 
-module_param_named(enable_pc8, i915.enable_pc8, int, 0600);
-MODULE_PARM_DESC(enable_pc8,
-       "Enable support for low power package C states (PC8+) (default: true)");
-
-module_param_named(pc8_timeout, i915.pc8_timeout, int, 0600);
-MODULE_PARM_DESC(pc8_timeout,
-       "Number of msecs of idleness required to enter PC8+ (default: 5000)");
-
 module_param_named(prefault_disable, i915.prefault_disable, bool, 0600);
 MODULE_PARM_DESC(prefault_disable,
        "Disable page prefaulting for pread/pwrite/reloc (default:false). "
 
 static void hsw_restore_lcpll(struct drm_i915_private *dev_priv)
 {
        uint32_t val;
+       unsigned long irqflags;
 
        val = I915_READ(LCPLL_CTL);
 
                    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;
                        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;
        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));
        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);
 
 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);
        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)
        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);