drivers/gpu/drm/xe/xe_pmu.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/xe/xe_pmu.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/xe/xe_pmu.c
Extension
.c
Size
16134 bytes
Lines
601
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

if (IS_SRIOV_PF(xe)) {
			if (function_id > xe_sriov_pf_get_totalvfs(xe))
				return false;
		} else if (function_id) {
			return false;
		}

		break;
	}

	return true;
}

static void xe_pmu_event_destroy(struct perf_event *event)
{
	struct xe_device *xe = container_of(event->pmu, typeof(*xe), pmu.base);
	struct xe_gt *gt;
	unsigned int *fw_ref = event->pmu_private;

	if (fw_ref) {
		gt = xe_device_get_gt(xe, config_to_gt_id(event->attr.config));
		xe_force_wake_put(gt_to_fw(gt), *fw_ref);
		kfree(fw_ref);
		event->pmu_private = NULL;
	}

	drm_WARN_ON(&xe->drm, event->parent);
	xe_pm_runtime_put(xe);
	drm_dev_put(&xe->drm);
}

static int xe_pmu_event_init(struct perf_event *event)
{
	struct xe_device *xe = container_of(event->pmu, typeof(*xe), pmu.base);
	struct xe_pmu *pmu = &xe->pmu;
	unsigned int id, gt;

	if (!pmu->registered)
		return -ENODEV;

	if (event->attr.type != event->pmu->type)
		return -ENOENT;

	/* unsupported modes and filters */
	if (event->attr.sample_period) /* no sampling */
		return -EINVAL;

	if (event->cpu < 0)
		return -EINVAL;

	gt = config_to_gt_id(event->attr.config);
	id = config_to_event_id(event->attr.config);
	if (!event_supported(pmu, gt, id))
		return -ENOENT;

	if (has_branch_stack(event))
		return -EOPNOTSUPP;

	if (!event_param_valid(event))
		return -ENOENT;

	if (!event->parent) {
		drm_dev_get(&xe->drm);
		xe_pm_runtime_get(xe);
		if (!event_gt_forcewake(event)) {
			xe_pm_runtime_put(xe);
			drm_dev_put(&xe->drm);
			return -EINVAL;
		}
		event->destroy = xe_pmu_event_destroy;
	}

	return 0;
}

static u64 read_engine_events(struct xe_gt *gt, struct perf_event *event)
{
	struct xe_hw_engine *hwe;
	unsigned int function_id;
	u64 config, val = 0;

	config = event->attr.config;
	function_id = config_to_function_id(config);

	hwe = event_to_hwe(event);
	if (config_to_event_id(config) == XE_PMU_EVENT_ENGINE_ACTIVE_TICKS)
		val = xe_guc_engine_activity_active_ticks(&gt->uc.guc, hwe, function_id);
	else
		val = xe_guc_engine_activity_total_ticks(&gt->uc.guc, hwe, function_id);

Annotation

Implementation Notes