]> Pileus Git - ~andy/linux/commitdiff
iommu/amd: Add ioapic and hpet ivrs override
authorJoerg Roedel <joro@8bytes.org>
Tue, 9 Apr 2013 14:35:28 +0000 (16:35 +0200)
committerJoerg Roedel <joro@8bytes.org>
Fri, 19 Apr 2013 18:52:17 +0000 (20:52 +0200)
Add two new kernel commandline parameters ivrs_ioapic and
ivrs_hpet to override the Id->DeviceId mapping from the IVRS
ACPI table. This can be used to work around broken BIOSes to
get interrupt remapping working on AMD systems.

Tested-by: Borislav Petkov <bp@suse.de>
Tested-by: Suravee Suthikulanit <suravee.suthikulpanit@amd.com>
Reviewed-by: Shuah Khan <shuahkhan@gmail.com>
Signed-off-by: Joerg Roedel <joro@8bytes.org>
drivers/iommu/amd_iommu_init.c

index 2a3b1b174d5e669470ff3d493113dedb6fca241b..030d6abf31e7c0cb6de80fecd304a9bfa3185323 100644 (file)
@@ -2145,8 +2145,68 @@ static int __init parse_amd_iommu_options(char *str)
        return 1;
 }
 
-__setup("amd_iommu_dump", parse_amd_iommu_dump);
-__setup("amd_iommu=", parse_amd_iommu_options);
+static int __init parse_ivrs_ioapic(char *str)
+{
+       unsigned int bus, dev, fn;
+       int ret, id, i;
+       u16 devid;
+
+       ret = sscanf(str, "[%d]=%x:%x.%x", &id, &bus, &dev, &fn);
+
+       if (ret != 4) {
+               pr_err("AMD-Vi: Invalid command line: ivrs_ioapic%s\n", str);
+               return 1;
+       }
+
+       if (early_ioapic_map_size == EARLY_MAP_SIZE) {
+               pr_err("AMD-Vi: Early IOAPIC map overflow - ignoring ivrs_ioapic%s\n",
+                       str);
+               return 1;
+       }
+
+       devid = ((bus & 0xff) << 8) | ((dev & 0x1f) << 3) | (fn & 0x7);
+
+       i                               = early_ioapic_map_size++;
+       early_ioapic_map[i].id          = id;
+       early_ioapic_map[i].devid       = devid;
+       early_ioapic_map[i].cmd_line    = true;
+
+       return 1;
+}
+
+static int __init parse_ivrs_hpet(char *str)
+{
+       unsigned int bus, dev, fn;
+       int ret, id, i;
+       u16 devid;
+
+       ret = sscanf(str, "[%d]=%x:%x.%x", &id, &bus, &dev, &fn);
+
+       if (ret != 4) {
+               pr_err("AMD-Vi: Invalid command line: ivrs_hpet%s\n", str);
+               return 1;
+       }
+
+       if (early_hpet_map_size == EARLY_MAP_SIZE) {
+               pr_err("AMD-Vi: Early HPET map overflow - ignoring ivrs_hpet%s\n",
+                       str);
+               return 1;
+       }
+
+       devid = ((bus & 0xff) << 8) | ((dev & 0x1f) << 3) | (fn & 0x7);
+
+       i                               = early_hpet_map_size++;
+       early_hpet_map[i].id            = id;
+       early_hpet_map[i].devid         = devid;
+       early_hpet_map[i].cmd_line      = true;
+
+       return 1;
+}
+
+__setup("amd_iommu_dump",      parse_amd_iommu_dump);
+__setup("amd_iommu=",          parse_amd_iommu_options);
+__setup("ivrs_ioapic",         parse_ivrs_ioapic);
+__setup("ivrs_hpet",           parse_ivrs_hpet);
 
 IOMMU_INIT_FINISH(amd_iommu_detect,
                  gart_iommu_hole_init,