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

Commit 811f3267 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "iommu: msm: Do not sleep for 10 ms when TLB sync does not complete"

parents 00cb75c8 6a233e66
Loading
Loading
Loading
Loading
+15 −11
Original line number Diff line number Diff line
@@ -15,23 +15,24 @@

#define CTX_SHIFT  12

#define GET_GLOBAL_REG(reg, base) (readl_relaxed((base) + (reg)))
#define GET_GLOBAL_REG_Q(reg, base) (readq_relaxed((base) + (reg)))
#define GET_CTX_REG(reg, base, ctx) \
	(readl_relaxed((base) + (reg) + ((ctx) << CTX_SHIFT)))
#define GET_CTX_REG_Q(reg, base, ctx) \
	(readq_relaxed((base) + (reg) + ((ctx) << CTX_SHIFT)))
#define CTX_REG(reg, base, ctx) \
	((base) + (reg) + ((ctx) << CTX_SHIFT))
#define GLB_REG(reg, base) \
	((base) + (reg))

#define GET_GLOBAL_REG(reg, base) (readl_relaxed(GLB_REG(reg, base)))
#define GET_GLOBAL_REG_Q(reg, base) (readq_relaxed(GLB_REG(reg, base)))
#define GET_CTX_REG(reg, base, ctx) (readl_relaxed(CTX_REG(reg, base, ctx)))
#define GET_CTX_REG_Q(reg, base, ctx) (readq_relaxed(CTX_REG(reg, base, ctx)))

#define SET_GLOBAL_REG(reg, base, val)	writel_relaxed((val), ((base) + (reg)))
#define SET_GLOBAL_REG_Q(reg, base, val) \
	(writeq_relaxed((val), ((base) + (reg))))
	(writeq_relaxed((val), GLB_REG(reg, base)))

#define SET_CTX_REG(reg, base, ctx, val) \
	writel_relaxed((val), \
		((base) + (reg) + ((ctx) << CTX_SHIFT)))
	writel_relaxed((val), (CTX_REG(reg, base, ctx)))
#define SET_CTX_REG_Q(reg, base, ctx, val) \
	writeq_relaxed((val), \
		((base) + (reg) + ((ctx) << CTX_SHIFT)))
	writeq_relaxed((val), CTX_REG(reg, base, ctx))

/* Wrappers for numbered registers */
#define SET_GLOBAL_REG_N(b, n, r, v) SET_GLOBAL_REG((b), ((r) + (n << 2)), (v))
@@ -172,6 +173,9 @@ do { \
				GET_GLOBAL_FIELD(b, MICRO_MMU_CTRL, IDLE)
#define SET_MICRO_MMU_CTRL_RESERVED(b, v) \
				SET_GLOBAL_FIELD(b, MICRO_MMU_CTRL, RESERVED, v)

#define MMU_CTRL_IDLE (MICRO_MMU_CTRL_IDLE_MASK << MICRO_MMU_CTRL_IDLE_SHIFT)

#define SET_PREDICTIONDIS0(b, v) SET_GLOBAL_REG(PREDICTIONDIS0, (b), (v))
#define SET_PREDICTIONDIS1(b, v) SET_GLOBAL_REG(PREDICTIONDIS1, (b), (v))
#define SET_S1L1BFBLP0(b, v)     SET_GLOBAL_REG(S1L1BFBLP0, (b), (v))
+22 −16
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#include <linux/platform_device.h>
#include <linux/errno.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/mutex.h>
@@ -174,13 +175,20 @@ struct iommu_access_ops iommu_access_ops_v1 = {
	.iommu_lock_release = _iommu_lock_release,
};

void iommu_halt(const struct msm_iommu_drvdata *iommu_drvdata)
void iommu_halt(struct msm_iommu_drvdata const *iommu_drvdata)
{
	if (iommu_drvdata->halt_enabled) {
		SET_MICRO_MMU_CTRL_HALT_REQ(iommu_drvdata->base, 1);
		unsigned int val;
		void __iomem *base = iommu_drvdata->base;
		int res;

		SET_MICRO_MMU_CTRL_HALT_REQ(base, 1);
		res = readl_tight_poll_timeout(
			GLB_REG(MICRO_MMU_CTRL, base), val,
			     (val & MMU_CTRL_IDLE) == MMU_CTRL_IDLE, 5000000);

		while (GET_MICRO_MMU_CTRL_IDLE(iommu_drvdata->base) == 0)
			cpu_relax();
		if (res)
			BUG();
		/* Ensure device is idle before continuing */
		mb();
	}
@@ -204,21 +212,19 @@ void iommu_resume(const struct msm_iommu_drvdata *iommu_drvdata)
	}
}

static void __sync_tlb(void __iomem *base, int ctx)
static void __sync_tlb(struct msm_iommu_drvdata *iommu_drvdata, int ctx)
{
	int i;
	unsigned int val;
	unsigned int res;
	void __iomem *base = iommu_drvdata->cb_base;

	SET_TLBSYNC(base, ctx, 0);

	/* No barrier needed due to register proximity */
	for (i = 0; i < IOMMU_MSEC_TIMEOUT; i += IOMMU_MSEC_STEP)
		if (GET_CB_TLBSTATUS_SACTIVE(base, ctx) == 0)
			break;
		else
			msleep(IOMMU_MSEC_STEP);

	BUG_ON(i >= IOMMU_MSEC_TIMEOUT);
	/* No barrier needed due to read dependency */
	res = readl_tight_poll_timeout(CTX_REG(CB_TLBSTATUS, base, ctx), val,
				(val & CB_TLBSTATUS_SACTIVE) == 0, 5000000);
	if (res)
		BUG();
}

static int __flush_iotlb_va(struct iommu_domain *domain, unsigned int va)
@@ -242,7 +248,7 @@ static int __flush_iotlb_va(struct iommu_domain *domain, unsigned int va)
		SET_TLBIVA(iommu_drvdata->cb_base, ctx_drvdata->num,
			   ctx_drvdata->asid | (va & CB_TLBIVA_VA));
		mb();
		__sync_tlb(iommu_drvdata->cb_base, ctx_drvdata->num);
		__sync_tlb(iommu_drvdata, ctx_drvdata->num);
		__disable_clocks(iommu_drvdata);
	}
fail:
@@ -269,7 +275,7 @@ static int __flush_iotlb(struct iommu_domain *domain)
		SET_TLBIASID(iommu_drvdata->cb_base, ctx_drvdata->num,
			     ctx_drvdata->asid);
		mb();
		__sync_tlb(iommu_drvdata->cb_base, ctx_drvdata->num);
		__sync_tlb(iommu_drvdata, ctx_drvdata->num);
		__disable_clocks(iommu_drvdata);
	}