drivers/gpu/drm/xe/xe_sync.c

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

File Facts

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

struct xe_user_fence {
	struct xe_device *xe;
	struct kref refcount;
	struct dma_fence_cb cb;
	struct work_struct worker;
	struct mm_struct *mm;
	u64 __user *addr;
	u64 value;
	int signalled;
};

static void user_fence_destroy(struct kref *kref)
{
	struct xe_user_fence *ufence = container_of(kref, struct xe_user_fence,
						 refcount);

	mmdrop(ufence->mm);
	kfree(ufence);
}

static void user_fence_get(struct xe_user_fence *ufence)
{
	kref_get(&ufence->refcount);
}

static void user_fence_put(struct xe_user_fence *ufence)
{
	kref_put(&ufence->refcount, user_fence_destroy);
}

static struct xe_user_fence *user_fence_create(struct xe_device *xe, u64 addr,
					       u64 value)
{
	struct xe_user_fence *ufence;
	u64 __user *ptr = u64_to_user_ptr(addr);
	u64 __maybe_unused prefetch_val;

	if (get_user(prefetch_val, ptr))
		return ERR_PTR(-EFAULT);

	ufence = kzalloc_obj(*ufence);
	if (!ufence)
		return ERR_PTR(-ENOMEM);

	ufence->xe = xe;
	kref_init(&ufence->refcount);
	ufence->addr = ptr;
	ufence->value = value;
	ufence->mm = current->mm;
	mmgrab(ufence->mm);

	return ufence;
}

static void user_fence_worker(struct work_struct *w)
{
	struct xe_user_fence *ufence = container_of(w, struct xe_user_fence, worker);

	WRITE_ONCE(ufence->signalled, 1);
	if (mmget_not_zero(ufence->mm)) {
		kthread_use_mm(ufence->mm);
		if (copy_to_user(ufence->addr, &ufence->value, sizeof(ufence->value)))
			XE_WARN_ON("Copy to user failed");
		kthread_unuse_mm(ufence->mm);
		mmput(ufence->mm);
	} else {
		drm_dbg(&ufence->xe->drm, "mmget_not_zero() failed, ufence wasn't signaled\n");
	}

	/*
	 * Wake up waiters only after updating the ufence state, allowing the UMD
	 * to safely reuse the same ufence without encountering -EBUSY errors.
	 */
	wake_up_all(&ufence->xe->ufence_wq);
	user_fence_put(ufence);
}

static void kick_ufence(struct xe_user_fence *ufence, struct dma_fence *fence)
{
	INIT_WORK(&ufence->worker, user_fence_worker);
	queue_work(ufence->xe->ordered_wq, &ufence->worker);
	dma_fence_put(fence);
}

static void user_fence_cb(struct dma_fence *fence, struct dma_fence_cb *cb)
{
	struct xe_user_fence *ufence = container_of(cb, struct xe_user_fence, cb);

	kick_ufence(ufence, fence);
}

Annotation

Implementation Notes