drivers/gpu/drm/panfrost/panfrost_perfcnt.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/panfrost/panfrost_perfcnt.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/panfrost/panfrost_perfcnt.c
Extension
.c
Size
9365 bytes
Lines
354
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 panfrost_perfcnt {
	struct panfrost_gem_mapping *mapping;
	size_t bosize;
	void *buf;
	struct panfrost_file_priv *user;
	struct mutex lock;
	struct completion dump_comp;
};

void panfrost_perfcnt_clean_cache_done(struct panfrost_device *pfdev)
{
	complete(&pfdev->perfcnt->dump_comp);
}

void panfrost_perfcnt_sample_done(struct panfrost_device *pfdev)
{
	gpu_write(pfdev, GPU_CMD, GPU_CMD_CLEAN_CACHES);
}

static int panfrost_perfcnt_dump_locked(struct panfrost_device *pfdev)
{
	u64 gpuva;
	int ret;

	reinit_completion(&pfdev->perfcnt->dump_comp);
	gpuva = pfdev->perfcnt->mapping->mmnode.start << PAGE_SHIFT;
	gpu_write(pfdev, GPU_PERFCNT_BASE_LO, lower_32_bits(gpuva));
	gpu_write(pfdev, GPU_PERFCNT_BASE_HI, upper_32_bits(gpuva));
	gpu_write(pfdev, GPU_INT_CLEAR,
		  GPU_IRQ_CLEAN_CACHES_COMPLETED |
		  GPU_IRQ_PERFCNT_SAMPLE_COMPLETED);
	gpu_write(pfdev, GPU_CMD, GPU_CMD_PERFCNT_SAMPLE);
	ret = wait_for_completion_interruptible_timeout(&pfdev->perfcnt->dump_comp,
							msecs_to_jiffies(1000));
	if (!ret)
		ret = -ETIMEDOUT;
	else if (ret > 0)
		ret = 0;

	return ret;
}

static int panfrost_perfcnt_enable_locked(struct panfrost_device *pfdev,
					  struct drm_file *file_priv,
					  unsigned int counterset)
{
	struct panfrost_file_priv *user = file_priv->driver_priv;
	struct panfrost_perfcnt *perfcnt = pfdev->perfcnt;
	struct iosys_map map;
	struct drm_gem_shmem_object *bo;
	u32 cfg, as;
	int ret;

	if (user == perfcnt->user)
		return 0;
	else if (perfcnt->user)
		return -EBUSY;

	ret = pm_runtime_get_sync(pfdev->base.dev);
	if (ret < 0)
		goto err_put_pm;

	bo = drm_gem_shmem_create(&pfdev->base, perfcnt->bosize);
	if (IS_ERR(bo)) {
		ret = PTR_ERR(bo);
		goto err_put_pm;
	}

	/* Map the perfcnt buf in the address space attached to file_priv. */
	ret = panfrost_gem_open(&bo->base, file_priv);
	if (ret)
		goto err_put_bo;

	perfcnt->mapping = panfrost_gem_mapping_get(to_panfrost_bo(&bo->base),
						    user);
	if (!perfcnt->mapping) {
		ret = -EINVAL;
		goto err_close_bo;
	}

	ret = drm_gem_vmap(&bo->base, &map);
	if (ret)
		goto err_put_mapping;
	perfcnt->buf = map.vaddr;

	panfrost_gem_internal_set_label(&bo->base, "Perfcnt sample buffer");

	/*
	 * Invalidate the cache and clear the counters to start from a fresh
	 * state.

Annotation

Implementation Notes