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

Hi all,

Last update on this with a couple of sysfs file renamed. I don't have
any other update or unaddressed comment.

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          |  54 ++++-
 drivers/gpu/drm/i915/i915_reg.h          |   1 +
 drivers/gpu/drm/i915/i915_sysfs.c        | 348 +++++++++++++++++++++++++++++++
 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 +-
 9 files changed, 567 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] 19+ messages in thread

* [PATCH 1/4] drm/i915: store all subslice masks
  2017-11-20 12:23 [PATCH 0/4] drm/i915: Expose more GPU properties through sysfs Lionel Landwerlin
@ 2017-11-20 12:23 ` Lionel Landwerlin
  2017-11-20 12:23 ` [PATCH 2/4] drm/i915/debugfs: reuse max slice/subslices already stored in sseu Lionel Landwerlin
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 19+ messages in thread
From: Lionel Landwerlin @ 2017-11-20 12:23 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 df3852c02a35..3cc0f383b058 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -4477,7 +4477,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) +
@@ -4524,7 +4524,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;
@@ -4579,8 +4579,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;
@@ -4590,7 +4590,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] &
@@ -4612,9 +4612,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);
 
@@ -4633,6 +4636,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);
@@ -4640,10 +4644,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 b4d89e08724b..05bc73b828b5 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -415,7 +415,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 2b766253f970..78c49db4280a 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -800,9 +800,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;
@@ -811,11 +814,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 be6c39adebdf..8a9ea083de21 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -2063,7 +2063,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 f867aa6c31fc..5f96533e5341 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -99,7 +99,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] 19+ messages in thread

* [PATCH 2/4] drm/i915/debugfs: reuse max slice/subslices already stored in sseu
  2017-11-20 12:23 [PATCH 0/4] drm/i915: Expose more GPU properties through sysfs Lionel Landwerlin
  2017-11-20 12:23 ` [PATCH 1/4] drm/i915: store all subslice masks Lionel Landwerlin
@ 2017-11-20 12:23 ` Lionel Landwerlin
  2017-11-20 12:23 ` [PATCH 3/4] drm/i915: expose engine availability through sysfs Lionel Landwerlin
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 19+ messages in thread
From: Lionel Landwerlin @ 2017-11-20 12:23 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 3cc0f383b058..4dea1829c4d4 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -4492,11 +4492,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
@@ -4518,7 +4518,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;
@@ -4526,7 +4526,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))))
@@ -4546,17 +4546,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));
@@ -4571,7 +4565,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;
@@ -4582,7 +4576,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] 19+ messages in thread

* [PATCH 3/4] drm/i915: expose engine availability through sysfs
  2017-11-20 12:23 [PATCH 0/4] drm/i915: Expose more GPU properties through sysfs Lionel Landwerlin
  2017-11-20 12:23 ` [PATCH 1/4] drm/i915: store all subslice masks Lionel Landwerlin
  2017-11-20 12:23 ` [PATCH 2/4] drm/i915/debugfs: reuse max slice/subslices already stored in sseu Lionel Landwerlin
@ 2017-11-20 12:23 ` Lionel Landwerlin
  2017-11-20 15:57   ` Tvrtko Ursulin
                     ` (2 more replies)
  2017-11-20 12:23 ` [PATCH 4/4] drm/i915: expose EU topology " Lionel Landwerlin
                   ` (2 subsequent siblings)
  5 siblings, 3 replies; 19+ messages in thread
From: Lionel Landwerlin @ 2017-11-20 12:23 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
├── bcs
│   └── 0
│       ├── capabilities
│       ├── class
│       └── id
├── rcs
│   └── 0
│       ├── capabilities
│       ├── class
│       └── id
├── vcs
│   ├── 0
│   │   ├── capabilities
│   │   │   └── hevc
│   │   ├── class
│   │   └── id
│   └── 1
│       ├── capabilities
│       ├── class
│       └── id
└── vecs
    └── 0
        ├── capabilities
        ├── class
        └── id

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)

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

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 78c49db4280a..db550322207c 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2729,6 +2729,11 @@ struct drm_i915_private {
 		} oa;
 	} perf;
 
+	struct {
+		struct kobject kobj;
+		struct kobject 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_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 96c80fa0fcac..17aecd4fc6aa 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -186,6 +186,7 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
 #define VIDEO_ENHANCEMENT_CLASS	2
 #define COPY_ENGINE_CLASS	3
 #define OTHER_CLASS		4
+#define MAX_ENGINE_CLASS	5
 
 /* PCI config space */
 
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
index 791759f632e1..fd04d0b93eaf 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -559,6 +559,160 @@ static void i915_setup_error_capture(struct device *kdev) {}
 static void i915_teardown_error_capture(struct device *kdev) {}
 #endif
 
+static struct attribute engine_id_attr = {
+	.name = "id",
+	.mode = 0444,
+};
+
+static struct attribute engine_class_attr = {
+	.name = "class",
+	.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_id_attr)
+		return sprintf(buf, "%hhu\n", engine->uabi_id);
+	if (attr == &engine_class_attr)
+		return sprintf(buf, "%hhu\n", engine->uabi_class);
+	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;
+	bool registred[MAX_ENGINE_CLASS] = { false, };
+	int ret;
+
+	for_each_engine(engine_for_class, dev_priv, id_for_class) {
+		struct kobject *engine_class_kobj =
+			&dev_priv->gt_topology.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,
+					   gt_kobj->ktype,
+					   gt_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_id_attr);
+			if (ret)
+				return ret;
+			ret = sysfs_create_file(&engine->instance_kobj,
+						&engine_class_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_id_attr);
+		sysfs_remove_file(&engine->instance_kobj, &engine_class_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.kobj,
+				   kdev->kobj.ktype,
+				   &kdev->kobj,
+				   "gt");
+	if (ret)
+		return ret;
+
+	return i915_setup_engines_sysfs(dev_priv, &dev_priv->gt_topology.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.kobj);
+	kobject_del(&dev_priv->gt_topology.kobj);
+}
+
 void i915_setup_sysfs(struct drm_i915_private *dev_priv)
 {
 	struct device *kdev = dev_priv->drm.primary->kdev;
@@ -605,6 +759,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 +772,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 9897c7f78c51..9d82dfbb45db 100644
--- a/drivers/gpu/drm/i915/intel_engine_cs.c
+++ b/drivers/gpu/drm/i915/intel_engine_cs.c
@@ -133,6 +133,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 5f96533e5341..eca6c87a1e06 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -290,6 +290,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;
@@ -924,6 +927,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] 19+ messages in thread

* [PATCH 4/4] drm/i915: expose EU topology through sysfs
  2017-11-20 12:23 [PATCH 0/4] drm/i915: Expose more GPU properties through sysfs Lionel Landwerlin
                   ` (2 preceding siblings ...)
  2017-11-20 12:23 ` [PATCH 3/4] drm/i915: expose engine availability through sysfs Lionel Landwerlin
@ 2017-11-20 12:23 ` Lionel Landwerlin
  2017-11-20 16:13   ` Tvrtko Ursulin
  2017-11-20 12:45 ` ✓ Fi.CI.BAT: success for drm/i915: Expose more GPU properties through sysfs (rev3) Patchwork
  2017-11-20 13:33 ` ✓ Fi.CI.IGT: " Patchwork
  5 siblings, 1 reply; 19+ messages in thread
From: Lionel Landwerlin @ 2017-11-20 12:23 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/rcs/0/
├── capabilities
├── class
├── id
├── 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/rcs/0/slices_enabled_mask
0x7

$ cat /sys/devices/pci0000\:00/0000\:00\:02.0/drm/card0/gt/rcs/0/slice0/subslice2/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)

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

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index db550322207c..1ac0a191e8fc 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;
 
@@ -2732,6 +2750,14 @@ struct drm_i915_private {
 	struct {
 		struct kobject kobj;
 		struct kobject classes_kobjs[MAX_ENGINE_CLASS];
+
+		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 fd04d0b93eaf..df9d8fdbcb0a 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -559,6 +559,174 @@ 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_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, "0x0\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, "0x0\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_kobj)
+{
+	const struct sseu_dev_info *sseu = &INTEL_INFO(dev_priv)->sseu;
+	int ret, s, ss;
+
+	ret = sysfs_create_file(engine_kobj, &slices_enabled_mask_attr);
+	if (ret)
+		return ret;
+
+	ret = sysfs_create_file(engine_kobj, &max_slices_attr);
+	if (ret)
+		return ret;
+
+	ret = sysfs_create_file(engine_kobj, &max_subslices_per_slice_attr);
+	if (ret)
+		return ret;
+
+	ret = sysfs_create_file(engine_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,
+					   engine_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,
+					     struct kobject *engine_kobj)
+{
+	const struct sseu_dev_info *sseu = &INTEL_INFO(dev_priv)->sseu;
+	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(engine_kobj, &slices_enabled_mask_attr);
+	sysfs_remove_file(engine_kobj, &max_eus_per_subslice_attr);
+	sysfs_remove_file(engine_kobj, &max_subslices_per_slice_attr);
+	sysfs_remove_file(engine_kobj, &max_slices_attr);
+}
+
 static struct attribute engine_id_attr = {
 	.name = "id",
 	.mode = 0444,
@@ -574,11 +742,20 @@ 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);
+	const struct sseu_dev_info *sseu = &INTEL_INFO(engine->i915)->sseu;
 
 	if (attr == &engine_id_attr)
 		return sprintf(buf, "%hhu\n", engine->uabi_id);
 	if (attr == &engine_class_attr)
 		return sprintf(buf, "%hhu\n", engine->uabi_class);
+	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");
 }
 
@@ -671,6 +848,12 @@ static int i915_setup_engines_sysfs(struct drm_i915_private *dev_priv,
 				if (ret)
 					return ret;
 			}
+			if (engine->id == RCS) {
+				ret = i915_setup_rcs_topology_sysfs(dev_priv,
+								    &engine->instance_kobj);
+				if (ret)
+					return ret;
+			}
 		}
 	}
 
@@ -683,6 +866,11 @@ static void i915_teardown_engines_sysfs(struct drm_i915_private *dev_priv)
 	enum intel_engine_id id;
 
 	for_each_engine(engine, dev_priv, id) {
+		if (id == RCS) {
+			i915_teardown_rcs_topology_sysfs(dev_priv,
+							 &engine->instance_kobj);
+		}
+
 		sysfs_remove_file(&engine->instance_kobj, &engine_id_attr);
 		sysfs_remove_file(&engine->instance_kobj, &engine_class_attr);
 		sysfs_remove_file(&engine->capabilities_kobj,
-- 
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] 19+ messages in thread

* ✓ Fi.CI.BAT: success for drm/i915: Expose more GPU properties through sysfs (rev3)
  2017-11-20 12:23 [PATCH 0/4] drm/i915: Expose more GPU properties through sysfs Lionel Landwerlin
                   ` (3 preceding siblings ...)
  2017-11-20 12:23 ` [PATCH 4/4] drm/i915: expose EU topology " Lionel Landwerlin
@ 2017-11-20 12:45 ` Patchwork
  2017-11-20 13:33 ` ✓ Fi.CI.IGT: " Patchwork
  5 siblings, 0 replies; 19+ messages in thread
From: Patchwork @ 2017-11-20 12:45 UTC (permalink / raw)
  To: Lionel Landwerlin; +Cc: intel-gfx

== Series Details ==

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

== Summary ==

Series 33950v3 drm/i915: Expose more GPU properties through sysfs
https://patchwork.freedesktop.org/api/1.0/series/33950/revisions/3/mbox/

Test kms_busy:
        Subgroup basic-flip-a:
                fail       -> PASS       (fi-gdg-551) fdo#102654

fdo#102654 https://bugs.freedesktop.org/show_bug.cgi?id=102654

fi-bdw-gvtdvm    total:289  pass:265  dwarn:0   dfail:0   fail:0   skip:24  time:460s
fi-bsw-n3050     total:289  pass:243  dwarn:0   dfail:0   fail:0   skip:46  time:534s
fi-bwr-2160      total:289  pass:183  dwarn:0   dfail:0   fail:0   skip:106 time:277s
fi-bxt-dsi       total:289  pass:259  dwarn:0   dfail:0   fail:0   skip:30  time:509s
fi-bxt-j4205     total:289  pass:260  dwarn:0   dfail:0   fail:0   skip:29  time:507s
fi-byt-j1900     total:289  pass:254  dwarn:0   dfail:0   fail:0   skip:35  time:496s
fi-cfl-s2        total:289  pass:263  dwarn:0   dfail:0   fail:0   skip:26  time:611s
fi-elk-e7500     total:289  pass:229  dwarn:0   dfail:0   fail:0   skip:60  time:428s
fi-gdg-551       total:289  pass:177  dwarn:1   dfail:0   fail:2   skip:109 time:277s
fi-glk-1         total:289  pass:261  dwarn:0   dfail:0   fail:0   skip:28  time:539s
fi-hsw-4770      total:289  pass:262  dwarn:0   dfail:0   fail:0   skip:27  time:433s
fi-hsw-4770r     total:289  pass:262  dwarn:0   dfail:0   fail:0   skip:27  time:437s
fi-ilk-650       total:289  pass:228  dwarn:0   dfail:0   fail:0   skip:61  time:430s
fi-ivb-3520m     total:289  pass:260  dwarn:0   dfail:0   fail:0   skip:29  time:485s
fi-ivb-3770      total:289  pass:260  dwarn:0   dfail:0   fail:0   skip:29  time:468s
fi-kbl-7500u     total:289  pass:264  dwarn:1   dfail:0   fail:0   skip:24  time:484s
fi-kbl-7560u     total:289  pass:270  dwarn:0   dfail:0   fail:0   skip:19  time:533s
fi-kbl-7567u     total:289  pass:269  dwarn:0   dfail:0   fail:0   skip:20  time:476s
fi-kbl-r         total:289  pass:262  dwarn:0   dfail:0   fail:0   skip:27  time:532s
fi-pnv-d510      total:289  pass:222  dwarn:1   dfail:0   fail:0   skip:66  time:581s
fi-skl-6260u     total:289  pass:269  dwarn:0   dfail:0   fail:0   skip:20  time:460s
fi-skl-6600u     total:289  pass:262  dwarn:0   dfail:0   fail:0   skip:27  time:544s
fi-skl-6700hq    total:289  pass:263  dwarn:0   dfail:0   fail:0   skip:26  time:566s
fi-skl-6700k     total:289  pass:265  dwarn:0   dfail:0   fail:0   skip:24  time:526s
fi-skl-6770hq    total:289  pass:269  dwarn:0   dfail:0   fail:0   skip:20  time:495s
fi-skl-gvtdvm    total:289  pass:266  dwarn:0   dfail:0   fail:0   skip:23  time:466s
fi-snb-2520m     total:289  pass:250  dwarn:0   dfail:0   fail:0   skip:39  time:557s
fi-snb-2600      total:289  pass:249  dwarn:0   dfail:0   fail:0   skip:40  time:422s
Blacklisted hosts:
fi-glk-dsi       total:289  pass:157  dwarn:0   dfail:10  fail:2   skip:120 time:382s
fi-blb-e6850 failed to collect. IGT log at Patchwork_7201/fi-blb-e6850/igt.log

4b69b21e93c02a8b45781c490077dc1a35adc608 drm-tip: 2017y-11m-20d-10h-20m-58s UTC integration manifest
116f86c8b1f2 drm/i915: expose EU topology through sysfs
be7c8a5ea49d drm/i915: expose engine availability through sysfs
b494b86e700b drm/i915/debugfs: reuse max slice/subslices already stored in sseu
ff6c74e4d5cd drm/i915: store all subslice masks

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_7201/
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* ✓ Fi.CI.IGT: success for drm/i915: Expose more GPU properties through sysfs (rev3)
  2017-11-20 12:23 [PATCH 0/4] drm/i915: Expose more GPU properties through sysfs Lionel Landwerlin
                   ` (4 preceding siblings ...)
  2017-11-20 12:45 ` ✓ Fi.CI.BAT: success for drm/i915: Expose more GPU properties through sysfs (rev3) Patchwork
@ 2017-11-20 13:33 ` Patchwork
  5 siblings, 0 replies; 19+ messages in thread
From: Patchwork @ 2017-11-20 13:33 UTC (permalink / raw)
  To: Lionel Landwerlin; +Cc: intel-gfx

== Series Details ==

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

== Summary ==

Test drv_module_reload:
        Subgroup basic-no-display:
                pass       -> DMESG-WARN (shard-snb) fdo#102707
Test gem_eio:
        Subgroup in-flight-suspend:
                fail       -> PASS       (shard-hsw) fdo#103375

fdo#102707 https://bugs.freedesktop.org/show_bug.cgi?id=102707
fdo#103375 https://bugs.freedesktop.org/show_bug.cgi?id=103375

shard-hsw        total:2585 pass:1474 dwarn:1   dfail:1   fail:10  skip:1099 time:9476s
shard-snb        total:2585 pass:1258 dwarn:3   dfail:1   fail:12  skip:1311 time:7973s
Blacklisted hosts:
shard-apl        total:2565 pass:1605 dwarn:1   dfail:0   fail:21  skip:937 time:12969s
shard-kbl        total:2534 pass:1660 dwarn:16  dfail:6   fail:27  skip:823 time:10283s

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_7201/shards.html
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 3/4] drm/i915: expose engine availability through sysfs
  2017-11-20 12:23 ` [PATCH 3/4] drm/i915: expose engine availability through sysfs Lionel Landwerlin
@ 2017-11-20 15:57   ` Tvrtko Ursulin
  2017-11-21 12:41     ` Ewelina Musial
  2017-11-20 16:03   ` Tvrtko Ursulin
  2017-11-28 18:17   ` Tvrtko Ursulin
  2 siblings, 1 reply; 19+ messages in thread
From: Tvrtko Ursulin @ 2017-11-20 15:57 UTC (permalink / raw)
  To: Lionel Landwerlin, intel-gfx


On 20/11/2017 12:23, Lionel Landwerlin wrote:
> 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
> ├── bcs

It niggles me a bit that engine class names are directly under gt. If we 
end up having to add something else under gt then it will be a little 
bit of an enumeration trouble for userspace.

So I wanted to suggest gt/engines/rcs if that makes sense to people?

Regards,

Tvrtko

> │   └── 0
> │       ├── capabilities
> │       ├── class
> │       └── id
> ├── rcs
> │   └── 0
> │       ├── capabilities
> │       ├── class
> │       └── id
> ├── vcs
> │   ├── 0
> │   │   ├── capabilities
> │   │   │   └── hevc
> │   │   ├── class
> │   │   └── id
> │   └── 1
> │       ├── capabilities
> │       ├── class
> │       └── id
> └── vecs
>      └── 0
>          ├── capabilities
>          ├── class
>          └── id
> 
> 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)
> 
> Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
> ---
>   drivers/gpu/drm/i915/i915_drv.h         |   5 +
>   drivers/gpu/drm/i915/i915_reg.h         |   1 +
>   drivers/gpu/drm/i915/i915_sysfs.c       | 160 ++++++++++++++++++++++++++++++++
>   drivers/gpu/drm/i915/intel_engine_cs.c  |  12 +++
>   drivers/gpu/drm/i915/intel_ringbuffer.h |   4 +
>   5 files changed, 182 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 78c49db4280a..db550322207c 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -2729,6 +2729,11 @@ struct drm_i915_private {
>   		} oa;
>   	} perf;
>   
> +	struct {
> +		struct kobject kobj;
> +		struct kobject 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_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 96c80fa0fcac..17aecd4fc6aa 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -186,6 +186,7 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
>   #define VIDEO_ENHANCEMENT_CLASS	2
>   #define COPY_ENGINE_CLASS	3
>   #define OTHER_CLASS		4
> +#define MAX_ENGINE_CLASS	5
>   
>   /* PCI config space */
>   
> diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
> index 791759f632e1..fd04d0b93eaf 100644
> --- a/drivers/gpu/drm/i915/i915_sysfs.c
> +++ b/drivers/gpu/drm/i915/i915_sysfs.c
> @@ -559,6 +559,160 @@ static void i915_setup_error_capture(struct device *kdev) {}
>   static void i915_teardown_error_capture(struct device *kdev) {}
>   #endif
>   
> +static struct attribute engine_id_attr = {
> +	.name = "id",
> +	.mode = 0444,
> +};
> +
> +static struct attribute engine_class_attr = {
> +	.name = "class",
> +	.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_id_attr)
> +		return sprintf(buf, "%hhu\n", engine->uabi_id);
> +	if (attr == &engine_class_attr)
> +		return sprintf(buf, "%hhu\n", engine->uabi_class);
> +	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;
> +	bool registred[MAX_ENGINE_CLASS] = { false, };
> +	int ret;
> +
> +	for_each_engine(engine_for_class, dev_priv, id_for_class) {
> +		struct kobject *engine_class_kobj =
> +			&dev_priv->gt_topology.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,
> +					   gt_kobj->ktype,
> +					   gt_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_id_attr);
> +			if (ret)
> +				return ret;
> +			ret = sysfs_create_file(&engine->instance_kobj,
> +						&engine_class_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_id_attr);
> +		sysfs_remove_file(&engine->instance_kobj, &engine_class_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.kobj,
> +				   kdev->kobj.ktype,
> +				   &kdev->kobj,
> +				   "gt");
> +	if (ret)
> +		return ret;
> +
> +	return i915_setup_engines_sysfs(dev_priv, &dev_priv->gt_topology.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.kobj);
> +	kobject_del(&dev_priv->gt_topology.kobj);
> +}
> +
>   void i915_setup_sysfs(struct drm_i915_private *dev_priv)
>   {
>   	struct device *kdev = dev_priv->drm.primary->kdev;
> @@ -605,6 +759,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 +772,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 9897c7f78c51..9d82dfbb45db 100644
> --- a/drivers/gpu/drm/i915/intel_engine_cs.c
> +++ b/drivers/gpu/drm/i915/intel_engine_cs.c
> @@ -133,6 +133,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 5f96533e5341..eca6c87a1e06 100644
> --- a/drivers/gpu/drm/i915/intel_ringbuffer.h
> +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
> @@ -290,6 +290,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;
> @@ -924,6 +927,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);
>   
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 3/4] drm/i915: expose engine availability through sysfs
  2017-11-20 12:23 ` [PATCH 3/4] drm/i915: expose engine availability through sysfs Lionel Landwerlin
  2017-11-20 15:57   ` Tvrtko Ursulin
@ 2017-11-20 16:03   ` Tvrtko Ursulin
  2017-11-20 16:33     ` Lionel Landwerlin
  2017-11-28 18:17   ` Tvrtko Ursulin
  2 siblings, 1 reply; 19+ messages in thread
From: Tvrtko Ursulin @ 2017-11-20 16:03 UTC (permalink / raw)
  To: Lionel Landwerlin, intel-gfx


On 20/11/2017 12:23, Lionel Landwerlin wrote:
> 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
> ├── bcs
> │   └── 0
> │       ├── capabilities
> │       ├── class
> │       └── id

One more thing - I would need engine->instance here as well.

Regards,

Tvrtko

> ├── rcs
> │   └── 0
> │       ├── capabilities
> │       ├── class
> │       └── id
> ├── vcs
> │   ├── 0
> │   │   ├── capabilities
> │   │   │   └── hevc
> │   │   ├── class
> │   │   └── id
> │   └── 1
> │       ├── capabilities
> │       ├── class
> │       └── id
> └── vecs
>      └── 0
>          ├── capabilities
>          ├── class
>          └── id
> 
> 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)
> 
> Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
> ---
>   drivers/gpu/drm/i915/i915_drv.h         |   5 +
>   drivers/gpu/drm/i915/i915_reg.h         |   1 +
>   drivers/gpu/drm/i915/i915_sysfs.c       | 160 ++++++++++++++++++++++++++++++++
>   drivers/gpu/drm/i915/intel_engine_cs.c  |  12 +++
>   drivers/gpu/drm/i915/intel_ringbuffer.h |   4 +
>   5 files changed, 182 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 78c49db4280a..db550322207c 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -2729,6 +2729,11 @@ struct drm_i915_private {
>   		} oa;
>   	} perf;
>   
> +	struct {
> +		struct kobject kobj;
> +		struct kobject 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_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 96c80fa0fcac..17aecd4fc6aa 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -186,6 +186,7 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
>   #define VIDEO_ENHANCEMENT_CLASS	2
>   #define COPY_ENGINE_CLASS	3
>   #define OTHER_CLASS		4
> +#define MAX_ENGINE_CLASS	5
>   
>   /* PCI config space */
>   
> diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
> index 791759f632e1..fd04d0b93eaf 100644
> --- a/drivers/gpu/drm/i915/i915_sysfs.c
> +++ b/drivers/gpu/drm/i915/i915_sysfs.c
> @@ -559,6 +559,160 @@ static void i915_setup_error_capture(struct device *kdev) {}
>   static void i915_teardown_error_capture(struct device *kdev) {}
>   #endif
>   
> +static struct attribute engine_id_attr = {
> +	.name = "id",
> +	.mode = 0444,
> +};
> +
> +static struct attribute engine_class_attr = {
> +	.name = "class",
> +	.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_id_attr)
> +		return sprintf(buf, "%hhu\n", engine->uabi_id);
> +	if (attr == &engine_class_attr)
> +		return sprintf(buf, "%hhu\n", engine->uabi_class);
> +	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;
> +	bool registred[MAX_ENGINE_CLASS] = { false, };
> +	int ret;
> +
> +	for_each_engine(engine_for_class, dev_priv, id_for_class) {
> +		struct kobject *engine_class_kobj =
> +			&dev_priv->gt_topology.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,
> +					   gt_kobj->ktype,
> +					   gt_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_id_attr);
> +			if (ret)
> +				return ret;
> +			ret = sysfs_create_file(&engine->instance_kobj,
> +						&engine_class_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_id_attr);
> +		sysfs_remove_file(&engine->instance_kobj, &engine_class_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.kobj,
> +				   kdev->kobj.ktype,
> +				   &kdev->kobj,
> +				   "gt");
> +	if (ret)
> +		return ret;
> +
> +	return i915_setup_engines_sysfs(dev_priv, &dev_priv->gt_topology.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.kobj);
> +	kobject_del(&dev_priv->gt_topology.kobj);
> +}
> +
>   void i915_setup_sysfs(struct drm_i915_private *dev_priv)
>   {
>   	struct device *kdev = dev_priv->drm.primary->kdev;
> @@ -605,6 +759,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 +772,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 9897c7f78c51..9d82dfbb45db 100644
> --- a/drivers/gpu/drm/i915/intel_engine_cs.c
> +++ b/drivers/gpu/drm/i915/intel_engine_cs.c
> @@ -133,6 +133,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 5f96533e5341..eca6c87a1e06 100644
> --- a/drivers/gpu/drm/i915/intel_ringbuffer.h
> +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
> @@ -290,6 +290,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;
> @@ -924,6 +927,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);
>   
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 4/4] drm/i915: expose EU topology through sysfs
  2017-11-20 12:23 ` [PATCH 4/4] drm/i915: expose EU topology " Lionel Landwerlin
@ 2017-11-20 16:13   ` Tvrtko Ursulin
  2017-11-20 16:54     ` Lionel Landwerlin
  0 siblings, 1 reply; 19+ messages in thread
From: Tvrtko Ursulin @ 2017-11-20 16:13 UTC (permalink / raw)
  To: Lionel Landwerlin, intel-gfx


On 20/11/2017 12:23, Lionel Landwerlin wrote:
> 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/rcs/0/
> ├── capabilities
> ├── class
> ├── id
> ├── 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

For the topology layout I don't feel like an expert. :(

Is it more correct for it to be per engine instance, or per class?

Should it go under the topology subdir?

Should there be a symlink from rcs/0/topology -> ../topology ?

Should the organization be with more subdirs like 
topology/slice/0/subslice/0/eus_enabled_mask?

Is (sub)slices_enabled_mask required/helpful or it can be inferred from 
enumerating the slices?

Same for max_slices? Or perhaps it is a different meaning than the 
enabled mask?

Sorry, this is not very constructive, more questions than answers... :(

Regards,

Tvrtko

> 
> Each enabled_mask file gives us a mask of the enabled units :
> 
> $ cat /sys/devices/pci0000\:00/0000\:00\:02.0/drm/card0/gt/rcs/0/slices_enabled_mask
> 0x7
> 
> $ cat /sys/devices/pci0000\:00/0000\:00\:02.0/drm/card0/gt/rcs/0/slice0/subslice2/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)
> 
> Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
> ---
>   drivers/gpu/drm/i915/i915_drv.h   |  26 ++++++
>   drivers/gpu/drm/i915/i915_sysfs.c | 188 ++++++++++++++++++++++++++++++++++++++
>   2 files changed, 214 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index db550322207c..1ac0a191e8fc 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;
>   
> @@ -2732,6 +2750,14 @@ struct drm_i915_private {
>   	struct {
>   		struct kobject kobj;
>   		struct kobject classes_kobjs[MAX_ENGINE_CLASS];
> +
> +		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 fd04d0b93eaf..df9d8fdbcb0a 100644
> --- a/drivers/gpu/drm/i915/i915_sysfs.c
> +++ b/drivers/gpu/drm/i915/i915_sysfs.c
> @@ -559,6 +559,174 @@ 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_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, "0x0\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, "0x0\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_kobj)
> +{
> +	const struct sseu_dev_info *sseu = &INTEL_INFO(dev_priv)->sseu;
> +	int ret, s, ss;
> +
> +	ret = sysfs_create_file(engine_kobj, &slices_enabled_mask_attr);
> +	if (ret)
> +		return ret;
> +
> +	ret = sysfs_create_file(engine_kobj, &max_slices_attr);
> +	if (ret)
> +		return ret;
> +
> +	ret = sysfs_create_file(engine_kobj, &max_subslices_per_slice_attr);
> +	if (ret)
> +		return ret;
> +
> +	ret = sysfs_create_file(engine_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,
> +					   engine_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,
> +					     struct kobject *engine_kobj)
> +{
> +	const struct sseu_dev_info *sseu = &INTEL_INFO(dev_priv)->sseu;
> +	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(engine_kobj, &slices_enabled_mask_attr);
> +	sysfs_remove_file(engine_kobj, &max_eus_per_subslice_attr);
> +	sysfs_remove_file(engine_kobj, &max_subslices_per_slice_attr);
> +	sysfs_remove_file(engine_kobj, &max_slices_attr);
> +}
> +
>   static struct attribute engine_id_attr = {
>   	.name = "id",
>   	.mode = 0444,
> @@ -574,11 +742,20 @@ 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);
> +	const struct sseu_dev_info *sseu = &INTEL_INFO(engine->i915)->sseu;
>   
>   	if (attr == &engine_id_attr)
>   		return sprintf(buf, "%hhu\n", engine->uabi_id);
>   	if (attr == &engine_class_attr)
>   		return sprintf(buf, "%hhu\n", engine->uabi_class);
> +	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");
>   }
>   
> @@ -671,6 +848,12 @@ static int i915_setup_engines_sysfs(struct drm_i915_private *dev_priv,
>   				if (ret)
>   					return ret;
>   			}
> +			if (engine->id == RCS) {
> +				ret = i915_setup_rcs_topology_sysfs(dev_priv,
> +								    &engine->instance_kobj);
> +				if (ret)
> +					return ret;
> +			}
>   		}
>   	}
>   
> @@ -683,6 +866,11 @@ static void i915_teardown_engines_sysfs(struct drm_i915_private *dev_priv)
>   	enum intel_engine_id id;
>   
>   	for_each_engine(engine, dev_priv, id) {
> +		if (id == RCS) {
> +			i915_teardown_rcs_topology_sysfs(dev_priv,
> +							 &engine->instance_kobj);
> +		}
> +
>   		sysfs_remove_file(&engine->instance_kobj, &engine_id_attr);
>   		sysfs_remove_file(&engine->instance_kobj, &engine_class_attr);
>   		sysfs_remove_file(&engine->capabilities_kobj,
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 3/4] drm/i915: expose engine availability through sysfs
  2017-11-20 16:03   ` Tvrtko Ursulin
@ 2017-11-20 16:33     ` Lionel Landwerlin
  2017-11-20 17:08       ` Tvrtko Ursulin
  0 siblings, 1 reply; 19+ messages in thread
From: Lionel Landwerlin @ 2017-11-20 16:33 UTC (permalink / raw)
  To: Tvrtko Ursulin, intel-gfx

On 20/11/17 16:03, Tvrtko Ursulin wrote:
> - I would need engine->instance here as well. 
Sure.
I thought that wasn't uabi though.
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 4/4] drm/i915: expose EU topology through sysfs
  2017-11-20 16:13   ` Tvrtko Ursulin
@ 2017-11-20 16:54     ` Lionel Landwerlin
  0 siblings, 0 replies; 19+ messages in thread
From: Lionel Landwerlin @ 2017-11-20 16:54 UTC (permalink / raw)
  To: Tvrtko Ursulin, intel-gfx

On 20/11/17 16:13, Tvrtko Ursulin wrote:
>
> On 20/11/2017 12:23, Lionel Landwerlin wrote:
>> 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/rcs/0/
>> ├── capabilities
>> ├── class
>> ├── id
>> ├── 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
>
> For the topology layout I don't feel like an expert. :(
>
> Is it more correct for it to be per engine instance, or per class?

I think you have a point here.
As far as I can tell this is only one sets of slices. So I guess it 
should be at the class level.

>
> Should it go under the topology subdir?
>
> Should there be a symlink from rcs/0/topology -> ../topology ?

Yeah, sounds good to me.

>
> Should the organization be with more subdirs like 
> topology/slice/0/subslice/0/eus_enabled_mask?

I would leave it slice0/subslice0/... for now and if it becomes more 
crowded, create slice/<id>/subslice/<id> with links for backward 
compatibility.
I don't think we're going to expose a lot of properties.

>
> Is (sub)slices_enabled_mask required/helpful or it can be inferred 
> from enumerating the slices?

For simplicity in the kernel & userspace, it's helpful.
It makes the reading of the structure simpler.

>
> Same for max_slices? Or perhaps it is a different meaning than the 
> enabled mask?

That is essentially to help out userspace.
Most application will use a flat structure to access this information 
with a couple of strides.
The max_* fields gives the strides.

>
> Sorry, this is not very constructive, more questions than answers... :(

An outside opinion always raises interesting questions :)
Thanks!

>
> Regards,
>
> Tvrtko
>
>>
>> Each enabled_mask file gives us a mask of the enabled units :
>>
>> $ cat 
>> /sys/devices/pci0000\:00/0000\:00\:02.0/drm/card0/gt/rcs/0/slices_enabled_mask
>> 0x7
>>
>> $ cat 
>> /sys/devices/pci0000\:00/0000\:00\:02.0/drm/card0/gt/rcs/0/slice0/subslice2/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)
>>
>> Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
>> ---
>>   drivers/gpu/drm/i915/i915_drv.h   |  26 ++++++
>>   drivers/gpu/drm/i915/i915_sysfs.c | 188 
>> ++++++++++++++++++++++++++++++++++++++
>>   2 files changed, 214 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/i915/i915_drv.h 
>> b/drivers/gpu/drm/i915/i915_drv.h
>> index db550322207c..1ac0a191e8fc 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;
>>   @@ -2732,6 +2750,14 @@ struct drm_i915_private {
>>       struct {
>>           struct kobject kobj;
>>           struct kobject classes_kobjs[MAX_ENGINE_CLASS];
>> +
>> +        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 fd04d0b93eaf..df9d8fdbcb0a 100644
>> --- a/drivers/gpu/drm/i915/i915_sysfs.c
>> +++ b/drivers/gpu/drm/i915/i915_sysfs.c
>> @@ -559,6 +559,174 @@ 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_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, "0x0\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, "0x0\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_kobj)
>> +{
>> +    const struct sseu_dev_info *sseu = &INTEL_INFO(dev_priv)->sseu;
>> +    int ret, s, ss;
>> +
>> +    ret = sysfs_create_file(engine_kobj, &slices_enabled_mask_attr);
>> +    if (ret)
>> +        return ret;
>> +
>> +    ret = sysfs_create_file(engine_kobj, &max_slices_attr);
>> +    if (ret)
>> +        return ret;
>> +
>> +    ret = sysfs_create_file(engine_kobj, 
>> &max_subslices_per_slice_attr);
>> +    if (ret)
>> +        return ret;
>> +
>> +    ret = sysfs_create_file(engine_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,
>> +                       engine_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,
>> +                         struct kobject *engine_kobj)
>> +{
>> +    const struct sseu_dev_info *sseu = &INTEL_INFO(dev_priv)->sseu;
>> +    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(engine_kobj, &slices_enabled_mask_attr);
>> +    sysfs_remove_file(engine_kobj, &max_eus_per_subslice_attr);
>> +    sysfs_remove_file(engine_kobj, &max_subslices_per_slice_attr);
>> +    sysfs_remove_file(engine_kobj, &max_slices_attr);
>> +}
>> +
>>   static struct attribute engine_id_attr = {
>>       .name = "id",
>>       .mode = 0444,
>> @@ -574,11 +742,20 @@ 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);
>> +    const struct sseu_dev_info *sseu = &INTEL_INFO(engine->i915)->sseu;
>>         if (attr == &engine_id_attr)
>>           return sprintf(buf, "%hhu\n", engine->uabi_id);
>>       if (attr == &engine_class_attr)
>>           return sprintf(buf, "%hhu\n", engine->uabi_class);
>> +    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");
>>   }
>>   @@ -671,6 +848,12 @@ static int i915_setup_engines_sysfs(struct 
>> drm_i915_private *dev_priv,
>>                   if (ret)
>>                       return ret;
>>               }
>> +            if (engine->id == RCS) {
>> +                ret = i915_setup_rcs_topology_sysfs(dev_priv,
>> + &engine->instance_kobj);
>> +                if (ret)
>> +                    return ret;
>> +            }
>>           }
>>       }
>>   @@ -683,6 +866,11 @@ static void i915_teardown_engines_sysfs(struct 
>> drm_i915_private *dev_priv)
>>       enum intel_engine_id id;
>>         for_each_engine(engine, dev_priv, id) {
>> +        if (id == RCS) {
>> +            i915_teardown_rcs_topology_sysfs(dev_priv,
>> +                             &engine->instance_kobj);
>> +        }
>> +
>>           sysfs_remove_file(&engine->instance_kobj, &engine_id_attr);
>>           sysfs_remove_file(&engine->instance_kobj, &engine_class_attr);
>>           sysfs_remove_file(&engine->capabilities_kobj,
>>
>

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

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

* Re: [PATCH 3/4] drm/i915: expose engine availability through sysfs
  2017-11-20 16:33     ` Lionel Landwerlin
@ 2017-11-20 17:08       ` Tvrtko Ursulin
  0 siblings, 0 replies; 19+ messages in thread
From: Tvrtko Ursulin @ 2017-11-20 17:08 UTC (permalink / raw)
  To: Lionel Landwerlin, intel-gfx



On 20/11/2017 16:33, Lionel Landwerlin wrote:
> On 20/11/17 16:03, Tvrtko Ursulin wrote:
>> - I would need engine->instance here as well. 
> Sure.
> I thought that wasn't uabi though.

Then again engine->instance is already there as the containing directory 
name. So do I need it in a separate file, not sure.. so many questions, 
so little time.. :)

Regards,

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

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

* Re: [PATCH 3/4] drm/i915: expose engine availability through sysfs
  2017-11-20 15:57   ` Tvrtko Ursulin
@ 2017-11-21 12:41     ` Ewelina Musial
  0 siblings, 0 replies; 19+ messages in thread
From: Ewelina Musial @ 2017-11-21 12:41 UTC (permalink / raw)
  To: Tvrtko Ursulin; +Cc: intel-gfx

On Mon, Nov 20, 2017 at 03:57:49PM +0000, Tvrtko Ursulin wrote:
> 
> On 20/11/2017 12:23, Lionel Landwerlin wrote:
> > 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
> > ├── bcs
> 
> It niggles me a bit that engine class names are directly under gt. If we end
> up having to add something else under gt then it will be a little bit of an
> enumeration trouble for userspace.
> 
> So I wanted to suggest gt/engines/rcs if that makes sense to people?
> 
> Regards,
> 
> Tvrtko
> 
Good suggestion.  After adding anything else to gt/ will be more clearly.

--
Cheers,
Ewelina
> > │   └── 0
> > │       ├── capabilities
> > │       ├── class
> > │       └── id
> > ├── rcs
> > │   └── 0
> > │       ├── capabilities
> > │       ├── class
> > │       └── id
> > ├── vcs
> > │   ├── 0
> > │   │   ├── capabilities
> > │   │   │   └── hevc
> > │   │   ├── class
> > │   │   └── id
> > │   └── 1
> > │       ├── capabilities
> > │       ├── class
> > │       └── id
> > └── vecs
> >      └── 0
> >          ├── capabilities
> >          ├── class
> >          └── id
> > 
> > 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)
> > 
> > Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
> > ---
> >   drivers/gpu/drm/i915/i915_drv.h         |   5 +
> >   drivers/gpu/drm/i915/i915_reg.h         |   1 +
> >   drivers/gpu/drm/i915/i915_sysfs.c       | 160 ++++++++++++++++++++++++++++++++
> >   drivers/gpu/drm/i915/intel_engine_cs.c  |  12 +++
> >   drivers/gpu/drm/i915/intel_ringbuffer.h |   4 +
> >   5 files changed, 182 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> > index 78c49db4280a..db550322207c 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.h
> > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > @@ -2729,6 +2729,11 @@ struct drm_i915_private {
> >   		} oa;
> >   	} perf;
> > +	struct {
> > +		struct kobject kobj;
> > +		struct kobject 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_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> > index 96c80fa0fcac..17aecd4fc6aa 100644
> > --- a/drivers/gpu/drm/i915/i915_reg.h
> > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > @@ -186,6 +186,7 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
> >   #define VIDEO_ENHANCEMENT_CLASS	2
> >   #define COPY_ENGINE_CLASS	3
> >   #define OTHER_CLASS		4
> > +#define MAX_ENGINE_CLASS	5
> >   /* PCI config space */
> > diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
> > index 791759f632e1..fd04d0b93eaf 100644
> > --- a/drivers/gpu/drm/i915/i915_sysfs.c
> > +++ b/drivers/gpu/drm/i915/i915_sysfs.c
> > @@ -559,6 +559,160 @@ static void i915_setup_error_capture(struct device *kdev) {}
> >   static void i915_teardown_error_capture(struct device *kdev) {}
> >   #endif
> > +static struct attribute engine_id_attr = {
> > +	.name = "id",
> > +	.mode = 0444,
> > +};
> > +
> > +static struct attribute engine_class_attr = {
> > +	.name = "class",
> > +	.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_id_attr)
> > +		return sprintf(buf, "%hhu\n", engine->uabi_id);
> > +	if (attr == &engine_class_attr)
> > +		return sprintf(buf, "%hhu\n", engine->uabi_class);
> > +	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;
> > +	bool registred[MAX_ENGINE_CLASS] = { false, };
> > +	int ret;
> > +
> > +	for_each_engine(engine_for_class, dev_priv, id_for_class) {
> > +		struct kobject *engine_class_kobj =
> > +			&dev_priv->gt_topology.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,
> > +					   gt_kobj->ktype,
> > +					   gt_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_id_attr);
> > +			if (ret)
> > +				return ret;
> > +			ret = sysfs_create_file(&engine->instance_kobj,
> > +						&engine_class_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_id_attr);
> > +		sysfs_remove_file(&engine->instance_kobj, &engine_class_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.kobj,
> > +				   kdev->kobj.ktype,
> > +				   &kdev->kobj,
> > +				   "gt");
> > +	if (ret)
> > +		return ret;
> > +
> > +	return i915_setup_engines_sysfs(dev_priv, &dev_priv->gt_topology.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.kobj);
> > +	kobject_del(&dev_priv->gt_topology.kobj);
> > +}
> > +
> >   void i915_setup_sysfs(struct drm_i915_private *dev_priv)
> >   {
> >   	struct device *kdev = dev_priv->drm.primary->kdev;
> > @@ -605,6 +759,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 +772,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 9897c7f78c51..9d82dfbb45db 100644
> > --- a/drivers/gpu/drm/i915/intel_engine_cs.c
> > +++ b/drivers/gpu/drm/i915/intel_engine_cs.c
> > @@ -133,6 +133,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 5f96533e5341..eca6c87a1e06 100644
> > --- a/drivers/gpu/drm/i915/intel_ringbuffer.h
> > +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
> > @@ -290,6 +290,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;
> > @@ -924,6 +927,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);
> > 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 3/4] drm/i915: expose engine availability through sysfs
  2017-11-20 12:23 ` [PATCH 3/4] drm/i915: expose engine availability through sysfs Lionel Landwerlin
  2017-11-20 15:57   ` Tvrtko Ursulin
  2017-11-20 16:03   ` Tvrtko Ursulin
@ 2017-11-28 18:17   ` Tvrtko Ursulin
  2017-11-28 20:56     ` Chris Wilson
  2 siblings, 1 reply; 19+ messages in thread
From: Tvrtko Ursulin @ 2017-11-28 18:17 UTC (permalink / raw)
  To: Lionel Landwerlin, intel-gfx


On 20/11/2017 12:23, Lionel Landwerlin wrote:
> 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

On this one I think Joonas had a concern that it is difficult for
userspace to get to the sysfs root from the drm file descriptor.

Lionel pointed out that for master nodes it is quite easy:

fstat(fd, &st);
sprintf(sysfs_root, "/sys/dev/char/%u:%u", major(st.st_rdev), minor(st.st_rdev));

For render nodes it is trickier in a way that they would have to
additional resolve an unknown master drm card number. For instance:

/sys/dev/char/%u:%u/device/drm/cardX

Where the "X" is unknown.

But, is it even an use case for render nodes to try and get to the
sysfs root of the master card? Are they allowed to do so?

Regards,

Tvrtko


> ├── bcs
> │   └── 0
> │       ├── capabilities
> │       ├── class
> │       └── id
> ├── rcs
> │   └── 0
> │       ├── capabilities
> │       ├── class
> │       └── id
> ├── vcs
> │   ├── 0
> │   │   ├── capabilities
> │   │   │   └── hevc
> │   │   ├── class
> │   │   └── id
> │   └── 1
> │       ├── capabilities
> │       ├── class
> │       └── id
> └── vecs
>      └── 0
>          ├── capabilities
>          ├── class
>          └── id
> 
> 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)
> 
> Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
> ---
>   drivers/gpu/drm/i915/i915_drv.h         |   5 +
>   drivers/gpu/drm/i915/i915_reg.h         |   1 +
>   drivers/gpu/drm/i915/i915_sysfs.c       | 160 ++++++++++++++++++++++++++++++++
>   drivers/gpu/drm/i915/intel_engine_cs.c  |  12 +++
>   drivers/gpu/drm/i915/intel_ringbuffer.h |   4 +
>   5 files changed, 182 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 78c49db4280a..db550322207c 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -2729,6 +2729,11 @@ struct drm_i915_private {
>   		} oa;
>   	} perf;
>   
> +	struct {
> +		struct kobject kobj;
> +		struct kobject 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_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 96c80fa0fcac..17aecd4fc6aa 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -186,6 +186,7 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
>   #define VIDEO_ENHANCEMENT_CLASS	2
>   #define COPY_ENGINE_CLASS	3
>   #define OTHER_CLASS		4
> +#define MAX_ENGINE_CLASS	5
>   
>   /* PCI config space */
>   
> diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
> index 791759f632e1..fd04d0b93eaf 100644
> --- a/drivers/gpu/drm/i915/i915_sysfs.c
> +++ b/drivers/gpu/drm/i915/i915_sysfs.c
> @@ -559,6 +559,160 @@ static void i915_setup_error_capture(struct device *kdev) {}
>   static void i915_teardown_error_capture(struct device *kdev) {}
>   #endif
>   
> +static struct attribute engine_id_attr = {
> +	.name = "id",
> +	.mode = 0444,
> +};
> +
> +static struct attribute engine_class_attr = {
> +	.name = "class",
> +	.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_id_attr)
> +		return sprintf(buf, "%hhu\n", engine->uabi_id);
> +	if (attr == &engine_class_attr)
> +		return sprintf(buf, "%hhu\n", engine->uabi_class);
> +	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;
> +	bool registred[MAX_ENGINE_CLASS] = { false, };
> +	int ret;
> +
> +	for_each_engine(engine_for_class, dev_priv, id_for_class) {
> +		struct kobject *engine_class_kobj =
> +			&dev_priv->gt_topology.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,
> +					   gt_kobj->ktype,
> +					   gt_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_id_attr);
> +			if (ret)
> +				return ret;
> +			ret = sysfs_create_file(&engine->instance_kobj,
> +						&engine_class_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_id_attr);
> +		sysfs_remove_file(&engine->instance_kobj, &engine_class_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.kobj,
> +				   kdev->kobj.ktype,
> +				   &kdev->kobj,
> +				   "gt");
> +	if (ret)
> +		return ret;
> +
> +	return i915_setup_engines_sysfs(dev_priv, &dev_priv->gt_topology.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.kobj);
> +	kobject_del(&dev_priv->gt_topology.kobj);
> +}
> +
>   void i915_setup_sysfs(struct drm_i915_private *dev_priv)
>   {
>   	struct device *kdev = dev_priv->drm.primary->kdev;
> @@ -605,6 +759,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 +772,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 9897c7f78c51..9d82dfbb45db 100644
> --- a/drivers/gpu/drm/i915/intel_engine_cs.c
> +++ b/drivers/gpu/drm/i915/intel_engine_cs.c
> @@ -133,6 +133,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 5f96533e5341..eca6c87a1e06 100644
> --- a/drivers/gpu/drm/i915/intel_ringbuffer.h
> +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
> @@ -290,6 +290,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;
> @@ -924,6 +927,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);
>   
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 3/4] drm/i915: expose engine availability through sysfs
  2017-11-28 18:17   ` Tvrtko Ursulin
@ 2017-11-28 20:56     ` Chris Wilson
  2017-11-28 21:39       ` Chris Wilson
  0 siblings, 1 reply; 19+ messages in thread
From: Chris Wilson @ 2017-11-28 20:56 UTC (permalink / raw)
  To: Tvrtko Ursulin, Lionel Landwerlin, intel-gfx

Quoting Tvrtko Ursulin (2017-11-28 18:17:54)
> 
> On 20/11/2017 12:23, Lionel Landwerlin wrote:
> > 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
> 
> On this one I think Joonas had a concern that it is difficult for
> userspace to get to the sysfs root from the drm file descriptor.
> 
> Lionel pointed out that for master nodes it is quite easy:
> 
> fstat(fd, &st);
> sprintf(sysfs_root, "/sys/dev/char/%u:%u", major(st.st_rdev), minor(st.st_rdev));
> 
> For render nodes it is trickier in a way that they would have to
> additional resolve an unknown master drm card number. For instance:
> 
> /sys/dev/char/%u:%u/device/drm/cardX
> 
> Where the "X" is unknown.
> 
> But, is it even an use case for render nodes to try and get to the
> sysfs root of the master card? Are they allowed to do so?

Yes. Mesa uses render nodes, and mesa needs the topology for its
performance monitoring api.
-Chris
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 3/4] drm/i915: expose engine availability through sysfs
  2017-11-28 20:56     ` Chris Wilson
@ 2017-11-28 21:39       ` Chris Wilson
  2017-11-29  8:39         ` Tvrtko Ursulin
  0 siblings, 1 reply; 19+ messages in thread
From: Chris Wilson @ 2017-11-28 21:39 UTC (permalink / raw)
  To: Tvrtko Ursulin, Lionel Landwerlin, intel-gfx

Quoting Chris Wilson (2017-11-28 20:56:23)
> Quoting Tvrtko Ursulin (2017-11-28 18:17:54)
> > 
> > On 20/11/2017 12:23, Lionel Landwerlin wrote:
> > > 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
> > 
> > On this one I think Joonas had a concern that it is difficult for
> > userspace to get to the sysfs root from the drm file descriptor.
> > 
> > Lionel pointed out that for master nodes it is quite easy:
> > 
> > fstat(fd, &st);
> > sprintf(sysfs_root, "/sys/dev/char/%u:%u", major(st.st_rdev), minor(st.st_rdev));
> > 
> > For render nodes it is trickier in a way that they would have to
> > additional resolve an unknown master drm card number. For instance:
> > 
> > /sys/dev/char/%u:%u/device/drm/cardX
> > 
> > Where the "X" is unknown.
> > 
> > But, is it even an use case for render nodes to try and get to the
> > sysfs root of the master card? Are they allowed to do so?
> 
> Yes. Mesa uses render nodes, and mesa needs the topology for its
> performance monitoring api.

So /sys/dev/char/226:128/ does not link to /sys/dev/char/226:0/. Maybe
we should just add a card symlink from each minor back to our sysfs
root? That seems doable.

Then we just need open("/sys/dev/char/%u:%u/card");
-Chris
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 3/4] drm/i915: expose engine availability through sysfs
  2017-11-28 21:39       ` Chris Wilson
@ 2017-11-29  8:39         ` Tvrtko Ursulin
  0 siblings, 0 replies; 19+ messages in thread
From: Tvrtko Ursulin @ 2017-11-29  8:39 UTC (permalink / raw)
  To: Chris Wilson, Lionel Landwerlin, intel-gfx


On 28/11/2017 21:39, Chris Wilson wrote:
> Quoting Chris Wilson (2017-11-28 20:56:23)
>> Quoting Tvrtko Ursulin (2017-11-28 18:17:54)
>>>
>>> On 20/11/2017 12:23, Lionel Landwerlin wrote:
>>>> 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
>>>
>>> On this one I think Joonas had a concern that it is difficult for
>>> userspace to get to the sysfs root from the drm file descriptor.
>>>
>>> Lionel pointed out that for master nodes it is quite easy:
>>>
>>> fstat(fd, &st);
>>> sprintf(sysfs_root, "/sys/dev/char/%u:%u", major(st.st_rdev), minor(st.st_rdev));
>>>
>>> For render nodes it is trickier in a way that they would have to
>>> additional resolve an unknown master drm card number. For instance:
>>>
>>> /sys/dev/char/%u:%u/device/drm/cardX
>>>
>>> Where the "X" is unknown.
>>>
>>> But, is it even an use case for render nodes to try and get to the
>>> sysfs root of the master card? Are they allowed to do so?
>>
>> Yes. Mesa uses render nodes, and mesa needs the topology for its
>> performance monitoring api.
> 
> So /sys/dev/char/226:128/ does not link to /sys/dev/char/226:0/. Maybe
> we should just add a card symlink from each minor back to our sysfs
> root? That seems doable.
> 
> Then we just need open("/sys/dev/char/%u:%u/card");

There is a link via what I wrote above - 
"/sys/dev/char/%u:%u/device/drm/cardX", but the "X" part is cumbersome.

Adding a link with a constant name would indeed be better, but I wasn't 
sure if it is conceptually allowed and even forgot to mention it.

Regards,

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

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

* [PATCH 0/4] drm/i915: Expose more GPU properties through sysfs
@ 2017-11-16 16:00 Lionel Landwerlin
  0 siblings, 0 replies; 19+ messages in thread
From: Lionel Landwerlin @ 2017-11-16 16:00 UTC (permalink / raw)
  To: intel-gfx

Hi all,

Based on feedback on previous series by Tvrtko & myself, here is a
series that exposes EU topology & engines availability through sysfs.

Cheers,

Lionel Landwerlin (4):
  drm/i915: store all subslice masks
  drm/i915/debugfs: reuse max slice/subslices already stored in sseu
  drm/i915: expose EU topology through sysfs
  drm/i915: expose engine availability 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          |  54 ++++++-
 drivers/gpu/drm/i915/i915_sysfs.c        | 251 +++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_device_info.c | 169 +++++++++++++++------
 drivers/gpu/drm/i915/intel_lrc.c         |   2 +-
 drivers/gpu/drm/i915/intel_ringbuffer.h  |   4 +-
 7 files changed, 455 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] 19+ messages in thread

end of thread, other threads:[~2017-11-29  8:39 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-11-20 12:23 [PATCH 0/4] drm/i915: Expose more GPU properties through sysfs Lionel Landwerlin
2017-11-20 12:23 ` [PATCH 1/4] drm/i915: store all subslice masks Lionel Landwerlin
2017-11-20 12:23 ` [PATCH 2/4] drm/i915/debugfs: reuse max slice/subslices already stored in sseu Lionel Landwerlin
2017-11-20 12:23 ` [PATCH 3/4] drm/i915: expose engine availability through sysfs Lionel Landwerlin
2017-11-20 15:57   ` Tvrtko Ursulin
2017-11-21 12:41     ` Ewelina Musial
2017-11-20 16:03   ` Tvrtko Ursulin
2017-11-20 16:33     ` Lionel Landwerlin
2017-11-20 17:08       ` Tvrtko Ursulin
2017-11-28 18:17   ` Tvrtko Ursulin
2017-11-28 20:56     ` Chris Wilson
2017-11-28 21:39       ` Chris Wilson
2017-11-29  8:39         ` Tvrtko Ursulin
2017-11-20 12:23 ` [PATCH 4/4] drm/i915: expose EU topology " Lionel Landwerlin
2017-11-20 16:13   ` Tvrtko Ursulin
2017-11-20 16:54     ` Lionel Landwerlin
2017-11-20 12:45 ` ✓ Fi.CI.BAT: success for drm/i915: Expose more GPU properties through sysfs (rev3) Patchwork
2017-11-20 13:33 ` ✓ Fi.CI.IGT: " Patchwork
  -- strict thread matches above, loose matches on Subject: below --
2017-11-16 16:00 [PATCH 0/4] drm/i915: Expose more GPU properties through sysfs Lionel Landwerlin

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.