Message ID | 20171212212750.5372-3-christian.gmeiner@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Am Dienstag, den 12.12.2017, 22:27 +0100 schrieb Christian Gmeiner: > Query all domains and their signals and provide it this information > via struct etna_perfmon and the corresponding api functions. > > v2: > - code style changes > - etna_perfmon_create(..): add missing clean up in error case > > Signed-off-by: Christian Gmeiner <christian.gmeiner@gmail.com> Reviewed-by: Lucas Stach <l.stach@pengutronix.de> > --- > etnaviv/Makefile.sources | 1 + > etnaviv/etnaviv-symbol-check | 4 + > etnaviv/etnaviv_drmif.h | 11 +++ > etnaviv/etnaviv_perfmon.c | 189 > +++++++++++++++++++++++++++++++++++++++++++ > etnaviv/etnaviv_priv.h | 21 +++++ > 5 files changed, 226 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..949b9b62 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,12 @@ 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..aa5130a6 > --- /dev/null > +++ b/etnaviv/etnaviv_perfmon.c > @@ -0,0 +1,189 @@ > +/* > + * 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"); > + return NULL; > + } > + > + 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: > + etna_perfmon_del(pm); > + 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..7b289b61 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])) >
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..949b9b62 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,12 @@ 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..aa5130a6 --- /dev/null +++ b/etnaviv/etnaviv_perfmon.c @@ -0,0 +1,189 @@ +/* + * 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"); + return NULL; + } + + 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: + etna_perfmon_del(pm); + 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..7b289b61 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]))
Query all domains and their signals and provide it this information via struct etna_perfmon and the corresponding api functions. v2: - code style changes - etna_perfmon_create(..): add missing clean up in error case Signed-off-by: Christian Gmeiner <christian.gmeiner@gmail.com> --- etnaviv/Makefile.sources | 1 + etnaviv/etnaviv-symbol-check | 4 + etnaviv/etnaviv_drmif.h | 11 +++ etnaviv/etnaviv_perfmon.c | 189 +++++++++++++++++++++++++++++++++++++++++++ etnaviv/etnaviv_priv.h | 21 +++++ 5 files changed, 226 insertions(+) create mode 100644 etnaviv/etnaviv_perfmon.c