drm/i915/bdw: Check for slice, subslice and EU count for BDW
authorŁukasz Daniluk <lukasz.daniluk@intel.com>
Fri, 25 Sep 2015 09:54:58 +0000 (11:54 +0200)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Wed, 30 Sep 2015 12:13:03 +0000 (14:13 +0200)
Added checks for available slices, subslices and EUs for Broadwell. This
information is filled in intel_device_info and is available to user with
GET_PARAM.
Added checks for enabled slices, subslices and EU for Broadwell. This
information is based on available counts but takes power gated slices
into account. It can be read in debugfs.
Introduce new register defines that contain information on slices on
Broadwell.

v2:
- Introduce GT_SLICE_INFO register
- Change Broadwell sseu_device_status function to use GT_SLICE_INFO
  register instead of RPCS register
- Undo removal of dev_priv variables in Cherryview and Gen9
  sseu_device_satus functions

v3:
- Fix style issues

v4:
- Corrected comment
- Reverted reordering of defines

Cc: Jeff Mcgee <jeff.mcgee@intel.com>
Cc: Arun Siluvery <arun.siluvery@linux.intel.com>
Signed-off-by: Łukasz Daniluk <lukasz.daniluk@intel.com>
Reviewed-by: Jeff McGee <jeff.mcgee@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_reg.h

index 9839831..2ac1ba8 100644 (file)
@@ -5048,13 +5048,38 @@ static void gen9_sseu_device_status(struct drm_device *dev,
        }
 }
 
+static void broadwell_sseu_device_status(struct drm_device *dev,
+                                        struct sseu_dev_status *stat)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int s;
+       u32 slice_info = I915_READ(GEN8_GT_SLICE_INFO);
+
+       stat->slice_total = hweight32(slice_info & GEN8_LSLICESTAT_MASK);
+
+       if (stat->slice_total) {
+               stat->subslice_per_slice = INTEL_INFO(dev)->subslice_per_slice;
+               stat->subslice_total = stat->slice_total *
+                                      stat->subslice_per_slice;
+               stat->eu_per_subslice = INTEL_INFO(dev)->eu_per_subslice;
+               stat->eu_total = stat->eu_per_subslice * stat->subslice_total;
+
+               /* subtract fused off EU(s) from enabled slice(s) */
+               for (s = 0; s < stat->slice_total; s++) {
+                       u8 subslice_7eu = INTEL_INFO(dev)->subslice_7eu[s];
+
+                       stat->eu_total -= hweight8(subslice_7eu);
+               }
+       }
+}
+
 static int i915_sseu_status(struct seq_file *m, void *unused)
 {
        struct drm_info_node *node = (struct drm_info_node *) m->private;
        struct drm_device *dev = node->minor->dev;
        struct sseu_dev_status stat;
 
-       if ((INTEL_INFO(dev)->gen < 8) || IS_BROADWELL(dev))
+       if (INTEL_INFO(dev)->gen < 8)
                return -ENODEV;
 
        seq_puts(m, "SSEU Device Info\n");
@@ -5079,6 +5104,8 @@ static int i915_sseu_status(struct seq_file *m, void *unused)
        memset(&stat, 0, sizeof(stat));
        if (IS_CHERRYVIEW(dev)) {
                cherryview_sseu_device_status(dev, &stat);
+       } else if (IS_BROADWELL(dev)) {
+               broadwell_sseu_device_status(dev, &stat);
        } else if (INTEL_INFO(dev)->gen >= 9) {
                gen9_sseu_device_status(dev, &stat);
        }
index ae1ba47..20b4b79 100644 (file)
@@ -702,6 +702,82 @@ static void gen9_sseu_info_init(struct drm_device *dev)
        info->has_eu_pg = (info->eu_per_subslice > 2);
 }
 
+static void broadwell_sseu_info_init(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_device_info *info;
+       const int s_max = 3, ss_max = 3, eu_max = 8;
+       int s, ss;
+       u32 fuse2, eu_disable[s_max], s_enable, ss_disable;
+
+       fuse2 = I915_READ(GEN8_FUSE2);
+       s_enable = (fuse2 & GEN8_F2_S_ENA_MASK) >> GEN8_F2_S_ENA_SHIFT;
+       ss_disable = (fuse2 & GEN8_F2_SS_DIS_MASK) >> GEN8_F2_SS_DIS_SHIFT;
+
+       eu_disable[0] = I915_READ(GEN8_EU_DISABLE0) & GEN8_EU_DIS0_S0_MASK;
+       eu_disable[1] = (I915_READ(GEN8_EU_DISABLE0) >> GEN8_EU_DIS0_S1_SHIFT) |
+                       ((I915_READ(GEN8_EU_DISABLE1) & GEN8_EU_DIS1_S1_MASK) <<
+                        (32 - GEN8_EU_DIS0_S1_SHIFT));
+       eu_disable[2] = (I915_READ(GEN8_EU_DISABLE1) >> GEN8_EU_DIS1_S2_SHIFT) |
+                       ((I915_READ(GEN8_EU_DISABLE2) & GEN8_EU_DIS2_S2_MASK) <<
+                        (32 - GEN8_EU_DIS1_S2_SHIFT));
+
+
+       info = (struct intel_device_info *)&dev_priv->info;
+       info->slice_total = hweight32(s_enable);
+
+       /*
+        * The subslice disable field is global, i.e. it applies
+        * to each of the enabled slices.
+        */
+       info->subslice_per_slice = ss_max - hweight32(ss_disable);
+       info->subslice_total = info->slice_total * info->subslice_per_slice;
+
+       /*
+        * Iterate through enabled slices and subslices to
+        * count the total enabled EU.
+        */
+       for (s = 0; s < s_max; s++) {
+               if (!(s_enable & (0x1 << s)))
+                       /* skip disabled slice */
+                       continue;
+
+               for (ss = 0; ss < ss_max; ss++) {
+                       u32 n_disabled;
+
+                       if (ss_disable & (0x1 << ss))
+                               /* skip disabled subslice */
+                               continue;
+
+                       n_disabled = hweight8(eu_disable[s] >> (ss * eu_max));
+
+                       /*
+                        * Record which subslices have 7 EUs.
+                        */
+                       if (eu_max - n_disabled == 7)
+                               info->subslice_7eu[s] |= 1 << ss;
+
+                       info->eu_total += eu_max - n_disabled;
+               }
+       }
+
+       /*
+        * BDW is expected to always have a uniform distribution of EU across
+        * subslices with the exception that any one EU in any one subslice may
+        * be fused off for die recovery.
+        */
+       info->eu_per_subslice = info->subslice_total ?
+               DIV_ROUND_UP(info->eu_total, info->subslice_total) : 0;
+
+       /*
+        * BDW supports slice power gating on devices with more than
+        * one slice.
+        */
+       info->has_slice_pg = (info->slice_total > 1);
+       info->has_subslice_pg = 0;
+       info->has_eu_pg = 0;
+}
+
 /*
  * Determine various intel_device_info fields at runtime.
  *
@@ -772,6 +848,8 @@ static void intel_device_info_runtime_init(struct drm_device *dev)
        /* Initialize slice/subslice/EU info */
        if (IS_CHERRYVIEW(dev))
                cherryview_sseu_info_init(dev);
+       else if (IS_BROADWELL(dev))
+               broadwell_sseu_info_init(dev);
        else if (INTEL_INFO(dev)->gen >= 9)
                gen9_sseu_info_init(dev);
 
index 3709d6b..0b2e314 100644 (file)
@@ -1887,12 +1887,27 @@ enum skl_disp_power_wells {
 #define   CHV_FGT_EU_DIS_SS1_R1_MASK   (0xf << CHV_FGT_EU_DIS_SS1_R1_SHIFT)
 
 #define GEN8_FUSE2                     0x9120
+#define   GEN8_F2_SS_DIS_SHIFT         21
+#define   GEN8_F2_SS_DIS_MASK          (0x7 << GEN8_F2_SS_DIS_SHIFT)
 #define   GEN8_F2_S_ENA_SHIFT          25
 #define   GEN8_F2_S_ENA_MASK           (0x7 << GEN8_F2_S_ENA_SHIFT)
 
 #define   GEN9_F2_SS_DIS_SHIFT         20
 #define   GEN9_F2_SS_DIS_MASK          (0xf << GEN9_F2_SS_DIS_SHIFT)
 
+#define GEN8_EU_DISABLE0               0x9134
+#define   GEN8_EU_DIS0_S0_MASK         0xffffff
+#define   GEN8_EU_DIS0_S1_SHIFT                24
+#define   GEN8_EU_DIS0_S1_MASK         (0xff << GEN8_EU_DIS0_S1_SHIFT)
+
+#define GEN8_EU_DISABLE1               0x9138
+#define   GEN8_EU_DIS1_S1_MASK         0xffff
+#define   GEN8_EU_DIS1_S2_SHIFT                16
+#define   GEN8_EU_DIS1_S2_MASK         (0xffff << GEN8_EU_DIS1_S2_SHIFT)
+
+#define GEN8_EU_DISABLE2               0x913c
+#define   GEN8_EU_DIS2_S2_MASK         0xff
+
 #define GEN9_EU_DISABLE(slice)         (0x9134 + (slice)*0x4)
 
 #define GEN6_BSD_SLEEP_PSMI_CONTROL    0x12050
@@ -6885,6 +6900,9 @@ enum skl_disp_power_wells {
 #define   GEN6_RC6                     3
 #define   GEN6_RC7                     4
 
+#define GEN8_GT_SLICE_INFO             0x138064
+#define   GEN8_LSLICESTAT_MASK         0x7
+
 #define CHV_POWER_SS0_SIG1             0xa720
 #define CHV_POWER_SS1_SIG1             0xa728
 #define   CHV_SS_PG_ENABLE             (1<<1)