summaryrefslogtreecommitdiffstats
path: root/drivers/iommu/amd_iommu_init.c
diff options
context:
space:
mode:
authorAdrian Huang <adrianhuang0701@gmail.com>2019-11-14 07:14:47 +0100
committerJoerg Roedel <jroedel@suse.de>2019-12-23 14:06:15 +0100
commit387caf0b759ac437a65ad5d59665558025f350fc (patch)
tree76ee0055b568b51eceb4033f5d913827c090d7ae /drivers/iommu/amd_iommu_init.c
parentLinux 5.5-rc3 (diff)
downloadlinux-387caf0b759ac437a65ad5d59665558025f350fc.tar.xz
linux-387caf0b759ac437a65ad5d59665558025f350fc.zip
iommu/amd: Treat per-device exclusion ranges as r/w unity-mapped regions
Some buggy BIOSes might define multiple exclusion ranges of the IVMD entries which are associated with the same IOMMU hardware. This leads to the overwritten exclusion range (exclusion_start and exclusion_length members) in set_device_exclusion_range(). Here is a real case: When attaching two Broadcom RAID controllers to a server, the first one reports the failure during booting (the disks connecting to the RAID controller cannot be detected). This patch prevents the issue by treating per-device exclusion ranges as r/w unity-mapped regions. Discussion: * https://lists.linuxfoundation.org/pipermail/iommu/2019-November/040140.html Suggested-by: Joerg Roedel <joro@8bytes.org> Signed-off-by: Adrian Huang <ahuang12@lenovo.com> Signed-off-by: Joerg Roedel <jroedel@suse.de>
Diffstat (limited to 'drivers/iommu/amd_iommu_init.c')
-rw-r--r--drivers/iommu/amd_iommu_init.c20
1 files changed, 10 insertions, 10 deletions
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index 568c52317757..1b65302e07b1 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -71,6 +71,8 @@
#define IVHD_FLAG_ISOC_EN_MASK 0x08
#define IVMD_FLAG_EXCL_RANGE 0x08
+#define IVMD_FLAG_IW 0x04
+#define IVMD_FLAG_IR 0x02
#define IVMD_FLAG_UNITY_MAP 0x01
#define ACPI_DEVFLAG_INITPASS 0x01
@@ -1121,16 +1123,14 @@ static void __init set_device_exclusion_range(u16 devid, struct ivmd_header *m)
if (!(m->flags & IVMD_FLAG_EXCL_RANGE))
return;
- if (iommu) {
- /*
- * We only can configure exclusion ranges per IOMMU, not
- * per device. But we can enable the exclusion range per
- * device. This is done here
- */
- set_dev_entry_bit(devid, DEV_ENTRY_EX);
- iommu->exclusion_start = m->range_start;
- iommu->exclusion_length = m->range_length;
- }
+ /*
+ * Treat per-device exclusion ranges as r/w unity-mapped regions
+ * since some buggy BIOSes might lead to the overwritten exclusion
+ * range (exclusion_start and exclusion_length members). This
+ * happens when there are multiple exclusion ranges (IVMD entries)
+ * defined in ACPI table.
+ */
+ m->flags = (IVMD_FLAG_IW | IVMD_FLAG_IR | IVMD_FLAG_UNITY_MAP);
}
/*