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