Re: [PATCH v2] drm/etnaviv: rework perfmon query infrastructure

From: Lucas Stach
Date: Tue Mar 03 2020 - 06:49:37 EST


On Fr, 2020-02-28 at 11:37 +0100, Christian Gmeiner wrote:
> Report the correct perfmon domains and signals depending
> on the supported feature flags.
>
> Reported-by: Dan Carpenter <dan.carpenter@xxxxxxxxxx>
> Fixes: 9e2c2e273012 ("drm/etnaviv: add infrastructure to query perf counter")
> Cc: stable@xxxxxxxxxxxxxxx
> Signed-off-by: Christian Gmeiner <christian.gmeiner@xxxxxxxxx>

Thanks, applied to etnaviv/next.

Regards,
Lucas

>
> ---
> Changes V1 -> V2:
> - Handle domain == NULL case better to get rid of BUG_ON(..) usage.
> ---
> drivers/gpu/drm/etnaviv/etnaviv_perfmon.c | 59 ++++++++++++++++++++---
> 1 file changed, 52 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/gpu/drm/etnaviv/etnaviv_perfmon.c b/drivers/gpu/drm/etnaviv/etnaviv_perfmon.c
> index 8adbf2861bff..e6795bafcbb9 100644
> --- a/drivers/gpu/drm/etnaviv/etnaviv_perfmon.c
> +++ b/drivers/gpu/drm/etnaviv/etnaviv_perfmon.c
> @@ -32,6 +32,7 @@ struct etnaviv_pm_domain {
> };
>
> struct etnaviv_pm_domain_meta {
> + unsigned int feature;
> const struct etnaviv_pm_domain *domains;
> u32 nr_domains;
> };
> @@ -410,36 +411,78 @@ static const struct etnaviv_pm_domain doms_vg[] = {
>
> static const struct etnaviv_pm_domain_meta doms_meta[] = {
> {
> + .feature = chipFeatures_PIPE_3D,
> .nr_domains = ARRAY_SIZE(doms_3d),
> .domains = &doms_3d[0]
> },
> {
> + .feature = chipFeatures_PIPE_2D,
> .nr_domains = ARRAY_SIZE(doms_2d),
> .domains = &doms_2d[0]
> },
> {
> + .feature = chipFeatures_PIPE_VG,
> .nr_domains = ARRAY_SIZE(doms_vg),
> .domains = &doms_vg[0]
> }
> };
>
> +static unsigned int num_pm_domains(const struct etnaviv_gpu *gpu)
> +{
> + unsigned int num = 0, i;
> +
> + for (i = 0; i < ARRAY_SIZE(doms_meta); i++) {
> + const struct etnaviv_pm_domain_meta *meta = &doms_meta[i];
> +
> + if (gpu->identity.features & meta->feature)
> + num += meta->nr_domains;
> + }
> +
> + return num;
> +}
> +
> +static const struct etnaviv_pm_domain *pm_domain(const struct etnaviv_gpu *gpu,
> + unsigned int index)
> +{
> + const struct etnaviv_pm_domain *domain = NULL;
> + unsigned int offset = 0, i;
> +
> + for (i = 0; i < ARRAY_SIZE(doms_meta); i++) {
> + const struct etnaviv_pm_domain_meta *meta = &doms_meta[i];
> +
> + if (!(gpu->identity.features & meta->feature))
> + continue;
> +
> + if (meta->nr_domains < (index - offset)) {
> + offset += meta->nr_domains;
> + continue;
> + }
> +
> + domain = meta->domains + (index - offset);
> + }
> +
> + return domain;
> +}
> +
> int etnaviv_pm_query_dom(struct etnaviv_gpu *gpu,
> struct drm_etnaviv_pm_domain *domain)
> {
> - const struct etnaviv_pm_domain_meta *meta = &doms_meta[domain->pipe];
> + const unsigned int nr_domains = num_pm_domains(gpu);
> const struct etnaviv_pm_domain *dom;
>
> - if (domain->iter >= meta->nr_domains)
> + if (domain->iter >= nr_domains)
> return -EINVAL;
>
> - dom = meta->domains + domain->iter;
> + dom = pm_domain(gpu, domain->iter);
> + if (!dom)
> + return -EINVAL;
>
> domain->id = domain->iter;
> domain->nr_signals = dom->nr_signals;
> strncpy(domain->name, dom->name, sizeof(domain->name));
>
> domain->iter++;
> - if (domain->iter == meta->nr_domains)
> + if (domain->iter == nr_domains)
> domain->iter = 0xff;
>
> return 0;
> @@ -448,14 +491,16 @@ int etnaviv_pm_query_dom(struct etnaviv_gpu *gpu,
> int etnaviv_pm_query_sig(struct etnaviv_gpu *gpu,
> struct drm_etnaviv_pm_signal *signal)
> {
> - const struct etnaviv_pm_domain_meta *meta = &doms_meta[signal->pipe];
> + const unsigned int nr_domains = num_pm_domains(gpu);
> const struct etnaviv_pm_domain *dom;
> const struct etnaviv_pm_signal *sig;
>
> - if (signal->domain >= meta->nr_domains)
> + if (signal->domain >= nr_domains)
> return -EINVAL;
>
> - dom = meta->domains + signal->domain;
> + dom = pm_domain(gpu, signal->domain);
> + if (!dom)
> + return -EINVAL;
>
> if (signal->iter >= dom->nr_signals)
> return -EINVAL;