msm: iommu: Selectively invalidate TLB entries
When mapping or unmapping within a domain, only invalidate
the TLB entries associated with the VA of the mapping being
modified (and the ASID associated with the related context)
rather than invalidating the entire TLB.
Signed-off-by: Stepan Moskovchenko <stepanm@codeaurora.org>
diff --git a/arch/arm/mach-msm/iommu.c b/arch/arm/mach-msm/iommu.c
index e6420f0..753cc33 100644
--- a/arch/arm/mach-msm/iommu.c
+++ b/arch/arm/mach-msm/iommu.c
@@ -105,6 +105,38 @@
return ret;
}
+static int __flush_iotlb_va(struct iommu_domain *domain, unsigned int va)
+{
+ struct msm_priv *priv = domain->priv;
+ struct msm_iommu_drvdata *iommu_drvdata;
+ struct msm_iommu_ctx_drvdata *ctx_drvdata;
+ int ret = 0;
+ int asid;
+
+ list_for_each_entry(ctx_drvdata, &priv->list_attached, attached_elm) {
+ if (!ctx_drvdata->pdev || !ctx_drvdata->pdev->dev.parent)
+ BUG();
+
+ iommu_drvdata = dev_get_drvdata(ctx_drvdata->pdev->dev.parent);
+ if (!iommu_drvdata)
+ BUG();
+
+ ret = __enable_clocks(iommu_drvdata);
+ if (ret)
+ goto fail;
+
+ asid = GET_CONTEXTIDR_ASID(iommu_drvdata->base,
+ ctx_drvdata->num);
+
+ SET_TLBIVA(iommu_drvdata->base, ctx_drvdata->num,
+ asid | (va & TLBIVA_VA));
+ mb();
+ __disable_clocks(iommu_drvdata);
+ }
+fail:
+ return ret;
+}
+
static void __reset_context(void __iomem *base, int ctx)
{
SET_BPRCOSH(base, ctx, 0);
@@ -522,7 +554,7 @@
clean_pte(sl_pte, sl_pte + 16);
}
- ret = __flush_iotlb(domain);
+ ret = __flush_iotlb_va(domain, va);
fail:
spin_unlock_irqrestore(&msm_iommu_lock, flags);
return ret;
@@ -620,7 +652,7 @@
}
}
- ret = __flush_iotlb(domain);
+ ret = __flush_iotlb_va(domain, va);
fail:
spin_unlock_irqrestore(&msm_iommu_lock, flags);
return ret;
@@ -655,9 +687,6 @@
if (ret)
goto fail;
- /* Invalidate context TLB */
- SET_CTX_TLBIALL(base, ctx, 0);
- mb();
SET_V2PPR(base, ctx, va & V2Pxx_VA);
mb();