Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 76247c57 authored by Tarun Karra's avatar Tarun Karra Committed by Jeremy Gebben
Browse files

msm: kgsl: Map global pagetable entries after IOMMU attach



Upstream IOMMU driver only supports map after the pagetable
is attached. Change the sequence in GPU driver to match
upstream IOMMU driver requirement.  Panic if we fail to map
global entries.

Change-Id: I1997e11d84b9de545f61bc16fd3d092ba80158f7
Signed-off-by: default avatarTarun Karra <tkarra@codeaurora.org>
Signed-off-by: default avatarJordan Crouse <jcrouse@codeaurora.org>
parent 729ef8ff
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -979,6 +979,8 @@ static int kgsl_iommu_start(struct kgsl_mmu *mmu)
	if (status)
		goto done;

	kgsl_map_global_pt_entries(mmu->defaultpagetable);

	kgsl_iommu_enable_clk(mmu);

	/* Get the lsb value of pagetables set in the IOMMU ttbr0 register as
+31 −14
Original line number Diff line number Diff line
@@ -104,6 +104,16 @@ EXPORT_SYMBOL(kgsl_search_global_pt_entries);
static void kgsl_unmap_global_pt_entries(struct kgsl_pagetable *pagetable)
{
	int i;
	unsigned long flags;

	BUG_ON(pagetable->name == KGSL_MMU_GLOBAL_PT);

	spin_lock_irqsave(&kgsl_driver.ptlock, flags);
	if (pagetable->globals_mapped == false) {
		spin_unlock_irqrestore(&kgsl_driver.ptlock, flags);
		return;
	}
	spin_unlock_irqrestore(&kgsl_driver.ptlock, flags);

	for (i = 0; i < KGSL_MAX_GLOBAL_PT_ENTRIES; i++) {
		struct kgsl_memdesc *entry = kgsl_global_pt_entries.entries[i];
@@ -123,6 +133,10 @@ static void kgsl_unmap_global_pt_entries(struct kgsl_pagetable *pagetable)
		kgsl_mmu_unmap(pagetable,
				kgsl_global_pt_entries.entries[i]);
	}

	spin_lock_irqsave(&kgsl_driver.ptlock, flags);
	pagetable->globals_mapped = false;
	spin_unlock_irqrestore(&kgsl_driver.ptlock, flags);
}

/**
@@ -131,11 +145,18 @@ static void kgsl_unmap_global_pt_entries(struct kgsl_pagetable *pagetable)
 * @pagetable: Pointer to a kgsl_pagetable structure
 *
 * Map all the current global PT entries into the specified pagetable.
 * Returns error if an entry fails to map or 0 on success.
 */
static int kgsl_map_global_pt_entries(struct kgsl_pagetable *pagetable)
void kgsl_map_global_pt_entries(struct kgsl_pagetable *pagetable)
{
	int i, ret = 0;
	unsigned long flags;

	spin_lock_irqsave(&kgsl_driver.ptlock, flags);
	if (pagetable->globals_mapped == true) {
		spin_unlock_irqrestore(&kgsl_driver.ptlock, flags);
		return;
	}
	spin_unlock_irqrestore(&kgsl_driver.ptlock, flags);

	for (i = 0; !ret && i < KGSL_MAX_GLOBAL_PT_ENTRIES; i++) {
		struct kgsl_memdesc *entry = kgsl_global_pt_entries.entries[i];
@@ -153,16 +174,15 @@ static int kgsl_map_global_pt_entries(struct kgsl_pagetable *pagetable)
			continue;

		ret = kgsl_mmu_map(pagetable, entry);
		if (ret)
			break;

		/* If we cannot map the global entries, nothing will work. */
		BUG_ON(ret);
	}

	if (ret)
		kgsl_unmap_global_pt_entries(pagetable);

	return ret;
	spin_lock_irqsave(&kgsl_driver.ptlock, flags);
	pagetable->globals_mapped = true;
	spin_unlock_irqrestore(&kgsl_driver.ptlock, flags);
}
EXPORT_SYMBOL(kgsl_map_global_pt_entries);

/**
 * kgsl_remove_global_pt_entry() - Remove a memory descriptor from the global PT
@@ -614,11 +634,8 @@ kgsl_mmu_createpagetableobject(struct kgsl_mmu *mmu,
			goto err;
	}

	if (KGSL_MMU_SECURE_PT != name) {
		status = kgsl_map_global_pt_entries(pagetable);
		if (status)
			goto err;
	}
	if ((KGSL_MMU_SECURE_PT != name) && (KGSL_MMU_GLOBAL_PT != name))
		kgsl_map_global_pt_entries(pagetable);

	spin_lock_irqsave(&kgsl_driver.ptlock, flags);
	list_add(&pagetable->list, &kgsl_driver.pagetable_list);
+2 −0
Original line number Diff line number Diff line
@@ -60,6 +60,7 @@ struct kgsl_pagetable {
	struct kgsl_mmu *mmu;
	unsigned long *mem_bitmap;
	unsigned int bitmap_size;
	bool globals_mapped;
};

struct kgsl_mmu;
@@ -173,6 +174,7 @@ int kgsl_mmu_gpuaddr_in_range(struct kgsl_pagetable *pt, uint64_t gpuaddr);
int kgsl_add_global_pt_entry(struct kgsl_device *device,
	struct kgsl_memdesc *memdesc);
void kgsl_remove_global_pt_entry(struct kgsl_memdesc *memdesc);
void kgsl_map_global_pt_entries(struct kgsl_pagetable *pagetable);

struct kgsl_memdesc *kgsl_search_global_pt_entries(unsigned int gpuaddr,
		unsigned int size);