Skip to content

Commit c40aaaa

Browse files
dwmw2joergroedel
authored andcommitted
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. Signed-off-by: David Woodhouse <[email protected]> Reviewed-by: Lu Baolu <[email protected]> Link: https://lore.kernel.org/linux-iommu/[email protected]/ Signed-off-by: Joerg Roedel <[email protected]>
1 parent d2ef096 commit c40aaaa

1 file changed

Lines changed: 31 additions & 15 deletions

File tree

drivers/iommu/intel/dmar.c

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,8 +1024,8 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd)
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)
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)
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 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd)
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
}

0 commit comments

Comments
 (0)