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