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

Commit 23e1365c authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "iommu/arm-smmu: Fix context fault interrupt test"

parents 7a21e400 5c502c5c
Loading
Loading
Loading
Loading
+43 −32
Original line number Diff line number Diff line
@@ -285,14 +285,22 @@ static int selftest;
module_param_named(selftest, selftest, int, 0644);
static int irq_count;

struct arm_smmu_cf_selftest_data {
	struct arm_smmu_device *smmu;
	int cbndx;
};

static DECLARE_WAIT_QUEUE_HEAD(wait_int);
static irqreturn_t arm_smmu_cf_selftest(int irq, void *cb_base)
static irqreturn_t arm_smmu_cf_selftest(int irq, void *data)
{
	u32 fsr;
	struct irq_data *irq_data = irq_get_irq_data(irq);
	struct arm_smmu_cf_selftest_data *cb_data = data;
	struct arm_smmu_device *smmu = cb_data->smmu;
	int idx = cb_data->cbndx;
	unsigned long hwirq = ULONG_MAX;

	fsr = readl_relaxed(cb_base + ARM_SMMU_CB_FSR);
	fsr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSR);

	irq_count++;
	if (irq_data)
@@ -300,7 +308,7 @@ static irqreturn_t arm_smmu_cf_selftest(int irq, void *cb_base)
	pr_info("Interrupt (irq:%d hwirq:%ld) received, fsr:0x%x\n",
				irq, hwirq, fsr);

	writel_relaxed(fsr, cb_base + ARM_SMMU_CB_FSR);
	arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_FSR, fsr);

	wake_up(&wait_int);
	return IRQ_HANDLED;
@@ -310,6 +318,7 @@ static void arm_smmu_interrupt_selftest(struct arm_smmu_device *smmu)
{
	int cb;
	int cb_count = 0;
	struct arm_smmu_cf_selftest_data *cb_data;

	if (!selftest)
		return;
@@ -319,22 +328,26 @@ static void arm_smmu_interrupt_selftest(struct arm_smmu_device *smmu)
	if (smmu->version < ARM_SMMU_V2)
		return;

	cb_data = kmalloc(sizeof(*cb_data), GFP_KERNEL);
	if (!cb_data)
		return;
	cb_data->smmu = smmu;

	for_each_clear_bit_from(cb, smmu->context_map,
				smmu->num_context_banks) {
		int irq;
		int ret;
		void *cb_base;
		u32 reg;
		u32 reg_orig;
		int irq_cnt;

		irq = smmu->irqs[smmu->num_global_irqs + cb];
		cb_base = ARM_SMMU_CB(smmu, cb);
		cb_data->cbndx = cb;

		ret = devm_request_threaded_irq(smmu->dev, irq, NULL,
				arm_smmu_cf_selftest,
				IRQF_ONESHOT | IRQF_SHARED,
				"arm-smmu-context-fault", cb_base);
				"arm-smmu-context-fault", cb_data);
		if (ret < 0) {
			dev_err(smmu->dev,
				"Failed to request cntx IRQ %d (%u)\n",
@@ -345,25 +358,26 @@ static void arm_smmu_interrupt_selftest(struct arm_smmu_device *smmu)
		cb_count++;
		irq_cnt = irq_count;

		reg_orig = readl_relaxed(cb_base + ARM_SMMU_CB_SCTLR);
		reg_orig = arm_smmu_cb_read(smmu, cb, ARM_SMMU_CB_SCTLR);
		reg = reg_orig | SCTLR_CFIE | SCTLR_CFRE;

		writel_relaxed(reg, cb_base + ARM_SMMU_CB_SCTLR);
		arm_smmu_cb_write(smmu, cb, ARM_SMMU_CB_SCTLR, reg);
		dev_info(smmu->dev, "Testing cntx %d irq %d\n", cb, irq);

		/* Make sure ARM_SMMU_CB_SCTLR is configured */
		wmb();
		writel_relaxed(FSR_TF, cb_base + ARM_SMMU_CB_FSRRESTORE);
		arm_smmu_cb_write(smmu, cb, ARM_SMMU_CB_FSRRESTORE, FSR_TF);

		wait_event_timeout(wait_int, (irq_count > irq_cnt),
			msecs_to_jiffies(1000));

		/* Make sure ARM_SMMU_CB_FSRRESTORE is written to */
		wmb();
		writel_relaxed(reg_orig, cb_base + ARM_SMMU_CB_SCTLR);
		devm_free_irq(smmu->dev, irq, cb_base);
		arm_smmu_cb_write(smmu, cb, ARM_SMMU_CB_SCTLR, reg_orig);
		devm_free_irq(smmu->dev, irq, cb_data);
	}

	kfree(cb_data);
	dev_info(smmu->dev,
			"Interrupt selftest completed...\n");
	dev_info(smmu->dev,
@@ -4834,30 +4848,28 @@ module_exit(arm_smmu_exit);
#define TCU_HW_VERSION_HLOS1		(0x18)

#define DEBUG_SID_HALT_REG		0x0
#define DEBUG_SID_HALT_VAL		(0x1 << 16)
#define DEBUG_SID_HALT_SID_MASK		0x3ff
#define DEBUG_SID_HALT_REQ		BIT(16)
#define DEBUG_SID_HALT_SID		GENMASK(9, 0)

#define DEBUG_VA_ADDR_REG		0x8

#define DEBUG_TXN_TRIGG_REG		0x18
#define DEBUG_TXN_AXPROT_SHIFT		6
#define DEBUG_TXN_AXCACHE_SHIFT		2
#define DEBUG_TXN_AXPROT		GENMASK(8, 6)
#define DEBUG_TXN_AXCACHE		GENMASK(5, 2)
#define DEBUG_TRX_WRITE			(0x1 << 1)
#define DEBUG_TXN_READ			(0x0 << 1)
#define DEBUG_TXN_TRIGGER		0x1
#define DEBUG_TXN_TRIGGER		BIT(0)

#define DEBUG_SR_HALT_ACK_REG		0x20
#define DEBUG_SR_HALT_ACK_VAL		(0x1 << 1)
#define DEBUG_SR_ECATS_RUNNING_VAL	(0x1 << 0)

#define DEBUG_PAR_REG			0x28
#define DEBUG_PAR_PA_MASK		((0x1ULL << 36) - 1)
#define DEBUG_PAR_PA_SHIFT		12
#define DEBUG_PAR_FAULT_VAL		0x1
#define DEBUG_PAR_PA			GENMASK_ULL(47, 12)
#define DEBUG_PAR_FAULT_VAL		BIT(0)

#define DEBUG_AXUSER_REG		0x30
#define DEBUG_AXUSER_CDMID_MASK         0xff
#define DEBUG_AXUSER_CDMID_SHIFT        36
#define DEBUG_AXUSER_CDMID		GENMASK_ULL(43, 36)
#define DEBUG_AXUSER_CDMID_VAL          255

#define TBU_DBG_TIMEOUT_US		100
@@ -4943,7 +4955,7 @@ static int qsmmuv500_tbu_halt(struct qsmmuv500_tbu_device *tbu,

	base = tbu->base;
	halt = readl_relaxed(base + DEBUG_SID_HALT_REG);
	halt |= DEBUG_SID_HALT_VAL;
	halt |= DEBUG_SID_HALT_REQ;
	writel_relaxed(halt, base + DEBUG_SID_HALT_REG);

	if (!readl_poll_timeout_atomic(base + DEBUG_SR_HALT_ACK_REG, status,
@@ -5007,7 +5019,7 @@ static void qsmmuv500_tbu_resume(struct qsmmuv500_tbu_device *tbu)

	base = tbu->base;
	val = readl_relaxed(base + DEBUG_SID_HALT_REG);
	val &= ~DEBUG_SID_HALT_VAL;
	val &= ~DEBUG_SID_HALT_REQ;
	writel_relaxed(val, base + DEBUG_SID_HALT_REG);

	tbu->halt_count = 0;
@@ -5119,12 +5131,11 @@ static phys_addr_t qsmmuv500_iova_to_phys(
redo:
	/* Set address and stream-id */
	val = readq_relaxed(tbu->base + DEBUG_SID_HALT_REG);
	val &= ~DEBUG_SID_HALT_SID_MASK;
	val |= sid & DEBUG_SID_HALT_SID_MASK;
	val &= ~DEBUG_SID_HALT_SID;
	val |= FIELD_PREP(DEBUG_SID_HALT_SID, sid);
	writeq_relaxed(val, tbu->base + DEBUG_SID_HALT_REG);
	writeq_relaxed(iova, tbu->base + DEBUG_VA_ADDR_REG);
	val = (u64)(DEBUG_AXUSER_CDMID_VAL & DEBUG_AXUSER_CDMID_MASK) <<
		DEBUG_AXUSER_CDMID_SHIFT;
	val = FIELD_PREP(DEBUG_AXUSER_CDMID, DEBUG_AXUSER_CDMID_VAL);
	writeq_relaxed(val, tbu->base + DEBUG_AXUSER_REG);

	/*
@@ -5132,9 +5143,9 @@ static phys_addr_t qsmmuv500_iova_to_phys(
	 * Priviledged, nonsecure, data transaction
	 * Read operation.
	 */
	val = 0xF << DEBUG_TXN_AXCACHE_SHIFT;
	val |= 0x3 << DEBUG_TXN_AXPROT_SHIFT;
	val |= DEBUG_TXN_TRIGGER;
	val = FIELD_PREP(DEBUG_TXN_AXCACHE, 0xF) |
	      FIELD_PREP(DEBUG_TXN_AXPROT, 0x3) |
	      DEBUG_TXN_TRIGGER;
	writeq_relaxed(val, tbu->base + DEBUG_TXN_TRIGG_REG);

	ret = 0;
@@ -5176,7 +5187,7 @@ static phys_addr_t qsmmuv500_iova_to_phys(
		ret = -EINVAL;
	}

	phys = (val >> DEBUG_PAR_PA_SHIFT) & DEBUG_PAR_PA_MASK;
	phys = FIELD_GET(DEBUG_PAR_PA, val);
	if (ret < 0)
		phys = 0;

@@ -5184,7 +5195,7 @@ static phys_addr_t qsmmuv500_iova_to_phys(
	writeq_relaxed(0, tbu->base + DEBUG_TXN_TRIGG_REG);
	writeq_relaxed(0, tbu->base + DEBUG_VA_ADDR_REG);
	val = readl_relaxed(tbu->base + DEBUG_SID_HALT_REG);
	val &= ~DEBUG_SID_HALT_SID_MASK;
	val &= ~DEBUG_SID_HALT_SID;
	writel_relaxed(val, tbu->base + DEBUG_SID_HALT_REG);

	/*