diff mbox series

drm/etnaviv: rework perfmon query infrastructure

Message ID 20200106104339.215511-1-christian.gmeiner@gmail.com (mailing list archive)
State New, archived
Headers show
Series drm/etnaviv: rework perfmon query infrastructure | expand

Commit Message

Christian Gmeiner Jan. 6, 2020, 10:43 a.m. UTC
Report the correct perfmon domains and signals depending
on the supported feature flags.

Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Fixes: 9e2c2e273012 ("drm/etnaviv: add infrastructure to query perf counter")
Cc: stable@vger.kernel.org
Signed-off-by: Christian Gmeiner <christian.gmeiner@gmail.com>
---
 drivers/gpu/drm/etnaviv/etnaviv_perfmon.c | 57 ++++++++++++++++++++---
 1 file changed, 50 insertions(+), 7 deletions(-)

Comments

Christian Gmeiner Feb. 21, 2020, 8:28 a.m. UTC | #1
Am Mo., 6. Jan. 2020 um 11:43 Uhr schrieb Christian Gmeiner
<christian.gmeiner@gmail.com>:
>
> Report the correct perfmon domains and signals depending
> on the supported feature flags.
>
> Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
> Fixes: 9e2c2e273012 ("drm/etnaviv: add infrastructure to query perf counter")
> Cc: stable@vger.kernel.org
> Signed-off-by: Christian Gmeiner <christian.gmeiner@gmail.com>
> ---
>  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);
> +
> +       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;
> --
> 2.24.1
>

ping
Lucas Stach Feb. 26, 2020, 3:19 p.m. UTC | #2
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 <dan.carpenter@oracle.com>
> Fixes: 9e2c2e273012 ("drm/etnaviv: add infrastructure to query perf counter")
> Cc: stable@vger.kernel.org
> Signed-off-by: Christian Gmeiner <christian.gmeiner@gmail.com>
> ---
>  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;
Christian Gmeiner Feb. 28, 2020, 10:39 a.m. UTC | #3
Hi Lucas,

Am Mi., 26. Feb. 2020 um 16:19 Uhr schrieb Lucas Stach <l.stach@pengutronix.de>:
>
> Hi Christian,
>
> sorry for taking so long to get around to this.
>

No problem...

> 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 <dan.carpenter@oracle.com>
> > Fixes: 9e2c2e273012 ("drm/etnaviv: add infrastructure to query perf counter")
> > Cc: stable@vger.kernel.org
> > Signed-off-by: Christian Gmeiner <christian.gmeiner@gmail.com>
> > ---
> >  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.
>

Fixed it in V2.
diff mbox series

Patch

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);
+
+	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;