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