drivers/accel/habanalabs/common/mmu/mmu_v1.c

Source file repositories/reference/linux-study-clean/drivers/accel/habanalabs/common/mmu/mmu_v1.c

File Facts

System
Linux kernel
Corpus path
drivers/accel/habanalabs/common/mmu/mmu_v1.c
Extension
.c
Size
15065 bytes
Lines
551
Domain
Driver Families
Bucket
drivers/accel
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 (ctx->dram_default_hops[i] == ULLONG_MAX) {
			dev_err(hdev->dev, "failed to alloc hop 3, i: %d\n", i);
			rc = -ENOMEM;
			goto hop3_err;
		}
		hop3_allocated++;
	}

	/* need only pte 0 in hops 0 and 1 */
	pte_val = (hop1_addr & HOP_PHYS_ADDR_MASK) | PAGE_PRESENT_MASK;
	hl_mmu_dr_write_pte(ctx, hop0_addr, pte_val);

	pte_val = (hop2_addr & HOP_PHYS_ADDR_MASK) | PAGE_PRESENT_MASK;
	hl_mmu_dr_write_pte(ctx, hop1_addr, pte_val);
	hl_mmu_dr_get_pte(ctx, hop1_addr);

	hop2_pte_addr = hop2_addr;
	for (i = 0 ; i < num_of_hop3 ; i++) {
		pte_val = (ctx->dram_default_hops[i] & HOP_PHYS_ADDR_MASK) |
				PAGE_PRESENT_MASK;
		hl_mmu_dr_write_pte(ctx, hop2_pte_addr, pte_val);
		hl_mmu_dr_get_pte(ctx, hop2_addr);
		hop2_pte_addr += HL_PTE_SIZE;
	}

	pte_val = (prop->mmu_dram_default_page_addr & HOP_PHYS_ADDR_MASK) |
			LAST_MASK | PAGE_PRESENT_MASK;

	for (i = 0 ; i < num_of_hop3 ; i++) {
		hop3_pte_addr = ctx->dram_default_hops[i];
		for (j = 0 ; j < HOP_PTE_ENTRIES_512 ; j++) {
			hl_mmu_dr_write_final_pte(ctx, hop3_pte_addr, pte_val);
			hl_mmu_dr_get_pte(ctx, ctx->dram_default_hops[i]);
			hop3_pte_addr += HL_PTE_SIZE;
		}
	}

	hl_mmu_dr_flush(ctx);

	return 0;

hop3_err:
	for (i = 0 ; i < hop3_allocated ; i++)
		hl_mmu_dr_free_hop(ctx, ctx->dram_default_hops[i]);

	hl_mmu_dr_free_hop(ctx, hop2_addr);
hop2_err:
	hl_mmu_dr_free_hop(ctx, hop1_addr);
hop1_err:
	kfree(ctx->dram_default_hops);

	return rc;
}

static void dram_default_mapping_fini(struct hl_ctx *ctx)
{
	struct hl_device *hdev = ctx->hdev;
	struct asic_fixed_properties *prop = &hdev->asic_prop;
	u64 num_of_hop3, total_hops, hop0_addr, hop1_addr, hop2_addr,
		hop2_pte_addr, hop3_pte_addr;
	int i, j;

	if ((!prop->dram_supports_virtual_memory) ||
			(!hdev->dram_default_page_mapping) ||
			(ctx->asid == HL_KERNEL_ASID_ID))
		return;

	num_of_hop3 = prop->dram_size_for_default_page_mapping;
	do_div(num_of_hop3, prop->dram_page_size);
	do_div(num_of_hop3, HOP_PTE_ENTRIES_512);

	hop0_addr = hl_mmu_dr_get_hop0_addr(ctx);
	/* add hop1 and hop2 */
	total_hops = num_of_hop3 + 2;
	hop1_addr = ctx->dram_default_hops[total_hops - 1];
	hop2_addr = ctx->dram_default_hops[total_hops - 2];

	for (i = 0 ; i < num_of_hop3 ; i++) {
		hop3_pte_addr = ctx->dram_default_hops[i];
		for (j = 0 ; j < HOP_PTE_ENTRIES_512 ; j++) {
			hl_mmu_dr_clear_pte(ctx, hop3_pte_addr);
			hl_mmu_dr_put_pte(ctx, ctx->dram_default_hops[i]);
			hop3_pte_addr += HL_PTE_SIZE;
		}
	}

	hop2_pte_addr = hop2_addr;
	for (i = 0 ; i < num_of_hop3 ; i++) {
		hl_mmu_dr_clear_pte(ctx, hop2_pte_addr);
		hl_mmu_dr_put_pte(ctx, hop2_addr);

Annotation

Implementation Notes