drivers/gpu/drm/xe/xe_guc_pc.c

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

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/xe/xe_guc_pc.c
Extension
.c
Size
35002 bytes
Lines
1442
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 (ret) {
			xe_gt_err_once(gt, "Failed to cap max freq on flush to %u, %pe\n",
				       BMG_MERT_FLUSH_FREQ_CAP, ERR_PTR(ret));
			return;
		}

		atomic_set(&pc->flush_freq_limit, 1);

		/*
		 * If user has previously changed max freq, stash that value to
		 * restore later, otherwise use the current max. New user
		 * requests wait on flush.
		 */
		if (pc->user_requested_max != 0)
			pc->stashed_max_freq = pc->user_requested_max;
		else
			pc->stashed_max_freq = max_freq;
	}

	/*
	 * Wait for actual freq to go below the flush cap: even if the previous
	 * max was below cap, the current one might still be above it
	 */
	ret = wait_for_act_freq_max_limit(pc, BMG_MERT_FLUSH_FREQ_CAP);
	if (ret)
		xe_gt_err_once(gt, "Actual freq did not reduce to %u, %pe\n",
			       BMG_MERT_FLUSH_FREQ_CAP, ERR_PTR(ret));
}

/**
 * xe_guc_pc_remove_flush_freq_limit() - Remove max GT freq limit after L2 flush completes.
 * @pc: the xe_guc_pc object
 *
 * Retrieve the previous GT max frequency value.
 */
void xe_guc_pc_remove_flush_freq_limit(struct xe_guc_pc *pc)
{
	struct xe_gt *gt = pc_to_gt(pc);
	int ret = 0;

	if (!needs_flush_freq_limit(pc))
		return;

	if (!atomic_read(&pc->flush_freq_limit))
		return;

	mutex_lock(&pc->freq_lock);

	ret = pc_set_max_freq(&gt->uc.guc.pc, pc->stashed_max_freq);
	if (ret)
		xe_gt_err_once(gt, "Failed to restore max freq %u:%d",
			       pc->stashed_max_freq, ret);

	atomic_set(&pc->flush_freq_limit, 0);
	mutex_unlock(&pc->freq_lock);
	wake_up_var(&pc->flush_freq_limit);
}

static int pc_set_mert_freq_cap(struct xe_guc_pc *pc)
{
	int ret;

	if (!XE_GT_WA(pc_to_gt(pc), 22019338487))
		return 0;

	guard(mutex)(&pc->freq_lock);

	/*
	 * Get updated min/max and stash them.
	 */
	ret = xe_guc_pc_get_min_freq_locked(pc, &pc->stashed_min_freq);
	if (!ret)
		ret = xe_guc_pc_get_max_freq_locked(pc, &pc->stashed_max_freq);
	if (ret)
		return ret;

	/*
	 * Ensure min and max are bound by MERT_FREQ_CAP until driver loads.
	 */
	ret = pc_set_min_freq(pc, min(xe_guc_pc_get_rpe_freq(pc), pc_max_freq_cap(pc)));
	if (!ret)
		ret = pc_set_max_freq(pc, min(pc->rp0_freq, pc_max_freq_cap(pc)));

	return ret;
}

/**
 * xe_guc_pc_restore_stashed_freq - Set min/max back to stashed values
 * @pc: The GuC PC
 *

Annotation

Implementation Notes