Hi Christian,

sorry for taking so long to get around to this.

On Mo, 2020-01-06 at 11:43 +0100, Christian Gmeiner wrote:
> Report the correct perfmon domains and signals depending
> on the supported feature flags.
> 
> Reported-by: Dan Carpenter <[email protected]>
> Fixes: 9e2c2e273012 ("drm/etnaviv: add infrastructure to query perf counter")
> Cc: [email protected]
> Signed-off-by: Christian Gmeiner <[email protected]>
> ---
>  drivers/gpu/drm/etnaviv/etnaviv_perfmon.c | 57 ++++++++++++++++++++---
>  1 file changed, 50 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/gpu/drm/etnaviv/etnaviv_perfmon.c 
> b/drivers/gpu/drm/etnaviv/etnaviv_perfmon.c
> index 8adbf2861bff..7ae8f347ca06 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);
> +     }
> +
> +     BUG_ON(!domain);

This is a no-go. BUG_ON is reserved for only the most severe kernel
bugs where you can't possibly continue without risking a corruption of
non-volatile state. This isn't the case here, please instead just make
the callers handle a NULL return gracefully.

Regards,
Lucas

> +
> +     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);
>  
>       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,14 @@ 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 (signal->iter >= dom->nr_signals)
>               return -EINVAL;

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to