Merge "iommu/arm-smmu: avoid calling request_irq in atomic context"

This commit is contained in:
Linux Build Service Account 2014-08-14 14:23:42 -07:00 committed by Gerrit - the friendly Code Review server
commit 100eafb275

View file

@ -868,10 +868,15 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain)
static int arm_smmu_init_domain_context(struct iommu_domain *domain,
struct arm_smmu_device *smmu)
{
int irq, ret, start;
int irq, start, ret = 0;
unsigned long flags;
struct arm_smmu_domain *smmu_domain = domain->priv;
struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
spin_lock_irqsave(&smmu_domain->lock, flags);
if (smmu_domain->smmu)
goto out_unlock;
if (smmu->features & ARM_SMMU_FEAT_TRANS_NESTED) {
/*
* We will likely want to change this if/when KVM gets
@ -890,7 +895,7 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
ret = __arm_smmu_alloc_bitmap(smmu->context_map, start,
smmu->num_context_banks);
if (IS_ERR_VALUE(ret))
return ret;
goto out_unlock;
cfg->cbndx = ret;
if (smmu->version == 1) {
@ -900,6 +905,10 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
cfg->irptndx = cfg->cbndx;
}
ACCESS_ONCE(smmu_domain->smmu) = smmu;
arm_smmu_init_context_bank(smmu_domain);
spin_unlock_irqrestore(&smmu_domain->lock, flags);
irq = smmu->irqs[smmu->num_global_irqs + cfg->irptndx];
ret = request_irq(irq, arm_smmu_context_fault, IRQF_SHARED,
"arm-smmu-context-fault", domain);
@ -907,15 +916,12 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
dev_err(smmu->dev, "failed to request context IRQ %d (%u)\n",
cfg->irptndx, irq);
cfg->irptndx = INVALID_IRPTNDX;
goto out_free_context;
}
smmu_domain->smmu = smmu;
arm_smmu_init_context_bank(smmu_domain);
return 0;
out_free_context:
__arm_smmu_free_bitmap(smmu->context_map, cfg->cbndx);
out_unlock:
spin_unlock_irqrestore(&smmu_domain->lock, flags);
return ret;
}
@ -1172,11 +1178,10 @@ static void arm_smmu_domain_remove_master(struct arm_smmu_domain *smmu_domain,
static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
{
int ret = -EINVAL;
int ret;
struct arm_smmu_domain *smmu_domain = domain->priv;
struct arm_smmu_device *smmu;
struct arm_smmu_device *smmu, *dom_smmu;
struct arm_smmu_master_cfg *cfg;
unsigned long flags;
smmu = dev_get_master_dev(dev)->archdata.iommu;
if (!smmu) {
@ -1188,20 +1193,22 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
* Sanity check the domain. We don't support domains across
* different SMMUs.
*/
spin_lock_irqsave(&smmu_domain->lock, flags);
if (!smmu_domain->smmu) {
dom_smmu = ACCESS_ONCE(smmu_domain->smmu);
if (!dom_smmu) {
/* Now that we have a master, we can finalise the domain */
ret = arm_smmu_init_domain_context(domain, smmu);
if (IS_ERR_VALUE(ret))
goto err_unlock;
} else if (smmu_domain->smmu != smmu) {
return ret;
dom_smmu = smmu_domain->smmu;
}
if (dom_smmu != smmu) {
dev_err(dev,
"cannot attach to SMMU %s whilst already attached to domain on SMMU %s\n",
dev_name(smmu_domain->smmu->dev),
dev_name(smmu->dev));
goto err_unlock;
dev_name(smmu_domain->smmu->dev), dev_name(smmu->dev));
return -EINVAL;
}
spin_unlock_irqrestore(&smmu_domain->lock, flags);
/* Looks ok, so add the device to the domain */
cfg = find_smmu_master_cfg(smmu_domain->smmu, dev);
@ -1209,10 +1216,6 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
return -ENODEV;
return arm_smmu_domain_add_master(smmu_domain, cfg);
err_unlock:
spin_unlock_irqrestore(&smmu_domain->lock, flags);
return ret;
}
static void arm_smmu_detach_dev(struct iommu_domain *domain, struct device *dev)