diff options
Diffstat (limited to 'arch/x86/kernel/amd_iommu_init.c')
| -rw-r--r-- | arch/x86/kernel/amd_iommu_init.c | 221 |
1 files changed, 170 insertions, 51 deletions
diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index 5a170cbbbed8..bfc8453bd98d 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) 2007-2009 Advanced Micro Devices, Inc. | 2 | * Copyright (C) 2007-2010 Advanced Micro Devices, Inc. |
| 3 | * Author: Joerg Roedel <joerg.roedel@amd.com> | 3 | * Author: Joerg Roedel <joerg.roedel@amd.com> |
| 4 | * Leo Duran <leo.duran@amd.com> | 4 | * Leo Duran <leo.duran@amd.com> |
| 5 | * | 5 | * |
| @@ -21,7 +21,7 @@ | |||
| 21 | #include <linux/acpi.h> | 21 | #include <linux/acpi.h> |
| 22 | #include <linux/list.h> | 22 | #include <linux/list.h> |
| 23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
| 24 | #include <linux/sysdev.h> | 24 | #include <linux/syscore_ops.h> |
| 25 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
| 26 | #include <linux/msi.h> | 26 | #include <linux/msi.h> |
| 27 | #include <asm/pci-direct.h> | 27 | #include <asm/pci-direct.h> |
| @@ -31,7 +31,7 @@ | |||
| 31 | #include <asm/iommu.h> | 31 | #include <asm/iommu.h> |
| 32 | #include <asm/gart.h> | 32 | #include <asm/gart.h> |
| 33 | #include <asm/x86_init.h> | 33 | #include <asm/x86_init.h> |
| 34 | 34 | #include <asm/iommu_table.h> | |
| 35 | /* | 35 | /* |
| 36 | * definitions for the ACPI scanning code | 36 | * definitions for the ACPI scanning code |
| 37 | */ | 37 | */ |
| @@ -137,6 +137,7 @@ int amd_iommus_present; | |||
| 137 | 137 | ||
| 138 | /* IOMMUs have a non-present cache? */ | 138 | /* IOMMUs have a non-present cache? */ |
| 139 | bool amd_iommu_np_cache __read_mostly; | 139 | bool amd_iommu_np_cache __read_mostly; |
| 140 | bool amd_iommu_iotlb_sup __read_mostly = true; | ||
| 140 | 141 | ||
| 141 | /* | 142 | /* |
| 142 | * The ACPI table parsing functions set this variable on an error | 143 | * The ACPI table parsing functions set this variable on an error |
| @@ -180,6 +181,12 @@ static u32 dev_table_size; /* size of the device table */ | |||
| 180 | static u32 alias_table_size; /* size of the alias table */ | 181 | static u32 alias_table_size; /* size of the alias table */ |
| 181 | static u32 rlookup_table_size; /* size if the rlookup table */ | 182 | static u32 rlookup_table_size; /* size if the rlookup table */ |
| 182 | 183 | ||
| 184 | /* | ||
| 185 | * This function flushes all internal caches of | ||
| 186 | * the IOMMU used by this driver. | ||
| 187 | */ | ||
| 188 | extern void iommu_flush_all_caches(struct amd_iommu *iommu); | ||
| 189 | |||
| 183 | static inline void update_last_devid(u16 devid) | 190 | static inline void update_last_devid(u16 devid) |
| 184 | { | 191 | { |
| 185 | if (devid > amd_iommu_last_bdf) | 192 | if (devid > amd_iommu_last_bdf) |
| @@ -194,6 +201,39 @@ static inline unsigned long tbl_size(int entry_size) | |||
| 194 | return 1UL << shift; | 201 | return 1UL << shift; |
| 195 | } | 202 | } |
| 196 | 203 | ||
| 204 | /* Access to l1 and l2 indexed register spaces */ | ||
| 205 | |||
| 206 | static u32 iommu_read_l1(struct amd_iommu *iommu, u16 l1, u8 address) | ||
| 207 | { | ||
| 208 | u32 val; | ||
| 209 | |||
| 210 | pci_write_config_dword(iommu->dev, 0xf8, (address | l1 << 16)); | ||
| 211 | pci_read_config_dword(iommu->dev, 0xfc, &val); | ||
| 212 | return val; | ||
| 213 | } | ||
| 214 | |||
| 215 | static void iommu_write_l1(struct amd_iommu *iommu, u16 l1, u8 address, u32 val) | ||
| 216 | { | ||
| 217 | pci_write_config_dword(iommu->dev, 0xf8, (address | l1 << 16 | 1 << 31)); | ||
| 218 | pci_write_config_dword(iommu->dev, 0xfc, val); | ||
| 219 | pci_write_config_dword(iommu->dev, 0xf8, (address | l1 << 16)); | ||
| 220 | } | ||
| 221 | |||
| 222 | static u32 iommu_read_l2(struct amd_iommu *iommu, u8 address) | ||
| 223 | { | ||
| 224 | u32 val; | ||
| 225 | |||
| 226 | pci_write_config_dword(iommu->dev, 0xf0, address); | ||
| 227 | pci_read_config_dword(iommu->dev, 0xf4, &val); | ||
| 228 | return val; | ||
| 229 | } | ||
| 230 | |||
| 231 | static void iommu_write_l2(struct amd_iommu *iommu, u8 address, u32 val) | ||
| 232 | { | ||
| 233 | pci_write_config_dword(iommu->dev, 0xf0, (address | 1 << 8)); | ||
| 234 | pci_write_config_dword(iommu->dev, 0xf4, val); | ||
| 235 | } | ||
| 236 | |||
| 197 | /**************************************************************************** | 237 | /**************************************************************************** |
| 198 | * | 238 | * |
| 199 | * AMD IOMMU MMIO register space handling functions | 239 | * AMD IOMMU MMIO register space handling functions |
| @@ -260,9 +300,23 @@ static void iommu_feature_disable(struct amd_iommu *iommu, u8 bit) | |||
| 260 | /* Function to enable the hardware */ | 300 | /* Function to enable the hardware */ |
| 261 | static void iommu_enable(struct amd_iommu *iommu) | 301 | static void iommu_enable(struct amd_iommu *iommu) |
| 262 | { | 302 | { |
| 263 | printk(KERN_INFO "AMD-Vi: Enabling IOMMU at %s cap 0x%hx\n", | 303 | static const char * const feat_str[] = { |
| 304 | "PreF", "PPR", "X2APIC", "NX", "GT", "[5]", | ||
| 305 | "IA", "GA", "HE", "PC", NULL | ||
| 306 | }; | ||
| 307 | int i; | ||
| 308 | |||
| 309 | printk(KERN_INFO "AMD-Vi: Enabling IOMMU at %s cap 0x%hx", | ||
| 264 | dev_name(&iommu->dev->dev), iommu->cap_ptr); | 310 | dev_name(&iommu->dev->dev), iommu->cap_ptr); |
| 265 | 311 | ||
| 312 | if (iommu->cap & (1 << IOMMU_CAP_EFR)) { | ||
| 313 | printk(KERN_CONT " extended features: "); | ||
| 314 | for (i = 0; feat_str[i]; ++i) | ||
| 315 | if (iommu_feature(iommu, (1ULL << i))) | ||
| 316 | printk(KERN_CONT " %s", feat_str[i]); | ||
| 317 | } | ||
| 318 | printk(KERN_CONT "\n"); | ||
| 319 | |||
| 266 | iommu_feature_enable(iommu, CONTROL_IOMMU_EN); | 320 | iommu_feature_enable(iommu, CONTROL_IOMMU_EN); |
| 267 | } | 321 | } |
| 268 | 322 | ||
| @@ -618,7 +672,8 @@ static void __init set_device_exclusion_range(u16 devid, struct ivmd_header *m) | |||
| 618 | static void __init init_iommu_from_pci(struct amd_iommu *iommu) | 672 | static void __init init_iommu_from_pci(struct amd_iommu *iommu) |
| 619 | { | 673 | { |
| 620 | int cap_ptr = iommu->cap_ptr; | 674 | int cap_ptr = iommu->cap_ptr; |
| 621 | u32 range, misc; | 675 | u32 range, misc, low, high; |
| 676 | int i, j; | ||
| 622 | 677 | ||
| 623 | pci_read_config_dword(iommu->dev, cap_ptr + MMIO_CAP_HDR_OFFSET, | 678 | pci_read_config_dword(iommu->dev, cap_ptr + MMIO_CAP_HDR_OFFSET, |
| 624 | &iommu->cap); | 679 | &iommu->cap); |
| @@ -633,12 +688,38 @@ static void __init init_iommu_from_pci(struct amd_iommu *iommu) | |||
| 633 | MMIO_GET_LD(range)); | 688 | MMIO_GET_LD(range)); |
| 634 | iommu->evt_msi_num = MMIO_MSI_NUM(misc); | 689 | iommu->evt_msi_num = MMIO_MSI_NUM(misc); |
| 635 | 690 | ||
| 636 | if (is_rd890_iommu(iommu->dev)) { | 691 | if (!(iommu->cap & (1 << IOMMU_CAP_IOTLB))) |
| 637 | pci_read_config_dword(iommu->dev, 0xf0, &iommu->cache_cfg[0]); | 692 | amd_iommu_iotlb_sup = false; |
| 638 | pci_read_config_dword(iommu->dev, 0xf4, &iommu->cache_cfg[1]); | 693 | |
| 639 | pci_read_config_dword(iommu->dev, 0xf8, &iommu->cache_cfg[2]); | 694 | /* read extended feature bits */ |
| 640 | pci_read_config_dword(iommu->dev, 0xfc, &iommu->cache_cfg[3]); | 695 | low = readl(iommu->mmio_base + MMIO_EXT_FEATURES); |
| 641 | } | 696 | high = readl(iommu->mmio_base + MMIO_EXT_FEATURES + 4); |
| 697 | |||
| 698 | iommu->features = ((u64)high << 32) | low; | ||
| 699 | |||
| 700 | if (!is_rd890_iommu(iommu->dev)) | ||
| 701 | return; | ||
| 702 | |||
| 703 | /* | ||
| 704 | * Some rd890 systems may not be fully reconfigured by the BIOS, so | ||
| 705 | * it's necessary for us to store this information so it can be | ||
| 706 | * reprogrammed on resume | ||
| 707 | */ | ||
| 708 | |||
| 709 | pci_read_config_dword(iommu->dev, iommu->cap_ptr + 4, | ||
| 710 | &iommu->stored_addr_lo); | ||
| 711 | pci_read_config_dword(iommu->dev, iommu->cap_ptr + 8, | ||
| 712 | &iommu->stored_addr_hi); | ||
| 713 | |||
| 714 | /* Low bit locks writes to configuration space */ | ||
| 715 | iommu->stored_addr_lo &= ~1; | ||
| 716 | |||
| 717 | for (i = 0; i < 6; i++) | ||
| 718 | for (j = 0; j < 0x12; j++) | ||
| 719 | iommu->stored_l1[i][j] = iommu_read_l1(iommu, i, j); | ||
| 720 | |||
| 721 | for (i = 0; i < 0x83; i++) | ||
| 722 | iommu->stored_l2[i] = iommu_read_l2(iommu, i); | ||
| 642 | } | 723 | } |
| 643 | 724 | ||
| 644 | /* | 725 | /* |
| @@ -650,8 +731,8 @@ static void __init init_iommu_from_acpi(struct amd_iommu *iommu, | |||
| 650 | { | 731 | { |
| 651 | u8 *p = (u8 *)h; | 732 | u8 *p = (u8 *)h; |
| 652 | u8 *end = p, flags = 0; | 733 | u8 *end = p, flags = 0; |
| 653 | u16 dev_i, devid = 0, devid_start = 0, devid_to = 0; | 734 | u16 devid = 0, devid_start = 0, devid_to = 0; |
| 654 | u32 ext_flags = 0; | 735 | u32 dev_i, ext_flags = 0; |
| 655 | bool alias = false; | 736 | bool alias = false; |
| 656 | struct ivhd_entry *e; | 737 | struct ivhd_entry *e; |
| 657 | 738 | ||
| @@ -806,7 +887,7 @@ static void __init init_iommu_from_acpi(struct amd_iommu *iommu, | |||
| 806 | /* Initializes the device->iommu mapping for the driver */ | 887 | /* Initializes the device->iommu mapping for the driver */ |
| 807 | static int __init init_iommu_devices(struct amd_iommu *iommu) | 888 | static int __init init_iommu_devices(struct amd_iommu *iommu) |
| 808 | { | 889 | { |
| 809 | u16 i; | 890 | u32 i; |
| 810 | 891 | ||
| 811 | for (i = iommu->first_device; i <= iommu->last_device; ++i) | 892 | for (i = iommu->first_device; i <= iommu->last_device; ++i) |
| 812 | set_iommu_for_device(iommu, i); | 893 | set_iommu_for_device(iommu, i); |
| @@ -953,10 +1034,11 @@ static int iommu_setup_msi(struct amd_iommu *iommu) | |||
| 953 | if (pci_enable_msi(iommu->dev)) | 1034 | if (pci_enable_msi(iommu->dev)) |
| 954 | return 1; | 1035 | return 1; |
| 955 | 1036 | ||
| 956 | r = request_irq(iommu->dev->irq, amd_iommu_int_handler, | 1037 | r = request_threaded_irq(iommu->dev->irq, |
| 957 | IRQF_SAMPLE_RANDOM, | 1038 | amd_iommu_int_handler, |
| 958 | "AMD-Vi", | 1039 | amd_iommu_int_thread, |
| 959 | NULL); | 1040 | 0, "AMD-Vi", |
| 1041 | iommu->dev); | ||
| 960 | 1042 | ||
| 961 | if (r) { | 1043 | if (r) { |
| 962 | pci_disable_msi(iommu->dev); | 1044 | pci_disable_msi(iommu->dev); |
| @@ -1095,7 +1177,7 @@ static int __init init_memory_definitions(struct acpi_table_header *table) | |||
| 1095 | */ | 1177 | */ |
| 1096 | static void init_device_table(void) | 1178 | static void init_device_table(void) |
| 1097 | { | 1179 | { |
| 1098 | u16 devid; | 1180 | u32 devid; |
| 1099 | 1181 | ||
| 1100 | for (devid = 0; devid <= amd_iommu_last_bdf; ++devid) { | 1182 | for (devid = 0; devid <= amd_iommu_last_bdf; ++devid) { |
| 1101 | set_dev_entry_bit(devid, DEV_ENTRY_VALID); | 1183 | set_dev_entry_bit(devid, DEV_ENTRY_VALID); |
| @@ -1127,14 +1209,53 @@ static void iommu_init_flags(struct amd_iommu *iommu) | |||
| 1127 | iommu_feature_enable(iommu, CONTROL_COHERENT_EN); | 1209 | iommu_feature_enable(iommu, CONTROL_COHERENT_EN); |
| 1128 | } | 1210 | } |
| 1129 | 1211 | ||
| 1130 | static void iommu_apply_quirks(struct amd_iommu *iommu) | 1212 | static void iommu_apply_resume_quirks(struct amd_iommu *iommu) |
| 1131 | { | 1213 | { |
| 1132 | if (is_rd890_iommu(iommu->dev)) { | 1214 | int i, j; |
| 1133 | pci_write_config_dword(iommu->dev, 0xf0, iommu->cache_cfg[0]); | 1215 | u32 ioc_feature_control; |
| 1134 | pci_write_config_dword(iommu->dev, 0xf4, iommu->cache_cfg[1]); | 1216 | struct pci_dev *pdev = NULL; |
| 1135 | pci_write_config_dword(iommu->dev, 0xf8, iommu->cache_cfg[2]); | 1217 | |
| 1136 | pci_write_config_dword(iommu->dev, 0xfc, iommu->cache_cfg[3]); | 1218 | /* RD890 BIOSes may not have completely reconfigured the iommu */ |
| 1137 | } | 1219 | if (!is_rd890_iommu(iommu->dev)) |
| 1220 | return; | ||
| 1221 | |||
| 1222 | /* | ||
| 1223 | * First, we need to ensure that the iommu is enabled. This is | ||
| 1224 | * controlled by a register in the northbridge | ||
| 1225 | */ | ||
| 1226 | pdev = pci_get_bus_and_slot(iommu->dev->bus->number, PCI_DEVFN(0, 0)); | ||
| 1227 | |||
| 1228 | if (!pdev) | ||
| 1229 | return; | ||
| 1230 | |||
| 1231 | /* Select Northbridge indirect register 0x75 and enable writing */ | ||
| 1232 | pci_write_config_dword(pdev, 0x60, 0x75 | (1 << 7)); | ||
| 1233 | pci_read_config_dword(pdev, 0x64, &ioc_feature_control); | ||
| 1234 | |||
| 1235 | /* Enable the iommu */ | ||
| 1236 | if (!(ioc_feature_control & 0x1)) | ||
| 1237 | pci_write_config_dword(pdev, 0x64, ioc_feature_control | 1); | ||
| 1238 | |||
| 1239 | pci_dev_put(pdev); | ||
| 1240 | |||
| 1241 | /* Restore the iommu BAR */ | ||
| 1242 | pci_write_config_dword(iommu->dev, iommu->cap_ptr + 4, | ||
| 1243 | iommu->stored_addr_lo); | ||
| 1244 | pci_write_config_dword(iommu->dev, iommu->cap_ptr + 8, | ||
| 1245 | iommu->stored_addr_hi); | ||
| 1246 | |||
| 1247 | /* Restore the l1 indirect regs for each of the 6 l1s */ | ||
| 1248 | for (i = 0; i < 6; i++) | ||
| 1249 | for (j = 0; j < 0x12; j++) | ||
| 1250 | iommu_write_l1(iommu, i, j, iommu->stored_l1[i][j]); | ||
| 1251 | |||
| 1252 | /* Restore the l2 indirect regs */ | ||
| 1253 | for (i = 0; i < 0x83; i++) | ||
| 1254 | iommu_write_l2(iommu, i, iommu->stored_l2[i]); | ||
| 1255 | |||
| 1256 | /* Lock PCI setup registers */ | ||
| 1257 | pci_write_config_dword(iommu->dev, iommu->cap_ptr + 4, | ||
| 1258 | iommu->stored_addr_lo | 1); | ||
| 1138 | } | 1259 | } |
| 1139 | 1260 | ||
| 1140 | /* | 1261 | /* |
| @@ -1147,7 +1268,6 @@ static void enable_iommus(void) | |||
| 1147 | 1268 | ||
| 1148 | for_each_iommu(iommu) { | 1269 | for_each_iommu(iommu) { |
| 1149 | iommu_disable(iommu); | 1270 | iommu_disable(iommu); |
| 1150 | iommu_apply_quirks(iommu); | ||
| 1151 | iommu_init_flags(iommu); | 1271 | iommu_init_flags(iommu); |
| 1152 | iommu_set_device_table(iommu); | 1272 | iommu_set_device_table(iommu); |
| 1153 | iommu_enable_command_buffer(iommu); | 1273 | iommu_enable_command_buffer(iommu); |
| @@ -1155,6 +1275,7 @@ static void enable_iommus(void) | |||
| 1155 | iommu_set_exclusion_range(iommu); | 1275 | iommu_set_exclusion_range(iommu); |
| 1156 | iommu_init_msi(iommu); | 1276 | iommu_init_msi(iommu); |
| 1157 | iommu_enable(iommu); | 1277 | iommu_enable(iommu); |
| 1278 | iommu_flush_all_caches(iommu); | ||
| 1158 | } | 1279 | } |
| 1159 | } | 1280 | } |
| 1160 | 1281 | ||
| @@ -1171,8 +1292,13 @@ static void disable_iommus(void) | |||
| 1171 | * disable suspend until real resume implemented | 1292 | * disable suspend until real resume implemented |
| 1172 | */ | 1293 | */ |
| 1173 | 1294 | ||
| 1174 | static int amd_iommu_resume(struct sys_device *dev) | 1295 | static void amd_iommu_resume(void) |
| 1175 | { | 1296 | { |
| 1297 | struct amd_iommu *iommu; | ||
| 1298 | |||
| 1299 | for_each_iommu(iommu) | ||
| 1300 | iommu_apply_resume_quirks(iommu); | ||
| 1301 | |||
| 1176 | /* re-load the hardware */ | 1302 | /* re-load the hardware */ |
| 1177 | enable_iommus(); | 1303 | enable_iommus(); |
| 1178 | 1304 | ||
| @@ -1180,13 +1306,11 @@ static int amd_iommu_resume(struct sys_device *dev) | |||
| 1180 | * we have to flush after the IOMMUs are enabled because a | 1306 | * we have to flush after the IOMMUs are enabled because a |
| 1181 | * disabled IOMMU will never execute the commands we send | 1307 | * disabled IOMMU will never execute the commands we send |
| 1182 | */ | 1308 | */ |
| 1183 | amd_iommu_flush_all_devices(); | 1309 | for_each_iommu(iommu) |
| 1184 | amd_iommu_flush_all_domains(); | 1310 | iommu_flush_all_caches(iommu); |
| 1185 | |||
| 1186 | return 0; | ||
| 1187 | } | 1311 | } |
| 1188 | 1312 | ||
| 1189 | static int amd_iommu_suspend(struct sys_device *dev, pm_message_t state) | 1313 | static int amd_iommu_suspend(void) |
| 1190 | { | 1314 | { |
| 1191 | /* disable IOMMUs to go out of the way for BIOS */ | 1315 | /* disable IOMMUs to go out of the way for BIOS */ |
| 1192 | disable_iommus(); | 1316 | disable_iommus(); |
| @@ -1194,17 +1318,11 @@ static int amd_iommu_suspend(struct sys_device *dev, pm_message_t state) | |||
| 1194 | return 0; | 1318 | return 0; |
| 1195 | } | 1319 | } |
| 1196 | 1320 | ||
| 1197 | static struct sysdev_class amd_iommu_sysdev_class = { | 1321 | static struct syscore_ops amd_iommu_syscore_ops = { |
| 1198 | .name = "amd_iommu", | ||
| 1199 | .suspend = amd_iommu_suspend, | 1322 | .suspend = amd_iommu_suspend, |
| 1200 | .resume = amd_iommu_resume, | 1323 | .resume = amd_iommu_resume, |
| 1201 | }; | 1324 | }; |
| 1202 | 1325 | ||
| 1203 | static struct sys_device device_amd_iommu = { | ||
| 1204 | .id = 0, | ||
| 1205 | .cls = &amd_iommu_sysdev_class, | ||
| 1206 | }; | ||
| 1207 | |||
| 1208 | /* | 1326 | /* |
| 1209 | * This is the core init function for AMD IOMMU hardware in the system. | 1327 | * This is the core init function for AMD IOMMU hardware in the system. |
| 1210 | * This function is called from the generic x86 DMA layer initialization | 1328 | * This function is called from the generic x86 DMA layer initialization |
| @@ -1321,14 +1439,6 @@ static int __init amd_iommu_init(void) | |||
| 1321 | goto free; | 1439 | goto free; |
| 1322 | } | 1440 | } |
| 1323 | 1441 | ||
| 1324 | ret = sysdev_class_register(&amd_iommu_sysdev_class); | ||
| 1325 | if (ret) | ||
| 1326 | goto free; | ||
| 1327 | |||
| 1328 | ret = sysdev_register(&device_amd_iommu); | ||
| 1329 | if (ret) | ||
| 1330 | goto free; | ||
| 1331 | |||
| 1332 | ret = amd_iommu_init_devices(); | 1442 | ret = amd_iommu_init_devices(); |
| 1333 | if (ret) | 1443 | if (ret) |
| 1334 | goto free; | 1444 | goto free; |
| @@ -1347,6 +1457,8 @@ static int __init amd_iommu_init(void) | |||
| 1347 | 1457 | ||
| 1348 | amd_iommu_init_notifier(); | 1458 | amd_iommu_init_notifier(); |
| 1349 | 1459 | ||
| 1460 | register_syscore_ops(&amd_iommu_syscore_ops); | ||
| 1461 | |||
| 1350 | if (iommu_pass_through) | 1462 | if (iommu_pass_through) |
| 1351 | goto out; | 1463 | goto out; |
| 1352 | 1464 | ||
| @@ -1405,13 +1517,13 @@ static int __init early_amd_iommu_detect(struct acpi_table_header *table) | |||
| 1405 | return 0; | 1517 | return 0; |
| 1406 | } | 1518 | } |
| 1407 | 1519 | ||
| 1408 | void __init amd_iommu_detect(void) | 1520 | int __init amd_iommu_detect(void) |
| 1409 | { | 1521 | { |
| 1410 | if (no_iommu || (iommu_detected && !gart_iommu_aperture)) | 1522 | if (no_iommu || (iommu_detected && !gart_iommu_aperture)) |
| 1411 | return; | 1523 | return -ENODEV; |
| 1412 | 1524 | ||
| 1413 | if (amd_iommu_disabled) | 1525 | if (amd_iommu_disabled) |
| 1414 | return; | 1526 | return -ENODEV; |
| 1415 | 1527 | ||
| 1416 | if (acpi_table_parse("IVRS", early_amd_iommu_detect) == 0) { | 1528 | if (acpi_table_parse("IVRS", early_amd_iommu_detect) == 0) { |
| 1417 | iommu_detected = 1; | 1529 | iommu_detected = 1; |
| @@ -1420,7 +1532,9 @@ void __init amd_iommu_detect(void) | |||
| 1420 | 1532 | ||
| 1421 | /* Make sure ACS will be enabled */ | 1533 | /* Make sure ACS will be enabled */ |
| 1422 | pci_request_acs(); | 1534 | pci_request_acs(); |
| 1535 | return 1; | ||
| 1423 | } | 1536 | } |
| 1537 | return -ENODEV; | ||
| 1424 | } | 1538 | } |
| 1425 | 1539 | ||
| 1426 | /**************************************************************************** | 1540 | /**************************************************************************** |
| @@ -1451,3 +1565,8 @@ static int __init parse_amd_iommu_options(char *str) | |||
| 1451 | 1565 | ||
| 1452 | __setup("amd_iommu_dump", parse_amd_iommu_dump); | 1566 | __setup("amd_iommu_dump", parse_amd_iommu_dump); |
| 1453 | __setup("amd_iommu=", parse_amd_iommu_options); | 1567 | __setup("amd_iommu=", parse_amd_iommu_options); |
| 1568 | |||
| 1569 | IOMMU_INIT_FINISH(amd_iommu_detect, | ||
| 1570 | gart_iommu_hole_init, | ||
| 1571 | 0, | ||
| 1572 | 0); | ||
