mirror of
https://github.com/team-infusion-developers/android_kernel_samsung_msm8976.git
synced 2024-09-21 03:43:03 +00:00
Merge "iommu/arm-smmu: avoid calling request_irq in atomic context"
This commit is contained in:
commit
100eafb275
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue