Linux Audio

Check our new training course

Loading...
v5.4
  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}
v6.9.4
  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	strscpy_pad(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	strscpy_pad(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}