diff options
-rw-r--r-- | arch/x86/Kconfig | 2 | ||||
-rw-r--r-- | arch/x86/include/asm/apic.h | 3 | ||||
-rw-r--r-- | arch/x86/include/asm/io_apic.h | 11 | ||||
-rw-r--r-- | arch/x86/kernel/apic/apic.c | 70 | ||||
-rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 140 | ||||
-rw-r--r-- | drivers/pci/dmar.c | 71 | ||||
-rw-r--r-- | drivers/pci/intel-iommu.c | 239 | ||||
-rw-r--r-- | drivers/pci/intr_remapping.c | 84 | ||||
-rw-r--r-- | include/linux/dmar.h | 11 | ||||
-rw-r--r-- | include/linux/intel-iommu.h | 13 |
10 files changed, 539 insertions, 105 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 5b2196ab8168..4b3408206091 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -253,6 +253,7 @@ config SMP | |||
253 | config X86_X2APIC | 253 | config X86_X2APIC |
254 | bool "Support x2apic" | 254 | bool "Support x2apic" |
255 | depends on X86_LOCAL_APIC && X86_64 | 255 | depends on X86_LOCAL_APIC && X86_64 |
256 | select INTR_REMAP | ||
256 | ---help--- | 257 | ---help--- |
257 | This enables x2apic support on CPUs that have this feature. | 258 | This enables x2apic support on CPUs that have this feature. |
258 | 259 | ||
@@ -1881,7 +1882,6 @@ config DMAR_FLOPPY_WA | |||
1881 | config INTR_REMAP | 1882 | config INTR_REMAP |
1882 | bool "Support for Interrupt Remapping (EXPERIMENTAL)" | 1883 | bool "Support for Interrupt Remapping (EXPERIMENTAL)" |
1883 | depends on X86_64 && X86_IO_APIC && PCI_MSI && ACPI && EXPERIMENTAL | 1884 | depends on X86_64 && X86_IO_APIC && PCI_MSI && ACPI && EXPERIMENTAL |
1884 | select X86_X2APIC | ||
1885 | ---help--- | 1885 | ---help--- |
1886 | Supports Interrupt remapping for IO-APIC and MSI devices. | 1886 | Supports Interrupt remapping for IO-APIC and MSI devices. |
1887 | To use x2apic mode in the CPU's which support x2APIC enhancements or | 1887 | To use x2apic mode in the CPU's which support x2APIC enhancements or |
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index df8a300dfe6c..42f2f8377422 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h | |||
@@ -107,6 +107,9 @@ extern u32 native_safe_apic_wait_icr_idle(void); | |||
107 | extern void native_apic_icr_write(u32 low, u32 id); | 107 | extern void native_apic_icr_write(u32 low, u32 id); |
108 | extern u64 native_apic_icr_read(void); | 108 | extern u64 native_apic_icr_read(void); |
109 | 109 | ||
110 | #define EIM_8BIT_APIC_ID 0 | ||
111 | #define EIM_32BIT_APIC_ID 1 | ||
112 | |||
110 | #ifdef CONFIG_X86_X2APIC | 113 | #ifdef CONFIG_X86_X2APIC |
111 | /* | 114 | /* |
112 | * Make previous memory operations globally visible before | 115 | * Make previous memory operations globally visible before |
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h index 373cc2bbcad2..9d826e436010 100644 --- a/arch/x86/include/asm/io_apic.h +++ b/arch/x86/include/asm/io_apic.h | |||
@@ -162,10 +162,13 @@ extern int (*ioapic_renumber_irq)(int ioapic, int irq); | |||
162 | extern void ioapic_init_mappings(void); | 162 | extern void ioapic_init_mappings(void); |
163 | 163 | ||
164 | #ifdef CONFIG_X86_64 | 164 | #ifdef CONFIG_X86_64 |
165 | extern int save_IO_APIC_setup(void); | 165 | extern struct IO_APIC_route_entry **alloc_ioapic_entries(void); |
166 | extern void mask_IO_APIC_setup(void); | 166 | extern void free_ioapic_entries(struct IO_APIC_route_entry **ioapic_entries); |
167 | extern void restore_IO_APIC_setup(void); | 167 | extern int save_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries); |
168 | extern void reinit_intr_remapped_IO_APIC(int); | 168 | extern void mask_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries); |
169 | extern int restore_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries); | ||
170 | extern void reinit_intr_remapped_IO_APIC(int intr_remapping, | ||
171 | struct IO_APIC_route_entry **ioapic_entries); | ||
169 | #endif | 172 | #endif |
170 | 173 | ||
171 | extern void probe_nr_irqs_gsi(void); | 174 | extern void probe_nr_irqs_gsi(void); |
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 85eb8e100818..098ec84b8c00 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c | |||
@@ -1304,6 +1304,7 @@ void __init enable_IR_x2apic(void) | |||
1304 | #ifdef CONFIG_INTR_REMAP | 1304 | #ifdef CONFIG_INTR_REMAP |
1305 | int ret; | 1305 | int ret; |
1306 | unsigned long flags; | 1306 | unsigned long flags; |
1307 | struct IO_APIC_route_entry **ioapic_entries = NULL; | ||
1307 | 1308 | ||
1308 | if (!cpu_has_x2apic) | 1309 | if (!cpu_has_x2apic) |
1309 | return; | 1310 | return; |
@@ -1334,17 +1335,23 @@ void __init enable_IR_x2apic(void) | |||
1334 | return; | 1335 | return; |
1335 | } | 1336 | } |
1336 | 1337 | ||
1337 | ret = save_IO_APIC_setup(); | 1338 | ioapic_entries = alloc_ioapic_entries(); |
1339 | if (!ioapic_entries) { | ||
1340 | pr_info("Allocate ioapic_entries failed: %d\n", ret); | ||
1341 | goto end; | ||
1342 | } | ||
1343 | |||
1344 | ret = save_IO_APIC_setup(ioapic_entries); | ||
1338 | if (ret) { | 1345 | if (ret) { |
1339 | pr_info("Saving IO-APIC state failed: %d\n", ret); | 1346 | pr_info("Saving IO-APIC state failed: %d\n", ret); |
1340 | goto end; | 1347 | goto end; |
1341 | } | 1348 | } |
1342 | 1349 | ||
1343 | local_irq_save(flags); | 1350 | local_irq_save(flags); |
1344 | mask_IO_APIC_setup(); | 1351 | mask_IO_APIC_setup(ioapic_entries); |
1345 | mask_8259A(); | 1352 | mask_8259A(); |
1346 | 1353 | ||
1347 | ret = enable_intr_remapping(1); | 1354 | ret = enable_intr_remapping(EIM_32BIT_APIC_ID); |
1348 | 1355 | ||
1349 | if (ret && x2apic_preenabled) { | 1356 | if (ret && x2apic_preenabled) { |
1350 | local_irq_restore(flags); | 1357 | local_irq_restore(flags); |
@@ -1364,9 +1371,9 @@ end_restore: | |||
1364 | /* | 1371 | /* |
1365 | * IR enabling failed | 1372 | * IR enabling failed |
1366 | */ | 1373 | */ |
1367 | restore_IO_APIC_setup(); | 1374 | restore_IO_APIC_setup(ioapic_entries); |
1368 | else | 1375 | else |
1369 | reinit_intr_remapped_IO_APIC(x2apic_preenabled); | 1376 | reinit_intr_remapped_IO_APIC(x2apic_preenabled, ioapic_entries); |
1370 | 1377 | ||
1371 | unmask_8259A(); | 1378 | unmask_8259A(); |
1372 | local_irq_restore(flags); | 1379 | local_irq_restore(flags); |
@@ -1379,6 +1386,8 @@ end: | |||
1379 | pr_info("Enabled Interrupt-remapping\n"); | 1386 | pr_info("Enabled Interrupt-remapping\n"); |
1380 | } else | 1387 | } else |
1381 | pr_err("Failed to enable Interrupt-remapping and x2apic\n"); | 1388 | pr_err("Failed to enable Interrupt-remapping and x2apic\n"); |
1389 | if (ioapic_entries) | ||
1390 | free_ioapic_entries(ioapic_entries); | ||
1382 | #else | 1391 | #else |
1383 | if (!cpu_has_x2apic) | 1392 | if (!cpu_has_x2apic) |
1384 | return; | 1393 | return; |
@@ -1954,6 +1963,10 @@ static int lapic_suspend(struct sys_device *dev, pm_message_t state) | |||
1954 | 1963 | ||
1955 | local_irq_save(flags); | 1964 | local_irq_save(flags); |
1956 | disable_local_APIC(); | 1965 | disable_local_APIC(); |
1966 | #ifdef CONFIG_INTR_REMAP | ||
1967 | if (intr_remapping_enabled) | ||
1968 | disable_intr_remapping(); | ||
1969 | #endif | ||
1957 | local_irq_restore(flags); | 1970 | local_irq_restore(flags); |
1958 | return 0; | 1971 | return 0; |
1959 | } | 1972 | } |
@@ -1964,15 +1977,41 @@ static int lapic_resume(struct sys_device *dev) | |||
1964 | unsigned long flags; | 1977 | unsigned long flags; |
1965 | int maxlvt; | 1978 | int maxlvt; |
1966 | 1979 | ||
1980 | #ifdef CONFIG_INTR_REMAP | ||
1981 | int ret; | ||
1982 | struct IO_APIC_route_entry **ioapic_entries = NULL; | ||
1983 | |||
1967 | if (!apic_pm_state.active) | 1984 | if (!apic_pm_state.active) |
1968 | return 0; | 1985 | return 0; |
1969 | 1986 | ||
1970 | maxlvt = lapic_get_maxlvt(); | ||
1971 | |||
1972 | local_irq_save(flags); | 1987 | local_irq_save(flags); |
1988 | if (x2apic) { | ||
1989 | ioapic_entries = alloc_ioapic_entries(); | ||
1990 | if (!ioapic_entries) { | ||
1991 | WARN(1, "Alloc ioapic_entries in lapic resume failed."); | ||
1992 | return -ENOMEM; | ||
1993 | } | ||
1994 | |||
1995 | ret = save_IO_APIC_setup(ioapic_entries); | ||
1996 | if (ret) { | ||
1997 | WARN(1, "Saving IO-APIC state failed: %d\n", ret); | ||
1998 | free_ioapic_entries(ioapic_entries); | ||
1999 | return ret; | ||
2000 | } | ||
2001 | |||
2002 | mask_IO_APIC_setup(ioapic_entries); | ||
2003 | mask_8259A(); | ||
2004 | enable_x2apic(); | ||
2005 | } | ||
2006 | #else | ||
2007 | if (!apic_pm_state.active) | ||
2008 | return 0; | ||
1973 | 2009 | ||
2010 | local_irq_save(flags); | ||
1974 | if (x2apic) | 2011 | if (x2apic) |
1975 | enable_x2apic(); | 2012 | enable_x2apic(); |
2013 | #endif | ||
2014 | |||
1976 | else { | 2015 | else { |
1977 | /* | 2016 | /* |
1978 | * Make sure the APICBASE points to the right address | 2017 | * Make sure the APICBASE points to the right address |
@@ -1986,6 +2025,7 @@ static int lapic_resume(struct sys_device *dev) | |||
1986 | wrmsr(MSR_IA32_APICBASE, l, h); | 2025 | wrmsr(MSR_IA32_APICBASE, l, h); |
1987 | } | 2026 | } |
1988 | 2027 | ||
2028 | maxlvt = lapic_get_maxlvt(); | ||
1989 | apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED); | 2029 | apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED); |
1990 | apic_write(APIC_ID, apic_pm_state.apic_id); | 2030 | apic_write(APIC_ID, apic_pm_state.apic_id); |
1991 | apic_write(APIC_DFR, apic_pm_state.apic_dfr); | 2031 | apic_write(APIC_DFR, apic_pm_state.apic_dfr); |
@@ -2009,8 +2049,20 @@ static int lapic_resume(struct sys_device *dev) | |||
2009 | apic_write(APIC_ESR, 0); | 2049 | apic_write(APIC_ESR, 0); |
2010 | apic_read(APIC_ESR); | 2050 | apic_read(APIC_ESR); |
2011 | 2051 | ||
2052 | #ifdef CONFIG_INTR_REMAP | ||
2053 | if (intr_remapping_enabled) | ||
2054 | reenable_intr_remapping(EIM_32BIT_APIC_ID); | ||
2055 | |||
2056 | if (x2apic) { | ||
2057 | unmask_8259A(); | ||
2058 | restore_IO_APIC_setup(ioapic_entries); | ||
2059 | free_ioapic_entries(ioapic_entries); | ||
2060 | } | ||
2061 | #endif | ||
2062 | |||
2012 | local_irq_restore(flags); | 2063 | local_irq_restore(flags); |
2013 | 2064 | ||
2065 | |||
2014 | return 0; | 2066 | return 0; |
2015 | } | 2067 | } |
2016 | 2068 | ||
@@ -2048,7 +2100,9 @@ static int __init init_lapic_sysfs(void) | |||
2048 | error = sysdev_register(&device_lapic); | 2100 | error = sysdev_register(&device_lapic); |
2049 | return error; | 2101 | return error; |
2050 | } | 2102 | } |
2051 | device_initcall(init_lapic_sysfs); | 2103 | |
2104 | /* local apic needs to resume before other devices access its registers. */ | ||
2105 | core_initcall(init_lapic_sysfs); | ||
2052 | 2106 | ||
2053 | #else /* CONFIG_PM */ | 2107 | #else /* CONFIG_PM */ |
2054 | 2108 | ||
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 1bb5c6cee3eb..767fe7e46d68 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
@@ -851,63 +851,74 @@ __setup("pirq=", ioapic_pirq_setup); | |||
851 | #endif /* CONFIG_X86_32 */ | 851 | #endif /* CONFIG_X86_32 */ |
852 | 852 | ||
853 | #ifdef CONFIG_INTR_REMAP | 853 | #ifdef CONFIG_INTR_REMAP |
854 | /* I/O APIC RTE contents at the OS boot up */ | 854 | struct IO_APIC_route_entry **alloc_ioapic_entries(void) |
855 | static struct IO_APIC_route_entry *early_ioapic_entries[MAX_IO_APICS]; | 855 | { |
856 | int apic; | ||
857 | struct IO_APIC_route_entry **ioapic_entries; | ||
858 | |||
859 | ioapic_entries = kzalloc(sizeof(*ioapic_entries) * nr_ioapics, | ||
860 | GFP_ATOMIC); | ||
861 | if (!ioapic_entries) | ||
862 | return 0; | ||
863 | |||
864 | for (apic = 0; apic < nr_ioapics; apic++) { | ||
865 | ioapic_entries[apic] = | ||
866 | kzalloc(sizeof(struct IO_APIC_route_entry) * | ||
867 | nr_ioapic_registers[apic], GFP_ATOMIC); | ||
868 | if (!ioapic_entries[apic]) | ||
869 | goto nomem; | ||
870 | } | ||
871 | |||
872 | return ioapic_entries; | ||
873 | |||
874 | nomem: | ||
875 | while (--apic >= 0) | ||
876 | kfree(ioapic_entries[apic]); | ||
877 | kfree(ioapic_entries); | ||
878 | |||
879 | return 0; | ||
880 | } | ||
856 | 881 | ||
857 | /* | 882 | /* |
858 | * Saves all the IO-APIC RTE's | 883 | * Saves all the IO-APIC RTE's |
859 | */ | 884 | */ |
860 | int save_IO_APIC_setup(void) | 885 | int save_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries) |
861 | { | 886 | { |
862 | union IO_APIC_reg_01 reg_01; | ||
863 | unsigned long flags; | ||
864 | int apic, pin; | 887 | int apic, pin; |
865 | 888 | ||
866 | /* | 889 | if (!ioapic_entries) |
867 | * The number of IO-APIC IRQ registers (== #pins): | 890 | return -ENOMEM; |
868 | */ | ||
869 | for (apic = 0; apic < nr_ioapics; apic++) { | ||
870 | spin_lock_irqsave(&ioapic_lock, flags); | ||
871 | reg_01.raw = io_apic_read(apic, 1); | ||
872 | spin_unlock_irqrestore(&ioapic_lock, flags); | ||
873 | nr_ioapic_registers[apic] = reg_01.bits.entries+1; | ||
874 | } | ||
875 | 891 | ||
876 | for (apic = 0; apic < nr_ioapics; apic++) { | 892 | for (apic = 0; apic < nr_ioapics; apic++) { |
877 | early_ioapic_entries[apic] = | 893 | if (!ioapic_entries[apic]) |
878 | kzalloc(sizeof(struct IO_APIC_route_entry) * | 894 | return -ENOMEM; |
879 | nr_ioapic_registers[apic], GFP_KERNEL); | ||
880 | if (!early_ioapic_entries[apic]) | ||
881 | goto nomem; | ||
882 | } | ||
883 | 895 | ||
884 | for (apic = 0; apic < nr_ioapics; apic++) | ||
885 | for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) | 896 | for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) |
886 | early_ioapic_entries[apic][pin] = | 897 | ioapic_entries[apic][pin] = |
887 | ioapic_read_entry(apic, pin); | 898 | ioapic_read_entry(apic, pin); |
899 | } | ||
888 | 900 | ||
889 | return 0; | 901 | return 0; |
890 | |||
891 | nomem: | ||
892 | while (apic >= 0) | ||
893 | kfree(early_ioapic_entries[apic--]); | ||
894 | memset(early_ioapic_entries, 0, | ||
895 | ARRAY_SIZE(early_ioapic_entries)); | ||
896 | |||
897 | return -ENOMEM; | ||
898 | } | 902 | } |
899 | 903 | ||
900 | void mask_IO_APIC_setup(void) | 904 | /* |
905 | * Mask all IO APIC entries. | ||
906 | */ | ||
907 | void mask_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries) | ||
901 | { | 908 | { |
902 | int apic, pin; | 909 | int apic, pin; |
903 | 910 | ||
911 | if (!ioapic_entries) | ||
912 | return; | ||
913 | |||
904 | for (apic = 0; apic < nr_ioapics; apic++) { | 914 | for (apic = 0; apic < nr_ioapics; apic++) { |
905 | if (!early_ioapic_entries[apic]) | 915 | if (!ioapic_entries[apic]) |
906 | break; | 916 | break; |
917 | |||
907 | for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) { | 918 | for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) { |
908 | struct IO_APIC_route_entry entry; | 919 | struct IO_APIC_route_entry entry; |
909 | 920 | ||
910 | entry = early_ioapic_entries[apic][pin]; | 921 | entry = ioapic_entries[apic][pin]; |
911 | if (!entry.mask) { | 922 | if (!entry.mask) { |
912 | entry.mask = 1; | 923 | entry.mask = 1; |
913 | ioapic_write_entry(apic, pin, entry); | 924 | ioapic_write_entry(apic, pin, entry); |
@@ -916,22 +927,30 @@ void mask_IO_APIC_setup(void) | |||
916 | } | 927 | } |
917 | } | 928 | } |
918 | 929 | ||
919 | void restore_IO_APIC_setup(void) | 930 | /* |
931 | * Restore IO APIC entries which was saved in ioapic_entries. | ||
932 | */ | ||
933 | int restore_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries) | ||
920 | { | 934 | { |
921 | int apic, pin; | 935 | int apic, pin; |
922 | 936 | ||
937 | if (!ioapic_entries) | ||
938 | return -ENOMEM; | ||
939 | |||
923 | for (apic = 0; apic < nr_ioapics; apic++) { | 940 | for (apic = 0; apic < nr_ioapics; apic++) { |
924 | if (!early_ioapic_entries[apic]) | 941 | if (!ioapic_entries[apic]) |
925 | break; | 942 | return -ENOMEM; |
943 | |||
926 | for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) | 944 | for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) |
927 | ioapic_write_entry(apic, pin, | 945 | ioapic_write_entry(apic, pin, |
928 | early_ioapic_entries[apic][pin]); | 946 | ioapic_entries[apic][pin]); |
929 | kfree(early_ioapic_entries[apic]); | ||
930 | early_ioapic_entries[apic] = NULL; | ||
931 | } | 947 | } |
948 | return 0; | ||
932 | } | 949 | } |
933 | 950 | ||
934 | void reinit_intr_remapped_IO_APIC(int intr_remapping) | 951 | void reinit_intr_remapped_IO_APIC(int intr_remapping, |
952 | struct IO_APIC_route_entry **ioapic_entries) | ||
953 | |||
935 | { | 954 | { |
936 | /* | 955 | /* |
937 | * for now plain restore of previous settings. | 956 | * for now plain restore of previous settings. |
@@ -940,7 +959,17 @@ void reinit_intr_remapped_IO_APIC(int intr_remapping) | |||
940 | * table entries. for now, do a plain restore, and wait for | 959 | * table entries. for now, do a plain restore, and wait for |
941 | * the setup_IO_APIC_irqs() to do proper initialization. | 960 | * the setup_IO_APIC_irqs() to do proper initialization. |
942 | */ | 961 | */ |
943 | restore_IO_APIC_setup(); | 962 | restore_IO_APIC_setup(ioapic_entries); |
963 | } | ||
964 | |||
965 | void free_ioapic_entries(struct IO_APIC_route_entry **ioapic_entries) | ||
966 | { | ||
967 | int apic; | ||
968 | |||
969 | for (apic = 0; apic < nr_ioapics; apic++) | ||
970 | kfree(ioapic_entries[apic]); | ||
971 | |||
972 | kfree(ioapic_entries); | ||
944 | } | 973 | } |
945 | #endif | 974 | #endif |
946 | 975 | ||
@@ -2495,7 +2524,7 @@ static void irq_complete_move(struct irq_desc **descp) | |||
2495 | static inline void irq_complete_move(struct irq_desc **descp) {} | 2524 | static inline void irq_complete_move(struct irq_desc **descp) {} |
2496 | #endif | 2525 | #endif |
2497 | 2526 | ||
2498 | #ifdef CONFIG_INTR_REMAP | 2527 | #ifdef CONFIG_X86_X2APIC |
2499 | static void __eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg) | 2528 | static void __eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg) |
2500 | { | 2529 | { |
2501 | int apic, pin; | 2530 | int apic, pin; |
@@ -2540,7 +2569,6 @@ static void ack_x2apic_edge(unsigned int irq) | |||
2540 | { | 2569 | { |
2541 | ack_x2APIC_irq(); | 2570 | ack_x2APIC_irq(); |
2542 | } | 2571 | } |
2543 | |||
2544 | #endif | 2572 | #endif |
2545 | 2573 | ||
2546 | static void ack_apic_edge(unsigned int irq) | 2574 | static void ack_apic_edge(unsigned int irq) |
@@ -2651,6 +2679,26 @@ static void ack_apic_level(unsigned int irq) | |||
2651 | #endif | 2679 | #endif |
2652 | } | 2680 | } |
2653 | 2681 | ||
2682 | #ifdef CONFIG_INTR_REMAP | ||
2683 | static void ir_ack_apic_edge(unsigned int irq) | ||
2684 | { | ||
2685 | #ifdef CONFIG_X86_X2APIC | ||
2686 | if (x2apic_enabled()) | ||
2687 | return ack_x2apic_edge(irq); | ||
2688 | #endif | ||
2689 | return ack_apic_edge(irq); | ||
2690 | } | ||
2691 | |||
2692 | static void ir_ack_apic_level(unsigned int irq) | ||
2693 | { | ||
2694 | #ifdef CONFIG_X86_X2APIC | ||
2695 | if (x2apic_enabled()) | ||
2696 | return ack_x2apic_level(irq); | ||
2697 | #endif | ||
2698 | return ack_apic_level(irq); | ||
2699 | } | ||
2700 | #endif /* CONFIG_INTR_REMAP */ | ||
2701 | |||
2654 | static struct irq_chip ioapic_chip __read_mostly = { | 2702 | static struct irq_chip ioapic_chip __read_mostly = { |
2655 | .name = "IO-APIC", | 2703 | .name = "IO-APIC", |
2656 | .startup = startup_ioapic_irq, | 2704 | .startup = startup_ioapic_irq, |
@@ -2670,8 +2718,8 @@ static struct irq_chip ir_ioapic_chip __read_mostly = { | |||
2670 | .mask = mask_IO_APIC_irq, | 2718 | .mask = mask_IO_APIC_irq, |
2671 | .unmask = unmask_IO_APIC_irq, | 2719 | .unmask = unmask_IO_APIC_irq, |
2672 | #ifdef CONFIG_INTR_REMAP | 2720 | #ifdef CONFIG_INTR_REMAP |
2673 | .ack = ack_x2apic_edge, | 2721 | .ack = ir_ack_apic_edge, |
2674 | .eoi = ack_x2apic_level, | 2722 | .eoi = ir_ack_apic_level, |
2675 | #ifdef CONFIG_SMP | 2723 | #ifdef CONFIG_SMP |
2676 | .set_affinity = set_ir_ioapic_affinity_irq, | 2724 | .set_affinity = set_ir_ioapic_affinity_irq, |
2677 | #endif | 2725 | #endif |
@@ -3397,7 +3445,7 @@ static struct irq_chip msi_ir_chip = { | |||
3397 | .unmask = unmask_msi_irq, | 3445 | .unmask = unmask_msi_irq, |
3398 | .mask = mask_msi_irq, | 3446 | .mask = mask_msi_irq, |
3399 | #ifdef CONFIG_INTR_REMAP | 3447 | #ifdef CONFIG_INTR_REMAP |
3400 | .ack = ack_x2apic_edge, | 3448 | .ack = ir_ack_apic_edge, |
3401 | #ifdef CONFIG_SMP | 3449 | #ifdef CONFIG_SMP |
3402 | .set_affinity = ir_set_msi_irq_affinity, | 3450 | .set_affinity = ir_set_msi_irq_affinity, |
3403 | #endif | 3451 | #endif |
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c index d313039e2fdf..25a00ce4f24d 100644 --- a/drivers/pci/dmar.c +++ b/drivers/pci/dmar.c | |||
@@ -180,6 +180,7 @@ dmar_parse_one_drhd(struct acpi_dmar_header *header) | |||
180 | dmaru->hdr = header; | 180 | dmaru->hdr = header; |
181 | drhd = (struct acpi_dmar_hardware_unit *)header; | 181 | drhd = (struct acpi_dmar_hardware_unit *)header; |
182 | dmaru->reg_base_addr = drhd->address; | 182 | dmaru->reg_base_addr = drhd->address; |
183 | dmaru->segment = drhd->segment; | ||
183 | dmaru->include_all = drhd->flags & 0x1; /* BIT0: INCLUDE_ALL */ | 184 | dmaru->include_all = drhd->flags & 0x1; /* BIT0: INCLUDE_ALL */ |
184 | 185 | ||
185 | ret = alloc_iommu(dmaru); | 186 | ret = alloc_iommu(dmaru); |
@@ -790,14 +791,41 @@ end: | |||
790 | } | 791 | } |
791 | 792 | ||
792 | /* | 793 | /* |
794 | * Enable queued invalidation. | ||
795 | */ | ||
796 | static void __dmar_enable_qi(struct intel_iommu *iommu) | ||
797 | { | ||
798 | u32 cmd, sts; | ||
799 | unsigned long flags; | ||
800 | struct q_inval *qi = iommu->qi; | ||
801 | |||
802 | qi->free_head = qi->free_tail = 0; | ||
803 | qi->free_cnt = QI_LENGTH; | ||
804 | |||
805 | spin_lock_irqsave(&iommu->register_lock, flags); | ||
806 | |||
807 | /* write zero to the tail reg */ | ||
808 | writel(0, iommu->reg + DMAR_IQT_REG); | ||
809 | |||
810 | dmar_writeq(iommu->reg + DMAR_IQA_REG, virt_to_phys(qi->desc)); | ||
811 | |||
812 | cmd = iommu->gcmd | DMA_GCMD_QIE; | ||
813 | iommu->gcmd |= DMA_GCMD_QIE; | ||
814 | writel(cmd, iommu->reg + DMAR_GCMD_REG); | ||
815 | |||
816 | /* Make sure hardware complete it */ | ||
817 | IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, readl, (sts & DMA_GSTS_QIES), sts); | ||
818 | |||
819 | spin_unlock_irqrestore(&iommu->register_lock, flags); | ||
820 | } | ||
821 | |||
822 | /* | ||
793 | * Enable Queued Invalidation interface. This is a must to support | 823 | * Enable Queued Invalidation interface. This is a must to support |
794 | * interrupt-remapping. Also used by DMA-remapping, which replaces | 824 | * interrupt-remapping. Also used by DMA-remapping, which replaces |
795 | * register based IOTLB invalidation. | 825 | * register based IOTLB invalidation. |
796 | */ | 826 | */ |
797 | int dmar_enable_qi(struct intel_iommu *iommu) | 827 | int dmar_enable_qi(struct intel_iommu *iommu) |
798 | { | 828 | { |
799 | u32 cmd, sts; | ||
800 | unsigned long flags; | ||
801 | struct q_inval *qi; | 829 | struct q_inval *qi; |
802 | 830 | ||
803 | if (!ecap_qis(iommu->ecap)) | 831 | if (!ecap_qis(iommu->ecap)) |
@@ -835,19 +863,7 @@ int dmar_enable_qi(struct intel_iommu *iommu) | |||
835 | 863 | ||
836 | spin_lock_init(&qi->q_lock); | 864 | spin_lock_init(&qi->q_lock); |
837 | 865 | ||
838 | spin_lock_irqsave(&iommu->register_lock, flags); | 866 | __dmar_enable_qi(iommu); |
839 | /* write zero to the tail reg */ | ||
840 | writel(0, iommu->reg + DMAR_IQT_REG); | ||
841 | |||
842 | dmar_writeq(iommu->reg + DMAR_IQA_REG, virt_to_phys(qi->desc)); | ||
843 | |||
844 | cmd = iommu->gcmd | DMA_GCMD_QIE; | ||
845 | iommu->gcmd |= DMA_GCMD_QIE; | ||
846 | writel(cmd, iommu->reg + DMAR_GCMD_REG); | ||
847 | |||
848 | /* Make sure hardware complete it */ | ||
849 | IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, readl, (sts & DMA_GSTS_QIES), sts); | ||
850 | spin_unlock_irqrestore(&iommu->register_lock, flags); | ||
851 | 867 | ||
852 | return 0; | 868 | return 0; |
853 | } | 869 | } |
@@ -1102,3 +1118,28 @@ int __init enable_drhd_fault_handling(void) | |||
1102 | 1118 | ||
1103 | return 0; | 1119 | return 0; |
1104 | } | 1120 | } |
1121 | |||
1122 | /* | ||
1123 | * Re-enable Queued Invalidation interface. | ||
1124 | */ | ||
1125 | int dmar_reenable_qi(struct intel_iommu *iommu) | ||
1126 | { | ||
1127 | if (!ecap_qis(iommu->ecap)) | ||
1128 | return -ENOENT; | ||
1129 | |||
1130 | if (!iommu->qi) | ||
1131 | return -ENOENT; | ||
1132 | |||
1133 | /* | ||
1134 | * First disable queued invalidation. | ||
1135 | */ | ||
1136 | dmar_disable_qi(iommu); | ||
1137 | /* | ||
1138 | * Then enable queued invalidation again. Since there is no pending | ||
1139 | * invalidation requests now, it's safe to re-enable queued | ||
1140 | * invalidation. | ||
1141 | */ | ||
1142 | __dmar_enable_qi(iommu); | ||
1143 | |||
1144 | return 0; | ||
1145 | } | ||
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 23e56a564e05..dcda5212f3bb 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/iova.h> | 36 | #include <linux/iova.h> |
37 | #include <linux/iommu.h> | 37 | #include <linux/iommu.h> |
38 | #include <linux/intel-iommu.h> | 38 | #include <linux/intel-iommu.h> |
39 | #include <linux/sysdev.h> | ||
39 | #include <asm/cacheflush.h> | 40 | #include <asm/cacheflush.h> |
40 | #include <asm/iommu.h> | 41 | #include <asm/iommu.h> |
41 | #include "pci.h" | 42 | #include "pci.h" |
@@ -247,7 +248,8 @@ struct dmar_domain { | |||
247 | struct device_domain_info { | 248 | struct device_domain_info { |
248 | struct list_head link; /* link to domain siblings */ | 249 | struct list_head link; /* link to domain siblings */ |
249 | struct list_head global; /* link to global list */ | 250 | struct list_head global; /* link to global list */ |
250 | u8 bus; /* PCI bus numer */ | 251 | int segment; /* PCI domain */ |
252 | u8 bus; /* PCI bus number */ | ||
251 | u8 devfn; /* PCI devfn number */ | 253 | u8 devfn; /* PCI devfn number */ |
252 | struct pci_dev *dev; /* it's NULL for PCIE-to-PCI bridge */ | 254 | struct pci_dev *dev; /* it's NULL for PCIE-to-PCI bridge */ |
253 | struct dmar_domain *domain; /* pointer to domain */ | 255 | struct dmar_domain *domain; /* pointer to domain */ |
@@ -467,7 +469,7 @@ static void domain_update_iommu_cap(struct dmar_domain *domain) | |||
467 | domain_update_iommu_snooping(domain); | 469 | domain_update_iommu_snooping(domain); |
468 | } | 470 | } |
469 | 471 | ||
470 | static struct intel_iommu *device_to_iommu(u8 bus, u8 devfn) | 472 | static struct intel_iommu *device_to_iommu(int segment, u8 bus, u8 devfn) |
471 | { | 473 | { |
472 | struct dmar_drhd_unit *drhd = NULL; | 474 | struct dmar_drhd_unit *drhd = NULL; |
473 | int i; | 475 | int i; |
@@ -475,12 +477,20 @@ static struct intel_iommu *device_to_iommu(u8 bus, u8 devfn) | |||
475 | for_each_drhd_unit(drhd) { | 477 | for_each_drhd_unit(drhd) { |
476 | if (drhd->ignored) | 478 | if (drhd->ignored) |
477 | continue; | 479 | continue; |
480 | if (segment != drhd->segment) | ||
481 | continue; | ||
478 | 482 | ||
479 | for (i = 0; i < drhd->devices_cnt; i++) | 483 | for (i = 0; i < drhd->devices_cnt; i++) { |
480 | if (drhd->devices[i] && | 484 | if (drhd->devices[i] && |
481 | drhd->devices[i]->bus->number == bus && | 485 | drhd->devices[i]->bus->number == bus && |
482 | drhd->devices[i]->devfn == devfn) | 486 | drhd->devices[i]->devfn == devfn) |
483 | return drhd->iommu; | 487 | return drhd->iommu; |
488 | if (drhd->devices[i] && | ||
489 | drhd->devices[i]->subordinate && | ||
490 | drhd->devices[i]->subordinate->number <= bus && | ||
491 | drhd->devices[i]->subordinate->subordinate >= bus) | ||
492 | return drhd->iommu; | ||
493 | } | ||
484 | 494 | ||
485 | if (drhd->include_all) | 495 | if (drhd->include_all) |
486 | return drhd->iommu; | 496 | return drhd->iommu; |
@@ -1312,7 +1322,7 @@ static void domain_exit(struct dmar_domain *domain) | |||
1312 | } | 1322 | } |
1313 | 1323 | ||
1314 | static int domain_context_mapping_one(struct dmar_domain *domain, | 1324 | static int domain_context_mapping_one(struct dmar_domain *domain, |
1315 | u8 bus, u8 devfn) | 1325 | int segment, u8 bus, u8 devfn) |
1316 | { | 1326 | { |
1317 | struct context_entry *context; | 1327 | struct context_entry *context; |
1318 | unsigned long flags; | 1328 | unsigned long flags; |
@@ -1327,7 +1337,7 @@ static int domain_context_mapping_one(struct dmar_domain *domain, | |||
1327 | bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); | 1337 | bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); |
1328 | BUG_ON(!domain->pgd); | 1338 | BUG_ON(!domain->pgd); |
1329 | 1339 | ||
1330 | iommu = device_to_iommu(bus, devfn); | 1340 | iommu = device_to_iommu(segment, bus, devfn); |
1331 | if (!iommu) | 1341 | if (!iommu) |
1332 | return -ENODEV; | 1342 | return -ENODEV; |
1333 | 1343 | ||
@@ -1417,8 +1427,8 @@ domain_context_mapping(struct dmar_domain *domain, struct pci_dev *pdev) | |||
1417 | int ret; | 1427 | int ret; |
1418 | struct pci_dev *tmp, *parent; | 1428 | struct pci_dev *tmp, *parent; |
1419 | 1429 | ||
1420 | ret = domain_context_mapping_one(domain, pdev->bus->number, | 1430 | ret = domain_context_mapping_one(domain, pci_domain_nr(pdev->bus), |
1421 | pdev->devfn); | 1431 | pdev->bus->number, pdev->devfn); |
1422 | if (ret) | 1432 | if (ret) |
1423 | return ret; | 1433 | return ret; |
1424 | 1434 | ||
@@ -1429,18 +1439,23 @@ domain_context_mapping(struct dmar_domain *domain, struct pci_dev *pdev) | |||
1429 | /* Secondary interface's bus number and devfn 0 */ | 1439 | /* Secondary interface's bus number and devfn 0 */ |
1430 | parent = pdev->bus->self; | 1440 | parent = pdev->bus->self; |
1431 | while (parent != tmp) { | 1441 | while (parent != tmp) { |
1432 | ret = domain_context_mapping_one(domain, parent->bus->number, | 1442 | ret = domain_context_mapping_one(domain, |
1433 | parent->devfn); | 1443 | pci_domain_nr(parent->bus), |
1444 | parent->bus->number, | ||
1445 | parent->devfn); | ||
1434 | if (ret) | 1446 | if (ret) |
1435 | return ret; | 1447 | return ret; |
1436 | parent = parent->bus->self; | 1448 | parent = parent->bus->self; |
1437 | } | 1449 | } |
1438 | if (tmp->is_pcie) /* this is a PCIE-to-PCI bridge */ | 1450 | if (tmp->is_pcie) /* this is a PCIE-to-PCI bridge */ |
1439 | return domain_context_mapping_one(domain, | 1451 | return domain_context_mapping_one(domain, |
1440 | tmp->subordinate->number, 0); | 1452 | pci_domain_nr(tmp->subordinate), |
1453 | tmp->subordinate->number, 0); | ||
1441 | else /* this is a legacy PCI bridge */ | 1454 | else /* this is a legacy PCI bridge */ |
1442 | return domain_context_mapping_one(domain, | 1455 | return domain_context_mapping_one(domain, |
1443 | tmp->bus->number, tmp->devfn); | 1456 | pci_domain_nr(tmp->bus), |
1457 | tmp->bus->number, | ||
1458 | tmp->devfn); | ||
1444 | } | 1459 | } |
1445 | 1460 | ||
1446 | static int domain_context_mapped(struct pci_dev *pdev) | 1461 | static int domain_context_mapped(struct pci_dev *pdev) |
@@ -1449,12 +1464,12 @@ static int domain_context_mapped(struct pci_dev *pdev) | |||
1449 | struct pci_dev *tmp, *parent; | 1464 | struct pci_dev *tmp, *parent; |
1450 | struct intel_iommu *iommu; | 1465 | struct intel_iommu *iommu; |
1451 | 1466 | ||
1452 | iommu = device_to_iommu(pdev->bus->number, pdev->devfn); | 1467 | iommu = device_to_iommu(pci_domain_nr(pdev->bus), pdev->bus->number, |
1468 | pdev->devfn); | ||
1453 | if (!iommu) | 1469 | if (!iommu) |
1454 | return -ENODEV; | 1470 | return -ENODEV; |
1455 | 1471 | ||
1456 | ret = device_context_mapped(iommu, | 1472 | ret = device_context_mapped(iommu, pdev->bus->number, pdev->devfn); |
1457 | pdev->bus->number, pdev->devfn); | ||
1458 | if (!ret) | 1473 | if (!ret) |
1459 | return ret; | 1474 | return ret; |
1460 | /* dependent device mapping */ | 1475 | /* dependent device mapping */ |
@@ -1465,17 +1480,17 @@ static int domain_context_mapped(struct pci_dev *pdev) | |||
1465 | parent = pdev->bus->self; | 1480 | parent = pdev->bus->self; |
1466 | while (parent != tmp) { | 1481 | while (parent != tmp) { |
1467 | ret = device_context_mapped(iommu, parent->bus->number, | 1482 | ret = device_context_mapped(iommu, parent->bus->number, |
1468 | parent->devfn); | 1483 | parent->devfn); |
1469 | if (!ret) | 1484 | if (!ret) |
1470 | return ret; | 1485 | return ret; |
1471 | parent = parent->bus->self; | 1486 | parent = parent->bus->self; |
1472 | } | 1487 | } |
1473 | if (tmp->is_pcie) | 1488 | if (tmp->is_pcie) |
1474 | return device_context_mapped(iommu, | 1489 | return device_context_mapped(iommu, tmp->subordinate->number, |
1475 | tmp->subordinate->number, 0); | 1490 | 0); |
1476 | else | 1491 | else |
1477 | return device_context_mapped(iommu, | 1492 | return device_context_mapped(iommu, tmp->bus->number, |
1478 | tmp->bus->number, tmp->devfn); | 1493 | tmp->devfn); |
1479 | } | 1494 | } |
1480 | 1495 | ||
1481 | static int | 1496 | static int |
@@ -1542,7 +1557,7 @@ static void domain_remove_dev_info(struct dmar_domain *domain) | |||
1542 | info->dev->dev.archdata.iommu = NULL; | 1557 | info->dev->dev.archdata.iommu = NULL; |
1543 | spin_unlock_irqrestore(&device_domain_lock, flags); | 1558 | spin_unlock_irqrestore(&device_domain_lock, flags); |
1544 | 1559 | ||
1545 | iommu = device_to_iommu(info->bus, info->devfn); | 1560 | iommu = device_to_iommu(info->segment, info->bus, info->devfn); |
1546 | iommu_detach_dev(iommu, info->bus, info->devfn); | 1561 | iommu_detach_dev(iommu, info->bus, info->devfn); |
1547 | free_devinfo_mem(info); | 1562 | free_devinfo_mem(info); |
1548 | 1563 | ||
@@ -1577,11 +1592,14 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw) | |||
1577 | struct pci_dev *dev_tmp; | 1592 | struct pci_dev *dev_tmp; |
1578 | unsigned long flags; | 1593 | unsigned long flags; |
1579 | int bus = 0, devfn = 0; | 1594 | int bus = 0, devfn = 0; |
1595 | int segment; | ||
1580 | 1596 | ||
1581 | domain = find_domain(pdev); | 1597 | domain = find_domain(pdev); |
1582 | if (domain) | 1598 | if (domain) |
1583 | return domain; | 1599 | return domain; |
1584 | 1600 | ||
1601 | segment = pci_domain_nr(pdev->bus); | ||
1602 | |||
1585 | dev_tmp = pci_find_upstream_pcie_bridge(pdev); | 1603 | dev_tmp = pci_find_upstream_pcie_bridge(pdev); |
1586 | if (dev_tmp) { | 1604 | if (dev_tmp) { |
1587 | if (dev_tmp->is_pcie) { | 1605 | if (dev_tmp->is_pcie) { |
@@ -1593,7 +1611,8 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw) | |||
1593 | } | 1611 | } |
1594 | spin_lock_irqsave(&device_domain_lock, flags); | 1612 | spin_lock_irqsave(&device_domain_lock, flags); |
1595 | list_for_each_entry(info, &device_domain_list, global) { | 1613 | list_for_each_entry(info, &device_domain_list, global) { |
1596 | if (info->bus == bus && info->devfn == devfn) { | 1614 | if (info->segment == segment && |
1615 | info->bus == bus && info->devfn == devfn) { | ||
1597 | found = info->domain; | 1616 | found = info->domain; |
1598 | break; | 1617 | break; |
1599 | } | 1618 | } |
@@ -1631,6 +1650,7 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw) | |||
1631 | domain_exit(domain); | 1650 | domain_exit(domain); |
1632 | goto error; | 1651 | goto error; |
1633 | } | 1652 | } |
1653 | info->segment = segment; | ||
1634 | info->bus = bus; | 1654 | info->bus = bus; |
1635 | info->devfn = devfn; | 1655 | info->devfn = devfn; |
1636 | info->dev = NULL; | 1656 | info->dev = NULL; |
@@ -1642,7 +1662,8 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw) | |||
1642 | found = NULL; | 1662 | found = NULL; |
1643 | spin_lock_irqsave(&device_domain_lock, flags); | 1663 | spin_lock_irqsave(&device_domain_lock, flags); |
1644 | list_for_each_entry(tmp, &device_domain_list, global) { | 1664 | list_for_each_entry(tmp, &device_domain_list, global) { |
1645 | if (tmp->bus == bus && tmp->devfn == devfn) { | 1665 | if (tmp->segment == segment && |
1666 | tmp->bus == bus && tmp->devfn == devfn) { | ||
1646 | found = tmp->domain; | 1667 | found = tmp->domain; |
1647 | break; | 1668 | break; |
1648 | } | 1669 | } |
@@ -1662,6 +1683,7 @@ found_domain: | |||
1662 | info = alloc_devinfo_mem(); | 1683 | info = alloc_devinfo_mem(); |
1663 | if (!info) | 1684 | if (!info) |
1664 | goto error; | 1685 | goto error; |
1686 | info->segment = segment; | ||
1665 | info->bus = pdev->bus->number; | 1687 | info->bus = pdev->bus->number; |
1666 | info->devfn = pdev->devfn; | 1688 | info->devfn = pdev->devfn; |
1667 | info->dev = pdev; | 1689 | info->dev = pdev; |
@@ -1946,6 +1968,15 @@ static int __init init_dmars(void) | |||
1946 | } | 1968 | } |
1947 | } | 1969 | } |
1948 | 1970 | ||
1971 | #ifdef CONFIG_INTR_REMAP | ||
1972 | if (!intr_remapping_enabled) { | ||
1973 | ret = enable_intr_remapping(0); | ||
1974 | if (ret) | ||
1975 | printk(KERN_ERR | ||
1976 | "IOMMU: enable interrupt remapping failed\n"); | ||
1977 | } | ||
1978 | #endif | ||
1979 | |||
1949 | /* | 1980 | /* |
1950 | * For each rmrr | 1981 | * For each rmrr |
1951 | * for each dev attached to rmrr | 1982 | * for each dev attached to rmrr |
@@ -2597,6 +2628,150 @@ static void __init init_no_remapping_devices(void) | |||
2597 | } | 2628 | } |
2598 | } | 2629 | } |
2599 | 2630 | ||
2631 | #ifdef CONFIG_SUSPEND | ||
2632 | static int init_iommu_hw(void) | ||
2633 | { | ||
2634 | struct dmar_drhd_unit *drhd; | ||
2635 | struct intel_iommu *iommu = NULL; | ||
2636 | |||
2637 | for_each_active_iommu(iommu, drhd) | ||
2638 | if (iommu->qi) | ||
2639 | dmar_reenable_qi(iommu); | ||
2640 | |||
2641 | for_each_active_iommu(iommu, drhd) { | ||
2642 | iommu_flush_write_buffer(iommu); | ||
2643 | |||
2644 | iommu_set_root_entry(iommu); | ||
2645 | |||
2646 | iommu->flush.flush_context(iommu, 0, 0, 0, | ||
2647 | DMA_CCMD_GLOBAL_INVL, 0); | ||
2648 | iommu->flush.flush_iotlb(iommu, 0, 0, 0, | ||
2649 | DMA_TLB_GLOBAL_FLUSH, 0); | ||
2650 | iommu_disable_protect_mem_regions(iommu); | ||
2651 | iommu_enable_translation(iommu); | ||
2652 | } | ||
2653 | |||
2654 | return 0; | ||
2655 | } | ||
2656 | |||
2657 | static void iommu_flush_all(void) | ||
2658 | { | ||
2659 | struct dmar_drhd_unit *drhd; | ||
2660 | struct intel_iommu *iommu; | ||
2661 | |||
2662 | for_each_active_iommu(iommu, drhd) { | ||
2663 | iommu->flush.flush_context(iommu, 0, 0, 0, | ||
2664 | DMA_CCMD_GLOBAL_INVL, 0); | ||
2665 | iommu->flush.flush_iotlb(iommu, 0, 0, 0, | ||
2666 | DMA_TLB_GLOBAL_FLUSH, 0); | ||
2667 | } | ||
2668 | } | ||
2669 | |||
2670 | static int iommu_suspend(struct sys_device *dev, pm_message_t state) | ||
2671 | { | ||
2672 | struct dmar_drhd_unit *drhd; | ||
2673 | struct intel_iommu *iommu = NULL; | ||
2674 | unsigned long flag; | ||
2675 | |||
2676 | for_each_active_iommu(iommu, drhd) { | ||
2677 | iommu->iommu_state = kzalloc(sizeof(u32) * MAX_SR_DMAR_REGS, | ||
2678 | GFP_ATOMIC); | ||
2679 | if (!iommu->iommu_state) | ||
2680 | goto nomem; | ||
2681 | } | ||
2682 | |||
2683 | iommu_flush_all(); | ||
2684 | |||
2685 | for_each_active_iommu(iommu, drhd) { | ||
2686 | iommu_disable_translation(iommu); | ||
2687 | |||
2688 | spin_lock_irqsave(&iommu->register_lock, flag); | ||
2689 | |||
2690 | iommu->iommu_state[SR_DMAR_FECTL_REG] = | ||
2691 | readl(iommu->reg + DMAR_FECTL_REG); | ||
2692 | iommu->iommu_state[SR_DMAR_FEDATA_REG] = | ||
2693 | readl(iommu->reg + DMAR_FEDATA_REG); | ||
2694 | iommu->iommu_state[SR_DMAR_FEADDR_REG] = | ||
2695 | readl(iommu->reg + DMAR_FEADDR_REG); | ||
2696 | iommu->iommu_state[SR_DMAR_FEUADDR_REG] = | ||
2697 | readl(iommu->reg + DMAR_FEUADDR_REG); | ||
2698 | |||
2699 | spin_unlock_irqrestore(&iommu->register_lock, flag); | ||
2700 | } | ||
2701 | return 0; | ||
2702 | |||
2703 | nomem: | ||
2704 | for_each_active_iommu(iommu, drhd) | ||
2705 | kfree(iommu->iommu_state); | ||
2706 | |||
2707 | return -ENOMEM; | ||
2708 | } | ||
2709 | |||
2710 | static int iommu_resume(struct sys_device *dev) | ||
2711 | { | ||
2712 | struct dmar_drhd_unit *drhd; | ||
2713 | struct intel_iommu *iommu = NULL; | ||
2714 | unsigned long flag; | ||
2715 | |||
2716 | if (init_iommu_hw()) { | ||
2717 | WARN(1, "IOMMU setup failed, DMAR can not resume!\n"); | ||
2718 | return -EIO; | ||
2719 | } | ||
2720 | |||
2721 | for_each_active_iommu(iommu, drhd) { | ||
2722 | |||
2723 | spin_lock_irqsave(&iommu->register_lock, flag); | ||
2724 | |||
2725 | writel(iommu->iommu_state[SR_DMAR_FECTL_REG], | ||
2726 | iommu->reg + DMAR_FECTL_REG); | ||
2727 | writel(iommu->iommu_state[SR_DMAR_FEDATA_REG], | ||
2728 | iommu->reg + DMAR_FEDATA_REG); | ||
2729 | writel(iommu->iommu_state[SR_DMAR_FEADDR_REG], | ||
2730 | iommu->reg + DMAR_FEADDR_REG); | ||
2731 | writel(iommu->iommu_state[SR_DMAR_FEUADDR_REG], | ||
2732 | iommu->reg + DMAR_FEUADDR_REG); | ||
2733 | |||
2734 | spin_unlock_irqrestore(&iommu->register_lock, flag); | ||
2735 | } | ||
2736 | |||
2737 | for_each_active_iommu(iommu, drhd) | ||
2738 | kfree(iommu->iommu_state); | ||
2739 | |||
2740 | return 0; | ||
2741 | } | ||
2742 | |||
2743 | static struct sysdev_class iommu_sysclass = { | ||
2744 | .name = "iommu", | ||
2745 | .resume = iommu_resume, | ||
2746 | .suspend = iommu_suspend, | ||
2747 | }; | ||
2748 | |||
2749 | static struct sys_device device_iommu = { | ||
2750 | .cls = &iommu_sysclass, | ||
2751 | }; | ||
2752 | |||
2753 | static int __init init_iommu_sysfs(void) | ||
2754 | { | ||
2755 | int error; | ||
2756 | |||
2757 | error = sysdev_class_register(&iommu_sysclass); | ||
2758 | if (error) | ||
2759 | return error; | ||
2760 | |||
2761 | error = sysdev_register(&device_iommu); | ||
2762 | if (error) | ||
2763 | sysdev_class_unregister(&iommu_sysclass); | ||
2764 | |||
2765 | return error; | ||
2766 | } | ||
2767 | |||
2768 | #else | ||
2769 | static int __init init_iommu_sysfs(void) | ||
2770 | { | ||
2771 | return 0; | ||
2772 | } | ||
2773 | #endif /* CONFIG_PM */ | ||
2774 | |||
2600 | int __init intel_iommu_init(void) | 2775 | int __init intel_iommu_init(void) |
2601 | { | 2776 | { |
2602 | int ret = 0; | 2777 | int ret = 0; |
@@ -2632,6 +2807,7 @@ int __init intel_iommu_init(void) | |||
2632 | init_timer(&unmap_timer); | 2807 | init_timer(&unmap_timer); |
2633 | force_iommu = 1; | 2808 | force_iommu = 1; |
2634 | dma_ops = &intel_dma_ops; | 2809 | dma_ops = &intel_dma_ops; |
2810 | init_iommu_sysfs(); | ||
2635 | 2811 | ||
2636 | register_iommu(&intel_iommu_ops); | 2812 | register_iommu(&intel_iommu_ops); |
2637 | 2813 | ||
@@ -2648,6 +2824,7 @@ static int vm_domain_add_dev_info(struct dmar_domain *domain, | |||
2648 | if (!info) | 2824 | if (!info) |
2649 | return -ENOMEM; | 2825 | return -ENOMEM; |
2650 | 2826 | ||
2827 | info->segment = pci_domain_nr(pdev->bus); | ||
2651 | info->bus = pdev->bus->number; | 2828 | info->bus = pdev->bus->number; |
2652 | info->devfn = pdev->devfn; | 2829 | info->devfn = pdev->devfn; |
2653 | info->dev = pdev; | 2830 | info->dev = pdev; |
@@ -2677,15 +2854,15 @@ static void iommu_detach_dependent_devices(struct intel_iommu *iommu, | |||
2677 | parent = pdev->bus->self; | 2854 | parent = pdev->bus->self; |
2678 | while (parent != tmp) { | 2855 | while (parent != tmp) { |
2679 | iommu_detach_dev(iommu, parent->bus->number, | 2856 | iommu_detach_dev(iommu, parent->bus->number, |
2680 | parent->devfn); | 2857 | parent->devfn); |
2681 | parent = parent->bus->self; | 2858 | parent = parent->bus->self; |
2682 | } | 2859 | } |
2683 | if (tmp->is_pcie) /* this is a PCIE-to-PCI bridge */ | 2860 | if (tmp->is_pcie) /* this is a PCIE-to-PCI bridge */ |
2684 | iommu_detach_dev(iommu, | 2861 | iommu_detach_dev(iommu, |
2685 | tmp->subordinate->number, 0); | 2862 | tmp->subordinate->number, 0); |
2686 | else /* this is a legacy PCI bridge */ | 2863 | else /* this is a legacy PCI bridge */ |
2687 | iommu_detach_dev(iommu, | 2864 | iommu_detach_dev(iommu, tmp->bus->number, |
2688 | tmp->bus->number, tmp->devfn); | 2865 | tmp->devfn); |
2689 | } | 2866 | } |
2690 | } | 2867 | } |
2691 | 2868 | ||
@@ -2698,13 +2875,15 @@ static void vm_domain_remove_one_dev_info(struct dmar_domain *domain, | |||
2698 | int found = 0; | 2875 | int found = 0; |
2699 | struct list_head *entry, *tmp; | 2876 | struct list_head *entry, *tmp; |
2700 | 2877 | ||
2701 | iommu = device_to_iommu(pdev->bus->number, pdev->devfn); | 2878 | iommu = device_to_iommu(pci_domain_nr(pdev->bus), pdev->bus->number, |
2879 | pdev->devfn); | ||
2702 | if (!iommu) | 2880 | if (!iommu) |
2703 | return; | 2881 | return; |
2704 | 2882 | ||
2705 | spin_lock_irqsave(&device_domain_lock, flags); | 2883 | spin_lock_irqsave(&device_domain_lock, flags); |
2706 | list_for_each_safe(entry, tmp, &domain->devices) { | 2884 | list_for_each_safe(entry, tmp, &domain->devices) { |
2707 | info = list_entry(entry, struct device_domain_info, link); | 2885 | info = list_entry(entry, struct device_domain_info, link); |
2886 | /* No need to compare PCI domain; it has to be the same */ | ||
2708 | if (info->bus == pdev->bus->number && | 2887 | if (info->bus == pdev->bus->number && |
2709 | info->devfn == pdev->devfn) { | 2888 | info->devfn == pdev->devfn) { |
2710 | list_del(&info->link); | 2889 | list_del(&info->link); |
@@ -2729,7 +2908,8 @@ static void vm_domain_remove_one_dev_info(struct dmar_domain *domain, | |||
2729 | * owned by this domain, clear this iommu in iommu_bmp | 2908 | * owned by this domain, clear this iommu in iommu_bmp |
2730 | * update iommu count and coherency | 2909 | * update iommu count and coherency |
2731 | */ | 2910 | */ |
2732 | if (device_to_iommu(info->bus, info->devfn) == iommu) | 2911 | if (iommu == device_to_iommu(info->segment, info->bus, |
2912 | info->devfn)) | ||
2733 | found = 1; | 2913 | found = 1; |
2734 | } | 2914 | } |
2735 | 2915 | ||
@@ -2762,7 +2942,7 @@ static void vm_domain_remove_all_dev_info(struct dmar_domain *domain) | |||
2762 | 2942 | ||
2763 | spin_unlock_irqrestore(&device_domain_lock, flags1); | 2943 | spin_unlock_irqrestore(&device_domain_lock, flags1); |
2764 | 2944 | ||
2765 | iommu = device_to_iommu(info->bus, info->devfn); | 2945 | iommu = device_to_iommu(info->segment, info->bus, info->devfn); |
2766 | iommu_detach_dev(iommu, info->bus, info->devfn); | 2946 | iommu_detach_dev(iommu, info->bus, info->devfn); |
2767 | iommu_detach_dependent_devices(iommu, info->dev); | 2947 | iommu_detach_dependent_devices(iommu, info->dev); |
2768 | 2948 | ||
@@ -2950,7 +3130,8 @@ static int intel_iommu_attach_device(struct iommu_domain *domain, | |||
2950 | } | 3130 | } |
2951 | } | 3131 | } |
2952 | 3132 | ||
2953 | iommu = device_to_iommu(pdev->bus->number, pdev->devfn); | 3133 | iommu = device_to_iommu(pci_domain_nr(pdev->bus), pdev->bus->number, |
3134 | pdev->devfn); | ||
2954 | if (!iommu) | 3135 | if (!iommu) |
2955 | return -ENODEV; | 3136 | return -ENODEV; |
2956 | 3137 | ||
diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c index b041a409f4a7..f5e0ea724a6f 100644 --- a/drivers/pci/intr_remapping.c +++ b/drivers/pci/intr_remapping.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <asm/cpu.h> | 9 | #include <asm/cpu.h> |
10 | #include <linux/intel-iommu.h> | 10 | #include <linux/intel-iommu.h> |
11 | #include "intr_remapping.h" | 11 | #include "intr_remapping.h" |
12 | #include <acpi/acpi.h> | ||
12 | 13 | ||
13 | static struct ioapic_scope ir_ioapic[MAX_IO_APICS]; | 14 | static struct ioapic_scope ir_ioapic[MAX_IO_APICS]; |
14 | static int ir_ioapic_num; | 15 | static int ir_ioapic_num; |
@@ -415,12 +416,27 @@ static void iommu_set_intr_remapping(struct intel_iommu *iommu, int mode) | |||
415 | 416 | ||
416 | /* Set interrupt-remapping table pointer */ | 417 | /* Set interrupt-remapping table pointer */ |
417 | cmd = iommu->gcmd | DMA_GCMD_SIRTP; | 418 | cmd = iommu->gcmd | DMA_GCMD_SIRTP; |
419 | iommu->gcmd |= DMA_GCMD_SIRTP; | ||
418 | writel(cmd, iommu->reg + DMAR_GCMD_REG); | 420 | writel(cmd, iommu->reg + DMAR_GCMD_REG); |
419 | 421 | ||
420 | IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, | 422 | IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, |
421 | readl, (sts & DMA_GSTS_IRTPS), sts); | 423 | readl, (sts & DMA_GSTS_IRTPS), sts); |
422 | spin_unlock_irqrestore(&iommu->register_lock, flags); | 424 | spin_unlock_irqrestore(&iommu->register_lock, flags); |
423 | 425 | ||
426 | if (mode == 0) { | ||
427 | spin_lock_irqsave(&iommu->register_lock, flags); | ||
428 | |||
429 | /* enable comaptiblity format interrupt pass through */ | ||
430 | cmd = iommu->gcmd | DMA_GCMD_CFI; | ||
431 | iommu->gcmd |= DMA_GCMD_CFI; | ||
432 | writel(cmd, iommu->reg + DMAR_GCMD_REG); | ||
433 | |||
434 | IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, | ||
435 | readl, (sts & DMA_GSTS_CFIS), sts); | ||
436 | |||
437 | spin_unlock_irqrestore(&iommu->register_lock, flags); | ||
438 | } | ||
439 | |||
424 | /* | 440 | /* |
425 | * global invalidation of interrupt entry cache before enabling | 441 | * global invalidation of interrupt entry cache before enabling |
426 | * interrupt-remapping. | 442 | * interrupt-remapping. |
@@ -470,7 +486,7 @@ static int setup_intr_remapping(struct intel_iommu *iommu, int mode) | |||
470 | /* | 486 | /* |
471 | * Disable Interrupt Remapping. | 487 | * Disable Interrupt Remapping. |
472 | */ | 488 | */ |
473 | static void disable_intr_remapping(struct intel_iommu *iommu) | 489 | static void iommu_disable_intr_remapping(struct intel_iommu *iommu) |
474 | { | 490 | { |
475 | unsigned long flags; | 491 | unsigned long flags; |
476 | u32 sts; | 492 | u32 sts; |
@@ -478,6 +494,12 @@ static void disable_intr_remapping(struct intel_iommu *iommu) | |||
478 | if (!ecap_ir_support(iommu->ecap)) | 494 | if (!ecap_ir_support(iommu->ecap)) |
479 | return; | 495 | return; |
480 | 496 | ||
497 | /* | ||
498 | * global invalidation of interrupt entry cache before disabling | ||
499 | * interrupt-remapping. | ||
500 | */ | ||
501 | qi_global_iec(iommu); | ||
502 | |||
481 | spin_lock_irqsave(&iommu->register_lock, flags); | 503 | spin_lock_irqsave(&iommu->register_lock, flags); |
482 | 504 | ||
483 | sts = dmar_readq(iommu->reg + DMAR_GSTS_REG); | 505 | sts = dmar_readq(iommu->reg + DMAR_GSTS_REG); |
@@ -503,6 +525,13 @@ int __init enable_intr_remapping(int eim) | |||
503 | struct intel_iommu *iommu = drhd->iommu; | 525 | struct intel_iommu *iommu = drhd->iommu; |
504 | 526 | ||
505 | /* | 527 | /* |
528 | * If the queued invalidation is already initialized, | ||
529 | * shouldn't disable it. | ||
530 | */ | ||
531 | if (iommu->qi) | ||
532 | continue; | ||
533 | |||
534 | /* | ||
506 | * Clear previous faults. | 535 | * Clear previous faults. |
507 | */ | 536 | */ |
508 | dmar_fault(-1, iommu); | 537 | dmar_fault(-1, iommu); |
@@ -511,7 +540,7 @@ int __init enable_intr_remapping(int eim) | |||
511 | * Disable intr remapping and queued invalidation, if already | 540 | * Disable intr remapping and queued invalidation, if already |
512 | * enabled prior to OS handover. | 541 | * enabled prior to OS handover. |
513 | */ | 542 | */ |
514 | disable_intr_remapping(iommu); | 543 | iommu_disable_intr_remapping(iommu); |
515 | 544 | ||
516 | dmar_disable_qi(iommu); | 545 | dmar_disable_qi(iommu); |
517 | } | 546 | } |
@@ -639,3 +668,54 @@ int __init parse_ioapics_under_ir(void) | |||
639 | 668 | ||
640 | return ir_supported; | 669 | return ir_supported; |
641 | } | 670 | } |
671 | |||
672 | void disable_intr_remapping(void) | ||
673 | { | ||
674 | struct dmar_drhd_unit *drhd; | ||
675 | struct intel_iommu *iommu = NULL; | ||
676 | |||
677 | /* | ||
678 | * Disable Interrupt-remapping for all the DRHD's now. | ||
679 | */ | ||
680 | for_each_iommu(iommu, drhd) { | ||
681 | if (!ecap_ir_support(iommu->ecap)) | ||
682 | continue; | ||
683 | |||
684 | iommu_disable_intr_remapping(iommu); | ||
685 | } | ||
686 | } | ||
687 | |||
688 | int reenable_intr_remapping(int eim) | ||
689 | { | ||
690 | struct dmar_drhd_unit *drhd; | ||
691 | int setup = 0; | ||
692 | struct intel_iommu *iommu = NULL; | ||
693 | |||
694 | for_each_iommu(iommu, drhd) | ||
695 | if (iommu->qi) | ||
696 | dmar_reenable_qi(iommu); | ||
697 | |||
698 | /* | ||
699 | * Setup Interrupt-remapping for all the DRHD's now. | ||
700 | */ | ||
701 | for_each_iommu(iommu, drhd) { | ||
702 | if (!ecap_ir_support(iommu->ecap)) | ||
703 | continue; | ||
704 | |||
705 | /* Set up interrupt remapping for iommu.*/ | ||
706 | iommu_set_intr_remapping(iommu, eim); | ||
707 | setup = 1; | ||
708 | } | ||
709 | |||
710 | if (!setup) | ||
711 | goto error; | ||
712 | |||
713 | return 0; | ||
714 | |||
715 | error: | ||
716 | /* | ||
717 | * handle error condition gracefully here! | ||
718 | */ | ||
719 | return -1; | ||
720 | } | ||
721 | |||
diff --git a/include/linux/dmar.h b/include/linux/dmar.h index 2f3427468956..e397dc342cda 100644 --- a/include/linux/dmar.h +++ b/include/linux/dmar.h | |||
@@ -34,6 +34,7 @@ struct dmar_drhd_unit { | |||
34 | u64 reg_base_addr; /* register base address*/ | 34 | u64 reg_base_addr; /* register base address*/ |
35 | struct pci_dev **devices; /* target device array */ | 35 | struct pci_dev **devices; /* target device array */ |
36 | int devices_cnt; /* target device count */ | 36 | int devices_cnt; /* target device count */ |
37 | u16 segment; /* PCI domain */ | ||
37 | u8 ignored:1; /* ignore drhd */ | 38 | u8 ignored:1; /* ignore drhd */ |
38 | u8 include_all:1; | 39 | u8 include_all:1; |
39 | struct intel_iommu *iommu; | 40 | struct intel_iommu *iommu; |
@@ -44,6 +45,14 @@ extern struct list_head dmar_drhd_units; | |||
44 | #define for_each_drhd_unit(drhd) \ | 45 | #define for_each_drhd_unit(drhd) \ |
45 | list_for_each_entry(drhd, &dmar_drhd_units, list) | 46 | list_for_each_entry(drhd, &dmar_drhd_units, list) |
46 | 47 | ||
48 | #define for_each_active_iommu(i, drhd) \ | ||
49 | list_for_each_entry(drhd, &dmar_drhd_units, list) \ | ||
50 | if (i=drhd->iommu, drhd->ignored) {} else | ||
51 | |||
52 | #define for_each_iommu(i, drhd) \ | ||
53 | list_for_each_entry(drhd, &dmar_drhd_units, list) \ | ||
54 | if (i=drhd->iommu, 0) {} else | ||
55 | |||
47 | extern int dmar_table_init(void); | 56 | extern int dmar_table_init(void); |
48 | extern int dmar_dev_scope_init(void); | 57 | extern int dmar_dev_scope_init(void); |
49 | 58 | ||
@@ -100,6 +109,8 @@ struct irte { | |||
100 | #ifdef CONFIG_INTR_REMAP | 109 | #ifdef CONFIG_INTR_REMAP |
101 | extern int intr_remapping_enabled; | 110 | extern int intr_remapping_enabled; |
102 | extern int enable_intr_remapping(int); | 111 | extern int enable_intr_remapping(int); |
112 | extern void disable_intr_remapping(void); | ||
113 | extern int reenable_intr_remapping(int); | ||
103 | 114 | ||
104 | extern int get_irte(int irq, struct irte *entry); | 115 | extern int get_irte(int irq, struct irte *entry); |
105 | extern int modify_irte(int irq, struct irte *irte_modified); | 116 | extern int modify_irte(int irq, struct irte *irte_modified); |
diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h index 77214ead1a36..aa8c53171233 100644 --- a/include/linux/intel-iommu.h +++ b/include/linux/intel-iommu.h | |||
@@ -164,6 +164,7 @@ static inline void dmar_writeq(void __iomem *addr, u64 val) | |||
164 | #define DMA_GCMD_QIE (((u32)1) << 26) | 164 | #define DMA_GCMD_QIE (((u32)1) << 26) |
165 | #define DMA_GCMD_SIRTP (((u32)1) << 24) | 165 | #define DMA_GCMD_SIRTP (((u32)1) << 24) |
166 | #define DMA_GCMD_IRE (((u32) 1) << 25) | 166 | #define DMA_GCMD_IRE (((u32) 1) << 25) |
167 | #define DMA_GCMD_CFI (((u32) 1) << 23) | ||
167 | 168 | ||
168 | /* GSTS_REG */ | 169 | /* GSTS_REG */ |
169 | #define DMA_GSTS_TES (((u32)1) << 31) | 170 | #define DMA_GSTS_TES (((u32)1) << 31) |
@@ -174,6 +175,7 @@ static inline void dmar_writeq(void __iomem *addr, u64 val) | |||
174 | #define DMA_GSTS_QIES (((u32)1) << 26) | 175 | #define DMA_GSTS_QIES (((u32)1) << 26) |
175 | #define DMA_GSTS_IRTPS (((u32)1) << 24) | 176 | #define DMA_GSTS_IRTPS (((u32)1) << 24) |
176 | #define DMA_GSTS_IRES (((u32)1) << 25) | 177 | #define DMA_GSTS_IRES (((u32)1) << 25) |
178 | #define DMA_GSTS_CFIS (((u32)1) << 23) | ||
177 | 179 | ||
178 | /* CCMD_REG */ | 180 | /* CCMD_REG */ |
179 | #define DMA_CCMD_ICC (((u64)1) << 63) | 181 | #define DMA_CCMD_ICC (((u64)1) << 63) |
@@ -284,6 +286,14 @@ struct iommu_flush { | |||
284 | unsigned int size_order, u64 type, int non_present_entry_flush); | 286 | unsigned int size_order, u64 type, int non_present_entry_flush); |
285 | }; | 287 | }; |
286 | 288 | ||
289 | enum { | ||
290 | SR_DMAR_FECTL_REG, | ||
291 | SR_DMAR_FEDATA_REG, | ||
292 | SR_DMAR_FEADDR_REG, | ||
293 | SR_DMAR_FEUADDR_REG, | ||
294 | MAX_SR_DMAR_REGS | ||
295 | }; | ||
296 | |||
287 | struct intel_iommu { | 297 | struct intel_iommu { |
288 | void __iomem *reg; /* Pointer to hardware regs, virtual addr */ | 298 | void __iomem *reg; /* Pointer to hardware regs, virtual addr */ |
289 | u64 cap; | 299 | u64 cap; |
@@ -304,6 +314,8 @@ struct intel_iommu { | |||
304 | struct iommu_flush flush; | 314 | struct iommu_flush flush; |
305 | #endif | 315 | #endif |
306 | struct q_inval *qi; /* Queued invalidation info */ | 316 | struct q_inval *qi; /* Queued invalidation info */ |
317 | u32 *iommu_state; /* Store iommu states between suspend and resume.*/ | ||
318 | |||
307 | #ifdef CONFIG_INTR_REMAP | 319 | #ifdef CONFIG_INTR_REMAP |
308 | struct ir_table *ir_table; /* Interrupt remapping info */ | 320 | struct ir_table *ir_table; /* Interrupt remapping info */ |
309 | #endif | 321 | #endif |
@@ -322,6 +334,7 @@ extern int alloc_iommu(struct dmar_drhd_unit *drhd); | |||
322 | extern void free_iommu(struct intel_iommu *iommu); | 334 | extern void free_iommu(struct intel_iommu *iommu); |
323 | extern int dmar_enable_qi(struct intel_iommu *iommu); | 335 | extern int dmar_enable_qi(struct intel_iommu *iommu); |
324 | extern void dmar_disable_qi(struct intel_iommu *iommu); | 336 | extern void dmar_disable_qi(struct intel_iommu *iommu); |
337 | extern int dmar_reenable_qi(struct intel_iommu *iommu); | ||
325 | extern void qi_global_iec(struct intel_iommu *iommu); | 338 | extern void qi_global_iec(struct intel_iommu *iommu); |
326 | 339 | ||
327 | extern int qi_flush_context(struct intel_iommu *iommu, u16 did, u16 sid, | 340 | extern int qi_flush_context(struct intel_iommu *iommu, u16 did, u16 sid, |