diff options
Diffstat (limited to 'drivers/iommu')
-rw-r--r-- | drivers/iommu/dmar.c | 43 | ||||
-rw-r--r-- | drivers/iommu/intel_irq_remapping.c | 2 |
2 files changed, 29 insertions, 16 deletions
diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index 00169c9eb3ee..54f27dd9f156 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -1012,8 +1012,8 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd) { struct intel_iommu *iommu; u32 ver, sts; - int agaw = 0; - int msagaw = 0; + int agaw = -1; + int msagaw = -1; int err; if (!drhd->reg_base_addr) { @@ -1038,17 +1038,28 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd) } err = -EINVAL; - agaw = iommu_calculate_agaw(iommu); - if (agaw < 0) { - pr_err("Cannot get a valid agaw for iommu (seq_id = %d)\n", - iommu->seq_id); - goto err_unmap; + if (cap_sagaw(iommu->cap) == 0) { + pr_info("%s: No supported address widths. Not attempting DMA translation.\n", + iommu->name); + drhd->ignored = 1; } - msagaw = iommu_calculate_max_sagaw(iommu); - if (msagaw < 0) { - pr_err("Cannot get a valid max agaw for iommu (seq_id = %d)\n", - iommu->seq_id); - goto err_unmap; + + if (!drhd->ignored) { + agaw = iommu_calculate_agaw(iommu); + if (agaw < 0) { + pr_err("Cannot get a valid agaw for iommu (seq_id = %d)\n", + iommu->seq_id); + drhd->ignored = 1; + } + } + if (!drhd->ignored) { + msagaw = iommu_calculate_max_sagaw(iommu); + if (msagaw < 0) { + pr_err("Cannot get a valid max agaw for iommu (seq_id = %d)\n", + iommu->seq_id); + drhd->ignored = 1; + agaw = -1; + } } iommu->agaw = agaw; iommu->msagaw = msagaw; @@ -1076,16 +1087,15 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd) raw_spin_lock_init(&iommu->register_lock); drhd->iommu = iommu; + iommu->drhd = drhd; - if (intel_iommu_enabled) + if (intel_iommu_enabled && !drhd->ignored) iommu->iommu_dev = iommu_device_create(NULL, iommu, intel_iommu_groups, "%s", iommu->name); return 0; -err_unmap: - unmap_iommu(iommu); error_free_seq_id: dmar_free_seq_id(iommu); error: @@ -1095,7 +1105,8 @@ error: static void free_iommu(struct intel_iommu *iommu) { - iommu_device_destroy(iommu->iommu_dev); + if (intel_iommu_enabled && !iommu->drhd->ignored) + iommu_device_destroy(iommu->iommu_dev); if (iommu->irq) { if (iommu->pr_irq) { diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c index ce125ec23d2a..88ba1a65c283 100644 --- a/drivers/iommu/intel_irq_remapping.c +++ b/drivers/iommu/intel_irq_remapping.c @@ -1350,6 +1350,8 @@ static int intel_irq_remapping_alloc(struct irq_domain *domain, irq_data = irq_domain_get_irq_data(domain, virq + i); irq_cfg = irqd_cfg(irq_data); if (!irq_data || !irq_cfg) { + if (!i) + kfree(data); ret = -EINVAL; goto out_free_data; } |