1 /* 2 * SPDX-License-Identifier: MIT 3 * 4 * Copyright © 2019 Intel Corporation 5 */ 6 7 #include "i915_drv.h" 8 #include "intel_lrc_reg.h" 9 #include "intel_sseu.h" 10 11 void intel_sseu_set_info(struct sseu_dev_info *sseu, u8 max_slices, 12 u8 max_subslices, u8 max_eus_per_subslice) 13 { 14 sseu->max_slices = max_slices; 15 sseu->max_subslices = max_subslices; 16 sseu->max_eus_per_subslice = max_eus_per_subslice; 17 18 sseu->ss_stride = GEN_SSEU_STRIDE(sseu->max_subslices); 19 GEM_BUG_ON(sseu->ss_stride > GEN_MAX_SUBSLICE_STRIDE); 20 sseu->eu_stride = GEN_SSEU_STRIDE(sseu->max_eus_per_subslice); 21 GEM_BUG_ON(sseu->eu_stride > GEN_MAX_EU_STRIDE); 22 } 23 24 unsigned int 25 intel_sseu_subslice_total(const struct sseu_dev_info *sseu) 26 { 27 unsigned int i, total = 0; 28 29 for (i = 0; i < ARRAY_SIZE(sseu->subslice_mask); i++) 30 total += hweight8(sseu->subslice_mask[i]); 31 32 return total; 33 } 34 35 u32 intel_sseu_get_subslices(const struct sseu_dev_info *sseu, u8 slice) 36 { 37 int i, offset = slice * sseu->ss_stride; 38 u32 mask = 0; 39 40 GEM_BUG_ON(slice >= sseu->max_slices); 41 42 for (i = 0; i < sseu->ss_stride; i++) 43 mask |= (u32)sseu->subslice_mask[offset + i] << 44 i * BITS_PER_BYTE; 45 46 return mask; 47 } 48 49 void intel_sseu_set_subslices(struct sseu_dev_info *sseu, int slice, 50 u32 ss_mask) 51 { 52 int offset = slice * sseu->ss_stride; 53 54 memcpy(&sseu->subslice_mask[offset], &ss_mask, sseu->ss_stride); 55 } 56 57 unsigned int 58 intel_sseu_subslices_per_slice(const struct sseu_dev_info *sseu, u8 slice) 59 { 60 return hweight32(intel_sseu_get_subslices(sseu, slice)); 61 } 62 63 u32 intel_sseu_make_rpcs(struct drm_i915_private *i915, 64 const struct intel_sseu *req_sseu) 65 { 66 const struct sseu_dev_info *sseu = &RUNTIME_INFO(i915)->sseu; 67 bool subslice_pg = sseu->has_subslice_pg; 68 struct intel_sseu ctx_sseu; 69 u8 slices, subslices; 70 u32 rpcs = 0; 71 72 /* 73 * No explicit RPCS request is needed to ensure full 74 * slice/subslice/EU enablement prior to Gen9. 75 */ 76 if (INTEL_GEN(i915) < 9) 77 return 0; 78 79 /* 80 * If i915/perf is active, we want a stable powergating configuration 81 * on the system. 82 * 83 * We could choose full enablement, but on ICL we know there are use 84 * cases which disable slices for functional, apart for performance 85 * reasons. So in this case we select a known stable subset. 86 */ 87 if (!i915->perf.exclusive_stream) { 88 ctx_sseu = *req_sseu; 89 } else { 90 ctx_sseu = intel_sseu_from_device_info(sseu); 91 92 if (IS_GEN(i915, 11)) { 93 /* 94 * We only need subslice count so it doesn't matter 95 * which ones we select - just turn off low bits in the 96 * amount of half of all available subslices per slice. 97 */ 98 ctx_sseu.subslice_mask = 99 ~(~0 << (hweight8(ctx_sseu.subslice_mask) / 2)); 100 ctx_sseu.slice_mask = 0x1; 101 } 102 } 103 104 slices = hweight8(ctx_sseu.slice_mask); 105 subslices = hweight8(ctx_sseu.subslice_mask); 106 107 /* 108 * Since the SScount bitfield in GEN8_R_PWR_CLK_STATE is only three bits 109 * wide and Icelake has up to eight subslices, specfial programming is 110 * needed in order to correctly enable all subslices. 111 * 112 * According to documentation software must consider the configuration 113 * as 2x4x8 and hardware will translate this to 1x8x8. 114 * 115 * Furthemore, even though SScount is three bits, maximum documented 116 * value for it is four. From this some rules/restrictions follow: 117 * 118 * 1. 119 * If enabled subslice count is greater than four, two whole slices must 120 * be enabled instead. 121 * 122 * 2. 123 * When more than one slice is enabled, hardware ignores the subslice 124 * count altogether. 125 * 126 * From these restrictions it follows that it is not possible to enable 127 * a count of subslices between the SScount maximum of four restriction, 128 * and the maximum available number on a particular SKU. Either all 129 * subslices are enabled, or a count between one and four on the first 130 * slice. 131 */ 132 if (IS_GEN(i915, 11) && 133 slices == 1 && 134 subslices > min_t(u8, 4, hweight8(sseu->subslice_mask[0]) / 2)) { 135 GEM_BUG_ON(subslices & 1); 136 137 subslice_pg = false; 138 slices *= 2; 139 } 140 141 /* 142 * Starting in Gen9, render power gating can leave 143 * slice/subslice/EU in a partially enabled state. We 144 * must make an explicit request through RPCS for full 145 * enablement. 146 */ 147 if (sseu->has_slice_pg) { 148 u32 mask, val = slices; 149 150 if (INTEL_GEN(i915) >= 11) { 151 mask = GEN11_RPCS_S_CNT_MASK; 152 val <<= GEN11_RPCS_S_CNT_SHIFT; 153 } else { 154 mask = GEN8_RPCS_S_CNT_MASK; 155 val <<= GEN8_RPCS_S_CNT_SHIFT; 156 } 157 158 GEM_BUG_ON(val & ~mask); 159 val &= mask; 160 161 rpcs |= GEN8_RPCS_ENABLE | GEN8_RPCS_S_CNT_ENABLE | val; 162 } 163 164 if (subslice_pg) { 165 u32 val = subslices; 166 167 val <<= GEN8_RPCS_SS_CNT_SHIFT; 168 169 GEM_BUG_ON(val & ~GEN8_RPCS_SS_CNT_MASK); 170 val &= GEN8_RPCS_SS_CNT_MASK; 171 172 rpcs |= GEN8_RPCS_ENABLE | GEN8_RPCS_SS_CNT_ENABLE | val; 173 } 174 175 if (sseu->has_eu_pg) { 176 u32 val; 177 178 val = ctx_sseu.min_eus_per_subslice << GEN8_RPCS_EU_MIN_SHIFT; 179 GEM_BUG_ON(val & ~GEN8_RPCS_EU_MIN_MASK); 180 val &= GEN8_RPCS_EU_MIN_MASK; 181 182 rpcs |= val; 183 184 val = ctx_sseu.max_eus_per_subslice << GEN8_RPCS_EU_MAX_SHIFT; 185 GEM_BUG_ON(val & ~GEN8_RPCS_EU_MAX_MASK); 186 val &= GEN8_RPCS_EU_MAX_MASK; 187 188 rpcs |= val; 189 190 rpcs |= GEN8_RPCS_ENABLE; 191 } 192 193 return rpcs; 194 } 195