]> Git Repo - linux.git/blob - drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c
Merge tag 'amd-drm-next-6.5-2023-06-09' of https://gitlab.freedesktop.org/agd5f/linux...
[linux.git] / drivers / gpu / drm / i915 / gt / intel_sseu_debugfs.c
1 // SPDX-License-Identifier: MIT
2
3 /*
4  * Copyright © 2020 Intel Corporation
5  */
6
7 #include <linux/bitmap.h>
8 #include <linux/string_helpers.h>
9
10 #include "i915_drv.h"
11 #include "intel_gt_debugfs.h"
12 #include "intel_gt_regs.h"
13 #include "intel_sseu_debugfs.h"
14
15 static void cherryview_sseu_device_status(struct intel_gt *gt,
16                                           struct sseu_dev_info *sseu)
17 {
18 #define SS_MAX 2
19         struct intel_uncore *uncore = gt->uncore;
20         const int ss_max = SS_MAX;
21         u32 sig1[SS_MAX], sig2[SS_MAX];
22         int ss;
23
24         sig1[0] = intel_uncore_read(uncore, CHV_POWER_SS0_SIG1);
25         sig1[1] = intel_uncore_read(uncore, CHV_POWER_SS1_SIG1);
26         sig2[0] = intel_uncore_read(uncore, CHV_POWER_SS0_SIG2);
27         sig2[1] = intel_uncore_read(uncore, CHV_POWER_SS1_SIG2);
28
29         for (ss = 0; ss < ss_max; ss++) {
30                 unsigned int eu_cnt;
31
32                 if (sig1[ss] & CHV_SS_PG_ENABLE)
33                         /* skip disabled subslice */
34                         continue;
35
36                 sseu->slice_mask = BIT(0);
37                 sseu->subslice_mask.hsw[0] |= BIT(ss);
38                 eu_cnt = ((sig1[ss] & CHV_EU08_PG_ENABLE) ? 0 : 2) +
39                          ((sig1[ss] & CHV_EU19_PG_ENABLE) ? 0 : 2) +
40                          ((sig1[ss] & CHV_EU210_PG_ENABLE) ? 0 : 2) +
41                          ((sig2[ss] & CHV_EU311_PG_ENABLE) ? 0 : 2);
42                 sseu->eu_total += eu_cnt;
43                 sseu->eu_per_subslice = max_t(unsigned int,
44                                               sseu->eu_per_subslice, eu_cnt);
45         }
46 #undef SS_MAX
47 }
48
49 static void gen11_sseu_device_status(struct intel_gt *gt,
50                                      struct sseu_dev_info *sseu)
51 {
52 #define SS_MAX 8
53         struct intel_uncore *uncore = gt->uncore;
54         const struct intel_gt_info *info = &gt->info;
55         u32 s_reg[SS_MAX], eu_reg[2 * SS_MAX], eu_mask[2];
56         int s, ss;
57
58         for (s = 0; s < info->sseu.max_slices; s++) {
59                 /*
60                  * FIXME: Valid SS Mask respects the spec and read
61                  * only valid bits for those registers, excluding reserved
62                  * although this seems wrong because it would leave many
63                  * subslices without ACK.
64                  */
65                 s_reg[s] = intel_uncore_read(uncore, GEN10_SLICE_PGCTL_ACK(s)) &
66                         GEN10_PGCTL_VALID_SS_MASK(s);
67                 eu_reg[2 * s] = intel_uncore_read(uncore,
68                                                   GEN10_SS01_EU_PGCTL_ACK(s));
69                 eu_reg[2 * s + 1] = intel_uncore_read(uncore,
70                                                       GEN10_SS23_EU_PGCTL_ACK(s));
71         }
72
73         eu_mask[0] = GEN9_PGCTL_SSA_EU08_ACK |
74                      GEN9_PGCTL_SSA_EU19_ACK |
75                      GEN9_PGCTL_SSA_EU210_ACK |
76                      GEN9_PGCTL_SSA_EU311_ACK;
77         eu_mask[1] = GEN9_PGCTL_SSB_EU08_ACK |
78                      GEN9_PGCTL_SSB_EU19_ACK |
79                      GEN9_PGCTL_SSB_EU210_ACK |
80                      GEN9_PGCTL_SSB_EU311_ACK;
81
82         for (s = 0; s < info->sseu.max_slices; s++) {
83                 if ((s_reg[s] & GEN9_PGCTL_SLICE_ACK) == 0)
84                         /* skip disabled slice */
85                         continue;
86
87                 sseu->slice_mask |= BIT(s);
88                 sseu->subslice_mask.hsw[s] = info->sseu.subslice_mask.hsw[s];
89
90                 for (ss = 0; ss < info->sseu.max_subslices; ss++) {
91                         unsigned int eu_cnt;
92
93                         if (info->sseu.has_subslice_pg &&
94                             !(s_reg[s] & (GEN9_PGCTL_SS_ACK(ss))))
95                                 /* skip disabled subslice */
96                                 continue;
97
98                         eu_cnt = 2 * hweight32(eu_reg[2 * s + ss / 2] &
99                                                eu_mask[ss % 2]);
100                         sseu->eu_total += eu_cnt;
101                         sseu->eu_per_subslice = max_t(unsigned int,
102                                                       sseu->eu_per_subslice,
103                                                       eu_cnt);
104                 }
105         }
106 #undef SS_MAX
107 }
108
109 static void gen9_sseu_device_status(struct intel_gt *gt,
110                                     struct sseu_dev_info *sseu)
111 {
112 #define SS_MAX 3
113         struct intel_uncore *uncore = gt->uncore;
114         const struct intel_gt_info *info = &gt->info;
115         u32 s_reg[SS_MAX], eu_reg[2 * SS_MAX], eu_mask[2];
116         int s, ss;
117
118         for (s = 0; s < info->sseu.max_slices; s++) {
119                 s_reg[s] = intel_uncore_read(uncore, GEN9_SLICE_PGCTL_ACK(s));
120                 eu_reg[2 * s] =
121                         intel_uncore_read(uncore, GEN9_SS01_EU_PGCTL_ACK(s));
122                 eu_reg[2 * s + 1] =
123                         intel_uncore_read(uncore, GEN9_SS23_EU_PGCTL_ACK(s));
124         }
125
126         eu_mask[0] = GEN9_PGCTL_SSA_EU08_ACK |
127                      GEN9_PGCTL_SSA_EU19_ACK |
128                      GEN9_PGCTL_SSA_EU210_ACK |
129                      GEN9_PGCTL_SSA_EU311_ACK;
130         eu_mask[1] = GEN9_PGCTL_SSB_EU08_ACK |
131                      GEN9_PGCTL_SSB_EU19_ACK |
132                      GEN9_PGCTL_SSB_EU210_ACK |
133                      GEN9_PGCTL_SSB_EU311_ACK;
134
135         for (s = 0; s < info->sseu.max_slices; s++) {
136                 if ((s_reg[s] & GEN9_PGCTL_SLICE_ACK) == 0)
137                         /* skip disabled slice */
138                         continue;
139
140                 sseu->slice_mask |= BIT(s);
141
142                 if (IS_GEN9_BC(gt->i915))
143                         sseu->subslice_mask.hsw[s] = info->sseu.subslice_mask.hsw[s];
144
145                 for (ss = 0; ss < info->sseu.max_subslices; ss++) {
146                         unsigned int eu_cnt;
147
148                         if (IS_GEN9_LP(gt->i915)) {
149                                 if (!(s_reg[s] & (GEN9_PGCTL_SS_ACK(ss))))
150                                         /* skip disabled subslice */
151                                         continue;
152
153                                 sseu->subslice_mask.hsw[s] |= BIT(ss);
154                         }
155
156                         eu_cnt = eu_reg[2 * s + ss / 2] & eu_mask[ss % 2];
157                         eu_cnt = 2 * hweight32(eu_cnt);
158
159                         sseu->eu_total += eu_cnt;
160                         sseu->eu_per_subslice = max_t(unsigned int,
161                                                       sseu->eu_per_subslice,
162                                                       eu_cnt);
163                 }
164         }
165 #undef SS_MAX
166 }
167
168 static void bdw_sseu_device_status(struct intel_gt *gt,
169                                    struct sseu_dev_info *sseu)
170 {
171         const struct intel_gt_info *info = &gt->info;
172         u32 slice_info = intel_uncore_read(gt->uncore, GEN8_GT_SLICE_INFO);
173         int s;
174
175         sseu->slice_mask = slice_info & GEN8_LSLICESTAT_MASK;
176
177         if (sseu->slice_mask) {
178                 sseu->eu_per_subslice = info->sseu.eu_per_subslice;
179                 for (s = 0; s < fls(sseu->slice_mask); s++)
180                         sseu->subslice_mask.hsw[s] = info->sseu.subslice_mask.hsw[s];
181                 sseu->eu_total = sseu->eu_per_subslice *
182                                  intel_sseu_subslice_total(sseu);
183
184                 /* subtract fused off EU(s) from enabled slice(s) */
185                 for (s = 0; s < fls(sseu->slice_mask); s++) {
186                         u8 subslice_7eu = info->sseu.subslice_7eu[s];
187
188                         sseu->eu_total -= hweight8(subslice_7eu);
189                 }
190         }
191 }
192
193 static void i915_print_sseu_info(struct seq_file *m,
194                                  bool is_available_info,
195                                  bool has_pooled_eu,
196                                  const struct sseu_dev_info *sseu)
197 {
198         const char *type = is_available_info ? "Available" : "Enabled";
199
200         seq_printf(m, "  %s Slice Mask: %04x\n", type,
201                    sseu->slice_mask);
202         seq_printf(m, "  %s Slice Total: %u\n", type,
203                    hweight8(sseu->slice_mask));
204         seq_printf(m, "  %s Subslice Total: %u\n", type,
205                    intel_sseu_subslice_total(sseu));
206         intel_sseu_print_ss_info(type, sseu, m);
207         seq_printf(m, "  %s EU Total: %u\n", type,
208                    sseu->eu_total);
209         seq_printf(m, "  %s EU Per Subslice: %u\n", type,
210                    sseu->eu_per_subslice);
211
212         if (!is_available_info)
213                 return;
214
215         seq_printf(m, "  Has Pooled EU: %s\n", str_yes_no(has_pooled_eu));
216         if (has_pooled_eu)
217                 seq_printf(m, "  Min EU in pool: %u\n", sseu->min_eu_in_pool);
218
219         seq_printf(m, "  Has Slice Power Gating: %s\n",
220                    str_yes_no(sseu->has_slice_pg));
221         seq_printf(m, "  Has Subslice Power Gating: %s\n",
222                    str_yes_no(sseu->has_subslice_pg));
223         seq_printf(m, "  Has EU Power Gating: %s\n",
224                    str_yes_no(sseu->has_eu_pg));
225 }
226
227 /*
228  * this is called from top-level debugfs as well, so we can't get the gt from
229  * the seq_file.
230  */
231 int intel_sseu_status(struct seq_file *m, struct intel_gt *gt)
232 {
233         struct drm_i915_private *i915 = gt->i915;
234         const struct intel_gt_info *info = &gt->info;
235         struct sseu_dev_info *sseu;
236         intel_wakeref_t wakeref;
237
238         if (GRAPHICS_VER(i915) < 8)
239                 return -ENODEV;
240
241         seq_puts(m, "SSEU Device Info\n");
242         i915_print_sseu_info(m, true, HAS_POOLED_EU(i915), &info->sseu);
243
244         seq_puts(m, "SSEU Device Status\n");
245
246         sseu = kzalloc(sizeof(*sseu), GFP_KERNEL);
247         if (!sseu)
248                 return -ENOMEM;
249
250         intel_sseu_set_info(sseu, info->sseu.max_slices,
251                             info->sseu.max_subslices,
252                             info->sseu.max_eus_per_subslice);
253
254         with_intel_runtime_pm(&i915->runtime_pm, wakeref) {
255                 if (IS_CHERRYVIEW(i915))
256                         cherryview_sseu_device_status(gt, sseu);
257                 else if (IS_BROADWELL(i915))
258                         bdw_sseu_device_status(gt, sseu);
259                 else if (GRAPHICS_VER(i915) == 9)
260                         gen9_sseu_device_status(gt, sseu);
261                 else if (GRAPHICS_VER(i915) >= 11)
262                         gen11_sseu_device_status(gt, sseu);
263         }
264
265         i915_print_sseu_info(m, false, HAS_POOLED_EU(i915), sseu);
266
267         kfree(sseu);
268
269         return 0;
270 }
271
272 static int sseu_status_show(struct seq_file *m, void *unused)
273 {
274         struct intel_gt *gt = m->private;
275
276         return intel_sseu_status(m, gt);
277 }
278 DEFINE_INTEL_GT_DEBUGFS_ATTRIBUTE(sseu_status);
279
280 static int sseu_topology_show(struct seq_file *m, void *unused)
281 {
282         struct intel_gt *gt = m->private;
283         struct drm_printer p = drm_seq_file_printer(m);
284
285         intel_sseu_print_topology(gt->i915, &gt->info.sseu, &p);
286
287         return 0;
288 }
289 DEFINE_INTEL_GT_DEBUGFS_ATTRIBUTE(sseu_topology);
290
291 void intel_sseu_debugfs_register(struct intel_gt *gt, struct dentry *root)
292 {
293         static const struct intel_gt_debugfs_file files[] = {
294                 { "sseu_status", &sseu_status_fops, NULL },
295                 { "sseu_topology", &sseu_topology_fops, NULL },
296         };
297
298         intel_gt_debugfs_register_files(root, files, ARRAY_SIZE(files), gt);
299 }
This page took 0.051392 seconds and 4 git commands to generate.