drivers/gpu/drm/i915/i915_vma.c

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

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/i915/i915_vma.c
Extension
.c
Size
60143 bytes
Lines
2335
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

struct i915_vma_work {
	struct dma_fence_work base;
	struct i915_address_space *vm;
	struct i915_vm_pt_stash stash;
	struct i915_vma_resource *vma_res;
	struct drm_i915_gem_object *obj;
	struct i915_sw_dma_fence_cb cb;
	unsigned int pat_index;
	unsigned int flags;
};

static void __vma_bind(struct dma_fence_work *work)
{
	struct i915_vma_work *vw = container_of(work, typeof(*vw), base);
	struct i915_vma_resource *vma_res = vw->vma_res;

	/*
	 * We are about the bind the object, which must mean we have already
	 * signaled the work to potentially clear/move the pages underneath. If
	 * something went wrong at that stage then the object should have
	 * unknown_state set, in which case we need to skip the bind.
	 */
	if (i915_gem_object_has_unknown_state(vw->obj))
		return;

	vma_res->ops->bind_vma(vma_res->vm, &vw->stash,
			       vma_res, vw->pat_index, vw->flags);
}

static void __vma_release(struct dma_fence_work *work)
{
	struct i915_vma_work *vw = container_of(work, typeof(*vw), base);

	if (vw->obj)
		i915_gem_object_put(vw->obj);

	i915_vm_free_pt_stash(vw->vm, &vw->stash);
	if (vw->vma_res)
		i915_vma_resource_put(vw->vma_res);
}

static const struct dma_fence_work_ops bind_ops = {
	.name = "bind",
	.work = __vma_bind,
	.release = __vma_release,
};

struct i915_vma_work *i915_vma_work(void)
{
	struct i915_vma_work *vw;

	vw = kzalloc_obj(*vw);
	if (!vw)
		return NULL;

	dma_fence_work_init(&vw->base, &bind_ops);
	vw->base.dma.error = -EAGAIN; /* disable the worker by default */

	return vw;
}

int i915_vma_wait_for_bind(struct i915_vma *vma)
{
	int err = 0;

	if (rcu_access_pointer(vma->active.excl.fence)) {
		struct dma_fence *fence;

		rcu_read_lock();
		fence = dma_fence_get_rcu_safe(&vma->active.excl.fence);
		rcu_read_unlock();
		if (fence) {
			err = dma_fence_wait(fence, true);
			dma_fence_put(fence);
		}
	}

	return err;
}

#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)
static int i915_vma_verify_bind_complete(struct i915_vma *vma)
{
	struct dma_fence *fence = i915_active_fence_get(&vma->active.excl);
	int err;

	if (!fence)
		return 0;

	if (dma_fence_is_signaled(fence))

Annotation

Implementation Notes