drivers/gpu/drm/etnaviv/etnaviv_perfmon.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/etnaviv/etnaviv_perfmon.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/etnaviv/etnaviv_perfmon.c
Extension
.c
Size
13409 bytes
Lines
588
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct etnaviv_pm_signal {
	char name[64];
	u32 data;

	u32 (*sample)(struct etnaviv_gpu *gpu,
		      const struct etnaviv_pm_domain *domain,
		      const struct etnaviv_pm_signal *signal);
};

struct etnaviv_pm_domain {
	char name[64];

	/* profile register */
	u32 profile_read;
	u32 profile_config;

	u8 nr_signals;
	const struct etnaviv_pm_signal *signal;
};

struct etnaviv_pm_domain_meta {
	unsigned int feature;
	const struct etnaviv_pm_domain *domains;
	u32 nr_domains;
};

static u32 perf_reg_read(struct etnaviv_gpu *gpu,
	const struct etnaviv_pm_domain *domain,
	const struct etnaviv_pm_signal *signal)
{
	gpu_write(gpu, domain->profile_config, signal->data);

	return gpu_read(gpu, domain->profile_read);
}

static inline void pipe_select(struct etnaviv_gpu *gpu, u32 clock, unsigned pipe)
{
	clock &= ~(VIVS_HI_CLOCK_CONTROL_DEBUG_PIXEL_PIPE__MASK);
	clock |= VIVS_HI_CLOCK_CONTROL_DEBUG_PIXEL_PIPE(pipe);

	gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, clock);
}

static u32 pipe_perf_reg_read(struct etnaviv_gpu *gpu,
	const struct etnaviv_pm_domain *domain,
	const struct etnaviv_pm_signal *signal)
{
	u32 clock = gpu_read(gpu, VIVS_HI_CLOCK_CONTROL);
	u32 value = 0;
	unsigned i;

	lockdep_assert_held(&gpu->lock);

	for (i = 0; i < gpu->identity.pixel_pipes; i++) {
		pipe_select(gpu, clock, i);
		value += perf_reg_read(gpu, domain, signal);
	}

	/* switch back to pixel pipe 0 to prevent GPU hang */
	pipe_select(gpu, clock, 0);

	return value;
}

static u32 pipe_reg_read(struct etnaviv_gpu *gpu,
	const struct etnaviv_pm_domain *domain,
	const struct etnaviv_pm_signal *signal)
{
	u32 clock = gpu_read(gpu, VIVS_HI_CLOCK_CONTROL);
	u32 value = 0;
	unsigned i;

	lockdep_assert_held(&gpu->lock);

	for (i = 0; i < gpu->identity.pixel_pipes; i++) {
		pipe_select(gpu, clock, i);
		value += gpu_read(gpu, signal->data);
	}

	/* switch back to pixel pipe 0 to prevent GPU hang */
	pipe_select(gpu, clock, 0);

	return value;
}

static u32 hi_total_cycle_read(struct etnaviv_gpu *gpu,
	const struct etnaviv_pm_domain *domain,
	const struct etnaviv_pm_signal *signal)
{
	u32 reg = VIVS_HI_PROFILE_TOTAL_CYCLES;

Annotation

Implementation Notes