|
@@ -2480,6 +2480,9 @@ int logical_xcs_ring_init(struct intel_engine_cs *engine)
|
|
|
static u32
|
|
|
make_rpcs(struct drm_i915_private *dev_priv)
|
|
|
{
|
|
|
+ bool subslice_pg = INTEL_INFO(dev_priv)->sseu.has_subslice_pg;
|
|
|
+ u8 slices = hweight8(INTEL_INFO(dev_priv)->sseu.slice_mask);
|
|
|
+ u8 subslices = hweight8(INTEL_INFO(dev_priv)->sseu.subslice_mask[0]);
|
|
|
u32 rpcs = 0;
|
|
|
|
|
|
/*
|
|
@@ -2489,6 +2492,38 @@ make_rpcs(struct drm_i915_private *dev_priv)
|
|
|
if (INTEL_GEN(dev_priv) < 9)
|
|
|
return 0;
|
|
|
|
|
|
+ /*
|
|
|
+ * Since the SScount bitfield in GEN8_R_PWR_CLK_STATE is only three bits
|
|
|
+ * wide and Icelake has up to eight subslices, specfial programming is
|
|
|
+ * needed in order to correctly enable all subslices.
|
|
|
+ *
|
|
|
+ * According to documentation software must consider the configuration
|
|
|
+ * as 2x4x8 and hardware will translate this to 1x8x8.
|
|
|
+ *
|
|
|
+ * Furthemore, even though SScount is three bits, maximum documented
|
|
|
+ * value for it is four. From this some rules/restrictions follow:
|
|
|
+ *
|
|
|
+ * 1.
|
|
|
+ * If enabled subslice count is greater than four, two whole slices must
|
|
|
+ * be enabled instead.
|
|
|
+ *
|
|
|
+ * 2.
|
|
|
+ * When more than one slice is enabled, hardware ignores the subslice
|
|
|
+ * count altogether.
|
|
|
+ *
|
|
|
+ * From these restrictions it follows that it is not possible to enable
|
|
|
+ * a count of subslices between the SScount maximum of four restriction,
|
|
|
+ * and the maximum available number on a particular SKU. Either all
|
|
|
+ * subslices are enabled, or a count between one and four on the first
|
|
|
+ * slice.
|
|
|
+ */
|
|
|
+ if (IS_GEN11(dev_priv) && slices == 1 && subslices >= 4) {
|
|
|
+ GEM_BUG_ON(subslices & 1);
|
|
|
+
|
|
|
+ subslice_pg = false;
|
|
|
+ slices *= 2;
|
|
|
+ }
|
|
|
+
|
|
|
/*
|
|
|
* Starting in Gen9, render power gating can leave
|
|
|
* slice/subslice/EU in a partially enabled state. We
|
|
@@ -2496,24 +2531,50 @@ make_rpcs(struct drm_i915_private *dev_priv)
|
|
|
* enablement.
|
|
|
*/
|
|
|
if (INTEL_INFO(dev_priv)->sseu.has_slice_pg) {
|
|
|
- rpcs |= GEN8_RPCS_S_CNT_ENABLE;
|
|
|
- rpcs |= hweight8(INTEL_INFO(dev_priv)->sseu.slice_mask) <<
|
|
|
- GEN8_RPCS_S_CNT_SHIFT;
|
|
|
- rpcs |= GEN8_RPCS_ENABLE;
|
|
|
+ u32 mask, val = slices;
|
|
|
+
|
|
|
+ if (INTEL_GEN(dev_priv) >= 11) {
|
|
|
+ mask = GEN11_RPCS_S_CNT_MASK;
|
|
|
+ val <<= GEN11_RPCS_S_CNT_SHIFT;
|
|
|
+ } else {
|
|
|
+ mask = GEN8_RPCS_S_CNT_MASK;
|
|
|
+ val <<= GEN8_RPCS_S_CNT_SHIFT;
|
|
|
+ }
|
|
|
+
|
|
|
+ GEM_BUG_ON(val & ~mask);
|
|
|
+ val &= mask;
|
|
|
+
|
|
|
+ rpcs |= GEN8_RPCS_ENABLE | GEN8_RPCS_S_CNT_ENABLE | val;
|
|
|
}
|
|
|
|
|
|
- if (INTEL_INFO(dev_priv)->sseu.has_subslice_pg) {
|
|
|
- rpcs |= GEN8_RPCS_SS_CNT_ENABLE;
|
|
|
- rpcs |= hweight8(INTEL_INFO(dev_priv)->sseu.subslice_mask[0]) <<
|
|
|
- GEN8_RPCS_SS_CNT_SHIFT;
|
|
|
- rpcs |= GEN8_RPCS_ENABLE;
|
|
|
+ if (subslice_pg) {
|
|
|
+ u32 val = subslices;
|
|
|
+
|
|
|
+ val <<= GEN8_RPCS_SS_CNT_SHIFT;
|
|
|
+
|
|
|
+ GEM_BUG_ON(val & ~GEN8_RPCS_SS_CNT_MASK);
|
|
|
+ val &= GEN8_RPCS_SS_CNT_MASK;
|
|
|
+
|
|
|
+ rpcs |= GEN8_RPCS_ENABLE | GEN8_RPCS_SS_CNT_ENABLE | val;
|
|
|
}
|
|
|
|
|
|
if (INTEL_INFO(dev_priv)->sseu.has_eu_pg) {
|
|
|
- rpcs |= INTEL_INFO(dev_priv)->sseu.eu_per_subslice <<
|
|
|
- GEN8_RPCS_EU_MIN_SHIFT;
|
|
|
- rpcs |= INTEL_INFO(dev_priv)->sseu.eu_per_subslice <<
|
|
|
- GEN8_RPCS_EU_MAX_SHIFT;
|
|
|
+ u32 val;
|
|
|
+
|
|
|
+ val = INTEL_INFO(dev_priv)->sseu.eu_per_subslice <<
|
|
|
+ GEN8_RPCS_EU_MIN_SHIFT;
|
|
|
+ GEM_BUG_ON(val & ~GEN8_RPCS_EU_MIN_MASK);
|
|
|
+ val &= GEN8_RPCS_EU_MIN_MASK;
|
|
|
+
|
|
|
+ rpcs |= val;
|
|
|
+
|
|
|
+ val = INTEL_INFO(dev_priv)->sseu.eu_per_subslice <<
|
|
|
+ GEN8_RPCS_EU_MAX_SHIFT;
|
|
|
+ GEM_BUG_ON(val & ~GEN8_RPCS_EU_MAX_MASK);
|
|
|
+ val &= GEN8_RPCS_EU_MAX_MASK;
|
|
|
+
|
|
|
+ rpcs |= val;
|
|
|
+
|
|
|
rpcs |= GEN8_RPCS_ENABLE;
|
|
|
}
|
|
|
|