]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blob - drivers/gpu/drm/etnaviv/etnaviv_perfmon.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
[mirror_ubuntu-jammy-kernel.git] / drivers / gpu / drm / etnaviv / etnaviv_perfmon.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (C) 2017 Etnaviv Project
4 * Copyright (C) 2017 Zodiac Inflight Innovations
5 */
6
7 #include "common.xml.h"
8 #include "etnaviv_gpu.h"
9 #include "etnaviv_perfmon.h"
10 #include "state_hi.xml.h"
11
12 struct etnaviv_pm_domain;
13
14 struct etnaviv_pm_signal {
15 char name[64];
16 u32 data;
17
18 u32 (*sample)(struct etnaviv_gpu *gpu,
19 const struct etnaviv_pm_domain *domain,
20 const struct etnaviv_pm_signal *signal);
21 };
22
23 struct etnaviv_pm_domain {
24 char name[64];
25
26 /* profile register */
27 u32 profile_read;
28 u32 profile_config;
29
30 u8 nr_signals;
31 const struct etnaviv_pm_signal *signal;
32 };
33
34 struct etnaviv_pm_domain_meta {
35 const struct etnaviv_pm_domain *domains;
36 u32 nr_domains;
37 };
38
39 static u32 perf_reg_read(struct etnaviv_gpu *gpu,
40 const struct etnaviv_pm_domain *domain,
41 const struct etnaviv_pm_signal *signal)
42 {
43 gpu_write(gpu, domain->profile_config, signal->data);
44
45 return gpu_read(gpu, domain->profile_read);
46 }
47
48 static u32 pipe_reg_read(struct etnaviv_gpu *gpu,
49 const struct etnaviv_pm_domain *domain,
50 const struct etnaviv_pm_signal *signal)
51 {
52 u32 clock = gpu_read(gpu, VIVS_HI_CLOCK_CONTROL);
53 u32 value = 0;
54 unsigned i;
55
56 for (i = 0; i < gpu->identity.pixel_pipes; i++) {
57 clock &= ~(VIVS_HI_CLOCK_CONTROL_DEBUG_PIXEL_PIPE__MASK);
58 clock |= VIVS_HI_CLOCK_CONTROL_DEBUG_PIXEL_PIPE(i);
59 gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, clock);
60 gpu_write(gpu, domain->profile_config, signal->data);
61 value += gpu_read(gpu, domain->profile_read);
62 }
63
64 /* switch back to pixel pipe 0 to prevent GPU hang */
65 clock &= ~(VIVS_HI_CLOCK_CONTROL_DEBUG_PIXEL_PIPE__MASK);
66 clock |= VIVS_HI_CLOCK_CONTROL_DEBUG_PIXEL_PIPE(0);
67 gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, clock);
68
69 return value;
70 }
71
72 static u32 hi_total_cycle_read(struct etnaviv_gpu *gpu,
73 const struct etnaviv_pm_domain *domain,
74 const struct etnaviv_pm_signal *signal)
75 {
76 u32 reg = VIVS_HI_PROFILE_TOTAL_CYCLES;
77
78 if (gpu->identity.model == chipModel_GC880 ||
79 gpu->identity.model == chipModel_GC2000 ||
80 gpu->identity.model == chipModel_GC2100)
81 reg = VIVS_MC_PROFILE_CYCLE_COUNTER;
82
83 return gpu_read(gpu, reg);
84 }
85
86 static u32 hi_total_idle_cycle_read(struct etnaviv_gpu *gpu,
87 const struct etnaviv_pm_domain *domain,
88 const struct etnaviv_pm_signal *signal)
89 {
90 u32 reg = VIVS_HI_PROFILE_IDLE_CYCLES;
91
92 if (gpu->identity.model == chipModel_GC880 ||
93 gpu->identity.model == chipModel_GC2000 ||
94 gpu->identity.model == chipModel_GC2100)
95 reg = VIVS_HI_PROFILE_TOTAL_CYCLES;
96
97 return gpu_read(gpu, reg);
98 }
99
100 static const struct etnaviv_pm_domain doms_3d[] = {
101 {
102 .name = "HI",
103 .profile_read = VIVS_MC_PROFILE_HI_READ,
104 .profile_config = VIVS_MC_PROFILE_CONFIG2,
105 .nr_signals = 5,
106 .signal = (const struct etnaviv_pm_signal[]) {
107 {
108 "TOTAL_CYCLES",
109 0,
110 &hi_total_cycle_read
111 },
112 {
113 "IDLE_CYCLES",
114 0,
115 &hi_total_idle_cycle_read
116 },
117 {
118 "AXI_CYCLES_READ_REQUEST_STALLED",
119 VIVS_MC_PROFILE_CONFIG2_HI_AXI_CYCLES_READ_REQUEST_STALLED,
120 &perf_reg_read
121 },
122 {
123 "AXI_CYCLES_WRITE_REQUEST_STALLED",
124 VIVS_MC_PROFILE_CONFIG2_HI_AXI_CYCLES_WRITE_REQUEST_STALLED,
125 &perf_reg_read
126 },
127 {
128 "AXI_CYCLES_WRITE_DATA_STALLED",
129 VIVS_MC_PROFILE_CONFIG2_HI_AXI_CYCLES_WRITE_DATA_STALLED,
130 &perf_reg_read
131 }
132 }
133 },
134 {
135 .name = "PE",
136 .profile_read = VIVS_MC_PROFILE_PE_READ,
137 .profile_config = VIVS_MC_PROFILE_CONFIG0,
138 .nr_signals = 4,
139 .signal = (const struct etnaviv_pm_signal[]) {
140 {
141 "PIXEL_COUNT_KILLED_BY_COLOR_PIPE",
142 VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_KILLED_BY_COLOR_PIPE,
143 &pipe_reg_read
144 },
145 {
146 "PIXEL_COUNT_KILLED_BY_DEPTH_PIPE",
147 VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_KILLED_BY_DEPTH_PIPE,
148 &pipe_reg_read
149 },
150 {
151 "PIXEL_COUNT_DRAWN_BY_COLOR_PIPE",
152 VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_DRAWN_BY_COLOR_PIPE,
153 &pipe_reg_read
154 },
155 {
156 "PIXEL_COUNT_DRAWN_BY_DEPTH_PIPE",
157 VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_DRAWN_BY_DEPTH_PIPE,
158 &pipe_reg_read
159 }
160 }
161 },
162 {
163 .name = "SH",
164 .profile_read = VIVS_MC_PROFILE_SH_READ,
165 .profile_config = VIVS_MC_PROFILE_CONFIG0,
166 .nr_signals = 9,
167 .signal = (const struct etnaviv_pm_signal[]) {
168 {
169 "SHADER_CYCLES",
170 VIVS_MC_PROFILE_CONFIG0_SH_SHADER_CYCLES,
171 &perf_reg_read
172 },
173 {
174 "PS_INST_COUNTER",
175 VIVS_MC_PROFILE_CONFIG0_SH_PS_INST_COUNTER,
176 &perf_reg_read
177 },
178 {
179 "RENDERED_PIXEL_COUNTER",
180 VIVS_MC_PROFILE_CONFIG0_SH_RENDERED_PIXEL_COUNTER,
181 &perf_reg_read
182 },
183 {
184 "VS_INST_COUNTER",
185 VIVS_MC_PROFILE_CONFIG0_SH_VS_INST_COUNTER,
186 &pipe_reg_read
187 },
188 {
189 "RENDERED_VERTICE_COUNTER",
190 VIVS_MC_PROFILE_CONFIG0_SH_RENDERED_VERTICE_COUNTER,
191 &pipe_reg_read
192 },
193 {
194 "VTX_BRANCH_INST_COUNTER",
195 VIVS_MC_PROFILE_CONFIG0_SH_VTX_BRANCH_INST_COUNTER,
196 &pipe_reg_read
197 },
198 {
199 "VTX_TEXLD_INST_COUNTER",
200 VIVS_MC_PROFILE_CONFIG0_SH_VTX_TEXLD_INST_COUNTER,
201 &pipe_reg_read
202 },
203 {
204 "PXL_BRANCH_INST_COUNTER",
205 VIVS_MC_PROFILE_CONFIG0_SH_PXL_BRANCH_INST_COUNTER,
206 &pipe_reg_read
207 },
208 {
209 "PXL_TEXLD_INST_COUNTER",
210 VIVS_MC_PROFILE_CONFIG0_SH_PXL_TEXLD_INST_COUNTER,
211 &pipe_reg_read
212 }
213 }
214 },
215 {
216 .name = "PA",
217 .profile_read = VIVS_MC_PROFILE_PA_READ,
218 .profile_config = VIVS_MC_PROFILE_CONFIG1,
219 .nr_signals = 6,
220 .signal = (const struct etnaviv_pm_signal[]) {
221 {
222 "INPUT_VTX_COUNTER",
223 VIVS_MC_PROFILE_CONFIG1_PA_INPUT_VTX_COUNTER,
224 &perf_reg_read
225 },
226 {
227 "INPUT_PRIM_COUNTER",
228 VIVS_MC_PROFILE_CONFIG1_PA_INPUT_PRIM_COUNTER,
229 &perf_reg_read
230 },
231 {
232 "OUTPUT_PRIM_COUNTER",
233 VIVS_MC_PROFILE_CONFIG1_PA_OUTPUT_PRIM_COUNTER,
234 &perf_reg_read
235 },
236 {
237 "DEPTH_CLIPPED_COUNTER",
238 VIVS_MC_PROFILE_CONFIG1_PA_DEPTH_CLIPPED_COUNTER,
239 &pipe_reg_read
240 },
241 {
242 "TRIVIAL_REJECTED_COUNTER",
243 VIVS_MC_PROFILE_CONFIG1_PA_TRIVIAL_REJECTED_COUNTER,
244 &pipe_reg_read
245 },
246 {
247 "CULLED_COUNTER",
248 VIVS_MC_PROFILE_CONFIG1_PA_CULLED_COUNTER,
249 &pipe_reg_read
250 }
251 }
252 },
253 {
254 .name = "SE",
255 .profile_read = VIVS_MC_PROFILE_SE_READ,
256 .profile_config = VIVS_MC_PROFILE_CONFIG1,
257 .nr_signals = 2,
258 .signal = (const struct etnaviv_pm_signal[]) {
259 {
260 "CULLED_TRIANGLE_COUNT",
261 VIVS_MC_PROFILE_CONFIG1_SE_CULLED_TRIANGLE_COUNT,
262 &perf_reg_read
263 },
264 {
265 "CULLED_LINES_COUNT",
266 VIVS_MC_PROFILE_CONFIG1_SE_CULLED_LINES_COUNT,
267 &perf_reg_read
268 }
269 }
270 },
271 {
272 .name = "RA",
273 .profile_read = VIVS_MC_PROFILE_RA_READ,
274 .profile_config = VIVS_MC_PROFILE_CONFIG1,
275 .nr_signals = 7,
276 .signal = (const struct etnaviv_pm_signal[]) {
277 {
278 "VALID_PIXEL_COUNT",
279 VIVS_MC_PROFILE_CONFIG1_RA_VALID_PIXEL_COUNT,
280 &perf_reg_read
281 },
282 {
283 "TOTAL_QUAD_COUNT",
284 VIVS_MC_PROFILE_CONFIG1_RA_TOTAL_QUAD_COUNT,
285 &perf_reg_read
286 },
287 {
288 "VALID_QUAD_COUNT_AFTER_EARLY_Z",
289 VIVS_MC_PROFILE_CONFIG1_RA_VALID_QUAD_COUNT_AFTER_EARLY_Z,
290 &perf_reg_read
291 },
292 {
293 "TOTAL_PRIMITIVE_COUNT",
294 VIVS_MC_PROFILE_CONFIG1_RA_TOTAL_PRIMITIVE_COUNT,
295 &perf_reg_read
296 },
297 {
298 "PIPE_CACHE_MISS_COUNTER",
299 VIVS_MC_PROFILE_CONFIG1_RA_PIPE_CACHE_MISS_COUNTER,
300 &perf_reg_read
301 },
302 {
303 "PREFETCH_CACHE_MISS_COUNTER",
304 VIVS_MC_PROFILE_CONFIG1_RA_PREFETCH_CACHE_MISS_COUNTER,
305 &perf_reg_read
306 },
307 {
308 "CULLED_QUAD_COUNT",
309 VIVS_MC_PROFILE_CONFIG1_RA_CULLED_QUAD_COUNT,
310 &perf_reg_read
311 }
312 }
313 },
314 {
315 .name = "TX",
316 .profile_read = VIVS_MC_PROFILE_TX_READ,
317 .profile_config = VIVS_MC_PROFILE_CONFIG1,
318 .nr_signals = 9,
319 .signal = (const struct etnaviv_pm_signal[]) {
320 {
321 "TOTAL_BILINEAR_REQUESTS",
322 VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_BILINEAR_REQUESTS,
323 &perf_reg_read
324 },
325 {
326 "TOTAL_TRILINEAR_REQUESTS",
327 VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_TRILINEAR_REQUESTS,
328 &perf_reg_read
329 },
330 {
331 "TOTAL_DISCARDED_TEXTURE_REQUESTS",
332 VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_DISCARDED_TEXTURE_REQUESTS,
333 &perf_reg_read
334 },
335 {
336 "TOTAL_TEXTURE_REQUESTS",
337 VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_TEXTURE_REQUESTS,
338 &perf_reg_read
339 },
340 {
341 "MEM_READ_COUNT",
342 VIVS_MC_PROFILE_CONFIG1_TX_MEM_READ_COUNT,
343 &perf_reg_read
344 },
345 {
346 "MEM_READ_IN_8B_COUNT",
347 VIVS_MC_PROFILE_CONFIG1_TX_MEM_READ_IN_8B_COUNT,
348 &perf_reg_read
349 },
350 {
351 "CACHE_MISS_COUNT",
352 VIVS_MC_PROFILE_CONFIG1_TX_CACHE_MISS_COUNT,
353 &perf_reg_read
354 },
355 {
356 "CACHE_HIT_TEXEL_COUNT",
357 VIVS_MC_PROFILE_CONFIG1_TX_CACHE_HIT_TEXEL_COUNT,
358 &perf_reg_read
359 },
360 {
361 "CACHE_MISS_TEXEL_COUNT",
362 VIVS_MC_PROFILE_CONFIG1_TX_CACHE_MISS_TEXEL_COUNT,
363 &perf_reg_read
364 }
365 }
366 },
367 {
368 .name = "MC",
369 .profile_read = VIVS_MC_PROFILE_MC_READ,
370 .profile_config = VIVS_MC_PROFILE_CONFIG2,
371 .nr_signals = 3,
372 .signal = (const struct etnaviv_pm_signal[]) {
373 {
374 "TOTAL_READ_REQ_8B_FROM_PIPELINE",
375 VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_READ_REQ_8B_FROM_PIPELINE,
376 &perf_reg_read
377 },
378 {
379 "TOTAL_READ_REQ_8B_FROM_IP",
380 VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_READ_REQ_8B_FROM_IP,
381 &perf_reg_read
382 },
383 {
384 "TOTAL_WRITE_REQ_8B_FROM_PIPELINE",
385 VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_WRITE_REQ_8B_FROM_PIPELINE,
386 &perf_reg_read
387 }
388 }
389 }
390 };
391
392 static const struct etnaviv_pm_domain doms_2d[] = {
393 {
394 .name = "PE",
395 .profile_read = VIVS_MC_PROFILE_PE_READ,
396 .profile_config = VIVS_MC_PROFILE_CONFIG0,
397 .nr_signals = 1,
398 .signal = (const struct etnaviv_pm_signal[]) {
399 {
400 "PIXELS_RENDERED_2D",
401 VIVS_MC_PROFILE_CONFIG0_PE_PIXELS_RENDERED_2D,
402 &pipe_reg_read
403 }
404 }
405 }
406 };
407
408 static const struct etnaviv_pm_domain doms_vg[] = {
409 };
410
411 static const struct etnaviv_pm_domain_meta doms_meta[] = {
412 {
413 .nr_domains = ARRAY_SIZE(doms_3d),
414 .domains = &doms_3d[0]
415 },
416 {
417 .nr_domains = ARRAY_SIZE(doms_2d),
418 .domains = &doms_2d[0]
419 },
420 {
421 .nr_domains = ARRAY_SIZE(doms_vg),
422 .domains = &doms_vg[0]
423 }
424 };
425
426 int etnaviv_pm_query_dom(struct etnaviv_gpu *gpu,
427 struct drm_etnaviv_pm_domain *domain)
428 {
429 const struct etnaviv_pm_domain_meta *meta = &doms_meta[domain->pipe];
430 const struct etnaviv_pm_domain *dom;
431
432 if (domain->iter >= meta->nr_domains)
433 return -EINVAL;
434
435 dom = meta->domains + domain->iter;
436
437 domain->id = domain->iter;
438 domain->nr_signals = dom->nr_signals;
439 strncpy(domain->name, dom->name, sizeof(domain->name));
440
441 domain->iter++;
442 if (domain->iter == meta->nr_domains)
443 domain->iter = 0xff;
444
445 return 0;
446 }
447
448 int etnaviv_pm_query_sig(struct etnaviv_gpu *gpu,
449 struct drm_etnaviv_pm_signal *signal)
450 {
451 const struct etnaviv_pm_domain_meta *meta = &doms_meta[signal->pipe];
452 const struct etnaviv_pm_domain *dom;
453 const struct etnaviv_pm_signal *sig;
454
455 if (signal->domain >= meta->nr_domains)
456 return -EINVAL;
457
458 dom = meta->domains + signal->domain;
459
460 if (signal->iter >= dom->nr_signals)
461 return -EINVAL;
462
463 sig = &dom->signal[signal->iter];
464
465 signal->id = signal->iter;
466 strncpy(signal->name, sig->name, sizeof(signal->name));
467
468 signal->iter++;
469 if (signal->iter == dom->nr_signals)
470 signal->iter = 0xffff;
471
472 return 0;
473 }
474
475 int etnaviv_pm_req_validate(const struct drm_etnaviv_gem_submit_pmr *r,
476 u32 exec_state)
477 {
478 const struct etnaviv_pm_domain_meta *meta = &doms_meta[exec_state];
479 const struct etnaviv_pm_domain *dom;
480
481 if (r->domain >= meta->nr_domains)
482 return -EINVAL;
483
484 dom = meta->domains + r->domain;
485
486 if (r->signal >= dom->nr_signals)
487 return -EINVAL;
488
489 return 0;
490 }
491
492 void etnaviv_perfmon_process(struct etnaviv_gpu *gpu,
493 const struct etnaviv_perfmon_request *pmr, u32 exec_state)
494 {
495 const struct etnaviv_pm_domain_meta *meta = &doms_meta[exec_state];
496 const struct etnaviv_pm_domain *dom;
497 const struct etnaviv_pm_signal *sig;
498 u32 *bo = pmr->bo_vma;
499 u32 val;
500
501 dom = meta->domains + pmr->domain;
502 sig = &dom->signal[pmr->signal];
503 val = sig->sample(gpu, dom, sig);
504
505 *(bo + pmr->offset) = val;
506 }