]>
Commit | Line | Data |
---|---|---|
9e2c2e27 CG |
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" | |
249300c7 | 19 | #include "etnaviv_perfmon.h" |
33deff0a | 20 | #include "state_hi.xml.h" |
9e2c2e27 CG |
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]; | |
33deff0a CG |
35 | |
36 | /* profile register */ | |
37 | u32 profile_read; | |
38 | u32 profile_config; | |
39 | ||
9e2c2e27 CG |
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 | ||
33deff0a CG |
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 | ||
a3d0c390 CG |
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 | ||
9e2c2e27 | 89 | static const struct etnaviv_pm_domain doms_3d[] = { |
33deff0a CG |
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 | } | |
a3d0c390 CG |
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 | } | |
98b2482e CG |
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 | } | |
c3787ff6 CG |
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 | } | |
33deff0a | 241 | } |
9e2c2e27 CG |
242 | }; |
243 | ||
244 | static const struct etnaviv_pm_domain doms_2d[] = { | |
a3d0c390 CG |
245 | { |
246 | .name = "PE", | |
247 | .profile_read = VIVS_MC_PROFILE_PE_READ, | |
248 | .profile_config = VIVS_MC_PROFILE_CONFIG0, | |
249 | .nr_signals = 1, | |
250 | .signal = (const struct etnaviv_pm_signal[]) { | |
251 | { | |
252 | "PIXELS_RENDERED_2D", | |
253 | VIVS_MC_PROFILE_CONFIG0_PE_PIXELS_RENDERED_2D, | |
254 | &pipe_reg_read | |
255 | } | |
256 | } | |
257 | } | |
9e2c2e27 CG |
258 | }; |
259 | ||
260 | static const struct etnaviv_pm_domain doms_vg[] = { | |
261 | }; | |
262 | ||
263 | static const struct etnaviv_pm_domain_meta doms_meta[] = { | |
264 | { | |
265 | .nr_domains = ARRAY_SIZE(doms_3d), | |
266 | .domains = &doms_3d[0] | |
267 | }, | |
268 | { | |
269 | .nr_domains = ARRAY_SIZE(doms_2d), | |
270 | .domains = &doms_2d[0] | |
271 | }, | |
272 | { | |
273 | .nr_domains = ARRAY_SIZE(doms_vg), | |
274 | .domains = &doms_vg[0] | |
275 | } | |
276 | }; | |
277 | ||
278 | int etnaviv_pm_query_dom(struct etnaviv_gpu *gpu, | |
279 | struct drm_etnaviv_pm_domain *domain) | |
280 | { | |
281 | const struct etnaviv_pm_domain_meta *meta = &doms_meta[domain->pipe]; | |
282 | const struct etnaviv_pm_domain *dom; | |
283 | ||
284 | if (domain->iter >= meta->nr_domains) | |
285 | return -EINVAL; | |
286 | ||
287 | dom = meta->domains + domain->iter; | |
288 | ||
289 | domain->id = domain->iter; | |
290 | domain->nr_signals = dom->nr_signals; | |
291 | strncpy(domain->name, dom->name, sizeof(domain->name)); | |
292 | ||
293 | domain->iter++; | |
294 | if (domain->iter == meta->nr_domains) | |
295 | domain->iter = 0xff; | |
296 | ||
297 | return 0; | |
298 | } | |
299 | ||
300 | int etnaviv_pm_query_sig(struct etnaviv_gpu *gpu, | |
301 | struct drm_etnaviv_pm_signal *signal) | |
302 | { | |
303 | const struct etnaviv_pm_domain_meta *meta = &doms_meta[signal->pipe]; | |
304 | const struct etnaviv_pm_domain *dom; | |
305 | const struct etnaviv_pm_signal *sig; | |
306 | ||
307 | if (signal->domain >= meta->nr_domains) | |
308 | return -EINVAL; | |
309 | ||
310 | dom = meta->domains + signal->domain; | |
311 | ||
312 | if (signal->iter > dom->nr_signals) | |
313 | return -EINVAL; | |
314 | ||
315 | sig = &dom->signal[signal->iter]; | |
316 | ||
317 | signal->id = signal->iter; | |
318 | strncpy(signal->name, sig->name, sizeof(signal->name)); | |
319 | ||
320 | signal->iter++; | |
321 | if (signal->iter == dom->nr_signals) | |
322 | signal->iter = 0xffff; | |
323 | ||
324 | return 0; | |
325 | } | |
46df52cd CG |
326 | |
327 | int etnaviv_pm_req_validate(const struct drm_etnaviv_gem_submit_pmr *r, | |
328 | u32 exec_state) | |
329 | { | |
330 | const struct etnaviv_pm_domain_meta *meta = &doms_meta[exec_state]; | |
331 | const struct etnaviv_pm_domain *dom; | |
332 | ||
333 | if (r->domain >= meta->nr_domains) | |
334 | return -EINVAL; | |
335 | ||
336 | dom = meta->domains + r->domain; | |
337 | ||
338 | if (r->signal > dom->nr_signals) | |
339 | return -EINVAL; | |
340 | ||
341 | return 0; | |
342 | } | |
249300c7 CG |
343 | |
344 | void etnaviv_perfmon_process(struct etnaviv_gpu *gpu, | |
345 | const struct etnaviv_perfmon_request *pmr) | |
346 | { | |
347 | const struct etnaviv_pm_domain_meta *meta = &doms_meta[gpu->exec_state]; | |
348 | const struct etnaviv_pm_domain *dom; | |
349 | const struct etnaviv_pm_signal *sig; | |
350 | u32 *bo = pmr->bo_vma; | |
351 | u32 val; | |
352 | ||
353 | dom = meta->domains + pmr->domain; | |
354 | sig = &dom->signal[pmr->signal]; | |
355 | val = sig->sample(gpu, dom, sig); | |
356 | ||
357 | *(bo + pmr->offset) = val; | |
358 | } |