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

Commit c8769d86 authored by Sudarshan Rajagopalan's avatar Sudarshan Rajagopalan Committed by Gerrit - the friendly Code Review server
Browse files

iommu: smmu: Defer SMR mask discovery after writes to SCR0



The format of the SMR register depends on the value of 
SCR0.EXIDENABLE bit. With the support for Extended Stream
ID now available, defer the SMR mask testing after SCR0
register is written.

Change-Id: Iafdd6c38be5c0cd4be2f6f53c50853c308226c26
Signed-off-by: default avatarSudarshan Rajagopalan <sudaraja@codeaurora.org>
parent 3295850b
Loading
Loading
Loading
Loading
+26 −20
Original line number Diff line number Diff line
@@ -1847,14 +1847,37 @@ static void arm_smmu_write_sme(struct arm_smmu_device *smmu, int idx)
 * The width of SMR's mask field depends on sCR0_EXIDENABLE, so this function
 * should be called after sCR0 is written.
 */
static void arm_smmu_test_smr_masks(struct arm_smmu_device *smmu, int idx)
static void arm_smmu_test_smr_masks(struct arm_smmu_device *smmu)
{
	unsigned long size;
	void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
	u32 smr;
	u32 smr, id;
	int idx;

	/* Check if Stream Match Register support is included */
	if (!smmu->smrs)
		return;

	/* ID0 */
	id = readl_relaxed(gr0_base + ARM_SMMU_GR0_ID0);
	size = (id >> ID0_NUMSMRG_SHIFT) & ID0_NUMSMRG_MASK;

	/*
	 * Few SMR registers may be inuse before the smmu driver
	 * probes(say by the bootloader). Find a SMR register
	 * which is not inuse.
	 */
	for (idx = 0; idx < size; idx++) {
		smr = readl_relaxed(gr0_base + ARM_SMMU_GR0_SMR(idx));
		if (!(smr & SMR_VALID))
			break;
	}
	if (idx == size) {
		dev_err(smmu->dev,
				"Unable to compute streamid_masks\n");
		return;
	}

	/*
	 * SMR.ID bits may not be preserved if the corresponding MASK
	 * bits are set, so check each one separately. We can reject
@@ -3775,24 +3798,6 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
			return -ENODEV;
		}

		/*
		 * SMR.ID bits may not be preserved if the corresponding MASK
		 * bits are set, so check each one separately. We can reject
		 * masters later if they try to claim IDs outside these masks.
		 */
		for (i = 0; i < size; i++) {
			smr = readl_relaxed(gr0_base + ARM_SMMU_GR0_SMR(i));
			if (!(smr & SMR_VALID))
				break;
		}
		if (i == size) {
			dev_err(smmu->dev,
				"Unable to compute streamid_masks\n");
			return -ENODEV;
		}

		arm_smmu_test_smr_masks(smmu, i);

		/* Zero-initialised to mark as invalid */
		smmu->smrs = devm_kcalloc(smmu->dev, size, sizeof(*smmu->smrs),
					  GFP_KERNEL);
@@ -4202,6 +4207,7 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
	}
	platform_set_drvdata(pdev, smmu);
	arm_smmu_device_reset(smmu);
	arm_smmu_test_smr_masks(smmu);
	arm_smmu_power_off(smmu->pwr);

	/*