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