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

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

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/i915/gt/selftest_tlb.c
Extension
.c
Size
10435 bytes
Lines
406
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 (!i915_request_completed(rq)) {
			pr_err("%s(%s): Semaphore sanitycheck failed %llx, with alignment %llx, using PTE size %x (phys %x, sg %x)\n",
			       ce->engine->name, va->obj->mm.region->name ?: "smem",
			       addr, align, va->resource->page_sizes_gtt,
			       va->page_sizes.phys, va->page_sizes.sg);
			err = -EIO;
		}
	} else if (!i915_request_completed(rq)) {
		struct i915_vma_resource vb_res = {
			.bi.pages = vb->obj->mm.pages,
			.bi.page_sizes = vb->obj->mm.page_sizes,
			.start = i915_vma_offset(vb),
			.vma_size = i915_vma_size(vb)
		};
		unsigned int pte_flags = 0;

		/* Flip the PTE between A and B */
		if (i915_gem_object_is_lmem(vb->obj))
			pte_flags |= PTE_LM;
		ce->vm->insert_entries(ce->vm, &vb_res, pat_index, pte_flags);

		/* Flush the PTE update to concurrent HW */
		tlbinv(ce->vm, addr & -length, length);

		if (wait_for(i915_request_completed(rq), HZ / 2)) {
			pr_err("%s: Request did not complete; the COND_BBE did not read the updated PTE\n",
			       ce->engine->name);
			err = -EINVAL;
		}
	} else {
		pr_err("Spinner ended unexpectedly\n");
		err = -EIO;
	}
	i915_request_put(rq);

	cs = page_mask_bits(batch->mm.mapping);
	*cs = MI_BATCH_BUFFER_END;
	wmb();

out_va:
	if (vb != va)
		vb->node = vb_node;
	i915_vma_unpin(va);
	if (i915_vma_unbind_unlocked(va))
		err = -EIO;
out:
	i915_gem_object_put(batch);
	return err;
}

static struct drm_i915_gem_object *create_lmem(struct intel_gt *gt)
{
	struct intel_memory_region *mr = gt->i915->mm.regions[INTEL_REGION_LMEM_0];
	resource_size_t size = SZ_1G;

	/*
	 * Allocation of largest possible page size allows to test all types
	 * of pages. To succeed with both allocations, especially in case of Small
	 * BAR, try to allocate no more than quarter of mappable memory.
	 */
	if (mr && size > resource_size(&mr->io) / 4)
		size = resource_size(&mr->io) / 4;

	return i915_gem_object_create_lmem(gt->i915, size, I915_BO_ALLOC_CONTIGUOUS);
}

static struct drm_i915_gem_object *create_smem(struct intel_gt *gt)
{
	/*
	 * SZ_64K pages require covering the whole 2M PT (gen8 to tgl/dg1).
	 * While that does not require the whole 2M block to be contiguous
	 * it is easier to make it so, since we need that for SZ_2M pagees.
	 * Since we randomly offset the start of the vma, we need a 4M object
	 * so that there is a 2M range within it is suitable for SZ_64K PTE.
	 */
	return i915_gem_object_create_internal(gt->i915, SZ_4M);
}

static int
mem_tlbinv(struct intel_gt *gt,
	   struct drm_i915_gem_object *(*create_fn)(struct intel_gt *),
	   void (*tlbinv)(struct i915_address_space *vm, u64 addr, u64 length))
{
	unsigned int ppgtt_size = RUNTIME_INFO(gt->i915)->ppgtt_size;
	struct intel_engine_cs *engine;
	struct drm_i915_gem_object *A, *B;
	struct i915_ppgtt *ppgtt;
	struct i915_vma *va, *vb;
	enum intel_engine_id id;
	I915_RND_STATE(prng);

Annotation

Implementation Notes