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