drm/i915: move force wake support into intel_pm
authorEugeni Dodonov <eugeni.dodonov@intel.com>
Mon, 2 Jul 2012 14:51:11 +0000 (11:51 -0300)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Thu, 5 Jul 2012 07:56:04 +0000 (09:56 +0200)
This commit moves force wake support routines into intel_pm modules, and
exports the gen6_gt_check_fifodbg routine (used in I915_READ).

Signed-off-by: Eugeni Dodonov <eugeni.dodonov@intel.com>
Acked-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_pm.c

index 3ac414ff7f847095b3b4db3bb34b48a72874608a..c7e76e03a684046bbd986ea23f747c3aa86e88b5 100644 (file)
@@ -433,197 +433,6 @@ bool i915_semaphore_is_enabled(struct drm_device *dev)
        return 1;
 }
 
-static void __gen6_gt_wait_for_thread_c0(struct drm_i915_private *dev_priv)
-{
-       u32 gt_thread_status_mask;
-
-       if (IS_HASWELL(dev_priv->dev))
-               gt_thread_status_mask = GEN6_GT_THREAD_STATUS_CORE_MASK_HSW;
-       else
-               gt_thread_status_mask = GEN6_GT_THREAD_STATUS_CORE_MASK;
-
-       /* w/a for a sporadic read returning 0 by waiting for the GT
-        * thread to wake up.
-        */
-       if (wait_for_atomic_us((I915_READ_NOTRACE(GEN6_GT_THREAD_STATUS_REG) & gt_thread_status_mask) == 0, 500))
-               DRM_ERROR("GT thread status wait timed out\n");
-}
-
-static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
-{
-       u32 forcewake_ack;
-
-       if (IS_HASWELL(dev_priv->dev))
-               forcewake_ack = FORCEWAKE_ACK_HSW;
-       else
-               forcewake_ack = FORCEWAKE_ACK;
-
-       if (wait_for_atomic_us((I915_READ_NOTRACE(forcewake_ack) & 1) == 0, 500))
-               DRM_ERROR("Force wake wait timed out\n");
-
-       I915_WRITE_NOTRACE(FORCEWAKE, 1);
-
-       if (wait_for_atomic_us((I915_READ_NOTRACE(forcewake_ack) & 1), 500))
-               DRM_ERROR("Force wake wait timed out\n");
-
-       __gen6_gt_wait_for_thread_c0(dev_priv);
-}
-
-static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv)
-{
-       u32 forcewake_ack;
-
-       if (IS_HASWELL(dev_priv->dev))
-               forcewake_ack = FORCEWAKE_ACK_HSW;
-       else
-               forcewake_ack = FORCEWAKE_MT_ACK;
-
-       if (wait_for_atomic_us((I915_READ_NOTRACE(forcewake_ack) & 1) == 0, 500))
-               DRM_ERROR("Force wake wait timed out\n");
-
-       I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_ENABLE(1));
-
-       if (wait_for_atomic_us((I915_READ_NOTRACE(forcewake_ack) & 1), 500))
-               DRM_ERROR("Force wake wait timed out\n");
-
-       __gen6_gt_wait_for_thread_c0(dev_priv);
-}
-
-/*
- * Generally this is called implicitly by the register read function. However,
- * if some sequence requires the GT to not power down then this function should
- * be called at the beginning of the sequence followed by a call to
- * gen6_gt_force_wake_put() at the end of the sequence.
- */
-void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
-{
-       unsigned long irqflags;
-
-       spin_lock_irqsave(&dev_priv->gt_lock, irqflags);
-       if (dev_priv->forcewake_count++ == 0)
-               dev_priv->gt.force_wake_get(dev_priv);
-       spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags);
-}
-
-static void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv)
-{
-       u32 gtfifodbg;
-       gtfifodbg = I915_READ_NOTRACE(GTFIFODBG);
-       if (WARN(gtfifodbg & GT_FIFO_CPU_ERROR_MASK,
-            "MMIO read or write has been dropped %x\n", gtfifodbg))
-               I915_WRITE_NOTRACE(GTFIFODBG, GT_FIFO_CPU_ERROR_MASK);
-}
-
-static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
-{
-       I915_WRITE_NOTRACE(FORCEWAKE, 0);
-       /* The below doubles as a POSTING_READ */
-       gen6_gt_check_fifodbg(dev_priv);
-}
-
-static void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv)
-{
-       I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(1));
-       /* The below doubles as a POSTING_READ */
-       gen6_gt_check_fifodbg(dev_priv);
-}
-
-/*
- * see gen6_gt_force_wake_get()
- */
-void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
-{
-       unsigned long irqflags;
-
-       spin_lock_irqsave(&dev_priv->gt_lock, irqflags);
-       if (--dev_priv->forcewake_count == 0)
-               dev_priv->gt.force_wake_put(dev_priv);
-       spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags);
-}
-
-int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv)
-{
-       int ret = 0;
-
-       if (dev_priv->gt_fifo_count < GT_FIFO_NUM_RESERVED_ENTRIES) {
-               int loop = 500;
-               u32 fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES);
-               while (fifo <= GT_FIFO_NUM_RESERVED_ENTRIES && loop--) {
-                       udelay(10);
-                       fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES);
-               }
-               if (WARN_ON(loop < 0 && fifo <= GT_FIFO_NUM_RESERVED_ENTRIES))
-                       ++ret;
-               dev_priv->gt_fifo_count = fifo;
-       }
-       dev_priv->gt_fifo_count--;
-
-       return ret;
-}
-
-static void vlv_force_wake_get(struct drm_i915_private *dev_priv)
-{
-       /* Already awake? */
-       if ((I915_READ(0x130094) & 0xa1) == 0xa1)
-               return;
-
-       I915_WRITE_NOTRACE(FORCEWAKE_VLV, 0xffffffff);
-       POSTING_READ(FORCEWAKE_VLV);
-
-       if (wait_for_atomic_us((I915_READ_NOTRACE(FORCEWAKE_ACK_VLV) & 1), 500))
-               DRM_ERROR("Force wake wait timed out\n");
-
-       __gen6_gt_wait_for_thread_c0(dev_priv);
-}
-
-static void vlv_force_wake_put(struct drm_i915_private *dev_priv)
-{
-       I915_WRITE_NOTRACE(FORCEWAKE_VLV, 0xffff0000);
-       /* FIXME: confirm VLV behavior with Punit folks */
-       POSTING_READ(FORCEWAKE_VLV);
-}
-
-void intel_gt_init(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-
-       spin_lock_init(&dev_priv->gt_lock);
-
-       if (IS_VALLEYVIEW(dev)) {
-               dev_priv->gt.force_wake_get = vlv_force_wake_get;
-               dev_priv->gt.force_wake_put = vlv_force_wake_put;
-       } else if (INTEL_INFO(dev)->gen >= 6) {
-               dev_priv->gt.force_wake_get = __gen6_gt_force_wake_get;
-               dev_priv->gt.force_wake_put = __gen6_gt_force_wake_put;
-
-               /* IVB configs may use multi-threaded forcewake */
-               if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) {
-                       u32 ecobus;
-
-                       /* A small trick here - if the bios hasn't configured
-                        * MT forcewake, and if the device is in RC6, then
-                        * force_wake_mt_get will not wake the device and the
-                        * ECOBUS read will return zero. Which will be
-                        * (correctly) interpreted by the test below as MT
-                        * forcewake being disabled.
-                        */
-                       mutex_lock(&dev->struct_mutex);
-                       __gen6_gt_force_wake_mt_get(dev_priv);
-                       ecobus = I915_READ_NOTRACE(ECOBUS);
-                       __gen6_gt_force_wake_mt_put(dev_priv);
-                       mutex_unlock(&dev->struct_mutex);
-
-                       if (ecobus & FORCEWAKE_MT_ENABLE) {
-                               DRM_DEBUG_KMS("Using MT version of forcewake\n");
-                               dev_priv->gt.force_wake_get =
-                                       __gen6_gt_force_wake_mt_get;
-                               dev_priv->gt.force_wake_put =
-                                       __gen6_gt_force_wake_mt_put;
-                       }
-               }
-       }
-}
-
 static int i915_drm_freeze(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
index cc1573b2b60bf718116600231f68755113e40ae5..7d521aa51544ccc03d36398d8ed903e4a49bc3ea 100644 (file)
@@ -493,6 +493,7 @@ extern void intel_gpu_ips_teardown(void);
 
 extern void intel_enable_gt_powersave(struct drm_device *dev);
 extern void intel_disable_gt_powersave(struct drm_device *dev);
+extern void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv);
 
 extern void intel_ddi_dpms(struct drm_encoder *encoder, int mode);
 extern void intel_ddi_mode_set(struct drm_encoder *encoder,
index 6e02698e9a3d806effae1a736cb61959f7e977d6..3f58d7aeb70a7dbf001fcf69c9078bd90b2984b9 100644 (file)
@@ -3948,3 +3948,194 @@ void intel_init_pm(struct drm_device *dev)
        intel_init_power_wells(dev);
 }
 
+static void __gen6_gt_wait_for_thread_c0(struct drm_i915_private *dev_priv)
+{
+       u32 gt_thread_status_mask;
+
+       if (IS_HASWELL(dev_priv->dev))
+               gt_thread_status_mask = GEN6_GT_THREAD_STATUS_CORE_MASK_HSW;
+       else
+               gt_thread_status_mask = GEN6_GT_THREAD_STATUS_CORE_MASK;
+
+       /* w/a for a sporadic read returning 0 by waiting for the GT
+        * thread to wake up.
+        */
+       if (wait_for_atomic_us((I915_READ_NOTRACE(GEN6_GT_THREAD_STATUS_REG) & gt_thread_status_mask) == 0, 500))
+               DRM_ERROR("GT thread status wait timed out\n");
+}
+
+static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
+{
+       u32 forcewake_ack;
+
+       if (IS_HASWELL(dev_priv->dev))
+               forcewake_ack = FORCEWAKE_ACK_HSW;
+       else
+               forcewake_ack = FORCEWAKE_ACK;
+
+       if (wait_for_atomic_us((I915_READ_NOTRACE(forcewake_ack) & 1) == 0, 500))
+               DRM_ERROR("Force wake wait timed out\n");
+
+       I915_WRITE_NOTRACE(FORCEWAKE, 1);
+
+       if (wait_for_atomic_us((I915_READ_NOTRACE(forcewake_ack) & 1), 500))
+               DRM_ERROR("Force wake wait timed out\n");
+
+       __gen6_gt_wait_for_thread_c0(dev_priv);
+}
+
+static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv)
+{
+       u32 forcewake_ack;
+
+       if (IS_HASWELL(dev_priv->dev))
+               forcewake_ack = FORCEWAKE_ACK_HSW;
+       else
+               forcewake_ack = FORCEWAKE_MT_ACK;
+
+       if (wait_for_atomic_us((I915_READ_NOTRACE(forcewake_ack) & 1) == 0, 500))
+               DRM_ERROR("Force wake wait timed out\n");
+
+       I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_ENABLE(1));
+
+       if (wait_for_atomic_us((I915_READ_NOTRACE(forcewake_ack) & 1), 500))
+               DRM_ERROR("Force wake wait timed out\n");
+
+       __gen6_gt_wait_for_thread_c0(dev_priv);
+}
+
+/*
+ * Generally this is called implicitly by the register read function. However,
+ * if some sequence requires the GT to not power down then this function should
+ * be called at the beginning of the sequence followed by a call to
+ * gen6_gt_force_wake_put() at the end of the sequence.
+ */
+void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
+{
+       unsigned long irqflags;
+
+       spin_lock_irqsave(&dev_priv->gt_lock, irqflags);
+       if (dev_priv->forcewake_count++ == 0)
+               dev_priv->gt.force_wake_get(dev_priv);
+       spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags);
+}
+
+void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv)
+{
+       u32 gtfifodbg;
+       gtfifodbg = I915_READ_NOTRACE(GTFIFODBG);
+       if (WARN(gtfifodbg & GT_FIFO_CPU_ERROR_MASK,
+            "MMIO read or write has been dropped %x\n", gtfifodbg))
+               I915_WRITE_NOTRACE(GTFIFODBG, GT_FIFO_CPU_ERROR_MASK);
+}
+
+static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
+{
+       I915_WRITE_NOTRACE(FORCEWAKE, 0);
+       /* The below doubles as a POSTING_READ */
+       gen6_gt_check_fifodbg(dev_priv);
+}
+
+static void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv)
+{
+       I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(1));
+       /* The below doubles as a POSTING_READ */
+       gen6_gt_check_fifodbg(dev_priv);
+}
+
+/*
+ * see gen6_gt_force_wake_get()
+ */
+void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
+{
+       unsigned long irqflags;
+
+       spin_lock_irqsave(&dev_priv->gt_lock, irqflags);
+       if (--dev_priv->forcewake_count == 0)
+               dev_priv->gt.force_wake_put(dev_priv);
+       spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags);
+}
+
+int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv)
+{
+       int ret = 0;
+
+       if (dev_priv->gt_fifo_count < GT_FIFO_NUM_RESERVED_ENTRIES) {
+               int loop = 500;
+               u32 fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES);
+               while (fifo <= GT_FIFO_NUM_RESERVED_ENTRIES && loop--) {
+                       udelay(10);
+                       fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES);
+               }
+               if (WARN_ON(loop < 0 && fifo <= GT_FIFO_NUM_RESERVED_ENTRIES))
+                       ++ret;
+               dev_priv->gt_fifo_count = fifo;
+       }
+       dev_priv->gt_fifo_count--;
+
+       return ret;
+}
+
+static void vlv_force_wake_get(struct drm_i915_private *dev_priv)
+{
+       /* Already awake? */
+       if ((I915_READ(0x130094) & 0xa1) == 0xa1)
+               return;
+
+       I915_WRITE_NOTRACE(FORCEWAKE_VLV, 0xffffffff);
+       POSTING_READ(FORCEWAKE_VLV);
+
+       if (wait_for_atomic_us((I915_READ_NOTRACE(FORCEWAKE_ACK_VLV) & 1), 500))
+               DRM_ERROR("Force wake wait timed out\n");
+
+       __gen6_gt_wait_for_thread_c0(dev_priv);
+}
+
+static void vlv_force_wake_put(struct drm_i915_private *dev_priv)
+{
+       I915_WRITE_NOTRACE(FORCEWAKE_VLV, 0xffff0000);
+       /* FIXME: confirm VLV behavior with Punit folks */
+       POSTING_READ(FORCEWAKE_VLV);
+}
+
+void intel_gt_init(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       spin_lock_init(&dev_priv->gt_lock);
+
+       if (IS_VALLEYVIEW(dev)) {
+               dev_priv->gt.force_wake_get = vlv_force_wake_get;
+               dev_priv->gt.force_wake_put = vlv_force_wake_put;
+       } else if (INTEL_INFO(dev)->gen >= 6) {
+               dev_priv->gt.force_wake_get = __gen6_gt_force_wake_get;
+               dev_priv->gt.force_wake_put = __gen6_gt_force_wake_put;
+
+               /* IVB configs may use multi-threaded forcewake */
+               if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) {
+                       u32 ecobus;
+
+                       /* A small trick here - if the bios hasn't configured
+                        * MT forcewake, and if the device is in RC6, then
+                        * force_wake_mt_get will not wake the device and the
+                        * ECOBUS read will return zero. Which will be
+                        * (correctly) interpreted by the test below as MT
+                        * forcewake being disabled.
+                        */
+                       mutex_lock(&dev->struct_mutex);
+                       __gen6_gt_force_wake_mt_get(dev_priv);
+                       ecobus = I915_READ_NOTRACE(ECOBUS);
+                       __gen6_gt_force_wake_mt_put(dev_priv);
+                       mutex_unlock(&dev->struct_mutex);
+
+                       if (ecobus & FORCEWAKE_MT_ENABLE) {
+                               DRM_DEBUG_KMS("Using MT version of forcewake\n");
+                               dev_priv->gt.force_wake_get =
+                                       __gen6_gt_force_wake_mt_get;
+                               dev_priv->gt.force_wake_put =
+                                       __gen6_gt_force_wake_mt_put;
+                       }
+               }
+       }
+}
+