提交 3c8766d0 编写于 作者: O Olav Haugan 提交者: Will Deacon

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: NOlav Haugan <ohaugan@codeaurora.org>
[will: added missing NUMSIDB_* definitions]
Signed-off-by: NWill Deacon <will.deacon@arm.com>
上级 43b412be
...@@ -146,6 +146,8 @@ ...@@ -146,6 +146,8 @@
#define ID0_CTTW (1 << 14) #define ID0_CTTW (1 << 14)
#define ID0_NUMIRPT_SHIFT 16 #define ID0_NUMIRPT_SHIFT 16
#define ID0_NUMIRPT_MASK 0xff #define ID0_NUMIRPT_MASK 0xff
#define ID0_NUMSIDB_SHIFT 9
#define ID0_NUMSIDB_MASK 0xf
#define ID0_NUMSMRG_SHIFT 0 #define ID0_NUMSMRG_SHIFT 0
#define ID0_NUMSMRG_MASK 0xff #define ID0_NUMSMRG_MASK 0xff
...@@ -524,9 +526,18 @@ static int register_smmu_master(struct arm_smmu_device *smmu, ...@@ -524,9 +526,18 @@ static int register_smmu_master(struct arm_smmu_device *smmu,
master->of_node = masterspec->np; master->of_node = masterspec->np;
master->cfg.num_streamids = masterspec->args_count; master->cfg.num_streamids = masterspec->args_count;
for (i = 0; i < master->cfg.num_streamids; ++i) for (i = 0; i < master->cfg.num_streamids; ++i) {
master->cfg.streamids[i] = masterspec->args[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); return insert_smmu_master(smmu, master);
} }
...@@ -1624,7 +1635,7 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu) ...@@ -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 */ /* Mark all SMRn as invalid and all S2CRn as bypass */
for (i = 0; i < smmu->num_mapping_groups; ++i) { 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, writel_relaxed(S2CR_TYPE_BYPASS,
gr0_base + ARM_SMMU_GR0_S2CR(i)); gr0_base + ARM_SMMU_GR0_S2CR(i));
} }
...@@ -1759,6 +1770,9 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu) ...@@ -1759,6 +1770,9 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
dev_notice(smmu->dev, dev_notice(smmu->dev,
"\tstream matching with %u register groups, mask 0x%x", "\tstream matching with %u register groups, mask 0x%x",
smmu->num_mapping_groups, mask); smmu->num_mapping_groups, mask);
} else {
smmu->num_mapping_groups = (id >> ID0_NUMSIDB_SHIFT) &
ID0_NUMSIDB_MASK;
} }
/* ID1 */ /* ID1 */
...@@ -1887,6 +1901,10 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev) ...@@ -1887,6 +1901,10 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
smmu->irqs[i] = irq; smmu->irqs[i] = irq;
} }
err = arm_smmu_device_cfg_probe(smmu);
if (err)
return err;
i = 0; i = 0;
smmu->masters = RB_ROOT; smmu->masters = RB_ROOT;
while (!of_parse_phandle_with_args(dev->of_node, "mmu-masters", 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) ...@@ -1903,10 +1921,6 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
} }
dev_notice(dev, "registered %d master devices\n", i); 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); parse_driver_options(smmu);
if (smmu->version > 1 && if (smmu->version > 1 &&
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册