Linux Audio

Check our new training course

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