All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/5] i915: SSEU handling updates
@ 2022-04-27 23:07 ` Matt Roper
  0 siblings, 0 replies; 27+ messages in thread
From: Matt Roper @ 2022-04-27 23:07 UTC (permalink / raw)
  To: intel-gfx; +Cc: tvrtko.ursulin, dri-devel

This series makes a handful of updates to i915's internal handling of
slice/subslice/EU (SSEU) data to handle recent platforms like Xe_HP in a
more natural manner and to prepare for some additional upcoming
platforms we have in the pipeline (the first of which I'll probably
start sending patches for in the next week or two).  One key idea of
this series is that although we have a fixed ABI to convey SSEU data to
userspace (i.e., multiple u8[] arrays with data stored at different
strides), we don't need to use this cumbersome format for the driver's
own internal storage.  As long as we can convert into the uapi form
properly when responding to the I915_QUERY ioctl, it's preferable to use
an internal storage format that's easier for the driver to work with.
Doing so can also save us some storage space on modern platforms since
we don't always need to replicate a bunch of data that's architecturally
guaranteed to be identical.

Another key point here is that Xe_HP platforms today have subslice (DSS)
masks that are 32 bits, which maxes out the storage of a u32.  On future
platforms the architecture design is going to start spreading their DSS
masks over multiple 32-bit fuse registers.  So even for platforms where
the total number of DSS doesn't actually go up, we're going to need
larger storage than just a u32 to express the mask properly.  To
accomodate this, we start storing our subslice mask in a new typedef
that can be processed by the linux/bitmap.h operations.

Finally, since no userspace for Xe_HP or beyond is using the legacy
I915_GETPARAM ioctl lookups for I915_PARAM_SLICE_MASK and
I915_PARAM_SUBSLICE_MASK (since they've migrated to the more flexible
I915_QUERY ioctl that can return more than a simple u32 value), we take
the opportunity to officially drop support for those GETPARAM lookups on
modern platforms.  Maintaining support for these GETPARAM lookups don't
make sense for a number of reasons:

 * Traditional slices no longer exist, and newer ideas like gslices,
   cslices, mslices, etc. aren't something userspace needs to query
   since it can be inferred from other information.
 * The GETPARAM ioctl doesn't have a way to distinguish between geometry
   subslice masks and compute subslice masks, which are distinct on
   Xe_HP and beyond.
 * The I915_GETPARAM ioctl is limited to returning a 32-bit value, so
   when subslice masks begin to exceed 32-bits, it simply can't return
   the entire mask.
 * The GETPARAM ioctl doesn't have a way to give sensible information
   for multi-tile devices.


Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>

Matt Roper (5):
  drm/i915/sseu: Don't try to store EU mask internally in UAPI format
  drm/i915/xehp: Drop GETPARAM lookups of I915_PARAM_[SUB]SLICE_MASK
  drm/i915/xehp: Use separate sseu init function
  drm/i915/sseu: Simplify gen11+ SSEU handling
  drm/i915/sseu: Disassociate internal subslice mask representation from
    uapi

 drivers/gpu/drm/i915/gem/i915_gem_context.c  |   4 +-
 drivers/gpu/drm/i915/gt/intel_engine_cs.c    |   2 +-
 drivers/gpu/drm/i915/gt/intel_gt.c           |  14 +-
 drivers/gpu/drm/i915/gt/intel_sseu.c         | 371 +++++++++++--------
 drivers/gpu/drm/i915/gt/intel_sseu.h         |  69 ++--
 drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c |  28 +-
 drivers/gpu/drm/i915/gt/intel_workarounds.c  |  28 +-
 drivers/gpu/drm/i915/i915_getparam.c         |  10 +-
 drivers/gpu/drm/i915/i915_query.c            |  16 +-
 9 files changed, 323 insertions(+), 219 deletions(-)

-- 
2.35.1


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

* [Intel-gfx] [PATCH 0/5] i915: SSEU handling updates
@ 2022-04-27 23:07 ` Matt Roper
  0 siblings, 0 replies; 27+ messages in thread
From: Matt Roper @ 2022-04-27 23:07 UTC (permalink / raw)
  To: intel-gfx; +Cc: dri-devel

This series makes a handful of updates to i915's internal handling of
slice/subslice/EU (SSEU) data to handle recent platforms like Xe_HP in a
more natural manner and to prepare for some additional upcoming
platforms we have in the pipeline (the first of which I'll probably
start sending patches for in the next week or two).  One key idea of
this series is that although we have a fixed ABI to convey SSEU data to
userspace (i.e., multiple u8[] arrays with data stored at different
strides), we don't need to use this cumbersome format for the driver's
own internal storage.  As long as we can convert into the uapi form
properly when responding to the I915_QUERY ioctl, it's preferable to use
an internal storage format that's easier for the driver to work with.
Doing so can also save us some storage space on modern platforms since
we don't always need to replicate a bunch of data that's architecturally
guaranteed to be identical.

Another key point here is that Xe_HP platforms today have subslice (DSS)
masks that are 32 bits, which maxes out the storage of a u32.  On future
platforms the architecture design is going to start spreading their DSS
masks over multiple 32-bit fuse registers.  So even for platforms where
the total number of DSS doesn't actually go up, we're going to need
larger storage than just a u32 to express the mask properly.  To
accomodate this, we start storing our subslice mask in a new typedef
that can be processed by the linux/bitmap.h operations.

Finally, since no userspace for Xe_HP or beyond is using the legacy
I915_GETPARAM ioctl lookups for I915_PARAM_SLICE_MASK and
I915_PARAM_SUBSLICE_MASK (since they've migrated to the more flexible
I915_QUERY ioctl that can return more than a simple u32 value), we take
the opportunity to officially drop support for those GETPARAM lookups on
modern platforms.  Maintaining support for these GETPARAM lookups don't
make sense for a number of reasons:

 * Traditional slices no longer exist, and newer ideas like gslices,
   cslices, mslices, etc. aren't something userspace needs to query
   since it can be inferred from other information.
 * The GETPARAM ioctl doesn't have a way to distinguish between geometry
   subslice masks and compute subslice masks, which are distinct on
   Xe_HP and beyond.
 * The I915_GETPARAM ioctl is limited to returning a 32-bit value, so
   when subslice masks begin to exceed 32-bits, it simply can't return
   the entire mask.
 * The GETPARAM ioctl doesn't have a way to give sensible information
   for multi-tile devices.


Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>

Matt Roper (5):
  drm/i915/sseu: Don't try to store EU mask internally in UAPI format
  drm/i915/xehp: Drop GETPARAM lookups of I915_PARAM_[SUB]SLICE_MASK
  drm/i915/xehp: Use separate sseu init function
  drm/i915/sseu: Simplify gen11+ SSEU handling
  drm/i915/sseu: Disassociate internal subslice mask representation from
    uapi

 drivers/gpu/drm/i915/gem/i915_gem_context.c  |   4 +-
 drivers/gpu/drm/i915/gt/intel_engine_cs.c    |   2 +-
 drivers/gpu/drm/i915/gt/intel_gt.c           |  14 +-
 drivers/gpu/drm/i915/gt/intel_sseu.c         | 371 +++++++++++--------
 drivers/gpu/drm/i915/gt/intel_sseu.h         |  69 ++--
 drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c |  28 +-
 drivers/gpu/drm/i915/gt/intel_workarounds.c  |  28 +-
 drivers/gpu/drm/i915/i915_getparam.c         |  10 +-
 drivers/gpu/drm/i915/i915_query.c            |  16 +-
 9 files changed, 323 insertions(+), 219 deletions(-)

-- 
2.35.1


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

* [PATCH 1/5] drm/i915/sseu: Don't try to store EU mask internally in UAPI format
  2022-04-27 23:07 ` [Intel-gfx] " Matt Roper
@ 2022-04-27 23:07   ` Matt Roper
  -1 siblings, 0 replies; 27+ messages in thread
From: Matt Roper @ 2022-04-27 23:07 UTC (permalink / raw)
  To: intel-gfx; +Cc: tvrtko.ursulin, dri-devel

Storing the EU mask internally in the same format the I915_QUERY
topology queries use makes the final copy_to_user() a bit simpler, but
makes the rest of the driver's SSEU more complicated.  Given that modern
platforms (gen11 and beyond) are architecturally guaranteed to have
equivalent EU masks for every subslice, it also wastes quite a bit of
space since we're storing a duplicate copy of the EU mask for every
single subslice where we really only need to store one instance.

Let's add a has_common_ss_eumask flag to the SSEU structure to determine
which type of hardware we're working on.  For the older pre-gen11
platforms the various subslices can have different EU masks so we use an
array of u16[] to store each subslice's copy.  For gen11 and beyond
we'll only use index [0] of the array and not worry about copying the
repeated value, except when converting into uapi form for the I915_QUERY
ioctl.

Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
---
 drivers/gpu/drm/i915/gt/intel_sseu.c | 66 +++++++++++++++++++++-------
 drivers/gpu/drm/i915/gt/intel_sseu.h | 21 ++++++++-
 drivers/gpu/drm/i915/i915_query.c    |  8 ++--
 3 files changed, 73 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/intel_sseu.c b/drivers/gpu/drm/i915/gt/intel_sseu.c
index 9881a6790574..13387b4024ea 100644
--- a/drivers/gpu/drm/i915/gt/intel_sseu.c
+++ b/drivers/gpu/drm/i915/gt/intel_sseu.c
@@ -91,36 +91,70 @@ static int sseu_eu_idx(const struct sseu_dev_info *sseu, int slice,
 static u16 sseu_get_eus(const struct sseu_dev_info *sseu, int slice,
 			int subslice)
 {
-	int i, offset = sseu_eu_idx(sseu, slice, subslice);
-	u16 eu_mask = 0;
-
-	for (i = 0; i < sseu->eu_stride; i++)
-		eu_mask |=
-			((u16)sseu->eu_mask[offset + i]) << (i * BITS_PER_BYTE);
+	if (!intel_sseu_has_subslice(sseu, slice, subslice))
+		return 0;
 
-	return eu_mask;
+	if (sseu->has_common_ss_eumask)
+		return sseu->eu_mask[0];
+	else
+		return sseu->eu_mask[slice * sseu->max_subslices + subslice];
 }
 
 static void sseu_set_eus(struct sseu_dev_info *sseu, int slice, int subslice,
 			 u16 eu_mask)
 {
-	int i, offset = sseu_eu_idx(sseu, slice, subslice);
+	WARN_ON(sseu->has_common_ss_eumask);
+	WARN_ON(sseu->max_eus_per_subslice > sizeof(sseu->eu_mask[0]) * BITS_PER_BYTE);
 
-	for (i = 0; i < sseu->eu_stride; i++)
-		sseu->eu_mask[offset + i] =
-			(eu_mask >> (BITS_PER_BYTE * i)) & 0xff;
+	sseu->eu_mask[slice * sseu->max_subslices + subslice] =
+		eu_mask & GENMASK(sseu->max_eus_per_subslice - 1, 0);
 }
 
 static u16 compute_eu_total(const struct sseu_dev_info *sseu)
 {
 	u16 i, total = 0;
 
+	if (sseu->has_common_ss_eumask)
+		return intel_sseu_subslices_per_slice(sseu, 0) *
+			hweight16(sseu->eu_mask[0]);
+
 	for (i = 0; i < ARRAY_SIZE(sseu->eu_mask); i++)
-		total += hweight8(sseu->eu_mask[i]);
+		total += hweight16(sseu->eu_mask[i]);
 
 	return total;
 }
 
+/**
+ * intel_sseu_copy_eumask_to_user - Copy EU mask into a userspace buffer
+ * @to: Pointer to userspace buffer to copy to
+ * @sseu: SSEU structure containing EU mask to copy
+ *
+ * Copies the EU mask to a userspace buffer in the format expected by
+ * the query ioctl's topology queries.
+ *
+ * Returns the result of the copy_to_user() operation.
+ */
+int intel_sseu_copy_eumask_to_user(void __user *to,
+				   const struct sseu_dev_info *sseu)
+{
+	u8 eu_mask[GEN_SS_MASK_SIZE * GEN_MAX_EU_STRIDE] = {};
+	int len = sseu->max_slices * sseu->max_subslices * sseu->eu_stride;
+	int s, ss, i;
+
+	for (s = 0; s < sseu->max_slices; s++) {
+		for (ss = 0; ss < sseu->max_subslices; ss++) {
+			int offset = sseu_eu_idx(sseu, s, ss);
+			u16 mask = sseu_get_eus(sseu, s, ss);
+
+			for (i = 0; i < sseu->eu_stride; i++)
+				eu_mask[offset + i] =
+					(mask >> (BITS_PER_BYTE * i)) & 0xff;
+		}
+	}
+
+	return copy_to_user(to, eu_mask, len);
+}
+
 static u32 get_ss_stride_mask(struct sseu_dev_info *sseu, u8 s, u32 ss_en)
 {
 	u32 ss_mask;
@@ -134,7 +168,7 @@ static u32 get_ss_stride_mask(struct sseu_dev_info *sseu, u8 s, u32 ss_en)
 static void gen11_compute_sseu_info(struct sseu_dev_info *sseu, u8 s_en,
 				    u32 g_ss_en, u32 c_ss_en, u16 eu_en)
 {
-	int s, ss;
+	int s;
 
 	/* g_ss_en/c_ss_en represent entire subslice mask across all slices */
 	GEM_BUG_ON(sseu->max_slices * sseu->max_subslices >
@@ -162,11 +196,9 @@ static void gen11_compute_sseu_info(struct sseu_dev_info *sseu, u8 s_en,
 		intel_sseu_set_subslices(sseu, s, sseu->subslice_mask,
 					 get_ss_stride_mask(sseu, s,
 							    g_ss_en | c_ss_en));
-
-		for (ss = 0; ss < sseu->max_subslices; ss++)
-			if (intel_sseu_has_subslice(sseu, s, ss))
-				sseu_set_eus(sseu, s, ss, eu_en);
 	}
+	sseu->has_common_ss_eumask = 1;
+	sseu->eu_mask[0] = eu_en;
 	sseu->eu_per_subslice = hweight16(eu_en);
 	sseu->eu_total = compute_eu_total(sseu);
 }
diff --git a/drivers/gpu/drm/i915/gt/intel_sseu.h b/drivers/gpu/drm/i915/gt/intel_sseu.h
index 5c078df4729c..106726a2244e 100644
--- a/drivers/gpu/drm/i915/gt/intel_sseu.h
+++ b/drivers/gpu/drm/i915/gt/intel_sseu.h
@@ -57,7 +57,21 @@ struct sseu_dev_info {
 	u8 subslice_mask[GEN_SS_MASK_SIZE];
 	u8 geometry_subslice_mask[GEN_SS_MASK_SIZE];
 	u8 compute_subslice_mask[GEN_SS_MASK_SIZE];
-	u8 eu_mask[GEN_SS_MASK_SIZE * GEN_MAX_EU_STRIDE];
+
+	/*
+	 * EU masks.  Use has_common_ss_eumask to determine how the field
+	 * will be interpreted.
+	 *
+	 * On pre-gen11 platforms, each subslice has independent EU fusing, so
+	 * we store an array of u16's that are sufficient to represent each
+	 * subslice's EU mask on pre-gen11 platforms.
+	 *
+	 * For gen11 and beyond, all subslices will always have the same set of
+	 * enabled/disabled EUs so only eu_mask[0] is utilized; all other array
+	 * entries are ignored.
+	 */
+	u16 eu_mask[GEN_MAX_HSW_SLICES * GEN_MAX_SS_PER_HSW_SLICE];
+
 	u16 eu_total;
 	u8 eu_per_subslice;
 	u8 min_eu_in_pool;
@@ -66,6 +80,8 @@ struct sseu_dev_info {
 	u8 has_slice_pg:1;
 	u8 has_subslice_pg:1;
 	u8 has_eu_pg:1;
+	/* All subslices have the same set of enabled/disabled EUs? */
+	u8 has_common_ss_eumask:1;
 
 	/* Topology fields */
 	u8 max_slices;
@@ -145,4 +161,7 @@ void intel_sseu_print_topology(struct drm_i915_private *i915,
 
 u16 intel_slicemask_from_dssmask(u64 dss_mask, int dss_per_slice);
 
+int intel_sseu_copy_eumask_to_user(void __user *to,
+				   const struct sseu_dev_info *sseu);
+
 #endif /* __INTEL_SSEU_H__ */
diff --git a/drivers/gpu/drm/i915/i915_query.c b/drivers/gpu/drm/i915/i915_query.c
index 7584cec53d5d..16f43bf32a05 100644
--- a/drivers/gpu/drm/i915/i915_query.c
+++ b/drivers/gpu/drm/i915/i915_query.c
@@ -76,10 +76,10 @@ static int fill_topology_info(const struct sseu_dev_info *sseu,
 			 subslice_mask, subslice_length))
 		return -EFAULT;
 
-	if (copy_to_user(u64_to_user_ptr(query_item->data_ptr +
-					 sizeof(topo) +
-					 slice_length + subslice_length),
-			 sseu->eu_mask, eu_length))
+	if (intel_sseu_copy_eumask_to_user(u64_to_user_ptr(query_item->data_ptr +
+							   sizeof(topo) +
+							   slice_length + subslice_length),
+					   sseu))
 		return -EFAULT;
 
 	return total_length;
-- 
2.35.1


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

* [Intel-gfx] [PATCH 1/5] drm/i915/sseu: Don't try to store EU mask internally in UAPI format
@ 2022-04-27 23:07   ` Matt Roper
  0 siblings, 0 replies; 27+ messages in thread
From: Matt Roper @ 2022-04-27 23:07 UTC (permalink / raw)
  To: intel-gfx; +Cc: dri-devel

Storing the EU mask internally in the same format the I915_QUERY
topology queries use makes the final copy_to_user() a bit simpler, but
makes the rest of the driver's SSEU more complicated.  Given that modern
platforms (gen11 and beyond) are architecturally guaranteed to have
equivalent EU masks for every subslice, it also wastes quite a bit of
space since we're storing a duplicate copy of the EU mask for every
single subslice where we really only need to store one instance.

Let's add a has_common_ss_eumask flag to the SSEU structure to determine
which type of hardware we're working on.  For the older pre-gen11
platforms the various subslices can have different EU masks so we use an
array of u16[] to store each subslice's copy.  For gen11 and beyond
we'll only use index [0] of the array and not worry about copying the
repeated value, except when converting into uapi form for the I915_QUERY
ioctl.

Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
---
 drivers/gpu/drm/i915/gt/intel_sseu.c | 66 +++++++++++++++++++++-------
 drivers/gpu/drm/i915/gt/intel_sseu.h | 21 ++++++++-
 drivers/gpu/drm/i915/i915_query.c    |  8 ++--
 3 files changed, 73 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/intel_sseu.c b/drivers/gpu/drm/i915/gt/intel_sseu.c
index 9881a6790574..13387b4024ea 100644
--- a/drivers/gpu/drm/i915/gt/intel_sseu.c
+++ b/drivers/gpu/drm/i915/gt/intel_sseu.c
@@ -91,36 +91,70 @@ static int sseu_eu_idx(const struct sseu_dev_info *sseu, int slice,
 static u16 sseu_get_eus(const struct sseu_dev_info *sseu, int slice,
 			int subslice)
 {
-	int i, offset = sseu_eu_idx(sseu, slice, subslice);
-	u16 eu_mask = 0;
-
-	for (i = 0; i < sseu->eu_stride; i++)
-		eu_mask |=
-			((u16)sseu->eu_mask[offset + i]) << (i * BITS_PER_BYTE);
+	if (!intel_sseu_has_subslice(sseu, slice, subslice))
+		return 0;
 
-	return eu_mask;
+	if (sseu->has_common_ss_eumask)
+		return sseu->eu_mask[0];
+	else
+		return sseu->eu_mask[slice * sseu->max_subslices + subslice];
 }
 
 static void sseu_set_eus(struct sseu_dev_info *sseu, int slice, int subslice,
 			 u16 eu_mask)
 {
-	int i, offset = sseu_eu_idx(sseu, slice, subslice);
+	WARN_ON(sseu->has_common_ss_eumask);
+	WARN_ON(sseu->max_eus_per_subslice > sizeof(sseu->eu_mask[0]) * BITS_PER_BYTE);
 
-	for (i = 0; i < sseu->eu_stride; i++)
-		sseu->eu_mask[offset + i] =
-			(eu_mask >> (BITS_PER_BYTE * i)) & 0xff;
+	sseu->eu_mask[slice * sseu->max_subslices + subslice] =
+		eu_mask & GENMASK(sseu->max_eus_per_subslice - 1, 0);
 }
 
 static u16 compute_eu_total(const struct sseu_dev_info *sseu)
 {
 	u16 i, total = 0;
 
+	if (sseu->has_common_ss_eumask)
+		return intel_sseu_subslices_per_slice(sseu, 0) *
+			hweight16(sseu->eu_mask[0]);
+
 	for (i = 0; i < ARRAY_SIZE(sseu->eu_mask); i++)
-		total += hweight8(sseu->eu_mask[i]);
+		total += hweight16(sseu->eu_mask[i]);
 
 	return total;
 }
 
+/**
+ * intel_sseu_copy_eumask_to_user - Copy EU mask into a userspace buffer
+ * @to: Pointer to userspace buffer to copy to
+ * @sseu: SSEU structure containing EU mask to copy
+ *
+ * Copies the EU mask to a userspace buffer in the format expected by
+ * the query ioctl's topology queries.
+ *
+ * Returns the result of the copy_to_user() operation.
+ */
+int intel_sseu_copy_eumask_to_user(void __user *to,
+				   const struct sseu_dev_info *sseu)
+{
+	u8 eu_mask[GEN_SS_MASK_SIZE * GEN_MAX_EU_STRIDE] = {};
+	int len = sseu->max_slices * sseu->max_subslices * sseu->eu_stride;
+	int s, ss, i;
+
+	for (s = 0; s < sseu->max_slices; s++) {
+		for (ss = 0; ss < sseu->max_subslices; ss++) {
+			int offset = sseu_eu_idx(sseu, s, ss);
+			u16 mask = sseu_get_eus(sseu, s, ss);
+
+			for (i = 0; i < sseu->eu_stride; i++)
+				eu_mask[offset + i] =
+					(mask >> (BITS_PER_BYTE * i)) & 0xff;
+		}
+	}
+
+	return copy_to_user(to, eu_mask, len);
+}
+
 static u32 get_ss_stride_mask(struct sseu_dev_info *sseu, u8 s, u32 ss_en)
 {
 	u32 ss_mask;
@@ -134,7 +168,7 @@ static u32 get_ss_stride_mask(struct sseu_dev_info *sseu, u8 s, u32 ss_en)
 static void gen11_compute_sseu_info(struct sseu_dev_info *sseu, u8 s_en,
 				    u32 g_ss_en, u32 c_ss_en, u16 eu_en)
 {
-	int s, ss;
+	int s;
 
 	/* g_ss_en/c_ss_en represent entire subslice mask across all slices */
 	GEM_BUG_ON(sseu->max_slices * sseu->max_subslices >
@@ -162,11 +196,9 @@ static void gen11_compute_sseu_info(struct sseu_dev_info *sseu, u8 s_en,
 		intel_sseu_set_subslices(sseu, s, sseu->subslice_mask,
 					 get_ss_stride_mask(sseu, s,
 							    g_ss_en | c_ss_en));
-
-		for (ss = 0; ss < sseu->max_subslices; ss++)
-			if (intel_sseu_has_subslice(sseu, s, ss))
-				sseu_set_eus(sseu, s, ss, eu_en);
 	}
+	sseu->has_common_ss_eumask = 1;
+	sseu->eu_mask[0] = eu_en;
 	sseu->eu_per_subslice = hweight16(eu_en);
 	sseu->eu_total = compute_eu_total(sseu);
 }
diff --git a/drivers/gpu/drm/i915/gt/intel_sseu.h b/drivers/gpu/drm/i915/gt/intel_sseu.h
index 5c078df4729c..106726a2244e 100644
--- a/drivers/gpu/drm/i915/gt/intel_sseu.h
+++ b/drivers/gpu/drm/i915/gt/intel_sseu.h
@@ -57,7 +57,21 @@ struct sseu_dev_info {
 	u8 subslice_mask[GEN_SS_MASK_SIZE];
 	u8 geometry_subslice_mask[GEN_SS_MASK_SIZE];
 	u8 compute_subslice_mask[GEN_SS_MASK_SIZE];
-	u8 eu_mask[GEN_SS_MASK_SIZE * GEN_MAX_EU_STRIDE];
+
+	/*
+	 * EU masks.  Use has_common_ss_eumask to determine how the field
+	 * will be interpreted.
+	 *
+	 * On pre-gen11 platforms, each subslice has independent EU fusing, so
+	 * we store an array of u16's that are sufficient to represent each
+	 * subslice's EU mask on pre-gen11 platforms.
+	 *
+	 * For gen11 and beyond, all subslices will always have the same set of
+	 * enabled/disabled EUs so only eu_mask[0] is utilized; all other array
+	 * entries are ignored.
+	 */
+	u16 eu_mask[GEN_MAX_HSW_SLICES * GEN_MAX_SS_PER_HSW_SLICE];
+
 	u16 eu_total;
 	u8 eu_per_subslice;
 	u8 min_eu_in_pool;
@@ -66,6 +80,8 @@ struct sseu_dev_info {
 	u8 has_slice_pg:1;
 	u8 has_subslice_pg:1;
 	u8 has_eu_pg:1;
+	/* All subslices have the same set of enabled/disabled EUs? */
+	u8 has_common_ss_eumask:1;
 
 	/* Topology fields */
 	u8 max_slices;
@@ -145,4 +161,7 @@ void intel_sseu_print_topology(struct drm_i915_private *i915,
 
 u16 intel_slicemask_from_dssmask(u64 dss_mask, int dss_per_slice);
 
+int intel_sseu_copy_eumask_to_user(void __user *to,
+				   const struct sseu_dev_info *sseu);
+
 #endif /* __INTEL_SSEU_H__ */
diff --git a/drivers/gpu/drm/i915/i915_query.c b/drivers/gpu/drm/i915/i915_query.c
index 7584cec53d5d..16f43bf32a05 100644
--- a/drivers/gpu/drm/i915/i915_query.c
+++ b/drivers/gpu/drm/i915/i915_query.c
@@ -76,10 +76,10 @@ static int fill_topology_info(const struct sseu_dev_info *sseu,
 			 subslice_mask, subslice_length))
 		return -EFAULT;
 
-	if (copy_to_user(u64_to_user_ptr(query_item->data_ptr +
-					 sizeof(topo) +
-					 slice_length + subslice_length),
-			 sseu->eu_mask, eu_length))
+	if (intel_sseu_copy_eumask_to_user(u64_to_user_ptr(query_item->data_ptr +
+							   sizeof(topo) +
+							   slice_length + subslice_length),
+					   sseu))
 		return -EFAULT;
 
 	return total_length;
-- 
2.35.1


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

* [PATCH 2/5] drm/i915/xehp: Drop GETPARAM lookups of I915_PARAM_[SUB]SLICE_MASK
  2022-04-27 23:07 ` [Intel-gfx] " Matt Roper
@ 2022-04-27 23:07   ` Matt Roper
  -1 siblings, 0 replies; 27+ messages in thread
From: Matt Roper @ 2022-04-27 23:07 UTC (permalink / raw)
  To: intel-gfx; +Cc: tvrtko.ursulin, dri-devel

Slice/subslice/EU information should be obtained via the topology
queries provided by the I915_QUERY interface; let's turn off support for
the old GETPARAM lookups on Xe_HP and beyond where we can't return
meaningful values.

The slice mask lookup is meaningless since Xe_HP doesn't support
traditional slices (and we make no attempt to return the various new
units like gslices, cslices, mslices, etc.) here.

The subslice mask lookup is even more problematic; given the distinct
masks for geometry vs compute purposes, the combined mask returned here
is likely not what userspace would want to act upon anyway.  The value
is also limited to 32-bits by the nature of the GETPARAM ioctl which is
sufficient for the initial Xe_HP platforms, but is unable to convey the
larger masks that will be needed on other upcoming platforms.  Finally,
the value returned here becomes even less meaningful when used on
multi-tile platforms where each tile will have its own masks.

Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
---
 drivers/gpu/drm/i915/i915_getparam.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_getparam.c b/drivers/gpu/drm/i915/i915_getparam.c
index c12a0adefda5..ac9767c56619 100644
--- a/drivers/gpu/drm/i915/i915_getparam.c
+++ b/drivers/gpu/drm/i915/i915_getparam.c
@@ -148,11 +148,19 @@ int i915_getparam_ioctl(struct drm_device *dev, void *data,
 		value = intel_engines_has_context_isolation(i915);
 		break;
 	case I915_PARAM_SLICE_MASK:
+		/* Not supported from Xe_HP onward; use topology queries */
+		if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50))
+			return -EINVAL;
+
 		value = sseu->slice_mask;
 		if (!value)
 			return -ENODEV;
 		break;
 	case I915_PARAM_SUBSLICE_MASK:
+		/* Not supported from Xe_HP onward; use topology queries */
+		if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50))
+			return -EINVAL;
+
 		/* Only copy bits from the first slice */
 		memcpy(&value, sseu->subslice_mask,
 		       min(sseu->ss_stride, (u8)sizeof(value)));
-- 
2.35.1


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

* [Intel-gfx] [PATCH 2/5] drm/i915/xehp: Drop GETPARAM lookups of I915_PARAM_[SUB]SLICE_MASK
@ 2022-04-27 23:07   ` Matt Roper
  0 siblings, 0 replies; 27+ messages in thread
From: Matt Roper @ 2022-04-27 23:07 UTC (permalink / raw)
  To: intel-gfx; +Cc: dri-devel

Slice/subslice/EU information should be obtained via the topology
queries provided by the I915_QUERY interface; let's turn off support for
the old GETPARAM lookups on Xe_HP and beyond where we can't return
meaningful values.

The slice mask lookup is meaningless since Xe_HP doesn't support
traditional slices (and we make no attempt to return the various new
units like gslices, cslices, mslices, etc.) here.

The subslice mask lookup is even more problematic; given the distinct
masks for geometry vs compute purposes, the combined mask returned here
is likely not what userspace would want to act upon anyway.  The value
is also limited to 32-bits by the nature of the GETPARAM ioctl which is
sufficient for the initial Xe_HP platforms, but is unable to convey the
larger masks that will be needed on other upcoming platforms.  Finally,
the value returned here becomes even less meaningful when used on
multi-tile platforms where each tile will have its own masks.

Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
---
 drivers/gpu/drm/i915/i915_getparam.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_getparam.c b/drivers/gpu/drm/i915/i915_getparam.c
index c12a0adefda5..ac9767c56619 100644
--- a/drivers/gpu/drm/i915/i915_getparam.c
+++ b/drivers/gpu/drm/i915/i915_getparam.c
@@ -148,11 +148,19 @@ int i915_getparam_ioctl(struct drm_device *dev, void *data,
 		value = intel_engines_has_context_isolation(i915);
 		break;
 	case I915_PARAM_SLICE_MASK:
+		/* Not supported from Xe_HP onward; use topology queries */
+		if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50))
+			return -EINVAL;
+
 		value = sseu->slice_mask;
 		if (!value)
 			return -ENODEV;
 		break;
 	case I915_PARAM_SUBSLICE_MASK:
+		/* Not supported from Xe_HP onward; use topology queries */
+		if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50))
+			return -EINVAL;
+
 		/* Only copy bits from the first slice */
 		memcpy(&value, sseu->subslice_mask,
 		       min(sseu->ss_stride, (u8)sizeof(value)));
-- 
2.35.1


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

* [PATCH 3/5] drm/i915/xehp: Use separate sseu init function
  2022-04-27 23:07 ` [Intel-gfx] " Matt Roper
@ 2022-04-27 23:07   ` Matt Roper
  -1 siblings, 0 replies; 27+ messages in thread
From: Matt Roper @ 2022-04-27 23:07 UTC (permalink / raw)
  To: intel-gfx; +Cc: tvrtko.ursulin, dri-devel

Xe_HP has enough fundamental differences from previous platforms that it
makes sense to use a separate SSEU init function to keep things
straightforward and easy to understand.

Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
---
 drivers/gpu/drm/i915/gt/intel_sseu.c | 85 ++++++++++++++++------------
 1 file changed, 48 insertions(+), 37 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/intel_sseu.c b/drivers/gpu/drm/i915/gt/intel_sseu.c
index 13387b4024ea..ef66c2b8861a 100644
--- a/drivers/gpu/drm/i915/gt/intel_sseu.c
+++ b/drivers/gpu/drm/i915/gt/intel_sseu.c
@@ -203,13 +203,42 @@ static void gen11_compute_sseu_info(struct sseu_dev_info *sseu, u8 s_en,
 	sseu->eu_total = compute_eu_total(sseu);
 }
 
-static void gen12_sseu_info_init(struct intel_gt *gt)
+static void xehp_sseu_info_init(struct intel_gt *gt)
 {
 	struct sseu_dev_info *sseu = &gt->info.sseu;
 	struct intel_uncore *uncore = gt->uncore;
 	u32 g_dss_en, c_dss_en = 0;
 	u16 eu_en = 0;
 	u8 eu_en_fuse;
+	int eu;
+
+	/*
+	 * The concept of slice has been removed in Xe_HP.  To be compatible
+	 * with prior generations, assume a single slice across the entire
+	 * device. Then calculate out the DSS for each workload type within
+	 * that software slice.
+	 */
+	intel_sseu_set_info(sseu, 1, 32, 16);
+
+	g_dss_en = intel_uncore_read(uncore, GEN12_GT_GEOMETRY_DSS_ENABLE);
+	c_dss_en = intel_uncore_read(uncore, GEN12_GT_COMPUTE_DSS_ENABLE);
+
+	eu_en_fuse = intel_uncore_read(uncore, XEHP_EU_ENABLE) & XEHP_EU_ENA_MASK;
+
+	for (eu = 0; eu < sseu->max_eus_per_subslice / 2; eu++)
+		if (eu_en_fuse & BIT(eu))
+			eu_en |= BIT(eu * 2) | BIT(eu * 2 + 1);
+
+	gen11_compute_sseu_info(sseu, 0x1, g_dss_en, c_dss_en, eu_en);
+}
+
+static void gen12_sseu_info_init(struct intel_gt *gt)
+{
+	struct sseu_dev_info *sseu = &gt->info.sseu;
+	struct intel_uncore *uncore = gt->uncore;
+	u32 g_dss_en;
+	u16 eu_en = 0;
+	u8 eu_en_fuse;
 	u8 s_en;
 	int eu;
 
@@ -217,43 +246,23 @@ static void gen12_sseu_info_init(struct intel_gt *gt)
 	 * Gen12 has Dual-Subslices, which behave similarly to 2 gen11 SS.
 	 * Instead of splitting these, provide userspace with an array
 	 * of DSS to more closely represent the hardware resource.
-	 *
-	 * In addition, the concept of slice has been removed in Xe_HP.
-	 * To be compatible with prior generations, assume a single slice
-	 * across the entire device. Then calculate out the DSS for each
-	 * workload type within that software slice.
 	 */
-	if (IS_DG2(gt->i915) || IS_XEHPSDV(gt->i915))
-		intel_sseu_set_info(sseu, 1, 32, 16);
-	else
-		intel_sseu_set_info(sseu, 1, 6, 16);
+	intel_sseu_set_info(sseu, 1, 6, 16);
 
-	/*
-	 * As mentioned above, Xe_HP does not have the concept of a slice.
-	 * Enable one for software backwards compatibility.
-	 */
-	if (GRAPHICS_VER_FULL(gt->i915) >= IP_VER(12, 50))
-		s_en = 0x1;
-	else
-		s_en = intel_uncore_read(uncore, GEN11_GT_SLICE_ENABLE) &
-		       GEN11_GT_S_ENA_MASK;
+	s_en = intel_uncore_read(uncore, GEN11_GT_SLICE_ENABLE) &
+		GEN11_GT_S_ENA_MASK;
 
 	g_dss_en = intel_uncore_read(uncore, GEN12_GT_GEOMETRY_DSS_ENABLE);
-	if (GRAPHICS_VER_FULL(gt->i915) >= IP_VER(12, 50))
-		c_dss_en = intel_uncore_read(uncore, GEN12_GT_COMPUTE_DSS_ENABLE);
 
 	/* one bit per pair of EUs */
-	if (GRAPHICS_VER_FULL(gt->i915) >= IP_VER(12, 50))
-		eu_en_fuse = intel_uncore_read(uncore, XEHP_EU_ENABLE) & XEHP_EU_ENA_MASK;
-	else
-		eu_en_fuse = ~(intel_uncore_read(uncore, GEN11_EU_DISABLE) &
-			       GEN11_EU_DIS_MASK);
+	eu_en_fuse = ~(intel_uncore_read(uncore, GEN11_EU_DISABLE) &
+		       GEN11_EU_DIS_MASK);
 
 	for (eu = 0; eu < sseu->max_eus_per_subslice / 2; eu++)
 		if (eu_en_fuse & BIT(eu))
 			eu_en |= BIT(eu * 2) | BIT(eu * 2 + 1);
 
-	gen11_compute_sseu_info(sseu, s_en, g_dss_en, c_dss_en, eu_en);
+	gen11_compute_sseu_info(sseu, s_en, g_dss_en, 0, eu_en);
 
 	/* TGL only supports slice-level power gating */
 	sseu->has_slice_pg = 1;
@@ -608,18 +617,20 @@ void intel_sseu_info_init(struct intel_gt *gt)
 {
 	struct drm_i915_private *i915 = gt->i915;
 
-	if (IS_HASWELL(i915))
-		hsw_sseu_info_init(gt);
-	else if (IS_CHERRYVIEW(i915))
-		cherryview_sseu_info_init(gt);
-	else if (IS_BROADWELL(i915))
-		bdw_sseu_info_init(gt);
-	else if (GRAPHICS_VER(i915) == 9)
-		gen9_sseu_info_init(gt);
-	else if (GRAPHICS_VER(i915) == 11)
-		gen11_sseu_info_init(gt);
+	if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50))
+		xehp_sseu_info_init(gt);
 	else if (GRAPHICS_VER(i915) >= 12)
 		gen12_sseu_info_init(gt);
+	else if (GRAPHICS_VER(i915) >= 11)
+		gen11_sseu_info_init(gt);
+	else if (GRAPHICS_VER(i915) >= 9)
+		gen9_sseu_info_init(gt);
+	else if (IS_BROADWELL(i915))
+		bdw_sseu_info_init(gt);
+	else if (IS_CHERRYVIEW(i915))
+		cherryview_sseu_info_init(gt);
+	else if (IS_HASWELL(i915))
+		hsw_sseu_info_init(gt);
 }
 
 u32 intel_sseu_make_rpcs(struct intel_gt *gt,
-- 
2.35.1


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

* [Intel-gfx] [PATCH 3/5] drm/i915/xehp: Use separate sseu init function
@ 2022-04-27 23:07   ` Matt Roper
  0 siblings, 0 replies; 27+ messages in thread
From: Matt Roper @ 2022-04-27 23:07 UTC (permalink / raw)
  To: intel-gfx; +Cc: dri-devel

Xe_HP has enough fundamental differences from previous platforms that it
makes sense to use a separate SSEU init function to keep things
straightforward and easy to understand.

Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
---
 drivers/gpu/drm/i915/gt/intel_sseu.c | 85 ++++++++++++++++------------
 1 file changed, 48 insertions(+), 37 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/intel_sseu.c b/drivers/gpu/drm/i915/gt/intel_sseu.c
index 13387b4024ea..ef66c2b8861a 100644
--- a/drivers/gpu/drm/i915/gt/intel_sseu.c
+++ b/drivers/gpu/drm/i915/gt/intel_sseu.c
@@ -203,13 +203,42 @@ static void gen11_compute_sseu_info(struct sseu_dev_info *sseu, u8 s_en,
 	sseu->eu_total = compute_eu_total(sseu);
 }
 
-static void gen12_sseu_info_init(struct intel_gt *gt)
+static void xehp_sseu_info_init(struct intel_gt *gt)
 {
 	struct sseu_dev_info *sseu = &gt->info.sseu;
 	struct intel_uncore *uncore = gt->uncore;
 	u32 g_dss_en, c_dss_en = 0;
 	u16 eu_en = 0;
 	u8 eu_en_fuse;
+	int eu;
+
+	/*
+	 * The concept of slice has been removed in Xe_HP.  To be compatible
+	 * with prior generations, assume a single slice across the entire
+	 * device. Then calculate out the DSS for each workload type within
+	 * that software slice.
+	 */
+	intel_sseu_set_info(sseu, 1, 32, 16);
+
+	g_dss_en = intel_uncore_read(uncore, GEN12_GT_GEOMETRY_DSS_ENABLE);
+	c_dss_en = intel_uncore_read(uncore, GEN12_GT_COMPUTE_DSS_ENABLE);
+
+	eu_en_fuse = intel_uncore_read(uncore, XEHP_EU_ENABLE) & XEHP_EU_ENA_MASK;
+
+	for (eu = 0; eu < sseu->max_eus_per_subslice / 2; eu++)
+		if (eu_en_fuse & BIT(eu))
+			eu_en |= BIT(eu * 2) | BIT(eu * 2 + 1);
+
+	gen11_compute_sseu_info(sseu, 0x1, g_dss_en, c_dss_en, eu_en);
+}
+
+static void gen12_sseu_info_init(struct intel_gt *gt)
+{
+	struct sseu_dev_info *sseu = &gt->info.sseu;
+	struct intel_uncore *uncore = gt->uncore;
+	u32 g_dss_en;
+	u16 eu_en = 0;
+	u8 eu_en_fuse;
 	u8 s_en;
 	int eu;
 
@@ -217,43 +246,23 @@ static void gen12_sseu_info_init(struct intel_gt *gt)
 	 * Gen12 has Dual-Subslices, which behave similarly to 2 gen11 SS.
 	 * Instead of splitting these, provide userspace with an array
 	 * of DSS to more closely represent the hardware resource.
-	 *
-	 * In addition, the concept of slice has been removed in Xe_HP.
-	 * To be compatible with prior generations, assume a single slice
-	 * across the entire device. Then calculate out the DSS for each
-	 * workload type within that software slice.
 	 */
-	if (IS_DG2(gt->i915) || IS_XEHPSDV(gt->i915))
-		intel_sseu_set_info(sseu, 1, 32, 16);
-	else
-		intel_sseu_set_info(sseu, 1, 6, 16);
+	intel_sseu_set_info(sseu, 1, 6, 16);
 
-	/*
-	 * As mentioned above, Xe_HP does not have the concept of a slice.
-	 * Enable one for software backwards compatibility.
-	 */
-	if (GRAPHICS_VER_FULL(gt->i915) >= IP_VER(12, 50))
-		s_en = 0x1;
-	else
-		s_en = intel_uncore_read(uncore, GEN11_GT_SLICE_ENABLE) &
-		       GEN11_GT_S_ENA_MASK;
+	s_en = intel_uncore_read(uncore, GEN11_GT_SLICE_ENABLE) &
+		GEN11_GT_S_ENA_MASK;
 
 	g_dss_en = intel_uncore_read(uncore, GEN12_GT_GEOMETRY_DSS_ENABLE);
-	if (GRAPHICS_VER_FULL(gt->i915) >= IP_VER(12, 50))
-		c_dss_en = intel_uncore_read(uncore, GEN12_GT_COMPUTE_DSS_ENABLE);
 
 	/* one bit per pair of EUs */
-	if (GRAPHICS_VER_FULL(gt->i915) >= IP_VER(12, 50))
-		eu_en_fuse = intel_uncore_read(uncore, XEHP_EU_ENABLE) & XEHP_EU_ENA_MASK;
-	else
-		eu_en_fuse = ~(intel_uncore_read(uncore, GEN11_EU_DISABLE) &
-			       GEN11_EU_DIS_MASK);
+	eu_en_fuse = ~(intel_uncore_read(uncore, GEN11_EU_DISABLE) &
+		       GEN11_EU_DIS_MASK);
 
 	for (eu = 0; eu < sseu->max_eus_per_subslice / 2; eu++)
 		if (eu_en_fuse & BIT(eu))
 			eu_en |= BIT(eu * 2) | BIT(eu * 2 + 1);
 
-	gen11_compute_sseu_info(sseu, s_en, g_dss_en, c_dss_en, eu_en);
+	gen11_compute_sseu_info(sseu, s_en, g_dss_en, 0, eu_en);
 
 	/* TGL only supports slice-level power gating */
 	sseu->has_slice_pg = 1;
@@ -608,18 +617,20 @@ void intel_sseu_info_init(struct intel_gt *gt)
 {
 	struct drm_i915_private *i915 = gt->i915;
 
-	if (IS_HASWELL(i915))
-		hsw_sseu_info_init(gt);
-	else if (IS_CHERRYVIEW(i915))
-		cherryview_sseu_info_init(gt);
-	else if (IS_BROADWELL(i915))
-		bdw_sseu_info_init(gt);
-	else if (GRAPHICS_VER(i915) == 9)
-		gen9_sseu_info_init(gt);
-	else if (GRAPHICS_VER(i915) == 11)
-		gen11_sseu_info_init(gt);
+	if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50))
+		xehp_sseu_info_init(gt);
 	else if (GRAPHICS_VER(i915) >= 12)
 		gen12_sseu_info_init(gt);
+	else if (GRAPHICS_VER(i915) >= 11)
+		gen11_sseu_info_init(gt);
+	else if (GRAPHICS_VER(i915) >= 9)
+		gen9_sseu_info_init(gt);
+	else if (IS_BROADWELL(i915))
+		bdw_sseu_info_init(gt);
+	else if (IS_CHERRYVIEW(i915))
+		cherryview_sseu_info_init(gt);
+	else if (IS_HASWELL(i915))
+		hsw_sseu_info_init(gt);
 }
 
 u32 intel_sseu_make_rpcs(struct intel_gt *gt,
-- 
2.35.1


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

* [PATCH 4/5] drm/i915/sseu: Simplify gen11+ SSEU handling
  2022-04-27 23:07 ` [Intel-gfx] " Matt Roper
@ 2022-04-27 23:07   ` Matt Roper
  -1 siblings, 0 replies; 27+ messages in thread
From: Matt Roper @ 2022-04-27 23:07 UTC (permalink / raw)
  To: intel-gfx; +Cc: tvrtko.ursulin, dri-devel

Although gen11 and gen12 architectures supported the concept of multiple
slices, in practice all the platforms that were actually designed only
had a single slice (i.e., note the parameters to 'intel_sseu_set_info'
that we pass for each platform).  We can simplify the code slightly by
dropping the multi-slice logic from gen11+ platforms.

Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
---
 drivers/gpu/drm/i915/gt/intel_sseu.c | 73 ++++++++++++++--------------
 1 file changed, 36 insertions(+), 37 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/intel_sseu.c b/drivers/gpu/drm/i915/gt/intel_sseu.c
index ef66c2b8861a..f7ff6a9f67b0 100644
--- a/drivers/gpu/drm/i915/gt/intel_sseu.c
+++ b/drivers/gpu/drm/i915/gt/intel_sseu.c
@@ -155,48 +155,32 @@ int intel_sseu_copy_eumask_to_user(void __user *to,
 	return copy_to_user(to, eu_mask, len);
 }
 
-static u32 get_ss_stride_mask(struct sseu_dev_info *sseu, u8 s, u32 ss_en)
-{
-	u32 ss_mask;
-
-	ss_mask = ss_en >> (s * sseu->max_subslices);
-	ss_mask &= GENMASK(sseu->max_subslices - 1, 0);
-
-	return ss_mask;
-}
-
-static void gen11_compute_sseu_info(struct sseu_dev_info *sseu, u8 s_en,
+static void gen11_compute_sseu_info(struct sseu_dev_info *sseu,
 				    u32 g_ss_en, u32 c_ss_en, u16 eu_en)
 {
-	int s;
+	u32 valid_ss_mask = GENMASK(sseu->max_subslices - 1, 0);
 
 	/* g_ss_en/c_ss_en represent entire subslice mask across all slices */
 	GEM_BUG_ON(sseu->max_slices * sseu->max_subslices >
 		   sizeof(g_ss_en) * BITS_PER_BYTE);
 
-	for (s = 0; s < sseu->max_slices; s++) {
-		if ((s_en & BIT(s)) == 0)
-			continue;
+	sseu->slice_mask |= BIT(0);
+
+	/*
+	 * XeHP introduces the concept of compute vs geometry DSS. To reduce
+	 * variation between GENs around subslice usage, store a mask for both
+	 * the geometry and compute enabled masks since userspace will need to
+	 * be able to query these masks independently.  Also compute a total
+	 * enabled subslice count for the purposes of selecting subslices to
+	 * use in a particular GEM context.
+	 */
+	intel_sseu_set_subslices(sseu, 0, sseu->compute_subslice_mask,
+				 c_ss_en & valid_ss_mask);
+	intel_sseu_set_subslices(sseu, 0, sseu->geometry_subslice_mask,
+				 g_ss_en & valid_ss_mask);
+	intel_sseu_set_subslices(sseu, 0, sseu->subslice_mask,
+				 (g_ss_en | c_ss_en) & valid_ss_mask);
 
-		sseu->slice_mask |= BIT(s);
-
-		/*
-		 * XeHP introduces the concept of compute vs geometry DSS. To
-		 * reduce variation between GENs around subslice usage, store a
-		 * mask for both the geometry and compute enabled masks since
-		 * userspace will need to be able to query these masks
-		 * independently.  Also compute a total enabled subslice count
-		 * for the purposes of selecting subslices to use in a
-		 * particular GEM context.
-		 */
-		intel_sseu_set_subslices(sseu, s, sseu->compute_subslice_mask,
-					 get_ss_stride_mask(sseu, s, c_ss_en));
-		intel_sseu_set_subslices(sseu, s, sseu->geometry_subslice_mask,
-					 get_ss_stride_mask(sseu, s, g_ss_en));
-		intel_sseu_set_subslices(sseu, s, sseu->subslice_mask,
-					 get_ss_stride_mask(sseu, s,
-							    g_ss_en | c_ss_en));
-	}
 	sseu->has_common_ss_eumask = 1;
 	sseu->eu_mask[0] = eu_en;
 	sseu->eu_per_subslice = hweight16(eu_en);
@@ -229,7 +213,7 @@ static void xehp_sseu_info_init(struct intel_gt *gt)
 		if (eu_en_fuse & BIT(eu))
 			eu_en |= BIT(eu * 2) | BIT(eu * 2 + 1);
 
-	gen11_compute_sseu_info(sseu, 0x1, g_dss_en, c_dss_en, eu_en);
+	gen11_compute_sseu_info(sseu, g_dss_en, c_dss_en, eu_en);
 }
 
 static void gen12_sseu_info_init(struct intel_gt *gt)
@@ -249,8 +233,15 @@ static void gen12_sseu_info_init(struct intel_gt *gt)
 	 */
 	intel_sseu_set_info(sseu, 1, 6, 16);
 
+	/*
+	 * Although gen12 architecture supported multiple slices, TGL, RKL,
+	 * DG1, and ADL only had a single slice.
+	 */
 	s_en = intel_uncore_read(uncore, GEN11_GT_SLICE_ENABLE) &
 		GEN11_GT_S_ENA_MASK;
+	if (s_en != 0x1)
+		drm_dbg(&gt->i915->drm, "Slice mask %#x is not the expected 0x1!\n",
+			s_en);
 
 	g_dss_en = intel_uncore_read(uncore, GEN12_GT_GEOMETRY_DSS_ENABLE);
 
@@ -262,7 +253,7 @@ static void gen12_sseu_info_init(struct intel_gt *gt)
 		if (eu_en_fuse & BIT(eu))
 			eu_en |= BIT(eu * 2) | BIT(eu * 2 + 1);
 
-	gen11_compute_sseu_info(sseu, s_en, g_dss_en, 0, eu_en);
+	gen11_compute_sseu_info(sseu, g_dss_en, 0, eu_en);
 
 	/* TGL only supports slice-level power gating */
 	sseu->has_slice_pg = 1;
@@ -281,14 +272,22 @@ static void gen11_sseu_info_init(struct intel_gt *gt)
 	else
 		intel_sseu_set_info(sseu, 1, 8, 8);
 
+	/*
+	 * Although gen11 architecture supported multiple slices, ICL and
+	 * EHL/JSL only had a single slice in practice.
+	 */
 	s_en = intel_uncore_read(uncore, GEN11_GT_SLICE_ENABLE) &
 		GEN11_GT_S_ENA_MASK;
+	if (s_en != 0x1)
+		drm_dbg(&gt->i915->drm, "Slice mask %#x is not the expected 0x1!\n",
+			s_en);
+
 	ss_en = ~intel_uncore_read(uncore, GEN11_GT_SUBSLICE_DISABLE);
 
 	eu_en = ~(intel_uncore_read(uncore, GEN11_EU_DISABLE) &
 		  GEN11_EU_DIS_MASK);
 
-	gen11_compute_sseu_info(sseu, s_en, ss_en, 0, eu_en);
+	gen11_compute_sseu_info(sseu, ss_en, 0, eu_en);
 
 	/* ICL has no power gating restrictions. */
 	sseu->has_slice_pg = 1;
-- 
2.35.1


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

* [Intel-gfx] [PATCH 4/5] drm/i915/sseu: Simplify gen11+ SSEU handling
@ 2022-04-27 23:07   ` Matt Roper
  0 siblings, 0 replies; 27+ messages in thread
From: Matt Roper @ 2022-04-27 23:07 UTC (permalink / raw)
  To: intel-gfx; +Cc: dri-devel

Although gen11 and gen12 architectures supported the concept of multiple
slices, in practice all the platforms that were actually designed only
had a single slice (i.e., note the parameters to 'intel_sseu_set_info'
that we pass for each platform).  We can simplify the code slightly by
dropping the multi-slice logic from gen11+ platforms.

Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
---
 drivers/gpu/drm/i915/gt/intel_sseu.c | 73 ++++++++++++++--------------
 1 file changed, 36 insertions(+), 37 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/intel_sseu.c b/drivers/gpu/drm/i915/gt/intel_sseu.c
index ef66c2b8861a..f7ff6a9f67b0 100644
--- a/drivers/gpu/drm/i915/gt/intel_sseu.c
+++ b/drivers/gpu/drm/i915/gt/intel_sseu.c
@@ -155,48 +155,32 @@ int intel_sseu_copy_eumask_to_user(void __user *to,
 	return copy_to_user(to, eu_mask, len);
 }
 
-static u32 get_ss_stride_mask(struct sseu_dev_info *sseu, u8 s, u32 ss_en)
-{
-	u32 ss_mask;
-
-	ss_mask = ss_en >> (s * sseu->max_subslices);
-	ss_mask &= GENMASK(sseu->max_subslices - 1, 0);
-
-	return ss_mask;
-}
-
-static void gen11_compute_sseu_info(struct sseu_dev_info *sseu, u8 s_en,
+static void gen11_compute_sseu_info(struct sseu_dev_info *sseu,
 				    u32 g_ss_en, u32 c_ss_en, u16 eu_en)
 {
-	int s;
+	u32 valid_ss_mask = GENMASK(sseu->max_subslices - 1, 0);
 
 	/* g_ss_en/c_ss_en represent entire subslice mask across all slices */
 	GEM_BUG_ON(sseu->max_slices * sseu->max_subslices >
 		   sizeof(g_ss_en) * BITS_PER_BYTE);
 
-	for (s = 0; s < sseu->max_slices; s++) {
-		if ((s_en & BIT(s)) == 0)
-			continue;
+	sseu->slice_mask |= BIT(0);
+
+	/*
+	 * XeHP introduces the concept of compute vs geometry DSS. To reduce
+	 * variation between GENs around subslice usage, store a mask for both
+	 * the geometry and compute enabled masks since userspace will need to
+	 * be able to query these masks independently.  Also compute a total
+	 * enabled subslice count for the purposes of selecting subslices to
+	 * use in a particular GEM context.
+	 */
+	intel_sseu_set_subslices(sseu, 0, sseu->compute_subslice_mask,
+				 c_ss_en & valid_ss_mask);
+	intel_sseu_set_subslices(sseu, 0, sseu->geometry_subslice_mask,
+				 g_ss_en & valid_ss_mask);
+	intel_sseu_set_subslices(sseu, 0, sseu->subslice_mask,
+				 (g_ss_en | c_ss_en) & valid_ss_mask);
 
-		sseu->slice_mask |= BIT(s);
-
-		/*
-		 * XeHP introduces the concept of compute vs geometry DSS. To
-		 * reduce variation between GENs around subslice usage, store a
-		 * mask for both the geometry and compute enabled masks since
-		 * userspace will need to be able to query these masks
-		 * independently.  Also compute a total enabled subslice count
-		 * for the purposes of selecting subslices to use in a
-		 * particular GEM context.
-		 */
-		intel_sseu_set_subslices(sseu, s, sseu->compute_subslice_mask,
-					 get_ss_stride_mask(sseu, s, c_ss_en));
-		intel_sseu_set_subslices(sseu, s, sseu->geometry_subslice_mask,
-					 get_ss_stride_mask(sseu, s, g_ss_en));
-		intel_sseu_set_subslices(sseu, s, sseu->subslice_mask,
-					 get_ss_stride_mask(sseu, s,
-							    g_ss_en | c_ss_en));
-	}
 	sseu->has_common_ss_eumask = 1;
 	sseu->eu_mask[0] = eu_en;
 	sseu->eu_per_subslice = hweight16(eu_en);
@@ -229,7 +213,7 @@ static void xehp_sseu_info_init(struct intel_gt *gt)
 		if (eu_en_fuse & BIT(eu))
 			eu_en |= BIT(eu * 2) | BIT(eu * 2 + 1);
 
-	gen11_compute_sseu_info(sseu, 0x1, g_dss_en, c_dss_en, eu_en);
+	gen11_compute_sseu_info(sseu, g_dss_en, c_dss_en, eu_en);
 }
 
 static void gen12_sseu_info_init(struct intel_gt *gt)
@@ -249,8 +233,15 @@ static void gen12_sseu_info_init(struct intel_gt *gt)
 	 */
 	intel_sseu_set_info(sseu, 1, 6, 16);
 
+	/*
+	 * Although gen12 architecture supported multiple slices, TGL, RKL,
+	 * DG1, and ADL only had a single slice.
+	 */
 	s_en = intel_uncore_read(uncore, GEN11_GT_SLICE_ENABLE) &
 		GEN11_GT_S_ENA_MASK;
+	if (s_en != 0x1)
+		drm_dbg(&gt->i915->drm, "Slice mask %#x is not the expected 0x1!\n",
+			s_en);
 
 	g_dss_en = intel_uncore_read(uncore, GEN12_GT_GEOMETRY_DSS_ENABLE);
 
@@ -262,7 +253,7 @@ static void gen12_sseu_info_init(struct intel_gt *gt)
 		if (eu_en_fuse & BIT(eu))
 			eu_en |= BIT(eu * 2) | BIT(eu * 2 + 1);
 
-	gen11_compute_sseu_info(sseu, s_en, g_dss_en, 0, eu_en);
+	gen11_compute_sseu_info(sseu, g_dss_en, 0, eu_en);
 
 	/* TGL only supports slice-level power gating */
 	sseu->has_slice_pg = 1;
@@ -281,14 +272,22 @@ static void gen11_sseu_info_init(struct intel_gt *gt)
 	else
 		intel_sseu_set_info(sseu, 1, 8, 8);
 
+	/*
+	 * Although gen11 architecture supported multiple slices, ICL and
+	 * EHL/JSL only had a single slice in practice.
+	 */
 	s_en = intel_uncore_read(uncore, GEN11_GT_SLICE_ENABLE) &
 		GEN11_GT_S_ENA_MASK;
+	if (s_en != 0x1)
+		drm_dbg(&gt->i915->drm, "Slice mask %#x is not the expected 0x1!\n",
+			s_en);
+
 	ss_en = ~intel_uncore_read(uncore, GEN11_GT_SUBSLICE_DISABLE);
 
 	eu_en = ~(intel_uncore_read(uncore, GEN11_EU_DISABLE) &
 		  GEN11_EU_DIS_MASK);
 
-	gen11_compute_sseu_info(sseu, s_en, ss_en, 0, eu_en);
+	gen11_compute_sseu_info(sseu, ss_en, 0, eu_en);
 
 	/* ICL has no power gating restrictions. */
 	sseu->has_slice_pg = 1;
-- 
2.35.1


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

* [PATCH 5/5] drm/i915/sseu: Disassociate internal subslice mask representation from uapi
  2022-04-27 23:07 ` [Intel-gfx] " Matt Roper
@ 2022-04-27 23:07   ` Matt Roper
  -1 siblings, 0 replies; 27+ messages in thread
From: Matt Roper @ 2022-04-27 23:07 UTC (permalink / raw)
  To: intel-gfx; +Cc: tvrtko.ursulin, dri-devel

Rather than storing subslice masks internally as u8[] (inside the sseu
structure) and u32 (everywhere else), let's move over to using an
intel_sseu_ss_mask_t typedef compatible with the operations in
linux/bitmap.h.  We're soon going to start adding code for a new
platform where subslice masks are spread across two 32-bit registers
(requiring 64 bits to represent), and we expect future platforms will
likely take this even farther, requiring bitmask storage larger than a
simple u64 can hold.

Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
---
 drivers/gpu/drm/i915/gem/i915_gem_context.c  |   4 +-
 drivers/gpu/drm/i915/gt/intel_engine_cs.c    |   2 +-
 drivers/gpu/drm/i915/gt/intel_gt.c           |  14 +-
 drivers/gpu/drm/i915/gt/intel_sseu.c         | 197 +++++++++++--------
 drivers/gpu/drm/i915/gt/intel_sseu.h         |  48 ++---
 drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c |  28 +--
 drivers/gpu/drm/i915/gt/intel_workarounds.c  |  28 ++-
 drivers/gpu/drm/i915/i915_getparam.c         |   2 +-
 drivers/gpu/drm/i915/i915_query.c            |   8 +-
 9 files changed, 183 insertions(+), 148 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c
index ab4c5ab28e4d..ea012ee3a8de 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c
@@ -1901,7 +1901,7 @@ i915_gem_user_to_context_sseu(struct intel_gt *gt,
 	if (user->slice_mask & ~device->slice_mask)
 		return -EINVAL;
 
-	if (user->subslice_mask & ~device->subslice_mask[0])
+	if (user->subslice_mask & ~device->subslice_mask.b[0])
 		return -EINVAL;
 
 	if (user->max_eus_per_subslice > device->max_eus_per_subslice)
@@ -1915,7 +1915,7 @@ i915_gem_user_to_context_sseu(struct intel_gt *gt,
 	/* Part specific restrictions. */
 	if (GRAPHICS_VER(i915) == 11) {
 		unsigned int hw_s = hweight8(device->slice_mask);
-		unsigned int hw_ss_per_s = hweight8(device->subslice_mask[0]);
+		unsigned int hw_ss_per_s = hweight8(device->subslice_mask.b[0]);
 		unsigned int req_s = hweight8(context->slice_mask);
 		unsigned int req_ss = hweight8(context->subslice_mask);
 
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
index 14c6ddbbfde8..39c09963b3c7 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c
+++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
@@ -610,7 +610,7 @@ static void engine_mask_apply_compute_fuses(struct intel_gt *gt)
 	if (GRAPHICS_VER_FULL(i915) < IP_VER(12, 50))
 		return;
 
-	ccs_mask = intel_slicemask_from_dssmask(intel_sseu_get_compute_subslices(&info->sseu),
+	ccs_mask = intel_slicemask_from_dssmask(info->sseu.compute_subslice_mask,
 						ss_per_ccs);
 	/*
 	 * If all DSS in a quadrant are fused off, the corresponding CCS
diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c
index 92394f13b42f..cc03512d59ba 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt.c
@@ -133,13 +133,6 @@ static const struct intel_mmio_range dg2_lncf_steering_table[] = {
 	{},
 };
 
-static u16 slicemask(struct intel_gt *gt, int count)
-{
-	u64 dss_mask = intel_sseu_get_subslices(&gt->info.sseu, 0);
-
-	return intel_slicemask_from_dssmask(dss_mask, count);
-}
-
 int intel_gt_init_mmio(struct intel_gt *gt)
 {
 	struct drm_i915_private *i915 = gt->i915;
@@ -153,11 +146,14 @@ int intel_gt_init_mmio(struct intel_gt *gt)
 	 * An mslice is unavailable only if both the meml3 for the slice is
 	 * disabled *and* all of the DSS in the slice (quadrant) are disabled.
 	 */
-	if (HAS_MSLICES(i915))
+	if (HAS_MSLICES(i915)) {
 		gt->info.mslice_mask =
-			slicemask(gt, GEN_DSS_PER_MSLICE) |
+			intel_slicemask_from_dssmask(gt->info.sseu.subslice_mask,
+						     GEN_DSS_PER_MSLICE);
+		gt->info.mslice_mask |=
 			(intel_uncore_read(gt->uncore, GEN10_MIRROR_FUSE3) &
 			 GEN12_MEML3_EN_MASK);
+	}
 
 	if (IS_DG2(i915)) {
 		gt->steering_table[MSLICE] = xehpsdv_mslice_steering_table;
diff --git a/drivers/gpu/drm/i915/gt/intel_sseu.c b/drivers/gpu/drm/i915/gt/intel_sseu.c
index f7ff6a9f67b0..466505d6bd18 100644
--- a/drivers/gpu/drm/i915/gt/intel_sseu.c
+++ b/drivers/gpu/drm/i915/gt/intel_sseu.c
@@ -28,56 +28,49 @@ void intel_sseu_set_info(struct sseu_dev_info *sseu, u8 max_slices,
 unsigned int
 intel_sseu_subslice_total(const struct sseu_dev_info *sseu)
 {
-	unsigned int i, total = 0;
-
-	for (i = 0; i < ARRAY_SIZE(sseu->subslice_mask); i++)
-		total += hweight8(sseu->subslice_mask[i]);
-
-	return total;
+	return bitmap_weight(sseu->subslice_mask.b, I915_MAX_SS_FUSE_BITS);
 }
 
-static u32
-sseu_get_subslices(const struct sseu_dev_info *sseu,
-		   const u8 *subslice_mask, u8 slice)
+static intel_sseu_ss_mask_t
+get_ss_mask_for_slice(const struct sseu_dev_info *sseu,
+		      intel_sseu_ss_mask_t all_ss,
+		      int slice)
 {
-	int i, offset = slice * sseu->ss_stride;
-	u32 mask = 0;
+	intel_sseu_ss_mask_t mask = {}, slice_ss = {};
+	int offset = slice * sseu->max_subslices;
 
 	GEM_BUG_ON(slice >= sseu->max_slices);
 
-	for (i = 0; i < sseu->ss_stride; i++)
-		mask |= (u32)subslice_mask[offset + i] << i * BITS_PER_BYTE;
+	if (sseu->max_slices == 1)
+		return all_ss;
 
-	return mask;
-}
+	bitmap_set(mask.b, offset, sseu->max_subslices);
+	bitmap_and(slice_ss.b, all_ss.b, mask.b, I915_MAX_SS_FUSE_BITS);
+	bitmap_shift_right(slice_ss.b, slice_ss.b, offset, I915_MAX_SS_FUSE_BITS);
 
-u32 intel_sseu_get_subslices(const struct sseu_dev_info *sseu, u8 slice)
-{
-	return sseu_get_subslices(sseu, sseu->subslice_mask, slice);
+	return slice_ss;
 }
 
-static u32 sseu_get_geometry_subslices(const struct sseu_dev_info *sseu)
+intel_sseu_ss_mask_t
+intel_sseu_get_subslices(const struct sseu_dev_info *sseu, u8 slice)
 {
-	return sseu_get_subslices(sseu, sseu->geometry_subslice_mask, 0);
+	return get_ss_mask_for_slice(sseu, sseu->subslice_mask, slice);
 }
 
-u32 intel_sseu_get_compute_subslices(const struct sseu_dev_info *sseu)
-{
-	return sseu_get_subslices(sseu, sseu->compute_subslice_mask, 0);
-}
-
-void intel_sseu_set_subslices(struct sseu_dev_info *sseu, int slice,
-			      u8 *subslice_mask, u32 ss_mask)
-{
-	int offset = slice * sseu->ss_stride;
-
-	memcpy(&subslice_mask[offset], &ss_mask, sseu->ss_stride);
-}
-
-unsigned int
-intel_sseu_subslices_per_slice(const struct sseu_dev_info *sseu, u8 slice)
+/*
+ * Set the subslice mask associated with a specific slice.  Only needed on
+ * pre-gen11 platforms that have multiple slices.
+ */
+static void set_subslices(struct sseu_dev_info *sseu, int slice, u32 ss_mask)
 {
-	return hweight32(intel_sseu_get_subslices(sseu, slice));
+	intel_sseu_ss_mask_t mask = {}, newbits = {};
+	int offset = slice * sseu->max_subslices;
+
+	bitmap_set(mask.b, offset, sseu->max_subslices);
+	bitmap_from_arr32(newbits.b, &ss_mask, 32);
+	bitmap_shift_left(newbits.b, newbits.b, offset, I915_MAX_SS_FUSE_BITS);
+	bitmap_replace(sseu->subslice_mask.b, sseu->subslice_mask.b,
+		       newbits.b, mask.b, I915_MAX_SS_FUSE_BITS);
 }
 
 static int sseu_eu_idx(const struct sseu_dev_info *sseu, int slice,
@@ -115,7 +108,7 @@ static u16 compute_eu_total(const struct sseu_dev_info *sseu)
 	u16 i, total = 0;
 
 	if (sseu->has_common_ss_eumask)
-		return intel_sseu_subslices_per_slice(sseu, 0) *
+		return bitmap_weight(sseu->subslice_mask.b, I915_MAX_SS_FUSE_BITS) *
 			hweight16(sseu->eu_mask[0]);
 
 	for (i = 0; i < ARRAY_SIZE(sseu->eu_mask); i++)
@@ -155,11 +148,42 @@ int intel_sseu_copy_eumask_to_user(void __user *to,
 	return copy_to_user(to, eu_mask, len);
 }
 
-static void gen11_compute_sseu_info(struct sseu_dev_info *sseu,
-				    u32 g_ss_en, u32 c_ss_en, u16 eu_en)
+/**
+ * intel_sseu_copy_ssmask_to_user - Copy subslice mask into a userspace buffer
+ * @to: Pointer to userspace buffer to copy to
+ * @sseu: SSEU structure containing subslice mask to copy
+ *
+ * Copies the subslice mask to a userspace buffer in the format expected by
+ * the query ioctl's topology queries.
+ *
+ * Returns the result of the copy_to_user() operation.
+ */
+int intel_sseu_copy_ssmask_to_user(void __user *to,
+				   const struct sseu_dev_info *sseu)
 {
-	u32 valid_ss_mask = GENMASK(sseu->max_subslices - 1, 0);
+	u8 ss_mask[GEN_SS_MASK_SIZE] = {};
+	int len = sseu->max_slices * sseu->ss_stride;
+	int s, ss, i;
 
+	for (s = 0; s < sseu->max_slices; s++) {
+		for (ss = 0; ss < sseu->max_subslices; ss++) {
+			i = s * sseu->ss_stride + ss;
+
+			if (!intel_sseu_has_subslice(sseu, s, ss))
+				continue;
+
+			ss_mask[i / BITS_PER_BYTE] |= BIT(i % BITS_PER_BYTE);
+		}
+	}
+
+	return copy_to_user(to, ss_mask, len);
+}
+
+static void gen11_compute_sseu_info(struct sseu_dev_info *sseu,
+				    intel_sseu_ss_mask_t g_ss_en,
+				    intel_sseu_ss_mask_t c_ss_en,
+				    u16 eu_en)
+{
 	/* g_ss_en/c_ss_en represent entire subslice mask across all slices */
 	GEM_BUG_ON(sseu->max_slices * sseu->max_subslices >
 		   sizeof(g_ss_en) * BITS_PER_BYTE);
@@ -174,12 +198,12 @@ static void gen11_compute_sseu_info(struct sseu_dev_info *sseu,
 	 * enabled subslice count for the purposes of selecting subslices to
 	 * use in a particular GEM context.
 	 */
-	intel_sseu_set_subslices(sseu, 0, sseu->compute_subslice_mask,
-				 c_ss_en & valid_ss_mask);
-	intel_sseu_set_subslices(sseu, 0, sseu->geometry_subslice_mask,
-				 g_ss_en & valid_ss_mask);
-	intel_sseu_set_subslices(sseu, 0, sseu->subslice_mask,
-				 (g_ss_en | c_ss_en) & valid_ss_mask);
+	bitmap_copy(sseu->compute_subslice_mask.b, c_ss_en.b, I915_MAX_SS_FUSE_BITS);
+	bitmap_copy(sseu->geometry_subslice_mask.b, g_ss_en.b, I915_MAX_SS_FUSE_BITS);
+	bitmap_or(sseu->subslice_mask.b,
+		  sseu->compute_subslice_mask.b,
+		  sseu->geometry_subslice_mask.b,
+		  I915_MAX_SS_FUSE_BITS);
 
 	sseu->has_common_ss_eumask = 1;
 	sseu->eu_mask[0] = eu_en;
@@ -191,7 +215,8 @@ static void xehp_sseu_info_init(struct intel_gt *gt)
 {
 	struct sseu_dev_info *sseu = &gt->info.sseu;
 	struct intel_uncore *uncore = gt->uncore;
-	u32 g_dss_en, c_dss_en = 0;
+	intel_sseu_ss_mask_t g_dss_en = {}, c_dss_en = {};
+	u32 val;
 	u16 eu_en = 0;
 	u8 eu_en_fuse;
 	int eu;
@@ -204,8 +229,11 @@ static void xehp_sseu_info_init(struct intel_gt *gt)
 	 */
 	intel_sseu_set_info(sseu, 1, 32, 16);
 
-	g_dss_en = intel_uncore_read(uncore, GEN12_GT_GEOMETRY_DSS_ENABLE);
-	c_dss_en = intel_uncore_read(uncore, GEN12_GT_COMPUTE_DSS_ENABLE);
+	val = intel_uncore_read(uncore, GEN12_GT_GEOMETRY_DSS_ENABLE);
+	bitmap_from_arr32(g_dss_en.b, &val, 32);
+
+	val = intel_uncore_read(uncore, GEN12_GT_COMPUTE_DSS_ENABLE);
+	bitmap_from_arr32(c_dss_en.b, &val, 32);
 
 	eu_en_fuse = intel_uncore_read(uncore, XEHP_EU_ENABLE) & XEHP_EU_ENA_MASK;
 
@@ -220,7 +248,8 @@ static void gen12_sseu_info_init(struct intel_gt *gt)
 {
 	struct sseu_dev_info *sseu = &gt->info.sseu;
 	struct intel_uncore *uncore = gt->uncore;
-	u32 g_dss_en;
+	intel_sseu_ss_mask_t g_dss_en = {}, empty_mask = {};
+	u32 val;
 	u16 eu_en = 0;
 	u8 eu_en_fuse;
 	u8 s_en;
@@ -243,7 +272,8 @@ static void gen12_sseu_info_init(struct intel_gt *gt)
 		drm_dbg(&gt->i915->drm, "Slice mask %#x is not the expected 0x1!\n",
 			s_en);
 
-	g_dss_en = intel_uncore_read(uncore, GEN12_GT_GEOMETRY_DSS_ENABLE);
+	val = intel_uncore_read(uncore, GEN12_GT_GEOMETRY_DSS_ENABLE);
+	bitmap_from_arr32(g_dss_en.b, &val, 32);
 
 	/* one bit per pair of EUs */
 	eu_en_fuse = ~(intel_uncore_read(uncore, GEN11_EU_DISABLE) &
@@ -253,7 +283,7 @@ static void gen12_sseu_info_init(struct intel_gt *gt)
 		if (eu_en_fuse & BIT(eu))
 			eu_en |= BIT(eu * 2) | BIT(eu * 2 + 1);
 
-	gen11_compute_sseu_info(sseu, g_dss_en, 0, eu_en);
+	gen11_compute_sseu_info(sseu, g_dss_en, empty_mask, eu_en);
 
 	/* TGL only supports slice-level power gating */
 	sseu->has_slice_pg = 1;
@@ -263,7 +293,8 @@ static void gen11_sseu_info_init(struct intel_gt *gt)
 {
 	struct sseu_dev_info *sseu = &gt->info.sseu;
 	struct intel_uncore *uncore = gt->uncore;
-	u32 ss_en;
+	intel_sseu_ss_mask_t ss_en = {}, empty_mask = {};
+	u32 val;
 	u8 eu_en;
 	u8 s_en;
 
@@ -282,12 +313,13 @@ static void gen11_sseu_info_init(struct intel_gt *gt)
 		drm_dbg(&gt->i915->drm, "Slice mask %#x is not the expected 0x1!\n",
 			s_en);
 
-	ss_en = ~intel_uncore_read(uncore, GEN11_GT_SUBSLICE_DISABLE);
+	val = ~intel_uncore_read(uncore, GEN11_GT_SUBSLICE_DISABLE);
+	bitmap_from_arr32(ss_en.b, &val, 32);
 
 	eu_en = ~(intel_uncore_read(uncore, GEN11_EU_DISABLE) &
 		  GEN11_EU_DIS_MASK);
 
-	gen11_compute_sseu_info(sseu, ss_en, 0, eu_en);
+	gen11_compute_sseu_info(sseu, ss_en, empty_mask, eu_en);
 
 	/* ICL has no power gating restrictions. */
 	sseu->has_slice_pg = 1;
@@ -328,7 +360,7 @@ static void cherryview_sseu_info_init(struct intel_gt *gt)
 		sseu_set_eus(sseu, 0, 1, ~disabled_mask);
 	}
 
-	intel_sseu_set_subslices(sseu, 0, sseu->subslice_mask, subslice_mask);
+	set_subslices(sseu, 0, subslice_mask);
 
 	sseu->eu_total = compute_eu_total(sseu);
 
@@ -384,8 +416,7 @@ static void gen9_sseu_info_init(struct intel_gt *gt)
 			/* skip disabled slice */
 			continue;
 
-		intel_sseu_set_subslices(sseu, s, sseu->subslice_mask,
-					 subslice_mask);
+		set_subslices(sseu, s, subslice_mask);
 
 		eu_disable = intel_uncore_read(uncore, GEN9_EU_DISABLE(s));
 		for (ss = 0; ss < sseu->max_subslices; ss++) {
@@ -442,8 +473,8 @@ static void gen9_sseu_info_init(struct intel_gt *gt)
 	sseu->has_eu_pg = sseu->eu_per_subslice > 2;
 
 	if (IS_GEN9_LP(i915)) {
-#define IS_SS_DISABLED(ss)	(!(sseu->subslice_mask[0] & BIT(ss)))
-		info->has_pooled_eu = hweight8(sseu->subslice_mask[0]) == 3;
+#define IS_SS_DISABLED(ss)	test_bit(ss, sseu->subslice_mask.b)
+		info->has_pooled_eu = hweight8(sseu->subslice_mask.b[0]) == 3;
 
 		sseu->min_eu_in_pool = 0;
 		if (info->has_pooled_eu) {
@@ -497,8 +528,7 @@ static void bdw_sseu_info_init(struct intel_gt *gt)
 			/* skip disabled slice */
 			continue;
 
-		intel_sseu_set_subslices(sseu, s, sseu->subslice_mask,
-					 subslice_mask);
+		set_subslices(sseu, s, subslice_mask);
 
 		for (ss = 0; ss < sseu->max_subslices; ss++) {
 			u8 eu_disabled_mask;
@@ -595,8 +625,7 @@ static void hsw_sseu_info_init(struct intel_gt *gt)
 			    sseu->eu_per_subslice);
 
 	for (s = 0; s < sseu->max_slices; s++) {
-		intel_sseu_set_subslices(sseu, s, sseu->subslice_mask,
-					 subslice_mask);
+		set_subslices(sseu, s, subslice_mask);
 
 		for (ss = 0; ss < sseu->max_subslices; ss++) {
 			sseu_set_eus(sseu, s, ss,
@@ -685,7 +714,7 @@ u32 intel_sseu_make_rpcs(struct intel_gt *gt,
 	 */
 	if (GRAPHICS_VER(i915) == 11 &&
 	    slices == 1 &&
-	    subslices > min_t(u8, 4, hweight8(sseu->subslice_mask[0]) / 2)) {
+	    subslices > min_t(u8, 4, hweight8(sseu->subslice_mask.b[0]) / 2)) {
 		GEM_BUG_ON(subslices & 1);
 
 		subslice_pg = false;
@@ -755,9 +784,11 @@ void intel_sseu_dump(const struct sseu_dev_info *sseu, struct drm_printer *p)
 		   hweight8(sseu->slice_mask), sseu->slice_mask);
 	drm_printf(p, "subslice total: %u\n", intel_sseu_subslice_total(sseu));
 	for (s = 0; s < sseu->max_slices; s++) {
-		drm_printf(p, "slice%d: %u subslices, mask=%08x\n",
-			   s, intel_sseu_subslices_per_slice(sseu, s),
-			   intel_sseu_get_subslices(sseu, s));
+		intel_sseu_ss_mask_t ssmask = intel_sseu_get_subslices(sseu, s);
+
+		drm_printf(p, "slice%d: %u subslices, mask=%*pb\n",
+			   s, bitmap_weight(ssmask.b, I915_MAX_SS_FUSE_BITS),
+			   I915_MAX_SS_FUSE_BITS, ssmask.b);
 	}
 	drm_printf(p, "EU total: %u\n", sseu->eu_total);
 	drm_printf(p, "EU per subslice: %u\n", sseu->eu_per_subslice);
@@ -775,9 +806,11 @@ static void sseu_print_hsw_topology(const struct sseu_dev_info *sseu,
 	int s, ss;
 
 	for (s = 0; s < sseu->max_slices; s++) {
-		drm_printf(p, "slice%d: %u subslice(s) (0x%08x):\n",
-			   s, intel_sseu_subslices_per_slice(sseu, s),
-			   intel_sseu_get_subslices(sseu, s));
+		intel_sseu_ss_mask_t ssmask = intel_sseu_get_subslices(sseu, s);
+
+		drm_printf(p, "slice%d: %u subslice(s) (0x%*pb):\n",
+			   s, bitmap_weight(ssmask.b, I915_MAX_SS_FUSE_BITS),
+			   I915_MAX_SS_FUSE_BITS, ssmask.b);
 
 		for (ss = 0; ss < sseu->max_subslices; ss++) {
 			u16 enabled_eus = sseu_get_eus(sseu, s, ss);
@@ -791,16 +824,14 @@ static void sseu_print_hsw_topology(const struct sseu_dev_info *sseu,
 static void sseu_print_xehp_topology(const struct sseu_dev_info *sseu,
 				     struct drm_printer *p)
 {
-	u32 g_dss_mask = sseu_get_geometry_subslices(sseu);
-	u32 c_dss_mask = intel_sseu_get_compute_subslices(sseu);
 	int dss;
 
 	for (dss = 0; dss < sseu->max_subslices; dss++) {
 		u16 enabled_eus = sseu_get_eus(sseu, 0, dss);
 
 		drm_printf(p, "DSS_%02d: G:%3s C:%3s, %2u EUs (0x%04hx)\n", dss,
-			   str_yes_no(g_dss_mask & BIT(dss)),
-			   str_yes_no(c_dss_mask & BIT(dss)),
+			   str_yes_no(test_bit(dss, sseu->geometry_subslice_mask.b)),
+			   str_yes_no(test_bit(dss, sseu->compute_subslice_mask.b)),
 			   hweight16(enabled_eus), enabled_eus);
 	}
 }
@@ -818,20 +849,24 @@ void intel_sseu_print_topology(struct drm_i915_private *i915,
 	}
 }
 
-u16 intel_slicemask_from_dssmask(u64 dss_mask, int dss_per_slice)
+u16 intel_slicemask_from_dssmask(intel_sseu_ss_mask_t dss_mask,
+				 int dss_per_slice)
 {
+	intel_sseu_ss_mask_t per_slice_mask = {};
 	u16 slice_mask = 0;
 	int i;
 
-	WARN_ON(sizeof(dss_mask) * 8 / dss_per_slice > 8 * sizeof(slice_mask));
+	WARN_ON(DIV_ROUND_UP(I915_MAX_SS_FUSE_BITS, dss_per_slice) >
+		8 * sizeof(slice_mask));
 
-	for (i = 0; dss_mask; i++) {
-		if (dss_mask & GENMASK(dss_per_slice - 1, 0))
+	bitmap_fill(per_slice_mask.b, dss_per_slice);
+	for (i = 0; !bitmap_empty(dss_mask.b, I915_MAX_SS_FUSE_BITS); i++) {
+		if (bitmap_intersects(dss_mask.b, per_slice_mask.b, dss_per_slice))
 			slice_mask |= BIT(i);
 
-		dss_mask >>= dss_per_slice;
+		bitmap_shift_right(dss_mask.b, dss_mask.b, dss_per_slice,
+				   I915_MAX_SS_FUSE_BITS);
 	}
 
 	return slice_mask;
 }
-
diff --git a/drivers/gpu/drm/i915/gt/intel_sseu.h b/drivers/gpu/drm/i915/gt/intel_sseu.h
index 106726a2244e..455f085093ae 100644
--- a/drivers/gpu/drm/i915/gt/intel_sseu.h
+++ b/drivers/gpu/drm/i915/gt/intel_sseu.h
@@ -52,11 +52,22 @@ struct drm_printer;
 #define GEN_MAX_GSLICES		(GEN_MAX_DSS / GEN_DSS_PER_GSLICE)
 #define GEN_MAX_CSLICES		(GEN_MAX_DSS / GEN_DSS_PER_CSLICE)
 
+/*
+ * Maximum number of 32-bit registers used by hardware to express the
+ * enabled/disabled subslices.
+ */
+#define I915_MAX_SS_FUSE_REGS	1
+#define I915_MAX_SS_FUSE_BITS	(I915_MAX_SS_FUSE_REGS * 32)
+
+typedef struct {
+	unsigned long b[BITS_TO_LONGS(I915_MAX_SS_FUSE_BITS)];
+} intel_sseu_ss_mask_t;
+
 struct sseu_dev_info {
 	u8 slice_mask;
-	u8 subslice_mask[GEN_SS_MASK_SIZE];
-	u8 geometry_subslice_mask[GEN_SS_MASK_SIZE];
-	u8 compute_subslice_mask[GEN_SS_MASK_SIZE];
+	intel_sseu_ss_mask_t subslice_mask;
+	intel_sseu_ss_mask_t geometry_subslice_mask;
+	intel_sseu_ss_mask_t compute_subslice_mask;
 
 	/*
 	 * EU masks.  Use has_common_ss_eumask to determine how the field
@@ -107,7 +118,7 @@ intel_sseu_from_device_info(const struct sseu_dev_info *sseu)
 {
 	struct intel_sseu value = {
 		.slice_mask = sseu->slice_mask,
-		.subslice_mask = sseu->subslice_mask[0],
+		.subslice_mask = sseu->subslice_mask.b[0],
 		.min_eus_per_subslice = sseu->max_eus_per_subslice,
 		.max_eus_per_subslice = sseu->max_eus_per_subslice,
 	};
@@ -119,18 +130,8 @@ static inline bool
 intel_sseu_has_subslice(const struct sseu_dev_info *sseu, int slice,
 			int subslice)
 {
-	u8 mask;
-	int ss_idx = subslice / BITS_PER_BYTE;
-
-	if (slice >= sseu->max_slices ||
-	    subslice >= sseu->max_subslices)
-		return false;
-
-	GEM_BUG_ON(ss_idx >= sseu->ss_stride);
-
-	mask = sseu->subslice_mask[slice * sseu->ss_stride + ss_idx];
-
-	return mask & BIT(subslice % BITS_PER_BYTE);
+	return test_bit(slice * sseu->ss_stride + subslice,
+			sseu->subslice_mask.b);
 }
 
 void intel_sseu_set_info(struct sseu_dev_info *sseu, u8 max_slices,
@@ -139,15 +140,14 @@ void intel_sseu_set_info(struct sseu_dev_info *sseu, u8 max_slices,
 unsigned int
 intel_sseu_subslice_total(const struct sseu_dev_info *sseu);
 
-unsigned int
-intel_sseu_subslices_per_slice(const struct sseu_dev_info *sseu, u8 slice);
+intel_sseu_ss_mask_t
+intel_sseu_get_subslices(const struct sseu_dev_info *sseu, u8 slice);
 
-u32 intel_sseu_get_subslices(const struct sseu_dev_info *sseu, u8 slice);
-
-u32 intel_sseu_get_compute_subslices(const struct sseu_dev_info *sseu);
+intel_sseu_ss_mask_t
+intel_sseu_get_compute_subslices(const struct sseu_dev_info *sseu);
 
 void intel_sseu_set_subslices(struct sseu_dev_info *sseu, int slice,
-			      u8 *subslice_mask, u32 ss_mask);
+			      u32 ss_mask);
 
 void intel_sseu_info_init(struct intel_gt *gt);
 
@@ -159,9 +159,11 @@ void intel_sseu_print_topology(struct drm_i915_private *i915,
 			       const struct sseu_dev_info *sseu,
 			       struct drm_printer *p);
 
-u16 intel_slicemask_from_dssmask(u64 dss_mask, int dss_per_slice);
+u16 intel_slicemask_from_dssmask(intel_sseu_ss_mask_t dss_mask, int dss_per_slice);
 
 int intel_sseu_copy_eumask_to_user(void __user *to,
 				   const struct sseu_dev_info *sseu);
+int intel_sseu_copy_ssmask_to_user(void __user *to,
+				   const struct sseu_dev_info *sseu);
 
 #endif /* __INTEL_SSEU_H__ */
diff --git a/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c b/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c
index 2d5d011e01db..1f77bd52a3a6 100644
--- a/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c
+++ b/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c
@@ -4,6 +4,7 @@
  * Copyright © 2020 Intel Corporation
  */
 
+#include <linux/bitmap.h>
 #include <linux/string_helpers.h>
 
 #include "i915_drv.h"
@@ -12,11 +13,15 @@
 #include "intel_sseu_debugfs.h"
 
 static void sseu_copy_subslices(const struct sseu_dev_info *sseu,
-				int slice, u8 *to_mask)
+				int slice,
+				intel_sseu_ss_mask_t *to_mask)
 {
-	int offset = slice * sseu->ss_stride;
+	int offset = slice * sseu->max_subslices;
 
-	memcpy(&to_mask[offset], &sseu->subslice_mask[offset], sseu->ss_stride);
+	bitmap_fill(to_mask->b, sseu->max_subslices);
+	bitmap_shift_left(to_mask->b, to_mask->b, offset, I915_MAX_SS_FUSE_BITS);
+	bitmap_and(to_mask->b, to_mask->b, sseu->subslice_mask.b, I915_MAX_SS_FUSE_BITS);
+	bitmap_shift_right(to_mask->b, to_mask->b, offset, I915_MAX_SS_FUSE_BITS);
 }
 
 static void cherryview_sseu_device_status(struct intel_gt *gt,
@@ -41,7 +46,7 @@ static void cherryview_sseu_device_status(struct intel_gt *gt,
 			continue;
 
 		sseu->slice_mask = BIT(0);
-		sseu->subslice_mask[0] |= BIT(ss);
+		set_bit(0, sseu->subslice_mask.b);
 		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) +
@@ -92,7 +97,7 @@ static void gen11_sseu_device_status(struct intel_gt *gt,
 			continue;
 
 		sseu->slice_mask |= BIT(s);
-		sseu_copy_subslices(&info->sseu, s, sseu->subslice_mask);
+		sseu_copy_subslices(&info->sseu, s, &sseu->subslice_mask);
 
 		for (ss = 0; ss < info->sseu.max_subslices; ss++) {
 			unsigned int eu_cnt;
@@ -148,20 +153,17 @@ static void gen9_sseu_device_status(struct intel_gt *gt,
 
 		if (IS_GEN9_BC(gt->i915))
 			sseu_copy_subslices(&info->sseu, s,
-					    sseu->subslice_mask);
+					    &sseu->subslice_mask);
 
 		for (ss = 0; ss < info->sseu.max_subslices; ss++) {
 			unsigned int eu_cnt;
-			u8 ss_idx = s * info->sseu.ss_stride +
-				    ss / BITS_PER_BYTE;
 
 			if (IS_GEN9_LP(gt->i915)) {
 				if (!(s_reg[s] & (GEN9_PGCTL_SS_ACK(ss))))
 					/* skip disabled subslice */
 					continue;
 
-				sseu->subslice_mask[ss_idx] |=
-					BIT(ss % BITS_PER_BYTE);
+				set_bit(ss, sseu->subslice_mask.b);
 			}
 
 			eu_cnt = eu_reg[2 * s + ss / 2] & eu_mask[ss % 2];
@@ -189,7 +191,7 @@ static void bdw_sseu_device_status(struct intel_gt *gt,
 		sseu->eu_per_subslice = info->sseu.eu_per_subslice;
 		for (s = 0; s < fls(sseu->slice_mask); s++)
 			sseu_copy_subslices(&info->sseu, s,
-					    sseu->subslice_mask);
+					    &sseu->subslice_mask);
 		sseu->eu_total = sseu->eu_per_subslice *
 				 intel_sseu_subslice_total(sseu);
 
@@ -217,8 +219,10 @@ static void i915_print_sseu_info(struct seq_file *m,
 	seq_printf(m, "  %s Subslice Total: %u\n", type,
 		   intel_sseu_subslice_total(sseu));
 	for (s = 0; s < fls(sseu->slice_mask); s++) {
+		intel_sseu_ss_mask_t ssmask = intel_sseu_get_subslices(sseu, s);
+
 		seq_printf(m, "  %s Slice%i subslices: %u\n", type,
-			   s, intel_sseu_subslices_per_slice(sseu, s));
+			   s, bitmap_weight(ssmask.b, I915_MAX_SS_FUSE_BITS));
 	}
 	seq_printf(m, "  %s EU Total: %u\n", type,
 		   sseu->eu_total);
diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c
index a05c4b99b3fb..5db492072f99 100644
--- a/drivers/gpu/drm/i915/gt/intel_workarounds.c
+++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c
@@ -931,6 +931,7 @@ static void
 gen9_wa_init_mcr(struct drm_i915_private *i915, struct i915_wa_list *wal)
 {
 	const struct sseu_dev_info *sseu = &to_gt(i915)->info.sseu;
+	intel_sseu_ss_mask_t ssmask;
 	unsigned int slice, subslice;
 	u32 mcr, mcr_mask;
 
@@ -948,9 +949,9 @@ gen9_wa_init_mcr(struct drm_i915_private *i915, struct i915_wa_list *wal)
 	 * on s/ss combo, the read should be done with read_subslice_reg.
 	 */
 	slice = ffs(sseu->slice_mask) - 1;
-	GEM_BUG_ON(slice >= ARRAY_SIZE(sseu->subslice_mask));
-	subslice = ffs(intel_sseu_get_subslices(sseu, slice));
-	GEM_BUG_ON(!subslice);
+	ssmask = intel_sseu_get_subslices(sseu, slice);
+	subslice = find_first_bit(ssmask.b, I915_MAX_SS_FUSE_BITS);
+	GEM_BUG_ON(subslice == I915_MAX_SS_FUSE_BITS);
 	subslice--;
 
 	/*
@@ -1087,11 +1088,10 @@ static void
 icl_wa_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
 {
 	const struct sseu_dev_info *sseu = &gt->info.sseu;
-	unsigned int slice, subslice;
+	unsigned int subslice;
 
 	GEM_BUG_ON(GRAPHICS_VER(gt->i915) < 11);
 	GEM_BUG_ON(hweight8(sseu->slice_mask) > 1);
-	slice = 0;
 
 	/*
 	 * Although a platform may have subslices, we need to always steer
@@ -1102,7 +1102,7 @@ icl_wa_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
 	 * one of the higher subslices, we run the risk of reading back 0's or
 	 * random garbage.
 	 */
-	subslice = __ffs(intel_sseu_get_subslices(sseu, slice));
+	subslice = find_first_bit(sseu->subslice_mask.b, I915_MAX_SS_FUSE_BITS);
 
 	/*
 	 * If the subslice we picked above also steers us to a valid L3 bank,
@@ -1112,7 +1112,7 @@ icl_wa_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
 	if (gt->info.l3bank_mask & BIT(subslice))
 		gt->steering_table[L3BANK] = NULL;
 
-	__add_mcr_wa(gt, wal, slice, subslice);
+	__add_mcr_wa(gt, wal, 0, subslice);
 }
 
 static void
@@ -1120,7 +1120,6 @@ xehp_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
 {
 	const struct sseu_dev_info *sseu = &gt->info.sseu;
 	unsigned long slice, subslice = 0, slice_mask = 0;
-	u64 dss_mask = 0;
 	u32 lncf_mask = 0;
 	int i;
 
@@ -1151,8 +1150,8 @@ xehp_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
 	 */
 
 	/* Find the potential gslice candidates */
-	dss_mask = intel_sseu_get_subslices(sseu, 0);
-	slice_mask = intel_slicemask_from_dssmask(dss_mask, GEN_DSS_PER_GSLICE);
+	slice_mask = intel_slicemask_from_dssmask(sseu->subslice_mask,
+						  GEN_DSS_PER_GSLICE);
 
 	/*
 	 * Find the potential LNCF candidates.  Either LNCF within a valid
@@ -1177,9 +1176,9 @@ xehp_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
 	}
 
 	slice = __ffs(slice_mask);
-	subslice = __ffs(dss_mask >> (slice * GEN_DSS_PER_GSLICE));
+	subslice = find_next_bit(sseu->subslice_mask.b, I915_MAX_SS_FUSE_BITS,
+				 slice * GEN_DSS_PER_GSLICE);
 	WARN_ON(subslice > GEN_DSS_PER_GSLICE);
-	WARN_ON(dss_mask >> (slice * GEN_DSS_PER_GSLICE) == 0);
 
 	__add_mcr_wa(gt, wal, slice, subslice);
 
@@ -2012,9 +2011,8 @@ engine_fake_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
 
 static bool needs_wa_1308578152(struct intel_engine_cs *engine)
 {
-	u64 dss_mask = intel_sseu_get_subslices(&engine->gt->info.sseu, 0);
-
-	return (dss_mask & GENMASK(GEN_DSS_PER_GSLICE - 1, 0)) == 0;
+	return find_first_bit(engine->gt->info.sseu.subslice_mask.b,
+			      I915_MAX_SS_FUSE_BITS) >= GEN_DSS_PER_GSLICE;
 }
 
 static void
diff --git a/drivers/gpu/drm/i915/i915_getparam.c b/drivers/gpu/drm/i915/i915_getparam.c
index ac9767c56619..349d496d164a 100644
--- a/drivers/gpu/drm/i915/i915_getparam.c
+++ b/drivers/gpu/drm/i915/i915_getparam.c
@@ -162,7 +162,7 @@ int i915_getparam_ioctl(struct drm_device *dev, void *data,
 			return -EINVAL;
 
 		/* Only copy bits from the first slice */
-		memcpy(&value, sseu->subslice_mask,
+		memcpy(&value, sseu->subslice_mask.b,
 		       min(sseu->ss_stride, (u8)sizeof(value)));
 		if (!value)
 			return -ENODEV;
diff --git a/drivers/gpu/drm/i915/i915_query.c b/drivers/gpu/drm/i915/i915_query.c
index 16f43bf32a05..9afa6d1eaf95 100644
--- a/drivers/gpu/drm/i915/i915_query.c
+++ b/drivers/gpu/drm/i915/i915_query.c
@@ -31,7 +31,7 @@ static int copy_query_item(void *query_hdr, size_t query_sz,
 
 static int fill_topology_info(const struct sseu_dev_info *sseu,
 			      struct drm_i915_query_item *query_item,
-			      const u8 *subslice_mask)
+			      intel_sseu_ss_mask_t subslice_mask)
 {
 	struct drm_i915_query_topology_info topo;
 	u32 slice_length, subslice_length, eu_length, total_length;
@@ -71,9 +71,9 @@ static int fill_topology_info(const struct sseu_dev_info *sseu,
 			 &sseu->slice_mask, slice_length))
 		return -EFAULT;
 
-	if (copy_to_user(u64_to_user_ptr(query_item->data_ptr +
-					 sizeof(topo) + slice_length),
-			 subslice_mask, subslice_length))
+	if (intel_sseu_copy_ssmask_to_user(u64_to_user_ptr(query_item->data_ptr +
+							   sizeof(topo) + slice_length),
+					   sseu))
 		return -EFAULT;
 
 	if (intel_sseu_copy_eumask_to_user(u64_to_user_ptr(query_item->data_ptr +
-- 
2.35.1


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

* [Intel-gfx] [PATCH 5/5] drm/i915/sseu: Disassociate internal subslice mask representation from uapi
@ 2022-04-27 23:07   ` Matt Roper
  0 siblings, 0 replies; 27+ messages in thread
From: Matt Roper @ 2022-04-27 23:07 UTC (permalink / raw)
  To: intel-gfx; +Cc: dri-devel

Rather than storing subslice masks internally as u8[] (inside the sseu
structure) and u32 (everywhere else), let's move over to using an
intel_sseu_ss_mask_t typedef compatible with the operations in
linux/bitmap.h.  We're soon going to start adding code for a new
platform where subslice masks are spread across two 32-bit registers
(requiring 64 bits to represent), and we expect future platforms will
likely take this even farther, requiring bitmask storage larger than a
simple u64 can hold.

Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
---
 drivers/gpu/drm/i915/gem/i915_gem_context.c  |   4 +-
 drivers/gpu/drm/i915/gt/intel_engine_cs.c    |   2 +-
 drivers/gpu/drm/i915/gt/intel_gt.c           |  14 +-
 drivers/gpu/drm/i915/gt/intel_sseu.c         | 197 +++++++++++--------
 drivers/gpu/drm/i915/gt/intel_sseu.h         |  48 ++---
 drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c |  28 +--
 drivers/gpu/drm/i915/gt/intel_workarounds.c  |  28 ++-
 drivers/gpu/drm/i915/i915_getparam.c         |   2 +-
 drivers/gpu/drm/i915/i915_query.c            |   8 +-
 9 files changed, 183 insertions(+), 148 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c
index ab4c5ab28e4d..ea012ee3a8de 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c
@@ -1901,7 +1901,7 @@ i915_gem_user_to_context_sseu(struct intel_gt *gt,
 	if (user->slice_mask & ~device->slice_mask)
 		return -EINVAL;
 
-	if (user->subslice_mask & ~device->subslice_mask[0])
+	if (user->subslice_mask & ~device->subslice_mask.b[0])
 		return -EINVAL;
 
 	if (user->max_eus_per_subslice > device->max_eus_per_subslice)
@@ -1915,7 +1915,7 @@ i915_gem_user_to_context_sseu(struct intel_gt *gt,
 	/* Part specific restrictions. */
 	if (GRAPHICS_VER(i915) == 11) {
 		unsigned int hw_s = hweight8(device->slice_mask);
-		unsigned int hw_ss_per_s = hweight8(device->subslice_mask[0]);
+		unsigned int hw_ss_per_s = hweight8(device->subslice_mask.b[0]);
 		unsigned int req_s = hweight8(context->slice_mask);
 		unsigned int req_ss = hweight8(context->subslice_mask);
 
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
index 14c6ddbbfde8..39c09963b3c7 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c
+++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
@@ -610,7 +610,7 @@ static void engine_mask_apply_compute_fuses(struct intel_gt *gt)
 	if (GRAPHICS_VER_FULL(i915) < IP_VER(12, 50))
 		return;
 
-	ccs_mask = intel_slicemask_from_dssmask(intel_sseu_get_compute_subslices(&info->sseu),
+	ccs_mask = intel_slicemask_from_dssmask(info->sseu.compute_subslice_mask,
 						ss_per_ccs);
 	/*
 	 * If all DSS in a quadrant are fused off, the corresponding CCS
diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c
index 92394f13b42f..cc03512d59ba 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt.c
@@ -133,13 +133,6 @@ static const struct intel_mmio_range dg2_lncf_steering_table[] = {
 	{},
 };
 
-static u16 slicemask(struct intel_gt *gt, int count)
-{
-	u64 dss_mask = intel_sseu_get_subslices(&gt->info.sseu, 0);
-
-	return intel_slicemask_from_dssmask(dss_mask, count);
-}
-
 int intel_gt_init_mmio(struct intel_gt *gt)
 {
 	struct drm_i915_private *i915 = gt->i915;
@@ -153,11 +146,14 @@ int intel_gt_init_mmio(struct intel_gt *gt)
 	 * An mslice is unavailable only if both the meml3 for the slice is
 	 * disabled *and* all of the DSS in the slice (quadrant) are disabled.
 	 */
-	if (HAS_MSLICES(i915))
+	if (HAS_MSLICES(i915)) {
 		gt->info.mslice_mask =
-			slicemask(gt, GEN_DSS_PER_MSLICE) |
+			intel_slicemask_from_dssmask(gt->info.sseu.subslice_mask,
+						     GEN_DSS_PER_MSLICE);
+		gt->info.mslice_mask |=
 			(intel_uncore_read(gt->uncore, GEN10_MIRROR_FUSE3) &
 			 GEN12_MEML3_EN_MASK);
+	}
 
 	if (IS_DG2(i915)) {
 		gt->steering_table[MSLICE] = xehpsdv_mslice_steering_table;
diff --git a/drivers/gpu/drm/i915/gt/intel_sseu.c b/drivers/gpu/drm/i915/gt/intel_sseu.c
index f7ff6a9f67b0..466505d6bd18 100644
--- a/drivers/gpu/drm/i915/gt/intel_sseu.c
+++ b/drivers/gpu/drm/i915/gt/intel_sseu.c
@@ -28,56 +28,49 @@ void intel_sseu_set_info(struct sseu_dev_info *sseu, u8 max_slices,
 unsigned int
 intel_sseu_subslice_total(const struct sseu_dev_info *sseu)
 {
-	unsigned int i, total = 0;
-
-	for (i = 0; i < ARRAY_SIZE(sseu->subslice_mask); i++)
-		total += hweight8(sseu->subslice_mask[i]);
-
-	return total;
+	return bitmap_weight(sseu->subslice_mask.b, I915_MAX_SS_FUSE_BITS);
 }
 
-static u32
-sseu_get_subslices(const struct sseu_dev_info *sseu,
-		   const u8 *subslice_mask, u8 slice)
+static intel_sseu_ss_mask_t
+get_ss_mask_for_slice(const struct sseu_dev_info *sseu,
+		      intel_sseu_ss_mask_t all_ss,
+		      int slice)
 {
-	int i, offset = slice * sseu->ss_stride;
-	u32 mask = 0;
+	intel_sseu_ss_mask_t mask = {}, slice_ss = {};
+	int offset = slice * sseu->max_subslices;
 
 	GEM_BUG_ON(slice >= sseu->max_slices);
 
-	for (i = 0; i < sseu->ss_stride; i++)
-		mask |= (u32)subslice_mask[offset + i] << i * BITS_PER_BYTE;
+	if (sseu->max_slices == 1)
+		return all_ss;
 
-	return mask;
-}
+	bitmap_set(mask.b, offset, sseu->max_subslices);
+	bitmap_and(slice_ss.b, all_ss.b, mask.b, I915_MAX_SS_FUSE_BITS);
+	bitmap_shift_right(slice_ss.b, slice_ss.b, offset, I915_MAX_SS_FUSE_BITS);
 
-u32 intel_sseu_get_subslices(const struct sseu_dev_info *sseu, u8 slice)
-{
-	return sseu_get_subslices(sseu, sseu->subslice_mask, slice);
+	return slice_ss;
 }
 
-static u32 sseu_get_geometry_subslices(const struct sseu_dev_info *sseu)
+intel_sseu_ss_mask_t
+intel_sseu_get_subslices(const struct sseu_dev_info *sseu, u8 slice)
 {
-	return sseu_get_subslices(sseu, sseu->geometry_subslice_mask, 0);
+	return get_ss_mask_for_slice(sseu, sseu->subslice_mask, slice);
 }
 
-u32 intel_sseu_get_compute_subslices(const struct sseu_dev_info *sseu)
-{
-	return sseu_get_subslices(sseu, sseu->compute_subslice_mask, 0);
-}
-
-void intel_sseu_set_subslices(struct sseu_dev_info *sseu, int slice,
-			      u8 *subslice_mask, u32 ss_mask)
-{
-	int offset = slice * sseu->ss_stride;
-
-	memcpy(&subslice_mask[offset], &ss_mask, sseu->ss_stride);
-}
-
-unsigned int
-intel_sseu_subslices_per_slice(const struct sseu_dev_info *sseu, u8 slice)
+/*
+ * Set the subslice mask associated with a specific slice.  Only needed on
+ * pre-gen11 platforms that have multiple slices.
+ */
+static void set_subslices(struct sseu_dev_info *sseu, int slice, u32 ss_mask)
 {
-	return hweight32(intel_sseu_get_subslices(sseu, slice));
+	intel_sseu_ss_mask_t mask = {}, newbits = {};
+	int offset = slice * sseu->max_subslices;
+
+	bitmap_set(mask.b, offset, sseu->max_subslices);
+	bitmap_from_arr32(newbits.b, &ss_mask, 32);
+	bitmap_shift_left(newbits.b, newbits.b, offset, I915_MAX_SS_FUSE_BITS);
+	bitmap_replace(sseu->subslice_mask.b, sseu->subslice_mask.b,
+		       newbits.b, mask.b, I915_MAX_SS_FUSE_BITS);
 }
 
 static int sseu_eu_idx(const struct sseu_dev_info *sseu, int slice,
@@ -115,7 +108,7 @@ static u16 compute_eu_total(const struct sseu_dev_info *sseu)
 	u16 i, total = 0;
 
 	if (sseu->has_common_ss_eumask)
-		return intel_sseu_subslices_per_slice(sseu, 0) *
+		return bitmap_weight(sseu->subslice_mask.b, I915_MAX_SS_FUSE_BITS) *
 			hweight16(sseu->eu_mask[0]);
 
 	for (i = 0; i < ARRAY_SIZE(sseu->eu_mask); i++)
@@ -155,11 +148,42 @@ int intel_sseu_copy_eumask_to_user(void __user *to,
 	return copy_to_user(to, eu_mask, len);
 }
 
-static void gen11_compute_sseu_info(struct sseu_dev_info *sseu,
-				    u32 g_ss_en, u32 c_ss_en, u16 eu_en)
+/**
+ * intel_sseu_copy_ssmask_to_user - Copy subslice mask into a userspace buffer
+ * @to: Pointer to userspace buffer to copy to
+ * @sseu: SSEU structure containing subslice mask to copy
+ *
+ * Copies the subslice mask to a userspace buffer in the format expected by
+ * the query ioctl's topology queries.
+ *
+ * Returns the result of the copy_to_user() operation.
+ */
+int intel_sseu_copy_ssmask_to_user(void __user *to,
+				   const struct sseu_dev_info *sseu)
 {
-	u32 valid_ss_mask = GENMASK(sseu->max_subslices - 1, 0);
+	u8 ss_mask[GEN_SS_MASK_SIZE] = {};
+	int len = sseu->max_slices * sseu->ss_stride;
+	int s, ss, i;
 
+	for (s = 0; s < sseu->max_slices; s++) {
+		for (ss = 0; ss < sseu->max_subslices; ss++) {
+			i = s * sseu->ss_stride + ss;
+
+			if (!intel_sseu_has_subslice(sseu, s, ss))
+				continue;
+
+			ss_mask[i / BITS_PER_BYTE] |= BIT(i % BITS_PER_BYTE);
+		}
+	}
+
+	return copy_to_user(to, ss_mask, len);
+}
+
+static void gen11_compute_sseu_info(struct sseu_dev_info *sseu,
+				    intel_sseu_ss_mask_t g_ss_en,
+				    intel_sseu_ss_mask_t c_ss_en,
+				    u16 eu_en)
+{
 	/* g_ss_en/c_ss_en represent entire subslice mask across all slices */
 	GEM_BUG_ON(sseu->max_slices * sseu->max_subslices >
 		   sizeof(g_ss_en) * BITS_PER_BYTE);
@@ -174,12 +198,12 @@ static void gen11_compute_sseu_info(struct sseu_dev_info *sseu,
 	 * enabled subslice count for the purposes of selecting subslices to
 	 * use in a particular GEM context.
 	 */
-	intel_sseu_set_subslices(sseu, 0, sseu->compute_subslice_mask,
-				 c_ss_en & valid_ss_mask);
-	intel_sseu_set_subslices(sseu, 0, sseu->geometry_subslice_mask,
-				 g_ss_en & valid_ss_mask);
-	intel_sseu_set_subslices(sseu, 0, sseu->subslice_mask,
-				 (g_ss_en | c_ss_en) & valid_ss_mask);
+	bitmap_copy(sseu->compute_subslice_mask.b, c_ss_en.b, I915_MAX_SS_FUSE_BITS);
+	bitmap_copy(sseu->geometry_subslice_mask.b, g_ss_en.b, I915_MAX_SS_FUSE_BITS);
+	bitmap_or(sseu->subslice_mask.b,
+		  sseu->compute_subslice_mask.b,
+		  sseu->geometry_subslice_mask.b,
+		  I915_MAX_SS_FUSE_BITS);
 
 	sseu->has_common_ss_eumask = 1;
 	sseu->eu_mask[0] = eu_en;
@@ -191,7 +215,8 @@ static void xehp_sseu_info_init(struct intel_gt *gt)
 {
 	struct sseu_dev_info *sseu = &gt->info.sseu;
 	struct intel_uncore *uncore = gt->uncore;
-	u32 g_dss_en, c_dss_en = 0;
+	intel_sseu_ss_mask_t g_dss_en = {}, c_dss_en = {};
+	u32 val;
 	u16 eu_en = 0;
 	u8 eu_en_fuse;
 	int eu;
@@ -204,8 +229,11 @@ static void xehp_sseu_info_init(struct intel_gt *gt)
 	 */
 	intel_sseu_set_info(sseu, 1, 32, 16);
 
-	g_dss_en = intel_uncore_read(uncore, GEN12_GT_GEOMETRY_DSS_ENABLE);
-	c_dss_en = intel_uncore_read(uncore, GEN12_GT_COMPUTE_DSS_ENABLE);
+	val = intel_uncore_read(uncore, GEN12_GT_GEOMETRY_DSS_ENABLE);
+	bitmap_from_arr32(g_dss_en.b, &val, 32);
+
+	val = intel_uncore_read(uncore, GEN12_GT_COMPUTE_DSS_ENABLE);
+	bitmap_from_arr32(c_dss_en.b, &val, 32);
 
 	eu_en_fuse = intel_uncore_read(uncore, XEHP_EU_ENABLE) & XEHP_EU_ENA_MASK;
 
@@ -220,7 +248,8 @@ static void gen12_sseu_info_init(struct intel_gt *gt)
 {
 	struct sseu_dev_info *sseu = &gt->info.sseu;
 	struct intel_uncore *uncore = gt->uncore;
-	u32 g_dss_en;
+	intel_sseu_ss_mask_t g_dss_en = {}, empty_mask = {};
+	u32 val;
 	u16 eu_en = 0;
 	u8 eu_en_fuse;
 	u8 s_en;
@@ -243,7 +272,8 @@ static void gen12_sseu_info_init(struct intel_gt *gt)
 		drm_dbg(&gt->i915->drm, "Slice mask %#x is not the expected 0x1!\n",
 			s_en);
 
-	g_dss_en = intel_uncore_read(uncore, GEN12_GT_GEOMETRY_DSS_ENABLE);
+	val = intel_uncore_read(uncore, GEN12_GT_GEOMETRY_DSS_ENABLE);
+	bitmap_from_arr32(g_dss_en.b, &val, 32);
 
 	/* one bit per pair of EUs */
 	eu_en_fuse = ~(intel_uncore_read(uncore, GEN11_EU_DISABLE) &
@@ -253,7 +283,7 @@ static void gen12_sseu_info_init(struct intel_gt *gt)
 		if (eu_en_fuse & BIT(eu))
 			eu_en |= BIT(eu * 2) | BIT(eu * 2 + 1);
 
-	gen11_compute_sseu_info(sseu, g_dss_en, 0, eu_en);
+	gen11_compute_sseu_info(sseu, g_dss_en, empty_mask, eu_en);
 
 	/* TGL only supports slice-level power gating */
 	sseu->has_slice_pg = 1;
@@ -263,7 +293,8 @@ static void gen11_sseu_info_init(struct intel_gt *gt)
 {
 	struct sseu_dev_info *sseu = &gt->info.sseu;
 	struct intel_uncore *uncore = gt->uncore;
-	u32 ss_en;
+	intel_sseu_ss_mask_t ss_en = {}, empty_mask = {};
+	u32 val;
 	u8 eu_en;
 	u8 s_en;
 
@@ -282,12 +313,13 @@ static void gen11_sseu_info_init(struct intel_gt *gt)
 		drm_dbg(&gt->i915->drm, "Slice mask %#x is not the expected 0x1!\n",
 			s_en);
 
-	ss_en = ~intel_uncore_read(uncore, GEN11_GT_SUBSLICE_DISABLE);
+	val = ~intel_uncore_read(uncore, GEN11_GT_SUBSLICE_DISABLE);
+	bitmap_from_arr32(ss_en.b, &val, 32);
 
 	eu_en = ~(intel_uncore_read(uncore, GEN11_EU_DISABLE) &
 		  GEN11_EU_DIS_MASK);
 
-	gen11_compute_sseu_info(sseu, ss_en, 0, eu_en);
+	gen11_compute_sseu_info(sseu, ss_en, empty_mask, eu_en);
 
 	/* ICL has no power gating restrictions. */
 	sseu->has_slice_pg = 1;
@@ -328,7 +360,7 @@ static void cherryview_sseu_info_init(struct intel_gt *gt)
 		sseu_set_eus(sseu, 0, 1, ~disabled_mask);
 	}
 
-	intel_sseu_set_subslices(sseu, 0, sseu->subslice_mask, subslice_mask);
+	set_subslices(sseu, 0, subslice_mask);
 
 	sseu->eu_total = compute_eu_total(sseu);
 
@@ -384,8 +416,7 @@ static void gen9_sseu_info_init(struct intel_gt *gt)
 			/* skip disabled slice */
 			continue;
 
-		intel_sseu_set_subslices(sseu, s, sseu->subslice_mask,
-					 subslice_mask);
+		set_subslices(sseu, s, subslice_mask);
 
 		eu_disable = intel_uncore_read(uncore, GEN9_EU_DISABLE(s));
 		for (ss = 0; ss < sseu->max_subslices; ss++) {
@@ -442,8 +473,8 @@ static void gen9_sseu_info_init(struct intel_gt *gt)
 	sseu->has_eu_pg = sseu->eu_per_subslice > 2;
 
 	if (IS_GEN9_LP(i915)) {
-#define IS_SS_DISABLED(ss)	(!(sseu->subslice_mask[0] & BIT(ss)))
-		info->has_pooled_eu = hweight8(sseu->subslice_mask[0]) == 3;
+#define IS_SS_DISABLED(ss)	test_bit(ss, sseu->subslice_mask.b)
+		info->has_pooled_eu = hweight8(sseu->subslice_mask.b[0]) == 3;
 
 		sseu->min_eu_in_pool = 0;
 		if (info->has_pooled_eu) {
@@ -497,8 +528,7 @@ static void bdw_sseu_info_init(struct intel_gt *gt)
 			/* skip disabled slice */
 			continue;
 
-		intel_sseu_set_subslices(sseu, s, sseu->subslice_mask,
-					 subslice_mask);
+		set_subslices(sseu, s, subslice_mask);
 
 		for (ss = 0; ss < sseu->max_subslices; ss++) {
 			u8 eu_disabled_mask;
@@ -595,8 +625,7 @@ static void hsw_sseu_info_init(struct intel_gt *gt)
 			    sseu->eu_per_subslice);
 
 	for (s = 0; s < sseu->max_slices; s++) {
-		intel_sseu_set_subslices(sseu, s, sseu->subslice_mask,
-					 subslice_mask);
+		set_subslices(sseu, s, subslice_mask);
 
 		for (ss = 0; ss < sseu->max_subslices; ss++) {
 			sseu_set_eus(sseu, s, ss,
@@ -685,7 +714,7 @@ u32 intel_sseu_make_rpcs(struct intel_gt *gt,
 	 */
 	if (GRAPHICS_VER(i915) == 11 &&
 	    slices == 1 &&
-	    subslices > min_t(u8, 4, hweight8(sseu->subslice_mask[0]) / 2)) {
+	    subslices > min_t(u8, 4, hweight8(sseu->subslice_mask.b[0]) / 2)) {
 		GEM_BUG_ON(subslices & 1);
 
 		subslice_pg = false;
@@ -755,9 +784,11 @@ void intel_sseu_dump(const struct sseu_dev_info *sseu, struct drm_printer *p)
 		   hweight8(sseu->slice_mask), sseu->slice_mask);
 	drm_printf(p, "subslice total: %u\n", intel_sseu_subslice_total(sseu));
 	for (s = 0; s < sseu->max_slices; s++) {
-		drm_printf(p, "slice%d: %u subslices, mask=%08x\n",
-			   s, intel_sseu_subslices_per_slice(sseu, s),
-			   intel_sseu_get_subslices(sseu, s));
+		intel_sseu_ss_mask_t ssmask = intel_sseu_get_subslices(sseu, s);
+
+		drm_printf(p, "slice%d: %u subslices, mask=%*pb\n",
+			   s, bitmap_weight(ssmask.b, I915_MAX_SS_FUSE_BITS),
+			   I915_MAX_SS_FUSE_BITS, ssmask.b);
 	}
 	drm_printf(p, "EU total: %u\n", sseu->eu_total);
 	drm_printf(p, "EU per subslice: %u\n", sseu->eu_per_subslice);
@@ -775,9 +806,11 @@ static void sseu_print_hsw_topology(const struct sseu_dev_info *sseu,
 	int s, ss;
 
 	for (s = 0; s < sseu->max_slices; s++) {
-		drm_printf(p, "slice%d: %u subslice(s) (0x%08x):\n",
-			   s, intel_sseu_subslices_per_slice(sseu, s),
-			   intel_sseu_get_subslices(sseu, s));
+		intel_sseu_ss_mask_t ssmask = intel_sseu_get_subslices(sseu, s);
+
+		drm_printf(p, "slice%d: %u subslice(s) (0x%*pb):\n",
+			   s, bitmap_weight(ssmask.b, I915_MAX_SS_FUSE_BITS),
+			   I915_MAX_SS_FUSE_BITS, ssmask.b);
 
 		for (ss = 0; ss < sseu->max_subslices; ss++) {
 			u16 enabled_eus = sseu_get_eus(sseu, s, ss);
@@ -791,16 +824,14 @@ static void sseu_print_hsw_topology(const struct sseu_dev_info *sseu,
 static void sseu_print_xehp_topology(const struct sseu_dev_info *sseu,
 				     struct drm_printer *p)
 {
-	u32 g_dss_mask = sseu_get_geometry_subslices(sseu);
-	u32 c_dss_mask = intel_sseu_get_compute_subslices(sseu);
 	int dss;
 
 	for (dss = 0; dss < sseu->max_subslices; dss++) {
 		u16 enabled_eus = sseu_get_eus(sseu, 0, dss);
 
 		drm_printf(p, "DSS_%02d: G:%3s C:%3s, %2u EUs (0x%04hx)\n", dss,
-			   str_yes_no(g_dss_mask & BIT(dss)),
-			   str_yes_no(c_dss_mask & BIT(dss)),
+			   str_yes_no(test_bit(dss, sseu->geometry_subslice_mask.b)),
+			   str_yes_no(test_bit(dss, sseu->compute_subslice_mask.b)),
 			   hweight16(enabled_eus), enabled_eus);
 	}
 }
@@ -818,20 +849,24 @@ void intel_sseu_print_topology(struct drm_i915_private *i915,
 	}
 }
 
-u16 intel_slicemask_from_dssmask(u64 dss_mask, int dss_per_slice)
+u16 intel_slicemask_from_dssmask(intel_sseu_ss_mask_t dss_mask,
+				 int dss_per_slice)
 {
+	intel_sseu_ss_mask_t per_slice_mask = {};
 	u16 slice_mask = 0;
 	int i;
 
-	WARN_ON(sizeof(dss_mask) * 8 / dss_per_slice > 8 * sizeof(slice_mask));
+	WARN_ON(DIV_ROUND_UP(I915_MAX_SS_FUSE_BITS, dss_per_slice) >
+		8 * sizeof(slice_mask));
 
-	for (i = 0; dss_mask; i++) {
-		if (dss_mask & GENMASK(dss_per_slice - 1, 0))
+	bitmap_fill(per_slice_mask.b, dss_per_slice);
+	for (i = 0; !bitmap_empty(dss_mask.b, I915_MAX_SS_FUSE_BITS); i++) {
+		if (bitmap_intersects(dss_mask.b, per_slice_mask.b, dss_per_slice))
 			slice_mask |= BIT(i);
 
-		dss_mask >>= dss_per_slice;
+		bitmap_shift_right(dss_mask.b, dss_mask.b, dss_per_slice,
+				   I915_MAX_SS_FUSE_BITS);
 	}
 
 	return slice_mask;
 }
-
diff --git a/drivers/gpu/drm/i915/gt/intel_sseu.h b/drivers/gpu/drm/i915/gt/intel_sseu.h
index 106726a2244e..455f085093ae 100644
--- a/drivers/gpu/drm/i915/gt/intel_sseu.h
+++ b/drivers/gpu/drm/i915/gt/intel_sseu.h
@@ -52,11 +52,22 @@ struct drm_printer;
 #define GEN_MAX_GSLICES		(GEN_MAX_DSS / GEN_DSS_PER_GSLICE)
 #define GEN_MAX_CSLICES		(GEN_MAX_DSS / GEN_DSS_PER_CSLICE)
 
+/*
+ * Maximum number of 32-bit registers used by hardware to express the
+ * enabled/disabled subslices.
+ */
+#define I915_MAX_SS_FUSE_REGS	1
+#define I915_MAX_SS_FUSE_BITS	(I915_MAX_SS_FUSE_REGS * 32)
+
+typedef struct {
+	unsigned long b[BITS_TO_LONGS(I915_MAX_SS_FUSE_BITS)];
+} intel_sseu_ss_mask_t;
+
 struct sseu_dev_info {
 	u8 slice_mask;
-	u8 subslice_mask[GEN_SS_MASK_SIZE];
-	u8 geometry_subslice_mask[GEN_SS_MASK_SIZE];
-	u8 compute_subslice_mask[GEN_SS_MASK_SIZE];
+	intel_sseu_ss_mask_t subslice_mask;
+	intel_sseu_ss_mask_t geometry_subslice_mask;
+	intel_sseu_ss_mask_t compute_subslice_mask;
 
 	/*
 	 * EU masks.  Use has_common_ss_eumask to determine how the field
@@ -107,7 +118,7 @@ intel_sseu_from_device_info(const struct sseu_dev_info *sseu)
 {
 	struct intel_sseu value = {
 		.slice_mask = sseu->slice_mask,
-		.subslice_mask = sseu->subslice_mask[0],
+		.subslice_mask = sseu->subslice_mask.b[0],
 		.min_eus_per_subslice = sseu->max_eus_per_subslice,
 		.max_eus_per_subslice = sseu->max_eus_per_subslice,
 	};
@@ -119,18 +130,8 @@ static inline bool
 intel_sseu_has_subslice(const struct sseu_dev_info *sseu, int slice,
 			int subslice)
 {
-	u8 mask;
-	int ss_idx = subslice / BITS_PER_BYTE;
-
-	if (slice >= sseu->max_slices ||
-	    subslice >= sseu->max_subslices)
-		return false;
-
-	GEM_BUG_ON(ss_idx >= sseu->ss_stride);
-
-	mask = sseu->subslice_mask[slice * sseu->ss_stride + ss_idx];
-
-	return mask & BIT(subslice % BITS_PER_BYTE);
+	return test_bit(slice * sseu->ss_stride + subslice,
+			sseu->subslice_mask.b);
 }
 
 void intel_sseu_set_info(struct sseu_dev_info *sseu, u8 max_slices,
@@ -139,15 +140,14 @@ void intel_sseu_set_info(struct sseu_dev_info *sseu, u8 max_slices,
 unsigned int
 intel_sseu_subslice_total(const struct sseu_dev_info *sseu);
 
-unsigned int
-intel_sseu_subslices_per_slice(const struct sseu_dev_info *sseu, u8 slice);
+intel_sseu_ss_mask_t
+intel_sseu_get_subslices(const struct sseu_dev_info *sseu, u8 slice);
 
-u32 intel_sseu_get_subslices(const struct sseu_dev_info *sseu, u8 slice);
-
-u32 intel_sseu_get_compute_subslices(const struct sseu_dev_info *sseu);
+intel_sseu_ss_mask_t
+intel_sseu_get_compute_subslices(const struct sseu_dev_info *sseu);
 
 void intel_sseu_set_subslices(struct sseu_dev_info *sseu, int slice,
-			      u8 *subslice_mask, u32 ss_mask);
+			      u32 ss_mask);
 
 void intel_sseu_info_init(struct intel_gt *gt);
 
@@ -159,9 +159,11 @@ void intel_sseu_print_topology(struct drm_i915_private *i915,
 			       const struct sseu_dev_info *sseu,
 			       struct drm_printer *p);
 
-u16 intel_slicemask_from_dssmask(u64 dss_mask, int dss_per_slice);
+u16 intel_slicemask_from_dssmask(intel_sseu_ss_mask_t dss_mask, int dss_per_slice);
 
 int intel_sseu_copy_eumask_to_user(void __user *to,
 				   const struct sseu_dev_info *sseu);
+int intel_sseu_copy_ssmask_to_user(void __user *to,
+				   const struct sseu_dev_info *sseu);
 
 #endif /* __INTEL_SSEU_H__ */
diff --git a/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c b/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c
index 2d5d011e01db..1f77bd52a3a6 100644
--- a/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c
+++ b/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c
@@ -4,6 +4,7 @@
  * Copyright © 2020 Intel Corporation
  */
 
+#include <linux/bitmap.h>
 #include <linux/string_helpers.h>
 
 #include "i915_drv.h"
@@ -12,11 +13,15 @@
 #include "intel_sseu_debugfs.h"
 
 static void sseu_copy_subslices(const struct sseu_dev_info *sseu,
-				int slice, u8 *to_mask)
+				int slice,
+				intel_sseu_ss_mask_t *to_mask)
 {
-	int offset = slice * sseu->ss_stride;
+	int offset = slice * sseu->max_subslices;
 
-	memcpy(&to_mask[offset], &sseu->subslice_mask[offset], sseu->ss_stride);
+	bitmap_fill(to_mask->b, sseu->max_subslices);
+	bitmap_shift_left(to_mask->b, to_mask->b, offset, I915_MAX_SS_FUSE_BITS);
+	bitmap_and(to_mask->b, to_mask->b, sseu->subslice_mask.b, I915_MAX_SS_FUSE_BITS);
+	bitmap_shift_right(to_mask->b, to_mask->b, offset, I915_MAX_SS_FUSE_BITS);
 }
 
 static void cherryview_sseu_device_status(struct intel_gt *gt,
@@ -41,7 +46,7 @@ static void cherryview_sseu_device_status(struct intel_gt *gt,
 			continue;
 
 		sseu->slice_mask = BIT(0);
-		sseu->subslice_mask[0] |= BIT(ss);
+		set_bit(0, sseu->subslice_mask.b);
 		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) +
@@ -92,7 +97,7 @@ static void gen11_sseu_device_status(struct intel_gt *gt,
 			continue;
 
 		sseu->slice_mask |= BIT(s);
-		sseu_copy_subslices(&info->sseu, s, sseu->subslice_mask);
+		sseu_copy_subslices(&info->sseu, s, &sseu->subslice_mask);
 
 		for (ss = 0; ss < info->sseu.max_subslices; ss++) {
 			unsigned int eu_cnt;
@@ -148,20 +153,17 @@ static void gen9_sseu_device_status(struct intel_gt *gt,
 
 		if (IS_GEN9_BC(gt->i915))
 			sseu_copy_subslices(&info->sseu, s,
-					    sseu->subslice_mask);
+					    &sseu->subslice_mask);
 
 		for (ss = 0; ss < info->sseu.max_subslices; ss++) {
 			unsigned int eu_cnt;
-			u8 ss_idx = s * info->sseu.ss_stride +
-				    ss / BITS_PER_BYTE;
 
 			if (IS_GEN9_LP(gt->i915)) {
 				if (!(s_reg[s] & (GEN9_PGCTL_SS_ACK(ss))))
 					/* skip disabled subslice */
 					continue;
 
-				sseu->subslice_mask[ss_idx] |=
-					BIT(ss % BITS_PER_BYTE);
+				set_bit(ss, sseu->subslice_mask.b);
 			}
 
 			eu_cnt = eu_reg[2 * s + ss / 2] & eu_mask[ss % 2];
@@ -189,7 +191,7 @@ static void bdw_sseu_device_status(struct intel_gt *gt,
 		sseu->eu_per_subslice = info->sseu.eu_per_subslice;
 		for (s = 0; s < fls(sseu->slice_mask); s++)
 			sseu_copy_subslices(&info->sseu, s,
-					    sseu->subslice_mask);
+					    &sseu->subslice_mask);
 		sseu->eu_total = sseu->eu_per_subslice *
 				 intel_sseu_subslice_total(sseu);
 
@@ -217,8 +219,10 @@ static void i915_print_sseu_info(struct seq_file *m,
 	seq_printf(m, "  %s Subslice Total: %u\n", type,
 		   intel_sseu_subslice_total(sseu));
 	for (s = 0; s < fls(sseu->slice_mask); s++) {
+		intel_sseu_ss_mask_t ssmask = intel_sseu_get_subslices(sseu, s);
+
 		seq_printf(m, "  %s Slice%i subslices: %u\n", type,
-			   s, intel_sseu_subslices_per_slice(sseu, s));
+			   s, bitmap_weight(ssmask.b, I915_MAX_SS_FUSE_BITS));
 	}
 	seq_printf(m, "  %s EU Total: %u\n", type,
 		   sseu->eu_total);
diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c
index a05c4b99b3fb..5db492072f99 100644
--- a/drivers/gpu/drm/i915/gt/intel_workarounds.c
+++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c
@@ -931,6 +931,7 @@ static void
 gen9_wa_init_mcr(struct drm_i915_private *i915, struct i915_wa_list *wal)
 {
 	const struct sseu_dev_info *sseu = &to_gt(i915)->info.sseu;
+	intel_sseu_ss_mask_t ssmask;
 	unsigned int slice, subslice;
 	u32 mcr, mcr_mask;
 
@@ -948,9 +949,9 @@ gen9_wa_init_mcr(struct drm_i915_private *i915, struct i915_wa_list *wal)
 	 * on s/ss combo, the read should be done with read_subslice_reg.
 	 */
 	slice = ffs(sseu->slice_mask) - 1;
-	GEM_BUG_ON(slice >= ARRAY_SIZE(sseu->subslice_mask));
-	subslice = ffs(intel_sseu_get_subslices(sseu, slice));
-	GEM_BUG_ON(!subslice);
+	ssmask = intel_sseu_get_subslices(sseu, slice);
+	subslice = find_first_bit(ssmask.b, I915_MAX_SS_FUSE_BITS);
+	GEM_BUG_ON(subslice == I915_MAX_SS_FUSE_BITS);
 	subslice--;
 
 	/*
@@ -1087,11 +1088,10 @@ static void
 icl_wa_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
 {
 	const struct sseu_dev_info *sseu = &gt->info.sseu;
-	unsigned int slice, subslice;
+	unsigned int subslice;
 
 	GEM_BUG_ON(GRAPHICS_VER(gt->i915) < 11);
 	GEM_BUG_ON(hweight8(sseu->slice_mask) > 1);
-	slice = 0;
 
 	/*
 	 * Although a platform may have subslices, we need to always steer
@@ -1102,7 +1102,7 @@ icl_wa_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
 	 * one of the higher subslices, we run the risk of reading back 0's or
 	 * random garbage.
 	 */
-	subslice = __ffs(intel_sseu_get_subslices(sseu, slice));
+	subslice = find_first_bit(sseu->subslice_mask.b, I915_MAX_SS_FUSE_BITS);
 
 	/*
 	 * If the subslice we picked above also steers us to a valid L3 bank,
@@ -1112,7 +1112,7 @@ icl_wa_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
 	if (gt->info.l3bank_mask & BIT(subslice))
 		gt->steering_table[L3BANK] = NULL;
 
-	__add_mcr_wa(gt, wal, slice, subslice);
+	__add_mcr_wa(gt, wal, 0, subslice);
 }
 
 static void
@@ -1120,7 +1120,6 @@ xehp_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
 {
 	const struct sseu_dev_info *sseu = &gt->info.sseu;
 	unsigned long slice, subslice = 0, slice_mask = 0;
-	u64 dss_mask = 0;
 	u32 lncf_mask = 0;
 	int i;
 
@@ -1151,8 +1150,8 @@ xehp_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
 	 */
 
 	/* Find the potential gslice candidates */
-	dss_mask = intel_sseu_get_subslices(sseu, 0);
-	slice_mask = intel_slicemask_from_dssmask(dss_mask, GEN_DSS_PER_GSLICE);
+	slice_mask = intel_slicemask_from_dssmask(sseu->subslice_mask,
+						  GEN_DSS_PER_GSLICE);
 
 	/*
 	 * Find the potential LNCF candidates.  Either LNCF within a valid
@@ -1177,9 +1176,9 @@ xehp_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
 	}
 
 	slice = __ffs(slice_mask);
-	subslice = __ffs(dss_mask >> (slice * GEN_DSS_PER_GSLICE));
+	subslice = find_next_bit(sseu->subslice_mask.b, I915_MAX_SS_FUSE_BITS,
+				 slice * GEN_DSS_PER_GSLICE);
 	WARN_ON(subslice > GEN_DSS_PER_GSLICE);
-	WARN_ON(dss_mask >> (slice * GEN_DSS_PER_GSLICE) == 0);
 
 	__add_mcr_wa(gt, wal, slice, subslice);
 
@@ -2012,9 +2011,8 @@ engine_fake_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
 
 static bool needs_wa_1308578152(struct intel_engine_cs *engine)
 {
-	u64 dss_mask = intel_sseu_get_subslices(&engine->gt->info.sseu, 0);
-
-	return (dss_mask & GENMASK(GEN_DSS_PER_GSLICE - 1, 0)) == 0;
+	return find_first_bit(engine->gt->info.sseu.subslice_mask.b,
+			      I915_MAX_SS_FUSE_BITS) >= GEN_DSS_PER_GSLICE;
 }
 
 static void
diff --git a/drivers/gpu/drm/i915/i915_getparam.c b/drivers/gpu/drm/i915/i915_getparam.c
index ac9767c56619..349d496d164a 100644
--- a/drivers/gpu/drm/i915/i915_getparam.c
+++ b/drivers/gpu/drm/i915/i915_getparam.c
@@ -162,7 +162,7 @@ int i915_getparam_ioctl(struct drm_device *dev, void *data,
 			return -EINVAL;
 
 		/* Only copy bits from the first slice */
-		memcpy(&value, sseu->subslice_mask,
+		memcpy(&value, sseu->subslice_mask.b,
 		       min(sseu->ss_stride, (u8)sizeof(value)));
 		if (!value)
 			return -ENODEV;
diff --git a/drivers/gpu/drm/i915/i915_query.c b/drivers/gpu/drm/i915/i915_query.c
index 16f43bf32a05..9afa6d1eaf95 100644
--- a/drivers/gpu/drm/i915/i915_query.c
+++ b/drivers/gpu/drm/i915/i915_query.c
@@ -31,7 +31,7 @@ static int copy_query_item(void *query_hdr, size_t query_sz,
 
 static int fill_topology_info(const struct sseu_dev_info *sseu,
 			      struct drm_i915_query_item *query_item,
-			      const u8 *subslice_mask)
+			      intel_sseu_ss_mask_t subslice_mask)
 {
 	struct drm_i915_query_topology_info topo;
 	u32 slice_length, subslice_length, eu_length, total_length;
@@ -71,9 +71,9 @@ static int fill_topology_info(const struct sseu_dev_info *sseu,
 			 &sseu->slice_mask, slice_length))
 		return -EFAULT;
 
-	if (copy_to_user(u64_to_user_ptr(query_item->data_ptr +
-					 sizeof(topo) + slice_length),
-			 subslice_mask, subslice_length))
+	if (intel_sseu_copy_ssmask_to_user(u64_to_user_ptr(query_item->data_ptr +
+							   sizeof(topo) + slice_length),
+					   sseu))
 		return -EFAULT;
 
 	if (intel_sseu_copy_eumask_to_user(u64_to_user_ptr(query_item->data_ptr +
-- 
2.35.1


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

* [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for i915: SSEU handling updates
  2022-04-27 23:07 ` [Intel-gfx] " Matt Roper
                   ` (5 preceding siblings ...)
  (?)
@ 2022-04-27 23:26 ` Patchwork
  -1 siblings, 0 replies; 27+ messages in thread
From: Patchwork @ 2022-04-27 23:26 UTC (permalink / raw)
  To: Matt Roper; +Cc: intel-gfx

== Series Details ==

Series: i915: SSEU handling updates
URL   : https://patchwork.freedesktop.org/series/103244/
State : warning

== Summary ==

Error: dim checkpatch failed
55dde4d186fd drm/i915/sseu: Don't try to store EU mask internally in UAPI format
313094aca5e5 drm/i915/xehp: Drop GETPARAM lookups of I915_PARAM_[SUB]SLICE_MASK
706b98dc34e8 drm/i915/xehp: Use separate sseu init function
d03e472adee0 drm/i915/sseu: Simplify gen11+ SSEU handling
d98bc53c851d drm/i915/sseu: Disassociate internal subslice mask representation from uapi
-:485: WARNING:NEW_TYPEDEFS: do not add new typedefs
#485: FILE: drivers/gpu/drm/i915/gt/intel_sseu.h:62:
+typedef struct {

total: 0 errors, 1 warnings, 0 checks, 690 lines checked



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

* [Intel-gfx] ✗ Fi.CI.SPARSE: warning for i915: SSEU handling updates
  2022-04-27 23:07 ` [Intel-gfx] " Matt Roper
                   ` (6 preceding siblings ...)
  (?)
@ 2022-04-27 23:26 ` Patchwork
  -1 siblings, 0 replies; 27+ messages in thread
From: Patchwork @ 2022-04-27 23:26 UTC (permalink / raw)
  To: Matt Roper; +Cc: intel-gfx

== Series Details ==

Series: i915: SSEU handling updates
URL   : https://patchwork.freedesktop.org/series/103244/
State : warning

== Summary ==

Error: dim sparse failed
Sparse version: v0.6.2
Fast mode used, each commit won't be checked separately.



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

* [Intel-gfx] ✗ Fi.CI.BAT: failure for i915: SSEU handling updates
  2022-04-27 23:07 ` [Intel-gfx] " Matt Roper
                   ` (7 preceding siblings ...)
  (?)
@ 2022-04-27 23:55 ` Patchwork
  -1 siblings, 0 replies; 27+ messages in thread
From: Patchwork @ 2022-04-27 23:55 UTC (permalink / raw)
  To: Matt Roper; +Cc: intel-gfx

[-- Attachment #1: Type: text/plain, Size: 15839 bytes --]

== Series Details ==

Series: i915: SSEU handling updates
URL   : https://patchwork.freedesktop.org/series/103244/
State : failure

== Summary ==

CI Bug Log - changes from CI_DRM_11550 -> Patchwork_103244v1
====================================================

Summary
-------

  **FAILURE**

  Serious unknown changes coming with Patchwork_103244v1 absolutely need to be
  verified manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in Patchwork_103244v1, please notify your bug team to allow them
  to document this new failure mode, which will reduce false positives in CI.

  External URL: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v1/index.html

Participating hosts (43 -> 44)
------------------------------

  Additional (4): bat-dg2-8 fi-icl-u2 bat-dg1-6 bat-adlp-4 
  Missing    (3): fi-bsw-cyan bat-rpls-2 bat-jsl-2 

Possible new issues
-------------------

  Here are the unknown changes that may have been introduced in Patchwork_103244v1:

### IGT changes ###

#### Possible regressions ####

  * igt@i915_selftest@live:
    - bat-adlp-4:         NOTRUN -> [INCOMPLETE][1]
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v1/bat-adlp-4/igt@i915_selftest@live.html

  
#### Suppressed ####

  The following results come from untrusted machines, tests, or statuses.
  They do not affect the overall result.

  * igt@i915_selftest@live@execlists:
    - {bat-rpls-1}:       NOTRUN -> [INCOMPLETE][2]
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v1/bat-rpls-1/igt@i915_selftest@live@execlists.html

  
Known issues
------------

  Here are the changes found in Patchwork_103244v1 that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@gem_exec_suspend@basic-s0@smem:
    - bat-dg1-6:          NOTRUN -> [INCOMPLETE][3] ([i915#5827])
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v1/bat-dg1-6/igt@gem_exec_suspend@basic-s0@smem.html

  * igt@gem_huc_copy@huc-copy:
    - fi-icl-u2:          NOTRUN -> [SKIP][4] ([i915#2190])
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v1/fi-icl-u2/igt@gem_huc_copy@huc-copy.html

  * igt@gem_lmem_swapping@basic:
    - bat-adlp-4:         NOTRUN -> [SKIP][5] ([i915#4613]) +3 similar issues
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v1/bat-adlp-4/igt@gem_lmem_swapping@basic.html

  * igt@gem_lmem_swapping@parallel-random-engines:
    - fi-icl-u2:          NOTRUN -> [SKIP][6] ([i915#4613]) +3 similar issues
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v1/fi-icl-u2/igt@gem_lmem_swapping@parallel-random-engines.html

  * igt@gem_tiled_pread_basic:
    - bat-adlp-4:         NOTRUN -> [SKIP][7] ([i915#3282])
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v1/bat-adlp-4/igt@gem_tiled_pread_basic.html

  * igt@kms_chamelium@dp-crc-fast:
    - bat-adlp-4:         NOTRUN -> [SKIP][8] ([fdo#111827]) +8 similar issues
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v1/bat-adlp-4/igt@kms_chamelium@dp-crc-fast.html

  * igt@kms_chamelium@hdmi-hpd-fast:
    - fi-icl-u2:          NOTRUN -> [SKIP][9] ([fdo#111827]) +8 similar issues
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v1/fi-icl-u2/igt@kms_chamelium@hdmi-hpd-fast.html

  * igt@kms_cursor_legacy@basic-busy-flip-before-cursor-legacy:
    - fi-icl-u2:          NOTRUN -> [SKIP][10] ([fdo#109278]) +2 similar issues
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v1/fi-icl-u2/igt@kms_cursor_legacy@basic-busy-flip-before-cursor-legacy.html
    - bat-adlp-4:         NOTRUN -> [SKIP][11] ([i915#4103]) +1 similar issue
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v1/bat-adlp-4/igt@kms_cursor_legacy@basic-busy-flip-before-cursor-legacy.html

  * igt@kms_flip@basic-flip-vs-modeset@a-edp1:
    - bat-adlp-4:         NOTRUN -> [DMESG-WARN][12] ([i915#3576])
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v1/bat-adlp-4/igt@kms_flip@basic-flip-vs-modeset@a-edp1.html

  * igt@kms_force_connector_basic@force-load-detect:
    - fi-icl-u2:          NOTRUN -> [SKIP][13] ([fdo#109285])
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v1/fi-icl-u2/igt@kms_force_connector_basic@force-load-detect.html

  * igt@kms_force_connector_basic@prune-stale-modes:
    - bat-adlp-4:         NOTRUN -> [SKIP][14] ([i915#4093]) +3 similar issues
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v1/bat-adlp-4/igt@kms_force_connector_basic@prune-stale-modes.html

  * igt@kms_setmode@basic-clone-single-crtc:
    - fi-icl-u2:          NOTRUN -> [SKIP][15] ([i915#3555])
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v1/fi-icl-u2/igt@kms_setmode@basic-clone-single-crtc.html
    - bat-adlp-4:         NOTRUN -> [SKIP][16] ([i915#3555])
   [16]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v1/bat-adlp-4/igt@kms_setmode@basic-clone-single-crtc.html

  * igt@prime_vgem@basic-fence-read:
    - bat-adlp-4:         NOTRUN -> [SKIP][17] ([i915#3291] / [i915#3708]) +2 similar issues
   [17]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v1/bat-adlp-4/igt@prime_vgem@basic-fence-read.html

  * igt@prime_vgem@basic-userptr:
    - fi-icl-u2:          NOTRUN -> [SKIP][18] ([i915#3301])
   [18]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v1/fi-icl-u2/igt@prime_vgem@basic-userptr.html
    - bat-adlp-4:         NOTRUN -> [SKIP][19] ([i915#3301] / [i915#3708])
   [19]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v1/bat-adlp-4/igt@prime_vgem@basic-userptr.html

  
#### Possible fixes ####

  * igt@i915_selftest@live@gt_heartbeat:
    - fi-cfl-guc:         [DMESG-FAIL][20] ([i915#5334]) -> [PASS][21]
   [20]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/fi-cfl-guc/igt@i915_selftest@live@gt_heartbeat.html
   [21]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v1/fi-cfl-guc/igt@i915_selftest@live@gt_heartbeat.html

  * igt@i915_selftest@live@hangcheck:
    - fi-hsw-4770:        [INCOMPLETE][22] ([i915#4785]) -> [PASS][23]
   [22]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/fi-hsw-4770/igt@i915_selftest@live@hangcheck.html
   [23]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v1/fi-hsw-4770/igt@i915_selftest@live@hangcheck.html

  * igt@i915_selftest@live@hugepages:
    - {bat-rpls-1}:       [DMESG-WARN][24] ([i915#5278]) -> [PASS][25]
   [24]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/bat-rpls-1/igt@i915_selftest@live@hugepages.html
   [25]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v1/bat-rpls-1/igt@i915_selftest@live@hugepages.html

  * igt@i915_selftest@live@reset:
    - {bat-rpls-1}:       [DMESG-FAIL][26] ([i915#4983]) -> [PASS][27]
   [26]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/bat-rpls-1/igt@i915_selftest@live@reset.html
   [27]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v1/bat-rpls-1/igt@i915_selftest@live@reset.html

  * igt@kms_busy@basic@flip:
    - {bat-adlp-6}:       [DMESG-WARN][28] ([i915#3576]) -> [PASS][29] +1 similar issue
   [28]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/bat-adlp-6/igt@kms_busy@basic@flip.html
   [29]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v1/bat-adlp-6/igt@kms_busy@basic@flip.html

  
#### Warnings ####

  * igt@gem_exec_suspend@basic-s3@smem:
    - fi-rkl-11600:       [INCOMPLETE][30] ([i915#5127]) -> [INCOMPLETE][31] ([i915#5127] / [i915#5857])
   [30]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/fi-rkl-11600/igt@gem_exec_suspend@basic-s3@smem.html
   [31]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v1/fi-rkl-11600/igt@gem_exec_suspend@basic-s3@smem.html

  * igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c:
    - fi-kbl-7567u:       [SKIP][32] ([fdo#109271] / [i915#5341]) -> [SKIP][33] ([fdo#109271])
   [32]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/fi-kbl-7567u/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html
   [33]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v1/fi-kbl-7567u/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html
    - fi-pnv-d510:        [SKIP][34] ([fdo#109271] / [i915#5341]) -> [SKIP][35] ([fdo#109271])
   [34]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/fi-pnv-d510/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html
   [35]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v1/fi-pnv-d510/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html
    - fi-snb-2520m:       [SKIP][36] ([fdo#109271] / [i915#5341]) -> [SKIP][37] ([fdo#109271])
   [36]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/fi-snb-2520m/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html
   [37]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v1/fi-snb-2520m/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html
    - fi-bsw-kefka:       [SKIP][38] ([fdo#109271] / [i915#5341]) -> [SKIP][39] ([fdo#109271])
   [38]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/fi-bsw-kefka/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html
   [39]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v1/fi-bsw-kefka/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html
    - fi-kbl-8809g:       [SKIP][40] ([fdo#109271] / [i915#5341]) -> [SKIP][41] ([fdo#109271])
   [40]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/fi-kbl-8809g/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html
   [41]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v1/fi-kbl-8809g/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html
    - fi-bsw-nick:        [SKIP][42] ([fdo#109271] / [i915#5341]) -> [SKIP][43] ([fdo#109271])
   [42]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/fi-bsw-nick/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html
   [43]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v1/fi-bsw-nick/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html
    - fi-bwr-2160:        [SKIP][44] ([fdo#109271] / [i915#5341]) -> [SKIP][45] ([fdo#109271])
   [44]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/fi-bwr-2160/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html
   [45]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v1/fi-bwr-2160/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html
    - fi-snb-2600:        [SKIP][46] ([fdo#109271] / [i915#5341]) -> [SKIP][47] ([fdo#109271])
   [46]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/fi-snb-2600/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html
   [47]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v1/fi-snb-2600/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html
    - fi-elk-e7500:       [SKIP][48] ([fdo#109271] / [i915#5341]) -> [SKIP][49] ([fdo#109271])
   [48]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/fi-elk-e7500/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html
   [49]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v1/fi-elk-e7500/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html
    - fi-blb-e6850:       [SKIP][50] ([fdo#109271] / [i915#5341]) -> [SKIP][51] ([fdo#109271])
   [50]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/fi-blb-e6850/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html
   [51]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v1/fi-blb-e6850/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html
    - fi-ilk-650:         [SKIP][52] ([fdo#109271] / [i915#5341]) -> [SKIP][53] ([fdo#109271])
   [52]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/fi-ilk-650/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html
   [53]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v1/fi-ilk-650/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html

  
  {name}: This element is suppressed. This means it is ignored when computing
          the status of the difference (SUCCESS, WARNING, or FAILURE).

  [fdo#109271]: https://bugs.freedesktop.org/show_bug.cgi?id=109271
  [fdo#109278]: https://bugs.freedesktop.org/show_bug.cgi?id=109278
  [fdo#109285]: https://bugs.freedesktop.org/show_bug.cgi?id=109285
  [fdo#111827]: https://bugs.freedesktop.org/show_bug.cgi?id=111827
  [i915#1072]: https://gitlab.freedesktop.org/drm/intel/issues/1072
  [i915#1155]: https://gitlab.freedesktop.org/drm/intel/issues/1155
  [i915#2190]: https://gitlab.freedesktop.org/drm/intel/issues/2190
  [i915#2582]: https://gitlab.freedesktop.org/drm/intel/issues/2582
  [i915#3282]: https://gitlab.freedesktop.org/drm/intel/issues/3282
  [i915#3291]: https://gitlab.freedesktop.org/drm/intel/issues/3291
  [i915#3301]: https://gitlab.freedesktop.org/drm/intel/issues/3301
  [i915#3555]: https://gitlab.freedesktop.org/drm/intel/issues/3555
  [i915#3576]: https://gitlab.freedesktop.org/drm/intel/issues/3576
  [i915#3595]: https://gitlab.freedesktop.org/drm/intel/issues/3595
  [i915#3708]: https://gitlab.freedesktop.org/drm/intel/issues/3708
  [i915#4077]: https://gitlab.freedesktop.org/drm/intel/issues/4077
  [i915#4079]: https://gitlab.freedesktop.org/drm/intel/issues/4079
  [i915#4083]: https://gitlab.freedesktop.org/drm/intel/issues/4083
  [i915#4093]: https://gitlab.freedesktop.org/drm/intel/issues/4093
  [i915#4103]: https://gitlab.freedesktop.org/drm/intel/issues/4103
  [i915#4212]: https://gitlab.freedesktop.org/drm/intel/issues/4212
  [i915#4213]: https://gitlab.freedesktop.org/drm/intel/issues/4213
  [i915#4215]: https://gitlab.freedesktop.org/drm/intel/issues/4215
  [i915#4312]: https://gitlab.freedesktop.org/drm/intel/issues/4312
  [i915#4613]: https://gitlab.freedesktop.org/drm/intel/issues/4613
  [i915#4785]: https://gitlab.freedesktop.org/drm/intel/issues/4785
  [i915#4873]: https://gitlab.freedesktop.org/drm/intel/issues/4873
  [i915#4983]: https://gitlab.freedesktop.org/drm/intel/issues/4983
  [i915#5127]: https://gitlab.freedesktop.org/drm/intel/issues/5127
  [i915#5190]: https://gitlab.freedesktop.org/drm/intel/issues/5190
  [i915#5270]: https://gitlab.freedesktop.org/drm/intel/issues/5270
  [i915#5274]: https://gitlab.freedesktop.org/drm/intel/issues/5274
  [i915#5275]: https://gitlab.freedesktop.org/drm/intel/issues/5275
  [i915#5278]: https://gitlab.freedesktop.org/drm/intel/issues/5278
  [i915#5334]: https://gitlab.freedesktop.org/drm/intel/issues/5334
  [i915#5341]: https://gitlab.freedesktop.org/drm/intel/issues/5341
  [i915#5354]: https://gitlab.freedesktop.org/drm/intel/issues/5354
  [i915#5356]: https://gitlab.freedesktop.org/drm/intel/issues/5356
  [i915#5647]: https://gitlab.freedesktop.org/drm/intel/issues/5647
  [i915#5763]: https://gitlab.freedesktop.org/drm/intel/issues/5763
  [i915#5827]: https://gitlab.freedesktop.org/drm/intel/issues/5827
  [i915#5857]: https://gitlab.freedesktop.org/drm/intel/issues/5857


Build changes
-------------

  * Linux: CI_DRM_11550 -> Patchwork_103244v1

  CI-20190529: 20190529
  CI_DRM_11550: 56b089ae03ef8ea8ab7f474eaa70367898891ef0 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_6451: f055bd83bd831a938d639718c2359516224f15f9 @ https://gitlab.freedesktop.org/drm/igt-gpu-tools.git
  Patchwork_103244v1: 56b089ae03ef8ea8ab7f474eaa70367898891ef0 @ git://anongit.freedesktop.org/gfx-ci/linux


### Linux commits

56e42adedf3b drm/i915/sseu: Disassociate internal subslice mask representation from uapi
35ec8670cc4b drm/i915/sseu: Simplify gen11+ SSEU handling
5de08eebba13 drm/i915/xehp: Use separate sseu init function
4668670f995c drm/i915/xehp: Drop GETPARAM lookups of I915_PARAM_[SUB]SLICE_MASK
af193ec71bf8 drm/i915/sseu: Don't try to store EU mask internally in UAPI format

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v1/index.html

[-- Attachment #2: Type: text/html, Size: 18386 bytes --]

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

* [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for i915: SSEU handling updates (rev2)
  2022-04-27 23:07 ` [Intel-gfx] " Matt Roper
                   ` (8 preceding siblings ...)
  (?)
@ 2022-04-28  0:42 ` Patchwork
  -1 siblings, 0 replies; 27+ messages in thread
From: Patchwork @ 2022-04-28  0:42 UTC (permalink / raw)
  To: Matt Roper; +Cc: intel-gfx

== Series Details ==

Series: i915: SSEU handling updates (rev2)
URL   : https://patchwork.freedesktop.org/series/103244/
State : warning

== Summary ==

Error: dim checkpatch failed
721ef81dbce9 drm/i915/sseu: Don't try to store EU mask internally in UAPI format
91b82b1f6352 drm/i915/xehp: Drop GETPARAM lookups of I915_PARAM_[SUB]SLICE_MASK
b1d7cb90b2f3 drm/i915/xehp: Use separate sseu init function
24f87a81e92f drm/i915/sseu: Simplify gen11+ SSEU handling
0a3eeddf1db0 drm/i915/sseu: Disassociate internal subslice mask representation from uapi
-:485: WARNING:NEW_TYPEDEFS: do not add new typedefs
#485: FILE: drivers/gpu/drm/i915/gt/intel_sseu.h:62:
+typedef struct {

total: 0 errors, 1 warnings, 0 checks, 690 lines checked



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

* [Intel-gfx] ✗ Fi.CI.SPARSE: warning for i915: SSEU handling updates (rev2)
  2022-04-27 23:07 ` [Intel-gfx] " Matt Roper
                   ` (9 preceding siblings ...)
  (?)
@ 2022-04-28  0:42 ` Patchwork
  -1 siblings, 0 replies; 27+ messages in thread
From: Patchwork @ 2022-04-28  0:42 UTC (permalink / raw)
  To: Matt Roper; +Cc: intel-gfx

== Series Details ==

Series: i915: SSEU handling updates (rev2)
URL   : https://patchwork.freedesktop.org/series/103244/
State : warning

== Summary ==

Error: dim sparse failed
Sparse version: v0.6.2
Fast mode used, each commit won't be checked separately.



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

* [Intel-gfx] ✓ Fi.CI.BAT: success for i915: SSEU handling updates (rev2)
  2022-04-27 23:07 ` [Intel-gfx] " Matt Roper
                   ` (10 preceding siblings ...)
  (?)
@ 2022-04-28  1:11 ` Patchwork
  -1 siblings, 0 replies; 27+ messages in thread
From: Patchwork @ 2022-04-28  1:11 UTC (permalink / raw)
  To: Matt Roper; +Cc: intel-gfx

[-- Attachment #1: Type: text/plain, Size: 16244 bytes --]

== Series Details ==

Series: i915: SSEU handling updates (rev2)
URL   : https://patchwork.freedesktop.org/series/103244/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_11550 -> Patchwork_103244v2
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

  External URL: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/index.html

Participating hosts (43 -> 46)
------------------------------

  Additional (5): bat-dg1-6 bat-dg2-8 bat-adlm-1 fi-icl-u2 bat-adlp-4 
  Missing    (2): bat-rpls-2 fi-bsw-cyan 

Possible new issues
-------------------

  Here are the unknown changes that may have been introduced in Patchwork_103244v2:

### IGT changes ###

#### Suppressed ####

  The following results come from untrusted machines, tests, or statuses.
  They do not affect the overall result.

  * igt@dmabuf@all@dma_fence_chain:
    - {bat-rpls-1}:       NOTRUN -> [INCOMPLETE][1]
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/bat-rpls-1/igt@dmabuf@all@dma_fence_chain.html

  
Known issues
------------

  Here are the changes found in Patchwork_103244v2 that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@gem_exec_suspend@basic-s0@smem:
    - bat-dg1-6:          NOTRUN -> [INCOMPLETE][2] ([i915#5827])
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/bat-dg1-6/igt@gem_exec_suspend@basic-s0@smem.html

  * igt@gem_huc_copy@huc-copy:
    - fi-icl-u2:          NOTRUN -> [SKIP][3] ([i915#2190])
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/fi-icl-u2/igt@gem_huc_copy@huc-copy.html

  * igt@gem_lmem_swapping@basic:
    - bat-adlp-4:         NOTRUN -> [SKIP][4] ([i915#4613]) +3 similar issues
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/bat-adlp-4/igt@gem_lmem_swapping@basic.html

  * igt@gem_lmem_swapping@parallel-random-engines:
    - fi-icl-u2:          NOTRUN -> [SKIP][5] ([i915#4613]) +3 similar issues
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/fi-icl-u2/igt@gem_lmem_swapping@parallel-random-engines.html

  * igt@gem_tiled_pread_basic:
    - bat-adlp-4:         NOTRUN -> [SKIP][6] ([i915#3282])
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/bat-adlp-4/igt@gem_tiled_pread_basic.html

  * igt@i915_selftest@live@mman:
    - fi-bdw-5557u:       NOTRUN -> [INCOMPLETE][7] ([i915#5704])
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/fi-bdw-5557u/igt@i915_selftest@live@mman.html

  * igt@kms_chamelium@dp-crc-fast:
    - bat-adlp-4:         NOTRUN -> [SKIP][8] ([fdo#111827]) +8 similar issues
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/bat-adlp-4/igt@kms_chamelium@dp-crc-fast.html
    - fi-bdw-5557u:       NOTRUN -> [SKIP][9] ([fdo#109271] / [fdo#111827]) +8 similar issues
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/fi-bdw-5557u/igt@kms_chamelium@dp-crc-fast.html

  * igt@kms_chamelium@hdmi-hpd-fast:
    - fi-icl-u2:          NOTRUN -> [SKIP][10] ([fdo#111827]) +8 similar issues
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/fi-icl-u2/igt@kms_chamelium@hdmi-hpd-fast.html

  * igt@kms_cursor_legacy@basic-busy-flip-before-cursor-legacy:
    - fi-icl-u2:          NOTRUN -> [SKIP][11] ([fdo#109278]) +2 similar issues
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/fi-icl-u2/igt@kms_cursor_legacy@basic-busy-flip-before-cursor-legacy.html
    - bat-adlp-4:         NOTRUN -> [SKIP][12] ([i915#4103]) +1 similar issue
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/bat-adlp-4/igt@kms_cursor_legacy@basic-busy-flip-before-cursor-legacy.html

  * igt@kms_force_connector_basic@force-load-detect:
    - fi-icl-u2:          NOTRUN -> [SKIP][13] ([fdo#109285])
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/fi-icl-u2/igt@kms_force_connector_basic@force-load-detect.html

  * igt@kms_force_connector_basic@prune-stale-modes:
    - bat-adlp-4:         NOTRUN -> [SKIP][14] ([i915#4093]) +3 similar issues
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/bat-adlp-4/igt@kms_force_connector_basic@prune-stale-modes.html

  * igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-b:
    - fi-cfl-8109u:       [PASS][15] -> [DMESG-WARN][16] ([i915#62]) +11 similar issues
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/fi-cfl-8109u/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-b.html
   [16]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/fi-cfl-8109u/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-b.html

  * igt@kms_setmode@basic-clone-single-crtc:
    - fi-icl-u2:          NOTRUN -> [SKIP][17] ([i915#3555])
   [17]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/fi-icl-u2/igt@kms_setmode@basic-clone-single-crtc.html
    - fi-bdw-5557u:       NOTRUN -> [SKIP][18] ([fdo#109271]) +14 similar issues
   [18]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/fi-bdw-5557u/igt@kms_setmode@basic-clone-single-crtc.html
    - bat-adlp-4:         NOTRUN -> [SKIP][19] ([i915#3555])
   [19]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/bat-adlp-4/igt@kms_setmode@basic-clone-single-crtc.html

  * igt@prime_vgem@basic-fence-read:
    - bat-adlp-4:         NOTRUN -> [SKIP][20] ([i915#3291] / [i915#3708]) +2 similar issues
   [20]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/bat-adlp-4/igt@prime_vgem@basic-fence-read.html

  * igt@prime_vgem@basic-userptr:
    - fi-icl-u2:          NOTRUN -> [SKIP][21] ([i915#3301])
   [21]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/fi-icl-u2/igt@prime_vgem@basic-userptr.html
    - bat-adlp-4:         NOTRUN -> [SKIP][22] ([i915#3301] / [i915#3708])
   [22]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/bat-adlp-4/igt@prime_vgem@basic-userptr.html

  
#### Possible fixes ####

  * igt@i915_selftest@live@gt_heartbeat:
    - fi-cfl-guc:         [DMESG-FAIL][23] ([i915#5334]) -> [PASS][24]
   [23]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/fi-cfl-guc/igt@i915_selftest@live@gt_heartbeat.html
   [24]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/fi-cfl-guc/igt@i915_selftest@live@gt_heartbeat.html

  * igt@i915_selftest@live@hangcheck:
    - fi-hsw-4770:        [INCOMPLETE][25] ([i915#4785]) -> [PASS][26]
   [25]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/fi-hsw-4770/igt@i915_selftest@live@hangcheck.html
   [26]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/fi-hsw-4770/igt@i915_selftest@live@hangcheck.html

  * igt@i915_selftest@live@hugepages:
    - {bat-rpls-1}:       [DMESG-WARN][27] ([i915#5278]) -> [PASS][28]
   [27]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/bat-rpls-1/igt@i915_selftest@live@hugepages.html
   [28]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/bat-rpls-1/igt@i915_selftest@live@hugepages.html

  * igt@i915_selftest@live@reset:
    - {bat-rpls-1}:       [DMESG-FAIL][29] ([i915#4983]) -> [PASS][30]
   [29]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/bat-rpls-1/igt@i915_selftest@live@reset.html
   [30]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/bat-rpls-1/igt@i915_selftest@live@reset.html

  * igt@kms_busy@basic@flip:
    - {bat-adlp-6}:       [DMESG-WARN][31] ([i915#3576]) -> [PASS][32]
   [31]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/bat-adlp-6/igt@kms_busy@basic@flip.html
   [32]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/bat-adlp-6/igt@kms_busy@basic@flip.html

  
#### Warnings ####

  * igt@gem_exec_suspend@basic-s3@smem:
    - fi-rkl-11600:       [INCOMPLETE][33] ([i915#5127]) -> [INCOMPLETE][34] ([i915#5127] / [i915#5857])
   [33]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/fi-rkl-11600/igt@gem_exec_suspend@basic-s3@smem.html
   [34]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/fi-rkl-11600/igt@gem_exec_suspend@basic-s3@smem.html

  * igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c:
    - fi-kbl-7567u:       [SKIP][35] ([fdo#109271] / [i915#5341]) -> [SKIP][36] ([fdo#109271])
   [35]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/fi-kbl-7567u/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html
   [36]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/fi-kbl-7567u/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html
    - fi-pnv-d510:        [SKIP][37] ([fdo#109271] / [i915#5341]) -> [SKIP][38] ([fdo#109271])
   [37]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/fi-pnv-d510/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html
   [38]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/fi-pnv-d510/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html
    - fi-snb-2520m:       [SKIP][39] ([fdo#109271] / [i915#5341]) -> [SKIP][40] ([fdo#109271])
   [39]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/fi-snb-2520m/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html
   [40]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/fi-snb-2520m/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html
    - fi-bsw-kefka:       [SKIP][41] ([fdo#109271] / [i915#5341]) -> [SKIP][42] ([fdo#109271])
   [41]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/fi-bsw-kefka/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html
   [42]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/fi-bsw-kefka/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html
    - fi-kbl-8809g:       [SKIP][43] ([fdo#109271] / [i915#5341]) -> [SKIP][44] ([fdo#109271])
   [43]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/fi-kbl-8809g/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html
   [44]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/fi-kbl-8809g/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html
    - fi-bsw-nick:        [SKIP][45] ([fdo#109271] / [i915#5341]) -> [SKIP][46] ([fdo#109271])
   [45]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/fi-bsw-nick/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html
   [46]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/fi-bsw-nick/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html
    - fi-bwr-2160:        [SKIP][47] ([fdo#109271] / [i915#5341]) -> [SKIP][48] ([fdo#109271])
   [47]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/fi-bwr-2160/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html
   [48]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/fi-bwr-2160/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html
    - fi-snb-2600:        [SKIP][49] ([fdo#109271] / [i915#5341]) -> [SKIP][50] ([fdo#109271])
   [49]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/fi-snb-2600/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html
   [50]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/fi-snb-2600/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html
    - fi-elk-e7500:       [SKIP][51] ([fdo#109271] / [i915#5341]) -> [SKIP][52] ([fdo#109271])
   [51]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/fi-elk-e7500/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html
   [52]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/fi-elk-e7500/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html
    - fi-blb-e6850:       [SKIP][53] ([fdo#109271] / [i915#5341]) -> [SKIP][54] ([fdo#109271])
   [53]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/fi-blb-e6850/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html
   [54]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/fi-blb-e6850/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html
    - fi-ilk-650:         [SKIP][55] ([fdo#109271] / [i915#5341]) -> [SKIP][56] ([fdo#109271])
   [55]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/fi-ilk-650/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html
   [56]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/fi-ilk-650/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html

  
  {name}: This element is suppressed. This means it is ignored when computing
          the status of the difference (SUCCESS, WARNING, or FAILURE).

  [fdo#109271]: https://bugs.freedesktop.org/show_bug.cgi?id=109271
  [fdo#109278]: https://bugs.freedesktop.org/show_bug.cgi?id=109278
  [fdo#109285]: https://bugs.freedesktop.org/show_bug.cgi?id=109285
  [fdo#111827]: https://bugs.freedesktop.org/show_bug.cgi?id=111827
  [i915#1072]: https://gitlab.freedesktop.org/drm/intel/issues/1072
  [i915#1155]: https://gitlab.freedesktop.org/drm/intel/issues/1155
  [i915#2190]: https://gitlab.freedesktop.org/drm/intel/issues/2190
  [i915#2582]: https://gitlab.freedesktop.org/drm/intel/issues/2582
  [i915#3282]: https://gitlab.freedesktop.org/drm/intel/issues/3282
  [i915#3291]: https://gitlab.freedesktop.org/drm/intel/issues/3291
  [i915#3301]: https://gitlab.freedesktop.org/drm/intel/issues/3301
  [i915#3555]: https://gitlab.freedesktop.org/drm/intel/issues/3555
  [i915#3576]: https://gitlab.freedesktop.org/drm/intel/issues/3576
  [i915#3595]: https://gitlab.freedesktop.org/drm/intel/issues/3595
  [i915#3708]: https://gitlab.freedesktop.org/drm/intel/issues/3708
  [i915#4077]: https://gitlab.freedesktop.org/drm/intel/issues/4077
  [i915#4079]: https://gitlab.freedesktop.org/drm/intel/issues/4079
  [i915#4083]: https://gitlab.freedesktop.org/drm/intel/issues/4083
  [i915#4093]: https://gitlab.freedesktop.org/drm/intel/issues/4093
  [i915#4103]: https://gitlab.freedesktop.org/drm/intel/issues/4103
  [i915#4212]: https://gitlab.freedesktop.org/drm/intel/issues/4212
  [i915#4213]: https://gitlab.freedesktop.org/drm/intel/issues/4213
  [i915#4215]: https://gitlab.freedesktop.org/drm/intel/issues/4215
  [i915#4312]: https://gitlab.freedesktop.org/drm/intel/issues/4312
  [i915#4613]: https://gitlab.freedesktop.org/drm/intel/issues/4613
  [i915#4785]: https://gitlab.freedesktop.org/drm/intel/issues/4785
  [i915#4873]: https://gitlab.freedesktop.org/drm/intel/issues/4873
  [i915#4983]: https://gitlab.freedesktop.org/drm/intel/issues/4983
  [i915#5127]: https://gitlab.freedesktop.org/drm/intel/issues/5127
  [i915#5190]: https://gitlab.freedesktop.org/drm/intel/issues/5190
  [i915#5270]: https://gitlab.freedesktop.org/drm/intel/issues/5270
  [i915#5274]: https://gitlab.freedesktop.org/drm/intel/issues/5274
  [i915#5275]: https://gitlab.freedesktop.org/drm/intel/issues/5275
  [i915#5278]: https://gitlab.freedesktop.org/drm/intel/issues/5278
  [i915#5334]: https://gitlab.freedesktop.org/drm/intel/issues/5334
  [i915#5341]: https://gitlab.freedesktop.org/drm/intel/issues/5341
  [i915#5354]: https://gitlab.freedesktop.org/drm/intel/issues/5354
  [i915#5356]: https://gitlab.freedesktop.org/drm/intel/issues/5356
  [i915#5704]: https://gitlab.freedesktop.org/drm/intel/issues/5704
  [i915#5722]: https://gitlab.freedesktop.org/drm/intel/issues/5722
  [i915#5763]: https://gitlab.freedesktop.org/drm/intel/issues/5763
  [i915#5827]: https://gitlab.freedesktop.org/drm/intel/issues/5827
  [i915#5857]: https://gitlab.freedesktop.org/drm/intel/issues/5857
  [i915#62]: https://gitlab.freedesktop.org/drm/intel/issues/62


Build changes
-------------

  * Linux: CI_DRM_11550 -> Patchwork_103244v2

  CI-20190529: 20190529
  CI_DRM_11550: 56b089ae03ef8ea8ab7f474eaa70367898891ef0 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_6451: f055bd83bd831a938d639718c2359516224f15f9 @ https://gitlab.freedesktop.org/drm/igt-gpu-tools.git
  Patchwork_103244v2: 56b089ae03ef8ea8ab7f474eaa70367898891ef0 @ git://anongit.freedesktop.org/gfx-ci/linux


### Linux commits

a5f124264a07 drm/i915/sseu: Disassociate internal subslice mask representation from uapi
e01aa907ac57 drm/i915/sseu: Simplify gen11+ SSEU handling
6fc154e21d94 drm/i915/xehp: Use separate sseu init function
aa6c620a76b6 drm/i915/xehp: Drop GETPARAM lookups of I915_PARAM_[SUB]SLICE_MASK
f6a2a8ca730e drm/i915/sseu: Don't try to store EU mask internally in UAPI format

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/index.html

[-- Attachment #2: Type: text/html, Size: 18933 bytes --]

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

* [Intel-gfx] ✗ Fi.CI.IGT: failure for i915: SSEU handling updates (rev2)
  2022-04-27 23:07 ` [Intel-gfx] " Matt Roper
                   ` (11 preceding siblings ...)
  (?)
@ 2022-04-28  2:34 ` Patchwork
  -1 siblings, 0 replies; 27+ messages in thread
From: Patchwork @ 2022-04-28  2:34 UTC (permalink / raw)
  To: Matt Roper; +Cc: intel-gfx

[-- Attachment #1: Type: text/plain, Size: 48954 bytes --]

== Series Details ==

Series: i915: SSEU handling updates (rev2)
URL   : https://patchwork.freedesktop.org/series/103244/
State : failure

== Summary ==

CI Bug Log - changes from CI_DRM_11550_full -> Patchwork_103244v2_full
====================================================

Summary
-------

  **FAILURE**

  Serious unknown changes coming with Patchwork_103244v2_full absolutely need to be
  verified manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in Patchwork_103244v2_full, please notify your bug team to allow them
  to document this new failure mode, which will reduce false positives in CI.

  

Participating hosts (10 -> 13)
------------------------------

  Additional (3): shard-rkl shard-dg1 shard-tglu 

Possible new issues
-------------------

  Here are the unknown changes that may have been introduced in Patchwork_103244v2_full:

### IGT changes ###

#### Possible regressions ####

  * igt@i915_pm_sseu@full-enable:
    - shard-kbl:          [PASS][1] -> [FAIL][2] +3 similar issues
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-kbl3/igt@i915_pm_sseu@full-enable.html
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-kbl4/igt@i915_pm_sseu@full-enable.html

  
#### Warnings ####

  * igt@gem_eio@unwedge-stress:
    - shard-tglb:         [FAIL][3] ([i915#232]) -> [FAIL][4] +1 similar issue
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-tglb5/igt@gem_eio@unwedge-stress.html
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-tglb1/igt@gem_eio@unwedge-stress.html

  
#### Suppressed ####

  The following results come from untrusted machines, tests, or statuses.
  They do not affect the overall result.

  * igt@gem_exec_flush@basic-batch-kernel-default-wb:
    - {shard-rkl}:        NOTRUN -> [DMESG-WARN][5]
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-rkl-5/igt@gem_exec_flush@basic-batch-kernel-default-wb.html

  * igt@kms_vblank@pipe-b-ts-continuation-dpms-suspend:
    - {shard-dg1}:        NOTRUN -> [INCOMPLETE][6] +1 similar issue
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-dg1-19/igt@kms_vblank@pipe-b-ts-continuation-dpms-suspend.html

  * igt@perf_pmu@module-unload:
    - {shard-rkl}:        NOTRUN -> [INCOMPLETE][7]
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-rkl-5/igt@perf_pmu@module-unload.html

  
Known issues
------------

  Here are the changes found in Patchwork_103244v2_full that come from known issues:

### CI changes ###

#### Possible fixes ####

  * boot:
    - shard-skl:          ([PASS][8], [PASS][9], [PASS][10], [PASS][11], [PASS][12], [PASS][13], [PASS][14], [PASS][15], [PASS][16], [PASS][17], [PASS][18], [PASS][19], [FAIL][20], [PASS][21], [PASS][22], [PASS][23], [PASS][24], [PASS][25], [PASS][26], [PASS][27], [PASS][28], [PASS][29], [PASS][30], [PASS][31]) ([i915#5032]) -> ([PASS][32], [PASS][33], [PASS][34], [PASS][35], [PASS][36], [PASS][37], [PASS][38], [PASS][39], [PASS][40], [PASS][41], [PASS][42], [PASS][43], [PASS][44], [PASS][45], [PASS][46], [PASS][47], [PASS][48], [PASS][49], [PASS][50], [PASS][51], [PASS][52], [PASS][53], [PASS][54], [PASS][55], [PASS][56])
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-skl9/boot.html
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-skl9/boot.html
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-skl8/boot.html
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-skl8/boot.html
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-skl7/boot.html
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-skl7/boot.html
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-skl6/boot.html
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-skl6/boot.html
   [16]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-skl6/boot.html
   [17]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-skl5/boot.html
   [18]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-skl5/boot.html
   [19]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-skl5/boot.html
   [20]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-skl5/boot.html
   [21]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-skl4/boot.html
   [22]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-skl4/boot.html
   [23]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-skl4/boot.html
   [24]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-skl3/boot.html
   [25]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-skl3/boot.html
   [26]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-skl2/boot.html
   [27]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-skl2/boot.html
   [28]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-skl1/boot.html
   [29]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-skl1/boot.html
   [30]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-skl10/boot.html
   [31]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-skl10/boot.html
   [32]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl9/boot.html
   [33]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl9/boot.html
   [34]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl9/boot.html
   [35]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl8/boot.html
   [36]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl8/boot.html
   [37]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl8/boot.html
   [38]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl7/boot.html
   [39]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl7/boot.html
   [40]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl6/boot.html
   [41]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl6/boot.html
   [42]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl5/boot.html
   [43]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl5/boot.html
   [44]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl4/boot.html
   [45]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl4/boot.html
   [46]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl4/boot.html
   [47]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl3/boot.html
   [48]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl3/boot.html
   [49]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl2/boot.html
   [50]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl2/boot.html
   [51]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl1/boot.html
   [52]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl1/boot.html
   [53]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl1/boot.html
   [54]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl10/boot.html
   [55]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl10/boot.html
   [56]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl10/boot.html

  

### IGT changes ###

#### Issues hit ####

  * igt@gem_ctx_persistence@many-contexts:
    - shard-tglb:         [PASS][57] -> [FAIL][58] ([i915#2410])
   [57]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-tglb7/igt@gem_ctx_persistence@many-contexts.html
   [58]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-tglb5/igt@gem_ctx_persistence@many-contexts.html

  * igt@gem_exec_balancer@parallel-balancer:
    - shard-iclb:         [PASS][59] -> [SKIP][60] ([i915#4525])
   [59]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-iclb2/igt@gem_exec_balancer@parallel-balancer.html
   [60]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-iclb3/igt@gem_exec_balancer@parallel-balancer.html

  * igt@gem_exec_fair@basic-flow@rcs0:
    - shard-skl:          NOTRUN -> [SKIP][61] ([fdo#109271]) +161 similar issues
   [61]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl10/igt@gem_exec_fair@basic-flow@rcs0.html

  * igt@gem_exec_fair@basic-none-vip@rcs0:
    - shard-kbl:          [PASS][62] -> [FAIL][63] ([i915#2842]) +2 similar issues
   [62]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-kbl1/igt@gem_exec_fair@basic-none-vip@rcs0.html
   [63]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-kbl7/igt@gem_exec_fair@basic-none-vip@rcs0.html

  * igt@gem_exec_fair@basic-none@vecs0:
    - shard-glk:          [PASS][64] -> [FAIL][65] ([i915#2842])
   [64]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-glk4/igt@gem_exec_fair@basic-none@vecs0.html
   [65]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-glk2/igt@gem_exec_fair@basic-none@vecs0.html

  * igt@gem_exec_fair@basic-pace@vcs1:
    - shard-iclb:         NOTRUN -> [FAIL][66] ([i915#2842]) +1 similar issue
   [66]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-iclb4/igt@gem_exec_fair@basic-pace@vcs1.html

  * igt@gem_huc_copy@huc-copy:
    - shard-skl:          NOTRUN -> [SKIP][67] ([fdo#109271] / [i915#2190])
   [67]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl7/igt@gem_huc_copy@huc-copy.html

  * igt@gem_lmem_swapping@parallel-random:
    - shard-iclb:         NOTRUN -> [SKIP][68] ([i915#4613])
   [68]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-iclb5/igt@gem_lmem_swapping@parallel-random.html

  * igt@gem_lmem_swapping@verify-ccs:
    - shard-skl:          NOTRUN -> [SKIP][69] ([fdo#109271] / [i915#4613]) +2 similar issues
   [69]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl9/igt@gem_lmem_swapping@verify-ccs.html

  * igt@gem_reg_read@bad-register:
    - shard-skl:          [PASS][70] -> [DMESG-WARN][71] ([i915#1982])
   [70]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-skl8/igt@gem_reg_read@bad-register.html
   [71]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl3/igt@gem_reg_read@bad-register.html

  * igt@gen9_exec_parse@basic-rejected-ctx-param:
    - shard-iclb:         NOTRUN -> [SKIP][72] ([i915#2856])
   [72]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-iclb5/igt@gen9_exec_parse@basic-rejected-ctx-param.html

  * igt@i915_selftest@live@hangcheck:
    - shard-snb:          [PASS][73] -> [INCOMPLETE][74] ([i915#3921])
   [73]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-snb4/igt@i915_selftest@live@hangcheck.html
   [74]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-snb2/igt@i915_selftest@live@hangcheck.html

  * igt@kms_async_flips@alternate-sync-async-flip:
    - shard-skl:          [PASS][75] -> [FAIL][76] ([i915#2521])
   [75]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-skl9/igt@kms_async_flips@alternate-sync-async-flip.html
   [76]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl8/igt@kms_async_flips@alternate-sync-async-flip.html

  * igt@kms_big_fb@4-tiled-16bpp-rotate-270:
    - shard-iclb:         NOTRUN -> [SKIP][77] ([i915#5286])
   [77]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-iclb5/igt@kms_big_fb@4-tiled-16bpp-rotate-270.html

  * igt@kms_big_fb@linear-16bpp-rotate-270:
    - shard-iclb:         NOTRUN -> [SKIP][78] ([fdo#110725] / [fdo#111614])
   [78]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-iclb5/igt@kms_big_fb@linear-16bpp-rotate-270.html

  * igt@kms_big_fb@y-tiled-max-hw-stride-32bpp-rotate-180-hflip-async-flip:
    - shard-apl:          NOTRUN -> [SKIP][79] ([fdo#109271] / [i915#3777])
   [79]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-apl3/igt@kms_big_fb@y-tiled-max-hw-stride-32bpp-rotate-180-hflip-async-flip.html

  * igt@kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-180-hflip-async-flip:
    - shard-skl:          NOTRUN -> [SKIP][80] ([fdo#109271] / [i915#3777]) +2 similar issues
   [80]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl9/igt@kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-180-hflip-async-flip.html

  * igt@kms_big_fb@yf-tiled-max-hw-stride-64bpp-rotate-0-hflip:
    - shard-iclb:         NOTRUN -> [SKIP][81] ([fdo#110723])
   [81]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-iclb5/igt@kms_big_fb@yf-tiled-max-hw-stride-64bpp-rotate-0-hflip.html

  * igt@kms_ccs@pipe-a-random-ccs-data-y_tiled_gen12_mc_ccs:
    - shard-skl:          NOTRUN -> [SKIP][82] ([fdo#109271] / [i915#3886]) +6 similar issues
   [82]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl9/igt@kms_ccs@pipe-a-random-ccs-data-y_tiled_gen12_mc_ccs.html

  * igt@kms_ccs@pipe-b-random-ccs-data-y_tiled_gen12_rc_ccs_cc:
    - shard-iclb:         NOTRUN -> [SKIP][83] ([fdo#109278] / [i915#3886]) +1 similar issue
   [83]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-iclb5/igt@kms_ccs@pipe-b-random-ccs-data-y_tiled_gen12_rc_ccs_cc.html

  * igt@kms_ccs@pipe-d-bad-rotation-90-y_tiled_gen12_rc_ccs_cc:
    - shard-iclb:         NOTRUN -> [SKIP][84] ([fdo#109278]) +7 similar issues
   [84]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-iclb5/igt@kms_ccs@pipe-d-bad-rotation-90-y_tiled_gen12_rc_ccs_cc.html

  * igt@kms_chamelium@hdmi-mode-timings:
    - shard-iclb:         NOTRUN -> [SKIP][85] ([fdo#109284] / [fdo#111827]) +1 similar issue
   [85]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-iclb5/igt@kms_chamelium@hdmi-mode-timings.html

  * igt@kms_color@pipe-a-deep-color:
    - shard-iclb:         NOTRUN -> [SKIP][86] ([fdo#109278] / [i915#3555])
   [86]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-iclb5/igt@kms_color@pipe-a-deep-color.html

  * igt@kms_color_chamelium@pipe-a-ctm-green-to-red:
    - shard-apl:          NOTRUN -> [SKIP][87] ([fdo#109271] / [fdo#111827]) +1 similar issue
   [87]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-apl3/igt@kms_color_chamelium@pipe-a-ctm-green-to-red.html

  * igt@kms_color_chamelium@pipe-d-ctm-0-25:
    - shard-skl:          NOTRUN -> [SKIP][88] ([fdo#109271] / [fdo#111827]) +10 similar issues
   [88]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl5/igt@kms_color_chamelium@pipe-d-ctm-0-25.html

  * igt@kms_color_chamelium@pipe-d-ctm-blue-to-red:
    - shard-iclb:         NOTRUN -> [SKIP][89] ([fdo#109278] / [fdo#109284] / [fdo#111827])
   [89]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-iclb5/igt@kms_color_chamelium@pipe-d-ctm-blue-to-red.html

  * igt@kms_cursor_crc@pipe-c-cursor-512x512-random:
    - shard-iclb:         NOTRUN -> [SKIP][90] ([fdo#109278] / [fdo#109279])
   [90]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-iclb5/igt@kms_cursor_crc@pipe-c-cursor-512x512-random.html

  * igt@kms_cursor_legacy@cursorb-vs-flipa-atomic-transitions-varying-size:
    - shard-iclb:         NOTRUN -> [SKIP][91] ([fdo#109274] / [fdo#109278])
   [91]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-iclb5/igt@kms_cursor_legacy@cursorb-vs-flipa-atomic-transitions-varying-size.html

  * igt@kms_cursor_legacy@flip-vs-cursor-atomic:
    - shard-skl:          [PASS][92] -> [FAIL][93] ([i915#2346])
   [92]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-skl8/igt@kms_cursor_legacy@flip-vs-cursor-atomic.html
   [93]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl3/igt@kms_cursor_legacy@flip-vs-cursor-atomic.html

  * igt@kms_cursor_legacy@flip-vs-cursor-toggle:
    - shard-iclb:         [PASS][94] -> [FAIL][95] ([i915#2346])
   [94]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-iclb2/igt@kms_cursor_legacy@flip-vs-cursor-toggle.html
   [95]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-iclb7/igt@kms_cursor_legacy@flip-vs-cursor-toggle.html

  * igt@kms_fbcon_fbt@fbc-suspend:
    - shard-apl:          NOTRUN -> [INCOMPLETE][96] ([i915#180])
   [96]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-apl3/igt@kms_fbcon_fbt@fbc-suspend.html

  * igt@kms_fbcon_fbt@psr-suspend:
    - shard-skl:          [PASS][97] -> [FAIL][98] ([i915#4767])
   [97]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-skl8/igt@kms_fbcon_fbt@psr-suspend.html
   [98]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl3/igt@kms_fbcon_fbt@psr-suspend.html

  * igt@kms_flip@2x-flip-vs-expired-vblank:
    - shard-iclb:         NOTRUN -> [SKIP][99] ([fdo#109274])
   [99]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-iclb5/igt@kms_flip@2x-flip-vs-expired-vblank.html

  * igt@kms_flip@flip-vs-expired-vblank-interruptible@b-edp1:
    - shard-skl:          [PASS][100] -> [FAIL][101] ([i915#2122]) +2 similar issues
   [100]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-skl3/igt@kms_flip@flip-vs-expired-vblank-interruptible@b-edp1.html
   [101]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl3/igt@kms_flip@flip-vs-expired-vblank-interruptible@b-edp1.html

  * igt@kms_flip@flip-vs-suspend-interruptible@a-dp1:
    - shard-kbl:          [PASS][102] -> [DMESG-WARN][103] ([i915#180]) +7 similar issues
   [102]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-kbl4/igt@kms_flip@flip-vs-suspend-interruptible@a-dp1.html
   [103]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-kbl7/igt@kms_flip@flip-vs-suspend-interruptible@a-dp1.html

  * igt@kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile-downscaling:
    - shard-iclb:         [PASS][104] -> [SKIP][105] ([i915#3701])
   [104]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-iclb7/igt@kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile-downscaling.html
   [105]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-iclb2/igt@kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile-downscaling.html

  * igt@kms_flip_scaled_crc@flip-64bpp-ytile-to-16bpp-ytile-downscaling:
    - shard-skl:          NOTRUN -> [SKIP][106] ([fdo#109271] / [i915#3701])
   [106]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl10/igt@kms_flip_scaled_crc@flip-64bpp-ytile-to-16bpp-ytile-downscaling.html

  * igt@kms_frontbuffer_tracking@fbcpsr-2p-primscrn-cur-indfb-draw-pwrite:
    - shard-iclb:         NOTRUN -> [SKIP][107] ([fdo#109280]) +1 similar issue
   [107]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-iclb5/igt@kms_frontbuffer_tracking@fbcpsr-2p-primscrn-cur-indfb-draw-pwrite.html

  * igt@kms_hdr@bpc-switch@bpc-switch-edp-1-pipe-a:
    - shard-skl:          NOTRUN -> [FAIL][108] ([i915#1188])
   [108]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl9/igt@kms_hdr@bpc-switch@bpc-switch-edp-1-pipe-a.html

  * igt@kms_pipe_crc_basic@suspend-read-crc-pipe-d:
    - shard-skl:          NOTRUN -> [SKIP][109] ([fdo#109271] / [i915#533])
   [109]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl9/igt@kms_pipe_crc_basic@suspend-read-crc-pipe-d.html

  * igt@kms_plane_alpha_blend@pipe-a-coverage-7efc:
    - shard-skl:          [PASS][110] -> [FAIL][111] ([fdo#108145] / [i915#265])
   [110]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-skl7/igt@kms_plane_alpha_blend@pipe-a-coverage-7efc.html
   [111]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl2/igt@kms_plane_alpha_blend@pipe-a-coverage-7efc.html

  * igt@kms_plane_alpha_blend@pipe-c-alpha-transparent-fb:
    - shard-skl:          NOTRUN -> [FAIL][112] ([i915#265])
   [112]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl1/igt@kms_plane_alpha_blend@pipe-c-alpha-transparent-fb.html

  * igt@kms_plane_scaling@upscale-with-rotation-factor-0-25@pipe-b-edp-1-upscale-with-rotation:
    - shard-iclb:         NOTRUN -> [SKIP][113] ([i915#5176]) +2 similar issues
   [113]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-iclb5/igt@kms_plane_scaling@upscale-with-rotation-factor-0-25@pipe-b-edp-1-upscale-with-rotation.html

  * igt@kms_psr2_su@page_flip-p010:
    - shard-skl:          NOTRUN -> [SKIP][114] ([fdo#109271] / [i915#658])
   [114]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl9/igt@kms_psr2_su@page_flip-p010.html

  * igt@kms_psr@psr2_dpms:
    - shard-iclb:         NOTRUN -> [SKIP][115] ([fdo#109441])
   [115]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-iclb5/igt@kms_psr@psr2_dpms.html

  * igt@kms_setmode@basic:
    - shard-snb:          NOTRUN -> [SKIP][116] ([fdo#109271])
   [116]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-snb2/igt@kms_setmode@basic.html

  * igt@kms_setmode@invalid-clone-single-crtc-stealing:
    - shard-apl:          NOTRUN -> [SKIP][117] ([fdo#109271]) +20 similar issues
   [117]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-apl3/igt@kms_setmode@invalid-clone-single-crtc-stealing.html

  * igt@kms_vblank@pipe-b-ts-continuation-suspend:
    - shard-apl:          [PASS][118] -> [DMESG-WARN][119] ([i915#180]) +4 similar issues
   [118]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-apl6/igt@kms_vblank@pipe-b-ts-continuation-suspend.html
   [119]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-apl7/igt@kms_vblank@pipe-b-ts-continuation-suspend.html

  * igt@kms_vblank@pipe-b-wait-forked:
    - shard-snb:          [PASS][120] -> [SKIP][121] ([fdo#109271]) +4 similar issues
   [120]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-snb7/igt@kms_vblank@pipe-b-wait-forked.html
   [121]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-snb2/igt@kms_vblank@pipe-b-wait-forked.html

  * igt@kms_vrr@flip-dpms:
    - shard-iclb:         NOTRUN -> [SKIP][122] ([i915#3555])
   [122]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-iclb5/igt@kms_vrr@flip-dpms.html

  * igt@kms_writeback@writeback-check-output:
    - shard-skl:          NOTRUN -> [SKIP][123] ([fdo#109271] / [i915#2437])
   [123]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl1/igt@kms_writeback@writeback-check-output.html

  * igt@perf@polling-small-buf:
    - shard-skl:          [PASS][124] -> [FAIL][125] ([i915#1722])
   [124]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-skl7/igt@perf@polling-small-buf.html
   [125]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl2/igt@perf@polling-small-buf.html

  * igt@prime_nv_pcopy@test3_4:
    - shard-iclb:         NOTRUN -> [SKIP][126] ([fdo#109291])
   [126]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-iclb5/igt@prime_nv_pcopy@test3_4.html

  * igt@syncobj_timeline@invalid-transfer-non-existent-point:
    - shard-skl:          NOTRUN -> [DMESG-WARN][127] ([i915#5098])
   [127]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl10/igt@syncobj_timeline@invalid-transfer-non-existent-point.html

  * igt@sysfs_clients@sema-25:
    - shard-skl:          NOTRUN -> [SKIP][128] ([fdo#109271] / [i915#2994]) +2 similar issues
   [128]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl9/igt@sysfs_clients@sema-25.html

  
#### Possible fixes ####

  * igt@gem_eio@in-flight-contexts-10ms:
    - shard-tglb:         [TIMEOUT][129] ([i915#3063]) -> [PASS][130]
   [129]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-tglb3/igt@gem_eio@in-flight-contexts-10ms.html
   [130]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-tglb3/igt@gem_eio@in-flight-contexts-10ms.html

  * igt@gem_exec_fair@basic-none@vcs0:
    - shard-glk:          [FAIL][131] ([i915#2842]) -> [PASS][132] +1 similar issue
   [131]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-glk4/igt@gem_exec_fair@basic-none@vcs0.html
   [132]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-glk2/igt@gem_exec_fair@basic-none@vcs0.html

  * igt@gem_exec_fair@basic-pace@rcs0:
    - shard-kbl:          [FAIL][133] ([i915#2842]) -> [PASS][134]
   [133]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-kbl4/igt@gem_exec_fair@basic-pace@rcs0.html
   [134]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-kbl1/igt@gem_exec_fair@basic-pace@rcs0.html

  * igt@gem_exec_flush@basic-uc-rw-default:
    - shard-snb:          [SKIP][135] ([fdo#109271]) -> [PASS][136] +2 similar issues
   [135]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-snb6/igt@gem_exec_flush@basic-uc-rw-default.html
   [136]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-snb5/igt@gem_exec_flush@basic-uc-rw-default.html

  * igt@gem_exec_whisper@basic-fds-forked-all:
    - shard-skl:          [INCOMPLETE][137] ([i915#5843]) -> [PASS][138]
   [137]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-skl5/igt@gem_exec_whisper@basic-fds-forked-all.html
   [138]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl10/igt@gem_exec_whisper@basic-fds-forked-all.html

  * igt@gem_softpin@softpin:
    - shard-skl:          [DMESG-WARN][139] ([i915#1982]) -> [PASS][140]
   [139]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-skl10/igt@gem_softpin@softpin.html
   [140]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl6/igt@gem_softpin@softpin.html

  * igt@kms_async_flips@alternate-sync-async-flip:
    - shard-glk:          [FAIL][141] ([i915#2521]) -> [PASS][142]
   [141]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-glk6/igt@kms_async_flips@alternate-sync-async-flip.html
   [142]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-glk1/igt@kms_async_flips@alternate-sync-async-flip.html

  * igt@kms_cursor_crc@pipe-c-cursor-suspend:
    - shard-apl:          [DMESG-WARN][143] ([i915#180]) -> [PASS][144]
   [143]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-apl7/igt@kms_cursor_crc@pipe-c-cursor-suspend.html
   [144]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-apl3/igt@kms_cursor_crc@pipe-c-cursor-suspend.html

  * igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions-varying-size:
    - shard-glk:          [FAIL][145] ([i915#2346] / [i915#533]) -> [PASS][146]
   [145]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-glk4/igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions-varying-size.html
   [146]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-glk2/igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions-varying-size.html

  * igt@kms_flip@flip-vs-expired-vblank-interruptible@a-edp1:
    - shard-skl:          [FAIL][147] ([i915#79]) -> [PASS][148]
   [147]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-skl3/igt@kms_flip@flip-vs-expired-vblank-interruptible@a-edp1.html
   [148]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl3/igt@kms_flip@flip-vs-expired-vblank-interruptible@a-edp1.html

  * igt@kms_hdr@bpc-switch-suspend@bpc-switch-suspend-edp-1-pipe-a:
    - shard-skl:          [FAIL][149] ([i915#1188]) -> [PASS][150]
   [149]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-skl6/igt@kms_hdr@bpc-switch-suspend@bpc-switch-suspend-edp-1-pipe-a.html
   [150]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl5/igt@kms_hdr@bpc-switch-suspend@bpc-switch-suspend-edp-1-pipe-a.html

  * igt@kms_plane_scaling@planes-upscale-factor-0-25-downscale-factor-0-5@pipe-b-edp-1-planes-upscale-downscale:
    - shard-iclb:         [SKIP][151] ([i915#5235]) -> [PASS][152] +2 similar issues
   [151]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-iclb2/igt@kms_plane_scaling@planes-upscale-factor-0-25-downscale-factor-0-5@pipe-b-edp-1-planes-upscale-downscale.html
   [152]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-iclb3/igt@kms_plane_scaling@planes-upscale-factor-0-25-downscale-factor-0-5@pipe-b-edp-1-planes-upscale-downscale.html

  * igt@kms_psr@psr2_sprite_plane_move:
    - shard-iclb:         [SKIP][153] ([fdo#109441]) -> [PASS][154] +1 similar issue
   [153]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-iclb6/igt@kms_psr@psr2_sprite_plane_move.html
   [154]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-iclb2/igt@kms_psr@psr2_sprite_plane_move.html

  * igt@kms_vblank@pipe-a-ts-continuation-suspend:
    - shard-skl:          [INCOMPLETE][155] ([i915#4939]) -> [PASS][156]
   [155]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-skl5/igt@kms_vblank@pipe-a-ts-continuation-suspend.html
   [156]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl1/igt@kms_vblank@pipe-a-ts-continuation-suspend.html

  
#### Warnings ####

  * igt@gem_exec_balancer@parallel:
    - shard-iclb:         [SKIP][157] ([i915#4525]) -> [DMESG-WARN][158] ([i915#5614]) +2 similar issues
   [157]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-iclb6/igt@gem_exec_balancer@parallel.html
   [158]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-iclb1/igt@gem_exec_balancer@parallel.html

  * igt@gem_exec_balancer@parallel-keep-in-fence:
    - shard-iclb:         [DMESG-WARN][159] ([i915#5614]) -> [SKIP][160] ([i915#4525])
   [159]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-iclb4/igt@gem_exec_balancer@parallel-keep-in-fence.html
   [160]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-iclb5/igt@gem_exec_balancer@parallel-keep-in-fence.html

  * igt@i915_pm_dc@dc3co-vpb-simulation:
    - shard-iclb:         [SKIP][161] ([i915#588]) -> [SKIP][162] ([i915#658])
   [161]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-iclb2/igt@i915_pm_dc@dc3co-vpb-simulation.html
   [162]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-iclb7/igt@i915_pm_dc@dc3co-vpb-simulation.html

  * igt@kms_chamelium@dp-frame-dump:
    - shard-skl:          [SKIP][163] ([fdo#109271] / [fdo#111827]) -> [SKIP][164] ([fdo#109271] / [fdo#111827] / [i915#1888])
   [163]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-skl8/igt@kms_chamelium@dp-frame-dump.html
   [164]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-skl3/igt@kms_chamelium@dp-frame-dump.html

  * igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c:
    - shard-snb:          [SKIP][165] ([fdo#109271] / [i915#5341]) -> [SKIP][166] ([fdo#109271])
   [165]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-snb7/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html
   [166]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-snb2/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html

  * igt@kms_psr2_sf@cursor-plane-move-continuous-sf:
    - shard-iclb:         [SKIP][167] ([i915#2920]) -> [SKIP][168] ([i915#658])
   [167]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-iclb2/igt@kms_psr2_sf@cursor-plane-move-continuous-sf.html
   [168]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-iclb7/igt@kms_psr2_sf@cursor-plane-move-continuous-sf.html

  * igt@kms_psr2_sf@overlay-plane-move-continuous-sf:
    - shard-iclb:         [SKIP][169] ([i915#658]) -> [SKIP][170] ([i915#2920])
   [169]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-iclb7/igt@kms_psr2_sf@overlay-plane-move-continuous-sf.html
   [170]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-iclb2/igt@kms_psr2_sf@overlay-plane-move-continuous-sf.html

  * igt@kms_psr2_sf@plane-move-sf-dmg-area:
    - shard-iclb:         [SKIP][171] ([i915#2920]) -> [SKIP][172] ([fdo#111068] / [i915#658]) +1 similar issue
   [171]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-iclb2/igt@kms_psr2_sf@plane-move-sf-dmg-area.html
   [172]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-iclb3/igt@kms_psr2_sf@plane-move-sf-dmg-area.html

  * igt@runner@aborted:
    - shard-kbl:          ([FAIL][173], [FAIL][174], [FAIL][175], [FAIL][176], [FAIL][177], [FAIL][178], [FAIL][179], [FAIL][180], [FAIL][181], [FAIL][182]) ([i915#3002] / [i915#4312] / [i915#5257]) -> ([FAIL][183], [FAIL][184], [FAIL][185], [FAIL][186], [FAIL][187], [FAIL][188], [FAIL][189], [FAIL][190], [FAIL][191], [FAIL][192], [FAIL][193], [FAIL][194], [FAIL][195], [FAIL][196]) ([i915#180] / [i915#3002] / [i915#4312] / [i915#5257])
   [173]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-kbl7/igt@runner@aborted.html
   [174]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-kbl7/igt@runner@aborted.html
   [175]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-kbl7/igt@runner@aborted.html
   [176]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-kbl7/igt@runner@aborted.html
   [177]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-kbl4/igt@runner@aborted.html
   [178]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-kbl4/igt@runner@aborted.html
   [179]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-kbl6/igt@runner@aborted.html
   [180]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-kbl1/igt@runner@aborted.html
   [181]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-kbl1/igt@runner@aborted.html
   [182]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11550/shard-kbl3/igt@runner@aborted.html
   [183]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-kbl6/igt@runner@aborted.html
   [184]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-kbl7/igt@runner@aborted.html
   [185]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-kbl4/igt@runner@aborted.html
   [186]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-kbl3/igt@runner@aborted.html
   [187]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-kbl6/igt@runner@aborted.html
   [188]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-kbl4/igt@runner@aborted.html
   [189]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-kbl7/igt@runner@aborted.html
   [190]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-kbl7/igt@runner@aborted.html
   [191]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-kbl6/igt@runner@aborted.html
   [192]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-kbl1/igt@runner@aborted.html
   [193]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-kbl7/igt@runner@aborted.html
   [194]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-kbl7/igt@runner@aborted.html
   [195]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-kbl7/igt@runner@aborted.html
   [196]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/shard-kbl1/igt@runner@aborted.html

  
  {name}: This element is suppressed. This means it is ignored when computing
          the status of the difference (SUCCESS, WARNING, or FAILURE).

  [fdo#108145]: https://bugs.freedesktop.org/show_bug.cgi?id=108145
  [fdo#109271]: https://bugs.freedesktop.org/show_bug.cgi?id=109271
  [fdo#109274]: https://bugs.freedesktop.org/show_bug.cgi?id=109274
  [fdo#109278]: https://bugs.freedesktop.org/show_bug.cgi?id=109278
  [fdo#109279]: https://bugs.freedesktop.org/show_bug.cgi?id=109279
  [fdo#109280]: https://bugs.freedesktop.org/show_bug.cgi?id=109280
  [fdo#109283]: https://bugs.freedesktop.org/show_bug.cgi?id=109283
  [fdo#109284]: https://bugs.freedesktop.org/show_bug.cgi?id=109284
  [fdo#109285]: https://bugs.freedesktop.org/show_bug.cgi?id=109285
  [fdo#109289]: https://bugs.freedesktop.org/show_bug.cgi?id=109289
  [fdo#109291]: https://bugs.freedesktop.org/show_bug.cgi?id=109291
  [fdo#109295]: https://bugs.freedesktop.org/show_bug.cgi?id=109295
  [fdo#109300]: https://bugs.freedesktop.org/show_bug.cgi?id=109300
  [fdo#109302]: https://bugs.freedesktop.org/show_bug.cgi?id=109302
  [fdo#109303]: https://bugs.freedesktop.org/show_bug.cgi?id=109303
  [fdo#109307]: https://bugs.freedesktop.org/show_bug.cgi?id=109307
  [fdo#109308]: https://bugs.freedesktop.org/show_bug.cgi?id=109308
  [fdo#109309]: https://bugs.freedesktop.org/show_bug.cgi?id=109309
  [fdo#109312]: https://bugs.freedesktop.org/show_bug.cgi?id=109312
  [fdo#109313]: https://bugs.freedesktop.org/show_bug.cgi?id=109313
  [fdo#109314]: https://bugs.freedesktop.org/show_bug.cgi?id=109314
  [fdo#109441]: https://bugs.freedesktop.org/show_bug.cgi?id=109441
  [fdo#109506]: https://bugs.freedesktop.org/show_bug.cgi?id=109506
  [fdo#109642]: https://bugs.freedesktop.org/show_bug.cgi?id=109642
  [fdo#110189]: https://bugs.freedesktop.org/show_bug.cgi?id=110189
  [fdo#110542]: https://bugs.freedesktop.org/show_bug.cgi?id=110542
  [fdo#110723]: https://bugs.freedesktop.org/show_bug.cgi?id=110723
  [fdo#110725]: https://bugs.freedesktop.org/show_bug.cgi?id=110725
  [fdo#111068]: https://bugs.freedesktop.org/show_bug.cgi?id=111068
  [fdo#111314]: https://bugs.freedesktop.org/show_bug.cgi?id=111314
  [fdo#111614]: https://bugs.freedesktop.org/show_bug.cgi?id=111614
  [fdo#111615]: https://bugs.freedesktop.org/show_bug.cgi?id=111615
  [fdo#111644]: https://bugs.freedesktop.org/show_bug.cgi?id=111644
  [fdo#111656]: https://bugs.freedesktop.org/show_bug.cgi?id=111656
  [fdo#111825]: https://bugs.freedesktop.org/show_bug.cgi?id=111825
  [fdo#111827]: https://bugs.freedesktop.org/show_bug.cgi?id=111827
  [fdo#112022]: https://bugs.freedesktop.org/show_bug.cgi?id=112022
  [fdo#112054]: https://bugs.freedesktop.org/show_bug.cgi?id=112054
  [fdo#112283]: https://bugs.freedesktop.org/show_bug.cgi?id=112283
  [i915#1063]: https://gitlab.freedesktop.org/drm/intel/issues/1063
  [i915#1072]: https://gitlab.freedesktop.org/drm/intel/issues/1072
  [i915#1149]: https://gitlab.freedesktop.org/drm/intel/issues/1149
  [i915#1155]: https://gitlab.freedesktop.org/drm/intel/issues/1155
  [i915#1188]: https://gitlab.freedesktop.org/drm/intel/issues/1188
  [i915#132]: https://gitlab.freedesktop.org/drm/intel/issues/132
  [i915#1397]: https://gitlab.freedesktop.org/drm/intel/issues/1397
  [i915#1722]: https://gitlab.freedesktop.org/drm/intel/issues/1722
  [i915#1769]: https://gitlab.freedesktop.org/drm/intel/issues/1769
  [i915#180]: https://gitlab.freedesktop.org/drm/intel/issues/180
  [i915#1825]: https://gitlab.freedesktop.org/drm/intel/issues/1825
  [i915#1836]: https://gitlab.freedesktop.org/drm/intel/issues/1836
  [i915#1839]: https://gitlab.freedesktop.org/drm/intel/issues/1839
  [i915#1845]: https://gitlab.freedesktop.org/drm/intel/issues/1845
  [i915#1849]: https://gitlab.freedesktop.org/drm/intel/issues/1849
  [i915#1850]: https://gitlab.freedesktop.org/drm/intel/issues/1850
  [i915#1888]: https://gitlab.freedesktop.org/drm/intel/issues/1888
  [i915#1902]: https://gitlab.freedesktop.org/drm/intel/issues/1902
  [i915#1982]: https://gitlab.freedesktop.org/drm/intel/issues/1982
  [i915#2122]: https://gitlab.freedesktop.org/drm/intel/issues/2122
  [i915#2190]: https://gitlab.freedesktop.org/drm/intel/issues/2190
  [i915#232]: https://gitlab.freedesktop.org/drm/intel/issues/232
  [i915#2346]: https://gitlab.freedesktop.org/drm/intel/issues/2346
  [i915#2410]: https://gitlab.freedesktop.org/drm/intel/issues/2410
  [i915#2434]: https://gitlab.freedesktop.org/drm/intel/issues/2434
  [i915#2435]: https://gitlab.freedesktop.org/drm/intel/issues/2435
  [i915#2437]: https://gitlab.freedesktop.org/drm/intel/issues/2437
  [i915#2521]: https://gitlab.freedesktop.org/drm/intel/issues/2521
  [i915#2527]: https://gitlab.freedesktop.org/drm/intel/issues/2527
  [i915#2530]: https://gitlab.freedesktop.org/drm/intel/issues/2530
  [i915#2582]: https://gitlab.freedesktop.org/drm/intel/issues/2582
  [i915#2587]: https://gitlab.freedesktop.org/drm/intel/issues/2587
  [i915#265]: https://gitlab.freedesktop.org/drm/intel/issues/265
  [i915#2658]: https://gitlab.freedesktop.org/drm/intel/issues/2658
  [i915#2672]: https://gitlab.freedesktop.org/drm/intel/issues/2672
  [i915#2681]: https://gitlab.freedesktop.org/drm/intel/issues/2681
  [i915#2705]: https://gitlab.freedesktop.org/drm/intel/issues/2705
  [i915#280]: https://gitlab.freedesktop.org/drm/intel/issues/280
  [i915#284]: https://gitlab.freedesktop.org/drm/intel/issues/284
  [i915#2842]: https://gitlab.freedesktop.org/drm/intel/issues/2842
  [i915#2849]: https://gitlab.freedesktop.org/drm/intel/issues/2849
  [i915#2856]: https://gitlab.freedesktop.org/drm/intel/issues/2856
  [i915#2920]: https://gitlab.freedesktop.org/drm/intel/issues/2920
  [i915#2994]: https://gitlab.freedesktop.org/drm/intel/issues/2994
  [i915#3002]: https://gitlab.freedesktop.org/drm/intel/issues/3002
  [i915#3012]: https://gitlab.freedesktop.org/drm/intel/issues/3012
  [i915#3063]: https://gitlab.freedesktop.org/drm/intel/issues/3063
  [i915#3116]: https://gitlab.freedesktop.org/drm/intel/issues/3116
  [i915#3281]: https://gitlab.freedesktop.org/drm/intel/issues/3281
  [i915#3282]: https://gitlab.freedesktop.org/drm/intel/issues/3282
  [i915#3291]: https://gitlab.freedesktop.org/drm/intel/issues/3291
  [i915#3297]: https://gitlab.freedesktop.org/drm/intel/issues/3297
  [i915#3299]: https://gitlab.freedesktop.org/drm/intel/issues/3299
  [i915#3301]: https://gitlab.freedesktop.org/drm/intel/issues/3301
  [i915#3318]: https://gitlab.freedesktop.org/drm/intel/issues/3318
  [i915#3319]: https://gitlab.freedesktop.org/drm/intel/issues/3319
  [i915#3359]: https://gitlab.freedesktop.org/drm/intel/issues/3359
  [i915#3361]: https://gitlab.freedesktop.org/drm/intel/issues/3361
  [i915#3376]: https://gitlab.freedesktop.org/drm/intel/issues/3376
  [i915#3458]: https://gitlab.freedesktop.org/drm/intel/issues/3458
  [i915#3464]: https://gitlab.freedesktop.org/drm/intel/issues/3464
  [i915#3469]: https://gitlab.freedesktop.org/drm/intel/issues/3469
  [i915#3528]: https://gitlab.freedesktop.org/drm/intel/issues/3528
  [i915#3539]: https://gitlab.freedesktop.org/drm/intel/issues/3539
  [i915#3555]: https://gitlab.freedesktop.org/drm/intel/issues/3555
  [i915#3558]: https://gitlab.freedesktop.org/drm/intel/issues/3558
  [i915#3637]: https://gitlab.freedesktop.org/drm/intel/issues/3637
  [i915#3638]: https://gitlab.freedesktop.org/drm/intel/issues/3638
  [i915#3639]: https://gitlab.freedesktop.org/drm/intel/issues/3639
  [i915#3648]: https://gitlab.freedesktop.org/drm/intel/issues/3648
  [i915#3689]: https://gitlab.freedesktop.org/drm/intel/issues/3689
  [i915#3701]: https://gitlab.freedesktop.org/drm/intel/issues/3701
  [i915#3708]: https://gitlab.freedesktop.org/drm/intel/issues/3708
  [i915#3734]: https://gitlab.freedesktop.org/drm/intel/issues/3734
  [i915#3736]: https://gitlab.freedesktop.org/drm/intel/issues/3736
  [i915#3742]: https://gitlab.freedesktop.org/drm/intel/issues/3742
  [i915#3777]: https://gitlab.freedesktop.org/drm/intel/issues/3777
  [i915#3825]: https://gitlab.freedesktop.org/drm/intel/issues/3825
  [i915#3826]: https://gitlab.freedesktop.org/drm/intel/issues/3826
  [i915#3840]: https://gitlab.freedesktop.org/drm/intel/issues/3840
  [i915#3886]: https://gitlab.freedesktop.org/drm/intel/issues/3886
  [i915#3921]: https://gitlab.freedesktop.org/drm/intel/issues/3921
  [i915#3952]: https://gitlab.freedesktop.org/drm/intel/issues/3952
  [i915#3955]: https://gitlab.freedesktop.org/drm/intel/issues/3955
  [i915#3966]: https://gitlab.freedesktop.org/drm/intel/issues/3966
  [i915#4036]: https://gitlab.freedesktop.org/drm/intel/issues/4036
  [i915#404]: https://gitlab.freedesktop.org/drm/intel/issues/404
  [i915#4070]: https://gitlab.freedesktop.org/drm/intel/issues/4070
  [i915#4077]: https://gitlab.freedesktop.org/drm/intel/issues/4077
  [i915#4078]: https://gitlab.freedesktop.org/drm/intel/issues/4078
  [i915#4079]: https://gitlab.freedesktop.org/drm/intel/issues/4079
  [i915#4083]: https://gitlab.freedesktop.org/drm/intel/issues/4083
  [i915#4098]: https://gitlab.freedesktop.org/drm/intel/issues/4098
  [i915#4103]: https://gitlab.freedesktop.org/drm/intel/issues/4103
  [i915#426]: https://gitlab.freedesktop.org/drm/intel/issues/426
  [i915#4270]: https://gitlab.freedesktop.org/drm/intel/issues/4270
  [i915#4278]: https://gitlab.freedesktop.org/drm/intel/issues/4278
  [i915#4281]: https://gitlab.freedesktop.org/drm/intel/issues/4281
  [i915#4312]: https://gitlab.freedesktop.org/drm/intel/issues/4312
  [i915#4369]: https://gitlab.freedesktop.org/drm/intel/issues/4369
  [i915#4387]: https://gitlab.freedesktop.org/drm/intel/issues/4387
  [i915#4494]: https://gitlab.freedesktop.org/drm/intel/issues/4494
  [i915#4525]: https://gitlab.freedesktop.org/drm/intel/issues/4525
  [i915#4538]: https://gitlab.freedesktop.org/drm/intel/issues/4538
  [i915#4613]: https://gitlab.freedesktop.org/drm/intel/issues/4613
  [i915#4767]: https://gitlab.freedesktop.org/drm/intel/issues/4767
  [i915#4807]: https://gitlab.freedesktop.org/drm/intel/issues/4807
  [i915#4812]: https://gitlab.freedesktop.org/drm/intel/issues/4812
  [i915#4833]: https://gitlab.freedesktop.org/drm/intel/issues/4833
  [i915#4842]: https://gitlab.freedesktop.org/drm/intel/issues/4842
  [i915#4852]: https://gitlab.freedesktop.org/drm/intel/issues/4852
  [i915#4853]: https://gitlab.freedesktop.org/drm/intel/issues/4853
  [i915#4860]: https://gitlab.freedesktop.org/drm/intel/issues/4860
  [i915#4873]: https://gitlab.freedesktop.org/drm/intel/issues/4873
  [i915#4877]: https://gitlab.freedesktop.org/drm/intel/issues/4877
  [i915#4881]: https://gitlab.freedesktop.org/drm/intel/issues/4881
  [i915#4885]: https://gitlab.freedesktop.org/drm/intel/issues/4885
  [i915#4886]: https://gitlab.freedesktop.org/drm/intel/issues/4886
  [i915#4893]: https://gitlab.freedesktop.org/drm/intel/issues/4893
  [i915#4939]: https://gitlab.freedesktop.org/drm/intel/issues/4939
  [i915#4957]: https://gitlab.freedesktop.org/drm/intel/issues/4957
  [i915#4958]: https://gitlab.freedesktop.org/drm/intel/issues/4958
  [i915#4991]: https://gitlab.freedesktop.org/drm/intel/issues/4991
  [i915#5032]: https://gitlab.freedesktop.org/drm/intel/issues/5032
  [i915#5076]: https://gitlab.freedesktop.org/drm/intel/issues/5076
  [i915#5098]: https://gitlab.freedesktop.org/drm/intel/issues/5098
  [i915#5115]: https://gitlab.freedesktop.org/drm/intel/issues/5115
  [i915#5176]: https://gitlab.freedesktop.org/drm/intel/issues/5176
  [i915#5182]: https://gitlab.freedesktop.org/drm/intel/issues/5182
  [i915#5235]: https://gitlab.freedesktop.org/drm/intel/issues/5235
  [i915#5257]: https://gitlab.freedesktop.org/drm/intel/issues/5257
  [i915#5286]: https://gitlab.freedesktop.org/drm/intel/issues/5286
  [i915#5287]: https://gitlab.freedesktop.org/drm/intel/issues/5287
  [i915#5288]: https://gitlab.freedesktop.org/drm/intel/issues/5288
  [i915#5289]: https://gitlab.freedesktop.org/drm/intel/issues/5289
  [i915#5303]: https://gitlab.freedesktop.org/drm/intel/issues/5303
  [i915#5325]: https://gitlab.freedesktop.org/drm/intel/issues/5325
  [i915#533]: https://gitlab.freedesktop.org/drm/intel/issues/533
  [i915#5341]: https://gitlab.freedesktop.org/drm/intel/issues/5341
  [i915#5439]: https://gitlab.freedesktop.org/drm/intel/issues/5439
  [i915#5461]: https://gitlab.freedesktop.org/drm/intel/issues/5461
  [i915#5563]: https://gitlab.freedesktop.org/drm/intel/issues/5563
  [i915#5614]: https://gitlab.freedesktop.org/drm/intel/issues/5614
  [i915#5691]: https://gitlab.freedesktop.org/drm/intel/issues/5691
  [i915#5723]: https://gitlab.freedesktop.org/drm/intel/issues/5723
  [i915#5843]: https://gitlab.freedesktop.org/drm/intel/issues/5843
  [i915#5849]: https://gitlab.freedesktop.org/drm/intel/issues/5849
  [i915#588]: https://gitlab.freedesktop.org/drm/intel/issues/588
  [i915#658]: https://gitlab.freedesktop.org/drm/intel/issues/658
  [i915#79]: https://gitlab.freedesktop.org/drm/intel/issues/79


Build changes
-------------

  * Linux: CI_DRM_11550 -> Patchwork_103244v2

  CI-20190529: 20190529
  CI_DRM_11550: 56b089ae03ef8ea8ab7f474eaa70367898891ef0 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_6451: f055bd83bd831a938d639718c2359516224f15f9 @ https://gitlab.freedesktop.org/drm/igt-gpu-tools.git
  Patchwork_103244v2: 56b089ae03ef8ea8ab7f474eaa70367898891ef0 @ git://anongit.freedesktop.org/gfx-ci/linux
  piglit_4509: fdc5a4ca11124ab8413c7988896eec4c97336694 @ git://anongit.freedesktop.org/piglit

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_103244v2/index.html

[-- Attachment #2: Type: text/html, Size: 47256 bytes --]

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

* Re: [PATCH 5/5] drm/i915/sseu: Disassociate internal subslice mask representation from uapi
  2022-04-27 23:07   ` [Intel-gfx] " Matt Roper
@ 2022-04-28 12:18     ` Tvrtko Ursulin
  -1 siblings, 0 replies; 27+ messages in thread
From: Tvrtko Ursulin @ 2022-04-28 12:18 UTC (permalink / raw)
  To: Matt Roper, intel-gfx; +Cc: dri-devel


Hi,

On 28/04/2022 00:07, Matt Roper wrote:
> Rather than storing subslice masks internally as u8[] (inside the sseu
> structure) and u32 (everywhere else), let's move over to using an
> intel_sseu_ss_mask_t typedef compatible with the operations in
> linux/bitmap.h.  We're soon going to start adding code for a new
> platform where subslice masks are spread across two 32-bit registers
> (requiring 64 bits to represent), and we expect future platforms will
> likely take this even farther, requiring bitmask storage larger than a
> simple u64 can hold.

I won't have time to look into this in a detailed way for a few days. Until then a couple questions comments only.

First, out of curiousity, were you able to end up with less code after your series? With my bitmap conversion I think actually ended up with couple KB smaller text which was a good sign eliminating the internal layout complications was a good approach.

For your series I am not convinced by sseu->has_common_ss_eumask. Why the duality, just to save a few u32 at runtime?

I am also not convinced with leaving the eu_mask and subslice_mask being manually indexed with stride, calculcated by the driver. In my approach I simply went with multi-dimensional arrays which I think ends up with simpler code.

For all bitmap API call sites and *pb printk format sites, I suggest not hard-coding the widths from SSEU defines by querying the type itsef via wrappers. (See my BITMAP_BITS macro and helpers which wrap it for fields.)

Ie instead:

bitmap_shift_left(to_mask->b, to_mask->b, offset, I915_MAX_SS_FUSE_BITS);

I suggest:

bitmap_zero(slices.b, BITMAP_BITS(slices.b));

Also, all accesses to the bitmap type from outside intel_sse*.c|h should use intel_sseu wrappers and not embed knowledge of the typedef (that it has an member named .b etc).

And finally I would also use the opportunity to clean up the pointless u8 types for counts and such since I think they just result in worse code generation.

You can of course counter with what you did not like in my attempt. :) I know I did not finish the wrappers and possibly made an overkill by converting the slice mask to bitmap.

Regards,

Tvrtko
  
> Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
> ---
>   drivers/gpu/drm/i915/gem/i915_gem_context.c  |   4 +-
>   drivers/gpu/drm/i915/gt/intel_engine_cs.c    |   2 +-
>   drivers/gpu/drm/i915/gt/intel_gt.c           |  14 +-
>   drivers/gpu/drm/i915/gt/intel_sseu.c         | 197 +++++++++++--------
>   drivers/gpu/drm/i915/gt/intel_sseu.h         |  48 ++---
>   drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c |  28 +--
>   drivers/gpu/drm/i915/gt/intel_workarounds.c  |  28 ++-
>   drivers/gpu/drm/i915/i915_getparam.c         |   2 +-
>   drivers/gpu/drm/i915/i915_query.c            |   8 +-
>   9 files changed, 183 insertions(+), 148 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c
> index ab4c5ab28e4d..ea012ee3a8de 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c
> @@ -1901,7 +1901,7 @@ i915_gem_user_to_context_sseu(struct intel_gt *gt,
>   	if (user->slice_mask & ~device->slice_mask)
>   		return -EINVAL;
>   
> -	if (user->subslice_mask & ~device->subslice_mask[0])
> +	if (user->subslice_mask & ~device->subslice_mask.b[0])
>   		return -EINVAL;
>   
>   	if (user->max_eus_per_subslice > device->max_eus_per_subslice)
> @@ -1915,7 +1915,7 @@ i915_gem_user_to_context_sseu(struct intel_gt *gt,
>   	/* Part specific restrictions. */
>   	if (GRAPHICS_VER(i915) == 11) {
>   		unsigned int hw_s = hweight8(device->slice_mask);
> -		unsigned int hw_ss_per_s = hweight8(device->subslice_mask[0]);
> +		unsigned int hw_ss_per_s = hweight8(device->subslice_mask.b[0]);
>   		unsigned int req_s = hweight8(context->slice_mask);
>   		unsigned int req_ss = hweight8(context->subslice_mask);
>   
> diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
> index 14c6ddbbfde8..39c09963b3c7 100644
> --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c
> +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
> @@ -610,7 +610,7 @@ static void engine_mask_apply_compute_fuses(struct intel_gt *gt)
>   	if (GRAPHICS_VER_FULL(i915) < IP_VER(12, 50))
>   		return;
>   
> -	ccs_mask = intel_slicemask_from_dssmask(intel_sseu_get_compute_subslices(&info->sseu),
> +	ccs_mask = intel_slicemask_from_dssmask(info->sseu.compute_subslice_mask,
>   						ss_per_ccs);
>   	/*
>   	 * If all DSS in a quadrant are fused off, the corresponding CCS
> diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c
> index 92394f13b42f..cc03512d59ba 100644
> --- a/drivers/gpu/drm/i915/gt/intel_gt.c
> +++ b/drivers/gpu/drm/i915/gt/intel_gt.c
> @@ -133,13 +133,6 @@ static const struct intel_mmio_range dg2_lncf_steering_table[] = {
>   	{},
>   };
>   
> -static u16 slicemask(struct intel_gt *gt, int count)
> -{
> -	u64 dss_mask = intel_sseu_get_subslices(&gt->info.sseu, 0);
> -
> -	return intel_slicemask_from_dssmask(dss_mask, count);
> -}
> -
>   int intel_gt_init_mmio(struct intel_gt *gt)
>   {
>   	struct drm_i915_private *i915 = gt->i915;
> @@ -153,11 +146,14 @@ int intel_gt_init_mmio(struct intel_gt *gt)
>   	 * An mslice is unavailable only if both the meml3 for the slice is
>   	 * disabled *and* all of the DSS in the slice (quadrant) are disabled.
>   	 */
> -	if (HAS_MSLICES(i915))
> +	if (HAS_MSLICES(i915)) {
>   		gt->info.mslice_mask =
> -			slicemask(gt, GEN_DSS_PER_MSLICE) |
> +			intel_slicemask_from_dssmask(gt->info.sseu.subslice_mask,
> +						     GEN_DSS_PER_MSLICE);
> +		gt->info.mslice_mask |=
>   			(intel_uncore_read(gt->uncore, GEN10_MIRROR_FUSE3) &
>   			 GEN12_MEML3_EN_MASK);
> +	}
>   
>   	if (IS_DG2(i915)) {
>   		gt->steering_table[MSLICE] = xehpsdv_mslice_steering_table;
> diff --git a/drivers/gpu/drm/i915/gt/intel_sseu.c b/drivers/gpu/drm/i915/gt/intel_sseu.c
> index f7ff6a9f67b0..466505d6bd18 100644
> --- a/drivers/gpu/drm/i915/gt/intel_sseu.c
> +++ b/drivers/gpu/drm/i915/gt/intel_sseu.c
> @@ -28,56 +28,49 @@ void intel_sseu_set_info(struct sseu_dev_info *sseu, u8 max_slices,
>   unsigned int
>   intel_sseu_subslice_total(const struct sseu_dev_info *sseu)
>   {
> -	unsigned int i, total = 0;
> -
> -	for (i = 0; i < ARRAY_SIZE(sseu->subslice_mask); i++)
> -		total += hweight8(sseu->subslice_mask[i]);
> -
> -	return total;
> +	return bitmap_weight(sseu->subslice_mask.b, I915_MAX_SS_FUSE_BITS);
>   }
>   
> -static u32
> -sseu_get_subslices(const struct sseu_dev_info *sseu,
> -		   const u8 *subslice_mask, u8 slice)
> +static intel_sseu_ss_mask_t
> +get_ss_mask_for_slice(const struct sseu_dev_info *sseu,
> +		      intel_sseu_ss_mask_t all_ss,
> +		      int slice)
>   {
> -	int i, offset = slice * sseu->ss_stride;
> -	u32 mask = 0;
> +	intel_sseu_ss_mask_t mask = {}, slice_ss = {};
> +	int offset = slice * sseu->max_subslices;
>   
>   	GEM_BUG_ON(slice >= sseu->max_slices);
>   
> -	for (i = 0; i < sseu->ss_stride; i++)
> -		mask |= (u32)subslice_mask[offset + i] << i * BITS_PER_BYTE;
> +	if (sseu->max_slices == 1)
> +		return all_ss;
>   
> -	return mask;
> -}
> +	bitmap_set(mask.b, offset, sseu->max_subslices);
> +	bitmap_and(slice_ss.b, all_ss.b, mask.b, I915_MAX_SS_FUSE_BITS);
> +	bitmap_shift_right(slice_ss.b, slice_ss.b, offset, I915_MAX_SS_FUSE_BITS);
>   
> -u32 intel_sseu_get_subslices(const struct sseu_dev_info *sseu, u8 slice)
> -{
> -	return sseu_get_subslices(sseu, sseu->subslice_mask, slice);
> +	return slice_ss;
>   }
>   
> -static u32 sseu_get_geometry_subslices(const struct sseu_dev_info *sseu)
> +intel_sseu_ss_mask_t
> +intel_sseu_get_subslices(const struct sseu_dev_info *sseu, u8 slice)
>   {
> -	return sseu_get_subslices(sseu, sseu->geometry_subslice_mask, 0);
> +	return get_ss_mask_for_slice(sseu, sseu->subslice_mask, slice);
>   }
>   
> -u32 intel_sseu_get_compute_subslices(const struct sseu_dev_info *sseu)
> -{
> -	return sseu_get_subslices(sseu, sseu->compute_subslice_mask, 0);
> -}
> -
> -void intel_sseu_set_subslices(struct sseu_dev_info *sseu, int slice,
> -			      u8 *subslice_mask, u32 ss_mask)
> -{
> -	int offset = slice * sseu->ss_stride;
> -
> -	memcpy(&subslice_mask[offset], &ss_mask, sseu->ss_stride);
> -}
> -
> -unsigned int
> -intel_sseu_subslices_per_slice(const struct sseu_dev_info *sseu, u8 slice)
> +/*
> + * Set the subslice mask associated with a specific slice.  Only needed on
> + * pre-gen11 platforms that have multiple slices.
> + */
> +static void set_subslices(struct sseu_dev_info *sseu, int slice, u32 ss_mask)
>   {
> -	return hweight32(intel_sseu_get_subslices(sseu, slice));
> +	intel_sseu_ss_mask_t mask = {}, newbits = {};
> +	int offset = slice * sseu->max_subslices;
> +
> +	bitmap_set(mask.b, offset, sseu->max_subslices);
> +	bitmap_from_arr32(newbits.b, &ss_mask, 32);
> +	bitmap_shift_left(newbits.b, newbits.b, offset, I915_MAX_SS_FUSE_BITS);
> +	bitmap_replace(sseu->subslice_mask.b, sseu->subslice_mask.b,
> +		       newbits.b, mask.b, I915_MAX_SS_FUSE_BITS);
>   }
>   
>   static int sseu_eu_idx(const struct sseu_dev_info *sseu, int slice,
> @@ -115,7 +108,7 @@ static u16 compute_eu_total(const struct sseu_dev_info *sseu)
>   	u16 i, total = 0;
>   
>   	if (sseu->has_common_ss_eumask)
> -		return intel_sseu_subslices_per_slice(sseu, 0) *
> +		return bitmap_weight(sseu->subslice_mask.b, I915_MAX_SS_FUSE_BITS) *
>   			hweight16(sseu->eu_mask[0]);
>   
>   	for (i = 0; i < ARRAY_SIZE(sseu->eu_mask); i++)
> @@ -155,11 +148,42 @@ int intel_sseu_copy_eumask_to_user(void __user *to,
>   	return copy_to_user(to, eu_mask, len);
>   }
>   
> -static void gen11_compute_sseu_info(struct sseu_dev_info *sseu,
> -				    u32 g_ss_en, u32 c_ss_en, u16 eu_en)
> +/**
> + * intel_sseu_copy_ssmask_to_user - Copy subslice mask into a userspace buffer
> + * @to: Pointer to userspace buffer to copy to
> + * @sseu: SSEU structure containing subslice mask to copy
> + *
> + * Copies the subslice mask to a userspace buffer in the format expected by
> + * the query ioctl's topology queries.
> + *
> + * Returns the result of the copy_to_user() operation.
> + */
> +int intel_sseu_copy_ssmask_to_user(void __user *to,
> +				   const struct sseu_dev_info *sseu)
>   {
> -	u32 valid_ss_mask = GENMASK(sseu->max_subslices - 1, 0);
> +	u8 ss_mask[GEN_SS_MASK_SIZE] = {};
> +	int len = sseu->max_slices * sseu->ss_stride;
> +	int s, ss, i;
>   
> +	for (s = 0; s < sseu->max_slices; s++) {
> +		for (ss = 0; ss < sseu->max_subslices; ss++) {
> +			i = s * sseu->ss_stride + ss;
> +
> +			if (!intel_sseu_has_subslice(sseu, s, ss))
> +				continue;
> +
> +			ss_mask[i / BITS_PER_BYTE] |= BIT(i % BITS_PER_BYTE);
> +		}
> +	}
> +
> +	return copy_to_user(to, ss_mask, len);
> +}
> +
> +static void gen11_compute_sseu_info(struct sseu_dev_info *sseu,
> +				    intel_sseu_ss_mask_t g_ss_en,
> +				    intel_sseu_ss_mask_t c_ss_en,
> +				    u16 eu_en)
> +{
>   	/* g_ss_en/c_ss_en represent entire subslice mask across all slices */
>   	GEM_BUG_ON(sseu->max_slices * sseu->max_subslices >
>   		   sizeof(g_ss_en) * BITS_PER_BYTE);
> @@ -174,12 +198,12 @@ static void gen11_compute_sseu_info(struct sseu_dev_info *sseu,
>   	 * enabled subslice count for the purposes of selecting subslices to
>   	 * use in a particular GEM context.
>   	 */
> -	intel_sseu_set_subslices(sseu, 0, sseu->compute_subslice_mask,
> -				 c_ss_en & valid_ss_mask);
> -	intel_sseu_set_subslices(sseu, 0, sseu->geometry_subslice_mask,
> -				 g_ss_en & valid_ss_mask);
> -	intel_sseu_set_subslices(sseu, 0, sseu->subslice_mask,
> -				 (g_ss_en | c_ss_en) & valid_ss_mask);
> +	bitmap_copy(sseu->compute_subslice_mask.b, c_ss_en.b, I915_MAX_SS_FUSE_BITS);
> +	bitmap_copy(sseu->geometry_subslice_mask.b, g_ss_en.b, I915_MAX_SS_FUSE_BITS);
> +	bitmap_or(sseu->subslice_mask.b,
> +		  sseu->compute_subslice_mask.b,
> +		  sseu->geometry_subslice_mask.b,
> +		  I915_MAX_SS_FUSE_BITS);
>   
>   	sseu->has_common_ss_eumask = 1;
>   	sseu->eu_mask[0] = eu_en;
> @@ -191,7 +215,8 @@ static void xehp_sseu_info_init(struct intel_gt *gt)
>   {
>   	struct sseu_dev_info *sseu = &gt->info.sseu;
>   	struct intel_uncore *uncore = gt->uncore;
> -	u32 g_dss_en, c_dss_en = 0;
> +	intel_sseu_ss_mask_t g_dss_en = {}, c_dss_en = {};
> +	u32 val;
>   	u16 eu_en = 0;
>   	u8 eu_en_fuse;
>   	int eu;
> @@ -204,8 +229,11 @@ static void xehp_sseu_info_init(struct intel_gt *gt)
>   	 */
>   	intel_sseu_set_info(sseu, 1, 32, 16);
>   
> -	g_dss_en = intel_uncore_read(uncore, GEN12_GT_GEOMETRY_DSS_ENABLE);
> -	c_dss_en = intel_uncore_read(uncore, GEN12_GT_COMPUTE_DSS_ENABLE);
> +	val = intel_uncore_read(uncore, GEN12_GT_GEOMETRY_DSS_ENABLE);
> +	bitmap_from_arr32(g_dss_en.b, &val, 32);
> +
> +	val = intel_uncore_read(uncore, GEN12_GT_COMPUTE_DSS_ENABLE);
> +	bitmap_from_arr32(c_dss_en.b, &val, 32);
>   
>   	eu_en_fuse = intel_uncore_read(uncore, XEHP_EU_ENABLE) & XEHP_EU_ENA_MASK;
>   
> @@ -220,7 +248,8 @@ static void gen12_sseu_info_init(struct intel_gt *gt)
>   {
>   	struct sseu_dev_info *sseu = &gt->info.sseu;
>   	struct intel_uncore *uncore = gt->uncore;
> -	u32 g_dss_en;
> +	intel_sseu_ss_mask_t g_dss_en = {}, empty_mask = {};
> +	u32 val;
>   	u16 eu_en = 0;
>   	u8 eu_en_fuse;
>   	u8 s_en;
> @@ -243,7 +272,8 @@ static void gen12_sseu_info_init(struct intel_gt *gt)
>   		drm_dbg(&gt->i915->drm, "Slice mask %#x is not the expected 0x1!\n",
>   			s_en);
>   
> -	g_dss_en = intel_uncore_read(uncore, GEN12_GT_GEOMETRY_DSS_ENABLE);
> +	val = intel_uncore_read(uncore, GEN12_GT_GEOMETRY_DSS_ENABLE);
> +	bitmap_from_arr32(g_dss_en.b, &val, 32);
>   
>   	/* one bit per pair of EUs */
>   	eu_en_fuse = ~(intel_uncore_read(uncore, GEN11_EU_DISABLE) &
> @@ -253,7 +283,7 @@ static void gen12_sseu_info_init(struct intel_gt *gt)
>   		if (eu_en_fuse & BIT(eu))
>   			eu_en |= BIT(eu * 2) | BIT(eu * 2 + 1);
>   
> -	gen11_compute_sseu_info(sseu, g_dss_en, 0, eu_en);
> +	gen11_compute_sseu_info(sseu, g_dss_en, empty_mask, eu_en);
>   
>   	/* TGL only supports slice-level power gating */
>   	sseu->has_slice_pg = 1;
> @@ -263,7 +293,8 @@ static void gen11_sseu_info_init(struct intel_gt *gt)
>   {
>   	struct sseu_dev_info *sseu = &gt->info.sseu;
>   	struct intel_uncore *uncore = gt->uncore;
> -	u32 ss_en;
> +	intel_sseu_ss_mask_t ss_en = {}, empty_mask = {};
> +	u32 val;
>   	u8 eu_en;
>   	u8 s_en;
>   
> @@ -282,12 +313,13 @@ static void gen11_sseu_info_init(struct intel_gt *gt)
>   		drm_dbg(&gt->i915->drm, "Slice mask %#x is not the expected 0x1!\n",
>   			s_en);
>   
> -	ss_en = ~intel_uncore_read(uncore, GEN11_GT_SUBSLICE_DISABLE);
> +	val = ~intel_uncore_read(uncore, GEN11_GT_SUBSLICE_DISABLE);
> +	bitmap_from_arr32(ss_en.b, &val, 32);
>   
>   	eu_en = ~(intel_uncore_read(uncore, GEN11_EU_DISABLE) &
>   		  GEN11_EU_DIS_MASK);
>   
> -	gen11_compute_sseu_info(sseu, ss_en, 0, eu_en);
> +	gen11_compute_sseu_info(sseu, ss_en, empty_mask, eu_en);
>   
>   	/* ICL has no power gating restrictions. */
>   	sseu->has_slice_pg = 1;
> @@ -328,7 +360,7 @@ static void cherryview_sseu_info_init(struct intel_gt *gt)
>   		sseu_set_eus(sseu, 0, 1, ~disabled_mask);
>   	}
>   
> -	intel_sseu_set_subslices(sseu, 0, sseu->subslice_mask, subslice_mask);
> +	set_subslices(sseu, 0, subslice_mask);
>   
>   	sseu->eu_total = compute_eu_total(sseu);
>   
> @@ -384,8 +416,7 @@ static void gen9_sseu_info_init(struct intel_gt *gt)
>   			/* skip disabled slice */
>   			continue;
>   
> -		intel_sseu_set_subslices(sseu, s, sseu->subslice_mask,
> -					 subslice_mask);
> +		set_subslices(sseu, s, subslice_mask);
>   
>   		eu_disable = intel_uncore_read(uncore, GEN9_EU_DISABLE(s));
>   		for (ss = 0; ss < sseu->max_subslices; ss++) {
> @@ -442,8 +473,8 @@ static void gen9_sseu_info_init(struct intel_gt *gt)
>   	sseu->has_eu_pg = sseu->eu_per_subslice > 2;
>   
>   	if (IS_GEN9_LP(i915)) {
> -#define IS_SS_DISABLED(ss)	(!(sseu->subslice_mask[0] & BIT(ss)))
> -		info->has_pooled_eu = hweight8(sseu->subslice_mask[0]) == 3;
> +#define IS_SS_DISABLED(ss)	test_bit(ss, sseu->subslice_mask.b)
> +		info->has_pooled_eu = hweight8(sseu->subslice_mask.b[0]) == 3;
>   
>   		sseu->min_eu_in_pool = 0;
>   		if (info->has_pooled_eu) {
> @@ -497,8 +528,7 @@ static void bdw_sseu_info_init(struct intel_gt *gt)
>   			/* skip disabled slice */
>   			continue;
>   
> -		intel_sseu_set_subslices(sseu, s, sseu->subslice_mask,
> -					 subslice_mask);
> +		set_subslices(sseu, s, subslice_mask);
>   
>   		for (ss = 0; ss < sseu->max_subslices; ss++) {
>   			u8 eu_disabled_mask;
> @@ -595,8 +625,7 @@ static void hsw_sseu_info_init(struct intel_gt *gt)
>   			    sseu->eu_per_subslice);
>   
>   	for (s = 0; s < sseu->max_slices; s++) {
> -		intel_sseu_set_subslices(sseu, s, sseu->subslice_mask,
> -					 subslice_mask);
> +		set_subslices(sseu, s, subslice_mask);
>   
>   		for (ss = 0; ss < sseu->max_subslices; ss++) {
>   			sseu_set_eus(sseu, s, ss,
> @@ -685,7 +714,7 @@ u32 intel_sseu_make_rpcs(struct intel_gt *gt,
>   	 */
>   	if (GRAPHICS_VER(i915) == 11 &&
>   	    slices == 1 &&
> -	    subslices > min_t(u8, 4, hweight8(sseu->subslice_mask[0]) / 2)) {
> +	    subslices > min_t(u8, 4, hweight8(sseu->subslice_mask.b[0]) / 2)) {
>   		GEM_BUG_ON(subslices & 1);
>   
>   		subslice_pg = false;
> @@ -755,9 +784,11 @@ void intel_sseu_dump(const struct sseu_dev_info *sseu, struct drm_printer *p)
>   		   hweight8(sseu->slice_mask), sseu->slice_mask);
>   	drm_printf(p, "subslice total: %u\n", intel_sseu_subslice_total(sseu));
>   	for (s = 0; s < sseu->max_slices; s++) {
> -		drm_printf(p, "slice%d: %u subslices, mask=%08x\n",
> -			   s, intel_sseu_subslices_per_slice(sseu, s),
> -			   intel_sseu_get_subslices(sseu, s));
> +		intel_sseu_ss_mask_t ssmask = intel_sseu_get_subslices(sseu, s);
> +
> +		drm_printf(p, "slice%d: %u subslices, mask=%*pb\n",
> +			   s, bitmap_weight(ssmask.b, I915_MAX_SS_FUSE_BITS),
> +			   I915_MAX_SS_FUSE_BITS, ssmask.b);
>   	}
>   	drm_printf(p, "EU total: %u\n", sseu->eu_total);
>   	drm_printf(p, "EU per subslice: %u\n", sseu->eu_per_subslice);
> @@ -775,9 +806,11 @@ static void sseu_print_hsw_topology(const struct sseu_dev_info *sseu,
>   	int s, ss;
>   
>   	for (s = 0; s < sseu->max_slices; s++) {
> -		drm_printf(p, "slice%d: %u subslice(s) (0x%08x):\n",
> -			   s, intel_sseu_subslices_per_slice(sseu, s),
> -			   intel_sseu_get_subslices(sseu, s));
> +		intel_sseu_ss_mask_t ssmask = intel_sseu_get_subslices(sseu, s);
> +
> +		drm_printf(p, "slice%d: %u subslice(s) (0x%*pb):\n",
> +			   s, bitmap_weight(ssmask.b, I915_MAX_SS_FUSE_BITS),
> +			   I915_MAX_SS_FUSE_BITS, ssmask.b);
>   
>   		for (ss = 0; ss < sseu->max_subslices; ss++) {
>   			u16 enabled_eus = sseu_get_eus(sseu, s, ss);
> @@ -791,16 +824,14 @@ static void sseu_print_hsw_topology(const struct sseu_dev_info *sseu,
>   static void sseu_print_xehp_topology(const struct sseu_dev_info *sseu,
>   				     struct drm_printer *p)
>   {
> -	u32 g_dss_mask = sseu_get_geometry_subslices(sseu);
> -	u32 c_dss_mask = intel_sseu_get_compute_subslices(sseu);
>   	int dss;
>   
>   	for (dss = 0; dss < sseu->max_subslices; dss++) {
>   		u16 enabled_eus = sseu_get_eus(sseu, 0, dss);
>   
>   		drm_printf(p, "DSS_%02d: G:%3s C:%3s, %2u EUs (0x%04hx)\n", dss,
> -			   str_yes_no(g_dss_mask & BIT(dss)),
> -			   str_yes_no(c_dss_mask & BIT(dss)),
> +			   str_yes_no(test_bit(dss, sseu->geometry_subslice_mask.b)),
> +			   str_yes_no(test_bit(dss, sseu->compute_subslice_mask.b)),
>   			   hweight16(enabled_eus), enabled_eus);
>   	}
>   }
> @@ -818,20 +849,24 @@ void intel_sseu_print_topology(struct drm_i915_private *i915,
>   	}
>   }
>   
> -u16 intel_slicemask_from_dssmask(u64 dss_mask, int dss_per_slice)
> +u16 intel_slicemask_from_dssmask(intel_sseu_ss_mask_t dss_mask,
> +				 int dss_per_slice)
>   {
> +	intel_sseu_ss_mask_t per_slice_mask = {};
>   	u16 slice_mask = 0;
>   	int i;
>   
> -	WARN_ON(sizeof(dss_mask) * 8 / dss_per_slice > 8 * sizeof(slice_mask));
> +	WARN_ON(DIV_ROUND_UP(I915_MAX_SS_FUSE_BITS, dss_per_slice) >
> +		8 * sizeof(slice_mask));
>   
> -	for (i = 0; dss_mask; i++) {
> -		if (dss_mask & GENMASK(dss_per_slice - 1, 0))
> +	bitmap_fill(per_slice_mask.b, dss_per_slice);
> +	for (i = 0; !bitmap_empty(dss_mask.b, I915_MAX_SS_FUSE_BITS); i++) {
> +		if (bitmap_intersects(dss_mask.b, per_slice_mask.b, dss_per_slice))
>   			slice_mask |= BIT(i);
>   
> -		dss_mask >>= dss_per_slice;
> +		bitmap_shift_right(dss_mask.b, dss_mask.b, dss_per_slice,
> +				   I915_MAX_SS_FUSE_BITS);
>   	}
>   
>   	return slice_mask;
>   }
> -
> diff --git a/drivers/gpu/drm/i915/gt/intel_sseu.h b/drivers/gpu/drm/i915/gt/intel_sseu.h
> index 106726a2244e..455f085093ae 100644
> --- a/drivers/gpu/drm/i915/gt/intel_sseu.h
> +++ b/drivers/gpu/drm/i915/gt/intel_sseu.h
> @@ -52,11 +52,22 @@ struct drm_printer;
>   #define GEN_MAX_GSLICES		(GEN_MAX_DSS / GEN_DSS_PER_GSLICE)
>   #define GEN_MAX_CSLICES		(GEN_MAX_DSS / GEN_DSS_PER_CSLICE)
>   
> +/*
> + * Maximum number of 32-bit registers used by hardware to express the
> + * enabled/disabled subslices.
> + */
> +#define I915_MAX_SS_FUSE_REGS	1
> +#define I915_MAX_SS_FUSE_BITS	(I915_MAX_SS_FUSE_REGS * 32)
> +
> +typedef struct {
> +	unsigned long b[BITS_TO_LONGS(I915_MAX_SS_FUSE_BITS)];
> +} intel_sseu_ss_mask_t;
> +
>   struct sseu_dev_info {
>   	u8 slice_mask;
> -	u8 subslice_mask[GEN_SS_MASK_SIZE];
> -	u8 geometry_subslice_mask[GEN_SS_MASK_SIZE];
> -	u8 compute_subslice_mask[GEN_SS_MASK_SIZE];
> +	intel_sseu_ss_mask_t subslice_mask;
> +	intel_sseu_ss_mask_t geometry_subslice_mask;
> +	intel_sseu_ss_mask_t compute_subslice_mask;
>   
>   	/*
>   	 * EU masks.  Use has_common_ss_eumask to determine how the field
> @@ -107,7 +118,7 @@ intel_sseu_from_device_info(const struct sseu_dev_info *sseu)
>   {
>   	struct intel_sseu value = {
>   		.slice_mask = sseu->slice_mask,
> -		.subslice_mask = sseu->subslice_mask[0],
> +		.subslice_mask = sseu->subslice_mask.b[0],
>   		.min_eus_per_subslice = sseu->max_eus_per_subslice,
>   		.max_eus_per_subslice = sseu->max_eus_per_subslice,
>   	};
> @@ -119,18 +130,8 @@ static inline bool
>   intel_sseu_has_subslice(const struct sseu_dev_info *sseu, int slice,
>   			int subslice)
>   {
> -	u8 mask;
> -	int ss_idx = subslice / BITS_PER_BYTE;
> -
> -	if (slice >= sseu->max_slices ||
> -	    subslice >= sseu->max_subslices)
> -		return false;
> -
> -	GEM_BUG_ON(ss_idx >= sseu->ss_stride);
> -
> -	mask = sseu->subslice_mask[slice * sseu->ss_stride + ss_idx];
> -
> -	return mask & BIT(subslice % BITS_PER_BYTE);
> +	return test_bit(slice * sseu->ss_stride + subslice,
> +			sseu->subslice_mask.b);
>   }
>   
>   void intel_sseu_set_info(struct sseu_dev_info *sseu, u8 max_slices,
> @@ -139,15 +140,14 @@ void intel_sseu_set_info(struct sseu_dev_info *sseu, u8 max_slices,
>   unsigned int
>   intel_sseu_subslice_total(const struct sseu_dev_info *sseu);
>   
> -unsigned int
> -intel_sseu_subslices_per_slice(const struct sseu_dev_info *sseu, u8 slice);
> +intel_sseu_ss_mask_t
> +intel_sseu_get_subslices(const struct sseu_dev_info *sseu, u8 slice);
>   
> -u32 intel_sseu_get_subslices(const struct sseu_dev_info *sseu, u8 slice);
> -
> -u32 intel_sseu_get_compute_subslices(const struct sseu_dev_info *sseu);
> +intel_sseu_ss_mask_t
> +intel_sseu_get_compute_subslices(const struct sseu_dev_info *sseu);
>   
>   void intel_sseu_set_subslices(struct sseu_dev_info *sseu, int slice,
> -			      u8 *subslice_mask, u32 ss_mask);
> +			      u32 ss_mask);
>   
>   void intel_sseu_info_init(struct intel_gt *gt);
>   
> @@ -159,9 +159,11 @@ void intel_sseu_print_topology(struct drm_i915_private *i915,
>   			       const struct sseu_dev_info *sseu,
>   			       struct drm_printer *p);
>   
> -u16 intel_slicemask_from_dssmask(u64 dss_mask, int dss_per_slice);
> +u16 intel_slicemask_from_dssmask(intel_sseu_ss_mask_t dss_mask, int dss_per_slice);
>   
>   int intel_sseu_copy_eumask_to_user(void __user *to,
>   				   const struct sseu_dev_info *sseu);
> +int intel_sseu_copy_ssmask_to_user(void __user *to,
> +				   const struct sseu_dev_info *sseu);
>   
>   #endif /* __INTEL_SSEU_H__ */
> diff --git a/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c b/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c
> index 2d5d011e01db..1f77bd52a3a6 100644
> --- a/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c
> +++ b/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c
> @@ -4,6 +4,7 @@
>    * Copyright © 2020 Intel Corporation
>    */
>   
> +#include <linux/bitmap.h>
>   #include <linux/string_helpers.h>
>   
>   #include "i915_drv.h"
> @@ -12,11 +13,15 @@
>   #include "intel_sseu_debugfs.h"
>   
>   static void sseu_copy_subslices(const struct sseu_dev_info *sseu,
> -				int slice, u8 *to_mask)
> +				int slice,
> +				intel_sseu_ss_mask_t *to_mask)
>   {
> -	int offset = slice * sseu->ss_stride;
> +	int offset = slice * sseu->max_subslices;
>   
> -	memcpy(&to_mask[offset], &sseu->subslice_mask[offset], sseu->ss_stride);
> +	bitmap_fill(to_mask->b, sseu->max_subslices);
> +	bitmap_shift_left(to_mask->b, to_mask->b, offset, I915_MAX_SS_FUSE_BITS);
> +	bitmap_and(to_mask->b, to_mask->b, sseu->subslice_mask.b, I915_MAX_SS_FUSE_BITS);
> +	bitmap_shift_right(to_mask->b, to_mask->b, offset, I915_MAX_SS_FUSE_BITS);
>   }
>   
>   static void cherryview_sseu_device_status(struct intel_gt *gt,
> @@ -41,7 +46,7 @@ static void cherryview_sseu_device_status(struct intel_gt *gt,
>   			continue;
>   
>   		sseu->slice_mask = BIT(0);
> -		sseu->subslice_mask[0] |= BIT(ss);
> +		set_bit(0, sseu->subslice_mask.b);
>   		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) +
> @@ -92,7 +97,7 @@ static void gen11_sseu_device_status(struct intel_gt *gt,
>   			continue;
>   
>   		sseu->slice_mask |= BIT(s);
> -		sseu_copy_subslices(&info->sseu, s, sseu->subslice_mask);
> +		sseu_copy_subslices(&info->sseu, s, &sseu->subslice_mask);
>   
>   		for (ss = 0; ss < info->sseu.max_subslices; ss++) {
>   			unsigned int eu_cnt;
> @@ -148,20 +153,17 @@ static void gen9_sseu_device_status(struct intel_gt *gt,
>   
>   		if (IS_GEN9_BC(gt->i915))
>   			sseu_copy_subslices(&info->sseu, s,
> -					    sseu->subslice_mask);
> +					    &sseu->subslice_mask);
>   
>   		for (ss = 0; ss < info->sseu.max_subslices; ss++) {
>   			unsigned int eu_cnt;
> -			u8 ss_idx = s * info->sseu.ss_stride +
> -				    ss / BITS_PER_BYTE;
>   
>   			if (IS_GEN9_LP(gt->i915)) {
>   				if (!(s_reg[s] & (GEN9_PGCTL_SS_ACK(ss))))
>   					/* skip disabled subslice */
>   					continue;
>   
> -				sseu->subslice_mask[ss_idx] |=
> -					BIT(ss % BITS_PER_BYTE);
> +				set_bit(ss, sseu->subslice_mask.b);
>   			}
>   
>   			eu_cnt = eu_reg[2 * s + ss / 2] & eu_mask[ss % 2];
> @@ -189,7 +191,7 @@ static void bdw_sseu_device_status(struct intel_gt *gt,
>   		sseu->eu_per_subslice = info->sseu.eu_per_subslice;
>   		for (s = 0; s < fls(sseu->slice_mask); s++)
>   			sseu_copy_subslices(&info->sseu, s,
> -					    sseu->subslice_mask);
> +					    &sseu->subslice_mask);
>   		sseu->eu_total = sseu->eu_per_subslice *
>   				 intel_sseu_subslice_total(sseu);
>   
> @@ -217,8 +219,10 @@ static void i915_print_sseu_info(struct seq_file *m,
>   	seq_printf(m, "  %s Subslice Total: %u\n", type,
>   		   intel_sseu_subslice_total(sseu));
>   	for (s = 0; s < fls(sseu->slice_mask); s++) {
> +		intel_sseu_ss_mask_t ssmask = intel_sseu_get_subslices(sseu, s);
> +
>   		seq_printf(m, "  %s Slice%i subslices: %u\n", type,
> -			   s, intel_sseu_subslices_per_slice(sseu, s));
> +			   s, bitmap_weight(ssmask.b, I915_MAX_SS_FUSE_BITS));
>   	}
>   	seq_printf(m, "  %s EU Total: %u\n", type,
>   		   sseu->eu_total);
> diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c
> index a05c4b99b3fb..5db492072f99 100644
> --- a/drivers/gpu/drm/i915/gt/intel_workarounds.c
> +++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c
> @@ -931,6 +931,7 @@ static void
>   gen9_wa_init_mcr(struct drm_i915_private *i915, struct i915_wa_list *wal)
>   {
>   	const struct sseu_dev_info *sseu = &to_gt(i915)->info.sseu;
> +	intel_sseu_ss_mask_t ssmask;
>   	unsigned int slice, subslice;
>   	u32 mcr, mcr_mask;
>   
> @@ -948,9 +949,9 @@ gen9_wa_init_mcr(struct drm_i915_private *i915, struct i915_wa_list *wal)
>   	 * on s/ss combo, the read should be done with read_subslice_reg.
>   	 */
>   	slice = ffs(sseu->slice_mask) - 1;
> -	GEM_BUG_ON(slice >= ARRAY_SIZE(sseu->subslice_mask));
> -	subslice = ffs(intel_sseu_get_subslices(sseu, slice));
> -	GEM_BUG_ON(!subslice);
> +	ssmask = intel_sseu_get_subslices(sseu, slice);
> +	subslice = find_first_bit(ssmask.b, I915_MAX_SS_FUSE_BITS);
> +	GEM_BUG_ON(subslice == I915_MAX_SS_FUSE_BITS);
>   	subslice--;
>   
>   	/*
> @@ -1087,11 +1088,10 @@ static void
>   icl_wa_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
>   {
>   	const struct sseu_dev_info *sseu = &gt->info.sseu;
> -	unsigned int slice, subslice;
> +	unsigned int subslice;
>   
>   	GEM_BUG_ON(GRAPHICS_VER(gt->i915) < 11);
>   	GEM_BUG_ON(hweight8(sseu->slice_mask) > 1);
> -	slice = 0;
>   
>   	/*
>   	 * Although a platform may have subslices, we need to always steer
> @@ -1102,7 +1102,7 @@ icl_wa_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
>   	 * one of the higher subslices, we run the risk of reading back 0's or
>   	 * random garbage.
>   	 */
> -	subslice = __ffs(intel_sseu_get_subslices(sseu, slice));
> +	subslice = find_first_bit(sseu->subslice_mask.b, I915_MAX_SS_FUSE_BITS);
>   
>   	/*
>   	 * If the subslice we picked above also steers us to a valid L3 bank,
> @@ -1112,7 +1112,7 @@ icl_wa_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
>   	if (gt->info.l3bank_mask & BIT(subslice))
>   		gt->steering_table[L3BANK] = NULL;
>   
> -	__add_mcr_wa(gt, wal, slice, subslice);
> +	__add_mcr_wa(gt, wal, 0, subslice);
>   }
>   
>   static void
> @@ -1120,7 +1120,6 @@ xehp_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
>   {
>   	const struct sseu_dev_info *sseu = &gt->info.sseu;
>   	unsigned long slice, subslice = 0, slice_mask = 0;
> -	u64 dss_mask = 0;
>   	u32 lncf_mask = 0;
>   	int i;
>   
> @@ -1151,8 +1150,8 @@ xehp_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
>   	 */
>   
>   	/* Find the potential gslice candidates */
> -	dss_mask = intel_sseu_get_subslices(sseu, 0);
> -	slice_mask = intel_slicemask_from_dssmask(dss_mask, GEN_DSS_PER_GSLICE);
> +	slice_mask = intel_slicemask_from_dssmask(sseu->subslice_mask,
> +						  GEN_DSS_PER_GSLICE);
>   
>   	/*
>   	 * Find the potential LNCF candidates.  Either LNCF within a valid
> @@ -1177,9 +1176,9 @@ xehp_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
>   	}
>   
>   	slice = __ffs(slice_mask);
> -	subslice = __ffs(dss_mask >> (slice * GEN_DSS_PER_GSLICE));
> +	subslice = find_next_bit(sseu->subslice_mask.b, I915_MAX_SS_FUSE_BITS,
> +				 slice * GEN_DSS_PER_GSLICE);
>   	WARN_ON(subslice > GEN_DSS_PER_GSLICE);
> -	WARN_ON(dss_mask >> (slice * GEN_DSS_PER_GSLICE) == 0);
>   
>   	__add_mcr_wa(gt, wal, slice, subslice);
>   
> @@ -2012,9 +2011,8 @@ engine_fake_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
>   
>   static bool needs_wa_1308578152(struct intel_engine_cs *engine)
>   {
> -	u64 dss_mask = intel_sseu_get_subslices(&engine->gt->info.sseu, 0);
> -
> -	return (dss_mask & GENMASK(GEN_DSS_PER_GSLICE - 1, 0)) == 0;
> +	return find_first_bit(engine->gt->info.sseu.subslice_mask.b,
> +			      I915_MAX_SS_FUSE_BITS) >= GEN_DSS_PER_GSLICE;
>   }
>   
>   static void
> diff --git a/drivers/gpu/drm/i915/i915_getparam.c b/drivers/gpu/drm/i915/i915_getparam.c
> index ac9767c56619..349d496d164a 100644
> --- a/drivers/gpu/drm/i915/i915_getparam.c
> +++ b/drivers/gpu/drm/i915/i915_getparam.c
> @@ -162,7 +162,7 @@ int i915_getparam_ioctl(struct drm_device *dev, void *data,
>   			return -EINVAL;
>   
>   		/* Only copy bits from the first slice */
> -		memcpy(&value, sseu->subslice_mask,
> +		memcpy(&value, sseu->subslice_mask.b,
>   		       min(sseu->ss_stride, (u8)sizeof(value)));
>   		if (!value)
>   			return -ENODEV;
> diff --git a/drivers/gpu/drm/i915/i915_query.c b/drivers/gpu/drm/i915/i915_query.c
> index 16f43bf32a05..9afa6d1eaf95 100644
> --- a/drivers/gpu/drm/i915/i915_query.c
> +++ b/drivers/gpu/drm/i915/i915_query.c
> @@ -31,7 +31,7 @@ static int copy_query_item(void *query_hdr, size_t query_sz,
>   
>   static int fill_topology_info(const struct sseu_dev_info *sseu,
>   			      struct drm_i915_query_item *query_item,
> -			      const u8 *subslice_mask)
> +			      intel_sseu_ss_mask_t subslice_mask)
>   {
>   	struct drm_i915_query_topology_info topo;
>   	u32 slice_length, subslice_length, eu_length, total_length;
> @@ -71,9 +71,9 @@ static int fill_topology_info(const struct sseu_dev_info *sseu,
>   			 &sseu->slice_mask, slice_length))
>   		return -EFAULT;
>   
> -	if (copy_to_user(u64_to_user_ptr(query_item->data_ptr +
> -					 sizeof(topo) + slice_length),
> -			 subslice_mask, subslice_length))
> +	if (intel_sseu_copy_ssmask_to_user(u64_to_user_ptr(query_item->data_ptr +
> +							   sizeof(topo) + slice_length),
> +					   sseu))
>   		return -EFAULT;
>   
>   	if (intel_sseu_copy_eumask_to_user(u64_to_user_ptr(query_item->data_ptr +

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

* Re: [Intel-gfx] [PATCH 5/5] drm/i915/sseu: Disassociate internal subslice mask representation from uapi
@ 2022-04-28 12:18     ` Tvrtko Ursulin
  0 siblings, 0 replies; 27+ messages in thread
From: Tvrtko Ursulin @ 2022-04-28 12:18 UTC (permalink / raw)
  To: Matt Roper, intel-gfx; +Cc: dri-devel


Hi,

On 28/04/2022 00:07, Matt Roper wrote:
> Rather than storing subslice masks internally as u8[] (inside the sseu
> structure) and u32 (everywhere else), let's move over to using an
> intel_sseu_ss_mask_t typedef compatible with the operations in
> linux/bitmap.h.  We're soon going to start adding code for a new
> platform where subslice masks are spread across two 32-bit registers
> (requiring 64 bits to represent), and we expect future platforms will
> likely take this even farther, requiring bitmask storage larger than a
> simple u64 can hold.

I won't have time to look into this in a detailed way for a few days. Until then a couple questions comments only.

First, out of curiousity, were you able to end up with less code after your series? With my bitmap conversion I think actually ended up with couple KB smaller text which was a good sign eliminating the internal layout complications was a good approach.

For your series I am not convinced by sseu->has_common_ss_eumask. Why the duality, just to save a few u32 at runtime?

I am also not convinced with leaving the eu_mask and subslice_mask being manually indexed with stride, calculcated by the driver. In my approach I simply went with multi-dimensional arrays which I think ends up with simpler code.

For all bitmap API call sites and *pb printk format sites, I suggest not hard-coding the widths from SSEU defines by querying the type itsef via wrappers. (See my BITMAP_BITS macro and helpers which wrap it for fields.)

Ie instead:

bitmap_shift_left(to_mask->b, to_mask->b, offset, I915_MAX_SS_FUSE_BITS);

I suggest:

bitmap_zero(slices.b, BITMAP_BITS(slices.b));

Also, all accesses to the bitmap type from outside intel_sse*.c|h should use intel_sseu wrappers and not embed knowledge of the typedef (that it has an member named .b etc).

And finally I would also use the opportunity to clean up the pointless u8 types for counts and such since I think they just result in worse code generation.

You can of course counter with what you did not like in my attempt. :) I know I did not finish the wrappers and possibly made an overkill by converting the slice mask to bitmap.

Regards,

Tvrtko
  
> Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
> ---
>   drivers/gpu/drm/i915/gem/i915_gem_context.c  |   4 +-
>   drivers/gpu/drm/i915/gt/intel_engine_cs.c    |   2 +-
>   drivers/gpu/drm/i915/gt/intel_gt.c           |  14 +-
>   drivers/gpu/drm/i915/gt/intel_sseu.c         | 197 +++++++++++--------
>   drivers/gpu/drm/i915/gt/intel_sseu.h         |  48 ++---
>   drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c |  28 +--
>   drivers/gpu/drm/i915/gt/intel_workarounds.c  |  28 ++-
>   drivers/gpu/drm/i915/i915_getparam.c         |   2 +-
>   drivers/gpu/drm/i915/i915_query.c            |   8 +-
>   9 files changed, 183 insertions(+), 148 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c
> index ab4c5ab28e4d..ea012ee3a8de 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c
> @@ -1901,7 +1901,7 @@ i915_gem_user_to_context_sseu(struct intel_gt *gt,
>   	if (user->slice_mask & ~device->slice_mask)
>   		return -EINVAL;
>   
> -	if (user->subslice_mask & ~device->subslice_mask[0])
> +	if (user->subslice_mask & ~device->subslice_mask.b[0])
>   		return -EINVAL;
>   
>   	if (user->max_eus_per_subslice > device->max_eus_per_subslice)
> @@ -1915,7 +1915,7 @@ i915_gem_user_to_context_sseu(struct intel_gt *gt,
>   	/* Part specific restrictions. */
>   	if (GRAPHICS_VER(i915) == 11) {
>   		unsigned int hw_s = hweight8(device->slice_mask);
> -		unsigned int hw_ss_per_s = hweight8(device->subslice_mask[0]);
> +		unsigned int hw_ss_per_s = hweight8(device->subslice_mask.b[0]);
>   		unsigned int req_s = hweight8(context->slice_mask);
>   		unsigned int req_ss = hweight8(context->subslice_mask);
>   
> diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
> index 14c6ddbbfde8..39c09963b3c7 100644
> --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c
> +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
> @@ -610,7 +610,7 @@ static void engine_mask_apply_compute_fuses(struct intel_gt *gt)
>   	if (GRAPHICS_VER_FULL(i915) < IP_VER(12, 50))
>   		return;
>   
> -	ccs_mask = intel_slicemask_from_dssmask(intel_sseu_get_compute_subslices(&info->sseu),
> +	ccs_mask = intel_slicemask_from_dssmask(info->sseu.compute_subslice_mask,
>   						ss_per_ccs);
>   	/*
>   	 * If all DSS in a quadrant are fused off, the corresponding CCS
> diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c
> index 92394f13b42f..cc03512d59ba 100644
> --- a/drivers/gpu/drm/i915/gt/intel_gt.c
> +++ b/drivers/gpu/drm/i915/gt/intel_gt.c
> @@ -133,13 +133,6 @@ static const struct intel_mmio_range dg2_lncf_steering_table[] = {
>   	{},
>   };
>   
> -static u16 slicemask(struct intel_gt *gt, int count)
> -{
> -	u64 dss_mask = intel_sseu_get_subslices(&gt->info.sseu, 0);
> -
> -	return intel_slicemask_from_dssmask(dss_mask, count);
> -}
> -
>   int intel_gt_init_mmio(struct intel_gt *gt)
>   {
>   	struct drm_i915_private *i915 = gt->i915;
> @@ -153,11 +146,14 @@ int intel_gt_init_mmio(struct intel_gt *gt)
>   	 * An mslice is unavailable only if both the meml3 for the slice is
>   	 * disabled *and* all of the DSS in the slice (quadrant) are disabled.
>   	 */
> -	if (HAS_MSLICES(i915))
> +	if (HAS_MSLICES(i915)) {
>   		gt->info.mslice_mask =
> -			slicemask(gt, GEN_DSS_PER_MSLICE) |
> +			intel_slicemask_from_dssmask(gt->info.sseu.subslice_mask,
> +						     GEN_DSS_PER_MSLICE);
> +		gt->info.mslice_mask |=
>   			(intel_uncore_read(gt->uncore, GEN10_MIRROR_FUSE3) &
>   			 GEN12_MEML3_EN_MASK);
> +	}
>   
>   	if (IS_DG2(i915)) {
>   		gt->steering_table[MSLICE] = xehpsdv_mslice_steering_table;
> diff --git a/drivers/gpu/drm/i915/gt/intel_sseu.c b/drivers/gpu/drm/i915/gt/intel_sseu.c
> index f7ff6a9f67b0..466505d6bd18 100644
> --- a/drivers/gpu/drm/i915/gt/intel_sseu.c
> +++ b/drivers/gpu/drm/i915/gt/intel_sseu.c
> @@ -28,56 +28,49 @@ void intel_sseu_set_info(struct sseu_dev_info *sseu, u8 max_slices,
>   unsigned int
>   intel_sseu_subslice_total(const struct sseu_dev_info *sseu)
>   {
> -	unsigned int i, total = 0;
> -
> -	for (i = 0; i < ARRAY_SIZE(sseu->subslice_mask); i++)
> -		total += hweight8(sseu->subslice_mask[i]);
> -
> -	return total;
> +	return bitmap_weight(sseu->subslice_mask.b, I915_MAX_SS_FUSE_BITS);
>   }
>   
> -static u32
> -sseu_get_subslices(const struct sseu_dev_info *sseu,
> -		   const u8 *subslice_mask, u8 slice)
> +static intel_sseu_ss_mask_t
> +get_ss_mask_for_slice(const struct sseu_dev_info *sseu,
> +		      intel_sseu_ss_mask_t all_ss,
> +		      int slice)
>   {
> -	int i, offset = slice * sseu->ss_stride;
> -	u32 mask = 0;
> +	intel_sseu_ss_mask_t mask = {}, slice_ss = {};
> +	int offset = slice * sseu->max_subslices;
>   
>   	GEM_BUG_ON(slice >= sseu->max_slices);
>   
> -	for (i = 0; i < sseu->ss_stride; i++)
> -		mask |= (u32)subslice_mask[offset + i] << i * BITS_PER_BYTE;
> +	if (sseu->max_slices == 1)
> +		return all_ss;
>   
> -	return mask;
> -}
> +	bitmap_set(mask.b, offset, sseu->max_subslices);
> +	bitmap_and(slice_ss.b, all_ss.b, mask.b, I915_MAX_SS_FUSE_BITS);
> +	bitmap_shift_right(slice_ss.b, slice_ss.b, offset, I915_MAX_SS_FUSE_BITS);
>   
> -u32 intel_sseu_get_subslices(const struct sseu_dev_info *sseu, u8 slice)
> -{
> -	return sseu_get_subslices(sseu, sseu->subslice_mask, slice);
> +	return slice_ss;
>   }
>   
> -static u32 sseu_get_geometry_subslices(const struct sseu_dev_info *sseu)
> +intel_sseu_ss_mask_t
> +intel_sseu_get_subslices(const struct sseu_dev_info *sseu, u8 slice)
>   {
> -	return sseu_get_subslices(sseu, sseu->geometry_subslice_mask, 0);
> +	return get_ss_mask_for_slice(sseu, sseu->subslice_mask, slice);
>   }
>   
> -u32 intel_sseu_get_compute_subslices(const struct sseu_dev_info *sseu)
> -{
> -	return sseu_get_subslices(sseu, sseu->compute_subslice_mask, 0);
> -}
> -
> -void intel_sseu_set_subslices(struct sseu_dev_info *sseu, int slice,
> -			      u8 *subslice_mask, u32 ss_mask)
> -{
> -	int offset = slice * sseu->ss_stride;
> -
> -	memcpy(&subslice_mask[offset], &ss_mask, sseu->ss_stride);
> -}
> -
> -unsigned int
> -intel_sseu_subslices_per_slice(const struct sseu_dev_info *sseu, u8 slice)
> +/*
> + * Set the subslice mask associated with a specific slice.  Only needed on
> + * pre-gen11 platforms that have multiple slices.
> + */
> +static void set_subslices(struct sseu_dev_info *sseu, int slice, u32 ss_mask)
>   {
> -	return hweight32(intel_sseu_get_subslices(sseu, slice));
> +	intel_sseu_ss_mask_t mask = {}, newbits = {};
> +	int offset = slice * sseu->max_subslices;
> +
> +	bitmap_set(mask.b, offset, sseu->max_subslices);
> +	bitmap_from_arr32(newbits.b, &ss_mask, 32);
> +	bitmap_shift_left(newbits.b, newbits.b, offset, I915_MAX_SS_FUSE_BITS);
> +	bitmap_replace(sseu->subslice_mask.b, sseu->subslice_mask.b,
> +		       newbits.b, mask.b, I915_MAX_SS_FUSE_BITS);
>   }
>   
>   static int sseu_eu_idx(const struct sseu_dev_info *sseu, int slice,
> @@ -115,7 +108,7 @@ static u16 compute_eu_total(const struct sseu_dev_info *sseu)
>   	u16 i, total = 0;
>   
>   	if (sseu->has_common_ss_eumask)
> -		return intel_sseu_subslices_per_slice(sseu, 0) *
> +		return bitmap_weight(sseu->subslice_mask.b, I915_MAX_SS_FUSE_BITS) *
>   			hweight16(sseu->eu_mask[0]);
>   
>   	for (i = 0; i < ARRAY_SIZE(sseu->eu_mask); i++)
> @@ -155,11 +148,42 @@ int intel_sseu_copy_eumask_to_user(void __user *to,
>   	return copy_to_user(to, eu_mask, len);
>   }
>   
> -static void gen11_compute_sseu_info(struct sseu_dev_info *sseu,
> -				    u32 g_ss_en, u32 c_ss_en, u16 eu_en)
> +/**
> + * intel_sseu_copy_ssmask_to_user - Copy subslice mask into a userspace buffer
> + * @to: Pointer to userspace buffer to copy to
> + * @sseu: SSEU structure containing subslice mask to copy
> + *
> + * Copies the subslice mask to a userspace buffer in the format expected by
> + * the query ioctl's topology queries.
> + *
> + * Returns the result of the copy_to_user() operation.
> + */
> +int intel_sseu_copy_ssmask_to_user(void __user *to,
> +				   const struct sseu_dev_info *sseu)
>   {
> -	u32 valid_ss_mask = GENMASK(sseu->max_subslices - 1, 0);
> +	u8 ss_mask[GEN_SS_MASK_SIZE] = {};
> +	int len = sseu->max_slices * sseu->ss_stride;
> +	int s, ss, i;
>   
> +	for (s = 0; s < sseu->max_slices; s++) {
> +		for (ss = 0; ss < sseu->max_subslices; ss++) {
> +			i = s * sseu->ss_stride + ss;
> +
> +			if (!intel_sseu_has_subslice(sseu, s, ss))
> +				continue;
> +
> +			ss_mask[i / BITS_PER_BYTE] |= BIT(i % BITS_PER_BYTE);
> +		}
> +	}
> +
> +	return copy_to_user(to, ss_mask, len);
> +}
> +
> +static void gen11_compute_sseu_info(struct sseu_dev_info *sseu,
> +				    intel_sseu_ss_mask_t g_ss_en,
> +				    intel_sseu_ss_mask_t c_ss_en,
> +				    u16 eu_en)
> +{
>   	/* g_ss_en/c_ss_en represent entire subslice mask across all slices */
>   	GEM_BUG_ON(sseu->max_slices * sseu->max_subslices >
>   		   sizeof(g_ss_en) * BITS_PER_BYTE);
> @@ -174,12 +198,12 @@ static void gen11_compute_sseu_info(struct sseu_dev_info *sseu,
>   	 * enabled subslice count for the purposes of selecting subslices to
>   	 * use in a particular GEM context.
>   	 */
> -	intel_sseu_set_subslices(sseu, 0, sseu->compute_subslice_mask,
> -				 c_ss_en & valid_ss_mask);
> -	intel_sseu_set_subslices(sseu, 0, sseu->geometry_subslice_mask,
> -				 g_ss_en & valid_ss_mask);
> -	intel_sseu_set_subslices(sseu, 0, sseu->subslice_mask,
> -				 (g_ss_en | c_ss_en) & valid_ss_mask);
> +	bitmap_copy(sseu->compute_subslice_mask.b, c_ss_en.b, I915_MAX_SS_FUSE_BITS);
> +	bitmap_copy(sseu->geometry_subslice_mask.b, g_ss_en.b, I915_MAX_SS_FUSE_BITS);
> +	bitmap_or(sseu->subslice_mask.b,
> +		  sseu->compute_subslice_mask.b,
> +		  sseu->geometry_subslice_mask.b,
> +		  I915_MAX_SS_FUSE_BITS);
>   
>   	sseu->has_common_ss_eumask = 1;
>   	sseu->eu_mask[0] = eu_en;
> @@ -191,7 +215,8 @@ static void xehp_sseu_info_init(struct intel_gt *gt)
>   {
>   	struct sseu_dev_info *sseu = &gt->info.sseu;
>   	struct intel_uncore *uncore = gt->uncore;
> -	u32 g_dss_en, c_dss_en = 0;
> +	intel_sseu_ss_mask_t g_dss_en = {}, c_dss_en = {};
> +	u32 val;
>   	u16 eu_en = 0;
>   	u8 eu_en_fuse;
>   	int eu;
> @@ -204,8 +229,11 @@ static void xehp_sseu_info_init(struct intel_gt *gt)
>   	 */
>   	intel_sseu_set_info(sseu, 1, 32, 16);
>   
> -	g_dss_en = intel_uncore_read(uncore, GEN12_GT_GEOMETRY_DSS_ENABLE);
> -	c_dss_en = intel_uncore_read(uncore, GEN12_GT_COMPUTE_DSS_ENABLE);
> +	val = intel_uncore_read(uncore, GEN12_GT_GEOMETRY_DSS_ENABLE);
> +	bitmap_from_arr32(g_dss_en.b, &val, 32);
> +
> +	val = intel_uncore_read(uncore, GEN12_GT_COMPUTE_DSS_ENABLE);
> +	bitmap_from_arr32(c_dss_en.b, &val, 32);
>   
>   	eu_en_fuse = intel_uncore_read(uncore, XEHP_EU_ENABLE) & XEHP_EU_ENA_MASK;
>   
> @@ -220,7 +248,8 @@ static void gen12_sseu_info_init(struct intel_gt *gt)
>   {
>   	struct sseu_dev_info *sseu = &gt->info.sseu;
>   	struct intel_uncore *uncore = gt->uncore;
> -	u32 g_dss_en;
> +	intel_sseu_ss_mask_t g_dss_en = {}, empty_mask = {};
> +	u32 val;
>   	u16 eu_en = 0;
>   	u8 eu_en_fuse;
>   	u8 s_en;
> @@ -243,7 +272,8 @@ static void gen12_sseu_info_init(struct intel_gt *gt)
>   		drm_dbg(&gt->i915->drm, "Slice mask %#x is not the expected 0x1!\n",
>   			s_en);
>   
> -	g_dss_en = intel_uncore_read(uncore, GEN12_GT_GEOMETRY_DSS_ENABLE);
> +	val = intel_uncore_read(uncore, GEN12_GT_GEOMETRY_DSS_ENABLE);
> +	bitmap_from_arr32(g_dss_en.b, &val, 32);
>   
>   	/* one bit per pair of EUs */
>   	eu_en_fuse = ~(intel_uncore_read(uncore, GEN11_EU_DISABLE) &
> @@ -253,7 +283,7 @@ static void gen12_sseu_info_init(struct intel_gt *gt)
>   		if (eu_en_fuse & BIT(eu))
>   			eu_en |= BIT(eu * 2) | BIT(eu * 2 + 1);
>   
> -	gen11_compute_sseu_info(sseu, g_dss_en, 0, eu_en);
> +	gen11_compute_sseu_info(sseu, g_dss_en, empty_mask, eu_en);
>   
>   	/* TGL only supports slice-level power gating */
>   	sseu->has_slice_pg = 1;
> @@ -263,7 +293,8 @@ static void gen11_sseu_info_init(struct intel_gt *gt)
>   {
>   	struct sseu_dev_info *sseu = &gt->info.sseu;
>   	struct intel_uncore *uncore = gt->uncore;
> -	u32 ss_en;
> +	intel_sseu_ss_mask_t ss_en = {}, empty_mask = {};
> +	u32 val;
>   	u8 eu_en;
>   	u8 s_en;
>   
> @@ -282,12 +313,13 @@ static void gen11_sseu_info_init(struct intel_gt *gt)
>   		drm_dbg(&gt->i915->drm, "Slice mask %#x is not the expected 0x1!\n",
>   			s_en);
>   
> -	ss_en = ~intel_uncore_read(uncore, GEN11_GT_SUBSLICE_DISABLE);
> +	val = ~intel_uncore_read(uncore, GEN11_GT_SUBSLICE_DISABLE);
> +	bitmap_from_arr32(ss_en.b, &val, 32);
>   
>   	eu_en = ~(intel_uncore_read(uncore, GEN11_EU_DISABLE) &
>   		  GEN11_EU_DIS_MASK);
>   
> -	gen11_compute_sseu_info(sseu, ss_en, 0, eu_en);
> +	gen11_compute_sseu_info(sseu, ss_en, empty_mask, eu_en);
>   
>   	/* ICL has no power gating restrictions. */
>   	sseu->has_slice_pg = 1;
> @@ -328,7 +360,7 @@ static void cherryview_sseu_info_init(struct intel_gt *gt)
>   		sseu_set_eus(sseu, 0, 1, ~disabled_mask);
>   	}
>   
> -	intel_sseu_set_subslices(sseu, 0, sseu->subslice_mask, subslice_mask);
> +	set_subslices(sseu, 0, subslice_mask);
>   
>   	sseu->eu_total = compute_eu_total(sseu);
>   
> @@ -384,8 +416,7 @@ static void gen9_sseu_info_init(struct intel_gt *gt)
>   			/* skip disabled slice */
>   			continue;
>   
> -		intel_sseu_set_subslices(sseu, s, sseu->subslice_mask,
> -					 subslice_mask);
> +		set_subslices(sseu, s, subslice_mask);
>   
>   		eu_disable = intel_uncore_read(uncore, GEN9_EU_DISABLE(s));
>   		for (ss = 0; ss < sseu->max_subslices; ss++) {
> @@ -442,8 +473,8 @@ static void gen9_sseu_info_init(struct intel_gt *gt)
>   	sseu->has_eu_pg = sseu->eu_per_subslice > 2;
>   
>   	if (IS_GEN9_LP(i915)) {
> -#define IS_SS_DISABLED(ss)	(!(sseu->subslice_mask[0] & BIT(ss)))
> -		info->has_pooled_eu = hweight8(sseu->subslice_mask[0]) == 3;
> +#define IS_SS_DISABLED(ss)	test_bit(ss, sseu->subslice_mask.b)
> +		info->has_pooled_eu = hweight8(sseu->subslice_mask.b[0]) == 3;
>   
>   		sseu->min_eu_in_pool = 0;
>   		if (info->has_pooled_eu) {
> @@ -497,8 +528,7 @@ static void bdw_sseu_info_init(struct intel_gt *gt)
>   			/* skip disabled slice */
>   			continue;
>   
> -		intel_sseu_set_subslices(sseu, s, sseu->subslice_mask,
> -					 subslice_mask);
> +		set_subslices(sseu, s, subslice_mask);
>   
>   		for (ss = 0; ss < sseu->max_subslices; ss++) {
>   			u8 eu_disabled_mask;
> @@ -595,8 +625,7 @@ static void hsw_sseu_info_init(struct intel_gt *gt)
>   			    sseu->eu_per_subslice);
>   
>   	for (s = 0; s < sseu->max_slices; s++) {
> -		intel_sseu_set_subslices(sseu, s, sseu->subslice_mask,
> -					 subslice_mask);
> +		set_subslices(sseu, s, subslice_mask);
>   
>   		for (ss = 0; ss < sseu->max_subslices; ss++) {
>   			sseu_set_eus(sseu, s, ss,
> @@ -685,7 +714,7 @@ u32 intel_sseu_make_rpcs(struct intel_gt *gt,
>   	 */
>   	if (GRAPHICS_VER(i915) == 11 &&
>   	    slices == 1 &&
> -	    subslices > min_t(u8, 4, hweight8(sseu->subslice_mask[0]) / 2)) {
> +	    subslices > min_t(u8, 4, hweight8(sseu->subslice_mask.b[0]) / 2)) {
>   		GEM_BUG_ON(subslices & 1);
>   
>   		subslice_pg = false;
> @@ -755,9 +784,11 @@ void intel_sseu_dump(const struct sseu_dev_info *sseu, struct drm_printer *p)
>   		   hweight8(sseu->slice_mask), sseu->slice_mask);
>   	drm_printf(p, "subslice total: %u\n", intel_sseu_subslice_total(sseu));
>   	for (s = 0; s < sseu->max_slices; s++) {
> -		drm_printf(p, "slice%d: %u subslices, mask=%08x\n",
> -			   s, intel_sseu_subslices_per_slice(sseu, s),
> -			   intel_sseu_get_subslices(sseu, s));
> +		intel_sseu_ss_mask_t ssmask = intel_sseu_get_subslices(sseu, s);
> +
> +		drm_printf(p, "slice%d: %u subslices, mask=%*pb\n",
> +			   s, bitmap_weight(ssmask.b, I915_MAX_SS_FUSE_BITS),
> +			   I915_MAX_SS_FUSE_BITS, ssmask.b);
>   	}
>   	drm_printf(p, "EU total: %u\n", sseu->eu_total);
>   	drm_printf(p, "EU per subslice: %u\n", sseu->eu_per_subslice);
> @@ -775,9 +806,11 @@ static void sseu_print_hsw_topology(const struct sseu_dev_info *sseu,
>   	int s, ss;
>   
>   	for (s = 0; s < sseu->max_slices; s++) {
> -		drm_printf(p, "slice%d: %u subslice(s) (0x%08x):\n",
> -			   s, intel_sseu_subslices_per_slice(sseu, s),
> -			   intel_sseu_get_subslices(sseu, s));
> +		intel_sseu_ss_mask_t ssmask = intel_sseu_get_subslices(sseu, s);
> +
> +		drm_printf(p, "slice%d: %u subslice(s) (0x%*pb):\n",
> +			   s, bitmap_weight(ssmask.b, I915_MAX_SS_FUSE_BITS),
> +			   I915_MAX_SS_FUSE_BITS, ssmask.b);
>   
>   		for (ss = 0; ss < sseu->max_subslices; ss++) {
>   			u16 enabled_eus = sseu_get_eus(sseu, s, ss);
> @@ -791,16 +824,14 @@ static void sseu_print_hsw_topology(const struct sseu_dev_info *sseu,
>   static void sseu_print_xehp_topology(const struct sseu_dev_info *sseu,
>   				     struct drm_printer *p)
>   {
> -	u32 g_dss_mask = sseu_get_geometry_subslices(sseu);
> -	u32 c_dss_mask = intel_sseu_get_compute_subslices(sseu);
>   	int dss;
>   
>   	for (dss = 0; dss < sseu->max_subslices; dss++) {
>   		u16 enabled_eus = sseu_get_eus(sseu, 0, dss);
>   
>   		drm_printf(p, "DSS_%02d: G:%3s C:%3s, %2u EUs (0x%04hx)\n", dss,
> -			   str_yes_no(g_dss_mask & BIT(dss)),
> -			   str_yes_no(c_dss_mask & BIT(dss)),
> +			   str_yes_no(test_bit(dss, sseu->geometry_subslice_mask.b)),
> +			   str_yes_no(test_bit(dss, sseu->compute_subslice_mask.b)),
>   			   hweight16(enabled_eus), enabled_eus);
>   	}
>   }
> @@ -818,20 +849,24 @@ void intel_sseu_print_topology(struct drm_i915_private *i915,
>   	}
>   }
>   
> -u16 intel_slicemask_from_dssmask(u64 dss_mask, int dss_per_slice)
> +u16 intel_slicemask_from_dssmask(intel_sseu_ss_mask_t dss_mask,
> +				 int dss_per_slice)
>   {
> +	intel_sseu_ss_mask_t per_slice_mask = {};
>   	u16 slice_mask = 0;
>   	int i;
>   
> -	WARN_ON(sizeof(dss_mask) * 8 / dss_per_slice > 8 * sizeof(slice_mask));
> +	WARN_ON(DIV_ROUND_UP(I915_MAX_SS_FUSE_BITS, dss_per_slice) >
> +		8 * sizeof(slice_mask));
>   
> -	for (i = 0; dss_mask; i++) {
> -		if (dss_mask & GENMASK(dss_per_slice - 1, 0))
> +	bitmap_fill(per_slice_mask.b, dss_per_slice);
> +	for (i = 0; !bitmap_empty(dss_mask.b, I915_MAX_SS_FUSE_BITS); i++) {
> +		if (bitmap_intersects(dss_mask.b, per_slice_mask.b, dss_per_slice))
>   			slice_mask |= BIT(i);
>   
> -		dss_mask >>= dss_per_slice;
> +		bitmap_shift_right(dss_mask.b, dss_mask.b, dss_per_slice,
> +				   I915_MAX_SS_FUSE_BITS);
>   	}
>   
>   	return slice_mask;
>   }
> -
> diff --git a/drivers/gpu/drm/i915/gt/intel_sseu.h b/drivers/gpu/drm/i915/gt/intel_sseu.h
> index 106726a2244e..455f085093ae 100644
> --- a/drivers/gpu/drm/i915/gt/intel_sseu.h
> +++ b/drivers/gpu/drm/i915/gt/intel_sseu.h
> @@ -52,11 +52,22 @@ struct drm_printer;
>   #define GEN_MAX_GSLICES		(GEN_MAX_DSS / GEN_DSS_PER_GSLICE)
>   #define GEN_MAX_CSLICES		(GEN_MAX_DSS / GEN_DSS_PER_CSLICE)
>   
> +/*
> + * Maximum number of 32-bit registers used by hardware to express the
> + * enabled/disabled subslices.
> + */
> +#define I915_MAX_SS_FUSE_REGS	1
> +#define I915_MAX_SS_FUSE_BITS	(I915_MAX_SS_FUSE_REGS * 32)
> +
> +typedef struct {
> +	unsigned long b[BITS_TO_LONGS(I915_MAX_SS_FUSE_BITS)];
> +} intel_sseu_ss_mask_t;
> +
>   struct sseu_dev_info {
>   	u8 slice_mask;
> -	u8 subslice_mask[GEN_SS_MASK_SIZE];
> -	u8 geometry_subslice_mask[GEN_SS_MASK_SIZE];
> -	u8 compute_subslice_mask[GEN_SS_MASK_SIZE];
> +	intel_sseu_ss_mask_t subslice_mask;
> +	intel_sseu_ss_mask_t geometry_subslice_mask;
> +	intel_sseu_ss_mask_t compute_subslice_mask;
>   
>   	/*
>   	 * EU masks.  Use has_common_ss_eumask to determine how the field
> @@ -107,7 +118,7 @@ intel_sseu_from_device_info(const struct sseu_dev_info *sseu)
>   {
>   	struct intel_sseu value = {
>   		.slice_mask = sseu->slice_mask,
> -		.subslice_mask = sseu->subslice_mask[0],
> +		.subslice_mask = sseu->subslice_mask.b[0],
>   		.min_eus_per_subslice = sseu->max_eus_per_subslice,
>   		.max_eus_per_subslice = sseu->max_eus_per_subslice,
>   	};
> @@ -119,18 +130,8 @@ static inline bool
>   intel_sseu_has_subslice(const struct sseu_dev_info *sseu, int slice,
>   			int subslice)
>   {
> -	u8 mask;
> -	int ss_idx = subslice / BITS_PER_BYTE;
> -
> -	if (slice >= sseu->max_slices ||
> -	    subslice >= sseu->max_subslices)
> -		return false;
> -
> -	GEM_BUG_ON(ss_idx >= sseu->ss_stride);
> -
> -	mask = sseu->subslice_mask[slice * sseu->ss_stride + ss_idx];
> -
> -	return mask & BIT(subslice % BITS_PER_BYTE);
> +	return test_bit(slice * sseu->ss_stride + subslice,
> +			sseu->subslice_mask.b);
>   }
>   
>   void intel_sseu_set_info(struct sseu_dev_info *sseu, u8 max_slices,
> @@ -139,15 +140,14 @@ void intel_sseu_set_info(struct sseu_dev_info *sseu, u8 max_slices,
>   unsigned int
>   intel_sseu_subslice_total(const struct sseu_dev_info *sseu);
>   
> -unsigned int
> -intel_sseu_subslices_per_slice(const struct sseu_dev_info *sseu, u8 slice);
> +intel_sseu_ss_mask_t
> +intel_sseu_get_subslices(const struct sseu_dev_info *sseu, u8 slice);
>   
> -u32 intel_sseu_get_subslices(const struct sseu_dev_info *sseu, u8 slice);
> -
> -u32 intel_sseu_get_compute_subslices(const struct sseu_dev_info *sseu);
> +intel_sseu_ss_mask_t
> +intel_sseu_get_compute_subslices(const struct sseu_dev_info *sseu);
>   
>   void intel_sseu_set_subslices(struct sseu_dev_info *sseu, int slice,
> -			      u8 *subslice_mask, u32 ss_mask);
> +			      u32 ss_mask);
>   
>   void intel_sseu_info_init(struct intel_gt *gt);
>   
> @@ -159,9 +159,11 @@ void intel_sseu_print_topology(struct drm_i915_private *i915,
>   			       const struct sseu_dev_info *sseu,
>   			       struct drm_printer *p);
>   
> -u16 intel_slicemask_from_dssmask(u64 dss_mask, int dss_per_slice);
> +u16 intel_slicemask_from_dssmask(intel_sseu_ss_mask_t dss_mask, int dss_per_slice);
>   
>   int intel_sseu_copy_eumask_to_user(void __user *to,
>   				   const struct sseu_dev_info *sseu);
> +int intel_sseu_copy_ssmask_to_user(void __user *to,
> +				   const struct sseu_dev_info *sseu);
>   
>   #endif /* __INTEL_SSEU_H__ */
> diff --git a/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c b/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c
> index 2d5d011e01db..1f77bd52a3a6 100644
> --- a/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c
> +++ b/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c
> @@ -4,6 +4,7 @@
>    * Copyright © 2020 Intel Corporation
>    */
>   
> +#include <linux/bitmap.h>
>   #include <linux/string_helpers.h>
>   
>   #include "i915_drv.h"
> @@ -12,11 +13,15 @@
>   #include "intel_sseu_debugfs.h"
>   
>   static void sseu_copy_subslices(const struct sseu_dev_info *sseu,
> -				int slice, u8 *to_mask)
> +				int slice,
> +				intel_sseu_ss_mask_t *to_mask)
>   {
> -	int offset = slice * sseu->ss_stride;
> +	int offset = slice * sseu->max_subslices;
>   
> -	memcpy(&to_mask[offset], &sseu->subslice_mask[offset], sseu->ss_stride);
> +	bitmap_fill(to_mask->b, sseu->max_subslices);
> +	bitmap_shift_left(to_mask->b, to_mask->b, offset, I915_MAX_SS_FUSE_BITS);
> +	bitmap_and(to_mask->b, to_mask->b, sseu->subslice_mask.b, I915_MAX_SS_FUSE_BITS);
> +	bitmap_shift_right(to_mask->b, to_mask->b, offset, I915_MAX_SS_FUSE_BITS);
>   }
>   
>   static void cherryview_sseu_device_status(struct intel_gt *gt,
> @@ -41,7 +46,7 @@ static void cherryview_sseu_device_status(struct intel_gt *gt,
>   			continue;
>   
>   		sseu->slice_mask = BIT(0);
> -		sseu->subslice_mask[0] |= BIT(ss);
> +		set_bit(0, sseu->subslice_mask.b);
>   		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) +
> @@ -92,7 +97,7 @@ static void gen11_sseu_device_status(struct intel_gt *gt,
>   			continue;
>   
>   		sseu->slice_mask |= BIT(s);
> -		sseu_copy_subslices(&info->sseu, s, sseu->subslice_mask);
> +		sseu_copy_subslices(&info->sseu, s, &sseu->subslice_mask);
>   
>   		for (ss = 0; ss < info->sseu.max_subslices; ss++) {
>   			unsigned int eu_cnt;
> @@ -148,20 +153,17 @@ static void gen9_sseu_device_status(struct intel_gt *gt,
>   
>   		if (IS_GEN9_BC(gt->i915))
>   			sseu_copy_subslices(&info->sseu, s,
> -					    sseu->subslice_mask);
> +					    &sseu->subslice_mask);
>   
>   		for (ss = 0; ss < info->sseu.max_subslices; ss++) {
>   			unsigned int eu_cnt;
> -			u8 ss_idx = s * info->sseu.ss_stride +
> -				    ss / BITS_PER_BYTE;
>   
>   			if (IS_GEN9_LP(gt->i915)) {
>   				if (!(s_reg[s] & (GEN9_PGCTL_SS_ACK(ss))))
>   					/* skip disabled subslice */
>   					continue;
>   
> -				sseu->subslice_mask[ss_idx] |=
> -					BIT(ss % BITS_PER_BYTE);
> +				set_bit(ss, sseu->subslice_mask.b);
>   			}
>   
>   			eu_cnt = eu_reg[2 * s + ss / 2] & eu_mask[ss % 2];
> @@ -189,7 +191,7 @@ static void bdw_sseu_device_status(struct intel_gt *gt,
>   		sseu->eu_per_subslice = info->sseu.eu_per_subslice;
>   		for (s = 0; s < fls(sseu->slice_mask); s++)
>   			sseu_copy_subslices(&info->sseu, s,
> -					    sseu->subslice_mask);
> +					    &sseu->subslice_mask);
>   		sseu->eu_total = sseu->eu_per_subslice *
>   				 intel_sseu_subslice_total(sseu);
>   
> @@ -217,8 +219,10 @@ static void i915_print_sseu_info(struct seq_file *m,
>   	seq_printf(m, "  %s Subslice Total: %u\n", type,
>   		   intel_sseu_subslice_total(sseu));
>   	for (s = 0; s < fls(sseu->slice_mask); s++) {
> +		intel_sseu_ss_mask_t ssmask = intel_sseu_get_subslices(sseu, s);
> +
>   		seq_printf(m, "  %s Slice%i subslices: %u\n", type,
> -			   s, intel_sseu_subslices_per_slice(sseu, s));
> +			   s, bitmap_weight(ssmask.b, I915_MAX_SS_FUSE_BITS));
>   	}
>   	seq_printf(m, "  %s EU Total: %u\n", type,
>   		   sseu->eu_total);
> diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c
> index a05c4b99b3fb..5db492072f99 100644
> --- a/drivers/gpu/drm/i915/gt/intel_workarounds.c
> +++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c
> @@ -931,6 +931,7 @@ static void
>   gen9_wa_init_mcr(struct drm_i915_private *i915, struct i915_wa_list *wal)
>   {
>   	const struct sseu_dev_info *sseu = &to_gt(i915)->info.sseu;
> +	intel_sseu_ss_mask_t ssmask;
>   	unsigned int slice, subslice;
>   	u32 mcr, mcr_mask;
>   
> @@ -948,9 +949,9 @@ gen9_wa_init_mcr(struct drm_i915_private *i915, struct i915_wa_list *wal)
>   	 * on s/ss combo, the read should be done with read_subslice_reg.
>   	 */
>   	slice = ffs(sseu->slice_mask) - 1;
> -	GEM_BUG_ON(slice >= ARRAY_SIZE(sseu->subslice_mask));
> -	subslice = ffs(intel_sseu_get_subslices(sseu, slice));
> -	GEM_BUG_ON(!subslice);
> +	ssmask = intel_sseu_get_subslices(sseu, slice);
> +	subslice = find_first_bit(ssmask.b, I915_MAX_SS_FUSE_BITS);
> +	GEM_BUG_ON(subslice == I915_MAX_SS_FUSE_BITS);
>   	subslice--;
>   
>   	/*
> @@ -1087,11 +1088,10 @@ static void
>   icl_wa_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
>   {
>   	const struct sseu_dev_info *sseu = &gt->info.sseu;
> -	unsigned int slice, subslice;
> +	unsigned int subslice;
>   
>   	GEM_BUG_ON(GRAPHICS_VER(gt->i915) < 11);
>   	GEM_BUG_ON(hweight8(sseu->slice_mask) > 1);
> -	slice = 0;
>   
>   	/*
>   	 * Although a platform may have subslices, we need to always steer
> @@ -1102,7 +1102,7 @@ icl_wa_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
>   	 * one of the higher subslices, we run the risk of reading back 0's or
>   	 * random garbage.
>   	 */
> -	subslice = __ffs(intel_sseu_get_subslices(sseu, slice));
> +	subslice = find_first_bit(sseu->subslice_mask.b, I915_MAX_SS_FUSE_BITS);
>   
>   	/*
>   	 * If the subslice we picked above also steers us to a valid L3 bank,
> @@ -1112,7 +1112,7 @@ icl_wa_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
>   	if (gt->info.l3bank_mask & BIT(subslice))
>   		gt->steering_table[L3BANK] = NULL;
>   
> -	__add_mcr_wa(gt, wal, slice, subslice);
> +	__add_mcr_wa(gt, wal, 0, subslice);
>   }
>   
>   static void
> @@ -1120,7 +1120,6 @@ xehp_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
>   {
>   	const struct sseu_dev_info *sseu = &gt->info.sseu;
>   	unsigned long slice, subslice = 0, slice_mask = 0;
> -	u64 dss_mask = 0;
>   	u32 lncf_mask = 0;
>   	int i;
>   
> @@ -1151,8 +1150,8 @@ xehp_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
>   	 */
>   
>   	/* Find the potential gslice candidates */
> -	dss_mask = intel_sseu_get_subslices(sseu, 0);
> -	slice_mask = intel_slicemask_from_dssmask(dss_mask, GEN_DSS_PER_GSLICE);
> +	slice_mask = intel_slicemask_from_dssmask(sseu->subslice_mask,
> +						  GEN_DSS_PER_GSLICE);
>   
>   	/*
>   	 * Find the potential LNCF candidates.  Either LNCF within a valid
> @@ -1177,9 +1176,9 @@ xehp_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
>   	}
>   
>   	slice = __ffs(slice_mask);
> -	subslice = __ffs(dss_mask >> (slice * GEN_DSS_PER_GSLICE));
> +	subslice = find_next_bit(sseu->subslice_mask.b, I915_MAX_SS_FUSE_BITS,
> +				 slice * GEN_DSS_PER_GSLICE);
>   	WARN_ON(subslice > GEN_DSS_PER_GSLICE);
> -	WARN_ON(dss_mask >> (slice * GEN_DSS_PER_GSLICE) == 0);
>   
>   	__add_mcr_wa(gt, wal, slice, subslice);
>   
> @@ -2012,9 +2011,8 @@ engine_fake_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
>   
>   static bool needs_wa_1308578152(struct intel_engine_cs *engine)
>   {
> -	u64 dss_mask = intel_sseu_get_subslices(&engine->gt->info.sseu, 0);
> -
> -	return (dss_mask & GENMASK(GEN_DSS_PER_GSLICE - 1, 0)) == 0;
> +	return find_first_bit(engine->gt->info.sseu.subslice_mask.b,
> +			      I915_MAX_SS_FUSE_BITS) >= GEN_DSS_PER_GSLICE;
>   }
>   
>   static void
> diff --git a/drivers/gpu/drm/i915/i915_getparam.c b/drivers/gpu/drm/i915/i915_getparam.c
> index ac9767c56619..349d496d164a 100644
> --- a/drivers/gpu/drm/i915/i915_getparam.c
> +++ b/drivers/gpu/drm/i915/i915_getparam.c
> @@ -162,7 +162,7 @@ int i915_getparam_ioctl(struct drm_device *dev, void *data,
>   			return -EINVAL;
>   
>   		/* Only copy bits from the first slice */
> -		memcpy(&value, sseu->subslice_mask,
> +		memcpy(&value, sseu->subslice_mask.b,
>   		       min(sseu->ss_stride, (u8)sizeof(value)));
>   		if (!value)
>   			return -ENODEV;
> diff --git a/drivers/gpu/drm/i915/i915_query.c b/drivers/gpu/drm/i915/i915_query.c
> index 16f43bf32a05..9afa6d1eaf95 100644
> --- a/drivers/gpu/drm/i915/i915_query.c
> +++ b/drivers/gpu/drm/i915/i915_query.c
> @@ -31,7 +31,7 @@ static int copy_query_item(void *query_hdr, size_t query_sz,
>   
>   static int fill_topology_info(const struct sseu_dev_info *sseu,
>   			      struct drm_i915_query_item *query_item,
> -			      const u8 *subslice_mask)
> +			      intel_sseu_ss_mask_t subslice_mask)
>   {
>   	struct drm_i915_query_topology_info topo;
>   	u32 slice_length, subslice_length, eu_length, total_length;
> @@ -71,9 +71,9 @@ static int fill_topology_info(const struct sseu_dev_info *sseu,
>   			 &sseu->slice_mask, slice_length))
>   		return -EFAULT;
>   
> -	if (copy_to_user(u64_to_user_ptr(query_item->data_ptr +
> -					 sizeof(topo) + slice_length),
> -			 subslice_mask, subslice_length))
> +	if (intel_sseu_copy_ssmask_to_user(u64_to_user_ptr(query_item->data_ptr +
> +							   sizeof(topo) + slice_length),
> +					   sseu))
>   		return -EFAULT;
>   
>   	if (intel_sseu_copy_eumask_to_user(u64_to_user_ptr(query_item->data_ptr +

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

* Re: [PATCH 5/5] drm/i915/sseu: Disassociate internal subslice mask representation from uapi
  2022-04-28 12:18     ` [Intel-gfx] " Tvrtko Ursulin
@ 2022-05-06 23:34       ` Matt Roper
  -1 siblings, 0 replies; 27+ messages in thread
From: Matt Roper @ 2022-05-06 23:34 UTC (permalink / raw)
  To: Tvrtko Ursulin; +Cc: intel-gfx, dri-devel

On Thu, Apr 28, 2022 at 01:18:42PM +0100, Tvrtko Ursulin wrote:
> 
> Hi,
> 
> On 28/04/2022 00:07, Matt Roper wrote:
> > Rather than storing subslice masks internally as u8[] (inside the sseu
> > structure) and u32 (everywhere else), let's move over to using an
> > intel_sseu_ss_mask_t typedef compatible with the operations in
> > linux/bitmap.h.  We're soon going to start adding code for a new
> > platform where subslice masks are spread across two 32-bit registers
> > (requiring 64 bits to represent), and we expect future platforms will
> > likely take this even farther, requiring bitmask storage larger than a
> > simple u64 can hold.
> 
> I won't have time to look into this in a detailed way for a few days. Until then a couple questions comments only.
> 
> First, out of curiousity, were you able to end up with less code after your series? With my bitmap conversion I think actually ended up with couple KB smaller text which was a good sign eliminating the internal layout complications was a good approach.

Yeah, looks like I did:

   $ size i915.ko.orig i915.ko
      text    data     bss     dec     hex filename
   3479050  132498    6760 3618308  373604 i915.ko.orig
   3476552  132466    6760 3615778  372c22 i915.ko

> 
> For your series I am not convinced by sseu->has_common_ss_eumask. Why the duality, just to save a few u32 at runtime?

With this flag, eu_mask is an array of GEN_MAX_HSW_SLICES *
GEN_MAX_SS_PER_HSW_SLICE (i.e., 3*6 = 18).  If we store the replicated
EU masks, then we'll have 64 u16's on PVC (where we have a DSS mask
spread across two registers) and 96 u16's on a future platform that
spreads the mask across three fuse registers.  18 -> 96 (or possibly
even more farther in the future).  I think we've eliminated all of the
stack allocations of sseu structures now, so it probably isn't as
important as it used to be though; I can drop it if you think the size
savings aren't worth the extra complexity.

> 
> I am also not convinced with leaving the eu_mask and subslice_mask
> being manually indexed with stride, calculcated by the driver. In my
> approach I simply went with multi-dimensional arrays which I think
> ends up with simpler code.

So something like

        enum {
                u16 hsw[GEN_MAX_HSW_SLICES][GEN_MAX_SS_PER_HSW_SLICE];
                u16 xehp[GEN_MAX_DSS];
        } eu_mask;

?  Or should we just skip the enum and live with allocating three times
as much space as the largest Xe_HP platform needs?

> 
> For all bitmap API call sites and *pb printk format sites, I suggest not hard-coding the widths from SSEU defines by querying the type itsef via wrappers. (See my BITMAP_BITS macro and helpers which wrap it for fields.)
> 
> Ie instead:
> 
> bitmap_shift_left(to_mask->b, to_mask->b, offset, I915_MAX_SS_FUSE_BITS);
> 
> I suggest:
> 
> bitmap_zero(slices.b, BITMAP_BITS(slices.b));
> 
> Also, all accesses to the bitmap type from outside intel_sse*.c|h should use intel_sseu wrappers and not embed knowledge of the typedef (that it has an member named .b etc).
> 
> And finally I would also use the opportunity to clean up the pointless u8 types for counts and such since I think they just result in worse code generation.
> 
> You can of course counter with what you did not like in my attempt. :) I know I did not finish the wrappers and possibly made an overkill by converting the slice mask to bitmap.

These suggestions all make sense.  I'll work on incorporating them into
the next version.


Matt

> 
> Regards,
> 
> Tvrtko
> > Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
> > ---
> >   drivers/gpu/drm/i915/gem/i915_gem_context.c  |   4 +-
> >   drivers/gpu/drm/i915/gt/intel_engine_cs.c    |   2 +-
> >   drivers/gpu/drm/i915/gt/intel_gt.c           |  14 +-
> >   drivers/gpu/drm/i915/gt/intel_sseu.c         | 197 +++++++++++--------
> >   drivers/gpu/drm/i915/gt/intel_sseu.h         |  48 ++---
> >   drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c |  28 +--
> >   drivers/gpu/drm/i915/gt/intel_workarounds.c  |  28 ++-
> >   drivers/gpu/drm/i915/i915_getparam.c         |   2 +-
> >   drivers/gpu/drm/i915/i915_query.c            |   8 +-
> >   9 files changed, 183 insertions(+), 148 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c
> > index ab4c5ab28e4d..ea012ee3a8de 100644
> > --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c
> > +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c
> > @@ -1901,7 +1901,7 @@ i915_gem_user_to_context_sseu(struct intel_gt *gt,
> >   	if (user->slice_mask & ~device->slice_mask)
> >   		return -EINVAL;
> > -	if (user->subslice_mask & ~device->subslice_mask[0])
> > +	if (user->subslice_mask & ~device->subslice_mask.b[0])
> >   		return -EINVAL;
> >   	if (user->max_eus_per_subslice > device->max_eus_per_subslice)
> > @@ -1915,7 +1915,7 @@ i915_gem_user_to_context_sseu(struct intel_gt *gt,
> >   	/* Part specific restrictions. */
> >   	if (GRAPHICS_VER(i915) == 11) {
> >   		unsigned int hw_s = hweight8(device->slice_mask);
> > -		unsigned int hw_ss_per_s = hweight8(device->subslice_mask[0]);
> > +		unsigned int hw_ss_per_s = hweight8(device->subslice_mask.b[0]);
> >   		unsigned int req_s = hweight8(context->slice_mask);
> >   		unsigned int req_ss = hweight8(context->subslice_mask);
> > diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
> > index 14c6ddbbfde8..39c09963b3c7 100644
> > --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c
> > +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
> > @@ -610,7 +610,7 @@ static void engine_mask_apply_compute_fuses(struct intel_gt *gt)
> >   	if (GRAPHICS_VER_FULL(i915) < IP_VER(12, 50))
> >   		return;
> > -	ccs_mask = intel_slicemask_from_dssmask(intel_sseu_get_compute_subslices(&info->sseu),
> > +	ccs_mask = intel_slicemask_from_dssmask(info->sseu.compute_subslice_mask,
> >   						ss_per_ccs);
> >   	/*
> >   	 * If all DSS in a quadrant are fused off, the corresponding CCS
> > diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c
> > index 92394f13b42f..cc03512d59ba 100644
> > --- a/drivers/gpu/drm/i915/gt/intel_gt.c
> > +++ b/drivers/gpu/drm/i915/gt/intel_gt.c
> > @@ -133,13 +133,6 @@ static const struct intel_mmio_range dg2_lncf_steering_table[] = {
> >   	{},
> >   };
> > -static u16 slicemask(struct intel_gt *gt, int count)
> > -{
> > -	u64 dss_mask = intel_sseu_get_subslices(&gt->info.sseu, 0);
> > -
> > -	return intel_slicemask_from_dssmask(dss_mask, count);
> > -}
> > -
> >   int intel_gt_init_mmio(struct intel_gt *gt)
> >   {
> >   	struct drm_i915_private *i915 = gt->i915;
> > @@ -153,11 +146,14 @@ int intel_gt_init_mmio(struct intel_gt *gt)
> >   	 * An mslice is unavailable only if both the meml3 for the slice is
> >   	 * disabled *and* all of the DSS in the slice (quadrant) are disabled.
> >   	 */
> > -	if (HAS_MSLICES(i915))
> > +	if (HAS_MSLICES(i915)) {
> >   		gt->info.mslice_mask =
> > -			slicemask(gt, GEN_DSS_PER_MSLICE) |
> > +			intel_slicemask_from_dssmask(gt->info.sseu.subslice_mask,
> > +						     GEN_DSS_PER_MSLICE);
> > +		gt->info.mslice_mask |=
> >   			(intel_uncore_read(gt->uncore, GEN10_MIRROR_FUSE3) &
> >   			 GEN12_MEML3_EN_MASK);
> > +	}
> >   	if (IS_DG2(i915)) {
> >   		gt->steering_table[MSLICE] = xehpsdv_mslice_steering_table;
> > diff --git a/drivers/gpu/drm/i915/gt/intel_sseu.c b/drivers/gpu/drm/i915/gt/intel_sseu.c
> > index f7ff6a9f67b0..466505d6bd18 100644
> > --- a/drivers/gpu/drm/i915/gt/intel_sseu.c
> > +++ b/drivers/gpu/drm/i915/gt/intel_sseu.c
> > @@ -28,56 +28,49 @@ void intel_sseu_set_info(struct sseu_dev_info *sseu, u8 max_slices,
> >   unsigned int
> >   intel_sseu_subslice_total(const struct sseu_dev_info *sseu)
> >   {
> > -	unsigned int i, total = 0;
> > -
> > -	for (i = 0; i < ARRAY_SIZE(sseu->subslice_mask); i++)
> > -		total += hweight8(sseu->subslice_mask[i]);
> > -
> > -	return total;
> > +	return bitmap_weight(sseu->subslice_mask.b, I915_MAX_SS_FUSE_BITS);
> >   }
> > -static u32
> > -sseu_get_subslices(const struct sseu_dev_info *sseu,
> > -		   const u8 *subslice_mask, u8 slice)
> > +static intel_sseu_ss_mask_t
> > +get_ss_mask_for_slice(const struct sseu_dev_info *sseu,
> > +		      intel_sseu_ss_mask_t all_ss,
> > +		      int slice)
> >   {
> > -	int i, offset = slice * sseu->ss_stride;
> > -	u32 mask = 0;
> > +	intel_sseu_ss_mask_t mask = {}, slice_ss = {};
> > +	int offset = slice * sseu->max_subslices;
> >   	GEM_BUG_ON(slice >= sseu->max_slices);
> > -	for (i = 0; i < sseu->ss_stride; i++)
> > -		mask |= (u32)subslice_mask[offset + i] << i * BITS_PER_BYTE;
> > +	if (sseu->max_slices == 1)
> > +		return all_ss;
> > -	return mask;
> > -}
> > +	bitmap_set(mask.b, offset, sseu->max_subslices);
> > +	bitmap_and(slice_ss.b, all_ss.b, mask.b, I915_MAX_SS_FUSE_BITS);
> > +	bitmap_shift_right(slice_ss.b, slice_ss.b, offset, I915_MAX_SS_FUSE_BITS);
> > -u32 intel_sseu_get_subslices(const struct sseu_dev_info *sseu, u8 slice)
> > -{
> > -	return sseu_get_subslices(sseu, sseu->subslice_mask, slice);
> > +	return slice_ss;
> >   }
> > -static u32 sseu_get_geometry_subslices(const struct sseu_dev_info *sseu)
> > +intel_sseu_ss_mask_t
> > +intel_sseu_get_subslices(const struct sseu_dev_info *sseu, u8 slice)
> >   {
> > -	return sseu_get_subslices(sseu, sseu->geometry_subslice_mask, 0);
> > +	return get_ss_mask_for_slice(sseu, sseu->subslice_mask, slice);
> >   }
> > -u32 intel_sseu_get_compute_subslices(const struct sseu_dev_info *sseu)
> > -{
> > -	return sseu_get_subslices(sseu, sseu->compute_subslice_mask, 0);
> > -}
> > -
> > -void intel_sseu_set_subslices(struct sseu_dev_info *sseu, int slice,
> > -			      u8 *subslice_mask, u32 ss_mask)
> > -{
> > -	int offset = slice * sseu->ss_stride;
> > -
> > -	memcpy(&subslice_mask[offset], &ss_mask, sseu->ss_stride);
> > -}
> > -
> > -unsigned int
> > -intel_sseu_subslices_per_slice(const struct sseu_dev_info *sseu, u8 slice)
> > +/*
> > + * Set the subslice mask associated with a specific slice.  Only needed on
> > + * pre-gen11 platforms that have multiple slices.
> > + */
> > +static void set_subslices(struct sseu_dev_info *sseu, int slice, u32 ss_mask)
> >   {
> > -	return hweight32(intel_sseu_get_subslices(sseu, slice));
> > +	intel_sseu_ss_mask_t mask = {}, newbits = {};
> > +	int offset = slice * sseu->max_subslices;
> > +
> > +	bitmap_set(mask.b, offset, sseu->max_subslices);
> > +	bitmap_from_arr32(newbits.b, &ss_mask, 32);
> > +	bitmap_shift_left(newbits.b, newbits.b, offset, I915_MAX_SS_FUSE_BITS);
> > +	bitmap_replace(sseu->subslice_mask.b, sseu->subslice_mask.b,
> > +		       newbits.b, mask.b, I915_MAX_SS_FUSE_BITS);
> >   }
> >   static int sseu_eu_idx(const struct sseu_dev_info *sseu, int slice,
> > @@ -115,7 +108,7 @@ static u16 compute_eu_total(const struct sseu_dev_info *sseu)
> >   	u16 i, total = 0;
> >   	if (sseu->has_common_ss_eumask)
> > -		return intel_sseu_subslices_per_slice(sseu, 0) *
> > +		return bitmap_weight(sseu->subslice_mask.b, I915_MAX_SS_FUSE_BITS) *
> >   			hweight16(sseu->eu_mask[0]);
> >   	for (i = 0; i < ARRAY_SIZE(sseu->eu_mask); i++)
> > @@ -155,11 +148,42 @@ int intel_sseu_copy_eumask_to_user(void __user *to,
> >   	return copy_to_user(to, eu_mask, len);
> >   }
> > -static void gen11_compute_sseu_info(struct sseu_dev_info *sseu,
> > -				    u32 g_ss_en, u32 c_ss_en, u16 eu_en)
> > +/**
> > + * intel_sseu_copy_ssmask_to_user - Copy subslice mask into a userspace buffer
> > + * @to: Pointer to userspace buffer to copy to
> > + * @sseu: SSEU structure containing subslice mask to copy
> > + *
> > + * Copies the subslice mask to a userspace buffer in the format expected by
> > + * the query ioctl's topology queries.
> > + *
> > + * Returns the result of the copy_to_user() operation.
> > + */
> > +int intel_sseu_copy_ssmask_to_user(void __user *to,
> > +				   const struct sseu_dev_info *sseu)
> >   {
> > -	u32 valid_ss_mask = GENMASK(sseu->max_subslices - 1, 0);
> > +	u8 ss_mask[GEN_SS_MASK_SIZE] = {};
> > +	int len = sseu->max_slices * sseu->ss_stride;
> > +	int s, ss, i;
> > +	for (s = 0; s < sseu->max_slices; s++) {
> > +		for (ss = 0; ss < sseu->max_subslices; ss++) {
> > +			i = s * sseu->ss_stride + ss;
> > +
> > +			if (!intel_sseu_has_subslice(sseu, s, ss))
> > +				continue;
> > +
> > +			ss_mask[i / BITS_PER_BYTE] |= BIT(i % BITS_PER_BYTE);
> > +		}
> > +	}
> > +
> > +	return copy_to_user(to, ss_mask, len);
> > +}
> > +
> > +static void gen11_compute_sseu_info(struct sseu_dev_info *sseu,
> > +				    intel_sseu_ss_mask_t g_ss_en,
> > +				    intel_sseu_ss_mask_t c_ss_en,
> > +				    u16 eu_en)
> > +{
> >   	/* g_ss_en/c_ss_en represent entire subslice mask across all slices */
> >   	GEM_BUG_ON(sseu->max_slices * sseu->max_subslices >
> >   		   sizeof(g_ss_en) * BITS_PER_BYTE);
> > @@ -174,12 +198,12 @@ static void gen11_compute_sseu_info(struct sseu_dev_info *sseu,
> >   	 * enabled subslice count for the purposes of selecting subslices to
> >   	 * use in a particular GEM context.
> >   	 */
> > -	intel_sseu_set_subslices(sseu, 0, sseu->compute_subslice_mask,
> > -				 c_ss_en & valid_ss_mask);
> > -	intel_sseu_set_subslices(sseu, 0, sseu->geometry_subslice_mask,
> > -				 g_ss_en & valid_ss_mask);
> > -	intel_sseu_set_subslices(sseu, 0, sseu->subslice_mask,
> > -				 (g_ss_en | c_ss_en) & valid_ss_mask);
> > +	bitmap_copy(sseu->compute_subslice_mask.b, c_ss_en.b, I915_MAX_SS_FUSE_BITS);
> > +	bitmap_copy(sseu->geometry_subslice_mask.b, g_ss_en.b, I915_MAX_SS_FUSE_BITS);
> > +	bitmap_or(sseu->subslice_mask.b,
> > +		  sseu->compute_subslice_mask.b,
> > +		  sseu->geometry_subslice_mask.b,
> > +		  I915_MAX_SS_FUSE_BITS);
> >   	sseu->has_common_ss_eumask = 1;
> >   	sseu->eu_mask[0] = eu_en;
> > @@ -191,7 +215,8 @@ static void xehp_sseu_info_init(struct intel_gt *gt)
> >   {
> >   	struct sseu_dev_info *sseu = &gt->info.sseu;
> >   	struct intel_uncore *uncore = gt->uncore;
> > -	u32 g_dss_en, c_dss_en = 0;
> > +	intel_sseu_ss_mask_t g_dss_en = {}, c_dss_en = {};
> > +	u32 val;
> >   	u16 eu_en = 0;
> >   	u8 eu_en_fuse;
> >   	int eu;
> > @@ -204,8 +229,11 @@ static void xehp_sseu_info_init(struct intel_gt *gt)
> >   	 */
> >   	intel_sseu_set_info(sseu, 1, 32, 16);
> > -	g_dss_en = intel_uncore_read(uncore, GEN12_GT_GEOMETRY_DSS_ENABLE);
> > -	c_dss_en = intel_uncore_read(uncore, GEN12_GT_COMPUTE_DSS_ENABLE);
> > +	val = intel_uncore_read(uncore, GEN12_GT_GEOMETRY_DSS_ENABLE);
> > +	bitmap_from_arr32(g_dss_en.b, &val, 32);
> > +
> > +	val = intel_uncore_read(uncore, GEN12_GT_COMPUTE_DSS_ENABLE);
> > +	bitmap_from_arr32(c_dss_en.b, &val, 32);
> >   	eu_en_fuse = intel_uncore_read(uncore, XEHP_EU_ENABLE) & XEHP_EU_ENA_MASK;
> > @@ -220,7 +248,8 @@ static void gen12_sseu_info_init(struct intel_gt *gt)
> >   {
> >   	struct sseu_dev_info *sseu = &gt->info.sseu;
> >   	struct intel_uncore *uncore = gt->uncore;
> > -	u32 g_dss_en;
> > +	intel_sseu_ss_mask_t g_dss_en = {}, empty_mask = {};
> > +	u32 val;
> >   	u16 eu_en = 0;
> >   	u8 eu_en_fuse;
> >   	u8 s_en;
> > @@ -243,7 +272,8 @@ static void gen12_sseu_info_init(struct intel_gt *gt)
> >   		drm_dbg(&gt->i915->drm, "Slice mask %#x is not the expected 0x1!\n",
> >   			s_en);
> > -	g_dss_en = intel_uncore_read(uncore, GEN12_GT_GEOMETRY_DSS_ENABLE);
> > +	val = intel_uncore_read(uncore, GEN12_GT_GEOMETRY_DSS_ENABLE);
> > +	bitmap_from_arr32(g_dss_en.b, &val, 32);
> >   	/* one bit per pair of EUs */
> >   	eu_en_fuse = ~(intel_uncore_read(uncore, GEN11_EU_DISABLE) &
> > @@ -253,7 +283,7 @@ static void gen12_sseu_info_init(struct intel_gt *gt)
> >   		if (eu_en_fuse & BIT(eu))
> >   			eu_en |= BIT(eu * 2) | BIT(eu * 2 + 1);
> > -	gen11_compute_sseu_info(sseu, g_dss_en, 0, eu_en);
> > +	gen11_compute_sseu_info(sseu, g_dss_en, empty_mask, eu_en);
> >   	/* TGL only supports slice-level power gating */
> >   	sseu->has_slice_pg = 1;
> > @@ -263,7 +293,8 @@ static void gen11_sseu_info_init(struct intel_gt *gt)
> >   {
> >   	struct sseu_dev_info *sseu = &gt->info.sseu;
> >   	struct intel_uncore *uncore = gt->uncore;
> > -	u32 ss_en;
> > +	intel_sseu_ss_mask_t ss_en = {}, empty_mask = {};
> > +	u32 val;
> >   	u8 eu_en;
> >   	u8 s_en;
> > @@ -282,12 +313,13 @@ static void gen11_sseu_info_init(struct intel_gt *gt)
> >   		drm_dbg(&gt->i915->drm, "Slice mask %#x is not the expected 0x1!\n",
> >   			s_en);
> > -	ss_en = ~intel_uncore_read(uncore, GEN11_GT_SUBSLICE_DISABLE);
> > +	val = ~intel_uncore_read(uncore, GEN11_GT_SUBSLICE_DISABLE);
> > +	bitmap_from_arr32(ss_en.b, &val, 32);
> >   	eu_en = ~(intel_uncore_read(uncore, GEN11_EU_DISABLE) &
> >   		  GEN11_EU_DIS_MASK);
> > -	gen11_compute_sseu_info(sseu, ss_en, 0, eu_en);
> > +	gen11_compute_sseu_info(sseu, ss_en, empty_mask, eu_en);
> >   	/* ICL has no power gating restrictions. */
> >   	sseu->has_slice_pg = 1;
> > @@ -328,7 +360,7 @@ static void cherryview_sseu_info_init(struct intel_gt *gt)
> >   		sseu_set_eus(sseu, 0, 1, ~disabled_mask);
> >   	}
> > -	intel_sseu_set_subslices(sseu, 0, sseu->subslice_mask, subslice_mask);
> > +	set_subslices(sseu, 0, subslice_mask);
> >   	sseu->eu_total = compute_eu_total(sseu);
> > @@ -384,8 +416,7 @@ static void gen9_sseu_info_init(struct intel_gt *gt)
> >   			/* skip disabled slice */
> >   			continue;
> > -		intel_sseu_set_subslices(sseu, s, sseu->subslice_mask,
> > -					 subslice_mask);
> > +		set_subslices(sseu, s, subslice_mask);
> >   		eu_disable = intel_uncore_read(uncore, GEN9_EU_DISABLE(s));
> >   		for (ss = 0; ss < sseu->max_subslices; ss++) {
> > @@ -442,8 +473,8 @@ static void gen9_sseu_info_init(struct intel_gt *gt)
> >   	sseu->has_eu_pg = sseu->eu_per_subslice > 2;
> >   	if (IS_GEN9_LP(i915)) {
> > -#define IS_SS_DISABLED(ss)	(!(sseu->subslice_mask[0] & BIT(ss)))
> > -		info->has_pooled_eu = hweight8(sseu->subslice_mask[0]) == 3;
> > +#define IS_SS_DISABLED(ss)	test_bit(ss, sseu->subslice_mask.b)
> > +		info->has_pooled_eu = hweight8(sseu->subslice_mask.b[0]) == 3;
> >   		sseu->min_eu_in_pool = 0;
> >   		if (info->has_pooled_eu) {
> > @@ -497,8 +528,7 @@ static void bdw_sseu_info_init(struct intel_gt *gt)
> >   			/* skip disabled slice */
> >   			continue;
> > -		intel_sseu_set_subslices(sseu, s, sseu->subslice_mask,
> > -					 subslice_mask);
> > +		set_subslices(sseu, s, subslice_mask);
> >   		for (ss = 0; ss < sseu->max_subslices; ss++) {
> >   			u8 eu_disabled_mask;
> > @@ -595,8 +625,7 @@ static void hsw_sseu_info_init(struct intel_gt *gt)
> >   			    sseu->eu_per_subslice);
> >   	for (s = 0; s < sseu->max_slices; s++) {
> > -		intel_sseu_set_subslices(sseu, s, sseu->subslice_mask,
> > -					 subslice_mask);
> > +		set_subslices(sseu, s, subslice_mask);
> >   		for (ss = 0; ss < sseu->max_subslices; ss++) {
> >   			sseu_set_eus(sseu, s, ss,
> > @@ -685,7 +714,7 @@ u32 intel_sseu_make_rpcs(struct intel_gt *gt,
> >   	 */
> >   	if (GRAPHICS_VER(i915) == 11 &&
> >   	    slices == 1 &&
> > -	    subslices > min_t(u8, 4, hweight8(sseu->subslice_mask[0]) / 2)) {
> > +	    subslices > min_t(u8, 4, hweight8(sseu->subslice_mask.b[0]) / 2)) {
> >   		GEM_BUG_ON(subslices & 1);
> >   		subslice_pg = false;
> > @@ -755,9 +784,11 @@ void intel_sseu_dump(const struct sseu_dev_info *sseu, struct drm_printer *p)
> >   		   hweight8(sseu->slice_mask), sseu->slice_mask);
> >   	drm_printf(p, "subslice total: %u\n", intel_sseu_subslice_total(sseu));
> >   	for (s = 0; s < sseu->max_slices; s++) {
> > -		drm_printf(p, "slice%d: %u subslices, mask=%08x\n",
> > -			   s, intel_sseu_subslices_per_slice(sseu, s),
> > -			   intel_sseu_get_subslices(sseu, s));
> > +		intel_sseu_ss_mask_t ssmask = intel_sseu_get_subslices(sseu, s);
> > +
> > +		drm_printf(p, "slice%d: %u subslices, mask=%*pb\n",
> > +			   s, bitmap_weight(ssmask.b, I915_MAX_SS_FUSE_BITS),
> > +			   I915_MAX_SS_FUSE_BITS, ssmask.b);
> >   	}
> >   	drm_printf(p, "EU total: %u\n", sseu->eu_total);
> >   	drm_printf(p, "EU per subslice: %u\n", sseu->eu_per_subslice);
> > @@ -775,9 +806,11 @@ static void sseu_print_hsw_topology(const struct sseu_dev_info *sseu,
> >   	int s, ss;
> >   	for (s = 0; s < sseu->max_slices; s++) {
> > -		drm_printf(p, "slice%d: %u subslice(s) (0x%08x):\n",
> > -			   s, intel_sseu_subslices_per_slice(sseu, s),
> > -			   intel_sseu_get_subslices(sseu, s));
> > +		intel_sseu_ss_mask_t ssmask = intel_sseu_get_subslices(sseu, s);
> > +
> > +		drm_printf(p, "slice%d: %u subslice(s) (0x%*pb):\n",
> > +			   s, bitmap_weight(ssmask.b, I915_MAX_SS_FUSE_BITS),
> > +			   I915_MAX_SS_FUSE_BITS, ssmask.b);
> >   		for (ss = 0; ss < sseu->max_subslices; ss++) {
> >   			u16 enabled_eus = sseu_get_eus(sseu, s, ss);
> > @@ -791,16 +824,14 @@ static void sseu_print_hsw_topology(const struct sseu_dev_info *sseu,
> >   static void sseu_print_xehp_topology(const struct sseu_dev_info *sseu,
> >   				     struct drm_printer *p)
> >   {
> > -	u32 g_dss_mask = sseu_get_geometry_subslices(sseu);
> > -	u32 c_dss_mask = intel_sseu_get_compute_subslices(sseu);
> >   	int dss;
> >   	for (dss = 0; dss < sseu->max_subslices; dss++) {
> >   		u16 enabled_eus = sseu_get_eus(sseu, 0, dss);
> >   		drm_printf(p, "DSS_%02d: G:%3s C:%3s, %2u EUs (0x%04hx)\n", dss,
> > -			   str_yes_no(g_dss_mask & BIT(dss)),
> > -			   str_yes_no(c_dss_mask & BIT(dss)),
> > +			   str_yes_no(test_bit(dss, sseu->geometry_subslice_mask.b)),
> > +			   str_yes_no(test_bit(dss, sseu->compute_subslice_mask.b)),
> >   			   hweight16(enabled_eus), enabled_eus);
> >   	}
> >   }
> > @@ -818,20 +849,24 @@ void intel_sseu_print_topology(struct drm_i915_private *i915,
> >   	}
> >   }
> > -u16 intel_slicemask_from_dssmask(u64 dss_mask, int dss_per_slice)
> > +u16 intel_slicemask_from_dssmask(intel_sseu_ss_mask_t dss_mask,
> > +				 int dss_per_slice)
> >   {
> > +	intel_sseu_ss_mask_t per_slice_mask = {};
> >   	u16 slice_mask = 0;
> >   	int i;
> > -	WARN_ON(sizeof(dss_mask) * 8 / dss_per_slice > 8 * sizeof(slice_mask));
> > +	WARN_ON(DIV_ROUND_UP(I915_MAX_SS_FUSE_BITS, dss_per_slice) >
> > +		8 * sizeof(slice_mask));
> > -	for (i = 0; dss_mask; i++) {
> > -		if (dss_mask & GENMASK(dss_per_slice - 1, 0))
> > +	bitmap_fill(per_slice_mask.b, dss_per_slice);
> > +	for (i = 0; !bitmap_empty(dss_mask.b, I915_MAX_SS_FUSE_BITS); i++) {
> > +		if (bitmap_intersects(dss_mask.b, per_slice_mask.b, dss_per_slice))
> >   			slice_mask |= BIT(i);
> > -		dss_mask >>= dss_per_slice;
> > +		bitmap_shift_right(dss_mask.b, dss_mask.b, dss_per_slice,
> > +				   I915_MAX_SS_FUSE_BITS);
> >   	}
> >   	return slice_mask;
> >   }
> > -
> > diff --git a/drivers/gpu/drm/i915/gt/intel_sseu.h b/drivers/gpu/drm/i915/gt/intel_sseu.h
> > index 106726a2244e..455f085093ae 100644
> > --- a/drivers/gpu/drm/i915/gt/intel_sseu.h
> > +++ b/drivers/gpu/drm/i915/gt/intel_sseu.h
> > @@ -52,11 +52,22 @@ struct drm_printer;
> >   #define GEN_MAX_GSLICES		(GEN_MAX_DSS / GEN_DSS_PER_GSLICE)
> >   #define GEN_MAX_CSLICES		(GEN_MAX_DSS / GEN_DSS_PER_CSLICE)
> > +/*
> > + * Maximum number of 32-bit registers used by hardware to express the
> > + * enabled/disabled subslices.
> > + */
> > +#define I915_MAX_SS_FUSE_REGS	1
> > +#define I915_MAX_SS_FUSE_BITS	(I915_MAX_SS_FUSE_REGS * 32)
> > +
> > +typedef struct {
> > +	unsigned long b[BITS_TO_LONGS(I915_MAX_SS_FUSE_BITS)];
> > +} intel_sseu_ss_mask_t;
> > +
> >   struct sseu_dev_info {
> >   	u8 slice_mask;
> > -	u8 subslice_mask[GEN_SS_MASK_SIZE];
> > -	u8 geometry_subslice_mask[GEN_SS_MASK_SIZE];
> > -	u8 compute_subslice_mask[GEN_SS_MASK_SIZE];
> > +	intel_sseu_ss_mask_t subslice_mask;
> > +	intel_sseu_ss_mask_t geometry_subslice_mask;
> > +	intel_sseu_ss_mask_t compute_subslice_mask;
> >   	/*
> >   	 * EU masks.  Use has_common_ss_eumask to determine how the field
> > @@ -107,7 +118,7 @@ intel_sseu_from_device_info(const struct sseu_dev_info *sseu)
> >   {
> >   	struct intel_sseu value = {
> >   		.slice_mask = sseu->slice_mask,
> > -		.subslice_mask = sseu->subslice_mask[0],
> > +		.subslice_mask = sseu->subslice_mask.b[0],
> >   		.min_eus_per_subslice = sseu->max_eus_per_subslice,
> >   		.max_eus_per_subslice = sseu->max_eus_per_subslice,
> >   	};
> > @@ -119,18 +130,8 @@ static inline bool
> >   intel_sseu_has_subslice(const struct sseu_dev_info *sseu, int slice,
> >   			int subslice)
> >   {
> > -	u8 mask;
> > -	int ss_idx = subslice / BITS_PER_BYTE;
> > -
> > -	if (slice >= sseu->max_slices ||
> > -	    subslice >= sseu->max_subslices)
> > -		return false;
> > -
> > -	GEM_BUG_ON(ss_idx >= sseu->ss_stride);
> > -
> > -	mask = sseu->subslice_mask[slice * sseu->ss_stride + ss_idx];
> > -
> > -	return mask & BIT(subslice % BITS_PER_BYTE);
> > +	return test_bit(slice * sseu->ss_stride + subslice,
> > +			sseu->subslice_mask.b);
> >   }
> >   void intel_sseu_set_info(struct sseu_dev_info *sseu, u8 max_slices,
> > @@ -139,15 +140,14 @@ void intel_sseu_set_info(struct sseu_dev_info *sseu, u8 max_slices,
> >   unsigned int
> >   intel_sseu_subslice_total(const struct sseu_dev_info *sseu);
> > -unsigned int
> > -intel_sseu_subslices_per_slice(const struct sseu_dev_info *sseu, u8 slice);
> > +intel_sseu_ss_mask_t
> > +intel_sseu_get_subslices(const struct sseu_dev_info *sseu, u8 slice);
> > -u32 intel_sseu_get_subslices(const struct sseu_dev_info *sseu, u8 slice);
> > -
> > -u32 intel_sseu_get_compute_subslices(const struct sseu_dev_info *sseu);
> > +intel_sseu_ss_mask_t
> > +intel_sseu_get_compute_subslices(const struct sseu_dev_info *sseu);
> >   void intel_sseu_set_subslices(struct sseu_dev_info *sseu, int slice,
> > -			      u8 *subslice_mask, u32 ss_mask);
> > +			      u32 ss_mask);
> >   void intel_sseu_info_init(struct intel_gt *gt);
> > @@ -159,9 +159,11 @@ void intel_sseu_print_topology(struct drm_i915_private *i915,
> >   			       const struct sseu_dev_info *sseu,
> >   			       struct drm_printer *p);
> > -u16 intel_slicemask_from_dssmask(u64 dss_mask, int dss_per_slice);
> > +u16 intel_slicemask_from_dssmask(intel_sseu_ss_mask_t dss_mask, int dss_per_slice);
> >   int intel_sseu_copy_eumask_to_user(void __user *to,
> >   				   const struct sseu_dev_info *sseu);
> > +int intel_sseu_copy_ssmask_to_user(void __user *to,
> > +				   const struct sseu_dev_info *sseu);
> >   #endif /* __INTEL_SSEU_H__ */
> > diff --git a/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c b/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c
> > index 2d5d011e01db..1f77bd52a3a6 100644
> > --- a/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c
> > +++ b/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c
> > @@ -4,6 +4,7 @@
> >    * Copyright © 2020 Intel Corporation
> >    */
> > +#include <linux/bitmap.h>
> >   #include <linux/string_helpers.h>
> >   #include "i915_drv.h"
> > @@ -12,11 +13,15 @@
> >   #include "intel_sseu_debugfs.h"
> >   static void sseu_copy_subslices(const struct sseu_dev_info *sseu,
> > -				int slice, u8 *to_mask)
> > +				int slice,
> > +				intel_sseu_ss_mask_t *to_mask)
> >   {
> > -	int offset = slice * sseu->ss_stride;
> > +	int offset = slice * sseu->max_subslices;
> > -	memcpy(&to_mask[offset], &sseu->subslice_mask[offset], sseu->ss_stride);
> > +	bitmap_fill(to_mask->b, sseu->max_subslices);
> > +	bitmap_shift_left(to_mask->b, to_mask->b, offset, I915_MAX_SS_FUSE_BITS);
> > +	bitmap_and(to_mask->b, to_mask->b, sseu->subslice_mask.b, I915_MAX_SS_FUSE_BITS);
> > +	bitmap_shift_right(to_mask->b, to_mask->b, offset, I915_MAX_SS_FUSE_BITS);
> >   }
> >   static void cherryview_sseu_device_status(struct intel_gt *gt,
> > @@ -41,7 +46,7 @@ static void cherryview_sseu_device_status(struct intel_gt *gt,
> >   			continue;
> >   		sseu->slice_mask = BIT(0);
> > -		sseu->subslice_mask[0] |= BIT(ss);
> > +		set_bit(0, sseu->subslice_mask.b);
> >   		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) +
> > @@ -92,7 +97,7 @@ static void gen11_sseu_device_status(struct intel_gt *gt,
> >   			continue;
> >   		sseu->slice_mask |= BIT(s);
> > -		sseu_copy_subslices(&info->sseu, s, sseu->subslice_mask);
> > +		sseu_copy_subslices(&info->sseu, s, &sseu->subslice_mask);
> >   		for (ss = 0; ss < info->sseu.max_subslices; ss++) {
> >   			unsigned int eu_cnt;
> > @@ -148,20 +153,17 @@ static void gen9_sseu_device_status(struct intel_gt *gt,
> >   		if (IS_GEN9_BC(gt->i915))
> >   			sseu_copy_subslices(&info->sseu, s,
> > -					    sseu->subslice_mask);
> > +					    &sseu->subslice_mask);
> >   		for (ss = 0; ss < info->sseu.max_subslices; ss++) {
> >   			unsigned int eu_cnt;
> > -			u8 ss_idx = s * info->sseu.ss_stride +
> > -				    ss / BITS_PER_BYTE;
> >   			if (IS_GEN9_LP(gt->i915)) {
> >   				if (!(s_reg[s] & (GEN9_PGCTL_SS_ACK(ss))))
> >   					/* skip disabled subslice */
> >   					continue;
> > -				sseu->subslice_mask[ss_idx] |=
> > -					BIT(ss % BITS_PER_BYTE);
> > +				set_bit(ss, sseu->subslice_mask.b);
> >   			}
> >   			eu_cnt = eu_reg[2 * s + ss / 2] & eu_mask[ss % 2];
> > @@ -189,7 +191,7 @@ static void bdw_sseu_device_status(struct intel_gt *gt,
> >   		sseu->eu_per_subslice = info->sseu.eu_per_subslice;
> >   		for (s = 0; s < fls(sseu->slice_mask); s++)
> >   			sseu_copy_subslices(&info->sseu, s,
> > -					    sseu->subslice_mask);
> > +					    &sseu->subslice_mask);
> >   		sseu->eu_total = sseu->eu_per_subslice *
> >   				 intel_sseu_subslice_total(sseu);
> > @@ -217,8 +219,10 @@ static void i915_print_sseu_info(struct seq_file *m,
> >   	seq_printf(m, "  %s Subslice Total: %u\n", type,
> >   		   intel_sseu_subslice_total(sseu));
> >   	for (s = 0; s < fls(sseu->slice_mask); s++) {
> > +		intel_sseu_ss_mask_t ssmask = intel_sseu_get_subslices(sseu, s);
> > +
> >   		seq_printf(m, "  %s Slice%i subslices: %u\n", type,
> > -			   s, intel_sseu_subslices_per_slice(sseu, s));
> > +			   s, bitmap_weight(ssmask.b, I915_MAX_SS_FUSE_BITS));
> >   	}
> >   	seq_printf(m, "  %s EU Total: %u\n", type,
> >   		   sseu->eu_total);
> > diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c
> > index a05c4b99b3fb..5db492072f99 100644
> > --- a/drivers/gpu/drm/i915/gt/intel_workarounds.c
> > +++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c
> > @@ -931,6 +931,7 @@ static void
> >   gen9_wa_init_mcr(struct drm_i915_private *i915, struct i915_wa_list *wal)
> >   {
> >   	const struct sseu_dev_info *sseu = &to_gt(i915)->info.sseu;
> > +	intel_sseu_ss_mask_t ssmask;
> >   	unsigned int slice, subslice;
> >   	u32 mcr, mcr_mask;
> > @@ -948,9 +949,9 @@ gen9_wa_init_mcr(struct drm_i915_private *i915, struct i915_wa_list *wal)
> >   	 * on s/ss combo, the read should be done with read_subslice_reg.
> >   	 */
> >   	slice = ffs(sseu->slice_mask) - 1;
> > -	GEM_BUG_ON(slice >= ARRAY_SIZE(sseu->subslice_mask));
> > -	subslice = ffs(intel_sseu_get_subslices(sseu, slice));
> > -	GEM_BUG_ON(!subslice);
> > +	ssmask = intel_sseu_get_subslices(sseu, slice);
> > +	subslice = find_first_bit(ssmask.b, I915_MAX_SS_FUSE_BITS);
> > +	GEM_BUG_ON(subslice == I915_MAX_SS_FUSE_BITS);
> >   	subslice--;
> >   	/*
> > @@ -1087,11 +1088,10 @@ static void
> >   icl_wa_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
> >   {
> >   	const struct sseu_dev_info *sseu = &gt->info.sseu;
> > -	unsigned int slice, subslice;
> > +	unsigned int subslice;
> >   	GEM_BUG_ON(GRAPHICS_VER(gt->i915) < 11);
> >   	GEM_BUG_ON(hweight8(sseu->slice_mask) > 1);
> > -	slice = 0;
> >   	/*
> >   	 * Although a platform may have subslices, we need to always steer
> > @@ -1102,7 +1102,7 @@ icl_wa_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
> >   	 * one of the higher subslices, we run the risk of reading back 0's or
> >   	 * random garbage.
> >   	 */
> > -	subslice = __ffs(intel_sseu_get_subslices(sseu, slice));
> > +	subslice = find_first_bit(sseu->subslice_mask.b, I915_MAX_SS_FUSE_BITS);
> >   	/*
> >   	 * If the subslice we picked above also steers us to a valid L3 bank,
> > @@ -1112,7 +1112,7 @@ icl_wa_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
> >   	if (gt->info.l3bank_mask & BIT(subslice))
> >   		gt->steering_table[L3BANK] = NULL;
> > -	__add_mcr_wa(gt, wal, slice, subslice);
> > +	__add_mcr_wa(gt, wal, 0, subslice);
> >   }
> >   static void
> > @@ -1120,7 +1120,6 @@ xehp_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
> >   {
> >   	const struct sseu_dev_info *sseu = &gt->info.sseu;
> >   	unsigned long slice, subslice = 0, slice_mask = 0;
> > -	u64 dss_mask = 0;
> >   	u32 lncf_mask = 0;
> >   	int i;
> > @@ -1151,8 +1150,8 @@ xehp_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
> >   	 */
> >   	/* Find the potential gslice candidates */
> > -	dss_mask = intel_sseu_get_subslices(sseu, 0);
> > -	slice_mask = intel_slicemask_from_dssmask(dss_mask, GEN_DSS_PER_GSLICE);
> > +	slice_mask = intel_slicemask_from_dssmask(sseu->subslice_mask,
> > +						  GEN_DSS_PER_GSLICE);
> >   	/*
> >   	 * Find the potential LNCF candidates.  Either LNCF within a valid
> > @@ -1177,9 +1176,9 @@ xehp_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
> >   	}
> >   	slice = __ffs(slice_mask);
> > -	subslice = __ffs(dss_mask >> (slice * GEN_DSS_PER_GSLICE));
> > +	subslice = find_next_bit(sseu->subslice_mask.b, I915_MAX_SS_FUSE_BITS,
> > +				 slice * GEN_DSS_PER_GSLICE);
> >   	WARN_ON(subslice > GEN_DSS_PER_GSLICE);
> > -	WARN_ON(dss_mask >> (slice * GEN_DSS_PER_GSLICE) == 0);
> >   	__add_mcr_wa(gt, wal, slice, subslice);
> > @@ -2012,9 +2011,8 @@ engine_fake_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
> >   static bool needs_wa_1308578152(struct intel_engine_cs *engine)
> >   {
> > -	u64 dss_mask = intel_sseu_get_subslices(&engine->gt->info.sseu, 0);
> > -
> > -	return (dss_mask & GENMASK(GEN_DSS_PER_GSLICE - 1, 0)) == 0;
> > +	return find_first_bit(engine->gt->info.sseu.subslice_mask.b,
> > +			      I915_MAX_SS_FUSE_BITS) >= GEN_DSS_PER_GSLICE;
> >   }
> >   static void
> > diff --git a/drivers/gpu/drm/i915/i915_getparam.c b/drivers/gpu/drm/i915/i915_getparam.c
> > index ac9767c56619..349d496d164a 100644
> > --- a/drivers/gpu/drm/i915/i915_getparam.c
> > +++ b/drivers/gpu/drm/i915/i915_getparam.c
> > @@ -162,7 +162,7 @@ int i915_getparam_ioctl(struct drm_device *dev, void *data,
> >   			return -EINVAL;
> >   		/* Only copy bits from the first slice */
> > -		memcpy(&value, sseu->subslice_mask,
> > +		memcpy(&value, sseu->subslice_mask.b,
> >   		       min(sseu->ss_stride, (u8)sizeof(value)));
> >   		if (!value)
> >   			return -ENODEV;
> > diff --git a/drivers/gpu/drm/i915/i915_query.c b/drivers/gpu/drm/i915/i915_query.c
> > index 16f43bf32a05..9afa6d1eaf95 100644
> > --- a/drivers/gpu/drm/i915/i915_query.c
> > +++ b/drivers/gpu/drm/i915/i915_query.c
> > @@ -31,7 +31,7 @@ static int copy_query_item(void *query_hdr, size_t query_sz,
> >   static int fill_topology_info(const struct sseu_dev_info *sseu,
> >   			      struct drm_i915_query_item *query_item,
> > -			      const u8 *subslice_mask)
> > +			      intel_sseu_ss_mask_t subslice_mask)
> >   {
> >   	struct drm_i915_query_topology_info topo;
> >   	u32 slice_length, subslice_length, eu_length, total_length;
> > @@ -71,9 +71,9 @@ static int fill_topology_info(const struct sseu_dev_info *sseu,
> >   			 &sseu->slice_mask, slice_length))
> >   		return -EFAULT;
> > -	if (copy_to_user(u64_to_user_ptr(query_item->data_ptr +
> > -					 sizeof(topo) + slice_length),
> > -			 subslice_mask, subslice_length))
> > +	if (intel_sseu_copy_ssmask_to_user(u64_to_user_ptr(query_item->data_ptr +
> > +							   sizeof(topo) + slice_length),
> > +					   sseu))
> >   		return -EFAULT;
> >   	if (intel_sseu_copy_eumask_to_user(u64_to_user_ptr(query_item->data_ptr +

-- 
Matt Roper
Graphics Software Engineer
VTT-OSGC Platform Enablement
Intel Corporation
(916) 356-2795

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

* Re: [Intel-gfx] [PATCH 5/5] drm/i915/sseu: Disassociate internal subslice mask representation from uapi
@ 2022-05-06 23:34       ` Matt Roper
  0 siblings, 0 replies; 27+ messages in thread
From: Matt Roper @ 2022-05-06 23:34 UTC (permalink / raw)
  To: Tvrtko Ursulin; +Cc: intel-gfx, dri-devel

On Thu, Apr 28, 2022 at 01:18:42PM +0100, Tvrtko Ursulin wrote:
> 
> Hi,
> 
> On 28/04/2022 00:07, Matt Roper wrote:
> > Rather than storing subslice masks internally as u8[] (inside the sseu
> > structure) and u32 (everywhere else), let's move over to using an
> > intel_sseu_ss_mask_t typedef compatible with the operations in
> > linux/bitmap.h.  We're soon going to start adding code for a new
> > platform where subslice masks are spread across two 32-bit registers
> > (requiring 64 bits to represent), and we expect future platforms will
> > likely take this even farther, requiring bitmask storage larger than a
> > simple u64 can hold.
> 
> I won't have time to look into this in a detailed way for a few days. Until then a couple questions comments only.
> 
> First, out of curiousity, were you able to end up with less code after your series? With my bitmap conversion I think actually ended up with couple KB smaller text which was a good sign eliminating the internal layout complications was a good approach.

Yeah, looks like I did:

   $ size i915.ko.orig i915.ko
      text    data     bss     dec     hex filename
   3479050  132498    6760 3618308  373604 i915.ko.orig
   3476552  132466    6760 3615778  372c22 i915.ko

> 
> For your series I am not convinced by sseu->has_common_ss_eumask. Why the duality, just to save a few u32 at runtime?

With this flag, eu_mask is an array of GEN_MAX_HSW_SLICES *
GEN_MAX_SS_PER_HSW_SLICE (i.e., 3*6 = 18).  If we store the replicated
EU masks, then we'll have 64 u16's on PVC (where we have a DSS mask
spread across two registers) and 96 u16's on a future platform that
spreads the mask across three fuse registers.  18 -> 96 (or possibly
even more farther in the future).  I think we've eliminated all of the
stack allocations of sseu structures now, so it probably isn't as
important as it used to be though; I can drop it if you think the size
savings aren't worth the extra complexity.

> 
> I am also not convinced with leaving the eu_mask and subslice_mask
> being manually indexed with stride, calculcated by the driver. In my
> approach I simply went with multi-dimensional arrays which I think
> ends up with simpler code.

So something like

        enum {
                u16 hsw[GEN_MAX_HSW_SLICES][GEN_MAX_SS_PER_HSW_SLICE];
                u16 xehp[GEN_MAX_DSS];
        } eu_mask;

?  Or should we just skip the enum and live with allocating three times
as much space as the largest Xe_HP platform needs?

> 
> For all bitmap API call sites and *pb printk format sites, I suggest not hard-coding the widths from SSEU defines by querying the type itsef via wrappers. (See my BITMAP_BITS macro and helpers which wrap it for fields.)
> 
> Ie instead:
> 
> bitmap_shift_left(to_mask->b, to_mask->b, offset, I915_MAX_SS_FUSE_BITS);
> 
> I suggest:
> 
> bitmap_zero(slices.b, BITMAP_BITS(slices.b));
> 
> Also, all accesses to the bitmap type from outside intel_sse*.c|h should use intel_sseu wrappers and not embed knowledge of the typedef (that it has an member named .b etc).
> 
> And finally I would also use the opportunity to clean up the pointless u8 types for counts and such since I think they just result in worse code generation.
> 
> You can of course counter with what you did not like in my attempt. :) I know I did not finish the wrappers and possibly made an overkill by converting the slice mask to bitmap.

These suggestions all make sense.  I'll work on incorporating them into
the next version.


Matt

> 
> Regards,
> 
> Tvrtko
> > Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
> > ---
> >   drivers/gpu/drm/i915/gem/i915_gem_context.c  |   4 +-
> >   drivers/gpu/drm/i915/gt/intel_engine_cs.c    |   2 +-
> >   drivers/gpu/drm/i915/gt/intel_gt.c           |  14 +-
> >   drivers/gpu/drm/i915/gt/intel_sseu.c         | 197 +++++++++++--------
> >   drivers/gpu/drm/i915/gt/intel_sseu.h         |  48 ++---
> >   drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c |  28 +--
> >   drivers/gpu/drm/i915/gt/intel_workarounds.c  |  28 ++-
> >   drivers/gpu/drm/i915/i915_getparam.c         |   2 +-
> >   drivers/gpu/drm/i915/i915_query.c            |   8 +-
> >   9 files changed, 183 insertions(+), 148 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c
> > index ab4c5ab28e4d..ea012ee3a8de 100644
> > --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c
> > +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c
> > @@ -1901,7 +1901,7 @@ i915_gem_user_to_context_sseu(struct intel_gt *gt,
> >   	if (user->slice_mask & ~device->slice_mask)
> >   		return -EINVAL;
> > -	if (user->subslice_mask & ~device->subslice_mask[0])
> > +	if (user->subslice_mask & ~device->subslice_mask.b[0])
> >   		return -EINVAL;
> >   	if (user->max_eus_per_subslice > device->max_eus_per_subslice)
> > @@ -1915,7 +1915,7 @@ i915_gem_user_to_context_sseu(struct intel_gt *gt,
> >   	/* Part specific restrictions. */
> >   	if (GRAPHICS_VER(i915) == 11) {
> >   		unsigned int hw_s = hweight8(device->slice_mask);
> > -		unsigned int hw_ss_per_s = hweight8(device->subslice_mask[0]);
> > +		unsigned int hw_ss_per_s = hweight8(device->subslice_mask.b[0]);
> >   		unsigned int req_s = hweight8(context->slice_mask);
> >   		unsigned int req_ss = hweight8(context->subslice_mask);
> > diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
> > index 14c6ddbbfde8..39c09963b3c7 100644
> > --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c
> > +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
> > @@ -610,7 +610,7 @@ static void engine_mask_apply_compute_fuses(struct intel_gt *gt)
> >   	if (GRAPHICS_VER_FULL(i915) < IP_VER(12, 50))
> >   		return;
> > -	ccs_mask = intel_slicemask_from_dssmask(intel_sseu_get_compute_subslices(&info->sseu),
> > +	ccs_mask = intel_slicemask_from_dssmask(info->sseu.compute_subslice_mask,
> >   						ss_per_ccs);
> >   	/*
> >   	 * If all DSS in a quadrant are fused off, the corresponding CCS
> > diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c
> > index 92394f13b42f..cc03512d59ba 100644
> > --- a/drivers/gpu/drm/i915/gt/intel_gt.c
> > +++ b/drivers/gpu/drm/i915/gt/intel_gt.c
> > @@ -133,13 +133,6 @@ static const struct intel_mmio_range dg2_lncf_steering_table[] = {
> >   	{},
> >   };
> > -static u16 slicemask(struct intel_gt *gt, int count)
> > -{
> > -	u64 dss_mask = intel_sseu_get_subslices(&gt->info.sseu, 0);
> > -
> > -	return intel_slicemask_from_dssmask(dss_mask, count);
> > -}
> > -
> >   int intel_gt_init_mmio(struct intel_gt *gt)
> >   {
> >   	struct drm_i915_private *i915 = gt->i915;
> > @@ -153,11 +146,14 @@ int intel_gt_init_mmio(struct intel_gt *gt)
> >   	 * An mslice is unavailable only if both the meml3 for the slice is
> >   	 * disabled *and* all of the DSS in the slice (quadrant) are disabled.
> >   	 */
> > -	if (HAS_MSLICES(i915))
> > +	if (HAS_MSLICES(i915)) {
> >   		gt->info.mslice_mask =
> > -			slicemask(gt, GEN_DSS_PER_MSLICE) |
> > +			intel_slicemask_from_dssmask(gt->info.sseu.subslice_mask,
> > +						     GEN_DSS_PER_MSLICE);
> > +		gt->info.mslice_mask |=
> >   			(intel_uncore_read(gt->uncore, GEN10_MIRROR_FUSE3) &
> >   			 GEN12_MEML3_EN_MASK);
> > +	}
> >   	if (IS_DG2(i915)) {
> >   		gt->steering_table[MSLICE] = xehpsdv_mslice_steering_table;
> > diff --git a/drivers/gpu/drm/i915/gt/intel_sseu.c b/drivers/gpu/drm/i915/gt/intel_sseu.c
> > index f7ff6a9f67b0..466505d6bd18 100644
> > --- a/drivers/gpu/drm/i915/gt/intel_sseu.c
> > +++ b/drivers/gpu/drm/i915/gt/intel_sseu.c
> > @@ -28,56 +28,49 @@ void intel_sseu_set_info(struct sseu_dev_info *sseu, u8 max_slices,
> >   unsigned int
> >   intel_sseu_subslice_total(const struct sseu_dev_info *sseu)
> >   {
> > -	unsigned int i, total = 0;
> > -
> > -	for (i = 0; i < ARRAY_SIZE(sseu->subslice_mask); i++)
> > -		total += hweight8(sseu->subslice_mask[i]);
> > -
> > -	return total;
> > +	return bitmap_weight(sseu->subslice_mask.b, I915_MAX_SS_FUSE_BITS);
> >   }
> > -static u32
> > -sseu_get_subslices(const struct sseu_dev_info *sseu,
> > -		   const u8 *subslice_mask, u8 slice)
> > +static intel_sseu_ss_mask_t
> > +get_ss_mask_for_slice(const struct sseu_dev_info *sseu,
> > +		      intel_sseu_ss_mask_t all_ss,
> > +		      int slice)
> >   {
> > -	int i, offset = slice * sseu->ss_stride;
> > -	u32 mask = 0;
> > +	intel_sseu_ss_mask_t mask = {}, slice_ss = {};
> > +	int offset = slice * sseu->max_subslices;
> >   	GEM_BUG_ON(slice >= sseu->max_slices);
> > -	for (i = 0; i < sseu->ss_stride; i++)
> > -		mask |= (u32)subslice_mask[offset + i] << i * BITS_PER_BYTE;
> > +	if (sseu->max_slices == 1)
> > +		return all_ss;
> > -	return mask;
> > -}
> > +	bitmap_set(mask.b, offset, sseu->max_subslices);
> > +	bitmap_and(slice_ss.b, all_ss.b, mask.b, I915_MAX_SS_FUSE_BITS);
> > +	bitmap_shift_right(slice_ss.b, slice_ss.b, offset, I915_MAX_SS_FUSE_BITS);
> > -u32 intel_sseu_get_subslices(const struct sseu_dev_info *sseu, u8 slice)
> > -{
> > -	return sseu_get_subslices(sseu, sseu->subslice_mask, slice);
> > +	return slice_ss;
> >   }
> > -static u32 sseu_get_geometry_subslices(const struct sseu_dev_info *sseu)
> > +intel_sseu_ss_mask_t
> > +intel_sseu_get_subslices(const struct sseu_dev_info *sseu, u8 slice)
> >   {
> > -	return sseu_get_subslices(sseu, sseu->geometry_subslice_mask, 0);
> > +	return get_ss_mask_for_slice(sseu, sseu->subslice_mask, slice);
> >   }
> > -u32 intel_sseu_get_compute_subslices(const struct sseu_dev_info *sseu)
> > -{
> > -	return sseu_get_subslices(sseu, sseu->compute_subslice_mask, 0);
> > -}
> > -
> > -void intel_sseu_set_subslices(struct sseu_dev_info *sseu, int slice,
> > -			      u8 *subslice_mask, u32 ss_mask)
> > -{
> > -	int offset = slice * sseu->ss_stride;
> > -
> > -	memcpy(&subslice_mask[offset], &ss_mask, sseu->ss_stride);
> > -}
> > -
> > -unsigned int
> > -intel_sseu_subslices_per_slice(const struct sseu_dev_info *sseu, u8 slice)
> > +/*
> > + * Set the subslice mask associated with a specific slice.  Only needed on
> > + * pre-gen11 platforms that have multiple slices.
> > + */
> > +static void set_subslices(struct sseu_dev_info *sseu, int slice, u32 ss_mask)
> >   {
> > -	return hweight32(intel_sseu_get_subslices(sseu, slice));
> > +	intel_sseu_ss_mask_t mask = {}, newbits = {};
> > +	int offset = slice * sseu->max_subslices;
> > +
> > +	bitmap_set(mask.b, offset, sseu->max_subslices);
> > +	bitmap_from_arr32(newbits.b, &ss_mask, 32);
> > +	bitmap_shift_left(newbits.b, newbits.b, offset, I915_MAX_SS_FUSE_BITS);
> > +	bitmap_replace(sseu->subslice_mask.b, sseu->subslice_mask.b,
> > +		       newbits.b, mask.b, I915_MAX_SS_FUSE_BITS);
> >   }
> >   static int sseu_eu_idx(const struct sseu_dev_info *sseu, int slice,
> > @@ -115,7 +108,7 @@ static u16 compute_eu_total(const struct sseu_dev_info *sseu)
> >   	u16 i, total = 0;
> >   	if (sseu->has_common_ss_eumask)
> > -		return intel_sseu_subslices_per_slice(sseu, 0) *
> > +		return bitmap_weight(sseu->subslice_mask.b, I915_MAX_SS_FUSE_BITS) *
> >   			hweight16(sseu->eu_mask[0]);
> >   	for (i = 0; i < ARRAY_SIZE(sseu->eu_mask); i++)
> > @@ -155,11 +148,42 @@ int intel_sseu_copy_eumask_to_user(void __user *to,
> >   	return copy_to_user(to, eu_mask, len);
> >   }
> > -static void gen11_compute_sseu_info(struct sseu_dev_info *sseu,
> > -				    u32 g_ss_en, u32 c_ss_en, u16 eu_en)
> > +/**
> > + * intel_sseu_copy_ssmask_to_user - Copy subslice mask into a userspace buffer
> > + * @to: Pointer to userspace buffer to copy to
> > + * @sseu: SSEU structure containing subslice mask to copy
> > + *
> > + * Copies the subslice mask to a userspace buffer in the format expected by
> > + * the query ioctl's topology queries.
> > + *
> > + * Returns the result of the copy_to_user() operation.
> > + */
> > +int intel_sseu_copy_ssmask_to_user(void __user *to,
> > +				   const struct sseu_dev_info *sseu)
> >   {
> > -	u32 valid_ss_mask = GENMASK(sseu->max_subslices - 1, 0);
> > +	u8 ss_mask[GEN_SS_MASK_SIZE] = {};
> > +	int len = sseu->max_slices * sseu->ss_stride;
> > +	int s, ss, i;
> > +	for (s = 0; s < sseu->max_slices; s++) {
> > +		for (ss = 0; ss < sseu->max_subslices; ss++) {
> > +			i = s * sseu->ss_stride + ss;
> > +
> > +			if (!intel_sseu_has_subslice(sseu, s, ss))
> > +				continue;
> > +
> > +			ss_mask[i / BITS_PER_BYTE] |= BIT(i % BITS_PER_BYTE);
> > +		}
> > +	}
> > +
> > +	return copy_to_user(to, ss_mask, len);
> > +}
> > +
> > +static void gen11_compute_sseu_info(struct sseu_dev_info *sseu,
> > +				    intel_sseu_ss_mask_t g_ss_en,
> > +				    intel_sseu_ss_mask_t c_ss_en,
> > +				    u16 eu_en)
> > +{
> >   	/* g_ss_en/c_ss_en represent entire subslice mask across all slices */
> >   	GEM_BUG_ON(sseu->max_slices * sseu->max_subslices >
> >   		   sizeof(g_ss_en) * BITS_PER_BYTE);
> > @@ -174,12 +198,12 @@ static void gen11_compute_sseu_info(struct sseu_dev_info *sseu,
> >   	 * enabled subslice count for the purposes of selecting subslices to
> >   	 * use in a particular GEM context.
> >   	 */
> > -	intel_sseu_set_subslices(sseu, 0, sseu->compute_subslice_mask,
> > -				 c_ss_en & valid_ss_mask);
> > -	intel_sseu_set_subslices(sseu, 0, sseu->geometry_subslice_mask,
> > -				 g_ss_en & valid_ss_mask);
> > -	intel_sseu_set_subslices(sseu, 0, sseu->subslice_mask,
> > -				 (g_ss_en | c_ss_en) & valid_ss_mask);
> > +	bitmap_copy(sseu->compute_subslice_mask.b, c_ss_en.b, I915_MAX_SS_FUSE_BITS);
> > +	bitmap_copy(sseu->geometry_subslice_mask.b, g_ss_en.b, I915_MAX_SS_FUSE_BITS);
> > +	bitmap_or(sseu->subslice_mask.b,
> > +		  sseu->compute_subslice_mask.b,
> > +		  sseu->geometry_subslice_mask.b,
> > +		  I915_MAX_SS_FUSE_BITS);
> >   	sseu->has_common_ss_eumask = 1;
> >   	sseu->eu_mask[0] = eu_en;
> > @@ -191,7 +215,8 @@ static void xehp_sseu_info_init(struct intel_gt *gt)
> >   {
> >   	struct sseu_dev_info *sseu = &gt->info.sseu;
> >   	struct intel_uncore *uncore = gt->uncore;
> > -	u32 g_dss_en, c_dss_en = 0;
> > +	intel_sseu_ss_mask_t g_dss_en = {}, c_dss_en = {};
> > +	u32 val;
> >   	u16 eu_en = 0;
> >   	u8 eu_en_fuse;
> >   	int eu;
> > @@ -204,8 +229,11 @@ static void xehp_sseu_info_init(struct intel_gt *gt)
> >   	 */
> >   	intel_sseu_set_info(sseu, 1, 32, 16);
> > -	g_dss_en = intel_uncore_read(uncore, GEN12_GT_GEOMETRY_DSS_ENABLE);
> > -	c_dss_en = intel_uncore_read(uncore, GEN12_GT_COMPUTE_DSS_ENABLE);
> > +	val = intel_uncore_read(uncore, GEN12_GT_GEOMETRY_DSS_ENABLE);
> > +	bitmap_from_arr32(g_dss_en.b, &val, 32);
> > +
> > +	val = intel_uncore_read(uncore, GEN12_GT_COMPUTE_DSS_ENABLE);
> > +	bitmap_from_arr32(c_dss_en.b, &val, 32);
> >   	eu_en_fuse = intel_uncore_read(uncore, XEHP_EU_ENABLE) & XEHP_EU_ENA_MASK;
> > @@ -220,7 +248,8 @@ static void gen12_sseu_info_init(struct intel_gt *gt)
> >   {
> >   	struct sseu_dev_info *sseu = &gt->info.sseu;
> >   	struct intel_uncore *uncore = gt->uncore;
> > -	u32 g_dss_en;
> > +	intel_sseu_ss_mask_t g_dss_en = {}, empty_mask = {};
> > +	u32 val;
> >   	u16 eu_en = 0;
> >   	u8 eu_en_fuse;
> >   	u8 s_en;
> > @@ -243,7 +272,8 @@ static void gen12_sseu_info_init(struct intel_gt *gt)
> >   		drm_dbg(&gt->i915->drm, "Slice mask %#x is not the expected 0x1!\n",
> >   			s_en);
> > -	g_dss_en = intel_uncore_read(uncore, GEN12_GT_GEOMETRY_DSS_ENABLE);
> > +	val = intel_uncore_read(uncore, GEN12_GT_GEOMETRY_DSS_ENABLE);
> > +	bitmap_from_arr32(g_dss_en.b, &val, 32);
> >   	/* one bit per pair of EUs */
> >   	eu_en_fuse = ~(intel_uncore_read(uncore, GEN11_EU_DISABLE) &
> > @@ -253,7 +283,7 @@ static void gen12_sseu_info_init(struct intel_gt *gt)
> >   		if (eu_en_fuse & BIT(eu))
> >   			eu_en |= BIT(eu * 2) | BIT(eu * 2 + 1);
> > -	gen11_compute_sseu_info(sseu, g_dss_en, 0, eu_en);
> > +	gen11_compute_sseu_info(sseu, g_dss_en, empty_mask, eu_en);
> >   	/* TGL only supports slice-level power gating */
> >   	sseu->has_slice_pg = 1;
> > @@ -263,7 +293,8 @@ static void gen11_sseu_info_init(struct intel_gt *gt)
> >   {
> >   	struct sseu_dev_info *sseu = &gt->info.sseu;
> >   	struct intel_uncore *uncore = gt->uncore;
> > -	u32 ss_en;
> > +	intel_sseu_ss_mask_t ss_en = {}, empty_mask = {};
> > +	u32 val;
> >   	u8 eu_en;
> >   	u8 s_en;
> > @@ -282,12 +313,13 @@ static void gen11_sseu_info_init(struct intel_gt *gt)
> >   		drm_dbg(&gt->i915->drm, "Slice mask %#x is not the expected 0x1!\n",
> >   			s_en);
> > -	ss_en = ~intel_uncore_read(uncore, GEN11_GT_SUBSLICE_DISABLE);
> > +	val = ~intel_uncore_read(uncore, GEN11_GT_SUBSLICE_DISABLE);
> > +	bitmap_from_arr32(ss_en.b, &val, 32);
> >   	eu_en = ~(intel_uncore_read(uncore, GEN11_EU_DISABLE) &
> >   		  GEN11_EU_DIS_MASK);
> > -	gen11_compute_sseu_info(sseu, ss_en, 0, eu_en);
> > +	gen11_compute_sseu_info(sseu, ss_en, empty_mask, eu_en);
> >   	/* ICL has no power gating restrictions. */
> >   	sseu->has_slice_pg = 1;
> > @@ -328,7 +360,7 @@ static void cherryview_sseu_info_init(struct intel_gt *gt)
> >   		sseu_set_eus(sseu, 0, 1, ~disabled_mask);
> >   	}
> > -	intel_sseu_set_subslices(sseu, 0, sseu->subslice_mask, subslice_mask);
> > +	set_subslices(sseu, 0, subslice_mask);
> >   	sseu->eu_total = compute_eu_total(sseu);
> > @@ -384,8 +416,7 @@ static void gen9_sseu_info_init(struct intel_gt *gt)
> >   			/* skip disabled slice */
> >   			continue;
> > -		intel_sseu_set_subslices(sseu, s, sseu->subslice_mask,
> > -					 subslice_mask);
> > +		set_subslices(sseu, s, subslice_mask);
> >   		eu_disable = intel_uncore_read(uncore, GEN9_EU_DISABLE(s));
> >   		for (ss = 0; ss < sseu->max_subslices; ss++) {
> > @@ -442,8 +473,8 @@ static void gen9_sseu_info_init(struct intel_gt *gt)
> >   	sseu->has_eu_pg = sseu->eu_per_subslice > 2;
> >   	if (IS_GEN9_LP(i915)) {
> > -#define IS_SS_DISABLED(ss)	(!(sseu->subslice_mask[0] & BIT(ss)))
> > -		info->has_pooled_eu = hweight8(sseu->subslice_mask[0]) == 3;
> > +#define IS_SS_DISABLED(ss)	test_bit(ss, sseu->subslice_mask.b)
> > +		info->has_pooled_eu = hweight8(sseu->subslice_mask.b[0]) == 3;
> >   		sseu->min_eu_in_pool = 0;
> >   		if (info->has_pooled_eu) {
> > @@ -497,8 +528,7 @@ static void bdw_sseu_info_init(struct intel_gt *gt)
> >   			/* skip disabled slice */
> >   			continue;
> > -		intel_sseu_set_subslices(sseu, s, sseu->subslice_mask,
> > -					 subslice_mask);
> > +		set_subslices(sseu, s, subslice_mask);
> >   		for (ss = 0; ss < sseu->max_subslices; ss++) {
> >   			u8 eu_disabled_mask;
> > @@ -595,8 +625,7 @@ static void hsw_sseu_info_init(struct intel_gt *gt)
> >   			    sseu->eu_per_subslice);
> >   	for (s = 0; s < sseu->max_slices; s++) {
> > -		intel_sseu_set_subslices(sseu, s, sseu->subslice_mask,
> > -					 subslice_mask);
> > +		set_subslices(sseu, s, subslice_mask);
> >   		for (ss = 0; ss < sseu->max_subslices; ss++) {
> >   			sseu_set_eus(sseu, s, ss,
> > @@ -685,7 +714,7 @@ u32 intel_sseu_make_rpcs(struct intel_gt *gt,
> >   	 */
> >   	if (GRAPHICS_VER(i915) == 11 &&
> >   	    slices == 1 &&
> > -	    subslices > min_t(u8, 4, hweight8(sseu->subslice_mask[0]) / 2)) {
> > +	    subslices > min_t(u8, 4, hweight8(sseu->subslice_mask.b[0]) / 2)) {
> >   		GEM_BUG_ON(subslices & 1);
> >   		subslice_pg = false;
> > @@ -755,9 +784,11 @@ void intel_sseu_dump(const struct sseu_dev_info *sseu, struct drm_printer *p)
> >   		   hweight8(sseu->slice_mask), sseu->slice_mask);
> >   	drm_printf(p, "subslice total: %u\n", intel_sseu_subslice_total(sseu));
> >   	for (s = 0; s < sseu->max_slices; s++) {
> > -		drm_printf(p, "slice%d: %u subslices, mask=%08x\n",
> > -			   s, intel_sseu_subslices_per_slice(sseu, s),
> > -			   intel_sseu_get_subslices(sseu, s));
> > +		intel_sseu_ss_mask_t ssmask = intel_sseu_get_subslices(sseu, s);
> > +
> > +		drm_printf(p, "slice%d: %u subslices, mask=%*pb\n",
> > +			   s, bitmap_weight(ssmask.b, I915_MAX_SS_FUSE_BITS),
> > +			   I915_MAX_SS_FUSE_BITS, ssmask.b);
> >   	}
> >   	drm_printf(p, "EU total: %u\n", sseu->eu_total);
> >   	drm_printf(p, "EU per subslice: %u\n", sseu->eu_per_subslice);
> > @@ -775,9 +806,11 @@ static void sseu_print_hsw_topology(const struct sseu_dev_info *sseu,
> >   	int s, ss;
> >   	for (s = 0; s < sseu->max_slices; s++) {
> > -		drm_printf(p, "slice%d: %u subslice(s) (0x%08x):\n",
> > -			   s, intel_sseu_subslices_per_slice(sseu, s),
> > -			   intel_sseu_get_subslices(sseu, s));
> > +		intel_sseu_ss_mask_t ssmask = intel_sseu_get_subslices(sseu, s);
> > +
> > +		drm_printf(p, "slice%d: %u subslice(s) (0x%*pb):\n",
> > +			   s, bitmap_weight(ssmask.b, I915_MAX_SS_FUSE_BITS),
> > +			   I915_MAX_SS_FUSE_BITS, ssmask.b);
> >   		for (ss = 0; ss < sseu->max_subslices; ss++) {
> >   			u16 enabled_eus = sseu_get_eus(sseu, s, ss);
> > @@ -791,16 +824,14 @@ static void sseu_print_hsw_topology(const struct sseu_dev_info *sseu,
> >   static void sseu_print_xehp_topology(const struct sseu_dev_info *sseu,
> >   				     struct drm_printer *p)
> >   {
> > -	u32 g_dss_mask = sseu_get_geometry_subslices(sseu);
> > -	u32 c_dss_mask = intel_sseu_get_compute_subslices(sseu);
> >   	int dss;
> >   	for (dss = 0; dss < sseu->max_subslices; dss++) {
> >   		u16 enabled_eus = sseu_get_eus(sseu, 0, dss);
> >   		drm_printf(p, "DSS_%02d: G:%3s C:%3s, %2u EUs (0x%04hx)\n", dss,
> > -			   str_yes_no(g_dss_mask & BIT(dss)),
> > -			   str_yes_no(c_dss_mask & BIT(dss)),
> > +			   str_yes_no(test_bit(dss, sseu->geometry_subslice_mask.b)),
> > +			   str_yes_no(test_bit(dss, sseu->compute_subslice_mask.b)),
> >   			   hweight16(enabled_eus), enabled_eus);
> >   	}
> >   }
> > @@ -818,20 +849,24 @@ void intel_sseu_print_topology(struct drm_i915_private *i915,
> >   	}
> >   }
> > -u16 intel_slicemask_from_dssmask(u64 dss_mask, int dss_per_slice)
> > +u16 intel_slicemask_from_dssmask(intel_sseu_ss_mask_t dss_mask,
> > +				 int dss_per_slice)
> >   {
> > +	intel_sseu_ss_mask_t per_slice_mask = {};
> >   	u16 slice_mask = 0;
> >   	int i;
> > -	WARN_ON(sizeof(dss_mask) * 8 / dss_per_slice > 8 * sizeof(slice_mask));
> > +	WARN_ON(DIV_ROUND_UP(I915_MAX_SS_FUSE_BITS, dss_per_slice) >
> > +		8 * sizeof(slice_mask));
> > -	for (i = 0; dss_mask; i++) {
> > -		if (dss_mask & GENMASK(dss_per_slice - 1, 0))
> > +	bitmap_fill(per_slice_mask.b, dss_per_slice);
> > +	for (i = 0; !bitmap_empty(dss_mask.b, I915_MAX_SS_FUSE_BITS); i++) {
> > +		if (bitmap_intersects(dss_mask.b, per_slice_mask.b, dss_per_slice))
> >   			slice_mask |= BIT(i);
> > -		dss_mask >>= dss_per_slice;
> > +		bitmap_shift_right(dss_mask.b, dss_mask.b, dss_per_slice,
> > +				   I915_MAX_SS_FUSE_BITS);
> >   	}
> >   	return slice_mask;
> >   }
> > -
> > diff --git a/drivers/gpu/drm/i915/gt/intel_sseu.h b/drivers/gpu/drm/i915/gt/intel_sseu.h
> > index 106726a2244e..455f085093ae 100644
> > --- a/drivers/gpu/drm/i915/gt/intel_sseu.h
> > +++ b/drivers/gpu/drm/i915/gt/intel_sseu.h
> > @@ -52,11 +52,22 @@ struct drm_printer;
> >   #define GEN_MAX_GSLICES		(GEN_MAX_DSS / GEN_DSS_PER_GSLICE)
> >   #define GEN_MAX_CSLICES		(GEN_MAX_DSS / GEN_DSS_PER_CSLICE)
> > +/*
> > + * Maximum number of 32-bit registers used by hardware to express the
> > + * enabled/disabled subslices.
> > + */
> > +#define I915_MAX_SS_FUSE_REGS	1
> > +#define I915_MAX_SS_FUSE_BITS	(I915_MAX_SS_FUSE_REGS * 32)
> > +
> > +typedef struct {
> > +	unsigned long b[BITS_TO_LONGS(I915_MAX_SS_FUSE_BITS)];
> > +} intel_sseu_ss_mask_t;
> > +
> >   struct sseu_dev_info {
> >   	u8 slice_mask;
> > -	u8 subslice_mask[GEN_SS_MASK_SIZE];
> > -	u8 geometry_subslice_mask[GEN_SS_MASK_SIZE];
> > -	u8 compute_subslice_mask[GEN_SS_MASK_SIZE];
> > +	intel_sseu_ss_mask_t subslice_mask;
> > +	intel_sseu_ss_mask_t geometry_subslice_mask;
> > +	intel_sseu_ss_mask_t compute_subslice_mask;
> >   	/*
> >   	 * EU masks.  Use has_common_ss_eumask to determine how the field
> > @@ -107,7 +118,7 @@ intel_sseu_from_device_info(const struct sseu_dev_info *sseu)
> >   {
> >   	struct intel_sseu value = {
> >   		.slice_mask = sseu->slice_mask,
> > -		.subslice_mask = sseu->subslice_mask[0],
> > +		.subslice_mask = sseu->subslice_mask.b[0],
> >   		.min_eus_per_subslice = sseu->max_eus_per_subslice,
> >   		.max_eus_per_subslice = sseu->max_eus_per_subslice,
> >   	};
> > @@ -119,18 +130,8 @@ static inline bool
> >   intel_sseu_has_subslice(const struct sseu_dev_info *sseu, int slice,
> >   			int subslice)
> >   {
> > -	u8 mask;
> > -	int ss_idx = subslice / BITS_PER_BYTE;
> > -
> > -	if (slice >= sseu->max_slices ||
> > -	    subslice >= sseu->max_subslices)
> > -		return false;
> > -
> > -	GEM_BUG_ON(ss_idx >= sseu->ss_stride);
> > -
> > -	mask = sseu->subslice_mask[slice * sseu->ss_stride + ss_idx];
> > -
> > -	return mask & BIT(subslice % BITS_PER_BYTE);
> > +	return test_bit(slice * sseu->ss_stride + subslice,
> > +			sseu->subslice_mask.b);
> >   }
> >   void intel_sseu_set_info(struct sseu_dev_info *sseu, u8 max_slices,
> > @@ -139,15 +140,14 @@ void intel_sseu_set_info(struct sseu_dev_info *sseu, u8 max_slices,
> >   unsigned int
> >   intel_sseu_subslice_total(const struct sseu_dev_info *sseu);
> > -unsigned int
> > -intel_sseu_subslices_per_slice(const struct sseu_dev_info *sseu, u8 slice);
> > +intel_sseu_ss_mask_t
> > +intel_sseu_get_subslices(const struct sseu_dev_info *sseu, u8 slice);
> > -u32 intel_sseu_get_subslices(const struct sseu_dev_info *sseu, u8 slice);
> > -
> > -u32 intel_sseu_get_compute_subslices(const struct sseu_dev_info *sseu);
> > +intel_sseu_ss_mask_t
> > +intel_sseu_get_compute_subslices(const struct sseu_dev_info *sseu);
> >   void intel_sseu_set_subslices(struct sseu_dev_info *sseu, int slice,
> > -			      u8 *subslice_mask, u32 ss_mask);
> > +			      u32 ss_mask);
> >   void intel_sseu_info_init(struct intel_gt *gt);
> > @@ -159,9 +159,11 @@ void intel_sseu_print_topology(struct drm_i915_private *i915,
> >   			       const struct sseu_dev_info *sseu,
> >   			       struct drm_printer *p);
> > -u16 intel_slicemask_from_dssmask(u64 dss_mask, int dss_per_slice);
> > +u16 intel_slicemask_from_dssmask(intel_sseu_ss_mask_t dss_mask, int dss_per_slice);
> >   int intel_sseu_copy_eumask_to_user(void __user *to,
> >   				   const struct sseu_dev_info *sseu);
> > +int intel_sseu_copy_ssmask_to_user(void __user *to,
> > +				   const struct sseu_dev_info *sseu);
> >   #endif /* __INTEL_SSEU_H__ */
> > diff --git a/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c b/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c
> > index 2d5d011e01db..1f77bd52a3a6 100644
> > --- a/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c
> > +++ b/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c
> > @@ -4,6 +4,7 @@
> >    * Copyright © 2020 Intel Corporation
> >    */
> > +#include <linux/bitmap.h>
> >   #include <linux/string_helpers.h>
> >   #include "i915_drv.h"
> > @@ -12,11 +13,15 @@
> >   #include "intel_sseu_debugfs.h"
> >   static void sseu_copy_subslices(const struct sseu_dev_info *sseu,
> > -				int slice, u8 *to_mask)
> > +				int slice,
> > +				intel_sseu_ss_mask_t *to_mask)
> >   {
> > -	int offset = slice * sseu->ss_stride;
> > +	int offset = slice * sseu->max_subslices;
> > -	memcpy(&to_mask[offset], &sseu->subslice_mask[offset], sseu->ss_stride);
> > +	bitmap_fill(to_mask->b, sseu->max_subslices);
> > +	bitmap_shift_left(to_mask->b, to_mask->b, offset, I915_MAX_SS_FUSE_BITS);
> > +	bitmap_and(to_mask->b, to_mask->b, sseu->subslice_mask.b, I915_MAX_SS_FUSE_BITS);
> > +	bitmap_shift_right(to_mask->b, to_mask->b, offset, I915_MAX_SS_FUSE_BITS);
> >   }
> >   static void cherryview_sseu_device_status(struct intel_gt *gt,
> > @@ -41,7 +46,7 @@ static void cherryview_sseu_device_status(struct intel_gt *gt,
> >   			continue;
> >   		sseu->slice_mask = BIT(0);
> > -		sseu->subslice_mask[0] |= BIT(ss);
> > +		set_bit(0, sseu->subslice_mask.b);
> >   		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) +
> > @@ -92,7 +97,7 @@ static void gen11_sseu_device_status(struct intel_gt *gt,
> >   			continue;
> >   		sseu->slice_mask |= BIT(s);
> > -		sseu_copy_subslices(&info->sseu, s, sseu->subslice_mask);
> > +		sseu_copy_subslices(&info->sseu, s, &sseu->subslice_mask);
> >   		for (ss = 0; ss < info->sseu.max_subslices; ss++) {
> >   			unsigned int eu_cnt;
> > @@ -148,20 +153,17 @@ static void gen9_sseu_device_status(struct intel_gt *gt,
> >   		if (IS_GEN9_BC(gt->i915))
> >   			sseu_copy_subslices(&info->sseu, s,
> > -					    sseu->subslice_mask);
> > +					    &sseu->subslice_mask);
> >   		for (ss = 0; ss < info->sseu.max_subslices; ss++) {
> >   			unsigned int eu_cnt;
> > -			u8 ss_idx = s * info->sseu.ss_stride +
> > -				    ss / BITS_PER_BYTE;
> >   			if (IS_GEN9_LP(gt->i915)) {
> >   				if (!(s_reg[s] & (GEN9_PGCTL_SS_ACK(ss))))
> >   					/* skip disabled subslice */
> >   					continue;
> > -				sseu->subslice_mask[ss_idx] |=
> > -					BIT(ss % BITS_PER_BYTE);
> > +				set_bit(ss, sseu->subslice_mask.b);
> >   			}
> >   			eu_cnt = eu_reg[2 * s + ss / 2] & eu_mask[ss % 2];
> > @@ -189,7 +191,7 @@ static void bdw_sseu_device_status(struct intel_gt *gt,
> >   		sseu->eu_per_subslice = info->sseu.eu_per_subslice;
> >   		for (s = 0; s < fls(sseu->slice_mask); s++)
> >   			sseu_copy_subslices(&info->sseu, s,
> > -					    sseu->subslice_mask);
> > +					    &sseu->subslice_mask);
> >   		sseu->eu_total = sseu->eu_per_subslice *
> >   				 intel_sseu_subslice_total(sseu);
> > @@ -217,8 +219,10 @@ static void i915_print_sseu_info(struct seq_file *m,
> >   	seq_printf(m, "  %s Subslice Total: %u\n", type,
> >   		   intel_sseu_subslice_total(sseu));
> >   	for (s = 0; s < fls(sseu->slice_mask); s++) {
> > +		intel_sseu_ss_mask_t ssmask = intel_sseu_get_subslices(sseu, s);
> > +
> >   		seq_printf(m, "  %s Slice%i subslices: %u\n", type,
> > -			   s, intel_sseu_subslices_per_slice(sseu, s));
> > +			   s, bitmap_weight(ssmask.b, I915_MAX_SS_FUSE_BITS));
> >   	}
> >   	seq_printf(m, "  %s EU Total: %u\n", type,
> >   		   sseu->eu_total);
> > diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c
> > index a05c4b99b3fb..5db492072f99 100644
> > --- a/drivers/gpu/drm/i915/gt/intel_workarounds.c
> > +++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c
> > @@ -931,6 +931,7 @@ static void
> >   gen9_wa_init_mcr(struct drm_i915_private *i915, struct i915_wa_list *wal)
> >   {
> >   	const struct sseu_dev_info *sseu = &to_gt(i915)->info.sseu;
> > +	intel_sseu_ss_mask_t ssmask;
> >   	unsigned int slice, subslice;
> >   	u32 mcr, mcr_mask;
> > @@ -948,9 +949,9 @@ gen9_wa_init_mcr(struct drm_i915_private *i915, struct i915_wa_list *wal)
> >   	 * on s/ss combo, the read should be done with read_subslice_reg.
> >   	 */
> >   	slice = ffs(sseu->slice_mask) - 1;
> > -	GEM_BUG_ON(slice >= ARRAY_SIZE(sseu->subslice_mask));
> > -	subslice = ffs(intel_sseu_get_subslices(sseu, slice));
> > -	GEM_BUG_ON(!subslice);
> > +	ssmask = intel_sseu_get_subslices(sseu, slice);
> > +	subslice = find_first_bit(ssmask.b, I915_MAX_SS_FUSE_BITS);
> > +	GEM_BUG_ON(subslice == I915_MAX_SS_FUSE_BITS);
> >   	subslice--;
> >   	/*
> > @@ -1087,11 +1088,10 @@ static void
> >   icl_wa_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
> >   {
> >   	const struct sseu_dev_info *sseu = &gt->info.sseu;
> > -	unsigned int slice, subslice;
> > +	unsigned int subslice;
> >   	GEM_BUG_ON(GRAPHICS_VER(gt->i915) < 11);
> >   	GEM_BUG_ON(hweight8(sseu->slice_mask) > 1);
> > -	slice = 0;
> >   	/*
> >   	 * Although a platform may have subslices, we need to always steer
> > @@ -1102,7 +1102,7 @@ icl_wa_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
> >   	 * one of the higher subslices, we run the risk of reading back 0's or
> >   	 * random garbage.
> >   	 */
> > -	subslice = __ffs(intel_sseu_get_subslices(sseu, slice));
> > +	subslice = find_first_bit(sseu->subslice_mask.b, I915_MAX_SS_FUSE_BITS);
> >   	/*
> >   	 * If the subslice we picked above also steers us to a valid L3 bank,
> > @@ -1112,7 +1112,7 @@ icl_wa_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
> >   	if (gt->info.l3bank_mask & BIT(subslice))
> >   		gt->steering_table[L3BANK] = NULL;
> > -	__add_mcr_wa(gt, wal, slice, subslice);
> > +	__add_mcr_wa(gt, wal, 0, subslice);
> >   }
> >   static void
> > @@ -1120,7 +1120,6 @@ xehp_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
> >   {
> >   	const struct sseu_dev_info *sseu = &gt->info.sseu;
> >   	unsigned long slice, subslice = 0, slice_mask = 0;
> > -	u64 dss_mask = 0;
> >   	u32 lncf_mask = 0;
> >   	int i;
> > @@ -1151,8 +1150,8 @@ xehp_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
> >   	 */
> >   	/* Find the potential gslice candidates */
> > -	dss_mask = intel_sseu_get_subslices(sseu, 0);
> > -	slice_mask = intel_slicemask_from_dssmask(dss_mask, GEN_DSS_PER_GSLICE);
> > +	slice_mask = intel_slicemask_from_dssmask(sseu->subslice_mask,
> > +						  GEN_DSS_PER_GSLICE);
> >   	/*
> >   	 * Find the potential LNCF candidates.  Either LNCF within a valid
> > @@ -1177,9 +1176,9 @@ xehp_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
> >   	}
> >   	slice = __ffs(slice_mask);
> > -	subslice = __ffs(dss_mask >> (slice * GEN_DSS_PER_GSLICE));
> > +	subslice = find_next_bit(sseu->subslice_mask.b, I915_MAX_SS_FUSE_BITS,
> > +				 slice * GEN_DSS_PER_GSLICE);
> >   	WARN_ON(subslice > GEN_DSS_PER_GSLICE);
> > -	WARN_ON(dss_mask >> (slice * GEN_DSS_PER_GSLICE) == 0);
> >   	__add_mcr_wa(gt, wal, slice, subslice);
> > @@ -2012,9 +2011,8 @@ engine_fake_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
> >   static bool needs_wa_1308578152(struct intel_engine_cs *engine)
> >   {
> > -	u64 dss_mask = intel_sseu_get_subslices(&engine->gt->info.sseu, 0);
> > -
> > -	return (dss_mask & GENMASK(GEN_DSS_PER_GSLICE - 1, 0)) == 0;
> > +	return find_first_bit(engine->gt->info.sseu.subslice_mask.b,
> > +			      I915_MAX_SS_FUSE_BITS) >= GEN_DSS_PER_GSLICE;
> >   }
> >   static void
> > diff --git a/drivers/gpu/drm/i915/i915_getparam.c b/drivers/gpu/drm/i915/i915_getparam.c
> > index ac9767c56619..349d496d164a 100644
> > --- a/drivers/gpu/drm/i915/i915_getparam.c
> > +++ b/drivers/gpu/drm/i915/i915_getparam.c
> > @@ -162,7 +162,7 @@ int i915_getparam_ioctl(struct drm_device *dev, void *data,
> >   			return -EINVAL;
> >   		/* Only copy bits from the first slice */
> > -		memcpy(&value, sseu->subslice_mask,
> > +		memcpy(&value, sseu->subslice_mask.b,
> >   		       min(sseu->ss_stride, (u8)sizeof(value)));
> >   		if (!value)
> >   			return -ENODEV;
> > diff --git a/drivers/gpu/drm/i915/i915_query.c b/drivers/gpu/drm/i915/i915_query.c
> > index 16f43bf32a05..9afa6d1eaf95 100644
> > --- a/drivers/gpu/drm/i915/i915_query.c
> > +++ b/drivers/gpu/drm/i915/i915_query.c
> > @@ -31,7 +31,7 @@ static int copy_query_item(void *query_hdr, size_t query_sz,
> >   static int fill_topology_info(const struct sseu_dev_info *sseu,
> >   			      struct drm_i915_query_item *query_item,
> > -			      const u8 *subslice_mask)
> > +			      intel_sseu_ss_mask_t subslice_mask)
> >   {
> >   	struct drm_i915_query_topology_info topo;
> >   	u32 slice_length, subslice_length, eu_length, total_length;
> > @@ -71,9 +71,9 @@ static int fill_topology_info(const struct sseu_dev_info *sseu,
> >   			 &sseu->slice_mask, slice_length))
> >   		return -EFAULT;
> > -	if (copy_to_user(u64_to_user_ptr(query_item->data_ptr +
> > -					 sizeof(topo) + slice_length),
> > -			 subslice_mask, subslice_length))
> > +	if (intel_sseu_copy_ssmask_to_user(u64_to_user_ptr(query_item->data_ptr +
> > +							   sizeof(topo) + slice_length),
> > +					   sseu))
> >   		return -EFAULT;
> >   	if (intel_sseu_copy_eumask_to_user(u64_to_user_ptr(query_item->data_ptr +

-- 
Matt Roper
Graphics Software Engineer
VTT-OSGC Platform Enablement
Intel Corporation
(916) 356-2795

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

* Re: [PATCH 5/5] drm/i915/sseu: Disassociate internal subslice mask representation from uapi
  2022-05-06 23:34       ` [Intel-gfx] " Matt Roper
@ 2022-05-09 14:18         ` Tvrtko Ursulin
  -1 siblings, 0 replies; 27+ messages in thread
From: Tvrtko Ursulin @ 2022-05-09 14:18 UTC (permalink / raw)
  To: Matt Roper; +Cc: intel-gfx, dri-devel


On 07/05/2022 00:34, Matt Roper wrote:
> On Thu, Apr 28, 2022 at 01:18:42PM +0100, Tvrtko Ursulin wrote:
>>
>> Hi,
>>
>> On 28/04/2022 00:07, Matt Roper wrote:
>>> Rather than storing subslice masks internally as u8[] (inside the sseu
>>> structure) and u32 (everywhere else), let's move over to using an
>>> intel_sseu_ss_mask_t typedef compatible with the operations in
>>> linux/bitmap.h.  We're soon going to start adding code for a new
>>> platform where subslice masks are spread across two 32-bit registers
>>> (requiring 64 bits to represent), and we expect future platforms will
>>> likely take this even farther, requiring bitmask storage larger than a
>>> simple u64 can hold.
>>
>> I won't have time to look into this in a detailed way for a few days. Until then a couple questions comments only.
>>
>> First, out of curiousity, were you able to end up with less code after your series? With my bitmap conversion I think actually ended up with couple KB smaller text which was a good sign eliminating the internal layout complications was a good approach.
> 
> Yeah, looks like I did:
> 
>     $ size i915.ko.orig i915.ko
>        text    data     bss     dec     hex filename
>     3479050  132498    6760 3618308  373604 i915.ko.orig
>     3476552  132466    6760 3615778  372c22 i915.ko
> 
>>
>> For your series I am not convinced by sseu->has_common_ss_eumask. Why the duality, just to save a few u32 at runtime?
> 
> With this flag, eu_mask is an array of GEN_MAX_HSW_SLICES *
> GEN_MAX_SS_PER_HSW_SLICE (i.e., 3*6 = 18).  If we store the replicated
> EU masks, then we'll have 64 u16's on PVC (where we have a DSS mask
> spread across two registers) and 96 u16's on a future platform that
> spreads the mask across three fuse registers.  18 -> 96 (or possibly
> even more farther in the future).  I think we've eliminated all of the
> stack allocations of sseu structures now, so it probably isn't as
> important as it used to be though; I can drop it if you think the size
> savings aren't worth the extra complexity.
> 
>>
>> I am also not convinced with leaving the eu_mask and subslice_mask
>> being manually indexed with stride, calculcated by the driver. In my
>> approach I simply went with multi-dimensional arrays which I think
>> ends up with simpler code.
> 
> So something like
> 
>          enum {
>                  u16 hsw[GEN_MAX_HSW_SLICES][GEN_MAX_SS_PER_HSW_SLICE];
>                  u16 xehp[GEN_MAX_DSS];
>          } eu_mask;
> 
> ?  Or should we just skip the enum and live with allocating three times
> as much space as the largest Xe_HP platform needs?

s/enum/union/ right? This is an excellent idea - further simplifies the 
code by expressing the reality of how data is organized and every 
platform just touches it's own data in the most logical and 
straightforward manner. If I am not missing some gotcha then yes please. 
(Like I am not sure how generalisation to bitmap will work together with 
union, from common callers, if there are such.)

Regards,

Tvrtko

>> For all bitmap API call sites and *pb printk format sites, I suggest not hard-coding the widths from SSEU defines by querying the type itsef via wrappers. (See my BITMAP_BITS macro and helpers which wrap it for fields.)
>>
>> Ie instead:
>>
>> bitmap_shift_left(to_mask->b, to_mask->b, offset, I915_MAX_SS_FUSE_BITS);
>>
>> I suggest:
>>
>> bitmap_zero(slices.b, BITMAP_BITS(slices.b));
>>
>> Also, all accesses to the bitmap type from outside intel_sse*.c|h should use intel_sseu wrappers and not embed knowledge of the typedef (that it has an member named .b etc).
>>
>> And finally I would also use the opportunity to clean up the pointless u8 types for counts and such since I think they just result in worse code generation.
>>
>> You can of course counter with what you did not like in my attempt. :) I know I did not finish the wrappers and possibly made an overkill by converting the slice mask to bitmap.
> 
> These suggestions all make sense.  I'll work on incorporating them into
> the next version. >
> 
> Matt
> 
>>
>> Regards,
>>
>> Tvrtko
>>> Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
>>> ---
>>>    drivers/gpu/drm/i915/gem/i915_gem_context.c  |   4 +-
>>>    drivers/gpu/drm/i915/gt/intel_engine_cs.c    |   2 +-
>>>    drivers/gpu/drm/i915/gt/intel_gt.c           |  14 +-
>>>    drivers/gpu/drm/i915/gt/intel_sseu.c         | 197 +++++++++++--------
>>>    drivers/gpu/drm/i915/gt/intel_sseu.h         |  48 ++---
>>>    drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c |  28 +--
>>>    drivers/gpu/drm/i915/gt/intel_workarounds.c  |  28 ++-
>>>    drivers/gpu/drm/i915/i915_getparam.c         |   2 +-
>>>    drivers/gpu/drm/i915/i915_query.c            |   8 +-
>>>    9 files changed, 183 insertions(+), 148 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c
>>> index ab4c5ab28e4d..ea012ee3a8de 100644
>>> --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c
>>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c
>>> @@ -1901,7 +1901,7 @@ i915_gem_user_to_context_sseu(struct intel_gt *gt,
>>>    	if (user->slice_mask & ~device->slice_mask)
>>>    		return -EINVAL;
>>> -	if (user->subslice_mask & ~device->subslice_mask[0])
>>> +	if (user->subslice_mask & ~device->subslice_mask.b[0])
>>>    		return -EINVAL;
>>>    	if (user->max_eus_per_subslice > device->max_eus_per_subslice)
>>> @@ -1915,7 +1915,7 @@ i915_gem_user_to_context_sseu(struct intel_gt *gt,
>>>    	/* Part specific restrictions. */
>>>    	if (GRAPHICS_VER(i915) == 11) {
>>>    		unsigned int hw_s = hweight8(device->slice_mask);
>>> -		unsigned int hw_ss_per_s = hweight8(device->subslice_mask[0]);
>>> +		unsigned int hw_ss_per_s = hweight8(device->subslice_mask.b[0]);
>>>    		unsigned int req_s = hweight8(context->slice_mask);
>>>    		unsigned int req_ss = hweight8(context->subslice_mask);
>>> diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
>>> index 14c6ddbbfde8..39c09963b3c7 100644
>>> --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c
>>> +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
>>> @@ -610,7 +610,7 @@ static void engine_mask_apply_compute_fuses(struct intel_gt *gt)
>>>    	if (GRAPHICS_VER_FULL(i915) < IP_VER(12, 50))
>>>    		return;
>>> -	ccs_mask = intel_slicemask_from_dssmask(intel_sseu_get_compute_subslices(&info->sseu),
>>> +	ccs_mask = intel_slicemask_from_dssmask(info->sseu.compute_subslice_mask,
>>>    						ss_per_ccs);
>>>    	/*
>>>    	 * If all DSS in a quadrant are fused off, the corresponding CCS
>>> diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c
>>> index 92394f13b42f..cc03512d59ba 100644
>>> --- a/drivers/gpu/drm/i915/gt/intel_gt.c
>>> +++ b/drivers/gpu/drm/i915/gt/intel_gt.c
>>> @@ -133,13 +133,6 @@ static const struct intel_mmio_range dg2_lncf_steering_table[] = {
>>>    	{},
>>>    };
>>> -static u16 slicemask(struct intel_gt *gt, int count)
>>> -{
>>> -	u64 dss_mask = intel_sseu_get_subslices(&gt->info.sseu, 0);
>>> -
>>> -	return intel_slicemask_from_dssmask(dss_mask, count);
>>> -}
>>> -
>>>    int intel_gt_init_mmio(struct intel_gt *gt)
>>>    {
>>>    	struct drm_i915_private *i915 = gt->i915;
>>> @@ -153,11 +146,14 @@ int intel_gt_init_mmio(struct intel_gt *gt)
>>>    	 * An mslice is unavailable only if both the meml3 for the slice is
>>>    	 * disabled *and* all of the DSS in the slice (quadrant) are disabled.
>>>    	 */
>>> -	if (HAS_MSLICES(i915))
>>> +	if (HAS_MSLICES(i915)) {
>>>    		gt->info.mslice_mask =
>>> -			slicemask(gt, GEN_DSS_PER_MSLICE) |
>>> +			intel_slicemask_from_dssmask(gt->info.sseu.subslice_mask,
>>> +						     GEN_DSS_PER_MSLICE);
>>> +		gt->info.mslice_mask |=
>>>    			(intel_uncore_read(gt->uncore, GEN10_MIRROR_FUSE3) &
>>>    			 GEN12_MEML3_EN_MASK);
>>> +	}
>>>    	if (IS_DG2(i915)) {
>>>    		gt->steering_table[MSLICE] = xehpsdv_mslice_steering_table;
>>> diff --git a/drivers/gpu/drm/i915/gt/intel_sseu.c b/drivers/gpu/drm/i915/gt/intel_sseu.c
>>> index f7ff6a9f67b0..466505d6bd18 100644
>>> --- a/drivers/gpu/drm/i915/gt/intel_sseu.c
>>> +++ b/drivers/gpu/drm/i915/gt/intel_sseu.c
>>> @@ -28,56 +28,49 @@ void intel_sseu_set_info(struct sseu_dev_info *sseu, u8 max_slices,
>>>    unsigned int
>>>    intel_sseu_subslice_total(const struct sseu_dev_info *sseu)
>>>    {
>>> -	unsigned int i, total = 0;
>>> -
>>> -	for (i = 0; i < ARRAY_SIZE(sseu->subslice_mask); i++)
>>> -		total += hweight8(sseu->subslice_mask[i]);
>>> -
>>> -	return total;
>>> +	return bitmap_weight(sseu->subslice_mask.b, I915_MAX_SS_FUSE_BITS);
>>>    }
>>> -static u32
>>> -sseu_get_subslices(const struct sseu_dev_info *sseu,
>>> -		   const u8 *subslice_mask, u8 slice)
>>> +static intel_sseu_ss_mask_t
>>> +get_ss_mask_for_slice(const struct sseu_dev_info *sseu,
>>> +		      intel_sseu_ss_mask_t all_ss,
>>> +		      int slice)
>>>    {
>>> -	int i, offset = slice * sseu->ss_stride;
>>> -	u32 mask = 0;
>>> +	intel_sseu_ss_mask_t mask = {}, slice_ss = {};
>>> +	int offset = slice * sseu->max_subslices;
>>>    	GEM_BUG_ON(slice >= sseu->max_slices);
>>> -	for (i = 0; i < sseu->ss_stride; i++)
>>> -		mask |= (u32)subslice_mask[offset + i] << i * BITS_PER_BYTE;
>>> +	if (sseu->max_slices == 1)
>>> +		return all_ss;
>>> -	return mask;
>>> -}
>>> +	bitmap_set(mask.b, offset, sseu->max_subslices);
>>> +	bitmap_and(slice_ss.b, all_ss.b, mask.b, I915_MAX_SS_FUSE_BITS);
>>> +	bitmap_shift_right(slice_ss.b, slice_ss.b, offset, I915_MAX_SS_FUSE_BITS);
>>> -u32 intel_sseu_get_subslices(const struct sseu_dev_info *sseu, u8 slice)
>>> -{
>>> -	return sseu_get_subslices(sseu, sseu->subslice_mask, slice);
>>> +	return slice_ss;
>>>    }
>>> -static u32 sseu_get_geometry_subslices(const struct sseu_dev_info *sseu)
>>> +intel_sseu_ss_mask_t
>>> +intel_sseu_get_subslices(const struct sseu_dev_info *sseu, u8 slice)
>>>    {
>>> -	return sseu_get_subslices(sseu, sseu->geometry_subslice_mask, 0);
>>> +	return get_ss_mask_for_slice(sseu, sseu->subslice_mask, slice);
>>>    }
>>> -u32 intel_sseu_get_compute_subslices(const struct sseu_dev_info *sseu)
>>> -{
>>> -	return sseu_get_subslices(sseu, sseu->compute_subslice_mask, 0);
>>> -}
>>> -
>>> -void intel_sseu_set_subslices(struct sseu_dev_info *sseu, int slice,
>>> -			      u8 *subslice_mask, u32 ss_mask)
>>> -{
>>> -	int offset = slice * sseu->ss_stride;
>>> -
>>> -	memcpy(&subslice_mask[offset], &ss_mask, sseu->ss_stride);
>>> -}
>>> -
>>> -unsigned int
>>> -intel_sseu_subslices_per_slice(const struct sseu_dev_info *sseu, u8 slice)
>>> +/*
>>> + * Set the subslice mask associated with a specific slice.  Only needed on
>>> + * pre-gen11 platforms that have multiple slices.
>>> + */
>>> +static void set_subslices(struct sseu_dev_info *sseu, int slice, u32 ss_mask)
>>>    {
>>> -	return hweight32(intel_sseu_get_subslices(sseu, slice));
>>> +	intel_sseu_ss_mask_t mask = {}, newbits = {};
>>> +	int offset = slice * sseu->max_subslices;
>>> +
>>> +	bitmap_set(mask.b, offset, sseu->max_subslices);
>>> +	bitmap_from_arr32(newbits.b, &ss_mask, 32);
>>> +	bitmap_shift_left(newbits.b, newbits.b, offset, I915_MAX_SS_FUSE_BITS);
>>> +	bitmap_replace(sseu->subslice_mask.b, sseu->subslice_mask.b,
>>> +		       newbits.b, mask.b, I915_MAX_SS_FUSE_BITS);
>>>    }
>>>    static int sseu_eu_idx(const struct sseu_dev_info *sseu, int slice,
>>> @@ -115,7 +108,7 @@ static u16 compute_eu_total(const struct sseu_dev_info *sseu)
>>>    	u16 i, total = 0;
>>>    	if (sseu->has_common_ss_eumask)
>>> -		return intel_sseu_subslices_per_slice(sseu, 0) *
>>> +		return bitmap_weight(sseu->subslice_mask.b, I915_MAX_SS_FUSE_BITS) *
>>>    			hweight16(sseu->eu_mask[0]);
>>>    	for (i = 0; i < ARRAY_SIZE(sseu->eu_mask); i++)
>>> @@ -155,11 +148,42 @@ int intel_sseu_copy_eumask_to_user(void __user *to,
>>>    	return copy_to_user(to, eu_mask, len);
>>>    }
>>> -static void gen11_compute_sseu_info(struct sseu_dev_info *sseu,
>>> -				    u32 g_ss_en, u32 c_ss_en, u16 eu_en)
>>> +/**
>>> + * intel_sseu_copy_ssmask_to_user - Copy subslice mask into a userspace buffer
>>> + * @to: Pointer to userspace buffer to copy to
>>> + * @sseu: SSEU structure containing subslice mask to copy
>>> + *
>>> + * Copies the subslice mask to a userspace buffer in the format expected by
>>> + * the query ioctl's topology queries.
>>> + *
>>> + * Returns the result of the copy_to_user() operation.
>>> + */
>>> +int intel_sseu_copy_ssmask_to_user(void __user *to,
>>> +				   const struct sseu_dev_info *sseu)
>>>    {
>>> -	u32 valid_ss_mask = GENMASK(sseu->max_subslices - 1, 0);
>>> +	u8 ss_mask[GEN_SS_MASK_SIZE] = {};
>>> +	int len = sseu->max_slices * sseu->ss_stride;
>>> +	int s, ss, i;
>>> +	for (s = 0; s < sseu->max_slices; s++) {
>>> +		for (ss = 0; ss < sseu->max_subslices; ss++) {
>>> +			i = s * sseu->ss_stride + ss;
>>> +
>>> +			if (!intel_sseu_has_subslice(sseu, s, ss))
>>> +				continue;
>>> +
>>> +			ss_mask[i / BITS_PER_BYTE] |= BIT(i % BITS_PER_BYTE);
>>> +		}
>>> +	}
>>> +
>>> +	return copy_to_user(to, ss_mask, len);
>>> +}
>>> +
>>> +static void gen11_compute_sseu_info(struct sseu_dev_info *sseu,
>>> +				    intel_sseu_ss_mask_t g_ss_en,
>>> +				    intel_sseu_ss_mask_t c_ss_en,
>>> +				    u16 eu_en)
>>> +{
>>>    	/* g_ss_en/c_ss_en represent entire subslice mask across all slices */
>>>    	GEM_BUG_ON(sseu->max_slices * sseu->max_subslices >
>>>    		   sizeof(g_ss_en) * BITS_PER_BYTE);
>>> @@ -174,12 +198,12 @@ static void gen11_compute_sseu_info(struct sseu_dev_info *sseu,
>>>    	 * enabled subslice count for the purposes of selecting subslices to
>>>    	 * use in a particular GEM context.
>>>    	 */
>>> -	intel_sseu_set_subslices(sseu, 0, sseu->compute_subslice_mask,
>>> -				 c_ss_en & valid_ss_mask);
>>> -	intel_sseu_set_subslices(sseu, 0, sseu->geometry_subslice_mask,
>>> -				 g_ss_en & valid_ss_mask);
>>> -	intel_sseu_set_subslices(sseu, 0, sseu->subslice_mask,
>>> -				 (g_ss_en | c_ss_en) & valid_ss_mask);
>>> +	bitmap_copy(sseu->compute_subslice_mask.b, c_ss_en.b, I915_MAX_SS_FUSE_BITS);
>>> +	bitmap_copy(sseu->geometry_subslice_mask.b, g_ss_en.b, I915_MAX_SS_FUSE_BITS);
>>> +	bitmap_or(sseu->subslice_mask.b,
>>> +		  sseu->compute_subslice_mask.b,
>>> +		  sseu->geometry_subslice_mask.b,
>>> +		  I915_MAX_SS_FUSE_BITS);
>>>    	sseu->has_common_ss_eumask = 1;
>>>    	sseu->eu_mask[0] = eu_en;
>>> @@ -191,7 +215,8 @@ static void xehp_sseu_info_init(struct intel_gt *gt)
>>>    {
>>>    	struct sseu_dev_info *sseu = &gt->info.sseu;
>>>    	struct intel_uncore *uncore = gt->uncore;
>>> -	u32 g_dss_en, c_dss_en = 0;
>>> +	intel_sseu_ss_mask_t g_dss_en = {}, c_dss_en = {};
>>> +	u32 val;
>>>    	u16 eu_en = 0;
>>>    	u8 eu_en_fuse;
>>>    	int eu;
>>> @@ -204,8 +229,11 @@ static void xehp_sseu_info_init(struct intel_gt *gt)
>>>    	 */
>>>    	intel_sseu_set_info(sseu, 1, 32, 16);
>>> -	g_dss_en = intel_uncore_read(uncore, GEN12_GT_GEOMETRY_DSS_ENABLE);
>>> -	c_dss_en = intel_uncore_read(uncore, GEN12_GT_COMPUTE_DSS_ENABLE);
>>> +	val = intel_uncore_read(uncore, GEN12_GT_GEOMETRY_DSS_ENABLE);
>>> +	bitmap_from_arr32(g_dss_en.b, &val, 32);
>>> +
>>> +	val = intel_uncore_read(uncore, GEN12_GT_COMPUTE_DSS_ENABLE);
>>> +	bitmap_from_arr32(c_dss_en.b, &val, 32);
>>>    	eu_en_fuse = intel_uncore_read(uncore, XEHP_EU_ENABLE) & XEHP_EU_ENA_MASK;
>>> @@ -220,7 +248,8 @@ static void gen12_sseu_info_init(struct intel_gt *gt)
>>>    {
>>>    	struct sseu_dev_info *sseu = &gt->info.sseu;
>>>    	struct intel_uncore *uncore = gt->uncore;
>>> -	u32 g_dss_en;
>>> +	intel_sseu_ss_mask_t g_dss_en = {}, empty_mask = {};
>>> +	u32 val;
>>>    	u16 eu_en = 0;
>>>    	u8 eu_en_fuse;
>>>    	u8 s_en;
>>> @@ -243,7 +272,8 @@ static void gen12_sseu_info_init(struct intel_gt *gt)
>>>    		drm_dbg(&gt->i915->drm, "Slice mask %#x is not the expected 0x1!\n",
>>>    			s_en);
>>> -	g_dss_en = intel_uncore_read(uncore, GEN12_GT_GEOMETRY_DSS_ENABLE);
>>> +	val = intel_uncore_read(uncore, GEN12_GT_GEOMETRY_DSS_ENABLE);
>>> +	bitmap_from_arr32(g_dss_en.b, &val, 32);
>>>    	/* one bit per pair of EUs */
>>>    	eu_en_fuse = ~(intel_uncore_read(uncore, GEN11_EU_DISABLE) &
>>> @@ -253,7 +283,7 @@ static void gen12_sseu_info_init(struct intel_gt *gt)
>>>    		if (eu_en_fuse & BIT(eu))
>>>    			eu_en |= BIT(eu * 2) | BIT(eu * 2 + 1);
>>> -	gen11_compute_sseu_info(sseu, g_dss_en, 0, eu_en);
>>> +	gen11_compute_sseu_info(sseu, g_dss_en, empty_mask, eu_en);
>>>    	/* TGL only supports slice-level power gating */
>>>    	sseu->has_slice_pg = 1;
>>> @@ -263,7 +293,8 @@ static void gen11_sseu_info_init(struct intel_gt *gt)
>>>    {
>>>    	struct sseu_dev_info *sseu = &gt->info.sseu;
>>>    	struct intel_uncore *uncore = gt->uncore;
>>> -	u32 ss_en;
>>> +	intel_sseu_ss_mask_t ss_en = {}, empty_mask = {};
>>> +	u32 val;
>>>    	u8 eu_en;
>>>    	u8 s_en;
>>> @@ -282,12 +313,13 @@ static void gen11_sseu_info_init(struct intel_gt *gt)
>>>    		drm_dbg(&gt->i915->drm, "Slice mask %#x is not the expected 0x1!\n",
>>>    			s_en);
>>> -	ss_en = ~intel_uncore_read(uncore, GEN11_GT_SUBSLICE_DISABLE);
>>> +	val = ~intel_uncore_read(uncore, GEN11_GT_SUBSLICE_DISABLE);
>>> +	bitmap_from_arr32(ss_en.b, &val, 32);
>>>    	eu_en = ~(intel_uncore_read(uncore, GEN11_EU_DISABLE) &
>>>    		  GEN11_EU_DIS_MASK);
>>> -	gen11_compute_sseu_info(sseu, ss_en, 0, eu_en);
>>> +	gen11_compute_sseu_info(sseu, ss_en, empty_mask, eu_en);
>>>    	/* ICL has no power gating restrictions. */
>>>    	sseu->has_slice_pg = 1;
>>> @@ -328,7 +360,7 @@ static void cherryview_sseu_info_init(struct intel_gt *gt)
>>>    		sseu_set_eus(sseu, 0, 1, ~disabled_mask);
>>>    	}
>>> -	intel_sseu_set_subslices(sseu, 0, sseu->subslice_mask, subslice_mask);
>>> +	set_subslices(sseu, 0, subslice_mask);
>>>    	sseu->eu_total = compute_eu_total(sseu);
>>> @@ -384,8 +416,7 @@ static void gen9_sseu_info_init(struct intel_gt *gt)
>>>    			/* skip disabled slice */
>>>    			continue;
>>> -		intel_sseu_set_subslices(sseu, s, sseu->subslice_mask,
>>> -					 subslice_mask);
>>> +		set_subslices(sseu, s, subslice_mask);
>>>    		eu_disable = intel_uncore_read(uncore, GEN9_EU_DISABLE(s));
>>>    		for (ss = 0; ss < sseu->max_subslices; ss++) {
>>> @@ -442,8 +473,8 @@ static void gen9_sseu_info_init(struct intel_gt *gt)
>>>    	sseu->has_eu_pg = sseu->eu_per_subslice > 2;
>>>    	if (IS_GEN9_LP(i915)) {
>>> -#define IS_SS_DISABLED(ss)	(!(sseu->subslice_mask[0] & BIT(ss)))
>>> -		info->has_pooled_eu = hweight8(sseu->subslice_mask[0]) == 3;
>>> +#define IS_SS_DISABLED(ss)	test_bit(ss, sseu->subslice_mask.b)
>>> +		info->has_pooled_eu = hweight8(sseu->subslice_mask.b[0]) == 3;
>>>    		sseu->min_eu_in_pool = 0;
>>>    		if (info->has_pooled_eu) {
>>> @@ -497,8 +528,7 @@ static void bdw_sseu_info_init(struct intel_gt *gt)
>>>    			/* skip disabled slice */
>>>    			continue;
>>> -		intel_sseu_set_subslices(sseu, s, sseu->subslice_mask,
>>> -					 subslice_mask);
>>> +		set_subslices(sseu, s, subslice_mask);
>>>    		for (ss = 0; ss < sseu->max_subslices; ss++) {
>>>    			u8 eu_disabled_mask;
>>> @@ -595,8 +625,7 @@ static void hsw_sseu_info_init(struct intel_gt *gt)
>>>    			    sseu->eu_per_subslice);
>>>    	for (s = 0; s < sseu->max_slices; s++) {
>>> -		intel_sseu_set_subslices(sseu, s, sseu->subslice_mask,
>>> -					 subslice_mask);
>>> +		set_subslices(sseu, s, subslice_mask);
>>>    		for (ss = 0; ss < sseu->max_subslices; ss++) {
>>>    			sseu_set_eus(sseu, s, ss,
>>> @@ -685,7 +714,7 @@ u32 intel_sseu_make_rpcs(struct intel_gt *gt,
>>>    	 */
>>>    	if (GRAPHICS_VER(i915) == 11 &&
>>>    	    slices == 1 &&
>>> -	    subslices > min_t(u8, 4, hweight8(sseu->subslice_mask[0]) / 2)) {
>>> +	    subslices > min_t(u8, 4, hweight8(sseu->subslice_mask.b[0]) / 2)) {
>>>    		GEM_BUG_ON(subslices & 1);
>>>    		subslice_pg = false;
>>> @@ -755,9 +784,11 @@ void intel_sseu_dump(const struct sseu_dev_info *sseu, struct drm_printer *p)
>>>    		   hweight8(sseu->slice_mask), sseu->slice_mask);
>>>    	drm_printf(p, "subslice total: %u\n", intel_sseu_subslice_total(sseu));
>>>    	for (s = 0; s < sseu->max_slices; s++) {
>>> -		drm_printf(p, "slice%d: %u subslices, mask=%08x\n",
>>> -			   s, intel_sseu_subslices_per_slice(sseu, s),
>>> -			   intel_sseu_get_subslices(sseu, s));
>>> +		intel_sseu_ss_mask_t ssmask = intel_sseu_get_subslices(sseu, s);
>>> +
>>> +		drm_printf(p, "slice%d: %u subslices, mask=%*pb\n",
>>> +			   s, bitmap_weight(ssmask.b, I915_MAX_SS_FUSE_BITS),
>>> +			   I915_MAX_SS_FUSE_BITS, ssmask.b);
>>>    	}
>>>    	drm_printf(p, "EU total: %u\n", sseu->eu_total);
>>>    	drm_printf(p, "EU per subslice: %u\n", sseu->eu_per_subslice);
>>> @@ -775,9 +806,11 @@ static void sseu_print_hsw_topology(const struct sseu_dev_info *sseu,
>>>    	int s, ss;
>>>    	for (s = 0; s < sseu->max_slices; s++) {
>>> -		drm_printf(p, "slice%d: %u subslice(s) (0x%08x):\n",
>>> -			   s, intel_sseu_subslices_per_slice(sseu, s),
>>> -			   intel_sseu_get_subslices(sseu, s));
>>> +		intel_sseu_ss_mask_t ssmask = intel_sseu_get_subslices(sseu, s);
>>> +
>>> +		drm_printf(p, "slice%d: %u subslice(s) (0x%*pb):\n",
>>> +			   s, bitmap_weight(ssmask.b, I915_MAX_SS_FUSE_BITS),
>>> +			   I915_MAX_SS_FUSE_BITS, ssmask.b);
>>>    		for (ss = 0; ss < sseu->max_subslices; ss++) {
>>>    			u16 enabled_eus = sseu_get_eus(sseu, s, ss);
>>> @@ -791,16 +824,14 @@ static void sseu_print_hsw_topology(const struct sseu_dev_info *sseu,
>>>    static void sseu_print_xehp_topology(const struct sseu_dev_info *sseu,
>>>    				     struct drm_printer *p)
>>>    {
>>> -	u32 g_dss_mask = sseu_get_geometry_subslices(sseu);
>>> -	u32 c_dss_mask = intel_sseu_get_compute_subslices(sseu);
>>>    	int dss;
>>>    	for (dss = 0; dss < sseu->max_subslices; dss++) {
>>>    		u16 enabled_eus = sseu_get_eus(sseu, 0, dss);
>>>    		drm_printf(p, "DSS_%02d: G:%3s C:%3s, %2u EUs (0x%04hx)\n", dss,
>>> -			   str_yes_no(g_dss_mask & BIT(dss)),
>>> -			   str_yes_no(c_dss_mask & BIT(dss)),
>>> +			   str_yes_no(test_bit(dss, sseu->geometry_subslice_mask.b)),
>>> +			   str_yes_no(test_bit(dss, sseu->compute_subslice_mask.b)),
>>>    			   hweight16(enabled_eus), enabled_eus);
>>>    	}
>>>    }
>>> @@ -818,20 +849,24 @@ void intel_sseu_print_topology(struct drm_i915_private *i915,
>>>    	}
>>>    }
>>> -u16 intel_slicemask_from_dssmask(u64 dss_mask, int dss_per_slice)
>>> +u16 intel_slicemask_from_dssmask(intel_sseu_ss_mask_t dss_mask,
>>> +				 int dss_per_slice)
>>>    {
>>> +	intel_sseu_ss_mask_t per_slice_mask = {};
>>>    	u16 slice_mask = 0;
>>>    	int i;
>>> -	WARN_ON(sizeof(dss_mask) * 8 / dss_per_slice > 8 * sizeof(slice_mask));
>>> +	WARN_ON(DIV_ROUND_UP(I915_MAX_SS_FUSE_BITS, dss_per_slice) >
>>> +		8 * sizeof(slice_mask));
>>> -	for (i = 0; dss_mask; i++) {
>>> -		if (dss_mask & GENMASK(dss_per_slice - 1, 0))
>>> +	bitmap_fill(per_slice_mask.b, dss_per_slice);
>>> +	for (i = 0; !bitmap_empty(dss_mask.b, I915_MAX_SS_FUSE_BITS); i++) {
>>> +		if (bitmap_intersects(dss_mask.b, per_slice_mask.b, dss_per_slice))
>>>    			slice_mask |= BIT(i);
>>> -		dss_mask >>= dss_per_slice;
>>> +		bitmap_shift_right(dss_mask.b, dss_mask.b, dss_per_slice,
>>> +				   I915_MAX_SS_FUSE_BITS);
>>>    	}
>>>    	return slice_mask;
>>>    }
>>> -
>>> diff --git a/drivers/gpu/drm/i915/gt/intel_sseu.h b/drivers/gpu/drm/i915/gt/intel_sseu.h
>>> index 106726a2244e..455f085093ae 100644
>>> --- a/drivers/gpu/drm/i915/gt/intel_sseu.h
>>> +++ b/drivers/gpu/drm/i915/gt/intel_sseu.h
>>> @@ -52,11 +52,22 @@ struct drm_printer;
>>>    #define GEN_MAX_GSLICES		(GEN_MAX_DSS / GEN_DSS_PER_GSLICE)
>>>    #define GEN_MAX_CSLICES		(GEN_MAX_DSS / GEN_DSS_PER_CSLICE)
>>> +/*
>>> + * Maximum number of 32-bit registers used by hardware to express the
>>> + * enabled/disabled subslices.
>>> + */
>>> +#define I915_MAX_SS_FUSE_REGS	1
>>> +#define I915_MAX_SS_FUSE_BITS	(I915_MAX_SS_FUSE_REGS * 32)
>>> +
>>> +typedef struct {
>>> +	unsigned long b[BITS_TO_LONGS(I915_MAX_SS_FUSE_BITS)];
>>> +} intel_sseu_ss_mask_t;
>>> +
>>>    struct sseu_dev_info {
>>>    	u8 slice_mask;
>>> -	u8 subslice_mask[GEN_SS_MASK_SIZE];
>>> -	u8 geometry_subslice_mask[GEN_SS_MASK_SIZE];
>>> -	u8 compute_subslice_mask[GEN_SS_MASK_SIZE];
>>> +	intel_sseu_ss_mask_t subslice_mask;
>>> +	intel_sseu_ss_mask_t geometry_subslice_mask;
>>> +	intel_sseu_ss_mask_t compute_subslice_mask;
>>>    	/*
>>>    	 * EU masks.  Use has_common_ss_eumask to determine how the field
>>> @@ -107,7 +118,7 @@ intel_sseu_from_device_info(const struct sseu_dev_info *sseu)
>>>    {
>>>    	struct intel_sseu value = {
>>>    		.slice_mask = sseu->slice_mask,
>>> -		.subslice_mask = sseu->subslice_mask[0],
>>> +		.subslice_mask = sseu->subslice_mask.b[0],
>>>    		.min_eus_per_subslice = sseu->max_eus_per_subslice,
>>>    		.max_eus_per_subslice = sseu->max_eus_per_subslice,
>>>    	};
>>> @@ -119,18 +130,8 @@ static inline bool
>>>    intel_sseu_has_subslice(const struct sseu_dev_info *sseu, int slice,
>>>    			int subslice)
>>>    {
>>> -	u8 mask;
>>> -	int ss_idx = subslice / BITS_PER_BYTE;
>>> -
>>> -	if (slice >= sseu->max_slices ||
>>> -	    subslice >= sseu->max_subslices)
>>> -		return false;
>>> -
>>> -	GEM_BUG_ON(ss_idx >= sseu->ss_stride);
>>> -
>>> -	mask = sseu->subslice_mask[slice * sseu->ss_stride + ss_idx];
>>> -
>>> -	return mask & BIT(subslice % BITS_PER_BYTE);
>>> +	return test_bit(slice * sseu->ss_stride + subslice,
>>> +			sseu->subslice_mask.b);
>>>    }
>>>    void intel_sseu_set_info(struct sseu_dev_info *sseu, u8 max_slices,
>>> @@ -139,15 +140,14 @@ void intel_sseu_set_info(struct sseu_dev_info *sseu, u8 max_slices,
>>>    unsigned int
>>>    intel_sseu_subslice_total(const struct sseu_dev_info *sseu);
>>> -unsigned int
>>> -intel_sseu_subslices_per_slice(const struct sseu_dev_info *sseu, u8 slice);
>>> +intel_sseu_ss_mask_t
>>> +intel_sseu_get_subslices(const struct sseu_dev_info *sseu, u8 slice);
>>> -u32 intel_sseu_get_subslices(const struct sseu_dev_info *sseu, u8 slice);
>>> -
>>> -u32 intel_sseu_get_compute_subslices(const struct sseu_dev_info *sseu);
>>> +intel_sseu_ss_mask_t
>>> +intel_sseu_get_compute_subslices(const struct sseu_dev_info *sseu);
>>>    void intel_sseu_set_subslices(struct sseu_dev_info *sseu, int slice,
>>> -			      u8 *subslice_mask, u32 ss_mask);
>>> +			      u32 ss_mask);
>>>    void intel_sseu_info_init(struct intel_gt *gt);
>>> @@ -159,9 +159,11 @@ void intel_sseu_print_topology(struct drm_i915_private *i915,
>>>    			       const struct sseu_dev_info *sseu,
>>>    			       struct drm_printer *p);
>>> -u16 intel_slicemask_from_dssmask(u64 dss_mask, int dss_per_slice);
>>> +u16 intel_slicemask_from_dssmask(intel_sseu_ss_mask_t dss_mask, int dss_per_slice);
>>>    int intel_sseu_copy_eumask_to_user(void __user *to,
>>>    				   const struct sseu_dev_info *sseu);
>>> +int intel_sseu_copy_ssmask_to_user(void __user *to,
>>> +				   const struct sseu_dev_info *sseu);
>>>    #endif /* __INTEL_SSEU_H__ */
>>> diff --git a/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c b/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c
>>> index 2d5d011e01db..1f77bd52a3a6 100644
>>> --- a/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c
>>> +++ b/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c
>>> @@ -4,6 +4,7 @@
>>>     * Copyright © 2020 Intel Corporation
>>>     */
>>> +#include <linux/bitmap.h>
>>>    #include <linux/string_helpers.h>
>>>    #include "i915_drv.h"
>>> @@ -12,11 +13,15 @@
>>>    #include "intel_sseu_debugfs.h"
>>>    static void sseu_copy_subslices(const struct sseu_dev_info *sseu,
>>> -				int slice, u8 *to_mask)
>>> +				int slice,
>>> +				intel_sseu_ss_mask_t *to_mask)
>>>    {
>>> -	int offset = slice * sseu->ss_stride;
>>> +	int offset = slice * sseu->max_subslices;
>>> -	memcpy(&to_mask[offset], &sseu->subslice_mask[offset], sseu->ss_stride);
>>> +	bitmap_fill(to_mask->b, sseu->max_subslices);
>>> +	bitmap_shift_left(to_mask->b, to_mask->b, offset, I915_MAX_SS_FUSE_BITS);
>>> +	bitmap_and(to_mask->b, to_mask->b, sseu->subslice_mask.b, I915_MAX_SS_FUSE_BITS);
>>> +	bitmap_shift_right(to_mask->b, to_mask->b, offset, I915_MAX_SS_FUSE_BITS);
>>>    }
>>>    static void cherryview_sseu_device_status(struct intel_gt *gt,
>>> @@ -41,7 +46,7 @@ static void cherryview_sseu_device_status(struct intel_gt *gt,
>>>    			continue;
>>>    		sseu->slice_mask = BIT(0);
>>> -		sseu->subslice_mask[0] |= BIT(ss);
>>> +		set_bit(0, sseu->subslice_mask.b);
>>>    		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) +
>>> @@ -92,7 +97,7 @@ static void gen11_sseu_device_status(struct intel_gt *gt,
>>>    			continue;
>>>    		sseu->slice_mask |= BIT(s);
>>> -		sseu_copy_subslices(&info->sseu, s, sseu->subslice_mask);
>>> +		sseu_copy_subslices(&info->sseu, s, &sseu->subslice_mask);
>>>    		for (ss = 0; ss < info->sseu.max_subslices; ss++) {
>>>    			unsigned int eu_cnt;
>>> @@ -148,20 +153,17 @@ static void gen9_sseu_device_status(struct intel_gt *gt,
>>>    		if (IS_GEN9_BC(gt->i915))
>>>    			sseu_copy_subslices(&info->sseu, s,
>>> -					    sseu->subslice_mask);
>>> +					    &sseu->subslice_mask);
>>>    		for (ss = 0; ss < info->sseu.max_subslices; ss++) {
>>>    			unsigned int eu_cnt;
>>> -			u8 ss_idx = s * info->sseu.ss_stride +
>>> -				    ss / BITS_PER_BYTE;
>>>    			if (IS_GEN9_LP(gt->i915)) {
>>>    				if (!(s_reg[s] & (GEN9_PGCTL_SS_ACK(ss))))
>>>    					/* skip disabled subslice */
>>>    					continue;
>>> -				sseu->subslice_mask[ss_idx] |=
>>> -					BIT(ss % BITS_PER_BYTE);
>>> +				set_bit(ss, sseu->subslice_mask.b);
>>>    			}
>>>    			eu_cnt = eu_reg[2 * s + ss / 2] & eu_mask[ss % 2];
>>> @@ -189,7 +191,7 @@ static void bdw_sseu_device_status(struct intel_gt *gt,
>>>    		sseu->eu_per_subslice = info->sseu.eu_per_subslice;
>>>    		for (s = 0; s < fls(sseu->slice_mask); s++)
>>>    			sseu_copy_subslices(&info->sseu, s,
>>> -					    sseu->subslice_mask);
>>> +					    &sseu->subslice_mask);
>>>    		sseu->eu_total = sseu->eu_per_subslice *
>>>    				 intel_sseu_subslice_total(sseu);
>>> @@ -217,8 +219,10 @@ static void i915_print_sseu_info(struct seq_file *m,
>>>    	seq_printf(m, "  %s Subslice Total: %u\n", type,
>>>    		   intel_sseu_subslice_total(sseu));
>>>    	for (s = 0; s < fls(sseu->slice_mask); s++) {
>>> +		intel_sseu_ss_mask_t ssmask = intel_sseu_get_subslices(sseu, s);
>>> +
>>>    		seq_printf(m, "  %s Slice%i subslices: %u\n", type,
>>> -			   s, intel_sseu_subslices_per_slice(sseu, s));
>>> +			   s, bitmap_weight(ssmask.b, I915_MAX_SS_FUSE_BITS));
>>>    	}
>>>    	seq_printf(m, "  %s EU Total: %u\n", type,
>>>    		   sseu->eu_total);
>>> diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c
>>> index a05c4b99b3fb..5db492072f99 100644
>>> --- a/drivers/gpu/drm/i915/gt/intel_workarounds.c
>>> +++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c
>>> @@ -931,6 +931,7 @@ static void
>>>    gen9_wa_init_mcr(struct drm_i915_private *i915, struct i915_wa_list *wal)
>>>    {
>>>    	const struct sseu_dev_info *sseu = &to_gt(i915)->info.sseu;
>>> +	intel_sseu_ss_mask_t ssmask;
>>>    	unsigned int slice, subslice;
>>>    	u32 mcr, mcr_mask;
>>> @@ -948,9 +949,9 @@ gen9_wa_init_mcr(struct drm_i915_private *i915, struct i915_wa_list *wal)
>>>    	 * on s/ss combo, the read should be done with read_subslice_reg.
>>>    	 */
>>>    	slice = ffs(sseu->slice_mask) - 1;
>>> -	GEM_BUG_ON(slice >= ARRAY_SIZE(sseu->subslice_mask));
>>> -	subslice = ffs(intel_sseu_get_subslices(sseu, slice));
>>> -	GEM_BUG_ON(!subslice);
>>> +	ssmask = intel_sseu_get_subslices(sseu, slice);
>>> +	subslice = find_first_bit(ssmask.b, I915_MAX_SS_FUSE_BITS);
>>> +	GEM_BUG_ON(subslice == I915_MAX_SS_FUSE_BITS);
>>>    	subslice--;
>>>    	/*
>>> @@ -1087,11 +1088,10 @@ static void
>>>    icl_wa_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
>>>    {
>>>    	const struct sseu_dev_info *sseu = &gt->info.sseu;
>>> -	unsigned int slice, subslice;
>>> +	unsigned int subslice;
>>>    	GEM_BUG_ON(GRAPHICS_VER(gt->i915) < 11);
>>>    	GEM_BUG_ON(hweight8(sseu->slice_mask) > 1);
>>> -	slice = 0;
>>>    	/*
>>>    	 * Although a platform may have subslices, we need to always steer
>>> @@ -1102,7 +1102,7 @@ icl_wa_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
>>>    	 * one of the higher subslices, we run the risk of reading back 0's or
>>>    	 * random garbage.
>>>    	 */
>>> -	subslice = __ffs(intel_sseu_get_subslices(sseu, slice));
>>> +	subslice = find_first_bit(sseu->subslice_mask.b, I915_MAX_SS_FUSE_BITS);
>>>    	/*
>>>    	 * If the subslice we picked above also steers us to a valid L3 bank,
>>> @@ -1112,7 +1112,7 @@ icl_wa_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
>>>    	if (gt->info.l3bank_mask & BIT(subslice))
>>>    		gt->steering_table[L3BANK] = NULL;
>>> -	__add_mcr_wa(gt, wal, slice, subslice);
>>> +	__add_mcr_wa(gt, wal, 0, subslice);
>>>    }
>>>    static void
>>> @@ -1120,7 +1120,6 @@ xehp_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
>>>    {
>>>    	const struct sseu_dev_info *sseu = &gt->info.sseu;
>>>    	unsigned long slice, subslice = 0, slice_mask = 0;
>>> -	u64 dss_mask = 0;
>>>    	u32 lncf_mask = 0;
>>>    	int i;
>>> @@ -1151,8 +1150,8 @@ xehp_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
>>>    	 */
>>>    	/* Find the potential gslice candidates */
>>> -	dss_mask = intel_sseu_get_subslices(sseu, 0);
>>> -	slice_mask = intel_slicemask_from_dssmask(dss_mask, GEN_DSS_PER_GSLICE);
>>> +	slice_mask = intel_slicemask_from_dssmask(sseu->subslice_mask,
>>> +						  GEN_DSS_PER_GSLICE);
>>>    	/*
>>>    	 * Find the potential LNCF candidates.  Either LNCF within a valid
>>> @@ -1177,9 +1176,9 @@ xehp_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
>>>    	}
>>>    	slice = __ffs(slice_mask);
>>> -	subslice = __ffs(dss_mask >> (slice * GEN_DSS_PER_GSLICE));
>>> +	subslice = find_next_bit(sseu->subslice_mask.b, I915_MAX_SS_FUSE_BITS,
>>> +				 slice * GEN_DSS_PER_GSLICE);
>>>    	WARN_ON(subslice > GEN_DSS_PER_GSLICE);
>>> -	WARN_ON(dss_mask >> (slice * GEN_DSS_PER_GSLICE) == 0);
>>>    	__add_mcr_wa(gt, wal, slice, subslice);
>>> @@ -2012,9 +2011,8 @@ engine_fake_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
>>>    static bool needs_wa_1308578152(struct intel_engine_cs *engine)
>>>    {
>>> -	u64 dss_mask = intel_sseu_get_subslices(&engine->gt->info.sseu, 0);
>>> -
>>> -	return (dss_mask & GENMASK(GEN_DSS_PER_GSLICE - 1, 0)) == 0;
>>> +	return find_first_bit(engine->gt->info.sseu.subslice_mask.b,
>>> +			      I915_MAX_SS_FUSE_BITS) >= GEN_DSS_PER_GSLICE;
>>>    }
>>>    static void
>>> diff --git a/drivers/gpu/drm/i915/i915_getparam.c b/drivers/gpu/drm/i915/i915_getparam.c
>>> index ac9767c56619..349d496d164a 100644
>>> --- a/drivers/gpu/drm/i915/i915_getparam.c
>>> +++ b/drivers/gpu/drm/i915/i915_getparam.c
>>> @@ -162,7 +162,7 @@ int i915_getparam_ioctl(struct drm_device *dev, void *data,
>>>    			return -EINVAL;
>>>    		/* Only copy bits from the first slice */
>>> -		memcpy(&value, sseu->subslice_mask,
>>> +		memcpy(&value, sseu->subslice_mask.b,
>>>    		       min(sseu->ss_stride, (u8)sizeof(value)));
>>>    		if (!value)
>>>    			return -ENODEV;
>>> diff --git a/drivers/gpu/drm/i915/i915_query.c b/drivers/gpu/drm/i915/i915_query.c
>>> index 16f43bf32a05..9afa6d1eaf95 100644
>>> --- a/drivers/gpu/drm/i915/i915_query.c
>>> +++ b/drivers/gpu/drm/i915/i915_query.c
>>> @@ -31,7 +31,7 @@ static int copy_query_item(void *query_hdr, size_t query_sz,
>>>    static int fill_topology_info(const struct sseu_dev_info *sseu,
>>>    			      struct drm_i915_query_item *query_item,
>>> -			      const u8 *subslice_mask)
>>> +			      intel_sseu_ss_mask_t subslice_mask)
>>>    {
>>>    	struct drm_i915_query_topology_info topo;
>>>    	u32 slice_length, subslice_length, eu_length, total_length;
>>> @@ -71,9 +71,9 @@ static int fill_topology_info(const struct sseu_dev_info *sseu,
>>>    			 &sseu->slice_mask, slice_length))
>>>    		return -EFAULT;
>>> -	if (copy_to_user(u64_to_user_ptr(query_item->data_ptr +
>>> -					 sizeof(topo) + slice_length),
>>> -			 subslice_mask, subslice_length))
>>> +	if (intel_sseu_copy_ssmask_to_user(u64_to_user_ptr(query_item->data_ptr +
>>> +							   sizeof(topo) + slice_length),
>>> +					   sseu))
>>>    		return -EFAULT;
>>>    	if (intel_sseu_copy_eumask_to_user(u64_to_user_ptr(query_item->data_ptr +
> 

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

* Re: [Intel-gfx] [PATCH 5/5] drm/i915/sseu: Disassociate internal subslice mask representation from uapi
@ 2022-05-09 14:18         ` Tvrtko Ursulin
  0 siblings, 0 replies; 27+ messages in thread
From: Tvrtko Ursulin @ 2022-05-09 14:18 UTC (permalink / raw)
  To: Matt Roper; +Cc: intel-gfx, dri-devel


On 07/05/2022 00:34, Matt Roper wrote:
> On Thu, Apr 28, 2022 at 01:18:42PM +0100, Tvrtko Ursulin wrote:
>>
>> Hi,
>>
>> On 28/04/2022 00:07, Matt Roper wrote:
>>> Rather than storing subslice masks internally as u8[] (inside the sseu
>>> structure) and u32 (everywhere else), let's move over to using an
>>> intel_sseu_ss_mask_t typedef compatible with the operations in
>>> linux/bitmap.h.  We're soon going to start adding code for a new
>>> platform where subslice masks are spread across two 32-bit registers
>>> (requiring 64 bits to represent), and we expect future platforms will
>>> likely take this even farther, requiring bitmask storage larger than a
>>> simple u64 can hold.
>>
>> I won't have time to look into this in a detailed way for a few days. Until then a couple questions comments only.
>>
>> First, out of curiousity, were you able to end up with less code after your series? With my bitmap conversion I think actually ended up with couple KB smaller text which was a good sign eliminating the internal layout complications was a good approach.
> 
> Yeah, looks like I did:
> 
>     $ size i915.ko.orig i915.ko
>        text    data     bss     dec     hex filename
>     3479050  132498    6760 3618308  373604 i915.ko.orig
>     3476552  132466    6760 3615778  372c22 i915.ko
> 
>>
>> For your series I am not convinced by sseu->has_common_ss_eumask. Why the duality, just to save a few u32 at runtime?
> 
> With this flag, eu_mask is an array of GEN_MAX_HSW_SLICES *
> GEN_MAX_SS_PER_HSW_SLICE (i.e., 3*6 = 18).  If we store the replicated
> EU masks, then we'll have 64 u16's on PVC (where we have a DSS mask
> spread across two registers) and 96 u16's on a future platform that
> spreads the mask across three fuse registers.  18 -> 96 (or possibly
> even more farther in the future).  I think we've eliminated all of the
> stack allocations of sseu structures now, so it probably isn't as
> important as it used to be though; I can drop it if you think the size
> savings aren't worth the extra complexity.
> 
>>
>> I am also not convinced with leaving the eu_mask and subslice_mask
>> being manually indexed with stride, calculcated by the driver. In my
>> approach I simply went with multi-dimensional arrays which I think
>> ends up with simpler code.
> 
> So something like
> 
>          enum {
>                  u16 hsw[GEN_MAX_HSW_SLICES][GEN_MAX_SS_PER_HSW_SLICE];
>                  u16 xehp[GEN_MAX_DSS];
>          } eu_mask;
> 
> ?  Or should we just skip the enum and live with allocating three times
> as much space as the largest Xe_HP platform needs?

s/enum/union/ right? This is an excellent idea - further simplifies the 
code by expressing the reality of how data is organized and every 
platform just touches it's own data in the most logical and 
straightforward manner. If I am not missing some gotcha then yes please. 
(Like I am not sure how generalisation to bitmap will work together with 
union, from common callers, if there are such.)

Regards,

Tvrtko

>> For all bitmap API call sites and *pb printk format sites, I suggest not hard-coding the widths from SSEU defines by querying the type itsef via wrappers. (See my BITMAP_BITS macro and helpers which wrap it for fields.)
>>
>> Ie instead:
>>
>> bitmap_shift_left(to_mask->b, to_mask->b, offset, I915_MAX_SS_FUSE_BITS);
>>
>> I suggest:
>>
>> bitmap_zero(slices.b, BITMAP_BITS(slices.b));
>>
>> Also, all accesses to the bitmap type from outside intel_sse*.c|h should use intel_sseu wrappers and not embed knowledge of the typedef (that it has an member named .b etc).
>>
>> And finally I would also use the opportunity to clean up the pointless u8 types for counts and such since I think they just result in worse code generation.
>>
>> You can of course counter with what you did not like in my attempt. :) I know I did not finish the wrappers and possibly made an overkill by converting the slice mask to bitmap.
> 
> These suggestions all make sense.  I'll work on incorporating them into
> the next version. >
> 
> Matt
> 
>>
>> Regards,
>>
>> Tvrtko
>>> Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
>>> ---
>>>    drivers/gpu/drm/i915/gem/i915_gem_context.c  |   4 +-
>>>    drivers/gpu/drm/i915/gt/intel_engine_cs.c    |   2 +-
>>>    drivers/gpu/drm/i915/gt/intel_gt.c           |  14 +-
>>>    drivers/gpu/drm/i915/gt/intel_sseu.c         | 197 +++++++++++--------
>>>    drivers/gpu/drm/i915/gt/intel_sseu.h         |  48 ++---
>>>    drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c |  28 +--
>>>    drivers/gpu/drm/i915/gt/intel_workarounds.c  |  28 ++-
>>>    drivers/gpu/drm/i915/i915_getparam.c         |   2 +-
>>>    drivers/gpu/drm/i915/i915_query.c            |   8 +-
>>>    9 files changed, 183 insertions(+), 148 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c
>>> index ab4c5ab28e4d..ea012ee3a8de 100644
>>> --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c
>>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c
>>> @@ -1901,7 +1901,7 @@ i915_gem_user_to_context_sseu(struct intel_gt *gt,
>>>    	if (user->slice_mask & ~device->slice_mask)
>>>    		return -EINVAL;
>>> -	if (user->subslice_mask & ~device->subslice_mask[0])
>>> +	if (user->subslice_mask & ~device->subslice_mask.b[0])
>>>    		return -EINVAL;
>>>    	if (user->max_eus_per_subslice > device->max_eus_per_subslice)
>>> @@ -1915,7 +1915,7 @@ i915_gem_user_to_context_sseu(struct intel_gt *gt,
>>>    	/* Part specific restrictions. */
>>>    	if (GRAPHICS_VER(i915) == 11) {
>>>    		unsigned int hw_s = hweight8(device->slice_mask);
>>> -		unsigned int hw_ss_per_s = hweight8(device->subslice_mask[0]);
>>> +		unsigned int hw_ss_per_s = hweight8(device->subslice_mask.b[0]);
>>>    		unsigned int req_s = hweight8(context->slice_mask);
>>>    		unsigned int req_ss = hweight8(context->subslice_mask);
>>> diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
>>> index 14c6ddbbfde8..39c09963b3c7 100644
>>> --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c
>>> +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
>>> @@ -610,7 +610,7 @@ static void engine_mask_apply_compute_fuses(struct intel_gt *gt)
>>>    	if (GRAPHICS_VER_FULL(i915) < IP_VER(12, 50))
>>>    		return;
>>> -	ccs_mask = intel_slicemask_from_dssmask(intel_sseu_get_compute_subslices(&info->sseu),
>>> +	ccs_mask = intel_slicemask_from_dssmask(info->sseu.compute_subslice_mask,
>>>    						ss_per_ccs);
>>>    	/*
>>>    	 * If all DSS in a quadrant are fused off, the corresponding CCS
>>> diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c
>>> index 92394f13b42f..cc03512d59ba 100644
>>> --- a/drivers/gpu/drm/i915/gt/intel_gt.c
>>> +++ b/drivers/gpu/drm/i915/gt/intel_gt.c
>>> @@ -133,13 +133,6 @@ static const struct intel_mmio_range dg2_lncf_steering_table[] = {
>>>    	{},
>>>    };
>>> -static u16 slicemask(struct intel_gt *gt, int count)
>>> -{
>>> -	u64 dss_mask = intel_sseu_get_subslices(&gt->info.sseu, 0);
>>> -
>>> -	return intel_slicemask_from_dssmask(dss_mask, count);
>>> -}
>>> -
>>>    int intel_gt_init_mmio(struct intel_gt *gt)
>>>    {
>>>    	struct drm_i915_private *i915 = gt->i915;
>>> @@ -153,11 +146,14 @@ int intel_gt_init_mmio(struct intel_gt *gt)
>>>    	 * An mslice is unavailable only if both the meml3 for the slice is
>>>    	 * disabled *and* all of the DSS in the slice (quadrant) are disabled.
>>>    	 */
>>> -	if (HAS_MSLICES(i915))
>>> +	if (HAS_MSLICES(i915)) {
>>>    		gt->info.mslice_mask =
>>> -			slicemask(gt, GEN_DSS_PER_MSLICE) |
>>> +			intel_slicemask_from_dssmask(gt->info.sseu.subslice_mask,
>>> +						     GEN_DSS_PER_MSLICE);
>>> +		gt->info.mslice_mask |=
>>>    			(intel_uncore_read(gt->uncore, GEN10_MIRROR_FUSE3) &
>>>    			 GEN12_MEML3_EN_MASK);
>>> +	}
>>>    	if (IS_DG2(i915)) {
>>>    		gt->steering_table[MSLICE] = xehpsdv_mslice_steering_table;
>>> diff --git a/drivers/gpu/drm/i915/gt/intel_sseu.c b/drivers/gpu/drm/i915/gt/intel_sseu.c
>>> index f7ff6a9f67b0..466505d6bd18 100644
>>> --- a/drivers/gpu/drm/i915/gt/intel_sseu.c
>>> +++ b/drivers/gpu/drm/i915/gt/intel_sseu.c
>>> @@ -28,56 +28,49 @@ void intel_sseu_set_info(struct sseu_dev_info *sseu, u8 max_slices,
>>>    unsigned int
>>>    intel_sseu_subslice_total(const struct sseu_dev_info *sseu)
>>>    {
>>> -	unsigned int i, total = 0;
>>> -
>>> -	for (i = 0; i < ARRAY_SIZE(sseu->subslice_mask); i++)
>>> -		total += hweight8(sseu->subslice_mask[i]);
>>> -
>>> -	return total;
>>> +	return bitmap_weight(sseu->subslice_mask.b, I915_MAX_SS_FUSE_BITS);
>>>    }
>>> -static u32
>>> -sseu_get_subslices(const struct sseu_dev_info *sseu,
>>> -		   const u8 *subslice_mask, u8 slice)
>>> +static intel_sseu_ss_mask_t
>>> +get_ss_mask_for_slice(const struct sseu_dev_info *sseu,
>>> +		      intel_sseu_ss_mask_t all_ss,
>>> +		      int slice)
>>>    {
>>> -	int i, offset = slice * sseu->ss_stride;
>>> -	u32 mask = 0;
>>> +	intel_sseu_ss_mask_t mask = {}, slice_ss = {};
>>> +	int offset = slice * sseu->max_subslices;
>>>    	GEM_BUG_ON(slice >= sseu->max_slices);
>>> -	for (i = 0; i < sseu->ss_stride; i++)
>>> -		mask |= (u32)subslice_mask[offset + i] << i * BITS_PER_BYTE;
>>> +	if (sseu->max_slices == 1)
>>> +		return all_ss;
>>> -	return mask;
>>> -}
>>> +	bitmap_set(mask.b, offset, sseu->max_subslices);
>>> +	bitmap_and(slice_ss.b, all_ss.b, mask.b, I915_MAX_SS_FUSE_BITS);
>>> +	bitmap_shift_right(slice_ss.b, slice_ss.b, offset, I915_MAX_SS_FUSE_BITS);
>>> -u32 intel_sseu_get_subslices(const struct sseu_dev_info *sseu, u8 slice)
>>> -{
>>> -	return sseu_get_subslices(sseu, sseu->subslice_mask, slice);
>>> +	return slice_ss;
>>>    }
>>> -static u32 sseu_get_geometry_subslices(const struct sseu_dev_info *sseu)
>>> +intel_sseu_ss_mask_t
>>> +intel_sseu_get_subslices(const struct sseu_dev_info *sseu, u8 slice)
>>>    {
>>> -	return sseu_get_subslices(sseu, sseu->geometry_subslice_mask, 0);
>>> +	return get_ss_mask_for_slice(sseu, sseu->subslice_mask, slice);
>>>    }
>>> -u32 intel_sseu_get_compute_subslices(const struct sseu_dev_info *sseu)
>>> -{
>>> -	return sseu_get_subslices(sseu, sseu->compute_subslice_mask, 0);
>>> -}
>>> -
>>> -void intel_sseu_set_subslices(struct sseu_dev_info *sseu, int slice,
>>> -			      u8 *subslice_mask, u32 ss_mask)
>>> -{
>>> -	int offset = slice * sseu->ss_stride;
>>> -
>>> -	memcpy(&subslice_mask[offset], &ss_mask, sseu->ss_stride);
>>> -}
>>> -
>>> -unsigned int
>>> -intel_sseu_subslices_per_slice(const struct sseu_dev_info *sseu, u8 slice)
>>> +/*
>>> + * Set the subslice mask associated with a specific slice.  Only needed on
>>> + * pre-gen11 platforms that have multiple slices.
>>> + */
>>> +static void set_subslices(struct sseu_dev_info *sseu, int slice, u32 ss_mask)
>>>    {
>>> -	return hweight32(intel_sseu_get_subslices(sseu, slice));
>>> +	intel_sseu_ss_mask_t mask = {}, newbits = {};
>>> +	int offset = slice * sseu->max_subslices;
>>> +
>>> +	bitmap_set(mask.b, offset, sseu->max_subslices);
>>> +	bitmap_from_arr32(newbits.b, &ss_mask, 32);
>>> +	bitmap_shift_left(newbits.b, newbits.b, offset, I915_MAX_SS_FUSE_BITS);
>>> +	bitmap_replace(sseu->subslice_mask.b, sseu->subslice_mask.b,
>>> +		       newbits.b, mask.b, I915_MAX_SS_FUSE_BITS);
>>>    }
>>>    static int sseu_eu_idx(const struct sseu_dev_info *sseu, int slice,
>>> @@ -115,7 +108,7 @@ static u16 compute_eu_total(const struct sseu_dev_info *sseu)
>>>    	u16 i, total = 0;
>>>    	if (sseu->has_common_ss_eumask)
>>> -		return intel_sseu_subslices_per_slice(sseu, 0) *
>>> +		return bitmap_weight(sseu->subslice_mask.b, I915_MAX_SS_FUSE_BITS) *
>>>    			hweight16(sseu->eu_mask[0]);
>>>    	for (i = 0; i < ARRAY_SIZE(sseu->eu_mask); i++)
>>> @@ -155,11 +148,42 @@ int intel_sseu_copy_eumask_to_user(void __user *to,
>>>    	return copy_to_user(to, eu_mask, len);
>>>    }
>>> -static void gen11_compute_sseu_info(struct sseu_dev_info *sseu,
>>> -				    u32 g_ss_en, u32 c_ss_en, u16 eu_en)
>>> +/**
>>> + * intel_sseu_copy_ssmask_to_user - Copy subslice mask into a userspace buffer
>>> + * @to: Pointer to userspace buffer to copy to
>>> + * @sseu: SSEU structure containing subslice mask to copy
>>> + *
>>> + * Copies the subslice mask to a userspace buffer in the format expected by
>>> + * the query ioctl's topology queries.
>>> + *
>>> + * Returns the result of the copy_to_user() operation.
>>> + */
>>> +int intel_sseu_copy_ssmask_to_user(void __user *to,
>>> +				   const struct sseu_dev_info *sseu)
>>>    {
>>> -	u32 valid_ss_mask = GENMASK(sseu->max_subslices - 1, 0);
>>> +	u8 ss_mask[GEN_SS_MASK_SIZE] = {};
>>> +	int len = sseu->max_slices * sseu->ss_stride;
>>> +	int s, ss, i;
>>> +	for (s = 0; s < sseu->max_slices; s++) {
>>> +		for (ss = 0; ss < sseu->max_subslices; ss++) {
>>> +			i = s * sseu->ss_stride + ss;
>>> +
>>> +			if (!intel_sseu_has_subslice(sseu, s, ss))
>>> +				continue;
>>> +
>>> +			ss_mask[i / BITS_PER_BYTE] |= BIT(i % BITS_PER_BYTE);
>>> +		}
>>> +	}
>>> +
>>> +	return copy_to_user(to, ss_mask, len);
>>> +}
>>> +
>>> +static void gen11_compute_sseu_info(struct sseu_dev_info *sseu,
>>> +				    intel_sseu_ss_mask_t g_ss_en,
>>> +				    intel_sseu_ss_mask_t c_ss_en,
>>> +				    u16 eu_en)
>>> +{
>>>    	/* g_ss_en/c_ss_en represent entire subslice mask across all slices */
>>>    	GEM_BUG_ON(sseu->max_slices * sseu->max_subslices >
>>>    		   sizeof(g_ss_en) * BITS_PER_BYTE);
>>> @@ -174,12 +198,12 @@ static void gen11_compute_sseu_info(struct sseu_dev_info *sseu,
>>>    	 * enabled subslice count for the purposes of selecting subslices to
>>>    	 * use in a particular GEM context.
>>>    	 */
>>> -	intel_sseu_set_subslices(sseu, 0, sseu->compute_subslice_mask,
>>> -				 c_ss_en & valid_ss_mask);
>>> -	intel_sseu_set_subslices(sseu, 0, sseu->geometry_subslice_mask,
>>> -				 g_ss_en & valid_ss_mask);
>>> -	intel_sseu_set_subslices(sseu, 0, sseu->subslice_mask,
>>> -				 (g_ss_en | c_ss_en) & valid_ss_mask);
>>> +	bitmap_copy(sseu->compute_subslice_mask.b, c_ss_en.b, I915_MAX_SS_FUSE_BITS);
>>> +	bitmap_copy(sseu->geometry_subslice_mask.b, g_ss_en.b, I915_MAX_SS_FUSE_BITS);
>>> +	bitmap_or(sseu->subslice_mask.b,
>>> +		  sseu->compute_subslice_mask.b,
>>> +		  sseu->geometry_subslice_mask.b,
>>> +		  I915_MAX_SS_FUSE_BITS);
>>>    	sseu->has_common_ss_eumask = 1;
>>>    	sseu->eu_mask[0] = eu_en;
>>> @@ -191,7 +215,8 @@ static void xehp_sseu_info_init(struct intel_gt *gt)
>>>    {
>>>    	struct sseu_dev_info *sseu = &gt->info.sseu;
>>>    	struct intel_uncore *uncore = gt->uncore;
>>> -	u32 g_dss_en, c_dss_en = 0;
>>> +	intel_sseu_ss_mask_t g_dss_en = {}, c_dss_en = {};
>>> +	u32 val;
>>>    	u16 eu_en = 0;
>>>    	u8 eu_en_fuse;
>>>    	int eu;
>>> @@ -204,8 +229,11 @@ static void xehp_sseu_info_init(struct intel_gt *gt)
>>>    	 */
>>>    	intel_sseu_set_info(sseu, 1, 32, 16);
>>> -	g_dss_en = intel_uncore_read(uncore, GEN12_GT_GEOMETRY_DSS_ENABLE);
>>> -	c_dss_en = intel_uncore_read(uncore, GEN12_GT_COMPUTE_DSS_ENABLE);
>>> +	val = intel_uncore_read(uncore, GEN12_GT_GEOMETRY_DSS_ENABLE);
>>> +	bitmap_from_arr32(g_dss_en.b, &val, 32);
>>> +
>>> +	val = intel_uncore_read(uncore, GEN12_GT_COMPUTE_DSS_ENABLE);
>>> +	bitmap_from_arr32(c_dss_en.b, &val, 32);
>>>    	eu_en_fuse = intel_uncore_read(uncore, XEHP_EU_ENABLE) & XEHP_EU_ENA_MASK;
>>> @@ -220,7 +248,8 @@ static void gen12_sseu_info_init(struct intel_gt *gt)
>>>    {
>>>    	struct sseu_dev_info *sseu = &gt->info.sseu;
>>>    	struct intel_uncore *uncore = gt->uncore;
>>> -	u32 g_dss_en;
>>> +	intel_sseu_ss_mask_t g_dss_en = {}, empty_mask = {};
>>> +	u32 val;
>>>    	u16 eu_en = 0;
>>>    	u8 eu_en_fuse;
>>>    	u8 s_en;
>>> @@ -243,7 +272,8 @@ static void gen12_sseu_info_init(struct intel_gt *gt)
>>>    		drm_dbg(&gt->i915->drm, "Slice mask %#x is not the expected 0x1!\n",
>>>    			s_en);
>>> -	g_dss_en = intel_uncore_read(uncore, GEN12_GT_GEOMETRY_DSS_ENABLE);
>>> +	val = intel_uncore_read(uncore, GEN12_GT_GEOMETRY_DSS_ENABLE);
>>> +	bitmap_from_arr32(g_dss_en.b, &val, 32);
>>>    	/* one bit per pair of EUs */
>>>    	eu_en_fuse = ~(intel_uncore_read(uncore, GEN11_EU_DISABLE) &
>>> @@ -253,7 +283,7 @@ static void gen12_sseu_info_init(struct intel_gt *gt)
>>>    		if (eu_en_fuse & BIT(eu))
>>>    			eu_en |= BIT(eu * 2) | BIT(eu * 2 + 1);
>>> -	gen11_compute_sseu_info(sseu, g_dss_en, 0, eu_en);
>>> +	gen11_compute_sseu_info(sseu, g_dss_en, empty_mask, eu_en);
>>>    	/* TGL only supports slice-level power gating */
>>>    	sseu->has_slice_pg = 1;
>>> @@ -263,7 +293,8 @@ static void gen11_sseu_info_init(struct intel_gt *gt)
>>>    {
>>>    	struct sseu_dev_info *sseu = &gt->info.sseu;
>>>    	struct intel_uncore *uncore = gt->uncore;
>>> -	u32 ss_en;
>>> +	intel_sseu_ss_mask_t ss_en = {}, empty_mask = {};
>>> +	u32 val;
>>>    	u8 eu_en;
>>>    	u8 s_en;
>>> @@ -282,12 +313,13 @@ static void gen11_sseu_info_init(struct intel_gt *gt)
>>>    		drm_dbg(&gt->i915->drm, "Slice mask %#x is not the expected 0x1!\n",
>>>    			s_en);
>>> -	ss_en = ~intel_uncore_read(uncore, GEN11_GT_SUBSLICE_DISABLE);
>>> +	val = ~intel_uncore_read(uncore, GEN11_GT_SUBSLICE_DISABLE);
>>> +	bitmap_from_arr32(ss_en.b, &val, 32);
>>>    	eu_en = ~(intel_uncore_read(uncore, GEN11_EU_DISABLE) &
>>>    		  GEN11_EU_DIS_MASK);
>>> -	gen11_compute_sseu_info(sseu, ss_en, 0, eu_en);
>>> +	gen11_compute_sseu_info(sseu, ss_en, empty_mask, eu_en);
>>>    	/* ICL has no power gating restrictions. */
>>>    	sseu->has_slice_pg = 1;
>>> @@ -328,7 +360,7 @@ static void cherryview_sseu_info_init(struct intel_gt *gt)
>>>    		sseu_set_eus(sseu, 0, 1, ~disabled_mask);
>>>    	}
>>> -	intel_sseu_set_subslices(sseu, 0, sseu->subslice_mask, subslice_mask);
>>> +	set_subslices(sseu, 0, subslice_mask);
>>>    	sseu->eu_total = compute_eu_total(sseu);
>>> @@ -384,8 +416,7 @@ static void gen9_sseu_info_init(struct intel_gt *gt)
>>>    			/* skip disabled slice */
>>>    			continue;
>>> -		intel_sseu_set_subslices(sseu, s, sseu->subslice_mask,
>>> -					 subslice_mask);
>>> +		set_subslices(sseu, s, subslice_mask);
>>>    		eu_disable = intel_uncore_read(uncore, GEN9_EU_DISABLE(s));
>>>    		for (ss = 0; ss < sseu->max_subslices; ss++) {
>>> @@ -442,8 +473,8 @@ static void gen9_sseu_info_init(struct intel_gt *gt)
>>>    	sseu->has_eu_pg = sseu->eu_per_subslice > 2;
>>>    	if (IS_GEN9_LP(i915)) {
>>> -#define IS_SS_DISABLED(ss)	(!(sseu->subslice_mask[0] & BIT(ss)))
>>> -		info->has_pooled_eu = hweight8(sseu->subslice_mask[0]) == 3;
>>> +#define IS_SS_DISABLED(ss)	test_bit(ss, sseu->subslice_mask.b)
>>> +		info->has_pooled_eu = hweight8(sseu->subslice_mask.b[0]) == 3;
>>>    		sseu->min_eu_in_pool = 0;
>>>    		if (info->has_pooled_eu) {
>>> @@ -497,8 +528,7 @@ static void bdw_sseu_info_init(struct intel_gt *gt)
>>>    			/* skip disabled slice */
>>>    			continue;
>>> -		intel_sseu_set_subslices(sseu, s, sseu->subslice_mask,
>>> -					 subslice_mask);
>>> +		set_subslices(sseu, s, subslice_mask);
>>>    		for (ss = 0; ss < sseu->max_subslices; ss++) {
>>>    			u8 eu_disabled_mask;
>>> @@ -595,8 +625,7 @@ static void hsw_sseu_info_init(struct intel_gt *gt)
>>>    			    sseu->eu_per_subslice);
>>>    	for (s = 0; s < sseu->max_slices; s++) {
>>> -		intel_sseu_set_subslices(sseu, s, sseu->subslice_mask,
>>> -					 subslice_mask);
>>> +		set_subslices(sseu, s, subslice_mask);
>>>    		for (ss = 0; ss < sseu->max_subslices; ss++) {
>>>    			sseu_set_eus(sseu, s, ss,
>>> @@ -685,7 +714,7 @@ u32 intel_sseu_make_rpcs(struct intel_gt *gt,
>>>    	 */
>>>    	if (GRAPHICS_VER(i915) == 11 &&
>>>    	    slices == 1 &&
>>> -	    subslices > min_t(u8, 4, hweight8(sseu->subslice_mask[0]) / 2)) {
>>> +	    subslices > min_t(u8, 4, hweight8(sseu->subslice_mask.b[0]) / 2)) {
>>>    		GEM_BUG_ON(subslices & 1);
>>>    		subslice_pg = false;
>>> @@ -755,9 +784,11 @@ void intel_sseu_dump(const struct sseu_dev_info *sseu, struct drm_printer *p)
>>>    		   hweight8(sseu->slice_mask), sseu->slice_mask);
>>>    	drm_printf(p, "subslice total: %u\n", intel_sseu_subslice_total(sseu));
>>>    	for (s = 0; s < sseu->max_slices; s++) {
>>> -		drm_printf(p, "slice%d: %u subslices, mask=%08x\n",
>>> -			   s, intel_sseu_subslices_per_slice(sseu, s),
>>> -			   intel_sseu_get_subslices(sseu, s));
>>> +		intel_sseu_ss_mask_t ssmask = intel_sseu_get_subslices(sseu, s);
>>> +
>>> +		drm_printf(p, "slice%d: %u subslices, mask=%*pb\n",
>>> +			   s, bitmap_weight(ssmask.b, I915_MAX_SS_FUSE_BITS),
>>> +			   I915_MAX_SS_FUSE_BITS, ssmask.b);
>>>    	}
>>>    	drm_printf(p, "EU total: %u\n", sseu->eu_total);
>>>    	drm_printf(p, "EU per subslice: %u\n", sseu->eu_per_subslice);
>>> @@ -775,9 +806,11 @@ static void sseu_print_hsw_topology(const struct sseu_dev_info *sseu,
>>>    	int s, ss;
>>>    	for (s = 0; s < sseu->max_slices; s++) {
>>> -		drm_printf(p, "slice%d: %u subslice(s) (0x%08x):\n",
>>> -			   s, intel_sseu_subslices_per_slice(sseu, s),
>>> -			   intel_sseu_get_subslices(sseu, s));
>>> +		intel_sseu_ss_mask_t ssmask = intel_sseu_get_subslices(sseu, s);
>>> +
>>> +		drm_printf(p, "slice%d: %u subslice(s) (0x%*pb):\n",
>>> +			   s, bitmap_weight(ssmask.b, I915_MAX_SS_FUSE_BITS),
>>> +			   I915_MAX_SS_FUSE_BITS, ssmask.b);
>>>    		for (ss = 0; ss < sseu->max_subslices; ss++) {
>>>    			u16 enabled_eus = sseu_get_eus(sseu, s, ss);
>>> @@ -791,16 +824,14 @@ static void sseu_print_hsw_topology(const struct sseu_dev_info *sseu,
>>>    static void sseu_print_xehp_topology(const struct sseu_dev_info *sseu,
>>>    				     struct drm_printer *p)
>>>    {
>>> -	u32 g_dss_mask = sseu_get_geometry_subslices(sseu);
>>> -	u32 c_dss_mask = intel_sseu_get_compute_subslices(sseu);
>>>    	int dss;
>>>    	for (dss = 0; dss < sseu->max_subslices; dss++) {
>>>    		u16 enabled_eus = sseu_get_eus(sseu, 0, dss);
>>>    		drm_printf(p, "DSS_%02d: G:%3s C:%3s, %2u EUs (0x%04hx)\n", dss,
>>> -			   str_yes_no(g_dss_mask & BIT(dss)),
>>> -			   str_yes_no(c_dss_mask & BIT(dss)),
>>> +			   str_yes_no(test_bit(dss, sseu->geometry_subslice_mask.b)),
>>> +			   str_yes_no(test_bit(dss, sseu->compute_subslice_mask.b)),
>>>    			   hweight16(enabled_eus), enabled_eus);
>>>    	}
>>>    }
>>> @@ -818,20 +849,24 @@ void intel_sseu_print_topology(struct drm_i915_private *i915,
>>>    	}
>>>    }
>>> -u16 intel_slicemask_from_dssmask(u64 dss_mask, int dss_per_slice)
>>> +u16 intel_slicemask_from_dssmask(intel_sseu_ss_mask_t dss_mask,
>>> +				 int dss_per_slice)
>>>    {
>>> +	intel_sseu_ss_mask_t per_slice_mask = {};
>>>    	u16 slice_mask = 0;
>>>    	int i;
>>> -	WARN_ON(sizeof(dss_mask) * 8 / dss_per_slice > 8 * sizeof(slice_mask));
>>> +	WARN_ON(DIV_ROUND_UP(I915_MAX_SS_FUSE_BITS, dss_per_slice) >
>>> +		8 * sizeof(slice_mask));
>>> -	for (i = 0; dss_mask; i++) {
>>> -		if (dss_mask & GENMASK(dss_per_slice - 1, 0))
>>> +	bitmap_fill(per_slice_mask.b, dss_per_slice);
>>> +	for (i = 0; !bitmap_empty(dss_mask.b, I915_MAX_SS_FUSE_BITS); i++) {
>>> +		if (bitmap_intersects(dss_mask.b, per_slice_mask.b, dss_per_slice))
>>>    			slice_mask |= BIT(i);
>>> -		dss_mask >>= dss_per_slice;
>>> +		bitmap_shift_right(dss_mask.b, dss_mask.b, dss_per_slice,
>>> +				   I915_MAX_SS_FUSE_BITS);
>>>    	}
>>>    	return slice_mask;
>>>    }
>>> -
>>> diff --git a/drivers/gpu/drm/i915/gt/intel_sseu.h b/drivers/gpu/drm/i915/gt/intel_sseu.h
>>> index 106726a2244e..455f085093ae 100644
>>> --- a/drivers/gpu/drm/i915/gt/intel_sseu.h
>>> +++ b/drivers/gpu/drm/i915/gt/intel_sseu.h
>>> @@ -52,11 +52,22 @@ struct drm_printer;
>>>    #define GEN_MAX_GSLICES		(GEN_MAX_DSS / GEN_DSS_PER_GSLICE)
>>>    #define GEN_MAX_CSLICES		(GEN_MAX_DSS / GEN_DSS_PER_CSLICE)
>>> +/*
>>> + * Maximum number of 32-bit registers used by hardware to express the
>>> + * enabled/disabled subslices.
>>> + */
>>> +#define I915_MAX_SS_FUSE_REGS	1
>>> +#define I915_MAX_SS_FUSE_BITS	(I915_MAX_SS_FUSE_REGS * 32)
>>> +
>>> +typedef struct {
>>> +	unsigned long b[BITS_TO_LONGS(I915_MAX_SS_FUSE_BITS)];
>>> +} intel_sseu_ss_mask_t;
>>> +
>>>    struct sseu_dev_info {
>>>    	u8 slice_mask;
>>> -	u8 subslice_mask[GEN_SS_MASK_SIZE];
>>> -	u8 geometry_subslice_mask[GEN_SS_MASK_SIZE];
>>> -	u8 compute_subslice_mask[GEN_SS_MASK_SIZE];
>>> +	intel_sseu_ss_mask_t subslice_mask;
>>> +	intel_sseu_ss_mask_t geometry_subslice_mask;
>>> +	intel_sseu_ss_mask_t compute_subslice_mask;
>>>    	/*
>>>    	 * EU masks.  Use has_common_ss_eumask to determine how the field
>>> @@ -107,7 +118,7 @@ intel_sseu_from_device_info(const struct sseu_dev_info *sseu)
>>>    {
>>>    	struct intel_sseu value = {
>>>    		.slice_mask = sseu->slice_mask,
>>> -		.subslice_mask = sseu->subslice_mask[0],
>>> +		.subslice_mask = sseu->subslice_mask.b[0],
>>>    		.min_eus_per_subslice = sseu->max_eus_per_subslice,
>>>    		.max_eus_per_subslice = sseu->max_eus_per_subslice,
>>>    	};
>>> @@ -119,18 +130,8 @@ static inline bool
>>>    intel_sseu_has_subslice(const struct sseu_dev_info *sseu, int slice,
>>>    			int subslice)
>>>    {
>>> -	u8 mask;
>>> -	int ss_idx = subslice / BITS_PER_BYTE;
>>> -
>>> -	if (slice >= sseu->max_slices ||
>>> -	    subslice >= sseu->max_subslices)
>>> -		return false;
>>> -
>>> -	GEM_BUG_ON(ss_idx >= sseu->ss_stride);
>>> -
>>> -	mask = sseu->subslice_mask[slice * sseu->ss_stride + ss_idx];
>>> -
>>> -	return mask & BIT(subslice % BITS_PER_BYTE);
>>> +	return test_bit(slice * sseu->ss_stride + subslice,
>>> +			sseu->subslice_mask.b);
>>>    }
>>>    void intel_sseu_set_info(struct sseu_dev_info *sseu, u8 max_slices,
>>> @@ -139,15 +140,14 @@ void intel_sseu_set_info(struct sseu_dev_info *sseu, u8 max_slices,
>>>    unsigned int
>>>    intel_sseu_subslice_total(const struct sseu_dev_info *sseu);
>>> -unsigned int
>>> -intel_sseu_subslices_per_slice(const struct sseu_dev_info *sseu, u8 slice);
>>> +intel_sseu_ss_mask_t
>>> +intel_sseu_get_subslices(const struct sseu_dev_info *sseu, u8 slice);
>>> -u32 intel_sseu_get_subslices(const struct sseu_dev_info *sseu, u8 slice);
>>> -
>>> -u32 intel_sseu_get_compute_subslices(const struct sseu_dev_info *sseu);
>>> +intel_sseu_ss_mask_t
>>> +intel_sseu_get_compute_subslices(const struct sseu_dev_info *sseu);
>>>    void intel_sseu_set_subslices(struct sseu_dev_info *sseu, int slice,
>>> -			      u8 *subslice_mask, u32 ss_mask);
>>> +			      u32 ss_mask);
>>>    void intel_sseu_info_init(struct intel_gt *gt);
>>> @@ -159,9 +159,11 @@ void intel_sseu_print_topology(struct drm_i915_private *i915,
>>>    			       const struct sseu_dev_info *sseu,
>>>    			       struct drm_printer *p);
>>> -u16 intel_slicemask_from_dssmask(u64 dss_mask, int dss_per_slice);
>>> +u16 intel_slicemask_from_dssmask(intel_sseu_ss_mask_t dss_mask, int dss_per_slice);
>>>    int intel_sseu_copy_eumask_to_user(void __user *to,
>>>    				   const struct sseu_dev_info *sseu);
>>> +int intel_sseu_copy_ssmask_to_user(void __user *to,
>>> +				   const struct sseu_dev_info *sseu);
>>>    #endif /* __INTEL_SSEU_H__ */
>>> diff --git a/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c b/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c
>>> index 2d5d011e01db..1f77bd52a3a6 100644
>>> --- a/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c
>>> +++ b/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c
>>> @@ -4,6 +4,7 @@
>>>     * Copyright © 2020 Intel Corporation
>>>     */
>>> +#include <linux/bitmap.h>
>>>    #include <linux/string_helpers.h>
>>>    #include "i915_drv.h"
>>> @@ -12,11 +13,15 @@
>>>    #include "intel_sseu_debugfs.h"
>>>    static void sseu_copy_subslices(const struct sseu_dev_info *sseu,
>>> -				int slice, u8 *to_mask)
>>> +				int slice,
>>> +				intel_sseu_ss_mask_t *to_mask)
>>>    {
>>> -	int offset = slice * sseu->ss_stride;
>>> +	int offset = slice * sseu->max_subslices;
>>> -	memcpy(&to_mask[offset], &sseu->subslice_mask[offset], sseu->ss_stride);
>>> +	bitmap_fill(to_mask->b, sseu->max_subslices);
>>> +	bitmap_shift_left(to_mask->b, to_mask->b, offset, I915_MAX_SS_FUSE_BITS);
>>> +	bitmap_and(to_mask->b, to_mask->b, sseu->subslice_mask.b, I915_MAX_SS_FUSE_BITS);
>>> +	bitmap_shift_right(to_mask->b, to_mask->b, offset, I915_MAX_SS_FUSE_BITS);
>>>    }
>>>    static void cherryview_sseu_device_status(struct intel_gt *gt,
>>> @@ -41,7 +46,7 @@ static void cherryview_sseu_device_status(struct intel_gt *gt,
>>>    			continue;
>>>    		sseu->slice_mask = BIT(0);
>>> -		sseu->subslice_mask[0] |= BIT(ss);
>>> +		set_bit(0, sseu->subslice_mask.b);
>>>    		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) +
>>> @@ -92,7 +97,7 @@ static void gen11_sseu_device_status(struct intel_gt *gt,
>>>    			continue;
>>>    		sseu->slice_mask |= BIT(s);
>>> -		sseu_copy_subslices(&info->sseu, s, sseu->subslice_mask);
>>> +		sseu_copy_subslices(&info->sseu, s, &sseu->subslice_mask);
>>>    		for (ss = 0; ss < info->sseu.max_subslices; ss++) {
>>>    			unsigned int eu_cnt;
>>> @@ -148,20 +153,17 @@ static void gen9_sseu_device_status(struct intel_gt *gt,
>>>    		if (IS_GEN9_BC(gt->i915))
>>>    			sseu_copy_subslices(&info->sseu, s,
>>> -					    sseu->subslice_mask);
>>> +					    &sseu->subslice_mask);
>>>    		for (ss = 0; ss < info->sseu.max_subslices; ss++) {
>>>    			unsigned int eu_cnt;
>>> -			u8 ss_idx = s * info->sseu.ss_stride +
>>> -				    ss / BITS_PER_BYTE;
>>>    			if (IS_GEN9_LP(gt->i915)) {
>>>    				if (!(s_reg[s] & (GEN9_PGCTL_SS_ACK(ss))))
>>>    					/* skip disabled subslice */
>>>    					continue;
>>> -				sseu->subslice_mask[ss_idx] |=
>>> -					BIT(ss % BITS_PER_BYTE);
>>> +				set_bit(ss, sseu->subslice_mask.b);
>>>    			}
>>>    			eu_cnt = eu_reg[2 * s + ss / 2] & eu_mask[ss % 2];
>>> @@ -189,7 +191,7 @@ static void bdw_sseu_device_status(struct intel_gt *gt,
>>>    		sseu->eu_per_subslice = info->sseu.eu_per_subslice;
>>>    		for (s = 0; s < fls(sseu->slice_mask); s++)
>>>    			sseu_copy_subslices(&info->sseu, s,
>>> -					    sseu->subslice_mask);
>>> +					    &sseu->subslice_mask);
>>>    		sseu->eu_total = sseu->eu_per_subslice *
>>>    				 intel_sseu_subslice_total(sseu);
>>> @@ -217,8 +219,10 @@ static void i915_print_sseu_info(struct seq_file *m,
>>>    	seq_printf(m, "  %s Subslice Total: %u\n", type,
>>>    		   intel_sseu_subslice_total(sseu));
>>>    	for (s = 0; s < fls(sseu->slice_mask); s++) {
>>> +		intel_sseu_ss_mask_t ssmask = intel_sseu_get_subslices(sseu, s);
>>> +
>>>    		seq_printf(m, "  %s Slice%i subslices: %u\n", type,
>>> -			   s, intel_sseu_subslices_per_slice(sseu, s));
>>> +			   s, bitmap_weight(ssmask.b, I915_MAX_SS_FUSE_BITS));
>>>    	}
>>>    	seq_printf(m, "  %s EU Total: %u\n", type,
>>>    		   sseu->eu_total);
>>> diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c
>>> index a05c4b99b3fb..5db492072f99 100644
>>> --- a/drivers/gpu/drm/i915/gt/intel_workarounds.c
>>> +++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c
>>> @@ -931,6 +931,7 @@ static void
>>>    gen9_wa_init_mcr(struct drm_i915_private *i915, struct i915_wa_list *wal)
>>>    {
>>>    	const struct sseu_dev_info *sseu = &to_gt(i915)->info.sseu;
>>> +	intel_sseu_ss_mask_t ssmask;
>>>    	unsigned int slice, subslice;
>>>    	u32 mcr, mcr_mask;
>>> @@ -948,9 +949,9 @@ gen9_wa_init_mcr(struct drm_i915_private *i915, struct i915_wa_list *wal)
>>>    	 * on s/ss combo, the read should be done with read_subslice_reg.
>>>    	 */
>>>    	slice = ffs(sseu->slice_mask) - 1;
>>> -	GEM_BUG_ON(slice >= ARRAY_SIZE(sseu->subslice_mask));
>>> -	subslice = ffs(intel_sseu_get_subslices(sseu, slice));
>>> -	GEM_BUG_ON(!subslice);
>>> +	ssmask = intel_sseu_get_subslices(sseu, slice);
>>> +	subslice = find_first_bit(ssmask.b, I915_MAX_SS_FUSE_BITS);
>>> +	GEM_BUG_ON(subslice == I915_MAX_SS_FUSE_BITS);
>>>    	subslice--;
>>>    	/*
>>> @@ -1087,11 +1088,10 @@ static void
>>>    icl_wa_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
>>>    {
>>>    	const struct sseu_dev_info *sseu = &gt->info.sseu;
>>> -	unsigned int slice, subslice;
>>> +	unsigned int subslice;
>>>    	GEM_BUG_ON(GRAPHICS_VER(gt->i915) < 11);
>>>    	GEM_BUG_ON(hweight8(sseu->slice_mask) > 1);
>>> -	slice = 0;
>>>    	/*
>>>    	 * Although a platform may have subslices, we need to always steer
>>> @@ -1102,7 +1102,7 @@ icl_wa_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
>>>    	 * one of the higher subslices, we run the risk of reading back 0's or
>>>    	 * random garbage.
>>>    	 */
>>> -	subslice = __ffs(intel_sseu_get_subslices(sseu, slice));
>>> +	subslice = find_first_bit(sseu->subslice_mask.b, I915_MAX_SS_FUSE_BITS);
>>>    	/*
>>>    	 * If the subslice we picked above also steers us to a valid L3 bank,
>>> @@ -1112,7 +1112,7 @@ icl_wa_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
>>>    	if (gt->info.l3bank_mask & BIT(subslice))
>>>    		gt->steering_table[L3BANK] = NULL;
>>> -	__add_mcr_wa(gt, wal, slice, subslice);
>>> +	__add_mcr_wa(gt, wal, 0, subslice);
>>>    }
>>>    static void
>>> @@ -1120,7 +1120,6 @@ xehp_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
>>>    {
>>>    	const struct sseu_dev_info *sseu = &gt->info.sseu;
>>>    	unsigned long slice, subslice = 0, slice_mask = 0;
>>> -	u64 dss_mask = 0;
>>>    	u32 lncf_mask = 0;
>>>    	int i;
>>> @@ -1151,8 +1150,8 @@ xehp_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
>>>    	 */
>>>    	/* Find the potential gslice candidates */
>>> -	dss_mask = intel_sseu_get_subslices(sseu, 0);
>>> -	slice_mask = intel_slicemask_from_dssmask(dss_mask, GEN_DSS_PER_GSLICE);
>>> +	slice_mask = intel_slicemask_from_dssmask(sseu->subslice_mask,
>>> +						  GEN_DSS_PER_GSLICE);
>>>    	/*
>>>    	 * Find the potential LNCF candidates.  Either LNCF within a valid
>>> @@ -1177,9 +1176,9 @@ xehp_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
>>>    	}
>>>    	slice = __ffs(slice_mask);
>>> -	subslice = __ffs(dss_mask >> (slice * GEN_DSS_PER_GSLICE));
>>> +	subslice = find_next_bit(sseu->subslice_mask.b, I915_MAX_SS_FUSE_BITS,
>>> +				 slice * GEN_DSS_PER_GSLICE);
>>>    	WARN_ON(subslice > GEN_DSS_PER_GSLICE);
>>> -	WARN_ON(dss_mask >> (slice * GEN_DSS_PER_GSLICE) == 0);
>>>    	__add_mcr_wa(gt, wal, slice, subslice);
>>> @@ -2012,9 +2011,8 @@ engine_fake_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
>>>    static bool needs_wa_1308578152(struct intel_engine_cs *engine)
>>>    {
>>> -	u64 dss_mask = intel_sseu_get_subslices(&engine->gt->info.sseu, 0);
>>> -
>>> -	return (dss_mask & GENMASK(GEN_DSS_PER_GSLICE - 1, 0)) == 0;
>>> +	return find_first_bit(engine->gt->info.sseu.subslice_mask.b,
>>> +			      I915_MAX_SS_FUSE_BITS) >= GEN_DSS_PER_GSLICE;
>>>    }
>>>    static void
>>> diff --git a/drivers/gpu/drm/i915/i915_getparam.c b/drivers/gpu/drm/i915/i915_getparam.c
>>> index ac9767c56619..349d496d164a 100644
>>> --- a/drivers/gpu/drm/i915/i915_getparam.c
>>> +++ b/drivers/gpu/drm/i915/i915_getparam.c
>>> @@ -162,7 +162,7 @@ int i915_getparam_ioctl(struct drm_device *dev, void *data,
>>>    			return -EINVAL;
>>>    		/* Only copy bits from the first slice */
>>> -		memcpy(&value, sseu->subslice_mask,
>>> +		memcpy(&value, sseu->subslice_mask.b,
>>>    		       min(sseu->ss_stride, (u8)sizeof(value)));
>>>    		if (!value)
>>>    			return -ENODEV;
>>> diff --git a/drivers/gpu/drm/i915/i915_query.c b/drivers/gpu/drm/i915/i915_query.c
>>> index 16f43bf32a05..9afa6d1eaf95 100644
>>> --- a/drivers/gpu/drm/i915/i915_query.c
>>> +++ b/drivers/gpu/drm/i915/i915_query.c
>>> @@ -31,7 +31,7 @@ static int copy_query_item(void *query_hdr, size_t query_sz,
>>>    static int fill_topology_info(const struct sseu_dev_info *sseu,
>>>    			      struct drm_i915_query_item *query_item,
>>> -			      const u8 *subslice_mask)
>>> +			      intel_sseu_ss_mask_t subslice_mask)
>>>    {
>>>    	struct drm_i915_query_topology_info topo;
>>>    	u32 slice_length, subslice_length, eu_length, total_length;
>>> @@ -71,9 +71,9 @@ static int fill_topology_info(const struct sseu_dev_info *sseu,
>>>    			 &sseu->slice_mask, slice_length))
>>>    		return -EFAULT;
>>> -	if (copy_to_user(u64_to_user_ptr(query_item->data_ptr +
>>> -					 sizeof(topo) + slice_length),
>>> -			 subslice_mask, subslice_length))
>>> +	if (intel_sseu_copy_ssmask_to_user(u64_to_user_ptr(query_item->data_ptr +
>>> +							   sizeof(topo) + slice_length),
>>> +					   sseu))
>>>    		return -EFAULT;
>>>    	if (intel_sseu_copy_eumask_to_user(u64_to_user_ptr(query_item->data_ptr +
> 

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

* [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for i915: SSEU handling updates
  2022-06-01 15:07 [PATCH v5 0/6] " Matt Roper
@ 2022-06-01 15:59 ` Patchwork
  0 siblings, 0 replies; 27+ messages in thread
From: Patchwork @ 2022-06-01 15:59 UTC (permalink / raw)
  To: Matt Roper; +Cc: intel-gfx

== Series Details ==

Series: i915: SSEU handling updates
URL   : https://patchwork.freedesktop.org/series/104611/
State : warning

== Summary ==

Error: dim checkpatch failed
92101c27eef9 drm/i915/xehp: Use separate sseu init function
7489d9903596 drm/i915/xehp: Drop GETPARAM lookups of I915_PARAM_[SUB]SLICE_MASK
7e1560b69810 drm/i915/sseu: Simplify gen11+ SSEU handling
529ade4a9e43 drm/i915/sseu: Don't try to store EU mask internally in UAPI format
7823e3f4a149 drm/i915/sseu: Disassociate internal subslice mask representation from uapi
-:523: ERROR:POINTER_LOCATION: "foo* bar" should be "foo *bar"
#523: FILE: drivers/gpu/drm/i915/gt/intel_sseu.c:844:
+void intel_sseu_print_ss_info(const char* type,

-:612: WARNING:NEW_TYPEDEFS: do not add new typedefs
#612: FILE: drivers/gpu/drm/i915/gt/intel_sseu.h:59:
+typedef union {

-:720: ERROR:POINTER_LOCATION: "foo* bar" should be "foo *bar"
#720: FILE: drivers/gpu/drm/i915/gt/intel_sseu.h:178:
+void intel_sseu_print_ss_info(const char* type,

total: 2 errors, 1 warnings, 0 checks, 830 lines checked
acc8c6a07c85 drm/i915/pvc: Add SSEU changes



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

* [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for i915: SSEU handling updates
  2022-05-20 23:04 [PATCH v4 0/6] i915: SSEU handling updates Matt Roper
@ 2022-05-20 23:46 ` Patchwork
  0 siblings, 0 replies; 27+ messages in thread
From: Patchwork @ 2022-05-20 23:46 UTC (permalink / raw)
  To: Matt Roper; +Cc: intel-gfx

== Series Details ==

Series: i915: SSEU handling updates
URL   : https://patchwork.freedesktop.org/series/104244/
State : warning

== Summary ==

Error: dim checkpatch failed
715c882f826e drm/i915/xehp: Use separate sseu init function
194ba3678abd drm/i915/xehp: Drop GETPARAM lookups of I915_PARAM_[SUB]SLICE_MASK
c1bbe76c5724 drm/i915/sseu: Simplify gen11+ SSEU handling
cb927114d301 drm/i915/sseu: Don't try to store EU mask internally in UAPI format
a0263df1c5fd drm/i915/sseu: Disassociate internal subslice mask representation from uapi
-:514: ERROR:POINTER_LOCATION: "foo* bar" should be "foo *bar"
#514: FILE: drivers/gpu/drm/i915/gt/intel_sseu.c:846:
+void intel_sseu_print_ss_info(const char* type,

-:602: WARNING:NEW_TYPEDEFS: do not add new typedefs
#602: FILE: drivers/gpu/drm/i915/gt/intel_sseu.h:59:
+typedef union {

-:710: ERROR:POINTER_LOCATION: "foo* bar" should be "foo *bar"
#710: FILE: drivers/gpu/drm/i915/gt/intel_sseu.h:176:
+void intel_sseu_print_ss_info(const char* type,

total: 2 errors, 1 warnings, 0 checks, 837 lines checked
2e230636389f drm/i915/pvc: Add SSEU changes



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

end of thread, other threads:[~2022-06-01 15:59 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-27 23:07 [PATCH 0/5] i915: SSEU handling updates Matt Roper
2022-04-27 23:07 ` [Intel-gfx] " Matt Roper
2022-04-27 23:07 ` [PATCH 1/5] drm/i915/sseu: Don't try to store EU mask internally in UAPI format Matt Roper
2022-04-27 23:07   ` [Intel-gfx] " Matt Roper
2022-04-27 23:07 ` [PATCH 2/5] drm/i915/xehp: Drop GETPARAM lookups of I915_PARAM_[SUB]SLICE_MASK Matt Roper
2022-04-27 23:07   ` [Intel-gfx] " Matt Roper
2022-04-27 23:07 ` [PATCH 3/5] drm/i915/xehp: Use separate sseu init function Matt Roper
2022-04-27 23:07   ` [Intel-gfx] " Matt Roper
2022-04-27 23:07 ` [PATCH 4/5] drm/i915/sseu: Simplify gen11+ SSEU handling Matt Roper
2022-04-27 23:07   ` [Intel-gfx] " Matt Roper
2022-04-27 23:07 ` [PATCH 5/5] drm/i915/sseu: Disassociate internal subslice mask representation from uapi Matt Roper
2022-04-27 23:07   ` [Intel-gfx] " Matt Roper
2022-04-28 12:18   ` Tvrtko Ursulin
2022-04-28 12:18     ` [Intel-gfx] " Tvrtko Ursulin
2022-05-06 23:34     ` Matt Roper
2022-05-06 23:34       ` [Intel-gfx] " Matt Roper
2022-05-09 14:18       ` Tvrtko Ursulin
2022-05-09 14:18         ` [Intel-gfx] " Tvrtko Ursulin
2022-04-27 23:26 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for i915: SSEU handling updates Patchwork
2022-04-27 23:26 ` [Intel-gfx] ✗ Fi.CI.SPARSE: " Patchwork
2022-04-27 23:55 ` [Intel-gfx] ✗ Fi.CI.BAT: failure " Patchwork
2022-04-28  0:42 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for i915: SSEU handling updates (rev2) Patchwork
2022-04-28  0:42 ` [Intel-gfx] ✗ Fi.CI.SPARSE: " Patchwork
2022-04-28  1:11 ` [Intel-gfx] ✓ Fi.CI.BAT: success " Patchwork
2022-04-28  2:34 ` [Intel-gfx] ✗ Fi.CI.IGT: failure " Patchwork
2022-05-20 23:04 [PATCH v4 0/6] i915: SSEU handling updates Matt Roper
2022-05-20 23:46 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for " Patchwork
2022-06-01 15:07 [PATCH v5 0/6] " Matt Roper
2022-06-01 15:59 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for " Patchwork

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