drivers/gpu/drm/xe/xe_query.c

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

File Facts

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

for_each_hw_engine(hwe, gt, id) {
			if (xe_hw_engine_is_reserved(hwe))
				continue;
			i++;
		}

	return sizeof(struct drm_xe_query_engines) +
		i * sizeof(struct drm_xe_engine);
}

typedef u64 (*__ktime_func_t)(void);
static __ktime_func_t __clock_id_to_func(clockid_t clk_id)
{
	/*
	 * Use logic same as the perf subsystem to allow user to select the
	 * reference clock id to be used for timestamps.
	 */
	switch (clk_id) {
	case CLOCK_MONOTONIC:
		return &ktime_get_ns;
	case CLOCK_MONOTONIC_RAW:
		return &ktime_get_raw_ns;
	case CLOCK_REALTIME:
		return &ktime_get_real_ns;
	case CLOCK_BOOTTIME:
		return &ktime_get_boottime_ns;
	case CLOCK_TAI:
		return &ktime_get_clocktai_ns;
	default:
		return NULL;
	}
}

static void
hwe_read_timestamp(struct xe_hw_engine *hwe, u64 *engine_ts, u64 *cpu_ts,
		   u64 *cpu_delta, __ktime_func_t cpu_clock)
{
	struct xe_mmio *mmio = &hwe->gt->mmio;
	u32 upper, lower, old_upper, loop = 0;
	struct xe_reg upper_reg = RING_TIMESTAMP_UDW(hwe->mmio_base),
		      lower_reg = RING_TIMESTAMP(hwe->mmio_base);

	upper = xe_mmio_read32(mmio, upper_reg);
	do {
		*cpu_delta = local_clock();
		*cpu_ts = cpu_clock();
		lower = xe_mmio_read32(mmio, lower_reg);
		*cpu_delta = local_clock() - *cpu_delta;
		old_upper = upper;
		upper = xe_mmio_read32(mmio, upper_reg);
	} while (upper != old_upper && loop++ < 2);

	*engine_ts = (u64)upper << 32 | lower;
}

static int
query_engine_cycles(struct xe_device *xe,
		    struct drm_xe_device_query *query)
{
	struct drm_xe_query_engine_cycles __user *query_ptr;
	struct drm_xe_engine_class_instance *eci;
	struct drm_xe_query_engine_cycles resp;
	size_t size = sizeof(resp);
	__ktime_func_t cpu_clock;
	struct xe_hw_engine *hwe;
	struct xe_gt *gt;

	if (IS_SRIOV_VF(xe))
		return -EOPNOTSUPP;

	if (query->size == 0) {
		query->size = size;
		return 0;
	} else if (XE_IOCTL_DBG(xe, query->size != size)) {
		return -EINVAL;
	}

	query_ptr = u64_to_user_ptr(query->data);
	if (copy_from_user(&resp, query_ptr, size))
		return -EFAULT;

	cpu_clock = __clock_id_to_func(resp.clockid);
	if (!cpu_clock)
		return -EINVAL;

	eci = &resp.eci;
	gt = xe_device_get_gt(xe, eci->gt_id);
	if (!gt)
		return -EINVAL;

Annotation

Implementation Notes