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

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

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/i915/gt/gen6_ppgtt.c
Extension
.c
Size
11811 bytes
Lines
470
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 (iter.dma == iter.max) {
			iter.sg = __sg_next(iter.sg);
			if (!iter.sg || sg_dma_len(iter.sg) == 0)
				break;

			iter.dma = sg_dma_address(iter.sg);
			iter.max = iter.dma + sg_dma_len(iter.sg);
		}

		if (++act_pte == GEN6_PTES) {
			vaddr = px_vaddr(i915_pt_entry(pd, ++act_pt));
			act_pte = 0;
		}
	} while (1);

	vma_res->page_sizes_gtt = I915_GTT_PAGE_SIZE;
}

static void gen6_flush_pd(struct gen6_ppgtt *ppgtt, u64 start, u64 end)
{
	struct i915_page_directory * const pd = ppgtt->base.pd;
	struct i915_page_table *pt;
	unsigned int pde;

	start = round_down(start, SZ_64K);
	end = round_up(end, SZ_64K) - start;

	mutex_lock(&ppgtt->flush);

	gen6_for_each_pde(pt, pd, start, end, pde)
		gen6_write_pde(ppgtt, pde, pt);

	mb();
	ioread32(ppgtt->pd_addr + pde - 1);
	gen6_ggtt_invalidate(ppgtt->base.vm.gt->ggtt);
	mb();

	mutex_unlock(&ppgtt->flush);
}

static void gen6_alloc_va_range(struct i915_address_space *vm,
				struct i915_vm_pt_stash *stash,
				u64 start, u64 length)
{
	struct gen6_ppgtt *ppgtt = to_gen6_ppgtt(i915_vm_to_ppgtt(vm));
	struct i915_page_directory * const pd = ppgtt->base.pd;
	struct i915_page_table *pt;
	bool flush = false;
	u64 from = start;
	unsigned int pde;

	spin_lock(&pd->lock);
	gen6_for_each_pde(pt, pd, start, length, pde) {
		const unsigned int count = gen6_pte_count(start, length);

		if (!pt) {
			spin_unlock(&pd->lock);

			pt = stash->pt[0];
			__i915_gem_object_pin_pages(pt->base);

			fill32_px(pt, vm->scratch[0]->encode);

			spin_lock(&pd->lock);
			if (!pd->entry[pde]) {
				stash->pt[0] = pt->stash;
				atomic_set(&pt->used, 0);
				pd->entry[pde] = pt;
			} else {
				pt = pd->entry[pde];
			}

			flush = true;
		}

		atomic_add(count, &pt->used);
	}
	spin_unlock(&pd->lock);

	if (flush && i915_vma_is_bound(ppgtt->vma, I915_VMA_GLOBAL_BIND)) {
		intel_wakeref_t wakeref;

		with_intel_runtime_pm(&vm->i915->runtime_pm, wakeref)
			gen6_flush_pd(ppgtt, from, start);
	}
}

static int gen6_ppgtt_init_scratch(struct gen6_ppgtt *ppgtt)
{
	struct i915_address_space * const vm = &ppgtt->base.vm;

Annotation

Implementation Notes