public inbox for intel-gfx@lists.freedesktop.org
 help / color / mirror / Atom feed
* [PATCH] drm/i915/bdw: Check for slice, subslice and EU count for BDW
@ 2015-08-13 12:38 Łukasz Daniluk
  2015-08-13 21:34 ` Bish, Jim
                   ` (2 more replies)
  0 siblings, 3 replies; 13+ messages in thread
From: Łukasz Daniluk @ 2015-08-13 12:38 UTC (permalink / raw)
  To: intel-gfx

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.

Cc: Jeff Mcgee <jeff.mcgee@intel.com>
Signed-off-by: Łukasz Daniluk <lukasz.daniluk@intel.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c | 35 +++++++++++++--
 drivers/gpu/drm/i915/i915_dma.c     | 89 +++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_reg.h     | 19 +++++++-
 3 files changed, 138 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 23a69307..a17f912 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -4838,7 +4838,6 @@ struct sseu_dev_status {
 static void cherryview_sseu_device_status(struct drm_device *dev,
 					  struct sseu_dev_status *stat)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
 	const int ss_max = 2;
 	int ss;
 	u32 sig1[ss_max], sig2[ss_max];
@@ -4870,7 +4869,6 @@ static void cherryview_sseu_device_status(struct drm_device *dev,
 static void gen9_sseu_device_status(struct drm_device *dev,
 				    struct sseu_dev_status *stat)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
 	int s_max = 3, ss_max = 4;
 	int s, ss;
 	u32 s_reg[s_max], eu_reg[2*s_max], eu_mask[2];
@@ -4932,13 +4930,42 @@ 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)
+{
+	int s;
+	u32 slice_info = I915_READ(GEN8_R_PWR_CLK_STATE);
+
+	/*
+	 * If first bit of slice_info is 0, there is no specific power
+	 * state set. Otherwise we read the count of enabled slices
+	 * from it.
+	 */
+	if (slice_info & (1<<31))
+		stat->slice_total = (slice_info & GEN8_RPCS_S_CNT_MASK)
+			>> GEN8_RPCS_S_CNT_SHIFT;
+	else
+		stat->slice_total = INTEL_INFO(dev)->slice_total;
+
+	stat->subslice_per_slice = INTEL_INFO(dev)->subslice_per_slice;
+	stat->eu_per_subslice = INTEL_INFO(dev)->eu_per_subslice;
+	stat->subslice_total = stat->slice_total * stat->subslice_per_slice;
+	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");
@@ -4963,6 +4990,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);
 	}
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index ab37d11..2d52b1e 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -705,6 +705,93 @@ 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 subslice(s) has(have) 7 EUs. we
+			 * can tune the hash used to spread work among
+			 * subslices if they are unbalanced.
+			 */
+			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.
  *
@@ -775,6 +862,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);
 
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index be87e3b..77e043e 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -1841,11 +1841,26 @@ 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_F2_SS_DIS_SHIFT		20
+#define GEN9_F2_SS_DIS_MASK		(0xf << GEN9_F2_SS_DIS_SHIFT)
 
 #define GEN9_EU_DISABLE(slice)		(0x9134 + (slice)*0x4)
 
-- 
Lukasz Daniluk

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH] drm/i915/bdw: Check for slice, subslice and EU count for BDW
  2015-08-13 12:38 [PATCH] drm/i915/bdw: Check for slice, subslice and EU count for BDW Łukasz Daniluk
@ 2015-08-13 21:34 ` Bish, Jim
  2015-08-14  0:11 ` Jeff McGee
  2015-09-02 15:47 ` [PATCH v2] " Łukasz Daniluk
  2 siblings, 0 replies; 13+ messages in thread
From: Bish, Jim @ 2015-08-13 21:34 UTC (permalink / raw)
  To: intel-gfx@lists.freedesktop.org

On Thu, 2015-08-13 at 14:38 +0200, Łukasz Daniluk wrote:
> 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.
> 
> Cc: Jeff Mcgee <jeff.mcgee@intel.com>
> Signed-off-by: Łukasz Daniluk <lukasz.daniluk@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_debugfs.c | 35 +++++++++++++--
>  drivers/gpu/drm/i915/i915_dma.c     | 89 
> +++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/i915_reg.h     | 19 +++++++-
>  3 files changed, 138 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c 
> b/drivers/gpu/drm/i915/i915_debugfs.c
> index 23a69307..a17f912 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -4838,7 +4838,6 @@ struct sseu_dev_status {
>  static void cherryview_sseu_device_status(struct drm_device *dev,
>                                         struct sseu_dev_status *stat)
>  {
> -     struct drm_i915_private *dev_priv = dev->dev_private;
>       const int ss_max = 2;
>       int ss;
>       u32 sig1[ss_max], sig2[ss_max];
> @@ -4870,7 +4869,6 @@ static void 
> cherryview_sseu_device_status(struct drm_device *dev,
>  static void gen9_sseu_device_status(struct drm_device *dev,
>                                   struct sseu_dev_status *stat)
>  {
> -     struct drm_i915_private *dev_priv = dev->dev_private;
>       int s_max = 3, ss_max = 4;
>       int s, ss;
>       u32 s_reg[s_max], eu_reg[2*s_max], eu_mask[2];
> @@ -4932,13 +4930,42 @@ 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)
> +{
> +     int s;
> +     u32 slice_info = I915_READ(GEN8_R_PWR_CLK_STATE);
> +
> +     /*
> +      * If first bit of slice_info is 0, there is no specific power
> +      * state set. Otherwise we read the count of enabled slices
> +      * from it.
> +      */
> +     if (slice_info & (1<<31))
> +             stat->slice_total = (slice_info & GEN8_RPCS_S_CNT_MASK)
> +                     >> GEN8_RPCS_S_CNT_SHIFT;
> +     else
> +             stat->slice_total = INTEL_INFO(dev)->slice_total;
> +
> +     stat->subslice_per_slice = INTEL_INFO(dev)->subslice_per_slice;
> +     stat->eu_per_subslice = INTEL_INFO(dev)->eu_per_subslice;
> +     stat->subslice_total = stat->slice_total * stat-
> >subslice_per_slice;
> +     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");
> @@ -4963,6 +4990,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);
>       }
> diff --git a/drivers/gpu/drm/i915/i915_dma.c 
> b/drivers/gpu/drm/i915/i915_dma.c
> index ab37d11..2d52b1e 100644
> --- a/drivers/gpu/drm/i915/i915_dma.c
> +++ b/drivers/gpu/drm/i915/i915_dma.c
> @@ -705,6 +705,93 @@ 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 subslice(s) has(have) 7 EUs. we
> +                      * can tune the hash used to spread work among
> +                      * subslices if they are unbalanced.
> +                      */
> +                     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.
I like comments but wondering if fused off for die recovery is ok.  W
ould it be better to indicate for sku options or something?
> +      */
> +     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.
>   *
> @@ -775,6 +862,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);
>  
> diff --git a/drivers/gpu/drm/i915/i915_reg.h 
> b/drivers/gpu/drm/i915/i915_reg.h
> index be87e3b..77e043e 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -1841,11 +1841,26 @@ 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_F2_SS_DIS_SHIFT         20
> +#define GEN9_F2_SS_DIS_MASK          (0xf << GEN9_F2_SS_DIS_SHIFT)
>  
>  #define GEN9_EU_DISABLE(slice)               (0x9134 + (slice)*0x4)
>  
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH] drm/i915/bdw: Check for slice, subslice and EU count for BDW
  2015-08-13 12:38 [PATCH] drm/i915/bdw: Check for slice, subslice and EU count for BDW Łukasz Daniluk
  2015-08-13 21:34 ` Bish, Jim
@ 2015-08-14  0:11 ` Jeff McGee
  2015-09-02 15:47 ` [PATCH v2] " Łukasz Daniluk
  2 siblings, 0 replies; 13+ messages in thread
From: Jeff McGee @ 2015-08-14  0:11 UTC (permalink / raw)
  To: Łukasz Daniluk; +Cc: intel-gfx

On Thu, Aug 13, 2015 at 02:38:48PM +0200, Łukasz Daniluk wrote:
> 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.
> 
> Cc: Jeff Mcgee <jeff.mcgee@intel.com>
> Signed-off-by: Łukasz Daniluk <lukasz.daniluk@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_debugfs.c | 35 +++++++++++++--
>  drivers/gpu/drm/i915/i915_dma.c     | 89 +++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/i915_reg.h     | 19 +++++++-
>  3 files changed, 138 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> index 23a69307..a17f912 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -4838,7 +4838,6 @@ struct sseu_dev_status {
>  static void cherryview_sseu_device_status(struct drm_device *dev,
>  					  struct sseu_dev_status *stat)
>  {
> -	struct drm_i915_private *dev_priv = dev->dev_private;
Did you compile this? I915_READ macro requires dev_priv.

>  	const int ss_max = 2;
>  	int ss;
>  	u32 sig1[ss_max], sig2[ss_max];
> @@ -4870,7 +4869,6 @@ static void cherryview_sseu_device_status(struct drm_device *dev,
>  static void gen9_sseu_device_status(struct drm_device *dev,
>  				    struct sseu_dev_status *stat)
>  {
> -	struct drm_i915_private *dev_priv = dev->dev_private;
Did you compile this? I915_READ macro requires dev_priv.
>  	int s_max = 3, ss_max = 4;
>  	int s, ss;
>  	u32 s_reg[s_max], eu_reg[2*s_max], eu_mask[2];
> @@ -4932,13 +4930,42 @@ 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)
> +{
> +	int s;
> +	u32 slice_info = I915_READ(GEN8_R_PWR_CLK_STATE);
RPCS register only shows what slice state was requested, not the actual
slice state. You need to use the GEN8_GT_SLICE_INFO register that I
shared with you in my original patch for this.
> +
> +	/*
> +	 * If first bit of slice_info is 0, there is no specific power
> +	 * state set. Otherwise we read the count of enabled slices
> +	 * from it.
> +	 */
> +	if (slice_info & (1<<31))
> +		stat->slice_total = (slice_info & GEN8_RPCS_S_CNT_MASK)
> +			>> GEN8_RPCS_S_CNT_SHIFT;
> +	else
> +		stat->slice_total = INTEL_INFO(dev)->slice_total;
> +
> +	stat->subslice_per_slice = INTEL_INFO(dev)->subslice_per_slice;
> +	stat->eu_per_subslice = INTEL_INFO(dev)->eu_per_subslice;
> +	stat->subslice_total = stat->slice_total * stat->subslice_per_slice;
> +	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");
> @@ -4963,6 +4990,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);
>  	}
> diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
> index ab37d11..2d52b1e 100644
> --- a/drivers/gpu/drm/i915/i915_dma.c
> +++ b/drivers/gpu/drm/i915/i915_dma.c
> @@ -705,6 +705,93 @@ 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 subslice(s) has(have) 7 EUs. we
> +			 * can tune the hash used to spread work among
> +			 * subslices if they are unbalanced.
> +			 */
> +			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.
>   *
> @@ -775,6 +862,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);
>  
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index be87e3b..77e043e 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -1841,11 +1841,26 @@ 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_F2_SS_DIS_SHIFT		20
> +#define GEN9_F2_SS_DIS_MASK		(0xf << GEN9_F2_SS_DIS_SHIFT)
>  
>  #define GEN9_EU_DISABLE(slice)		(0x9134 + (slice)*0x4)
>  
> -- 
> Lukasz Daniluk
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2] drm/i915/bdw: Check for slice, subslice and EU count for BDW
  2015-09-02 15:47 ` [PATCH v2] " Łukasz Daniluk
@ 2015-09-02 14:03   ` Chris Wilson
  2015-09-08 11:29     ` Daniluk, Lukasz
  2015-09-02 15:08   ` Arun Siluvery
  2015-09-17 11:51   ` [PATCH v3] " Łukasz Daniluk
  2 siblings, 1 reply; 13+ messages in thread
From: Chris Wilson @ 2015-09-02 14:03 UTC (permalink / raw)
  To: Łukasz Daniluk; +Cc: intel-gfx

On Wed, Sep 02, 2015 at 05:47:58PM +0200, Łukasz Daniluk wrote:
> +static void broadwell_sseu_device_status(struct drm_device *dev,

Why pass in dev if you only use dev_priv (and commit the sin of
repeatedly retrieving dev->dev_priv)?

> +					 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)
> +	{
Missed.

> +		stat->subslice_per_slice = INTEL_INFO(dev)->subslice_per_slice;
> +		stat->eu_per_subslice = INTEL_INFO(dev)->eu_per_subslice;
> +		stat->subslice_total = stat->slice_total * stat->subslice_per_slice;
> +		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);
> +		}

So why are we computing this twice? Is the debugfs to show the hw
registers or the sw tracking? Where do I see what we actually report? If
it is for the hw registers, report them. A perfect function here would
report the actual register values (possibly decoding them) and show what
the internal values are.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2] drm/i915/bdw: Check for slice, subslice and EU count for BDW
  2015-09-02 15:47 ` [PATCH v2] " Łukasz Daniluk
  2015-09-02 14:03   ` Chris Wilson
@ 2015-09-02 15:08   ` Arun Siluvery
  2015-09-08 12:53     ` Daniluk, Lukasz
  2015-09-17 11:51   ` [PATCH v3] " Łukasz Daniluk
  2 siblings, 1 reply; 13+ messages in thread
From: Arun Siluvery @ 2015-09-02 15:08 UTC (permalink / raw)
  To: Łukasz Daniluk, intel-gfx

On 02/09/2015 16:47, Łukasz Daniluk wrote:
> 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
>
> Cc: Jeff Mcgee <jeff.mcgee@intel.com>
> Signed-off-by: Łukasz Daniluk <lukasz.daniluk@intel.com>
> ---
>   drivers/gpu/drm/i915/i915_debugfs.c | 29 +++++++++++-
>   drivers/gpu/drm/i915/i915_dma.c     | 89 +++++++++++++++++++++++++++++++++++++
>   drivers/gpu/drm/i915/i915_reg.h     | 22 ++++++++-
>   3 files changed, 137 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> index 23a69307..e8a62ef 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -4932,13 +4932,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);
I don't see this register (0x138064 as defined below) in bdw spec.

> +
> +	stat->slice_total =
> +		hweight32(slice_info & GEN8_LSLICESTAT_MASK);

why not in a single line, seems to fit under 80 chars.

> +
> +	if (stat->slice_total)
> +	{
> +		stat->subslice_per_slice = INTEL_INFO(dev)->subslice_per_slice;
> +		stat->eu_per_subslice = INTEL_INFO(dev)->eu_per_subslice;
> +		stat->subslice_total = stat->slice_total * stat->subslice_per_slice;
> +		stat->eu_total = stat->eu_per_subslice * stat->subslice_total;
> +
Please reorder such that all subslice values are populated first 
followed by EUs to follow an order.

> +		/* 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");
> @@ -4963,6 +4988,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);
>   	}
> diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
> index ab37d11..2d52b1e 100644
> --- a/drivers/gpu/drm/i915/i915_dma.c
> +++ b/drivers/gpu/drm/i915/i915_dma.c
> @@ -705,6 +705,93 @@ 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;
I only see max of 2 slices for bdw in spec.

> +	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));
> +

GEN9_EU_DISABLE(slice) is already available, since the register 
addresses are same maybe it can be reused after renaming it to GEN8 
instead of creating new definitions? ofcourse shift/mask are different.

Indentation is off, in general please use () to force indentation.
first two statements can fit in single line.

regards
Arun

> +
> +	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 subslice(s) has(have) 7 EUs. we
> +			 * can tune the hash used to spread work among
> +			 * subslices if they are unbalanced.
> +			 */
> +			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.
>    *
> @@ -775,6 +862,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);
>
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index be87e3b..37f658f 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -1841,11 +1841,26 @@ 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_F2_SS_DIS_SHIFT		20
> +#define GEN9_F2_SS_DIS_MASK		(0xf << GEN9_F2_SS_DIS_SHIFT)
>
>   #define GEN9_EU_DISABLE(slice)		(0x9134 + (slice)*0x4)
>
> @@ -6822,6 +6837,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)
>

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v2] drm/i915/bdw: Check for slice, subslice and EU count for BDW
  2015-08-13 12:38 [PATCH] drm/i915/bdw: Check for slice, subslice and EU count for BDW Łukasz Daniluk
  2015-08-13 21:34 ` Bish, Jim
  2015-08-14  0:11 ` Jeff McGee
@ 2015-09-02 15:47 ` Łukasz Daniluk
  2015-09-02 14:03   ` Chris Wilson
                     ` (2 more replies)
  2 siblings, 3 replies; 13+ messages in thread
From: Łukasz Daniluk @ 2015-09-02 15:47 UTC (permalink / raw)
  To: intel-gfx

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

Cc: Jeff Mcgee <jeff.mcgee@intel.com>
Signed-off-by: Łukasz Daniluk <lukasz.daniluk@intel.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c | 29 +++++++++++-
 drivers/gpu/drm/i915/i915_dma.c     | 89 +++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_reg.h     | 22 ++++++++-
 3 files changed, 137 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 23a69307..e8a62ef 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -4932,13 +4932,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->eu_per_subslice = INTEL_INFO(dev)->eu_per_subslice;
+		stat->subslice_total = stat->slice_total * stat->subslice_per_slice;
+		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");
@@ -4963,6 +4988,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);
 	}
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index ab37d11..2d52b1e 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -705,6 +705,93 @@ 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 subslice(s) has(have) 7 EUs. we
+			 * can tune the hash used to spread work among
+			 * subslices if they are unbalanced.
+			 */
+			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.
  *
@@ -775,6 +862,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);
 
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index be87e3b..37f658f 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -1841,11 +1841,26 @@ 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_F2_SS_DIS_SHIFT		20
+#define GEN9_F2_SS_DIS_MASK		(0xf << GEN9_F2_SS_DIS_SHIFT)
 
 #define GEN9_EU_DISABLE(slice)		(0x9134 + (slice)*0x4)
 
@@ -6822,6 +6837,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)
-- 
Lukasz Daniluk

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH v2] drm/i915/bdw: Check for slice, subslice and EU count for BDW
  2015-09-02 14:03   ` Chris Wilson
@ 2015-09-08 11:29     ` Daniluk, Lukasz
  0 siblings, 0 replies; 13+ messages in thread
From: Daniluk, Lukasz @ 2015-09-08 11:29 UTC (permalink / raw)
  To: Chris Wilson; +Cc: intel-gfx@lists.freedesktop.org

> -----Original Message-----
> From: Chris Wilson [mailto:chris@chris-wilson.co.uk]
> Sent: Wednesday, September 2, 2015 16:03
> To: Daniluk, Lukasz
> Cc: intel-gfx@lists.freedesktop.org
> Subject: Re: [Intel-gfx] [PATCH v2] drm/i915/bdw: Check for slice, subslice and
> EU count for BDW
> 
> On Wed, Sep 02, 2015 at 05:47:58PM +0200, Łukasz Daniluk wrote:
> > +static void broadwell_sseu_device_status(struct drm_device *dev,
> 
> Why pass in dev if you only use dev_priv (and commit the sin of repeatedly
> retrieving dev->dev_priv)?

I was following the style of other _sseu_device_status functions. 
Also, I use INTEL_INFO that wants dev argument.

> 
> > +					 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)
> > +	{
> Missed.

Do you mean anything else than bracket here?

> 
> > +		stat->subslice_per_slice = INTEL_INFO(dev)->subslice_per_slice;
> > +		stat->eu_per_subslice = INTEL_INFO(dev)->eu_per_subslice;
> > +		stat->subslice_total = stat->slice_total * stat-
> >subslice_per_slice;
> > +		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);
> > +		}
> 
> So why are we computing this twice? Is the debugfs to show the hw registers or
> the sw tracking? Where do I see what we actually report? If it is for the hw
> registers, report them. A perfect function here would report the actual register
> values (possibly decoding them) and show what the internal values are.
> -Chris
> 
> --
> Chris Wilson, Intel Open Source Technology Centre

Nothing is computed twice here - all values that are unchanged are read using INTEL_INFO macro.
What is computed however is amount of active (not simply present on the system) subslices and EUs. 
These values depend on number of active slices. The for loop checks if the one of the active slice is 
the one with EU fused off for die recovery. When you read i915_sseu_status the first part (SSEU Device 
Info) gives you information on general capabilities (things that can be read using INTEL_INFO(dev)), 
the second part (SSEU Device Status) is giving you the contents of stat struct.

---
Łukasz Daniluk
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2] drm/i915/bdw: Check for slice, subslice and EU count for BDW
  2015-09-02 15:08   ` Arun Siluvery
@ 2015-09-08 12:53     ` Daniluk, Lukasz
  2015-09-08 15:15       ` Arun Siluvery
  0 siblings, 1 reply; 13+ messages in thread
From: Daniluk, Lukasz @ 2015-09-08 12:53 UTC (permalink / raw)
  To: Arun Siluvery, intel-gfx@lists.freedesktop.org

> -----Original Message-----
> From: Arun Siluvery [mailto:arun.siluvery@linux.intel.com]
> Sent: Wednesday, September 2, 2015 17:08
> To: Daniluk, Lukasz; intel-gfx@lists.freedesktop.org
> Subject: Re: [Intel-gfx] [PATCH v2] drm/i915/bdw: Check for slice, subslice and
> EU count for BDW
> 
> On 02/09/2015 16:47, Łukasz Daniluk wrote:
> > 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
> >
> > Cc: Jeff Mcgee <jeff.mcgee@intel.com>
> > Signed-off-by: Łukasz Daniluk <lukasz.daniluk@intel.com>
> > ---
> >   drivers/gpu/drm/i915/i915_debugfs.c | 29 +++++++++++-
> >   drivers/gpu/drm/i915/i915_dma.c     | 89
> +++++++++++++++++++++++++++++++++++++
> >   drivers/gpu/drm/i915/i915_reg.h     | 22 ++++++++-
> >   3 files changed, 137 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/i915_debugfs.c
> > b/drivers/gpu/drm/i915/i915_debugfs.c
> > index 23a69307..e8a62ef 100644
> > --- a/drivers/gpu/drm/i915/i915_debugfs.c
> > +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> > @@ -4932,13 +4932,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);
> I don't see this register (0x138064 as defined below) in bdw spec.
> 

Yes, this register isn't listed in spec. I am unsure when the full spec for this register 
will be published.

> > +
> > +	stat->slice_total =
> > +		hweight32(slice_info & GEN8_LSLICESTAT_MASK);
> 
> why not in a single line, seems to fit under 80 chars.
> 

I was using longer define name and didn't recheck if this line fits under 80. Thanks for catch.

> > +
> > +	if (stat->slice_total)
> > +	{
> > +		stat->subslice_per_slice = INTEL_INFO(dev)->subslice_per_slice;
> > +		stat->eu_per_subslice = INTEL_INFO(dev)->eu_per_subslice;
> > +		stat->subslice_total = stat->slice_total * stat-
> >subslice_per_slice;
> > +		stat->eu_total = stat->eu_per_subslice * stat->subslice_total;
> > +
> Please reorder such that all subslice values are populated first followed by EUs
> to follow an order.
> 

Okay. My idea was to order them based on where value comes from (is it computed here or 
simply read with INTEL_INFO).

> > +		/* 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");
> > @@ -4963,6 +4988,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);
> >   	}
> > diff --git a/drivers/gpu/drm/i915/i915_dma.c
> > b/drivers/gpu/drm/i915/i915_dma.c index ab37d11..2d52b1e 100644
> > --- a/drivers/gpu/drm/i915/i915_dma.c
> > +++ b/drivers/gpu/drm/i915/i915_dma.c
> > @@ -705,6 +705,93 @@ 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;
> I only see max of 2 slices for bdw in spec.
> 

Register values assume that there can be 3 slices (slice 0,1 and 2) and that’s why
I used 3 here as max slices count.

> > +	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));
> > +
> 
> GEN9_EU_DISABLE(slice) is already available, since the register addresses are
> same maybe it can be reused after renaming it to GEN8 instead of creating new
> definitions? ofcourse shift/mask are different.

I wouldn't use renaming of register from other generation. Since contents of this register 
are read in different way I treated these as different registers and that’s why I choose
to create new define without any references to GEN9 register. However, if the renaming 
(or even using existing define) is preferred approach I will modify the patch.

> 
> Indentation is off, in general please use () to force indentation.
> first two statements can fit in single line.
> 
> regards
> Arun
> 

Thank you for questions and style suggestions. I will reformat the lines before submitting 
updated patch.

---
Łukasz Daniluk

> > +
> > +	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 subslice(s) has(have) 7 EUs. we
> > +			 * can tune the hash used to spread work among
> > +			 * subslices if they are unbalanced.
> > +			 */
> > +			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.
> >    *
> > @@ -775,6 +862,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);
> >
> > diff --git a/drivers/gpu/drm/i915/i915_reg.h
> > b/drivers/gpu/drm/i915/i915_reg.h index be87e3b..37f658f 100644
> > --- a/drivers/gpu/drm/i915/i915_reg.h
> > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > @@ -1841,11 +1841,26 @@ 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_F2_SS_DIS_SHIFT		20
> > +#define GEN9_F2_SS_DIS_MASK		(0xf <<
> GEN9_F2_SS_DIS_SHIFT)
> >
> >   #define GEN9_EU_DISABLE(slice)		(0x9134 + (slice)*0x4)
> >
> > @@ -6822,6 +6837,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)
> >

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2] drm/i915/bdw: Check for slice, subslice and EU count for BDW
  2015-09-08 12:53     ` Daniluk, Lukasz
@ 2015-09-08 15:15       ` Arun Siluvery
  0 siblings, 0 replies; 13+ messages in thread
From: Arun Siluvery @ 2015-09-08 15:15 UTC (permalink / raw)
  To: Daniluk, Lukasz, intel-gfx@lists.freedesktop.org

On 08/09/2015 13:53, Daniluk, Lukasz wrote:
>> -----Original Message-----
>> From: Arun Siluvery [mailto:arun.siluvery@linux.intel.com]
>> Sent: Wednesday, September 2, 2015 17:08
>> To: Daniluk, Lukasz; intel-gfx@lists.freedesktop.org
>> Subject: Re: [Intel-gfx] [PATCH v2] drm/i915/bdw: Check for slice, subslice and
>> EU count for BDW
>>
>> On 02/09/2015 16:47, Łukasz Daniluk wrote:
>>> 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
>>>
>>> Cc: Jeff Mcgee <jeff.mcgee@intel.com>
>>> Signed-off-by: Łukasz Daniluk <lukasz.daniluk@intel.com>
>>> ---
>>>    drivers/gpu/drm/i915/i915_debugfs.c | 29 +++++++++++-
>>>    drivers/gpu/drm/i915/i915_dma.c     | 89
>> +++++++++++++++++++++++++++++++++++++
>>>    drivers/gpu/drm/i915/i915_reg.h     | 22 ++++++++-
>>>    3 files changed, 137 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c
>>> b/drivers/gpu/drm/i915/i915_debugfs.c
>>> index 23a69307..e8a62ef 100644
>>> --- a/drivers/gpu/drm/i915/i915_debugfs.c
>>> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
>>> @@ -4932,13 +4932,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);
>> I don't see this register (0x138064 as defined below) in bdw spec.
>>
>
> Yes, this register isn't listed in spec. I am unsure when the full spec for this register
> will be published.
>
>>> +
>>> +	stat->slice_total =
>>> +		hweight32(slice_info & GEN8_LSLICESTAT_MASK);
>>
>> why not in a single line, seems to fit under 80 chars.
>>
>
> I was using longer define name and didn't recheck if this line fits under 80. Thanks for catch.
>
>>> +
>>> +	if (stat->slice_total)
>>> +	{
>>> +		stat->subslice_per_slice = INTEL_INFO(dev)->subslice_per_slice;
>>> +		stat->eu_per_subslice = INTEL_INFO(dev)->eu_per_subslice;
>>> +		stat->subslice_total = stat->slice_total * stat-
>>> subslice_per_slice;
>>> +		stat->eu_total = stat->eu_per_subslice * stat->subslice_total;
>>> +
>> Please reorder such that all subslice values are populated first followed by EUs
>> to follow an order.
>>
>
> Okay. My idea was to order them based on where value comes from (is it computed here or
> simply read with INTEL_INFO).
>
>>> +		/* 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");
>>> @@ -4963,6 +4988,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);
>>>    	}
>>> diff --git a/drivers/gpu/drm/i915/i915_dma.c
>>> b/drivers/gpu/drm/i915/i915_dma.c index ab37d11..2d52b1e 100644
>>> --- a/drivers/gpu/drm/i915/i915_dma.c
>>> +++ b/drivers/gpu/drm/i915/i915_dma.c
>>> @@ -705,6 +705,93 @@ 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;
>> I only see max of 2 slices for bdw in spec.
>>
>
> Register values assume that there can be 3 slices (slice 0,1 and 2) and that’s why
> I used 3 here as max slices count.
>
>>> +	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));
>>> +
>>
>> GEN9_EU_DISABLE(slice) is already available, since the register addresses are
>> same maybe it can be reused after renaming it to GEN8 instead of creating new
>> definitions? ofcourse shift/mask are different.
>
> I wouldn't use renaming of register from other generation. Since contents of this register
> are read in different way I treated these as different registers and that’s why I choose
> to create new define without any references to GEN9 register. However, if the renaming
> (or even using existing define) is preferred approach I will modify the patch.

Normally we create a new define for newer Gen if the existing one cannot 
be reused, in this case it is the opposite, I am not sure what is best 
way to handle this, better to check with Daniel.

regards
Arun

>
>>
>> Indentation is off, in general please use () to force indentation.
>> first two statements can fit in single line.
>>
>> regards
>> Arun
>>
>
> Thank you for questions and style suggestions. I will reformat the lines before submitting
> updated patch.
>
> ---
> Łukasz Daniluk
>
>>> +
>>> +	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 subslice(s) has(have) 7 EUs. we
>>> +			 * can tune the hash used to spread work among
>>> +			 * subslices if they are unbalanced.
>>> +			 */
>>> +			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.
>>>     *
>>> @@ -775,6 +862,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);
>>>
>>> diff --git a/drivers/gpu/drm/i915/i915_reg.h
>>> b/drivers/gpu/drm/i915/i915_reg.h index be87e3b..37f658f 100644
>>> --- a/drivers/gpu/drm/i915/i915_reg.h
>>> +++ b/drivers/gpu/drm/i915/i915_reg.h
>>> @@ -1841,11 +1841,26 @@ 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_F2_SS_DIS_SHIFT		20
>>> +#define GEN9_F2_SS_DIS_MASK		(0xf <<
>> GEN9_F2_SS_DIS_SHIFT)
>>>
>>>    #define GEN9_EU_DISABLE(slice)		(0x9134 + (slice)*0x4)
>>>
>>> @@ -6822,6 +6837,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)
>>>
>

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v3] drm/i915/bdw: Check for slice, subslice and EU count for BDW
  2015-09-02 15:47 ` [PATCH v2] " Łukasz Daniluk
  2015-09-02 14:03   ` Chris Wilson
  2015-09-02 15:08   ` Arun Siluvery
@ 2015-09-17 11:51   ` Łukasz Daniluk
  2015-09-17 14:40     ` Jeff McGee
  2015-09-25  9:54     ` [PATCH v4] " Łukasz Daniluk
  2 siblings, 2 replies; 13+ messages in thread
From: Łukasz Daniluk @ 2015-09-17 11:51 UTC (permalink / raw)
  To: intel-gfx

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

Cc: Jeff Mcgee <jeff.mcgee@intel.com>
Cc: Arun Siluvery <arun.siluvery@linux.intel.com>
Signed-off-by: Łukasz Daniluk <lukasz.daniluk@intel.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c | 29 +++++++++++++-
 drivers/gpu/drm/i915/i915_dma.c     | 80 +++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_reg.h     | 22 +++++++++-
 3 files changed, 128 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 72ae347..d0f784d 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -5037,13 +5037,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");
@@ -5068,6 +5093,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);
 	}
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 066a0ef..6ec3ed6 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -713,6 +713,84 @@ 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 subslice(s) has(have) 7 EUs. we
+			 * can tune the hash used to spread work among
+			 * subslices if they are unbalanced.
+			 */
+			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.
  *
@@ -783,6 +861,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);
 
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 67bf205..da84488 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -1876,11 +1876,26 @@ 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_F2_SS_DIS_SHIFT		20
+#define GEN9_F2_SS_DIS_MASK		(0xf << GEN9_F2_SS_DIS_SHIFT)
 
 #define GEN9_EU_DISABLE(slice)		(0x9134 + (slice)*0x4)
 
@@ -6867,6 +6882,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)
-- 
Lukasz Daniluk

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH v3] drm/i915/bdw: Check for slice, subslice and EU count for BDW
  2015-09-17 11:51   ` [PATCH v3] " Łukasz Daniluk
@ 2015-09-17 14:40     ` Jeff McGee
  2015-09-25  9:54     ` [PATCH v4] " Łukasz Daniluk
  1 sibling, 0 replies; 13+ messages in thread
From: Jeff McGee @ 2015-09-17 14:40 UTC (permalink / raw)
  To: Łukasz Daniluk; +Cc: intel-gfx

On Thu, Sep 17, 2015 at 01:51:58PM +0200, Łukasz Daniluk wrote:
> 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
> 
> Cc: Jeff Mcgee <jeff.mcgee@intel.com>
> Cc: Arun Siluvery <arun.siluvery@linux.intel.com>
> Signed-off-by: Łukasz Daniluk <lukasz.daniluk@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_debugfs.c | 29 +++++++++++++-
>  drivers/gpu/drm/i915/i915_dma.c     | 80 +++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/i915_reg.h     | 22 +++++++++-
>  3 files changed, 128 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> index 72ae347..d0f784d 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -5037,13 +5037,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");
> @@ -5068,6 +5093,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);
>  	}
> diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
> index 066a0ef..6ec3ed6 100644
> --- a/drivers/gpu/drm/i915/i915_dma.c
> +++ b/drivers/gpu/drm/i915/i915_dma.c
> @@ -713,6 +713,84 @@ 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 subslice(s) has(have) 7 EUs. we
> +			 * can tune the hash used to spread work among
> +			 * subslices if they are unbalanced.
> +			 */
Should probably remove the part of the above comment which refers to hash
tuning since this doesn't seem to apply for BDW, only SKL.
> +			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.
>   *
> @@ -783,6 +861,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);
>  
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 67bf205..da84488 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -1876,11 +1876,26 @@ 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)
I think it is helpful to keep the above two macros here rather than move
them down below the GEN8_EU_DISABLEX definitions. Having them here makes it
more clear that they are Gen9-specific field definitions for the GEN8_FUSE2
register.

> +#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_F2_SS_DIS_SHIFT		20
> +#define GEN9_F2_SS_DIS_MASK		(0xf << GEN9_F2_SS_DIS_SHIFT)
>  
>  #define GEN9_EU_DISABLE(slice)		(0x9134 + (slice)*0x4)
>  
> @@ -6867,6 +6882,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)
> -- 
> Lukasz Daniluk
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v4] drm/i915/bdw: Check for slice, subslice and EU count for BDW
  2015-09-17 11:51   ` [PATCH v3] " Łukasz Daniluk
  2015-09-17 14:40     ` Jeff McGee
@ 2015-09-25  9:54     ` Łukasz Daniluk
  2015-09-29 19:58       ` Jeff McGee
  1 sibling, 1 reply; 13+ messages in thread
From: Łukasz Daniluk @ 2015-09-25  9:54 UTC (permalink / raw)
  To: intel-gfx

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>
---
 drivers/gpu/drm/i915/i915_debugfs.c | 29 +++++++++++++-
 drivers/gpu/drm/i915/i915_dma.c     | 78 +++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_reg.h     | 18 +++++++++
 3 files changed, 124 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 72ae347..d0f784d 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -5037,13 +5037,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");
@@ -5068,6 +5093,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);
 	}
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 066a0ef..72e2bbd 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -713,6 +713,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.
  *
@@ -783,6 +859,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);
 
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 67bf205..10761a3 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -1876,12 +1876,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
@@ -6867,6 +6882,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)
-- 
Lukasz Daniluk

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH v4] drm/i915/bdw: Check for slice, subslice and EU count for BDW
  2015-09-25  9:54     ` [PATCH v4] " Łukasz Daniluk
@ 2015-09-29 19:58       ` Jeff McGee
  0 siblings, 0 replies; 13+ messages in thread
From: Jeff McGee @ 2015-09-29 19:58 UTC (permalink / raw)
  To: Łukasz Daniluk; +Cc: intel-gfx

On Fri, Sep 25, 2015 at 11:54:58AM +0200, Łukasz Daniluk wrote:
> 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>
> ---
>  drivers/gpu/drm/i915/i915_debugfs.c | 29 +++++++++++++-
>  drivers/gpu/drm/i915/i915_dma.c     | 78 +++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/i915_reg.h     | 18 +++++++++
>  3 files changed, 124 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> index 72ae347..d0f784d 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -5037,13 +5037,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");
> @@ -5068,6 +5093,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);
>  	}
> diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
> index 066a0ef..72e2bbd 100644
> --- a/drivers/gpu/drm/i915/i915_dma.c
> +++ b/drivers/gpu/drm/i915/i915_dma.c
> @@ -713,6 +713,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.
>   *
> @@ -783,6 +859,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);
>  
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 67bf205..10761a3 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -1876,12 +1876,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
> @@ -6867,6 +6882,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)
> -- 
> Lukasz Daniluk
> 

Reviewed-by: Jeff McGee <jeff.mcgee@intel.com>
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2015-09-29 19:53 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-08-13 12:38 [PATCH] drm/i915/bdw: Check for slice, subslice and EU count for BDW Łukasz Daniluk
2015-08-13 21:34 ` Bish, Jim
2015-08-14  0:11 ` Jeff McGee
2015-09-02 15:47 ` [PATCH v2] " Łukasz Daniluk
2015-09-02 14:03   ` Chris Wilson
2015-09-08 11:29     ` Daniluk, Lukasz
2015-09-02 15:08   ` Arun Siluvery
2015-09-08 12:53     ` Daniluk, Lukasz
2015-09-08 15:15       ` Arun Siluvery
2015-09-17 11:51   ` [PATCH v3] " Łukasz Daniluk
2015-09-17 14:40     ` Jeff McGee
2015-09-25  9:54     ` [PATCH v4] " Łukasz Daniluk
2015-09-29 19:58       ` Jeff McGee

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox