drivers/gpu/drm/i915/gt/intel_rps.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/i915/gt/intel_rps.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/i915/gt/intel_rps.c
Extension
.c
Size
77529 bytes
Lines
2956
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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 (rps_uses_slpc(rps)) {
			slpc = rps_to_slpc(rps);

			/* Waitboost should not be done with power saving profile */
			if (slpc->power_profile == SLPC_POWER_PROFILES_POWER_SAVING)
				return;

			/* Return if old value is non zero */
			if (!atomic_fetch_inc(&slpc->num_waiters)) {
				/*
				 * Skip queuing boost work if frequency is already boosted,
				 * but still increment num_waiters.
				 */
				if (slpc->min_freq_softlimit >= slpc->boost_freq)
					return;

				GT_TRACE(rps_to_gt(rps), "boost fence:%llx:%llx\n",
					 rq->fence.context, rq->fence.seqno);
				queue_work(rps_to_gt(rps)->i915->unordered_wq,
					   &slpc->boost_work);
			}

			return;
		}

		if (atomic_fetch_inc(&rps->num_waiters))
			return;

		if (!intel_rps_is_active(rps))
			return;

		GT_TRACE(rps_to_gt(rps), "boost fence:%llx:%llx\n",
			 rq->fence.context, rq->fence.seqno);

		if (READ_ONCE(rps->cur_freq) < rps->boost_freq)
			queue_work(rps_to_gt(rps)->i915->unordered_wq, &rps->work);

		WRITE_ONCE(rps->boosts, rps->boosts + 1); /* debug only */
	}
}

int intel_rps_set(struct intel_rps *rps, u8 val)
{
	int err;

	lockdep_assert_held(&rps->lock);
	GEM_BUG_ON(val > rps->max_freq);
	GEM_BUG_ON(val < rps->min_freq);

	if (intel_rps_is_active(rps)) {
		err = rps_set(rps, val, true);
		if (err)
			return err;

		/*
		 * Make sure we continue to get interrupts
		 * until we hit the minimum or maximum frequencies.
		 */
		if (intel_rps_has_interrupts(rps)) {
			struct intel_uncore *uncore = rps_to_uncore(rps);

			set(uncore,
			    GEN6_RP_INTERRUPT_LIMITS, rps_limits(rps, val));

			set(uncore, GEN6_PMINTRMSK, rps_pm_mask(rps, val));
		}
	}

	rps->cur_freq = val;
	return 0;
}

static u32 intel_rps_read_state_cap(struct intel_rps *rps)
{
	struct drm_i915_private *i915 = rps_to_i915(rps);
	struct intel_uncore *uncore = rps_to_uncore(rps);

	if (IS_GEN9_LP(i915))
		return intel_uncore_read(uncore, BXT_RP_STATE_CAP);
	else
		return intel_uncore_read(uncore, GEN6_RP_STATE_CAP);
}

static void
mtl_get_freq_caps(struct intel_rps *rps, struct intel_rps_freq_caps *caps)
{
	struct intel_uncore *uncore = rps_to_uncore(rps);
	u32 rp_state_cap = rps_to_gt(rps)->type == GT_MEDIA ?
				intel_uncore_read(uncore, MTL_MEDIAP_STATE_CAP) :
				intel_uncore_read(uncore, MTL_RP_STATE_CAP);

Annotation

Implementation Notes