drivers/gpu/drm/xe/xe_oa.c

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

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/xe/xe_oa.c
Extension
.c
Size
79896 bytes
Lines
2868
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern 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

static const struct file_operations xe_oa_fops = {
	.owner		= THIS_MODULE,
	.release	= xe_oa_release,
	.poll		= xe_oa_poll,
	.read		= xe_oa_read,
	.unlocked_ioctl	= xe_oa_ioctl,
	.mmap		= xe_oa_mmap,
};

static int xe_oa_stream_init(struct xe_oa_stream *stream,
			     struct xe_oa_open_param *param)
{
	struct xe_gt *gt = param->hwe->gt;
	int ret;

	stream->exec_q = param->exec_q;
	stream->poll_period_ns = DEFAULT_POLL_PERIOD_NS;
	stream->oa_unit = param->oa_unit;
	stream->hwe = param->hwe;
	stream->gt = stream->hwe->gt;
	stream->oa_buffer.format = &stream->oa->oa_formats[param->oa_format];

	stream->sample = param->sample;
	stream->periodic = param->period_exponent >= 0;
	stream->period_exponent = param->period_exponent;
	stream->no_preempt = param->no_preempt;
	stream->wait_num_reports = param->wait_num_reports;

	stream->xef = xe_file_get(param->xef);
	stream->num_syncs = param->num_syncs;
	stream->syncs = param->syncs;

	/*
	 * For Xe2+, when overrun mode is enabled, there are no partial reports at the end
	 * of buffer, making the OA buffer effectively a non-power-of-2 size circular
	 * buffer whose size, circ_size, is a multiple of the report size
	 */
	if (GRAPHICS_VER(stream->oa->xe) >= 20 &&
	    stream->oa_unit->type == DRM_XE_OA_UNIT_TYPE_OAG && stream->sample)
		stream->oa_buffer.circ_size =
			param->oa_buffer_size -
			param->oa_buffer_size % stream->oa_buffer.format->size;
	else
		stream->oa_buffer.circ_size = param->oa_buffer_size;

	stream->oa_config = xe_oa_get_oa_config(stream->oa, param->metric_set);
	if (!stream->oa_config) {
		drm_dbg(&stream->oa->xe->drm, "Invalid OA config id=%i\n", param->metric_set);
		ret = -EINVAL;
		goto exit;
	}

	/* Take runtime pm ref and forcewake to disable RC6 */
	xe_pm_runtime_get(stream->oa->xe);
	stream->fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL);
	if (!xe_force_wake_ref_has_domain(stream->fw_ref, XE_FORCEWAKE_ALL)) {
		ret = -ETIMEDOUT;
		goto err_fw_put;
	}

	ret = xe_oa_alloc_oa_buffer(stream, param->oa_buffer_size);
	if (ret)
		goto err_fw_put;

	stream->k_exec_q = xe_exec_queue_create(stream->oa->xe, NULL,
						BIT(stream->hwe->logical_instance), 1,
						stream->hwe, EXEC_QUEUE_FLAG_KERNEL, 0);
	if (IS_ERR(stream->k_exec_q)) {
		ret = PTR_ERR(stream->k_exec_q);
		drm_err(&stream->oa->xe->drm, "gt%d, hwe %s, xe_exec_queue_create failed=%d",
			stream->gt->info.id, stream->hwe->name, ret);
		goto err_free_oa_buf;
	}

	ret = xe_oa_enable_metric_set(stream);
	if (ret) {
		drm_dbg(&stream->oa->xe->drm, "Unable to enable metric set\n");
		goto err_put_k_exec_q;
	}

	drm_dbg(&stream->oa->xe->drm, "opening stream oa config uuid=%s\n",
		stream->oa_config->uuid);

	WRITE_ONCE(stream->oa_unit->exclusive_stream, stream);

	hrtimer_setup(&stream->poll_check_timer, xe_oa_poll_check_timer_cb, CLOCK_MONOTONIC,
		      HRTIMER_MODE_REL);
	init_waitqueue_head(&stream->poll_wq);

	spin_lock_init(&stream->oa_buffer.ptr_lock);

Annotation

Implementation Notes