drm/i915/skl: Add SKL HW status to SSEU status
authorJeff McGee <jeff.mcgee@intel.com>
Fri, 13 Feb 2015 16:27:55 +0000 (10:27 -0600)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Mon, 23 Feb 2015 22:57:08 +0000 (23:57 +0100)
Add a new section to the 'i915_sseu_status' debugfs entry to
report the currently enabled counts of slice, subslice, and
execution units on the device. The count of enabled subslice
per slice represents the most enabled subslice on any one
slice for devices where imbalances may exist. Similarly, the
count of enabled EU per subslice represents the most enabled
EU on any one subslice.

Collect this device status for Skylake by reading the Gen9
power gate control ack message registers. Power gate control
operates on EU in pairs, therefore our reported counts of
enabled EU can be overestimated by one for each pair in which
one EU is fused-off.

Signed-off-by: Jeff McGee <jeff.mcgee@intel.com>
Reviewed-by: Damien Lespiau <damien.lespiau@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_reg.h

index 238cd6fa48af64636d634ab758ae2eeba71f8203..ac3f07e5511985820b11e11beef98dbb74d59e01 100644 (file)
@@ -4362,6 +4362,8 @@ 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 drm_i915_private *dev_priv = dev->dev_private;
+       unsigned int s_tot = 0, ss_tot = 0, ss_per = 0, eu_tot = 0, eu_per = 0;
 
        if (INTEL_INFO(dev)->gen < 9)
                return -ENODEV;
@@ -4384,6 +4386,54 @@ static int i915_sseu_status(struct seq_file *m, void *unused)
        seq_printf(m, "  Has EU Power Gating: %s\n",
                   yesno(INTEL_INFO(dev)->has_eu_pg));
 
+       seq_puts(m, "SSEU Device Status\n");
+       if (IS_SKYLAKE(dev)) {
+               const int s_max = 3, ss_max = 4;
+               int s, ss;
+               u32 s_reg[s_max], eu_reg[2*s_max], eu_mask[2];
+
+               s_reg[0] = I915_READ(GEN9_SLICE0_PGCTL_ACK);
+               s_reg[1] = I915_READ(GEN9_SLICE1_PGCTL_ACK);
+               s_reg[2] = I915_READ(GEN9_SLICE2_PGCTL_ACK);
+               eu_reg[0] = I915_READ(GEN9_SLICE0_SS01_EU_PGCTL_ACK);
+               eu_reg[1] = I915_READ(GEN9_SLICE0_SS23_EU_PGCTL_ACK);
+               eu_reg[2] = I915_READ(GEN9_SLICE1_SS01_EU_PGCTL_ACK);
+               eu_reg[3] = I915_READ(GEN9_SLICE1_SS23_EU_PGCTL_ACK);
+               eu_reg[4] = I915_READ(GEN9_SLICE2_SS01_EU_PGCTL_ACK);
+               eu_reg[5] = I915_READ(GEN9_SLICE2_SS23_EU_PGCTL_ACK);
+               eu_mask[0] = GEN9_PGCTL_SSA_EU08_ACK |
+                            GEN9_PGCTL_SSA_EU19_ACK |
+                            GEN9_PGCTL_SSA_EU210_ACK |
+                            GEN9_PGCTL_SSA_EU311_ACK;
+               eu_mask[1] = GEN9_PGCTL_SSB_EU08_ACK |
+                            GEN9_PGCTL_SSB_EU19_ACK |
+                            GEN9_PGCTL_SSB_EU210_ACK |
+                            GEN9_PGCTL_SSB_EU311_ACK;
+
+               for (s = 0; s < s_max; s++) {
+                       if ((s_reg[s] & GEN9_PGCTL_SLICE_ACK) == 0)
+                               /* skip disabled slice */
+                               continue;
+
+                       s_tot++;
+                       ss_per = INTEL_INFO(dev)->subslice_per_slice;
+                       ss_tot += ss_per;
+                       for (ss = 0; ss < ss_max; ss++) {
+                               unsigned int eu_cnt;
+
+                               eu_cnt = 2 * hweight32(eu_reg[2*s + ss/2] &
+                                                      eu_mask[ss%2]);
+                               eu_tot += eu_cnt;
+                               eu_per = max(eu_per, eu_cnt);
+                       }
+               }
+       }
+       seq_printf(m, "  Enabled Slice Total: %u\n", s_tot);
+       seq_printf(m, "  Enabled Subslice Total: %u\n", ss_tot);
+       seq_printf(m, "  Enabled Subslice Per Slice: %u\n", ss_per);
+       seq_printf(m, "  Enabled EU Total: %u\n", eu_tot);
+       seq_printf(m, "  Enabled EU Per Subslice: %u\n", eu_per);
+
        return 0;
 }
 
index f9d4367ee8d4f536f4c9e86fc1258915e75a89f9..4da883b2c3c844d3639e4e38a5d12c1a524000a8 100644 (file)
@@ -6209,6 +6209,26 @@ enum skl_disp_power_wells {
 #define   GEN6_RC6                     3
 #define   GEN6_RC7                     4
 
+#define GEN9_SLICE0_PGCTL_ACK          0x804c
+#define GEN9_SLICE1_PGCTL_ACK          0x8050
+#define GEN9_SLICE2_PGCTL_ACK          0x8054
+#define   GEN9_PGCTL_SLICE_ACK         (1 << 0)
+
+#define GEN9_SLICE0_SS01_EU_PGCTL_ACK  0x805c
+#define GEN9_SLICE0_SS23_EU_PGCTL_ACK  0x8060
+#define GEN9_SLICE1_SS01_EU_PGCTL_ACK  0x8064
+#define GEN9_SLICE1_SS23_EU_PGCTL_ACK  0x8068
+#define GEN9_SLICE2_SS01_EU_PGCTL_ACK  0x806c
+#define GEN9_SLICE2_SS23_EU_PGCTL_ACK  0x8070
+#define   GEN9_PGCTL_SSA_EU08_ACK      (1 << 0)
+#define   GEN9_PGCTL_SSA_EU19_ACK      (1 << 2)
+#define   GEN9_PGCTL_SSA_EU210_ACK     (1 << 4)
+#define   GEN9_PGCTL_SSA_EU311_ACK     (1 << 6)
+#define   GEN9_PGCTL_SSB_EU08_ACK      (1 << 8)
+#define   GEN9_PGCTL_SSB_EU19_ACK      (1 << 10)
+#define   GEN9_PGCTL_SSB_EU210_ACK     (1 << 12)
+#define   GEN9_PGCTL_SSB_EU311_ACK     (1 << 14)
+
 #define GEN7_MISCCPCTL                 (0x9424)
 #define   GEN7_DOP_CLOCK_GATE_ENABLE   (1<<0)