Commit 972157ca authored by Joerg Roedel's avatar Joerg Roedel

arm/smmu: Use irqsafe spinlock for domain lock

As the lock might be used through DMA-API which is allowed
in interrupt context.
Signed-off-by: default avatarJoerg Roedel <joro@8bytes.org>
Acked-by: default avatarWill Deacon <will.deacon@arm.com>
parent 15eeb2e9
...@@ -1159,6 +1159,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) ...@@ -1159,6 +1159,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
struct arm_smmu_domain *smmu_domain = domain->priv; struct arm_smmu_domain *smmu_domain = domain->priv;
struct arm_smmu_device *device_smmu = dev->archdata.iommu; struct arm_smmu_device *device_smmu = dev->archdata.iommu;
struct arm_smmu_master *master; struct arm_smmu_master *master;
unsigned long flags;
if (!device_smmu) { if (!device_smmu) {
dev_err(dev, "cannot attach to SMMU, is it on the same bus?\n"); dev_err(dev, "cannot attach to SMMU, is it on the same bus?\n");
...@@ -1169,7 +1170,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) ...@@ -1169,7 +1170,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
* Sanity check the domain. We don't currently support domains * Sanity check the domain. We don't currently support domains
* that cross between different SMMU chains. * that cross between different SMMU chains.
*/ */
spin_lock(&smmu_domain->lock); spin_lock_irqsave(&smmu_domain->lock, flags);
if (!smmu_domain->leaf_smmu) { if (!smmu_domain->leaf_smmu) {
/* Now that we have a master, we can finalise the domain */ /* Now that we have a master, we can finalise the domain */
ret = arm_smmu_init_domain_context(domain, dev); ret = arm_smmu_init_domain_context(domain, dev);
...@@ -1184,7 +1185,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) ...@@ -1184,7 +1185,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
dev_name(device_smmu->dev)); dev_name(device_smmu->dev));
goto err_unlock; goto err_unlock;
} }
spin_unlock(&smmu_domain->lock); spin_unlock_irqrestore(&smmu_domain->lock, flags);
/* Looks ok, so add the device to the domain */ /* Looks ok, so add the device to the domain */
master = find_smmu_master(smmu_domain->leaf_smmu, dev->of_node); master = find_smmu_master(smmu_domain->leaf_smmu, dev->of_node);
...@@ -1194,7 +1195,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) ...@@ -1194,7 +1195,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
return arm_smmu_domain_add_master(smmu_domain, master); return arm_smmu_domain_add_master(smmu_domain, master);
err_unlock: err_unlock:
spin_unlock(&smmu_domain->lock); spin_unlock_irqrestore(&smmu_domain->lock, flags);
return ret; return ret;
} }
...@@ -1396,6 +1397,7 @@ static int arm_smmu_handle_mapping(struct arm_smmu_domain *smmu_domain, ...@@ -1396,6 +1397,7 @@ static int arm_smmu_handle_mapping(struct arm_smmu_domain *smmu_domain,
struct arm_smmu_cfg *root_cfg = &smmu_domain->root_cfg; struct arm_smmu_cfg *root_cfg = &smmu_domain->root_cfg;
pgd_t *pgd = root_cfg->pgd; pgd_t *pgd = root_cfg->pgd;
struct arm_smmu_device *smmu = root_cfg->smmu; struct arm_smmu_device *smmu = root_cfg->smmu;
unsigned long irqflags;
if (root_cfg->cbar == CBAR_TYPE_S2_TRANS) { if (root_cfg->cbar == CBAR_TYPE_S2_TRANS) {
stage = 2; stage = 2;
...@@ -1418,7 +1420,7 @@ static int arm_smmu_handle_mapping(struct arm_smmu_domain *smmu_domain, ...@@ -1418,7 +1420,7 @@ static int arm_smmu_handle_mapping(struct arm_smmu_domain *smmu_domain,
if (paddr & ~output_mask) if (paddr & ~output_mask)
return -ERANGE; return -ERANGE;
spin_lock(&smmu_domain->lock); spin_lock_irqsave(&smmu_domain->lock, irqflags);
pgd += pgd_index(iova); pgd += pgd_index(iova);
end = iova + size; end = iova + size;
do { do {
...@@ -1434,7 +1436,7 @@ static int arm_smmu_handle_mapping(struct arm_smmu_domain *smmu_domain, ...@@ -1434,7 +1436,7 @@ static int arm_smmu_handle_mapping(struct arm_smmu_domain *smmu_domain,
} while (pgd++, iova != end); } while (pgd++, iova != end);
out_unlock: out_unlock:
spin_unlock(&smmu_domain->lock); spin_unlock_irqrestore(&smmu_domain->lock, irqflags);
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment