Merge tag 'drm-intel-next-2019-05-24' of git://anongit.freedesktop.org/drm/drm-intel...
[linux-2.6-microblaze.git] / drivers / gpu / drm / i915 / gt / intel_sseu.c
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 }