All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 0/4] drm/i915: Expose more GPU properties through sysfs
@ 2017-11-22 12:30 Lionel Landwerlin
  2017-11-22 12:30 ` [PATCH v4 1/4] drm/i915: store all subslice masks Lionel Landwerlin
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Lionel Landwerlin @ 2017-11-22 12:30 UTC (permalink / raw)
  To: intel-gfx

Hi,

Another updates with some layout changes in /sys.

Cheers,

Lionel Landwerlin (4):
  drm/i915: store all subslice masks
  drm/i915/debugfs: reuse max slice/subslices already stored in sseu
  drm/i915: expose engine availability through sysfs
  drm/i915: expose EU topology through sysfs

 drivers/gpu/drm/i915/i915_debugfs.c      |  50 ++--
 drivers/gpu/drm/i915/i915_drv.c          |   2 +-
 drivers/gpu/drm/i915/i915_drv.h          |  56 ++++-
 drivers/gpu/drm/i915/i915_sysfs.c        | 386 +++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_device_info.c | 169 ++++++++++----
 drivers/gpu/drm/i915/intel_engine_cs.c   |  12 +
 drivers/gpu/drm/i915/intel_lrc.c         |   2 +-
 drivers/gpu/drm/i915/intel_ringbuffer.h  |   6 +-
 8 files changed, 606 insertions(+), 77 deletions(-)

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

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

* [PATCH v4 1/4] drm/i915: store all subslice masks
  2017-11-22 12:30 [PATCH v4 0/4] drm/i915: Expose more GPU properties through sysfs Lionel Landwerlin
@ 2017-11-22 12:30 ` Lionel Landwerlin
  2017-11-22 12:30 ` [PATCH v4 2/4] drm/i915/debugfs: reuse max slice/subslices already stored in sseu Lionel Landwerlin
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Lionel Landwerlin @ 2017-11-22 12:30 UTC (permalink / raw)
  To: intel-gfx

Up to now, subslice mask was assumed to be uniform across slices. But
starting with Cannonlake, slices can be asymetric (for example slice0
has different number of subslices as slice1+). This change stores all
subslices masks for all slices rather than having a single mask that
applies to all slices.

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c      |  24 +++--
 drivers/gpu/drm/i915/i915_drv.c          |   2 +-
 drivers/gpu/drm/i915/i915_drv.h          |  23 ++++-
 drivers/gpu/drm/i915/intel_device_info.c | 169 ++++++++++++++++++++++---------
 drivers/gpu/drm/i915/intel_lrc.c         |   2 +-
 drivers/gpu/drm/i915/intel_ringbuffer.h  |   2 +-
 6 files changed, 161 insertions(+), 61 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 28294470ae31..ef091a2a6b12 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -4340,7 +4340,7 @@ static void cherryview_sseu_device_status(struct drm_i915_private *dev_priv,
 			continue;
 
 		sseu->slice_mask = BIT(0);
-		sseu->subslice_mask |= BIT(ss);
+		sseu->subslices_mask[0] |= BIT(ss);
 		eu_cnt = ((sig1[ss] & CHV_EU08_PG_ENABLE) ? 0 : 2) +
 			 ((sig1[ss] & CHV_EU19_PG_ENABLE) ? 0 : 2) +
 			 ((sig1[ss] & CHV_EU210_PG_ENABLE) ? 0 : 2) +
@@ -4387,7 +4387,7 @@ static void gen10_sseu_device_status(struct drm_i915_private *dev_priv,
 			continue;
 
 		sseu->slice_mask |= BIT(s);
-		sseu->subslice_mask = info->sseu.subslice_mask;
+		sseu->subslices_mask[s] = info->sseu.subslices_mask[s];
 
 		for (ss = 0; ss < ss_max; ss++) {
 			unsigned int eu_cnt;
@@ -4442,8 +4442,8 @@ static void gen9_sseu_device_status(struct drm_i915_private *dev_priv,
 		sseu->slice_mask |= BIT(s);
 
 		if (IS_GEN9_BC(dev_priv))
-			sseu->subslice_mask =
-				INTEL_INFO(dev_priv)->sseu.subslice_mask;
+			sseu->subslices_mask[s] =
+				INTEL_INFO(dev_priv)->sseu.subslices_mask[s];
 
 		for (ss = 0; ss < ss_max; ss++) {
 			unsigned int eu_cnt;
@@ -4453,7 +4453,7 @@ static void gen9_sseu_device_status(struct drm_i915_private *dev_priv,
 					/* skip disabled subslice */
 					continue;
 
-				sseu->subslice_mask |= BIT(ss);
+				sseu->subslices_mask[s] |= BIT(ss);
 			}
 
 			eu_cnt = 2 * hweight32(eu_reg[2*s + ss/2] &
@@ -4475,9 +4475,12 @@ static void broadwell_sseu_device_status(struct drm_i915_private *dev_priv,
 	sseu->slice_mask = slice_info & GEN8_LSLICESTAT_MASK;
 
 	if (sseu->slice_mask) {
-		sseu->subslice_mask = INTEL_INFO(dev_priv)->sseu.subslice_mask;
 		sseu->eu_per_subslice =
 				INTEL_INFO(dev_priv)->sseu.eu_per_subslice;
+		for (s = 0; s < fls(sseu->slice_mask); s++) {
+			sseu->subslices_mask[s] =
+				INTEL_INFO(dev_priv)->sseu.subslices_mask[s];
+		}
 		sseu->eu_total = sseu->eu_per_subslice *
 				 sseu_subslice_total(sseu);
 
@@ -4496,6 +4499,7 @@ static void i915_print_sseu_info(struct seq_file *m, bool is_available_info,
 {
 	struct drm_i915_private *dev_priv = node_to_i915(m->private);
 	const char *type = is_available_info ? "Available" : "Enabled";
+	int s;
 
 	seq_printf(m, "  %s Slice Mask: %04x\n", type,
 		   sseu->slice_mask);
@@ -4503,10 +4507,10 @@ static void i915_print_sseu_info(struct seq_file *m, bool is_available_info,
 		   hweight8(sseu->slice_mask));
 	seq_printf(m, "  %s Subslice Total: %u\n", type,
 		   sseu_subslice_total(sseu));
-	seq_printf(m, "  %s Subslice Mask: %04x\n", type,
-		   sseu->subslice_mask);
-	seq_printf(m, "  %s Subslice Per Slice: %u\n", type,
-		   hweight8(sseu->subslice_mask));
+	for (s = 0; s < fls(sseu->slice_mask); s++) {
+		seq_printf(m, "  %s Slice%i Subslice Mask: %04x\n", type,
+			   s, sseu->subslices_mask[s]);
+	}
 	seq_printf(m, "  %s EU Total: %u\n", type,
 		   sseu->eu_total);
 	seq_printf(m, "  %s EU Per Subslice: %u\n", type,
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 0793a27e2b95..175327862714 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -414,7 +414,7 @@ static int i915_getparam(struct drm_device *dev, void *data,
 			return -ENODEV;
 		break;
 	case I915_PARAM_SUBSLICE_MASK:
-		value = INTEL_INFO(dev_priv)->sseu.subslice_mask;
+		value = INTEL_INFO(dev_priv)->sseu.subslices_mask[0];
 		if (!value)
 			return -ENODEV;
 		break;
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index d575a56fc100..99981c5d3beb 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -801,9 +801,12 @@ struct intel_csr {
 	func(supports_tv); \
 	func(has_ipc);
 
+#define GEN_MAX_SLICES		(6) /* CNL upper bound */
+#define GEN_MAX_SUBSLICES	(7)
+
 struct sseu_dev_info {
 	u8 slice_mask;
-	u8 subslice_mask;
+	u8 subslices_mask[GEN_MAX_SLICES];
 	u8 eu_total;
 	u8 eu_per_subslice;
 	u8 min_eu_in_pool;
@@ -812,11 +815,27 @@ struct sseu_dev_info {
 	u8 has_slice_pg:1;
 	u8 has_subslice_pg:1;
 	u8 has_eu_pg:1;
+
+	/* Topology fields */
+	u8 max_slices;
+	u8 max_subslices;
+	u8 max_eus_per_subslice;
+
+	/* We don't have more than 8 eus per subslice at the moment and as we
+	 * store eus enabled using bits, no need to multiply by eus per
+	 * subslice.
+	 */
+	u8 eu_mask[GEN_MAX_SLICES * GEN_MAX_SUBSLICES];
 };
 
 static inline unsigned int sseu_subslice_total(const struct sseu_dev_info *sseu)
 {
-	return hweight8(sseu->slice_mask) * hweight8(sseu->subslice_mask);
+	unsigned s, total = 0;
+
+	for (s = 0; s < ARRAY_SIZE(sseu->subslices_mask); s++)
+		total += hweight8(sseu->subslices_mask[s]);
+
+	return total;
 }
 
 /* Keep in gen based order, and chronological order within a gen */
diff --git a/drivers/gpu/drm/i915/intel_device_info.c b/drivers/gpu/drm/i915/intel_device_info.c
index 405d70124a46..11ceb43ddcee 100644
--- a/drivers/gpu/drm/i915/intel_device_info.c
+++ b/drivers/gpu/drm/i915/intel_device_info.c
@@ -82,22 +82,74 @@ void intel_device_info_dump(struct drm_i915_private *dev_priv)
 #undef PRINT_FLAG
 }
 
+static u8 compute_eu_total(const struct sseu_dev_info *sseu)
+{
+	u8 i, total = 0;
+
+	for (i = 0; i < ARRAY_SIZE(sseu->eu_mask); i++)
+		total += hweight8(sseu->eu_mask[i]);
+
+	return total;
+}
+
 static void gen10_sseu_info_init(struct drm_i915_private *dev_priv)
 {
 	struct sseu_dev_info *sseu = &mkwrite_device_info(dev_priv)->sseu;
 	const u32 fuse2 = I915_READ(GEN8_FUSE2);
+	int s, ss, eu_mask = 0xff;
+	u32 subslice_mask, eu_en;
 
 	sseu->slice_mask = (fuse2 & GEN10_F2_S_ENA_MASK) >>
 			    GEN10_F2_S_ENA_SHIFT;
-	sseu->subslice_mask = (1 << 4) - 1;
-	sseu->subslice_mask &= ~((fuse2 & GEN10_F2_SS_DIS_MASK) >>
-				 GEN10_F2_SS_DIS_SHIFT);
+	sseu->max_slices = 6;
+	sseu->max_subslices = 4;
+	sseu->max_eus_per_subslice = 8;
+
+	subslice_mask = (1 << 4) - 1;
+	subslice_mask &= ~((fuse2 & GEN10_F2_SS_DIS_MASK) >>
+			   GEN10_F2_SS_DIS_SHIFT);
+
+	/* Slice0 can have up to 3 subslices, but there are only 2 in
+	 * slice1/2.
+	 */
+	sseu->subslices_mask[0] = subslice_mask;
+	for (s = 1; s < sseu->max_slices; s++)
+		sseu->subslices_mask[s] = subslice_mask & 0x3;
+
+	/* Slice0 */
+	eu_en = ~I915_READ(GEN8_EU_DISABLE0);
+	for (ss = 0; ss < sseu->max_subslices; ss++)
+		sseu->eu_mask[ss]     = (eu_en >> (8 * ss)) & eu_mask;
+	/* Slice1 */
+	sseu->eu_mask[sseu->max_subslices]         = (eu_en >> 24) & eu_mask;
+	eu_en = ~I915_READ(GEN8_EU_DISABLE1);
+	sseu->eu_mask[sseu->max_subslices + 1]     = eu_en & eu_mask;
+	/* Slice2 */
+	sseu->eu_mask[2 * sseu->max_subslices]     = (eu_en >> 8) & eu_mask;
+	sseu->eu_mask[2 * sseu->max_subslices + 1] = (eu_en >> 16) & eu_mask;
+	/* Slice3 */
+	sseu->eu_mask[3 * sseu->max_subslices]     = (eu_en >> 24) & eu_mask;
+	eu_en = ~I915_READ(GEN8_EU_DISABLE2);
+	sseu->eu_mask[3 * sseu->max_subslices + 1] = eu_en & eu_mask;
+	/* Slice4 */
+	sseu->eu_mask[4 * sseu->max_subslices]     = (eu_en >> 8) & eu_mask;
+	sseu->eu_mask[4 * sseu->max_subslices + 1] = (eu_en >> 16) & eu_mask;
+	/* Slice5 */
+	sseu->eu_mask[5 * sseu->max_subslices]     = (eu_en >> 24) & eu_mask;
+	eu_en = ~I915_READ(GEN10_EU_DISABLE3);
+	sseu->eu_mask[5 * sseu->max_subslices + 1] = eu_en & eu_mask;
+
+	/* Do a second pass where we marked the subslices disabled if all
+	 * their eus are off.
+	 */
+	for (s = 0; s < sseu->max_slices; s++) {
+		for (ss = 0; ss < sseu->max_subslices; ss++) {
+			if (sseu->eu_mask[s * sseu->max_subslices + ss] == 0)
+				sseu->subslices_mask[s] &= ~BIT(ss);
+		}
+	}
 
-	sseu->eu_total = hweight32(~I915_READ(GEN8_EU_DISABLE0));
-	sseu->eu_total += hweight32(~I915_READ(GEN8_EU_DISABLE1));
-	sseu->eu_total += hweight32(~I915_READ(GEN8_EU_DISABLE2));
-	sseu->eu_total += hweight8(~(I915_READ(GEN10_EU_DISABLE3) &
-				     GEN10_EU_DIS_SS_MASK));
+	sseu->eu_total = compute_eu_total(sseu);
 
 	/*
 	 * CNL is expected to always have a uniform distribution
@@ -118,26 +170,30 @@ static void gen10_sseu_info_init(struct drm_i915_private *dev_priv)
 static void cherryview_sseu_info_init(struct drm_i915_private *dev_priv)
 {
 	struct sseu_dev_info *sseu = &mkwrite_device_info(dev_priv)->sseu;
-	u32 fuse, eu_dis;
+	u32 fuse;
 
 	fuse = I915_READ(CHV_FUSE_GT);
 
 	sseu->slice_mask = BIT(0);
+	sseu->max_slices = 1;
+	sseu->max_subslices = 2;
+	sseu->max_eus_per_subslice = 8;
 
 	if (!(fuse & CHV_FGT_DISABLE_SS0)) {
-		sseu->subslice_mask |= BIT(0);
-		eu_dis = fuse & (CHV_FGT_EU_DIS_SS0_R0_MASK |
-				 CHV_FGT_EU_DIS_SS0_R1_MASK);
-		sseu->eu_total += 8 - hweight32(eu_dis);
+		sseu->subslices_mask[0] |= BIT(0);
+		sseu->eu_mask[0] = (fuse & CHV_FGT_EU_DIS_SS0_R0_MASK) >> CHV_FGT_EU_DIS_SS0_R0_SHIFT;
+		sseu->eu_mask[0] |= ((fuse & CHV_FGT_EU_DIS_SS0_R1_MASK) >> CHV_FGT_EU_DIS_SS0_R1_SHIFT) << 4;
+		sseu->subslices_mask[0] = 1;
 	}
 
 	if (!(fuse & CHV_FGT_DISABLE_SS1)) {
-		sseu->subslice_mask |= BIT(1);
-		eu_dis = fuse & (CHV_FGT_EU_DIS_SS1_R0_MASK |
-				 CHV_FGT_EU_DIS_SS1_R1_MASK);
-		sseu->eu_total += 8 - hweight32(eu_dis);
+		sseu->subslices_mask[0] |= BIT(1);
+		sseu->eu_mask[1] = (fuse & CHV_FGT_EU_DIS_SS1_R0_MASK) >> CHV_FGT_EU_DIS_SS0_R0_SHIFT;
+		sseu->eu_mask[2] |= ((fuse & CHV_FGT_EU_DIS_SS1_R1_MASK) >> CHV_FGT_EU_DIS_SS0_R1_SHIFT) << 4;
 	}
 
+	sseu->eu_total = compute_eu_total(sseu);
+
 	/*
 	 * CHV expected to always have a uniform distribution of EU
 	 * across subslices.
@@ -159,41 +215,50 @@ static void gen9_sseu_info_init(struct drm_i915_private *dev_priv)
 {
 	struct intel_device_info *info = mkwrite_device_info(dev_priv);
 	struct sseu_dev_info *sseu = &info->sseu;
-	int s_max = 3, ss_max = 4, eu_max = 8;
 	int s, ss;
-	u32 fuse2, eu_disable;
+	u32 fuse2, eu_disable, subslice_mask;
 	u8 eu_mask = 0xff;
 
 	fuse2 = I915_READ(GEN8_FUSE2);
 	sseu->slice_mask = (fuse2 & GEN8_F2_S_ENA_MASK) >> GEN8_F2_S_ENA_SHIFT;
 
+	/* BXT has a single slice and at most 3 subslices. */
+	sseu->max_slices = IS_GEN9_LP(dev_priv) ? 1 : 3;
+	sseu->max_subslices = IS_GEN9_LP(dev_priv) ? 3 : 4;
+	sseu->max_eus_per_subslice = 8;
+
 	/*
 	 * The subslice disable field is global, i.e. it applies
 	 * to each of the enabled slices.
 	*/
-	sseu->subslice_mask = (1 << ss_max) - 1;
-	sseu->subslice_mask &= ~((fuse2 & GEN9_F2_SS_DIS_MASK) >>
-				 GEN9_F2_SS_DIS_SHIFT);
+	subslice_mask = (1 << sseu->max_subslices) - 1;
+	subslice_mask &= ~((fuse2 & GEN9_F2_SS_DIS_MASK) >>
+			   GEN9_F2_SS_DIS_SHIFT);
 
 	/*
 	 * Iterate through enabled slices and subslices to
 	 * count the total enabled EU.
 	*/
-	for (s = 0; s < s_max; s++) {
+	for (s = 0; s < sseu->max_slices; s++) {
 		if (!(sseu->slice_mask & BIT(s)))
 			/* skip disabled slice */
 			continue;
 
+		sseu->subslices_mask[s] = subslice_mask;
+
 		eu_disable = I915_READ(GEN9_EU_DISABLE(s));
-		for (ss = 0; ss < ss_max; ss++) {
+		for (ss = 0; ss < sseu->max_subslices; ss++) {
 			int eu_per_ss;
 
-			if (!(sseu->subslice_mask & BIT(ss)))
+			if (!(sseu->subslices_mask[s] & BIT(ss)))
 				/* skip disabled subslice */
 				continue;
 
-			eu_per_ss = eu_max - hweight8((eu_disable >> (ss*8)) &
-						      eu_mask);
+			sseu->eu_mask[ss + s * sseu->max_subslices] =
+				~((eu_disable >> (ss*8)) & eu_mask);
+
+			eu_per_ss = sseu->max_eus_per_subslice -
+				hweight8((eu_disable >> (ss*8)) & eu_mask);
 
 			/*
 			 * Record which subslice(s) has(have) 7 EUs. we
@@ -202,11 +267,11 @@ static void gen9_sseu_info_init(struct drm_i915_private *dev_priv)
 			 */
 			if (eu_per_ss == 7)
 				sseu->subslice_7eu[s] |= BIT(ss);
-
-			sseu->eu_total += eu_per_ss;
 		}
 	}
 
+	sseu->eu_total = compute_eu_total(sseu);
+
 	/*
 	 * SKL is expected to always have a uniform distribution
 	 * of EU across subslices with the exception that any one
@@ -232,8 +297,8 @@ static void gen9_sseu_info_init(struct drm_i915_private *dev_priv)
 	sseu->has_eu_pg = sseu->eu_per_subslice > 2;
 
 	if (IS_GEN9_LP(dev_priv)) {
-#define IS_SS_DISABLED(ss)	(!(sseu->subslice_mask & BIT(ss)))
-		info->has_pooled_eu = hweight8(sseu->subslice_mask) == 3;
+#define IS_SS_DISABLED(ss)	(!(sseu->subslices_mask[0] & BIT(ss)))
+		info->has_pooled_eu = hweight8(sseu->subslices_mask[0]) == 3;
 
 		sseu->min_eu_in_pool = 0;
 		if (info->has_pooled_eu) {
@@ -251,19 +316,22 @@ static void gen9_sseu_info_init(struct drm_i915_private *dev_priv)
 static void broadwell_sseu_info_init(struct drm_i915_private *dev_priv)
 {
 	struct sseu_dev_info *sseu = &mkwrite_device_info(dev_priv)->sseu;
-	const int s_max = 3, ss_max = 3, eu_max = 8;
 	int s, ss;
-	u32 fuse2, eu_disable[3]; /* s_max */
+	u32 fuse2, subslice_mask, eu_disable[3]; /* s_max */
 
 	fuse2 = I915_READ(GEN8_FUSE2);
 	sseu->slice_mask = (fuse2 & GEN8_F2_S_ENA_MASK) >> GEN8_F2_S_ENA_SHIFT;
+	sseu->max_slices = 3;
+	sseu->max_subslices = 3;
+	sseu->max_eus_per_subslice = 8;
+
 	/*
 	 * The subslice disable field is global, i.e. it applies
 	 * to each of the enabled slices.
 	 */
-	sseu->subslice_mask = GENMASK(ss_max - 1, 0);
-	sseu->subslice_mask &= ~((fuse2 & GEN8_F2_SS_DIS_MASK) >>
-				 GEN8_F2_SS_DIS_SHIFT);
+	subslice_mask = GENMASK(sseu->max_subslices - 1, 0);
+	subslice_mask &= ~((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) |
@@ -277,30 +345,36 @@ static void broadwell_sseu_info_init(struct drm_i915_private *dev_priv)
 	 * Iterate through enabled slices and subslices to
 	 * count the total enabled EU.
 	 */
-	for (s = 0; s < s_max; s++) {
+	for (s = 0; s < sseu->max_slices; s++) {
 		if (!(sseu->slice_mask & BIT(s)))
 			/* skip disabled slice */
 			continue;
 
-		for (ss = 0; ss < ss_max; ss++) {
+		sseu->subslices_mask[s] = subslice_mask;
+
+		for (ss = 0; ss < sseu->max_subslices; ss++) {
 			u32 n_disabled;
 
-			if (!(sseu->subslice_mask & BIT(ss)))
+			if (!(sseu->subslices_mask[ss] & BIT(ss)))
 				/* skip disabled subslice */
 				continue;
 
-			n_disabled = hweight8(eu_disable[s] >> (ss * eu_max));
+			sseu->eu_mask[ss + s * sseu->max_subslices] =
+				~(eu_disable[s] >>
+				  (ss * sseu->max_eus_per_subslice));
+			n_disabled = hweight8(eu_disable[s] >>
+					      (ss * sseu->max_eus_per_subslice));
 
 			/*
 			 * Record which subslices have 7 EUs.
 			 */
-			if (eu_max - n_disabled == 7)
+			if (sseu->max_eus_per_subslice - n_disabled == 7)
 				sseu->subslice_7eu[s] |= 1 << ss;
-
-			sseu->eu_total += eu_max - n_disabled;
 		}
 	}
 
+	sseu->eu_total = compute_eu_total(sseu);
+
 	/*
 	 * 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
@@ -437,6 +511,7 @@ void intel_device_info_runtime_init(struct drm_i915_private *dev_priv)
 {
 	struct intel_device_info *info = mkwrite_device_info(dev_priv);
 	enum pipe pipe;
+	int s;
 
 	if (INTEL_GEN(dev_priv) >= 10) {
 		for_each_pipe(dev_priv, pipe)
@@ -548,9 +623,11 @@ void intel_device_info_runtime_init(struct drm_i915_private *dev_priv)
 	DRM_DEBUG_DRIVER("slice total: %u\n", hweight8(info->sseu.slice_mask));
 	DRM_DEBUG_DRIVER("subslice total: %u\n",
 			 sseu_subslice_total(&info->sseu));
-	DRM_DEBUG_DRIVER("subslice mask %04x\n", info->sseu.subslice_mask);
-	DRM_DEBUG_DRIVER("subslice per slice: %u\n",
-			 hweight8(info->sseu.subslice_mask));
+	for (s = 0; s < ARRAY_SIZE(info->sseu.subslices_mask); s++) {
+		DRM_DEBUG_DRIVER("subslice mask %04x\n", info->sseu.subslices_mask[s]);
+		DRM_DEBUG_DRIVER("subslice per slice: %u\n",
+				 hweight8(info->sseu.subslices_mask[s]));
+	}
 	DRM_DEBUG_DRIVER("EU total: %u\n", info->sseu.eu_total);
 	DRM_DEBUG_DRIVER("EU per subslice: %u\n", info->sseu.eu_per_subslice);
 	DRM_DEBUG_DRIVER("has slice power gating: %s\n",
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 570864583e28..1f555d3e056c 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -2071,7 +2071,7 @@ make_rpcs(struct drm_i915_private *dev_priv)
 
 	if (INTEL_INFO(dev_priv)->sseu.has_subslice_pg) {
 		rpcs |= GEN8_RPCS_SS_CNT_ENABLE;
-		rpcs |= hweight8(INTEL_INFO(dev_priv)->sseu.subslice_mask) <<
+		rpcs |= hweight8(INTEL_INFO(dev_priv)->sseu.subslices_mask[0]) <<
 			GEN8_RPCS_SS_CNT_SHIFT;
 		rpcs |= GEN8_RPCS_ENABLE;
 	}
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 3bd30d011866..bee3bc36b93b 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -90,7 +90,7 @@ hangcheck_action_to_str(const enum intel_engine_hangcheck_action a)
 
 #define instdone_subslice_mask(dev_priv__) \
 	(INTEL_GEN(dev_priv__) == 7 ? \
-	 1 : INTEL_INFO(dev_priv__)->sseu.subslice_mask)
+	 1 : INTEL_INFO(dev_priv__)->sseu.subslices_mask[0])
 
 #define for_each_instdone_slice_subslice(dev_priv__, slice__, subslice__) \
 	for ((slice__) = 0, (subslice__) = 0; \
-- 
2.15.0

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

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

* [PATCH v4 2/4] drm/i915/debugfs: reuse max slice/subslices already stored in sseu
  2017-11-22 12:30 [PATCH v4 0/4] drm/i915: Expose more GPU properties through sysfs Lionel Landwerlin
  2017-11-22 12:30 ` [PATCH v4 1/4] drm/i915: store all subslice masks Lionel Landwerlin
@ 2017-11-22 12:30 ` Lionel Landwerlin
  2017-11-22 12:30 ` [PATCH v4 3/4] drm/i915: expose engine availability through sysfs Lionel Landwerlin
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Lionel Landwerlin @ 2017-11-22 12:30 UTC (permalink / raw)
  To: intel-gfx

Now that we have that information in topology fields, let's just reused it.

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c | 26 ++++++++++----------------
 1 file changed, 10 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index ef091a2a6b12..961c5969b223 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -4355,11 +4355,11 @@ static void gen10_sseu_device_status(struct drm_i915_private *dev_priv,
 				     struct sseu_dev_info *sseu)
 {
 	const struct intel_device_info *info = INTEL_INFO(dev_priv);
-	int s_max = 6, ss_max = 4;
 	int s, ss;
-	u32 s_reg[s_max], eu_reg[2 * s_max], eu_mask[2];
+	u32 s_reg[info->sseu.max_slices],
+		eu_reg[2 * info->sseu.max_subslices], eu_mask[2];
 
-	for (s = 0; s < s_max; s++) {
+	for (s = 0; s < info->sseu.max_slices; s++) {
 		/*
 		 * FIXME: Valid SS Mask respects the spec and read
 		 * only valid bits for those registers, excluding reserverd
@@ -4381,7 +4381,7 @@ static void gen10_sseu_device_status(struct drm_i915_private *dev_priv,
 		     GEN9_PGCTL_SSB_EU210_ACK |
 		     GEN9_PGCTL_SSB_EU311_ACK;
 
-	for (s = 0; s < s_max; s++) {
+	for (s = 0; s < info->sseu.max_slices; s++) {
 		if ((s_reg[s] & GEN9_PGCTL_SLICE_ACK) == 0)
 			/* skip disabled slice */
 			continue;
@@ -4389,7 +4389,7 @@ static void gen10_sseu_device_status(struct drm_i915_private *dev_priv,
 		sseu->slice_mask |= BIT(s);
 		sseu->subslices_mask[s] = info->sseu.subslices_mask[s];
 
-		for (ss = 0; ss < ss_max; ss++) {
+		for (ss = 0; ss < info->sseu.max_subslices; ss++) {
 			unsigned int eu_cnt;
 
 			if (!(s_reg[s] & (GEN9_PGCTL_SS_ACK(ss))))
@@ -4409,17 +4409,11 @@ static void gen10_sseu_device_status(struct drm_i915_private *dev_priv,
 static void gen9_sseu_device_status(struct drm_i915_private *dev_priv,
 				    struct sseu_dev_info *sseu)
 {
-	int s_max = 3, ss_max = 4;
+	const struct intel_device_info *info = INTEL_INFO(dev_priv);
 	int s, ss;
-	u32 s_reg[s_max], eu_reg[2*s_max], eu_mask[2];
-
-	/* BXT has a single slice and at most 3 subslices. */
-	if (IS_GEN9_LP(dev_priv)) {
-		s_max = 1;
-		ss_max = 3;
-	}
+	u32 s_reg[info->sseu.max_slices], eu_reg[2*info->sseu.max_subslices], eu_mask[2];
 
-	for (s = 0; s < s_max; s++) {
+	for (s = 0; s < info->sseu.max_slices; s++) {
 		s_reg[s] = I915_READ(GEN9_SLICE_PGCTL_ACK(s));
 		eu_reg[2*s] = I915_READ(GEN9_SS01_EU_PGCTL_ACK(s));
 		eu_reg[2*s + 1] = I915_READ(GEN9_SS23_EU_PGCTL_ACK(s));
@@ -4434,7 +4428,7 @@ static void gen9_sseu_device_status(struct drm_i915_private *dev_priv,
 		     GEN9_PGCTL_SSB_EU210_ACK |
 		     GEN9_PGCTL_SSB_EU311_ACK;
 
-	for (s = 0; s < s_max; s++) {
+	for (s = 0; s < info->sseu.max_slices; s++) {
 		if ((s_reg[s] & GEN9_PGCTL_SLICE_ACK) == 0)
 			/* skip disabled slice */
 			continue;
@@ -4445,7 +4439,7 @@ static void gen9_sseu_device_status(struct drm_i915_private *dev_priv,
 			sseu->subslices_mask[s] =
 				INTEL_INFO(dev_priv)->sseu.subslices_mask[s];
 
-		for (ss = 0; ss < ss_max; ss++) {
+		for (ss = 0; ss < info->sseu.max_subslices; ss++) {
 			unsigned int eu_cnt;
 
 			if (IS_GEN9_LP(dev_priv)) {
-- 
2.15.0

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

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

* [PATCH v4 3/4] drm/i915: expose engine availability through sysfs
  2017-11-22 12:30 [PATCH v4 0/4] drm/i915: Expose more GPU properties through sysfs Lionel Landwerlin
  2017-11-22 12:30 ` [PATCH v4 1/4] drm/i915: store all subslice masks Lionel Landwerlin
  2017-11-22 12:30 ` [PATCH v4 2/4] drm/i915/debugfs: reuse max slice/subslices already stored in sseu Lionel Landwerlin
@ 2017-11-22 12:30 ` Lionel Landwerlin
  2017-11-22 12:30 ` [PATCH v4 4/4] drm/i915: expose EU topology " Lionel Landwerlin
  2017-11-22 12:33 ` ✗ Fi.CI.BAT: failure for drm/i915: Expose more GPU properties through sysfs (rev4) Patchwork
  4 siblings, 0 replies; 6+ messages in thread
From: Lionel Landwerlin @ 2017-11-22 12:30 UTC (permalink / raw)
  To: intel-gfx

This enables userspace to discover the engines available on the GPU.
Here is the layout on a Skylake GT4:

/sys/devices/pci0000:00/0000:00:02.0/drm/card0/gt/
└── engines
    ├── bcs
    │   └── 0
    │       ├── capabilities
    │       ├── class
    │       ├── id
    │       └── instance
    ├── rcs
    │   └── 0
    │       ├── capabilities
    │       ├── class
    │       ├── id
    │       └── instance
    ├── vcs
    │   ├── 0
    │   │   ├── capabilities
    │   │   │   └── hevc
    │   │   ├── class
    │   │   ├── id
    │   │   └── instance
    │   └── 1
    │       ├── capabilities
    │       ├── class
    │       ├── id
    │       └── instance
    └── vecs
        └── 0
            ├── capabilities
            ├── class
            ├── id
            └── instance

Further capabilities can be added later as attributes of each engine.

v2: Add capabilities sub directory (Tvrtko)
    Move engines directory to drm/card/gt (Chris)

v3: Move engines to drm/card/gt/engines/ (Tvrtko)
    Add instance attribute to engines (Tvrtko)

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h         |   6 ++
 drivers/gpu/drm/i915/i915_sysfs.c       | 178 ++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_engine_cs.c  |  12 +++
 drivers/gpu/drm/i915/intel_ringbuffer.h |   4 +
 4 files changed, 200 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 99981c5d3beb..617e00bb56c0 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2730,6 +2730,12 @@ struct drm_i915_private {
 		} oa;
 	} perf;
 
+	struct {
+		struct kobject gt_kobj;
+		struct kobject engines_kobj;
+		struct kobject engines_classes_kobjs[MAX_ENGINE_CLASS];
+	} gt_topology;
+
 	/* Abstract the submission mechanism (legacy ringbuffer or execlists) away */
 	struct {
 		void (*resume)(struct drm_i915_private *);
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
index c290cb600eea..d9e188813947 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -559,6 +559,178 @@ static void i915_setup_error_capture(struct device *kdev) {}
 static void i915_teardown_error_capture(struct device *kdev) {}
 #endif
 
+static struct attribute engine_class_attr = {
+	.name = "class",
+	.mode = 0444,
+};
+
+static struct attribute engine_id_attr = {
+	.name = "id",
+	.mode = 0444,
+};
+
+static struct attribute engine_instance_attr = {
+	.name = "instance",
+	.mode = 0444,
+};
+
+static ssize_t
+show_engine_attr(struct kobject *kobj, struct attribute *attr, char *buf)
+{
+	struct intel_engine_cs *engine =
+		container_of(kobj, struct intel_engine_cs, instance_kobj);
+
+	if (attr == &engine_class_attr)
+		return sprintf(buf, "%hhu\n", engine->uabi_class);
+	if (attr == &engine_id_attr)
+		return sprintf(buf, "%hhu\n", engine->uabi_id);
+	if (attr == &engine_instance_attr)
+		return sprintf(buf, "%hhu\n", engine->instance);
+	return sprintf(buf, "\n");
+}
+
+static const struct sysfs_ops engine_ops = {
+	.show = show_engine_attr,
+};
+
+static struct kobj_type engine_type = {
+	.sysfs_ops = &engine_ops,
+};
+
+static struct attribute engine_capability_hevc_attr = {
+	.name = "hevc",
+	.mode = 0444,
+};
+
+static ssize_t
+show_engine_capabilities_attr(struct kobject *kobj, struct attribute *attr, char *buf)
+{
+	struct intel_engine_cs *engine =
+		container_of(kobj, struct intel_engine_cs, capabilities_kobj);
+
+	if (attr == &engine_capability_hevc_attr)
+		return sprintf(buf, "%i\n", INTEL_GEN(engine->i915) >= 8);
+	return sprintf(buf, "\n");
+}
+
+static const struct sysfs_ops engine_capabilities_ops = {
+	.show = show_engine_capabilities_attr,
+};
+
+static struct kobj_type engine_capabilities_type = {
+	.sysfs_ops = &engine_capabilities_ops,
+};
+
+static int i915_setup_engines_sysfs(struct drm_i915_private *dev_priv,
+				    struct kobject *gt_kobj)
+{
+	struct intel_engine_cs *engine_for_class, *engine;
+	enum intel_engine_id id_for_class, id;
+	struct kobject *engines_kobj = &dev_priv->gt_topology.engines_kobj;
+	bool registred[MAX_ENGINE_CLASS + 1] = { false, };
+	int ret;
+
+	ret = kobject_init_and_add(engines_kobj, gt_kobj->ktype, gt_kobj,
+				   "engines");
+	if (ret)
+		return ret;
+
+	for_each_engine(engine_for_class, dev_priv, id_for_class) {
+		struct kobject *engine_class_kobj =
+			&dev_priv->gt_topology.engines_classes_kobjs[engine_for_class->class];
+
+		if (registred[engine_for_class->class])
+			continue;
+
+		registred[engine_for_class->class] = true;
+
+		ret = kobject_init_and_add(engine_class_kobj,
+					   engines_kobj->ktype,
+					   engines_kobj,
+					   intel_engine_get_class_name(engine_for_class));
+		if (ret)
+			return ret;
+
+		for_each_engine(engine, dev_priv, id) {
+			if (engine->class != engine_for_class->class)
+				continue;
+
+			ret = kobject_init_and_add(&engine->instance_kobj,
+						   &engine_type,
+						   engine_class_kobj,
+						   "%d", engine->instance);
+			if (ret)
+				return ret;
+
+			ret = sysfs_create_file(&engine->instance_kobj,
+						&engine_class_attr);
+			if (ret)
+				return ret;
+			ret = sysfs_create_file(&engine->instance_kobj,
+						&engine_id_attr);
+			if (ret)
+				return ret;
+			ret = sysfs_create_file(&engine->instance_kobj,
+						&engine_instance_attr);
+			if (ret)
+				return ret;
+
+			ret = kobject_init_and_add(&engine->capabilities_kobj,
+						   &engine_capabilities_type,
+						   &engine->instance_kobj,
+						   "capabilities");
+			if (ret)
+				return ret;
+
+			if (engine->id == VCS) {
+				ret = sysfs_create_file(&engine->capabilities_kobj,
+							&engine_capability_hevc_attr);
+				if (ret)
+					return ret;
+			}
+		}
+	}
+
+	return 0;
+}
+
+static void i915_teardown_engines_sysfs(struct drm_i915_private *dev_priv)
+{
+	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
+
+	for_each_engine(engine, dev_priv, id) {
+		sysfs_remove_file(&engine->instance_kobj, &engine_class_attr);
+		sysfs_remove_file(&engine->instance_kobj, &engine_id_attr);
+		sysfs_remove_file(&engine->instance_kobj, &engine_instance_attr);
+		sysfs_remove_file(&engine->capabilities_kobj,
+				  &engine_capability_hevc_attr);
+	}
+}
+
+static int i915_setup_gt_sysfs(struct drm_i915_private *dev_priv,
+			       struct device *kdev)
+{
+	int ret;
+
+	ret = kobject_init_and_add(&dev_priv->gt_topology.gt_kobj,
+				   kdev->kobj.ktype,
+				   &kdev->kobj,
+				   "gt");
+	if (ret)
+		return ret;
+
+	return i915_setup_engines_sysfs(dev_priv, &dev_priv->gt_topology.gt_kobj);
+}
+
+static void i915_teardown_gt_sysfs(struct drm_i915_private *dev_priv)
+{
+	i915_teardown_engines_sysfs(dev_priv);
+
+	kobject_get(&dev_priv->gt_topology.gt_kobj);
+	kobject_del(&dev_priv->gt_topology.gt_kobj);
+}
+
 void i915_setup_sysfs(struct drm_i915_private *dev_priv)
 {
 	struct device *kdev = dev_priv->drm.primary->kdev;
@@ -605,6 +777,10 @@ void i915_setup_sysfs(struct drm_i915_private *dev_priv)
 	if (ret)
 		DRM_ERROR("RPS sysfs setup failed\n");
 
+	ret = i915_setup_gt_sysfs(dev_priv, kdev);
+	if (ret)
+		DRM_ERROR("GT sysfs setup failed\n");
+
 	i915_setup_error_capture(kdev);
 }
 
@@ -614,6 +790,8 @@ void i915_teardown_sysfs(struct drm_i915_private *dev_priv)
 
 	i915_teardown_error_capture(kdev);
 
+	i915_teardown_gt_sysfs(dev_priv);
+
 	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
 		sysfs_remove_files(&kdev->kobj, vlv_attrs);
 	else
diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c
index fede62daf3e1..fea2a052b0d6 100644
--- a/drivers/gpu/drm/i915/intel_engine_cs.c
+++ b/drivers/gpu/drm/i915/intel_engine_cs.c
@@ -131,6 +131,18 @@ static const struct engine_info intel_engines[] = {
 	},
 };
 
+/**
+ * intel_engine_get_class_name() - return the name of the class for an engine
+ * @engine: engine
+ *
+ * Return: a string naming the class of the engine
+ */
+const char *
+intel_engine_get_class_name(struct intel_engine_cs *engine)
+{
+	return intel_engine_classes[engine->class].name;
+}
+
 /**
  * ___intel_engine_context_size() - return the size of the context for an engine
  * @dev_priv: i915 device private
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index bee3bc36b93b..85801c1bc3e1 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -282,6 +282,9 @@ struct intel_engine_cs {
 	struct drm_i915_private *i915;
 	char name[INTEL_ENGINE_CS_MAX_NAME];
 
+	struct kobject instance_kobj;
+	struct kobject capabilities_kobj;
+
 	enum intel_engine_id id;
 	unsigned int hw_id;
 	unsigned int guc_id;
@@ -981,6 +984,7 @@ gen8_emit_ggtt_write(u32 *cs, u32 value, u32 gtt_offset)
 	return cs;
 }
 
+const char *intel_engine_get_class_name(struct intel_engine_cs *engine);
 bool intel_engine_is_idle(struct intel_engine_cs *engine);
 bool intel_engines_are_idle(struct drm_i915_private *dev_priv);
 
-- 
2.15.0

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

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

* [PATCH v4 4/4] drm/i915: expose EU topology through sysfs
  2017-11-22 12:30 [PATCH v4 0/4] drm/i915: Expose more GPU properties through sysfs Lionel Landwerlin
                   ` (2 preceding siblings ...)
  2017-11-22 12:30 ` [PATCH v4 3/4] drm/i915: expose engine availability through sysfs Lionel Landwerlin
@ 2017-11-22 12:30 ` Lionel Landwerlin
  2017-11-22 12:33 ` ✗ Fi.CI.BAT: failure for drm/i915: Expose more GPU properties through sysfs (rev4) Patchwork
  4 siblings, 0 replies; 6+ messages in thread
From: Lionel Landwerlin @ 2017-11-22 12:30 UTC (permalink / raw)
  To: intel-gfx

With the introduction of asymetric slices in CNL, we cannot rely on
the previous SUBSLICE_MASK getparam. Here we introduce a more detailed
way of querying the Gen's GPU topology that doesn't aggregate numbers.

This is essential for monitoring parts of the GPU with the OA unit,
because signals need to be accounted properly based on whether part of
the GPU has been fused off. The current aggregated numbers like
EU_TOTAL do not gives us sufficient information.

Here is the sysfs layout on a Skylake GT4 :

/sys/devices/pci0000:00/0000:00:02.0/drm/card0/gt/engines/rcs/topology/
├── max_eus_per_subslice
├── max_slices
├── max_subslices_per_slice
├── slice0
│   ├── subslice0
│   │   └── eus_enabled_mask
│   ├── subslice1
│   │   └── eus_enabled_mask
│   ├── subslice2
│   │   └── eus_enabled_mask
│   ├── subslice3
│   │   └── eus_enabled_mask
│   └── subslices_enabled_mask
├── slice1
│   ├── subslice0
│   │   └── eus_enabled_mask
│   ├── subslice1
│   │   └── eus_enabled_mask
│   ├── subslice2
│   │   └── eus_enabled_mask
│   ├── subslice3
│   │   └── eus_enabled_mask
│   └── subslices_enabled_mask
├── slice2
│   ├── subslice0
│   │   └── eus_enabled_mask
│   ├── subslice1
│   │   └── eus_enabled_mask
│   ├── subslice2
│   │   └── eus_enabled_mask
│   ├── subslice3
│   │   └── eus_enabled_mask
│   └── subslices_enabled_mask
└── slices_enabled_mask

Each enabled_mask file gives us a mask of the enabled units :

$ cat /sys/devices/pci0000\:00/0000\:00\:02.0/drm/card0/gt/engines/rcs/topology/slices_enabled_mask
0x7

$ cat /sys/devices/pci0000\:00/0000\:00\:02.0/drm/card0/gt/engines/rcs/topology/slice2/subslice1/eus_enabled_mask
0xff

v2: Move topology below rcs engine (Chris)
    Add max_eus_per_subslice/max_slices/max_subslices_per_slice (Lionel)

v3: Rename enabled_mask (Lionel)

v4: Move slices to drm/card/gt/rcs/topology (Tvrtko)

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h   |  27 +++++
 drivers/gpu/drm/i915/i915_sysfs.c | 208 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 235 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 617e00bb56c0..7f183149dd6b 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2259,6 +2259,24 @@ struct intel_cdclk_state {
 	u8 voltage_level;
 };
 
+struct intel_topology_kobject {
+	struct kobject kobj;
+	struct drm_i915_private *dev_priv;
+};
+
+struct intel_slice_kobject {
+	struct kobject kobj;
+	struct drm_i915_private *dev_priv;
+	u8 slice_index;
+};
+
+struct intel_subslice_kobject {
+	struct kobject kobj;
+	struct drm_i915_private *dev_priv;
+	u8 slice_index;
+	u8 subslice_index;
+};
+
 struct drm_i915_private {
 	struct drm_device drm;
 
@@ -2734,6 +2752,15 @@ struct drm_i915_private {
 		struct kobject gt_kobj;
 		struct kobject engines_kobj;
 		struct kobject engines_classes_kobjs[MAX_ENGINE_CLASS];
+		struct kobject topology_kobj;
+
+		struct sysfs_slice {
+			struct intel_slice_kobject kobj;
+
+			struct sysfs_subslice {
+				struct intel_subslice_kobject kobj;
+			} subslices[GEN_MAX_SUBSLICES];
+		} slices[GEN_MAX_SLICES];
 	} gt_topology;
 
 	/* Abstract the submission mechanism (legacy ringbuffer or execlists) away */
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
index d9e188813947..f31cc6f1fbb2 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -559,6 +559,205 @@ static void i915_setup_error_capture(struct device *kdev) {}
 static void i915_teardown_error_capture(struct device *kdev) {}
 #endif
 
+static struct attribute slices_enabled_mask_attr = {
+	.name = "slices_enabled_mask",
+	.mode = 0444,
+};
+
+static struct attribute subslices_enabled_mask_attr = {
+	.name = "subslices_enabled_mask",
+	.mode = 0444,
+};
+
+static struct attribute eus_enabled_mask_attr = {
+	.name = "eus_enabled_mask",
+	.mode = 0444,
+};
+
+static struct attribute max_slices_attr = {
+	.name = "max_slices",
+	.mode = 0444,
+};
+
+static struct attribute max_subslices_per_slice_attr = {
+	.name = "max_subslices_per_slice",
+	.mode = 0444,
+};
+
+static struct attribute max_eus_per_subslice_attr = {
+	.name = "max_eus_per_subslice",
+	.mode = 0444,
+};
+
+static ssize_t
+show_topology_attr(struct kobject *kobj, struct attribute *attr, char *buf)
+{
+	struct drm_i915_private *dev_priv =
+		container_of(kobj, struct drm_i915_private, gt_topology.topology_kobj);
+	const struct sseu_dev_info *sseu = &INTEL_INFO(dev_priv)->sseu;
+
+	if (attr == &slices_enabled_mask_attr)
+		return sprintf(buf, "0x%hhx\n", sseu->slice_mask);
+	if (attr == &max_eus_per_subslice_attr)
+		return sprintf(buf, "%hhd\n", sseu->max_eus_per_subslice);
+	if (attr == &max_subslices_per_slice_attr)
+		return sprintf(buf, "%hhd\n", sseu->max_subslices);
+	if (attr == &max_slices_attr)
+		return sprintf(buf, "%hhd\n", sseu->max_slices);
+	return sprintf(buf, "\n");
+}
+
+static const struct sysfs_ops topology_ops = {
+	.show = show_topology_attr,
+};
+
+static struct kobj_type topology_type = {
+	.sysfs_ops = &topology_ops,
+};
+
+static ssize_t
+show_slice_attr(struct kobject *kobj, struct attribute *attr, char *buf)
+{
+	struct intel_slice_kobject *kobj_wrapper =
+		container_of(kobj, struct intel_slice_kobject, kobj);
+	struct drm_i915_private *dev_priv = kobj_wrapper->dev_priv;
+	const struct sseu_dev_info *sseu = &INTEL_INFO(dev_priv)->sseu;
+
+	if (attr == &subslices_enabled_mask_attr) {
+		return sprintf(buf, "0x%hhx\n",
+			       sseu->subslices_mask[kobj_wrapper->slice_index]);
+	}
+	return sprintf(buf, "\n");
+}
+
+static const struct sysfs_ops slice_ops = {
+	.show = show_slice_attr,
+};
+
+static struct kobj_type slice_type = {
+	.sysfs_ops = &slice_ops,
+};
+
+static ssize_t
+show_subslice_attr(struct kobject *kobj, struct attribute *attr, char *buf)
+{
+	struct intel_subslice_kobject *kobj_wrapper =
+		container_of(kobj, struct intel_subslice_kobject, kobj);
+	struct drm_i915_private *dev_priv = kobj_wrapper->dev_priv;
+	const struct sseu_dev_info *sseu = &INTEL_INFO(dev_priv)->sseu;
+	int subslice_stride = ALIGN(sseu->max_eus_per_subslice, 8) / 8;
+	int slice_stride = sseu->max_subslices * subslice_stride;
+
+	if (attr == &eus_enabled_mask_attr)
+		return sprintf(buf, "0x%hhx\n",
+			       sseu->eu_mask[kobj_wrapper->slice_index * slice_stride +
+					     kobj_wrapper->subslice_index * subslice_stride]);
+	return sprintf(buf, "\n");
+}
+
+static const struct sysfs_ops subslice_ops = {
+	.show = show_subslice_attr,
+};
+
+static struct kobj_type subslice_type = {
+	.sysfs_ops = &subslice_ops,
+};
+
+static int i915_setup_rcs_topology_sysfs(struct drm_i915_private *dev_priv,
+					 struct kobject *engine_class_kobj)
+{
+	const struct sseu_dev_info *sseu = &INTEL_INFO(dev_priv)->sseu;
+	struct kobject *topology_kobj = &dev_priv->gt_topology.topology_kobj;
+	int ret, s, ss;
+
+	ret = kobject_init_and_add(topology_kobj, &topology_type,
+				   engine_class_kobj, "topology");
+	if (ret)
+		return ret;
+
+	ret = sysfs_create_file(topology_kobj, &slices_enabled_mask_attr);
+	if (ret)
+		return ret;
+
+	ret = sysfs_create_file(topology_kobj, &max_slices_attr);
+	if (ret)
+		return ret;
+
+	ret = sysfs_create_file(topology_kobj, &max_subslices_per_slice_attr);
+	if (ret)
+		return ret;
+
+	ret = sysfs_create_file(topology_kobj, &max_eus_per_subslice_attr);
+	if (ret)
+		return ret;
+
+	for (s = 0; s < sseu->max_slices; s++) {
+		struct intel_slice_kobject *slice_kobj =
+			&dev_priv->gt_topology.slices[s].kobj;
+
+		slice_kobj->dev_priv = dev_priv;
+		slice_kobj->slice_index = s;
+		ret = kobject_init_and_add(&slice_kobj->kobj, &slice_type,
+					   topology_kobj, "slice%i", s);
+		if (ret)
+			return ret;
+
+		ret = sysfs_create_file(&slice_kobj->kobj,
+					&subslices_enabled_mask_attr);
+		if (ret)
+			return ret;
+
+		for (ss = 0; ss < sseu->max_subslices; ss++) {
+			struct intel_subslice_kobject *subslice_kobj =
+				&dev_priv->gt_topology.slices[s].subslices[ss].kobj;
+
+			subslice_kobj->dev_priv = dev_priv;
+			subslice_kobj->slice_index = s;
+			subslice_kobj->subslice_index = ss;
+			ret = kobject_init_and_add(&subslice_kobj->kobj,
+						   &subslice_type,
+						   &slice_kobj->kobj,
+						   "subslice%i", ss);
+			if (ret)
+				return ret;
+
+			ret = sysfs_create_file(&subslice_kobj->kobj,
+						&eus_enabled_mask_attr);
+			if (ret)
+				return ret;
+		}
+	}
+
+	return 0;
+}
+
+static void i915_teardown_rcs_topology_sysfs(struct drm_i915_private *dev_priv)
+{
+	const struct sseu_dev_info *sseu = &INTEL_INFO(dev_priv)->sseu;
+	struct kobject *topology_kobj = &dev_priv->gt_topology.topology_kobj;
+	int s, ss;
+
+	for (s = 0; s < sseu->max_slices; s++) {
+		struct intel_slice_kobject *slice_kobj =
+			&dev_priv->gt_topology.slices[s].kobj;
+
+		for (ss = 0; ss < sseu->max_subslices; ss++) {
+			struct intel_subslice_kobject *subslice_kobj =
+				&dev_priv->gt_topology.slices[s].subslices[ss].kobj;
+
+			sysfs_remove_file(&subslice_kobj->kobj,
+					  &eus_enabled_mask_attr);
+		}
+
+		sysfs_remove_file(&slice_kobj->kobj,
+				  &subslices_enabled_mask_attr);
+	}
+	sysfs_remove_file(topology_kobj, &slices_enabled_mask_attr);
+	sysfs_remove_file(topology_kobj, &max_eus_per_subslice_attr);
+	sysfs_remove_file(topology_kobj, &max_subslices_per_slice_attr);
+	sysfs_remove_file(topology_kobj, &max_slices_attr);
+}
+
 static struct attribute engine_class_attr = {
 	.name = "class",
 	.mode = 0444,
@@ -651,6 +850,13 @@ static int i915_setup_engines_sysfs(struct drm_i915_private *dev_priv,
 		if (ret)
 			return ret;
 
+		if (engine_for_class->class == RENDER_CLASS) {
+			ret = i915_setup_rcs_topology_sysfs(dev_priv,
+							    engine_class_kobj);
+			if (ret)
+				return ret;
+		}
+
 		for_each_engine(engine, dev_priv, id) {
 			if (engine->class != engine_for_class->class)
 				continue;
@@ -699,6 +905,8 @@ static void i915_teardown_engines_sysfs(struct drm_i915_private *dev_priv)
 	struct intel_engine_cs *engine;
 	enum intel_engine_id id;
 
+	i915_teardown_rcs_topology_sysfs(dev_priv);
+
 	for_each_engine(engine, dev_priv, id) {
 		sysfs_remove_file(&engine->instance_kobj, &engine_class_attr);
 		sysfs_remove_file(&engine->instance_kobj, &engine_id_attr);
-- 
2.15.0

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

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

* ✗ Fi.CI.BAT: failure for drm/i915: Expose more GPU properties through sysfs (rev4)
  2017-11-22 12:30 [PATCH v4 0/4] drm/i915: Expose more GPU properties through sysfs Lionel Landwerlin
                   ` (3 preceding siblings ...)
  2017-11-22 12:30 ` [PATCH v4 4/4] drm/i915: expose EU topology " Lionel Landwerlin
@ 2017-11-22 12:33 ` Patchwork
  4 siblings, 0 replies; 6+ messages in thread
From: Patchwork @ 2017-11-22 12:33 UTC (permalink / raw)
  To: Lionel Landwerlin; +Cc: intel-gfx

== Series Details ==

Series: drm/i915: Expose more GPU properties through sysfs (rev4)
URL   : https://patchwork.freedesktop.org/series/33950/
State : failure

== Summary ==

  CHK     include/config/kernel.release
  CHK     include/generated/uapi/linux/version.h
  CHK     include/generated/utsrelease.h
  CHK     include/generated/bounds.h
  CHK     include/generated/timeconst.h
  CHK     include/generated/asm-offsets.h
  CALL    scripts/checksyscalls.sh
  DESCEND  objtool
  CHK     scripts/mod/devicetable-offsets.h
  CHK     include/generated/compile.h
  CHK     kernel/config_data.h
  CC [M]  drivers/gpu/drm/i915/i915_drv.o
In file included from drivers/gpu/drm/i915/i915_drv.c:49:0:
drivers/gpu/drm/i915/i915_drv.h:2751:40: error: ‘MAX_ENGINE_CLASS’ undeclared here (not in a function)
   struct kobject engines_classes_kobjs[MAX_ENGINE_CLASS];
                                        ^~~~~~~~~~~~~~~~
scripts/Makefile.build:314: recipe for target 'drivers/gpu/drm/i915/i915_drv.o' failed
make[4]: *** [drivers/gpu/drm/i915/i915_drv.o] Error 1
scripts/Makefile.build:573: recipe for target 'drivers/gpu/drm/i915' failed
make[3]: *** [drivers/gpu/drm/i915] Error 2
scripts/Makefile.build:573: recipe for target 'drivers/gpu/drm' failed
make[2]: *** [drivers/gpu/drm] Error 2
scripts/Makefile.build:573: recipe for target 'drivers/gpu' failed
make[1]: *** [drivers/gpu] Error 2
Makefile:1024: recipe for target 'drivers' failed
make: *** [drivers] Error 2

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

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

end of thread, other threads:[~2017-11-22 12:33 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-11-22 12:30 [PATCH v4 0/4] drm/i915: Expose more GPU properties through sysfs Lionel Landwerlin
2017-11-22 12:30 ` [PATCH v4 1/4] drm/i915: store all subslice masks Lionel Landwerlin
2017-11-22 12:30 ` [PATCH v4 2/4] drm/i915/debugfs: reuse max slice/subslices already stored in sseu Lionel Landwerlin
2017-11-22 12:30 ` [PATCH v4 3/4] drm/i915: expose engine availability through sysfs Lionel Landwerlin
2017-11-22 12:30 ` [PATCH v4 4/4] drm/i915: expose EU topology " Lionel Landwerlin
2017-11-22 12:33 ` ✗ Fi.CI.BAT: failure for drm/i915: Expose more GPU properties through sysfs (rev4) Patchwork

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.