diff options
author | Joerg Roedel <joro@8bytes.org> | 2013-04-09 10:35:28 -0400 |
---|---|---|
committer | Joerg Roedel <joro@8bytes.org> | 2013-04-19 14:52:17 -0400 |
commit | 440e899805411d827d4fcce9eb37bf2417c812db (patch) | |
tree | 0316e0431180fd838a4ad02b22873a1ca2c0c452 /drivers/iommu | |
parent | 235dacbc795bb7ccf69db8ad9ff1587314cf857d (diff) |
iommu/amd: Add ioapic and hpet ivrs override
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>
Diffstat (limited to 'drivers/iommu')
-rw-r--r-- | drivers/iommu/amd_iommu_init.c | 64 |
1 files changed, 62 insertions, 2 deletions
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index 2a3b1b174d5e..030d6abf31e7 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c | |||
@@ -2145,8 +2145,68 @@ static int __init parse_amd_iommu_options(char *str) | |||
2145 | return 1; | 2145 | return 1; |
2146 | } | 2146 | } |
2147 | 2147 | ||
2148 | __setup("amd_iommu_dump", parse_amd_iommu_dump); | 2148 | static int __init parse_ivrs_ioapic(char *str) |
2149 | __setup("amd_iommu=", parse_amd_iommu_options); | 2149 | { |
2150 | unsigned int bus, dev, fn; | ||
2151 | int ret, id, i; | ||
2152 | u16 devid; | ||
2153 | |||
2154 | ret = sscanf(str, "[%d]=%x:%x.%x", &id, &bus, &dev, &fn); | ||
2155 | |||
2156 | if (ret != 4) { | ||
2157 | pr_err("AMD-Vi: Invalid command line: ivrs_ioapic%s\n", str); | ||
2158 | return 1; | ||
2159 | } | ||
2160 | |||
2161 | if (early_ioapic_map_size == EARLY_MAP_SIZE) { | ||
2162 | pr_err("AMD-Vi: Early IOAPIC map overflow - ignoring ivrs_ioapic%s\n", | ||
2163 | str); | ||
2164 | return 1; | ||
2165 | } | ||
2166 | |||
2167 | devid = ((bus & 0xff) << 8) | ((dev & 0x1f) << 3) | (fn & 0x7); | ||
2168 | |||
2169 | i = early_ioapic_map_size++; | ||
2170 | early_ioapic_map[i].id = id; | ||
2171 | early_ioapic_map[i].devid = devid; | ||
2172 | early_ioapic_map[i].cmd_line = true; | ||
2173 | |||
2174 | return 1; | ||
2175 | } | ||
2176 | |||
2177 | static int __init parse_ivrs_hpet(char *str) | ||
2178 | { | ||
2179 | unsigned int bus, dev, fn; | ||
2180 | int ret, id, i; | ||
2181 | u16 devid; | ||
2182 | |||
2183 | ret = sscanf(str, "[%d]=%x:%x.%x", &id, &bus, &dev, &fn); | ||
2184 | |||
2185 | if (ret != 4) { | ||
2186 | pr_err("AMD-Vi: Invalid command line: ivrs_hpet%s\n", str); | ||
2187 | return 1; | ||
2188 | } | ||
2189 | |||
2190 | if (early_hpet_map_size == EARLY_MAP_SIZE) { | ||
2191 | pr_err("AMD-Vi: Early HPET map overflow - ignoring ivrs_hpet%s\n", | ||
2192 | str); | ||
2193 | return 1; | ||
2194 | } | ||
2195 | |||
2196 | devid = ((bus & 0xff) << 8) | ((dev & 0x1f) << 3) | (fn & 0x7); | ||
2197 | |||
2198 | i = early_hpet_map_size++; | ||
2199 | early_hpet_map[i].id = id; | ||
2200 | early_hpet_map[i].devid = devid; | ||
2201 | early_hpet_map[i].cmd_line = true; | ||
2202 | |||
2203 | return 1; | ||
2204 | } | ||
2205 | |||
2206 | __setup("amd_iommu_dump", parse_amd_iommu_dump); | ||
2207 | __setup("amd_iommu=", parse_amd_iommu_options); | ||
2208 | __setup("ivrs_ioapic", parse_ivrs_ioapic); | ||
2209 | __setup("ivrs_hpet", parse_ivrs_hpet); | ||
2150 | 2210 | ||
2151 | IOMMU_INIT_FINISH(amd_iommu_detect, | 2211 | IOMMU_INIT_FINISH(amd_iommu_detect, |
2152 | gart_iommu_hole_init, | 2212 | gart_iommu_hole_init, |