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: Joerg Roedel <joro@8bytes.org> Acked-by: Will Deacon <will.deacon@arm.com>
This commit is contained in:
		
					parent
					
						
							
								15eeb2e925
							
						
					
				
			
			
				commit
				
					
						972157cac5
					
				
			
		
					 1 changed files with 7 additions and 5 deletions
				
			
		| 
						 | 
				
			
			@ -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_device *device_smmu = dev->archdata.iommu;
 | 
			
		||||
	struct arm_smmu_master *master;
 | 
			
		||||
	unsigned long flags;
 | 
			
		||||
 | 
			
		||||
	if (!device_smmu) {
 | 
			
		||||
		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)
 | 
			
		|||
	 * Sanity check the domain. We don't currently support domains
 | 
			
		||||
	 * that cross between different SMMU chains.
 | 
			
		||||
	 */
 | 
			
		||||
	spin_lock(&smmu_domain->lock);
 | 
			
		||||
	spin_lock_irqsave(&smmu_domain->lock, flags);
 | 
			
		||||
	if (!smmu_domain->leaf_smmu) {
 | 
			
		||||
		/* Now that we have a master, we can finalise the domain */
 | 
			
		||||
		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)
 | 
			
		|||
			dev_name(device_smmu->dev));
 | 
			
		||||
		goto err_unlock;
 | 
			
		||||
	}
 | 
			
		||||
	spin_unlock(&smmu_domain->lock);
 | 
			
		||||
	spin_unlock_irqrestore(&smmu_domain->lock, flags);
 | 
			
		||||
 | 
			
		||||
	/* Looks ok, so add the device to the domain */
 | 
			
		||||
	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)
 | 
			
		|||
	return arm_smmu_domain_add_master(smmu_domain, master);
 | 
			
		||||
 | 
			
		||||
err_unlock:
 | 
			
		||||
	spin_unlock(&smmu_domain->lock);
 | 
			
		||||
	spin_unlock_irqrestore(&smmu_domain->lock, flags);
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
	pgd_t *pgd = root_cfg->pgd;
 | 
			
		||||
	struct arm_smmu_device *smmu = root_cfg->smmu;
 | 
			
		||||
	unsigned long irqflags;
 | 
			
		||||
 | 
			
		||||
	if (root_cfg->cbar == CBAR_TYPE_S2_TRANS) {
 | 
			
		||||
		stage = 2;
 | 
			
		||||
| 
						 | 
				
			
			@ -1418,7 +1420,7 @@ static int arm_smmu_handle_mapping(struct arm_smmu_domain *smmu_domain,
 | 
			
		|||
	if (paddr & ~output_mask)
 | 
			
		||||
		return -ERANGE;
 | 
			
		||||
 | 
			
		||||
	spin_lock(&smmu_domain->lock);
 | 
			
		||||
	spin_lock_irqsave(&smmu_domain->lock, irqflags);
 | 
			
		||||
	pgd += pgd_index(iova);
 | 
			
		||||
	end = iova + size;
 | 
			
		||||
	do {
 | 
			
		||||
| 
						 | 
				
			
			@ -1434,7 +1436,7 @@ static int arm_smmu_handle_mapping(struct arm_smmu_domain *smmu_domain,
 | 
			
		|||
	} while (pgd++, iova != end);
 | 
			
		||||
 | 
			
		||||
out_unlock:
 | 
			
		||||
	spin_unlock(&smmu_domain->lock);
 | 
			
		||||
	spin_unlock_irqrestore(&smmu_domain->lock, irqflags);
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue