Commit ed1dd899 authored by Christian Gmeiner's avatar Christian Gmeiner Committed by Lucas Stach

drm/etnaviv: rework perfmon query infrastructure

Report the correct perfmon domains and signals depending
on the supported feature flags.
Reported-by: default avatarDan Carpenter <dan.carpenter@oracle.com>
Fixes: 9e2c2e27 ("drm/etnaviv: add infrastructure to query perf counter")
Cc: stable@vger.kernel.org
Signed-off-by: default avatarChristian Gmeiner <christian.gmeiner@gmail.com>
Signed-off-by: default avatarLucas Stach <l.stach@pengutronix.de>
parent f56f1579
...@@ -32,6 +32,7 @@ struct etnaviv_pm_domain { ...@@ -32,6 +32,7 @@ struct etnaviv_pm_domain {
}; };
struct etnaviv_pm_domain_meta { struct etnaviv_pm_domain_meta {
unsigned int feature;
const struct etnaviv_pm_domain *domains; const struct etnaviv_pm_domain *domains;
u32 nr_domains; u32 nr_domains;
}; };
...@@ -410,36 +411,78 @@ static const struct etnaviv_pm_domain doms_vg[] = { ...@@ -410,36 +411,78 @@ static const struct etnaviv_pm_domain doms_vg[] = {
static const struct etnaviv_pm_domain_meta doms_meta[] = { static const struct etnaviv_pm_domain_meta doms_meta[] = {
{ {
.feature = chipFeatures_PIPE_3D,
.nr_domains = ARRAY_SIZE(doms_3d), .nr_domains = ARRAY_SIZE(doms_3d),
.domains = &doms_3d[0] .domains = &doms_3d[0]
}, },
{ {
.feature = chipFeatures_PIPE_2D,
.nr_domains = ARRAY_SIZE(doms_2d), .nr_domains = ARRAY_SIZE(doms_2d),
.domains = &doms_2d[0] .domains = &doms_2d[0]
}, },
{ {
.feature = chipFeatures_PIPE_VG,
.nr_domains = ARRAY_SIZE(doms_vg), .nr_domains = ARRAY_SIZE(doms_vg),
.domains = &doms_vg[0] .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, int etnaviv_pm_query_dom(struct etnaviv_gpu *gpu,
struct drm_etnaviv_pm_domain *domain) 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; const struct etnaviv_pm_domain *dom;
if (domain->iter >= meta->nr_domains) if (domain->iter >= nr_domains)
return -EINVAL; return -EINVAL;
dom = meta->domains + domain->iter; dom = pm_domain(gpu, domain->iter);
if (!dom)
return -EINVAL;
domain->id = domain->iter; domain->id = domain->iter;
domain->nr_signals = dom->nr_signals; domain->nr_signals = dom->nr_signals;
strncpy(domain->name, dom->name, sizeof(domain->name)); strncpy(domain->name, dom->name, sizeof(domain->name));
domain->iter++; domain->iter++;
if (domain->iter == meta->nr_domains) if (domain->iter == nr_domains)
domain->iter = 0xff; domain->iter = 0xff;
return 0; return 0;
...@@ -448,14 +491,16 @@ int etnaviv_pm_query_dom(struct etnaviv_gpu *gpu, ...@@ -448,14 +491,16 @@ int etnaviv_pm_query_dom(struct etnaviv_gpu *gpu,
int etnaviv_pm_query_sig(struct etnaviv_gpu *gpu, int etnaviv_pm_query_sig(struct etnaviv_gpu *gpu,
struct drm_etnaviv_pm_signal *signal) 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_domain *dom;
const struct etnaviv_pm_signal *sig; const struct etnaviv_pm_signal *sig;
if (signal->domain >= meta->nr_domains) if (signal->domain >= nr_domains)
return -EINVAL; return -EINVAL;
dom = meta->domains + signal->domain; dom = pm_domain(gpu, signal->domain);
if (!dom)
return -EINVAL;
if (signal->iter >= dom->nr_signals) if (signal->iter >= dom->nr_signals)
return -EINVAL; return -EINVAL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment