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

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
Loading
Loading
Loading
Loading
+52 −7
Original line number Diff line number Diff line
@@ -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;