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