Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  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
 22struct etnaviv_pm_domain;
 23
 24struct 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
 33struct 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
 44struct etnaviv_pm_domain_meta {
 45	const struct etnaviv_pm_domain *domains;
 46	u32 nr_domains;
 47};
 48
 49static 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
 56static 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
 65static 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
 89static 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
381static 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
397static const struct etnaviv_pm_domain doms_vg[] = {
398};
399
400static 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
415int 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
437int 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
464int 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
481void etnaviv_perfmon_process(struct etnaviv_gpu *gpu,
482	const struct etnaviv_perfmon_request *pmr, u32 exec_state)
483{
484	const struct etnaviv_pm_domain_meta *meta = &doms_meta[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}