History

iommu/vt-d: Gracefully handle DMAR units with no supported address widths

Instead of bailing out completely, such a unit can still be used for interrupt remapping.

David Woodhouse committed 6 years ago

Commit c40aaaa1 parent d2ef0961 file · +31 −15Browse files

Unified · Split

drivers/iommu/intel/dmar.c+31−15
@@ -1024,8 +1024,8 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd) · 1023 unmodified lines
10241024 {
10251025 struct intel_iommu *iommu;
10261026 u32 ver, sts;
1027− int agaw = 0;
1028− int msagaw = 0;
1027+ int agaw = -1;
1028+ int msagaw = -1;
10291029 int err;
10301030
10311031 if (!drhd->reg_base_addr) {
@@ -1050,17 +1050,28 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd) · 18 unmodified lines
10501050 }
10511051
10521052 err = -EINVAL;
1053− agaw = iommu_calculate_agaw(iommu);
1054− if (agaw < 0) {
1055− pr_err("Cannot get a valid agaw for iommu (seq_id = %d)\n",
1056− iommu->seq_id);
1057− goto err_unmap;
1058− }
1059− msagaw = iommu_calculate_max_sagaw(iommu);
1060− if (msagaw < 0) {
1061− pr_err("Cannot get a valid max agaw for iommu (seq_id = %d)\n",
1062− iommu->seq_id);
1063− goto err_unmap;
1053+ if (cap_sagaw(iommu->cap) == 0) {
1054+ pr_info("%s: No supported address widths. Not attempting DMA translation.\n",
1055+ iommu->name);
1056+ drhd->ignored = 1;
1057+ }
1058+
1059+ if (!drhd->ignored) {
1060+ agaw = iommu_calculate_agaw(iommu);
1061+ if (agaw < 0) {
1062+ pr_err("Cannot get a valid agaw for iommu (seq_id = %d)\n",
1063+ iommu->seq_id);
1064+ drhd->ignored = 1;
1065+ }
1066+ }
1067+ if (!drhd->ignored) {
1068+ msagaw = iommu_calculate_max_sagaw(iommu);
1069+ if (msagaw < 0) {
1070+ pr_err("Cannot get a valid max agaw for iommu (seq_id = %d)\n",
1071+ iommu->seq_id);
1072+ drhd->ignored = 1;
1073+ agaw = -1;
1074+ }
10641075 }
10651076 iommu->agaw = agaw;
10661077 iommu->msagaw = msagaw;
@@ -1087,7 +1098,12 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd) · 20 unmodified lines
10871098
10881099 raw_spin_lock_init(&iommu->register_lock);
10891100
1090− if (intel_iommu_enabled) {
1101+ /*
1102+ * This is only for hotplug; at boot time intel_iommu_enabled won't
1103+ * be set yet. When intel_iommu_init() runs, it registers the units
1104+ * present at boot time, then sets intel_iommu_enabled.
1105+ */
1106+ if (intel_iommu_enabled && !drhd->ignored) {
10911107 err = iommu_device_sysfs_add(&iommu->iommu, NULL,
10921108 intel_iommu_groups,
10931109 "%s", iommu->name);
@@ -1117,7 +1133,7 @@ error: · 23 unmodified lines
11171133
11181134 static void free_iommu(struct intel_iommu *iommu)
11191135 {
1120− if (intel_iommu_enabled) {
1136+ if (intel_iommu_enabled && iommu->iommu.ops) {
11211137 iommu_device_unregister(&iommu->iommu);
11221138 iommu_device_sysfs_remove(&iommu->iommu);
11231139 }