Import the etnaviv header changes from kernel commit 05916bed1 (drm-next)
The drm_etnaviv_gem_submit structure was extended to include performance monitor requests. Also two new ioctls got added to be able to readout performance monitor domains and their signals.
Signed-off-by: Christian Gmeiner christian.gmeiner@gmail.com --- etnaviv/etnaviv_drm.h | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-)
diff --git a/etnaviv/etnaviv_drm.h b/etnaviv/etnaviv_drm.h index 76f6f78a..110cc73b 100644 --- a/etnaviv/etnaviv_drm.h +++ b/etnaviv/etnaviv_drm.h @@ -150,6 +150,19 @@ struct drm_etnaviv_gem_submit_bo { __u64 presumed; /* in/out, presumed buffer address */ };
+/* performance monitor request (pmr) */ +#define ETNA_PM_PROCESS_PRE 0x0001 +#define ETNA_PM_PROCESS_POST 0x0002 +struct drm_etnaviv_gem_submit_pmr { + __u32 flags; /* in, when to process request (ETNA_PM_PROCESS_x) */ + __u8 domain; /* in, pm domain */ + __u8 pad; + __u16 signal; /* in, pm signal */ + __u32 sequence; /* in, sequence number */ + __u32 read_offset; /* in, offset from read_bo */ + __u32 read_idx; /* in, index of read_bo buffer */ +}; + /* Each cmdstream submit consists of a table of buffers involved, and * one or more cmdstream buffers. This allows for conditional execution * (context-restore), and IB buffers needed for per tile/bin draw cmds. @@ -175,6 +188,9 @@ struct drm_etnaviv_gem_submit { __u64 stream; /* in, ptr to cmdstream */ __u32 flags; /* in, mask of ETNA_SUBMIT_x */ __s32 fence_fd; /* in/out, fence fd (see ETNA_SUBMIT_FENCE_FD_x) */ + __u64 pmrs; /* in, ptr to array of submit_pmr's */ + __u32 nr_pmrs; /* in, number of submit_pmr's */ + __u32 pad; };
/* The normal way to synchronize with the GPU is just to CPU_PREP on @@ -210,6 +226,27 @@ struct drm_etnaviv_gem_wait { struct drm_etnaviv_timespec timeout; /* in */ };
+/* + * Performance Monitor (PM): + */ + +struct drm_etnaviv_pm_domain { + __u32 pipe; /* in */ + __u8 iter; /* in/out, select pm domain at index iter */ + __u8 id; /* out, id of domain */ + __u16 nr_signals; /* out, how many signals does this domain provide */ + char name[64]; /* out, name of domain */ +}; + +struct drm_etnaviv_pm_signal { + __u32 pipe; /* in */ + __u8 domain; /* in, pm domain index */ + __u8 pad; + __u16 iter; /* in/out, select pm source at index iter */ + __u16 id; /* out, id of signal */ + char name[64]; /* out, name of domain */ +}; + #define DRM_ETNAVIV_GET_PARAM 0x00 /* placeholder: #define DRM_ETNAVIV_SET_PARAM 0x01 @@ -222,7 +259,9 @@ struct drm_etnaviv_gem_wait { #define DRM_ETNAVIV_WAIT_FENCE 0x07 #define DRM_ETNAVIV_GEM_USERPTR 0x08 #define DRM_ETNAVIV_GEM_WAIT 0x09 -#define DRM_ETNAVIV_NUM_IOCTLS 0x0a +#define DRM_ETNAVIV_PM_QUERY_DOM 0x0a +#define DRM_ETNAVIV_PM_QUERY_SIG 0x0b +#define DRM_ETNAVIV_NUM_IOCTLS 0x0c
#define DRM_IOCTL_ETNAVIV_GET_PARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_ETNAVIV_GET_PARAM, struct drm_etnaviv_param) #define DRM_IOCTL_ETNAVIV_GEM_NEW DRM_IOWR(DRM_COMMAND_BASE + DRM_ETNAVIV_GEM_NEW, struct drm_etnaviv_gem_new) @@ -233,6 +272,8 @@ struct drm_etnaviv_gem_wait { #define DRM_IOCTL_ETNAVIV_WAIT_FENCE DRM_IOW(DRM_COMMAND_BASE + DRM_ETNAVIV_WAIT_FENCE, struct drm_etnaviv_wait_fence) #define DRM_IOCTL_ETNAVIV_GEM_USERPTR DRM_IOWR(DRM_COMMAND_BASE + DRM_ETNAVIV_GEM_USERPTR, struct drm_etnaviv_gem_userptr) #define DRM_IOCTL_ETNAVIV_GEM_WAIT DRM_IOW(DRM_COMMAND_BASE + DRM_ETNAVIV_GEM_WAIT, struct drm_etnaviv_gem_wait) +#define DRM_IOCTL_ETNAVIV_PM_QUERY_DOM DRM_IOWR(DRM_COMMAND_BASE + DRM_ETNAVIV_PM_QUERY_DOM, struct drm_etnaviv_pm_domain) +#define DRM_IOCTL_ETNAVIV_PM_QUERY_SIG DRM_IOWR(DRM_COMMAND_BASE + DRM_ETNAVIV_PM_QUERY_SIG, struct drm_etnaviv_pm_signal)
#if defined(__cplusplus) }
Query all domains and their signals and provide it this information via struct etna_perfmon and the corresponding api functions.
Signed-off-by: Christian Gmeiner christian.gmeiner@gmail.com --- etnaviv/Makefile.sources | 1 + etnaviv/etnaviv-symbol-check | 4 + etnaviv/etnaviv_drmif.h | 10 +++ etnaviv/etnaviv_perfmon.c | 196 +++++++++++++++++++++++++++++++++++++++++++ etnaviv/etnaviv_priv.h | 21 +++++ 5 files changed, 232 insertions(+) create mode 100644 etnaviv/etnaviv_perfmon.c
diff --git a/etnaviv/Makefile.sources b/etnaviv/Makefile.sources index 52580567..0eb73783 100644 --- a/etnaviv/Makefile.sources +++ b/etnaviv/Makefile.sources @@ -3,6 +3,7 @@ LIBDRM_ETNAVIV_FILES := \ etnaviv_gpu.c \ etnaviv_bo.c \ etnaviv_bo_cache.c \ + etnaviv_perfmon.c \ etnaviv_pipe.c \ etnaviv_cmd_stream.c \ etnaviv_drm.h \ diff --git a/etnaviv/etnaviv-symbol-check b/etnaviv/etnaviv-symbol-check index 0e2030e4..bd95b459 100755 --- a/etnaviv/etnaviv-symbol-check +++ b/etnaviv/etnaviv-symbol-check @@ -42,6 +42,10 @@ etna_cmd_stream_flush etna_cmd_stream_flush2 etna_cmd_stream_finish etna_cmd_stream_reloc +etna_perfmon_create +etna_perfmon_del +etna_perfmon_get_dom_by_name +etna_perfmon_get_sig_by_name EOF done)
diff --git a/etnaviv/etnaviv_drmif.h b/etnaviv/etnaviv_drmif.h index 87704acd..0a7f6a3a 100644 --- a/etnaviv/etnaviv_drmif.h +++ b/etnaviv/etnaviv_drmif.h @@ -35,6 +35,9 @@ struct etna_pipe; struct etna_gpu; struct etna_device; struct etna_cmd_stream; +struct etna_perfmon; +struct etna_perfmon_domain; +struct etna_perfmon_signal;
enum etna_pipe_id { ETNA_PIPE_3D = 0, @@ -190,4 +193,11 @@ struct etna_reloc {
void etna_cmd_stream_reloc(struct etna_cmd_stream *stream, const struct etna_reloc *r);
+/* performance monitoring functions: + */ +struct etna_perfmon *etna_perfmon_create(struct etna_pipe *pipe); +void etna_perfmon_del(struct etna_perfmon *perfmon); +struct etna_perfmon_domain *etna_perfmon_get_dom_by_name(struct etna_perfmon *pm, const char *name); +struct etna_perfmon_signal *etna_perfmon_get_sig_by_name(struct etna_perfmon_domain *dom, const char *name); + #endif /* ETNAVIV_DRMIF_H_ */ diff --git a/etnaviv/etnaviv_perfmon.c b/etnaviv/etnaviv_perfmon.c new file mode 100644 index 00000000..16e37285 --- /dev/null +++ b/etnaviv/etnaviv_perfmon.c @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2017 Etnaviv Project + * Copyright (C) 2017 Zodiac Inflight Innovations + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Christian Gmeiner christian.gmeiner@gmail.com + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "etnaviv_priv.h" + +static int +etna_perfmon_query_signals(struct etna_perfmon *pm, struct etna_perfmon_domain *dom) +{ + struct etna_device *dev = pm->pipe->gpu->dev; + struct drm_etnaviv_pm_signal req = { + .pipe = pm->pipe->id, + .domain = dom->id + }; + + do { + struct etna_perfmon_signal *sig; + int ret; + + ret = drmCommandWriteRead(dev->fd, DRM_ETNAVIV_PM_QUERY_SIG, &req, sizeof(req)); + if (ret) + break; + + sig = calloc(1, sizeof(*sig)); + if (!sig) + return -ENOMEM; + + INFO_MSG("perfmon signal:"); + INFO_MSG("id = %d", req.id); + INFO_MSG("name = %s", req.name); + + sig->domain = dom; + sig->signal = req.id; + strncpy(sig->name, req.name, sizeof(sig->name)); + list_addtail(&sig->head, &dom->signals); + } while (req.iter != 0xffff); + + return 0; +} + +static int +etna_perfmon_query_domains(struct etna_perfmon *pm) +{ + struct etna_device *dev = pm->pipe->gpu->dev; + struct drm_etnaviv_pm_domain req = { + .pipe = pm->pipe->id + }; + + do { + struct etna_perfmon_domain *dom; + int ret; + + ret = drmCommandWriteRead(dev->fd, DRM_ETNAVIV_PM_QUERY_DOM, &req, sizeof(req)); + if (ret) + break; + + dom = calloc(1, sizeof(*dom)); + if (!dom) + return -ENOMEM; + list_inithead(&dom->signals); + + dom->id = req.id; + strncpy(dom->name, req.name, sizeof(dom->name)); + list_addtail(&dom->head, &pm->domains); + + INFO_MSG("perfmon domain:"); + INFO_MSG("id = %d", req.id); + INFO_MSG("name = %s", req.name); + INFO_MSG("nr_signals = %d", req.nr_signals); + + + /* Query all available signals for this domain. */ + if (req.nr_signals > 0) { + ret = etna_perfmon_query_signals(pm, dom); + if (ret) + return ret; + } + } while (req.iter != 0xff); + + return 0; +} + +static void +etna_perfmon_free_signals(struct etna_perfmon_domain *dom) +{ + struct etna_perfmon_signal *sig, *next; + + LIST_FOR_EACH_ENTRY_SAFE(sig, next, &dom->signals, head) { + list_del(&sig->head); + free(sig); + } +} + +static void +etna_perfmon_free_domains(struct etna_perfmon *pm) +{ + struct etna_perfmon_domain *dom, *next; + + LIST_FOR_EACH_ENTRY_SAFE(dom, next, &pm->domains, head) { + etna_perfmon_free_signals(dom); + list_del(&dom->head); + free(dom); + } +} + +struct etna_perfmon *etna_perfmon_create(struct etna_pipe *pipe) +{ + struct etna_perfmon *pm; + int ret; + + pm = calloc(1, sizeof(*pm)); + if (!pm) { + ERROR_MSG("allocation failed"); + goto fail; + } + + list_inithead(&pm->domains); + + pm->pipe = pipe; + + /* query all available domains and sources for this device */ + ret = etna_perfmon_query_domains(pm); + if (ret) + goto fail; + + return pm; + +fail: + return NULL; +} + +void etna_perfmon_del(struct etna_perfmon *pm) +{ + if (!pm) + return; + + etna_perfmon_free_domains(pm); + free(pm); +} + +struct etna_perfmon_domain * +etna_perfmon_get_dom_by_name(struct etna_perfmon *pm, const char *name) +{ + struct etna_perfmon_domain *dom; + + if (pm) { + LIST_FOR_EACH_ENTRY(dom, &pm->domains, head) { + if (!strcmp(dom->name, name)) + return dom; + } + } + + return NULL; +} + +struct etna_perfmon_signal * +etna_perfmon_get_sig_by_name(struct etna_perfmon_domain *dom, const char *name) +{ + struct etna_perfmon_signal *signal; + + if (dom) { + LIST_FOR_EACH_ENTRY(signal, &dom->signals, head) { + if (!strcmp(signal->name, name)) + return signal; + } + } + + return NULL; +} diff --git a/etnaviv/etnaviv_priv.h b/etnaviv/etnaviv_priv.h index 1334ba3f..37ffd803 100644 --- a/etnaviv/etnaviv_priv.h +++ b/etnaviv/etnaviv_priv.h @@ -151,6 +151,27 @@ struct etna_cmd_stream_priv { void *reset_notify_priv; };
+struct etna_perfmon { + struct list_head domains; + struct etna_pipe *pipe; +}; + +struct etna_perfmon_domain +{ + struct list_head head; + struct list_head signals; + uint8_t id; + char name[64]; +}; + +struct etna_perfmon_signal +{ + struct list_head head; + struct etna_perfmon_domain *domain; + uint8_t signal; + char name[64]; +}; + #define ALIGN(v,a) (((v) + (a) - 1) & ~((a) - 1)) #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
Add etna_cmd_stream_perf(..) to submit perform requests. Userspace can submit pmrs via submit ioctl to sample perfmon signals.
Signed-off-by: Christian Gmeiner christian.gmeiner@gmail.com --- etnaviv/etnaviv-symbol-check | 1 + etnaviv/etnaviv_cmd_stream.c | 20 ++++++++++++++++++++ etnaviv/etnaviv_drmif.h | 12 ++++++++++++ etnaviv/etnaviv_priv.h | 4 ++++ 4 files changed, 37 insertions(+)
diff --git a/etnaviv/etnaviv-symbol-check b/etnaviv/etnaviv-symbol-check index bd95b459..bc509615 100755 --- a/etnaviv/etnaviv-symbol-check +++ b/etnaviv/etnaviv-symbol-check @@ -41,6 +41,7 @@ etna_cmd_stream_timestamp etna_cmd_stream_flush etna_cmd_stream_flush2 etna_cmd_stream_finish +etna_cmd_stream_perf etna_cmd_stream_reloc etna_perfmon_create etna_perfmon_del diff --git a/etnaviv/etnaviv_cmd_stream.c b/etnaviv/etnaviv_cmd_stream.c index 8d0e8135..d6f26a88 100644 --- a/etnaviv/etnaviv_cmd_stream.c +++ b/etnaviv/etnaviv_cmd_stream.c @@ -105,6 +105,7 @@ void etna_cmd_stream_del(struct etna_cmd_stream *stream)
free(stream->buffer); free(priv->submit.relocs); + free(priv->submit.pmrs); free(priv); }
@@ -115,6 +116,7 @@ static void reset_buffer(struct etna_cmd_stream *stream) stream->offset = 0; priv->submit.nr_bos = 0; priv->submit.nr_relocs = 0; + priv->submit.nr_pmrs = 0; priv->nr_bos = 0;
if (priv->reset_notify) @@ -191,6 +193,8 @@ static void flush(struct etna_cmd_stream *stream, int in_fence_fd, .nr_bos = priv->submit.nr_bos, .relocs = VOID2U64(priv->submit.relocs), .nr_relocs = priv->submit.nr_relocs, + .pmrs = VOID2U64(priv->submit.pmrs), + .nr_pmrs = priv->submit.nr_pmrs, .stream = VOID2U64(stream->buffer), .stream_size = stream->offset * 4, /* in bytes */ }; @@ -260,3 +264,19 @@ void etna_cmd_stream_reloc(struct etna_cmd_stream *stream, const struct etna_rel
etna_cmd_stream_emit(stream, addr); } + +void etna_cmd_stream_perf(struct etna_cmd_stream *stream, const struct etna_perf *p) +{ + struct etna_cmd_stream_priv *priv = etna_cmd_stream_priv(stream); + struct drm_etnaviv_gem_submit_pmr *pmr; + uint32_t idx = APPEND(&priv->submit, pmrs); + + pmr = &priv->submit.pmrs[idx]; + + pmr->flags = p->flags; + pmr->sequence = p->sequence; + pmr->read_offset = p->offset; + pmr->read_idx = bo2idx(stream, p->bo, ETNA_SUBMIT_BO_READ); + pmr->domain = p->signal->domain->id; + pmr->signal = p->signal->signal; +} diff --git a/etnaviv/etnaviv_drmif.h b/etnaviv/etnaviv_drmif.h index 0a7f6a3a..e77a3b2a 100644 --- a/etnaviv/etnaviv_drmif.h +++ b/etnaviv/etnaviv_drmif.h @@ -200,4 +200,16 @@ void etna_perfmon_del(struct etna_perfmon *perfmon); struct etna_perfmon_domain *etna_perfmon_get_dom_by_name(struct etna_perfmon *pm, const char *name); struct etna_perfmon_signal *etna_perfmon_get_sig_by_name(struct etna_perfmon_domain *dom, const char *name);
+struct etna_perf { +#define ETNA_PM_PROCESS_PRE 0x0001 +#define ETNA_PM_PROCESS_POST 0x0002 + uint32_t flags; + uint32_t sequence; + struct etna_perfmon_signal *signal; + struct etna_bo *bo; + uint32_t offset; +}; + +void etna_cmd_stream_perf(struct etna_cmd_stream *stream, const struct etna_perf *p); + #endif /* ETNAVIV_DRMIF_H_ */ diff --git a/etnaviv/etnaviv_priv.h b/etnaviv/etnaviv_priv.h index 37ffd803..60e65ec8 100644 --- a/etnaviv/etnaviv_priv.h +++ b/etnaviv/etnaviv_priv.h @@ -140,6 +140,10 @@ struct etna_cmd_stream_priv { /* reloc's table: */ struct drm_etnaviv_gem_submit_reloc *relocs; uint32_t nr_relocs, max_relocs; + + /* perf's table: */ + struct drm_etnaviv_gem_submit_pmr *pmrs; + uint32_t nr_pmrs, max_pmrs; } submit;
/* should have matching entries in submit.bos: */
dri-devel@lists.freedesktop.org