2 * Copyright (c) 2017 Etnaviv Project
3 * Copyright (C) 2017 Zodiac Inflight Innovations
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sub license,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
25 * Christian Gmeiner <christian.gmeiner@gmail.com>
28 #include "util/u_inlines.h"
29 #include "util/u_memory.h"
31 #include "etnaviv_context.h"
32 #include "etnaviv_query_pm.h"
33 #include "etnaviv_screen.h"
35 struct etna_perfmon_source
41 struct etna_perfmon_config
45 const struct etna_perfmon_source
*source
;
48 static const struct etna_perfmon_config query_config
[] = {
50 .name
= "hi-total-cyles",
51 .type
= ETNA_QUERY_HI_TOTAL_CYCLES
,
52 .source
= (const struct etna_perfmon_source
[]) {
53 { "HI", "TOTAL_CYCLES" }
57 .name
= "hi-idle-cyles",
58 .type
= ETNA_QUERY_HI_IDLE_CYCLES
,
59 .source
= (const struct etna_perfmon_source
[]) {
60 { "HI", "IDLE_CYCLES" }
64 .name
= "hi-axi-cycles-read-request-stalled",
65 .type
= ETNA_QUERY_HI_AXI_CYCLES_READ_REQUEST_STALLED
,
66 .source
= (const struct etna_perfmon_source
[]) {
67 { "HI", "AXI_CYCLES_READ_REQUEST_STALLED" }
71 .name
= "hi-axi-cycles-write-request-stalled",
72 .type
= ETNA_QUERY_HI_AXI_CYCLES_WRITE_REQUEST_STALLED
,
73 .source
= (const struct etna_perfmon_source
[]) {
74 { "HI", "AXI_CYCLES_WRITE_REQUEST_STALLED" }
78 .name
= "hi-axi-cycles-write-data-stalled",
79 .type
= ETNA_QUERY_HI_AXI_CYCLES_WRITE_DATA_STALLED
,
80 .source
= (const struct etna_perfmon_source
[]) {
81 { "HI", "AXI_CYCLES_WRITE_DATA_STALLED" }
85 .name
= "pe-pixel-count-killed-by-color-pipe",
86 .type
= ETNA_QUERY_PE_PIXEL_COUNT_KILLED_BY_COLOR_PIPE
,
87 .source
= (const struct etna_perfmon_source
[]) {
88 { "PE", "PIXEL_COUNT_KILLED_BY_COLOR_PIPE" }
92 .name
= "pe-pixel-count-killed-by-depth-pipe",
93 .type
= ETNA_QUERY_PE_PIXEL_COUNT_KILLED_BY_DEPTH_PIPE
,
94 .source
= (const struct etna_perfmon_source
[]) {
95 { "PE", "PIXEL_COUNT_KILLED_BY_DEPTH_PIPE" }
99 .name
= "pe-pixel-count-drawn-by-color-pipe",
100 .type
= ETNA_QUERY_PE_PIXEL_COUNT_DRAWN_BY_COLOR_PIPE
,
101 .source
= (const struct etna_perfmon_source
[]) {
102 { "PE", "PIXEL_COUNT_DRAWN_BY_COLOR_PIPE" }
106 .name
= "pe-pixel-count-drawn-by-depth-pipe",
107 .type
= ETNA_QUERY_PE_PIXEL_COUNT_DRAWN_BY_DEPTH_PIPE
,
108 .source
= (const struct etna_perfmon_source
[]) {
109 { "PE", "PIXEL_COUNT_DRAWN_BY_DEPTH_PIPE" }
114 static const struct etna_perfmon_config
*
115 etna_pm_query_config(unsigned type
)
117 for (unsigned i
= 0; i
< ARRAY_SIZE(query_config
); i
++)
118 if (query_config
[i
].type
== type
)
119 return &query_config
[i
];
124 static struct etna_perfmon_signal
*
125 etna_pm_query_signal(struct etna_perfmon
*perfmon
,
126 const struct etna_perfmon_source
*source
)
128 struct etna_perfmon_domain
*domain
;
130 domain
= etna_perfmon_get_dom_by_name(perfmon
, source
->domain
);
134 return etna_perfmon_get_sig_by_name(domain
, source
->signal
);
138 etna_pm_cfg_supported(struct etna_perfmon
*perfmon
,
139 const struct etna_perfmon_config
*cfg
)
141 struct etna_perfmon_signal
*signal
= etna_pm_query_signal(perfmon
, cfg
->source
);
147 etna_pm_add_signal(struct etna_pm_query
*pq
, struct etna_perfmon
*perfmon
,
148 const struct etna_perfmon_config
*cfg
)
150 struct etna_perfmon_signal
*signal
= etna_pm_query_signal(perfmon
, cfg
->source
);
156 realloc_query_bo(struct etna_context
*ctx
, struct etna_pm_query
*pq
)
161 pq
->bo
= etna_bo_new(ctx
->screen
->dev
, 64, DRM_ETNA_GEM_CACHE_WC
);
162 if (unlikely(!pq
->bo
))
165 pq
->data
= etna_bo_map(pq
->bo
);
171 etna_pm_query_get(struct etna_cmd_stream
*stream
, struct etna_query
*q
,
174 struct etna_pm_query
*pq
= etna_pm_query(q
);
178 if (flags
== ETNA_PM_PROCESS_PRE
)
183 struct etna_perf p
= {
185 .sequence
= pq
->sequence
,
187 .signal
= pq
->signal
,
191 etna_cmd_stream_perf(stream
, &p
);
195 etna_pm_query_update(struct etna_query
*q
)
197 struct etna_pm_query
*pq
= etna_pm_query(q
);
199 if (pq
->data
[0] == pq
->sequence
)
204 etna_pm_destroy_query(struct etna_context
*ctx
, struct etna_query
*q
)
206 struct etna_pm_query
*pq
= etna_pm_query(q
);
213 etna_pm_begin_query(struct etna_context
*ctx
, struct etna_query
*q
)
215 struct etna_pm_query
*pq
= etna_pm_query(q
);
220 etna_pm_query_get(ctx
->stream
, q
, ETNA_PM_PROCESS_PRE
);
226 etna_pm_end_query(struct etna_context
*ctx
, struct etna_query
*q
)
228 etna_pm_query_get(ctx
->stream
, q
, ETNA_PM_PROCESS_POST
);
232 etna_pm_get_query_result(struct etna_context
*ctx
, struct etna_query
*q
,
233 boolean wait
, union pipe_query_result
*result
)
235 struct etna_pm_query
*pq
= etna_pm_query(q
);
237 etna_pm_query_update(q
);
243 if (!etna_bo_cpu_prep(pq
->bo
, DRM_ETNA_PREP_READ
))
247 etna_bo_cpu_fini(pq
->bo
);
250 result
->u32
= pq
->data
[2] - pq
->data
[1];
255 static const struct etna_query_funcs hw_query_funcs
= {
256 .destroy_query
= etna_pm_destroy_query
,
257 .begin_query
= etna_pm_begin_query
,
258 .end_query
= etna_pm_end_query
,
259 .get_query_result
= etna_pm_get_query_result
,
263 etna_pm_create_query(struct etna_context
*ctx
, unsigned query_type
)
265 struct etna_perfmon
*perfmon
= ctx
->screen
->perfmon
;
266 const struct etna_perfmon_config
*cfg
;
267 struct etna_pm_query
*pq
;
268 struct etna_query
*q
;
270 cfg
= etna_pm_query_config(query_type
);
274 if (!etna_pm_cfg_supported(perfmon
, cfg
))
277 pq
= CALLOC_STRUCT(etna_pm_query
);
281 if (!realloc_query_bo(ctx
, pq
)) {
287 q
->funcs
= &hw_query_funcs
;
288 q
->type
= query_type
;
290 etna_pm_add_signal(pq
, perfmon
, cfg
);
296 etna_pm_query_setup(struct etna_screen
*screen
)
298 screen
->perfmon
= etna_perfmon_create(screen
->pipe
);
300 if (!screen
->perfmon
)
303 for (unsigned i
= 0; i
< ARRAY_SIZE(query_config
); i
++) {
304 const struct etna_perfmon_config
*cfg
= &query_config
[i
];
306 if (!etna_pm_cfg_supported(screen
->perfmon
, cfg
))
309 util_dynarray_append(&screen
->supported_pm_queries
, unsigned, i
);
314 etna_pm_get_driver_query_info(struct pipe_screen
*pscreen
, unsigned index
,
315 struct pipe_driver_query_info
*info
)
317 const struct etna_screen
*screen
= etna_screen(pscreen
);
318 const unsigned num
= screen
->supported_pm_queries
.size
/ sizeof(unsigned);
327 i
= *util_dynarray_element(&screen
->supported_pm_queries
, unsigned, index
);
328 assert(i
< ARRAY_SIZE(query_config
));
330 info
->name
= query_config
[i
].name
;
331 info
->query_type
= query_config
[i
].type
;