drivers/gpu/drm/xe/xe_force_wake.c

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

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/xe/xe_force_wake.c
Extension
.c
Size
8579 bytes
Lines
303
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 (!domain->ref++) {
			awake_rqst |= BIT(domain->id);
			domain_wake(gt, domain);
		}
		ref_incr |= BIT(domain->id);
	}
	for_each_fw_domain_masked(domain, awake_rqst, fw, tmp) {
		if (domain_wake_wait(gt, domain) == 0) {
			fw->awake_domains |= BIT(domain->id);
		} else {
			awake_failed |= BIT(domain->id);
			--domain->ref;
		}
	}
	ref_incr &= ~awake_failed;
	spin_unlock_irqrestore(&fw->lock, flags);

	xe_gt_WARN(gt, awake_failed, "Forcewake domain%s %#x failed to acknowledge awake request\n",
		   str_plural(hweight_long(awake_failed)), awake_failed);

	if (domains == XE_FORCEWAKE_ALL && ref_incr == fw->initialized_domains)
		ref_incr |= XE_FORCEWAKE_ALL;

	return ref_incr;
}

/**
 * xe_force_wake_put - Decrement the refcount and put domain to sleep if refcount becomes 0
 * @fw: Pointer to the force wake structure
 * @fw_ref: return of xe_force_wake_get()
 *
 * This function reduces the reference counts for domains in fw_ref. If
 * refcount for any of the specified domain reaches 0, it puts the domain to sleep
 * and waits for acknowledgment for domain to sleep within 50 milisec timeout.
 * Warns in case of timeout of ack from domain.
 */
void xe_force_wake_put(struct xe_force_wake *fw, unsigned int fw_ref)
{
	struct xe_gt *gt = fw->gt;
	struct xe_force_wake_domain *domain;
	unsigned int tmp, sleep = 0;
	unsigned long flags;
	int ack_fail = 0;

	/*
	 * Avoid unnecessary lock and unlock when the function is called
	 * in error path of individual domains.
	 */
	if (!fw_ref)
		return;

	if (xe_force_wake_ref_has_domain(fw_ref, XE_FORCEWAKE_ALL))
		fw_ref = fw->initialized_domains;

	spin_lock_irqsave(&fw->lock, flags);
	for_each_fw_domain_masked(domain, fw_ref, fw, tmp) {
		xe_gt_assert(gt, domain->ref);

		if (!--domain->ref) {
			sleep |= BIT(domain->id);
			domain_sleep(gt, domain);
		}
	}
	for_each_fw_domain_masked(domain, sleep, fw, tmp) {
		if (domain_sleep_wait(gt, domain) == 0)
			fw->awake_domains &= ~BIT(domain->id);
		else
			ack_fail |= BIT(domain->id);
	}
	spin_unlock_irqrestore(&fw->lock, flags);

	xe_gt_WARN(gt, ack_fail, "Forcewake domain%s %#x failed to acknowledge sleep request\n",
		   str_plural(hweight_long(ack_fail)), ack_fail);
}

const char *xe_force_wake_domain_to_str(enum xe_force_wake_domain_id id)
{
	switch (id) {
	case XE_FW_DOMAIN_ID_GT:
		return "GT";
	case XE_FW_DOMAIN_ID_RENDER:
		return "Render";
	case XE_FW_DOMAIN_ID_MEDIA:
		return "Media";
	case XE_FW_DOMAIN_ID_MEDIA_VDBOX0:
		return "VDBox0";
	case XE_FW_DOMAIN_ID_MEDIA_VDBOX1:
		return "VDBox1";
	case XE_FW_DOMAIN_ID_MEDIA_VDBOX2:
		return "VDBox2";

Annotation

Implementation Notes