From 57ec171eae21ee0a2848ade1cb7f8f12a31b0731 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 31 Aug 2016 19:13:05 +0300 Subject: drm/i915: sseu: Convert subslice count fields to subslice mask In an upcoming patch we'll need the actual mask of subslices in addition to their count, so convert the subslice_per_slice field to a mask. Also we can easily calculate subslice_total from the other fields, so instead of storing a cached version of this, add a helper to calculate it. v2: - Use hweight8() on u8 typed vars instead of hweight32(). (Ben) Reviewed-by: Robert Bragg (v1) Reviewed-by: Ben Widawsky (v1) Tested-by: Ben Widawsky (v1) Signed-off-by: Imre Deak --- drivers/gpu/drm/i915/i915_debugfs.c | 37 +++++++---------- drivers/gpu/drm/i915/i915_drv.c | 2 +- drivers/gpu/drm/i915/i915_drv.h | 8 +++- drivers/gpu/drm/i915/intel_device_info.c | 69 +++++++++++++++----------------- drivers/gpu/drm/i915/intel_lrc.c | 2 +- 5 files changed, 55 insertions(+), 63 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 0ba28a8ad669..d09c77f141ed 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -5008,7 +5008,7 @@ static void cherryview_sseu_device_status(struct drm_i915_private *dev_priv, continue; sseu->slice_mask = BIT(0); - sseu->subslice_per_slice++; + sseu->subslice_mask |= BIT(ss); eu_cnt = ((sig1[ss] & CHV_EU08_PG_ENABLE) ? 0 : 2) + ((sig1[ss] & CHV_EU19_PG_ENABLE) ? 0 : 2) + ((sig1[ss] & CHV_EU210_PG_ENABLE) ? 0 : 2) + @@ -5017,7 +5017,6 @@ static void cherryview_sseu_device_status(struct drm_i915_private *dev_priv, sseu->eu_per_subslice = max_t(unsigned int, sseu->eu_per_subslice, eu_cnt); } - sseu->subslice_total = sseu->subslice_per_slice; } static void gen9_sseu_device_status(struct drm_i915_private *dev_priv, @@ -5049,8 +5048,6 @@ static void gen9_sseu_device_status(struct drm_i915_private *dev_priv, GEN9_PGCTL_SSB_EU311_ACK; for (s = 0; s < s_max; s++) { - unsigned int ss_cnt = 0; - if ((s_reg[s] & GEN9_PGCTL_SLICE_ACK) == 0) /* skip disabled slice */ continue; @@ -5058,18 +5055,19 @@ static void gen9_sseu_device_status(struct drm_i915_private *dev_priv, sseu->slice_mask |= BIT(s); if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) - ss_cnt = INTEL_INFO(dev_priv)->sseu.subslice_per_slice; + sseu->subslice_mask = + INTEL_INFO(dev_priv)->sseu.subslice_mask; for (ss = 0; ss < ss_max; ss++) { unsigned int eu_cnt; - if (IS_BROXTON(dev_priv) && - !(s_reg[s] & (GEN9_PGCTL_SS_ACK(ss)))) - /* skip disabled subslice */ - continue; + if (IS_BROXTON(dev_priv)) { + if (!(s_reg[s] & (GEN9_PGCTL_SS_ACK(ss)))) + /* skip disabled subslice */ + continue; - if (IS_BROXTON(dev_priv)) - ss_cnt++; + sseu->subslice_mask |= BIT(ss); + } eu_cnt = 2 * hweight32(eu_reg[2*s + ss/2] & eu_mask[ss%2]); @@ -5078,11 +5076,6 @@ static void gen9_sseu_device_status(struct drm_i915_private *dev_priv, sseu->eu_per_subslice, eu_cnt); } - - sseu->subslice_total += ss_cnt; - sseu->subslice_per_slice = max_t(unsigned int, - sseu->subslice_per_slice, - ss_cnt); } } @@ -5095,13 +5088,11 @@ static void broadwell_sseu_device_status(struct drm_i915_private *dev_priv, sseu->slice_mask = slice_info & GEN8_LSLICESTAT_MASK; if (sseu->slice_mask) { - sseu->subslice_per_slice = - INTEL_INFO(dev_priv)->sseu.subslice_per_slice; - sseu->subslice_total = hweight8(sseu->slice_mask) * - sseu->subslice_per_slice; + sseu->subslice_mask = INTEL_INFO(dev_priv)->sseu.subslice_mask; sseu->eu_per_subslice = INTEL_INFO(dev_priv)->sseu.eu_per_subslice; - sseu->eu_total = sseu->eu_per_subslice * sseu->subslice_total; + sseu->eu_total = sseu->eu_per_subslice * + sseu_subslice_total(sseu); /* subtract fused off EU(s) from enabled slice(s) */ for (s = 0; s < hweight8(sseu->slice_mask); s++) { @@ -5122,9 +5113,9 @@ static void i915_print_sseu_info(struct seq_file *m, bool is_available_info, seq_printf(m, " %s Slice Total: %u\n", type, hweight8(sseu->slice_mask)); seq_printf(m, " %s Subslice Total: %u\n", type, - sseu->subslice_total); + sseu_subslice_total(sseu)); seq_printf(m, " %s Subslice Per Slice: %u\n", type, - sseu->subslice_per_slice); + hweight8(sseu->subslice_mask)); seq_printf(m, " %s EU Total: %u\n", type, sseu->eu_total); seq_printf(m, " %s EU Per Subslice: %u\n", type, diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 5e22105b728f..02c34d6996ea 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -288,7 +288,7 @@ static int i915_getparam(struct drm_device *dev, void *data, value = i915_cmd_parser_get_version(dev_priv); break; case I915_PARAM_SUBSLICE_TOTAL: - value = INTEL_INFO(dev_priv)->sseu.subslice_total; + value = sseu_subslice_total(&INTEL_INFO(dev_priv)->sseu); if (!value) return -ENODEV; break; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 1ebc5ba69e34..757b1d1b9366 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -673,8 +673,7 @@ struct intel_csr { struct sseu_dev_info { u8 slice_mask; - u8 subslice_total; - u8 subslice_per_slice; + u8 subslice_mask; u8 eu_total; u8 eu_per_subslice; u8 min_eu_in_pool; @@ -685,6 +684,11 @@ struct sseu_dev_info { u8 has_eu_pg:1; }; +static inline unsigned int sseu_subslice_total(const struct sseu_dev_info *sseu) +{ + return hweight8(sseu->slice_mask) * hweight8(sseu->subslice_mask); +} + struct intel_device_info { u32 display_mmio_offset; u16 device_id; diff --git a/drivers/gpu/drm/i915/intel_device_info.c b/drivers/gpu/drm/i915/intel_device_info.c index 139d5298cde5..0bdec5c59f48 100644 --- a/drivers/gpu/drm/i915/intel_device_info.c +++ b/drivers/gpu/drm/i915/intel_device_info.c @@ -54,26 +54,25 @@ static void cherryview_sseu_info_init(struct drm_i915_private *dev_priv) sseu->slice_mask = BIT(0); if (!(fuse & CHV_FGT_DISABLE_SS0)) { - sseu->subslice_per_slice++; + sseu->subslice_mask |= BIT(0); eu_dis = fuse & (CHV_FGT_EU_DIS_SS0_R0_MASK | CHV_FGT_EU_DIS_SS0_R1_MASK); sseu->eu_total += 8 - hweight32(eu_dis); } if (!(fuse & CHV_FGT_DISABLE_SS1)) { - sseu->subslice_per_slice++; + sseu->subslice_mask |= BIT(1); eu_dis = fuse & (CHV_FGT_EU_DIS_SS1_R0_MASK | CHV_FGT_EU_DIS_SS1_R1_MASK); sseu->eu_total += 8 - hweight32(eu_dis); } - sseu->subslice_total = sseu->subslice_per_slice; /* * CHV expected to always have a uniform distribution of EU * across subslices. */ - sseu->eu_per_subslice = sseu->subslice_total ? - sseu->eu_total / sseu->subslice_total : + sseu->eu_per_subslice = sseu_subslice_total(sseu) ? + sseu->eu_total / sseu_subslice_total(sseu) : 0; /* * CHV supports subslice power gating on devices with more than @@ -81,7 +80,7 @@ static void cherryview_sseu_info_init(struct drm_i915_private *dev_priv) * more than one EU pair per subslice. */ sseu->has_slice_pg = 0; - sseu->has_subslice_pg = (sseu->subslice_total > 1); + sseu->has_subslice_pg = sseu_subslice_total(sseu) > 1; sseu->has_eu_pg = (sseu->eu_per_subslice > 2); } @@ -91,20 +90,19 @@ static void gen9_sseu_info_init(struct drm_i915_private *dev_priv) struct sseu_dev_info *sseu = &info->sseu; int s_max = 3, ss_max = 4, eu_max = 8; int s, ss; - u32 fuse2, ss_disable, eu_disable; + u32 fuse2, eu_disable; u8 eu_mask = 0xff; fuse2 = I915_READ(GEN8_FUSE2); sseu->slice_mask = (fuse2 & GEN8_F2_S_ENA_MASK) >> GEN8_F2_S_ENA_SHIFT; - ss_disable = (fuse2 & GEN9_F2_SS_DIS_MASK) >> GEN9_F2_SS_DIS_SHIFT; /* * The subslice disable field is global, i.e. it applies * to each of the enabled slices. */ - sseu->subslice_per_slice = ss_max - hweight32(ss_disable); - sseu->subslice_total = hweight8(sseu->slice_mask) * - sseu->subslice_per_slice; + sseu->subslice_mask = (1 << ss_max) - 1; + sseu->subslice_mask &= ~((fuse2 & GEN9_F2_SS_DIS_MASK) >> + GEN9_F2_SS_DIS_SHIFT); /* * Iterate through enabled slices and subslices to @@ -119,7 +117,7 @@ static void gen9_sseu_info_init(struct drm_i915_private *dev_priv) for (ss = 0; ss < ss_max; ss++) { int eu_per_ss; - if (ss_disable & BIT(ss)) + if (!(sseu->subslice_mask & BIT(ss))) /* skip disabled subslice */ continue; @@ -145,9 +143,9 @@ static void gen9_sseu_info_init(struct drm_i915_private *dev_priv) * recovery. BXT is expected to be perfectly uniform in EU * distribution. */ - sseu->eu_per_subslice = sseu->subslice_total ? + sseu->eu_per_subslice = sseu_subslice_total(sseu) ? DIV_ROUND_UP(sseu->eu_total, - sseu->subslice_total) : 0; + sseu_subslice_total(sseu)) : 0; /* * SKL supports slice power gating on devices with more than * one slice, and supports EU power gating on devices with @@ -160,11 +158,11 @@ static void gen9_sseu_info_init(struct drm_i915_private *dev_priv) (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) && hweight8(sseu->slice_mask) > 1; sseu->has_subslice_pg = - IS_BROXTON(dev_priv) && sseu->subslice_total > 1; + IS_BROXTON(dev_priv) && sseu_subslice_total(sseu) > 1; sseu->has_eu_pg = sseu->eu_per_subslice > 2; if (IS_BROXTON(dev_priv)) { -#define IS_SS_DISABLED(_ss_disable, ss) (_ss_disable & BIT(ss)) +#define IS_SS_DISABLED(ss) (!(sseu->subslice_mask & BIT(ss))) /* * There is a HW issue in 2x6 fused down parts that requires * Pooled EU to be enabled as a WA. The pool configuration @@ -172,16 +170,15 @@ static void gen9_sseu_info_init(struct drm_i915_private *dev_priv) * doesn't affect if the device has all 3 subslices enabled. */ /* WaEnablePooledEuFor2x6:bxt */ - info->has_pooled_eu = ((sseu->subslice_per_slice == 3) || - (sseu->subslice_per_slice == 2 && + info->has_pooled_eu = ((hweight8(sseu->subslice_mask) == 3) || + (hweight8(sseu->subslice_mask) == 2 && INTEL_REVID(dev_priv) < BXT_REVID_C0)); sseu->min_eu_in_pool = 0; if (info->has_pooled_eu) { - if (IS_SS_DISABLED(ss_disable, 0) || - IS_SS_DISABLED(ss_disable, 2)) + if (IS_SS_DISABLED(2) || IS_SS_DISABLED(0)) sseu->min_eu_in_pool = 3; - else if (IS_SS_DISABLED(ss_disable, 1)) + else if (IS_SS_DISABLED(1)) sseu->min_eu_in_pool = 6; else sseu->min_eu_in_pool = 9; @@ -195,11 +192,17 @@ static void broadwell_sseu_info_init(struct drm_i915_private *dev_priv) struct sseu_dev_info *sseu = &mkwrite_device_info(dev_priv)->sseu; const int s_max = 3, ss_max = 3, eu_max = 8; int s, ss; - u32 fuse2, eu_disable[s_max], ss_disable; + u32 fuse2, eu_disable[s_max]; fuse2 = I915_READ(GEN8_FUSE2); sseu->slice_mask = (fuse2 & GEN8_F2_S_ENA_MASK) >> GEN8_F2_S_ENA_SHIFT; - ss_disable = (fuse2 & GEN8_F2_SS_DIS_MASK) >> GEN8_F2_SS_DIS_SHIFT; + /* + * The subslice disable field is global, i.e. it applies + * to each of the enabled slices. + */ + sseu->subslice_mask = BIT(ss_max) - 1; + sseu->subslice_mask &= ~((fuse2 & GEN8_F2_SS_DIS_MASK) >> + GEN8_F2_SS_DIS_SHIFT); eu_disable[0] = I915_READ(GEN8_EU_DISABLE0) & GEN8_EU_DIS0_S0_MASK; eu_disable[1] = (I915_READ(GEN8_EU_DISABLE0) >> GEN8_EU_DIS0_S1_SHIFT) | @@ -209,14 +212,6 @@ static void broadwell_sseu_info_init(struct drm_i915_private *dev_priv) ((I915_READ(GEN8_EU_DISABLE2) & GEN8_EU_DIS2_S2_MASK) << (32 - GEN8_EU_DIS1_S2_SHIFT)); - /* - * The subslice disable field is global, i.e. it applies - * to each of the enabled slices. - */ - sseu->subslice_per_slice = ss_max - hweight32(ss_disable); - sseu->subslice_total = hweight8(sseu->slice_mask) * - sseu->subslice_per_slice; - /* * Iterate through enabled slices and subslices to * count the total enabled EU. @@ -229,7 +224,7 @@ static void broadwell_sseu_info_init(struct drm_i915_private *dev_priv) for (ss = 0; ss < ss_max; ss++) { u32 n_disabled; - if (ss_disable & (0x1 << ss)) + if (!(sseu->subslice_mask & BIT(ss))) /* skip disabled subslice */ continue; @@ -250,8 +245,9 @@ static void broadwell_sseu_info_init(struct drm_i915_private *dev_priv) * subslices with the exception that any one EU in any one subslice may * be fused off for die recovery. */ - sseu->eu_per_subslice = sseu->subslice_total ? - DIV_ROUND_UP(sseu->eu_total, sseu->subslice_total) : 0; + sseu->eu_per_subslice = sseu_subslice_total(sseu) ? + DIV_ROUND_UP(sseu->eu_total, + sseu_subslice_total(sseu)) : 0; /* * BDW supports slice power gating on devices with more than @@ -375,9 +371,10 @@ void intel_device_info_runtime_init(struct drm_i915_private *dev_priv) info->has_snoop = false; DRM_DEBUG_DRIVER("slice total: %u\n", hweight8(info->sseu.slice_mask)); - DRM_DEBUG_DRIVER("subslice total: %u\n", info->sseu.subslice_total); + DRM_DEBUG_DRIVER("subslice total: %u\n", + sseu_subslice_total(&info->sseu)); DRM_DEBUG_DRIVER("subslice per slice: %u\n", - info->sseu.subslice_per_slice); + hweight8(info->sseu.subslice_mask)); DRM_DEBUG_DRIVER("EU total: %u\n", info->sseu.eu_total); DRM_DEBUG_DRIVER("EU per subslice: %u\n", info->sseu.eu_per_subslice); DRM_DEBUG_DRIVER("has slice power gating: %s\n", diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 7209553ab162..92bfe47ad33c 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1905,7 +1905,7 @@ make_rpcs(struct drm_i915_private *dev_priv) if (INTEL_INFO(dev_priv)->sseu.has_subslice_pg) { rpcs |= GEN8_RPCS_SS_CNT_ENABLE; - rpcs |= INTEL_INFO(dev_priv)->sseu.subslice_per_slice << + rpcs |= hweight8(INTEL_INFO(dev_priv)->sseu.subslice_mask) << GEN8_RPCS_SS_CNT_SHIFT; rpcs |= GEN8_RPCS_ENABLE; } -- cgit v1.2.3-59-g8ed1b