xref: /openbmc/linux/drivers/gpu/drm/i915/gt/intel_sseu.c (revision 55fd7e02)
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 	u8 slices, subslices;
69 	u32 rpcs = 0;
70 
71 	/*
72 	 * No explicit RPCS request is needed to ensure full
73 	 * slice/subslice/EU enablement prior to Gen9.
74 	 */
75 	if (INTEL_GEN(i915) < 9)
76 		return 0;
77 
78 	/*
79 	 * If i915/perf is active, we want a stable powergating configuration
80 	 * on the system. Use the configuration pinned by i915/perf.
81 	 */
82 	if (i915->perf.exclusive_stream)
83 		req_sseu = &i915->perf.sseu;
84 
85 	slices = hweight8(req_sseu->slice_mask);
86 	subslices = hweight8(req_sseu->subslice_mask);
87 
88 	/*
89 	 * Since the SScount bitfield in GEN8_R_PWR_CLK_STATE is only three bits
90 	 * wide and Icelake has up to eight subslices, specfial programming is
91 	 * needed in order to correctly enable all subslices.
92 	 *
93 	 * According to documentation software must consider the configuration
94 	 * as 2x4x8 and hardware will translate this to 1x8x8.
95 	 *
96 	 * Furthemore, even though SScount is three bits, maximum documented
97 	 * value for it is four. From this some rules/restrictions follow:
98 	 *
99 	 * 1.
100 	 * If enabled subslice count is greater than four, two whole slices must
101 	 * be enabled instead.
102 	 *
103 	 * 2.
104 	 * When more than one slice is enabled, hardware ignores the subslice
105 	 * count altogether.
106 	 *
107 	 * From these restrictions it follows that it is not possible to enable
108 	 * a count of subslices between the SScount maximum of four restriction,
109 	 * and the maximum available number on a particular SKU. Either all
110 	 * subslices are enabled, or a count between one and four on the first
111 	 * slice.
112 	 */
113 	if (IS_GEN(i915, 11) &&
114 	    slices == 1 &&
115 	    subslices > min_t(u8, 4, hweight8(sseu->subslice_mask[0]) / 2)) {
116 		GEM_BUG_ON(subslices & 1);
117 
118 		subslice_pg = false;
119 		slices *= 2;
120 	}
121 
122 	/*
123 	 * Starting in Gen9, render power gating can leave
124 	 * slice/subslice/EU in a partially enabled state. We
125 	 * must make an explicit request through RPCS for full
126 	 * enablement.
127 	 */
128 	if (sseu->has_slice_pg) {
129 		u32 mask, val = slices;
130 
131 		if (INTEL_GEN(i915) >= 11) {
132 			mask = GEN11_RPCS_S_CNT_MASK;
133 			val <<= GEN11_RPCS_S_CNT_SHIFT;
134 		} else {
135 			mask = GEN8_RPCS_S_CNT_MASK;
136 			val <<= GEN8_RPCS_S_CNT_SHIFT;
137 		}
138 
139 		GEM_BUG_ON(val & ~mask);
140 		val &= mask;
141 
142 		rpcs |= GEN8_RPCS_ENABLE | GEN8_RPCS_S_CNT_ENABLE | val;
143 	}
144 
145 	if (subslice_pg) {
146 		u32 val = subslices;
147 
148 		val <<= GEN8_RPCS_SS_CNT_SHIFT;
149 
150 		GEM_BUG_ON(val & ~GEN8_RPCS_SS_CNT_MASK);
151 		val &= GEN8_RPCS_SS_CNT_MASK;
152 
153 		rpcs |= GEN8_RPCS_ENABLE | GEN8_RPCS_SS_CNT_ENABLE | val;
154 	}
155 
156 	if (sseu->has_eu_pg) {
157 		u32 val;
158 
159 		val = req_sseu->min_eus_per_subslice << GEN8_RPCS_EU_MIN_SHIFT;
160 		GEM_BUG_ON(val & ~GEN8_RPCS_EU_MIN_MASK);
161 		val &= GEN8_RPCS_EU_MIN_MASK;
162 
163 		rpcs |= val;
164 
165 		val = req_sseu->max_eus_per_subslice << GEN8_RPCS_EU_MAX_SHIFT;
166 		GEM_BUG_ON(val & ~GEN8_RPCS_EU_MAX_MASK);
167 		val &= GEN8_RPCS_EU_MAX_MASK;
168 
169 		rpcs |= val;
170 
171 		rpcs |= GEN8_RPCS_ENABLE;
172 	}
173 
174 	return rpcs;
175 }
176