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

Commit 3c8766d0 authored by Olav Haugan's avatar Olav Haugan Committed by Will Deacon
Browse files

iommu/arm-smmu: Do not access non-existing S2CR registers



The number of S2CR registers is not properly set when stream
matching is not supported. Fix this and add check that we do not try to
access outside of the number of S2CR regisrers.

Signed-off-by: default avatarOlav Haugan <ohaugan@codeaurora.org>
[will: added missing NUMSIDB_* definitions]
Signed-off-by: default avatarWill Deacon <will.deacon@arm.com>
parent 43b412be
Loading
Loading
Loading
Loading
+21 −7
Original line number Diff line number Diff line
@@ -146,6 +146,8 @@
#define ID0_CTTW			(1 << 14)
#define ID0_NUMIRPT_SHIFT		16
#define ID0_NUMIRPT_MASK		0xff
#define ID0_NUMSIDB_SHIFT		9
#define ID0_NUMSIDB_MASK		0xf
#define ID0_NUMSMRG_SHIFT		0
#define ID0_NUMSMRG_MASK		0xff

@@ -524,9 +526,18 @@ static int register_smmu_master(struct arm_smmu_device *smmu,
	master->of_node			= masterspec->np;
	master->cfg.num_streamids	= masterspec->args_count;

	for (i = 0; i < master->cfg.num_streamids; ++i)
		master->cfg.streamids[i] = masterspec->args[i];
	for (i = 0; i < master->cfg.num_streamids; ++i) {
		u16 streamid = masterspec->args[i];

		if (!(smmu->features & ARM_SMMU_FEAT_STREAM_MATCH) &&
		     (streamid >= smmu->num_mapping_groups)) {
			dev_err(dev,
				"stream ID for master device %s greater than maximum allowed (%d)\n",
				masterspec->np->name, smmu->num_mapping_groups);
			return -ERANGE;
		}
		master->cfg.streamids[i] = streamid;
	}
	return insert_smmu_master(smmu, master);
}

@@ -1624,7 +1635,7 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu)

	/* Mark all SMRn as invalid and all S2CRn as bypass */
	for (i = 0; i < smmu->num_mapping_groups; ++i) {
		writel_relaxed(~SMR_VALID, gr0_base + ARM_SMMU_GR0_SMR(i));
		writel_relaxed(0, gr0_base + ARM_SMMU_GR0_SMR(i));
		writel_relaxed(S2CR_TYPE_BYPASS,
			gr0_base + ARM_SMMU_GR0_S2CR(i));
	}
@@ -1759,6 +1770,9 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
		dev_notice(smmu->dev,
			   "\tstream matching with %u register groups, mask 0x%x",
			   smmu->num_mapping_groups, mask);
	} else {
		smmu->num_mapping_groups = (id >> ID0_NUMSIDB_SHIFT) &
					   ID0_NUMSIDB_MASK;
	}

	/* ID1 */
@@ -1887,6 +1901,10 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
		smmu->irqs[i] = irq;
	}

	err = arm_smmu_device_cfg_probe(smmu);
	if (err)
		return err;

	i = 0;
	smmu->masters = RB_ROOT;
	while (!of_parse_phandle_with_args(dev->of_node, "mmu-masters",
@@ -1903,10 +1921,6 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
	}
	dev_notice(dev, "registered %d master devices\n", i);

	err = arm_smmu_device_cfg_probe(smmu);
	if (err)
		goto out_put_masters;

	parse_driver_options(smmu);

	if (smmu->version > 1 &&