Linux Audio

Check our new training course

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