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

Commit 4112deb8 authored by Jeremy Gebben's avatar Jeremy Gebben
Browse files

msm: kgsl: store DOMAIN_ATTR_PT_BASE_ADDR value in the pagetable



We need to use this value in the iommu fault handler so
calling iommu_domain_get_attr() to look it up at that time
risks lock recursion in the iommu driver. Instead,
query this attribute once and keep the result.

Change-Id: Iaa8f676ef37a177936927780b077d7192d4f6ded
Signed-off-by: default avatarJeremy Gebben <jgebben@codeaurora.org>
parent 6b4066e4
Loading
Loading
Loading
Loading
+34 −26
Original line number Diff line number Diff line
@@ -70,32 +70,22 @@ static phys_addr_t
kgsl_iommu_get_current_ptbase(struct kgsl_mmu *mmu);

/*
 * kgsl_iommu_get_pt_base_addr - Get the address of the pagetable that the
 * IOMMU ttbr0 register is programmed with
 * kgsl_iommu_get_pt_base_addr - Get the physical address of the pagetable
 * @mmu - Pointer to mmu
 * @pt - kgsl pagetable pointer that contains the IOMMU domain pointer
 *
 * Return - actual pagetable address that the ttbr0 register is programmed
 * with
 */
static phys_addr_t kgsl_iommu_get_pt_base_addr(struct kgsl_mmu *mmu,
						struct kgsl_pagetable *pt)
{
	struct kgsl_iommu_pt *iommu_pt = pt->priv;
	phys_addr_t domain_ptbase;
	int ret;
	struct kgsl_iommu_pt *iommu_pt;

	ret = iommu_domain_get_attr(iommu_pt->domain,
		DOMAIN_ATTR_PT_BASE_ADDR, &domain_ptbase);
	if (pt == NULL)
		return 0;

	/*
	 * If we dont have a valid pagetable address, BUG_ON()
	 * GPU driver wont be functional if we go forward after this
	 * point and it will eventually lead to device reset.
	 */
	BUG_ON(ret);
	iommu_pt = pt->priv;

	return domain_ptbase & KGSL_IOMMU_CTX_TTBR0_ADDR_MASK;
	return iommu_pt->pt_base;
}

/*
@@ -572,9 +562,18 @@ static int kgsl_iommu_init_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt)
	if (KGSL_MMU_GLOBAL_PT == pt->name)
		iommu_set_fault_handler(iommu_pt->domain,
				kgsl_iommu_fault_handler, pt);
	else if (KGSL_MMU_SECURE_PT != pt->name)
		ret = iommu_domain_get_attr(iommu_pt->domain,
				DOMAIN_ATTR_PT_BASE_ADDR,
				&iommu_pt->pt_base);
	else
		iommu_pt->pt_base = 0;
err:
	if (ret)
	if (ret) {
		if (iommu_pt->domain != NULL)
			iommu_domain_free(iommu_pt->domain);
		kfree(iommu_pt);
	}

	return ret;
}
@@ -683,7 +682,7 @@ static int kgsl_attach_pagetable_iommu_domain(struct kgsl_mmu *mmu)
	for (i = 0; i < KGSL_IOMMU_CONTEXT_MAX; i++) {

		ctx = &iommu->ctx[i];
		if (ctx->dev == NULL)
		if (ctx->dev == NULL || ctx->attached)
			continue;

		if (KGSL_IOMMU_CONTEXT_SECURE == i) {
@@ -693,7 +692,6 @@ static int kgsl_attach_pagetable_iommu_domain(struct kgsl_mmu *mmu)
				continue;
		}

		if (!ctx->attached) {
		ret = iommu_attach_device(iommu_pt->domain, ctx->dev);
		if (ret) {
			KGSL_MEM_ERR(mmu->device,
@@ -705,6 +703,16 @@ static int kgsl_attach_pagetable_iommu_domain(struct kgsl_mmu *mmu)
		KGSL_MEM_INFO(mmu->device,
				"iommu pt %p attached to dev %p, ctx_id %d\n",
				iommu_pt->domain, ctx->dev, ctx->ctx_id);
		if (KGSL_IOMMU_CONTEXT_SECURE != i) {
			ret = iommu_domain_get_attr(iommu_pt->domain,
					DOMAIN_ATTR_PT_BASE_ADDR,
					&iommu_pt->pt_base);
			if (ret) {
				KGSL_CORE_ERR(
				  "pt_base query failed, using global pt\n");
				mmu->features |= KGSL_MMU_GLOBAL_PAGETABLE;
				ret = 0;
			}
		}
	}

+2 −0
Original line number Diff line number Diff line
@@ -212,10 +212,12 @@ struct kgsl_iommu {
 * struct kgsl_iommu_pt - Iommu pagetable structure private to kgsl driver
 * @domain: Pointer to the iommu domain that contains the iommu pagetable
 * @iommu: Pointer to iommu structure
 * @pt_base: physical base pointer of this pagetable.
 */
struct kgsl_iommu_pt {
	struct iommu_domain *domain;
	struct kgsl_iommu *iommu;
	phys_addr_t pt_base;
};

/*