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