forked from Minki/linux
iommu/arm-smmu: fix s2cr and smr teardown on device detach from domain
When we attach a device to a domain, we configure the SMRs (if we have any) to match the Stream IDs for the corresponding SMMU master and program the s2crs accordingly. However, on detach we tear down the s2crs assuming stream-indexing (as opposed to stream-matching) and SMRs assuming they are present. This patch fixes the device detach code so that it operates as a converse of the attach code. Cc: <stable@vger.kernel.org> Signed-off-by: Will Deacon <will.deacon@arm.com>
This commit is contained in:
parent
93b14135cf
commit
43b412bedb
@ -1116,6 +1116,9 @@ static void arm_smmu_master_free_smrs(struct arm_smmu_device *smmu,
|
||||
void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
|
||||
struct arm_smmu_smr *smrs = cfg->smrs;
|
||||
|
||||
if (!smrs)
|
||||
return;
|
||||
|
||||
/* Invalidate the SMRs before freeing back to the allocator */
|
||||
for (i = 0; i < cfg->num_streamids; ++i) {
|
||||
u8 idx = smrs[i].idx;
|
||||
@ -1128,20 +1131,6 @@ static void arm_smmu_master_free_smrs(struct arm_smmu_device *smmu,
|
||||
kfree(smrs);
|
||||
}
|
||||
|
||||
static void arm_smmu_bypass_stream_mapping(struct arm_smmu_device *smmu,
|
||||
struct arm_smmu_master_cfg *cfg)
|
||||
{
|
||||
int i;
|
||||
void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
|
||||
|
||||
for (i = 0; i < cfg->num_streamids; ++i) {
|
||||
u16 sid = cfg->streamids[i];
|
||||
|
||||
writel_relaxed(S2CR_TYPE_BYPASS,
|
||||
gr0_base + ARM_SMMU_GR0_S2CR(sid));
|
||||
}
|
||||
}
|
||||
|
||||
static int arm_smmu_domain_add_master(struct arm_smmu_domain *smmu_domain,
|
||||
struct arm_smmu_master_cfg *cfg)
|
||||
{
|
||||
@ -1168,13 +1157,21 @@ static int arm_smmu_domain_add_master(struct arm_smmu_domain *smmu_domain,
|
||||
static void arm_smmu_domain_remove_master(struct arm_smmu_domain *smmu_domain,
|
||||
struct arm_smmu_master_cfg *cfg)
|
||||
{
|
||||
int i;
|
||||
struct arm_smmu_device *smmu = smmu_domain->smmu;
|
||||
void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
|
||||
|
||||
/*
|
||||
* We *must* clear the S2CR first, because freeing the SMR means
|
||||
* that it can be re-allocated immediately.
|
||||
*/
|
||||
arm_smmu_bypass_stream_mapping(smmu, cfg);
|
||||
for (i = 0; i < cfg->num_streamids; ++i) {
|
||||
u32 idx = cfg->smrs ? cfg->smrs[i].idx : cfg->streamids[i];
|
||||
|
||||
writel_relaxed(S2CR_TYPE_BYPASS,
|
||||
gr0_base + ARM_SMMU_GR0_S2CR(idx));
|
||||
}
|
||||
|
||||
arm_smmu_master_free_smrs(smmu, cfg);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user