]> Git Repo - linux.git/blob - drivers/gpu/drm/etnaviv/etnaviv_perfmon.c
Linux 6.14-rc3
[linux.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         unsigned int feature;
36         const struct etnaviv_pm_domain *domains;
37         u32 nr_domains;
38 };
39
40 static u32 perf_reg_read(struct etnaviv_gpu *gpu,
41         const struct etnaviv_pm_domain *domain,
42         const struct etnaviv_pm_signal *signal)
43 {
44         gpu_write(gpu, domain->profile_config, signal->data);
45
46         return gpu_read(gpu, domain->profile_read);
47 }
48
49 static inline void pipe_select(struct etnaviv_gpu *gpu, u32 clock, unsigned pipe)
50 {
51         clock &= ~(VIVS_HI_CLOCK_CONTROL_DEBUG_PIXEL_PIPE__MASK);
52         clock |= VIVS_HI_CLOCK_CONTROL_DEBUG_PIXEL_PIPE(pipe);
53
54         gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, clock);
55 }
56
57 static u32 pipe_perf_reg_read(struct etnaviv_gpu *gpu,
58         const struct etnaviv_pm_domain *domain,
59         const struct etnaviv_pm_signal *signal)
60 {
61         u32 clock = gpu_read(gpu, VIVS_HI_CLOCK_CONTROL);
62         u32 value = 0;
63         unsigned i;
64
65         lockdep_assert_held(&gpu->lock);
66
67         for (i = 0; i < gpu->identity.pixel_pipes; i++) {
68                 pipe_select(gpu, clock, i);
69                 value += perf_reg_read(gpu, domain, signal);
70         }
71
72         /* switch back to pixel pipe 0 to prevent GPU hang */
73         pipe_select(gpu, clock, 0);
74
75         return value;
76 }
77
78 static u32 pipe_reg_read(struct etnaviv_gpu *gpu,
79         const struct etnaviv_pm_domain *domain,
80         const struct etnaviv_pm_signal *signal)
81 {
82         u32 clock = gpu_read(gpu, VIVS_HI_CLOCK_CONTROL);
83         u32 value = 0;
84         unsigned i;
85
86         lockdep_assert_held(&gpu->lock);
87
88         for (i = 0; i < gpu->identity.pixel_pipes; i++) {
89                 pipe_select(gpu, clock, i);
90                 value += gpu_read(gpu, signal->data);
91         }
92
93         /* switch back to pixel pipe 0 to prevent GPU hang */
94         pipe_select(gpu, clock, 0);
95
96         return value;
97 }
98
99 static u32 hi_total_cycle_read(struct etnaviv_gpu *gpu,
100         const struct etnaviv_pm_domain *domain,
101         const struct etnaviv_pm_signal *signal)
102 {
103         u32 reg = VIVS_HI_PROFILE_TOTAL_CYCLES;
104
105         if (gpu->identity.model == chipModel_GC880 ||
106                 gpu->identity.model == chipModel_GC2000 ||
107                 gpu->identity.model == chipModel_GC2100)
108                 reg = VIVS_MC_PROFILE_CYCLE_COUNTER;
109
110         return gpu_read(gpu, reg);
111 }
112
113 static u32 hi_total_idle_cycle_read(struct etnaviv_gpu *gpu,
114         const struct etnaviv_pm_domain *domain,
115         const struct etnaviv_pm_signal *signal)
116 {
117         u32 reg = VIVS_HI_PROFILE_IDLE_CYCLES;
118
119         if (gpu->identity.model == chipModel_GC880 ||
120                 gpu->identity.model == chipModel_GC2000 ||
121                 gpu->identity.model == chipModel_GC2100)
122                 reg = VIVS_HI_PROFILE_TOTAL_CYCLES;
123
124         return gpu_read(gpu, reg);
125 }
126
127 static const struct etnaviv_pm_domain doms_3d[] = {
128         {
129                 .name = "HI",
130                 .profile_read = VIVS_MC_PROFILE_HI_READ,
131                 .profile_config = VIVS_MC_PROFILE_CONFIG2,
132                 .nr_signals = 7,
133                 .signal = (const struct etnaviv_pm_signal[]) {
134                         {
135                                 "TOTAL_READ_BYTES8",
136                                 VIVS_HI_PROFILE_READ_BYTES8,
137                                 &pipe_reg_read,
138                         },
139                         {
140                                 "TOTAL_WRITE_BYTES8",
141                                 VIVS_HI_PROFILE_WRITE_BYTES8,
142                                 &pipe_reg_read,
143                         },
144                         {
145                                 "TOTAL_CYCLES",
146                                 0,
147                                 &hi_total_cycle_read
148                         },
149                         {
150                                 "IDLE_CYCLES",
151                                 0,
152                                 &hi_total_idle_cycle_read
153                         },
154                         {
155                                 "AXI_CYCLES_READ_REQUEST_STALLED",
156                                 VIVS_MC_PROFILE_CONFIG2_HI_AXI_CYCLES_READ_REQUEST_STALLED,
157                                 &perf_reg_read
158                         },
159                         {
160                                 "AXI_CYCLES_WRITE_REQUEST_STALLED",
161                                 VIVS_MC_PROFILE_CONFIG2_HI_AXI_CYCLES_WRITE_REQUEST_STALLED,
162                                 &perf_reg_read
163                         },
164                         {
165                                 "AXI_CYCLES_WRITE_DATA_STALLED",
166                                 VIVS_MC_PROFILE_CONFIG2_HI_AXI_CYCLES_WRITE_DATA_STALLED,
167                                 &perf_reg_read
168                         }
169                 }
170         },
171         {
172                 .name = "PE",
173                 .profile_read = VIVS_MC_PROFILE_PE_READ,
174                 .profile_config = VIVS_MC_PROFILE_CONFIG0,
175                 .nr_signals = 4,
176                 .signal = (const struct etnaviv_pm_signal[]) {
177                         {
178                                 "PIXEL_COUNT_KILLED_BY_COLOR_PIPE",
179                                 VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_KILLED_BY_COLOR_PIPE,
180                                 &pipe_perf_reg_read
181                         },
182                         {
183                                 "PIXEL_COUNT_KILLED_BY_DEPTH_PIPE",
184                                 VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_KILLED_BY_DEPTH_PIPE,
185                                 &pipe_perf_reg_read
186                         },
187                         {
188                                 "PIXEL_COUNT_DRAWN_BY_COLOR_PIPE",
189                                 VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_DRAWN_BY_COLOR_PIPE,
190                                 &pipe_perf_reg_read
191                         },
192                         {
193                                 "PIXEL_COUNT_DRAWN_BY_DEPTH_PIPE",
194                                 VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_DRAWN_BY_DEPTH_PIPE,
195                                 &pipe_perf_reg_read
196                         }
197                 }
198         },
199         {
200                 .name = "SH",
201                 .profile_read = VIVS_MC_PROFILE_SH_READ,
202                 .profile_config = VIVS_MC_PROFILE_CONFIG0,
203                 .nr_signals = 9,
204                 .signal = (const struct etnaviv_pm_signal[]) {
205                         {
206                                 "SHADER_CYCLES",
207                                 VIVS_MC_PROFILE_CONFIG0_SH_SHADER_CYCLES,
208                                 &perf_reg_read
209                         },
210                         {
211                                 "PS_INST_COUNTER",
212                                 VIVS_MC_PROFILE_CONFIG0_SH_PS_INST_COUNTER,
213                                 &perf_reg_read
214                         },
215                         {
216                                 "RENDERED_PIXEL_COUNTER",
217                                 VIVS_MC_PROFILE_CONFIG0_SH_RENDERED_PIXEL_COUNTER,
218                                 &perf_reg_read
219                         },
220                         {
221                                 "VS_INST_COUNTER",
222                                 VIVS_MC_PROFILE_CONFIG0_SH_VS_INST_COUNTER,
223                                 &pipe_perf_reg_read
224                         },
225                         {
226                                 "RENDERED_VERTICE_COUNTER",
227                                 VIVS_MC_PROFILE_CONFIG0_SH_RENDERED_VERTICE_COUNTER,
228                                 &pipe_perf_reg_read
229                         },
230                         {
231                                 "VTX_BRANCH_INST_COUNTER",
232                                 VIVS_MC_PROFILE_CONFIG0_SH_VTX_BRANCH_INST_COUNTER,
233                                 &pipe_perf_reg_read
234                         },
235                         {
236                                 "VTX_TEXLD_INST_COUNTER",
237                                 VIVS_MC_PROFILE_CONFIG0_SH_VTX_TEXLD_INST_COUNTER,
238                                 &pipe_perf_reg_read
239                         },
240                         {
241                                 "PXL_BRANCH_INST_COUNTER",
242                                 VIVS_MC_PROFILE_CONFIG0_SH_PXL_BRANCH_INST_COUNTER,
243                                 &pipe_perf_reg_read
244                         },
245                         {
246                                 "PXL_TEXLD_INST_COUNTER",
247                                 VIVS_MC_PROFILE_CONFIG0_SH_PXL_TEXLD_INST_COUNTER,
248                                 &pipe_perf_reg_read
249                         }
250                 }
251         },
252         {
253                 .name = "PA",
254                 .profile_read = VIVS_MC_PROFILE_PA_READ,
255                 .profile_config = VIVS_MC_PROFILE_CONFIG1,
256                 .nr_signals = 6,
257                 .signal = (const struct etnaviv_pm_signal[]) {
258                         {
259                                 "INPUT_VTX_COUNTER",
260                                 VIVS_MC_PROFILE_CONFIG1_PA_INPUT_VTX_COUNTER,
261                                 &perf_reg_read
262                         },
263                         {
264                                 "INPUT_PRIM_COUNTER",
265                                 VIVS_MC_PROFILE_CONFIG1_PA_INPUT_PRIM_COUNTER,
266                                 &perf_reg_read
267                         },
268                         {
269                                 "OUTPUT_PRIM_COUNTER",
270                                 VIVS_MC_PROFILE_CONFIG1_PA_OUTPUT_PRIM_COUNTER,
271                                 &perf_reg_read
272                         },
273                         {
274                                 "DEPTH_CLIPPED_COUNTER",
275                                 VIVS_MC_PROFILE_CONFIG1_PA_DEPTH_CLIPPED_COUNTER,
276                                 &pipe_perf_reg_read
277                         },
278                         {
279                                 "TRIVIAL_REJECTED_COUNTER",
280                                 VIVS_MC_PROFILE_CONFIG1_PA_TRIVIAL_REJECTED_COUNTER,
281                                 &pipe_perf_reg_read
282                         },
283                         {
284                                 "CULLED_COUNTER",
285                                 VIVS_MC_PROFILE_CONFIG1_PA_CULLED_COUNTER,
286                                 &pipe_perf_reg_read
287                         }
288                 }
289         },
290         {
291                 .name = "SE",
292                 .profile_read = VIVS_MC_PROFILE_SE_READ,
293                 .profile_config = VIVS_MC_PROFILE_CONFIG1,
294                 .nr_signals = 2,
295                 .signal = (const struct etnaviv_pm_signal[]) {
296                         {
297                                 "CULLED_TRIANGLE_COUNT",
298                                 VIVS_MC_PROFILE_CONFIG1_SE_CULLED_TRIANGLE_COUNT,
299                                 &perf_reg_read
300                         },
301                         {
302                                 "CULLED_LINES_COUNT",
303                                 VIVS_MC_PROFILE_CONFIG1_SE_CULLED_LINES_COUNT,
304                                 &perf_reg_read
305                         }
306                 }
307         },
308         {
309                 .name = "RA",
310                 .profile_read = VIVS_MC_PROFILE_RA_READ,
311                 .profile_config = VIVS_MC_PROFILE_CONFIG1,
312                 .nr_signals = 7,
313                 .signal = (const struct etnaviv_pm_signal[]) {
314                         {
315                                 "VALID_PIXEL_COUNT",
316                                 VIVS_MC_PROFILE_CONFIG1_RA_VALID_PIXEL_COUNT,
317                                 &perf_reg_read
318                         },
319                         {
320                                 "TOTAL_QUAD_COUNT",
321                                 VIVS_MC_PROFILE_CONFIG1_RA_TOTAL_QUAD_COUNT,
322                                 &perf_reg_read
323                         },
324                         {
325                                 "VALID_QUAD_COUNT_AFTER_EARLY_Z",
326                                 VIVS_MC_PROFILE_CONFIG1_RA_VALID_QUAD_COUNT_AFTER_EARLY_Z,
327                                 &perf_reg_read
328                         },
329                         {
330                                 "TOTAL_PRIMITIVE_COUNT",
331                                 VIVS_MC_PROFILE_CONFIG1_RA_TOTAL_PRIMITIVE_COUNT,
332                                 &perf_reg_read
333                         },
334                         {
335                                 "PIPE_CACHE_MISS_COUNTER",
336                                 VIVS_MC_PROFILE_CONFIG1_RA_PIPE_CACHE_MISS_COUNTER,
337                                 &perf_reg_read
338                         },
339                         {
340                                 "PREFETCH_CACHE_MISS_COUNTER",
341                                 VIVS_MC_PROFILE_CONFIG1_RA_PREFETCH_CACHE_MISS_COUNTER,
342                                 &perf_reg_read
343                         },
344                         {
345                                 "CULLED_QUAD_COUNT",
346                                 VIVS_MC_PROFILE_CONFIG1_RA_CULLED_QUAD_COUNT,
347                                 &perf_reg_read
348                         }
349                 }
350         },
351         {
352                 .name = "TX",
353                 .profile_read = VIVS_MC_PROFILE_TX_READ,
354                 .profile_config = VIVS_MC_PROFILE_CONFIG1,
355                 .nr_signals = 9,
356                 .signal = (const struct etnaviv_pm_signal[]) {
357                         {
358                                 "TOTAL_BILINEAR_REQUESTS",
359                                 VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_BILINEAR_REQUESTS,
360                                 &perf_reg_read
361                         },
362                         {
363                                 "TOTAL_TRILINEAR_REQUESTS",
364                                 VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_TRILINEAR_REQUESTS,
365                                 &perf_reg_read
366                         },
367                         {
368                                 "TOTAL_DISCARDED_TEXTURE_REQUESTS",
369                                 VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_DISCARDED_TEXTURE_REQUESTS,
370                                 &perf_reg_read
371                         },
372                         {
373                                 "TOTAL_TEXTURE_REQUESTS",
374                                 VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_TEXTURE_REQUESTS,
375                                 &perf_reg_read
376                         },
377                         {
378                                 "MEM_READ_COUNT",
379                                 VIVS_MC_PROFILE_CONFIG1_TX_MEM_READ_COUNT,
380                                 &perf_reg_read
381                         },
382                         {
383                                 "MEM_READ_IN_8B_COUNT",
384                                 VIVS_MC_PROFILE_CONFIG1_TX_MEM_READ_IN_8B_COUNT,
385                                 &perf_reg_read
386                         },
387                         {
388                                 "CACHE_MISS_COUNT",
389                                 VIVS_MC_PROFILE_CONFIG1_TX_CACHE_MISS_COUNT,
390                                 &perf_reg_read
391                         },
392                         {
393                                 "CACHE_HIT_TEXEL_COUNT",
394                                 VIVS_MC_PROFILE_CONFIG1_TX_CACHE_HIT_TEXEL_COUNT,
395                                 &perf_reg_read
396                         },
397                         {
398                                 "CACHE_MISS_TEXEL_COUNT",
399                                 VIVS_MC_PROFILE_CONFIG1_TX_CACHE_MISS_TEXEL_COUNT,
400                                 &perf_reg_read
401                         }
402                 }
403         },
404         {
405                 .name = "MC",
406                 .profile_read = VIVS_MC_PROFILE_MC_READ,
407                 .profile_config = VIVS_MC_PROFILE_CONFIG2,
408                 .nr_signals = 3,
409                 .signal = (const struct etnaviv_pm_signal[]) {
410                         {
411                                 "TOTAL_READ_REQ_8B_FROM_PIPELINE",
412                                 VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_READ_REQ_8B_FROM_PIPELINE,
413                                 &perf_reg_read
414                         },
415                         {
416                                 "TOTAL_READ_REQ_8B_FROM_IP",
417                                 VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_READ_REQ_8B_FROM_IP,
418                                 &perf_reg_read
419                         },
420                         {
421                                 "TOTAL_WRITE_REQ_8B_FROM_PIPELINE",
422                                 VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_WRITE_REQ_8B_FROM_PIPELINE,
423                                 &perf_reg_read
424                         }
425                 }
426         }
427 };
428
429 static const struct etnaviv_pm_domain doms_2d[] = {
430         {
431                 .name = "PE",
432                 .profile_read = VIVS_MC_PROFILE_PE_READ,
433                 .profile_config = VIVS_MC_PROFILE_CONFIG0,
434                 .nr_signals = 1,
435                 .signal = (const struct etnaviv_pm_signal[]) {
436                         {
437                                 "PIXELS_RENDERED_2D",
438                                 VIVS_MC_PROFILE_CONFIG0_PE_PIXELS_RENDERED_2D,
439                                 &pipe_perf_reg_read
440                         }
441                 }
442         }
443 };
444
445 static const struct etnaviv_pm_domain doms_vg[] = {
446 };
447
448 static const struct etnaviv_pm_domain_meta doms_meta[] = {
449         {
450                 .feature = chipFeatures_PIPE_3D,
451                 .nr_domains = ARRAY_SIZE(doms_3d),
452                 .domains = &doms_3d[0]
453         },
454         {
455                 .feature = chipFeatures_PIPE_2D,
456                 .nr_domains = ARRAY_SIZE(doms_2d),
457                 .domains = &doms_2d[0]
458         },
459         {
460                 .feature = chipFeatures_PIPE_VG,
461                 .nr_domains = ARRAY_SIZE(doms_vg),
462                 .domains = &doms_vg[0]
463         }
464 };
465
466 static unsigned int num_pm_domains(const struct etnaviv_gpu *gpu)
467 {
468         unsigned int num = 0, i;
469
470         for (i = 0; i < ARRAY_SIZE(doms_meta); i++) {
471                 const struct etnaviv_pm_domain_meta *meta = &doms_meta[i];
472
473                 if (gpu->identity.features & meta->feature)
474                         num += meta->nr_domains;
475         }
476
477         return num;
478 }
479
480 static const struct etnaviv_pm_domain *pm_domain(const struct etnaviv_gpu *gpu,
481         unsigned int index)
482 {
483         const struct etnaviv_pm_domain *domain = NULL;
484         unsigned int offset = 0, i;
485
486         for (i = 0; i < ARRAY_SIZE(doms_meta); i++) {
487                 const struct etnaviv_pm_domain_meta *meta = &doms_meta[i];
488
489                 if (!(gpu->identity.features & meta->feature))
490                         continue;
491
492                 if (index - offset >= meta->nr_domains) {
493                         offset += meta->nr_domains;
494                         continue;
495                 }
496
497                 domain = meta->domains + (index - offset);
498         }
499
500         return domain;
501 }
502
503 int etnaviv_pm_query_dom(struct etnaviv_gpu *gpu,
504         struct drm_etnaviv_pm_domain *domain)
505 {
506         const unsigned int nr_domains = num_pm_domains(gpu);
507         const struct etnaviv_pm_domain *dom;
508
509         if (domain->iter >= nr_domains)
510                 return -EINVAL;
511
512         dom = pm_domain(gpu, domain->iter);
513         if (!dom)
514                 return -EINVAL;
515
516         domain->id = domain->iter;
517         domain->nr_signals = dom->nr_signals;
518         strscpy_pad(domain->name, dom->name, sizeof(domain->name));
519
520         domain->iter++;
521         if (domain->iter == nr_domains)
522                 domain->iter = 0xff;
523
524         return 0;
525 }
526
527 int etnaviv_pm_query_sig(struct etnaviv_gpu *gpu,
528         struct drm_etnaviv_pm_signal *signal)
529 {
530         const unsigned int nr_domains = num_pm_domains(gpu);
531         const struct etnaviv_pm_domain *dom;
532         const struct etnaviv_pm_signal *sig;
533
534         if (signal->domain >= nr_domains)
535                 return -EINVAL;
536
537         dom = pm_domain(gpu, signal->domain);
538         if (!dom)
539                 return -EINVAL;
540
541         if (signal->iter >= dom->nr_signals)
542                 return -EINVAL;
543
544         sig = &dom->signal[signal->iter];
545
546         signal->id = signal->iter;
547         strscpy_pad(signal->name, sig->name, sizeof(signal->name));
548
549         signal->iter++;
550         if (signal->iter == dom->nr_signals)
551                 signal->iter = 0xffff;
552
553         return 0;
554 }
555
556 int etnaviv_pm_req_validate(const struct drm_etnaviv_gem_submit_pmr *r,
557         u32 exec_state)
558 {
559         const struct etnaviv_pm_domain_meta *meta = &doms_meta[exec_state];
560         const struct etnaviv_pm_domain *dom;
561
562         if (r->domain >= meta->nr_domains)
563                 return -EINVAL;
564
565         dom = meta->domains + r->domain;
566
567         if (r->signal >= dom->nr_signals)
568                 return -EINVAL;
569
570         return 0;
571 }
572
573 void etnaviv_perfmon_process(struct etnaviv_gpu *gpu,
574         const struct etnaviv_perfmon_request *pmr, u32 exec_state)
575 {
576         const struct etnaviv_pm_domain_meta *meta = &doms_meta[exec_state];
577         const struct etnaviv_pm_domain *dom;
578         const struct etnaviv_pm_signal *sig;
579         u32 *bo = pmr->bo_vma;
580         u32 val;
581
582         dom = meta->domains + pmr->domain;
583         sig = &dom->signal[pmr->signal];
584         val = sig->sample(gpu, dom, sig);
585
586         *(bo + pmr->offset) = val;
587 }
This page took 0.065189 seconds and 4 git commands to generate.