diff options
-rw-r--r-- | arch/x86/include/asm/io_apic.h | 2 | ||||
-rw-r--r-- | arch/x86/include/asm/x86_init.h | 9 | ||||
-rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 41 | ||||
-rw-r--r-- | arch/x86/kernel/x86_init.c | 9 | ||||
-rw-r--r-- | drivers/iommu/irq_remapping.c | 31 |
5 files changed, 61 insertions, 31 deletions
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h index 73d8c5398ea9..d59e17232c4d 100644 --- a/arch/x86/include/asm/io_apic.h +++ b/arch/x86/include/asm/io_apic.h | |||
@@ -179,6 +179,7 @@ extern void __init native_io_apic_init_mappings(void); | |||
179 | extern unsigned int native_io_apic_read(unsigned int apic, unsigned int reg); | 179 | extern unsigned int native_io_apic_read(unsigned int apic, unsigned int reg); |
180 | extern void native_io_apic_write(unsigned int apic, unsigned int reg, unsigned int val); | 180 | extern void native_io_apic_write(unsigned int apic, unsigned int reg, unsigned int val); |
181 | extern void native_io_apic_modify(unsigned int apic, unsigned int reg, unsigned int val); | 181 | extern void native_io_apic_modify(unsigned int apic, unsigned int reg, unsigned int val); |
182 | extern void native_disable_io_apic(void); | ||
182 | 183 | ||
183 | static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg) | 184 | static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg) |
184 | { | 185 | { |
@@ -223,6 +224,7 @@ static inline void disable_ioapic_support(void) { } | |||
223 | #define native_io_apic_read NULL | 224 | #define native_io_apic_read NULL |
224 | #define native_io_apic_write NULL | 225 | #define native_io_apic_write NULL |
225 | #define native_io_apic_modify NULL | 226 | #define native_io_apic_modify NULL |
227 | #define native_disable_io_apic NULL | ||
226 | #endif | 228 | #endif |
227 | 229 | ||
228 | #endif /* _ASM_X86_IO_APIC_H */ | 230 | #endif /* _ASM_X86_IO_APIC_H */ |
diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h index 57693498519c..b1d2d6aefcc9 100644 --- a/arch/x86/include/asm/x86_init.h +++ b/arch/x86/include/asm/x86_init.h | |||
@@ -190,10 +190,11 @@ struct x86_msi_ops { | |||
190 | }; | 190 | }; |
191 | 191 | ||
192 | struct x86_io_apic_ops { | 192 | struct x86_io_apic_ops { |
193 | void (*init) (void); | 193 | void (*init) (void); |
194 | unsigned int (*read) (unsigned int apic, unsigned int reg); | 194 | unsigned int (*read) (unsigned int apic, unsigned int reg); |
195 | void (*write) (unsigned int apic, unsigned int reg, unsigned int value); | 195 | void (*write) (unsigned int apic, unsigned int reg, unsigned int value); |
196 | void (*modify)(unsigned int apic, unsigned int reg, unsigned int value); | 196 | void (*modify) (unsigned int apic, unsigned int reg, unsigned int value); |
197 | void (*disable)(void); | ||
197 | }; | 198 | }; |
198 | 199 | ||
199 | extern struct x86_init_ops x86_init; | 200 | extern struct x86_init_ops x86_init; |
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 2016f9dabd72..cd5f4d7cc163 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
@@ -1921,30 +1921,14 @@ void __init enable_IO_APIC(void) | |||
1921 | clear_IO_APIC(); | 1921 | clear_IO_APIC(); |
1922 | } | 1922 | } |
1923 | 1923 | ||
1924 | /* | 1924 | void native_disable_io_apic(void) |
1925 | * Not an __init, needed by the reboot code | ||
1926 | */ | ||
1927 | void disable_IO_APIC(void) | ||
1928 | { | 1925 | { |
1929 | /* | 1926 | /* |
1930 | * Clear the IO-APIC before rebooting: | ||
1931 | */ | ||
1932 | clear_IO_APIC(); | ||
1933 | |||
1934 | if (!legacy_pic->nr_legacy_irqs) | ||
1935 | return; | ||
1936 | |||
1937 | /* | ||
1938 | * If the i8259 is routed through an IOAPIC | 1927 | * If the i8259 is routed through an IOAPIC |
1939 | * Put that IOAPIC in virtual wire mode | 1928 | * Put that IOAPIC in virtual wire mode |
1940 | * so legacy interrupts can be delivered. | 1929 | * so legacy interrupts can be delivered. |
1941 | * | ||
1942 | * With interrupt-remapping, for now we will use virtual wire A mode, | ||
1943 | * as virtual wire B is little complex (need to configure both | ||
1944 | * IOAPIC RTE as well as interrupt-remapping table entry). | ||
1945 | * As this gets called during crash dump, keep this simple for now. | ||
1946 | */ | 1930 | */ |
1947 | if (ioapic_i8259.pin != -1 && !irq_remapping_enabled) { | 1931 | if (ioapic_i8259.pin != -1) { |
1948 | struct IO_APIC_route_entry entry; | 1932 | struct IO_APIC_route_entry entry; |
1949 | 1933 | ||
1950 | memset(&entry, 0, sizeof(entry)); | 1934 | memset(&entry, 0, sizeof(entry)); |
@@ -1964,12 +1948,25 @@ void disable_IO_APIC(void) | |||
1964 | ioapic_write_entry(ioapic_i8259.apic, ioapic_i8259.pin, entry); | 1948 | ioapic_write_entry(ioapic_i8259.apic, ioapic_i8259.pin, entry); |
1965 | } | 1949 | } |
1966 | 1950 | ||
1951 | if (cpu_has_apic || apic_from_smp_config()) | ||
1952 | disconnect_bsp_APIC(ioapic_i8259.pin != -1); | ||
1953 | |||
1954 | } | ||
1955 | |||
1956 | /* | ||
1957 | * Not an __init, needed by the reboot code | ||
1958 | */ | ||
1959 | void disable_IO_APIC(void) | ||
1960 | { | ||
1967 | /* | 1961 | /* |
1968 | * Use virtual wire A mode when interrupt remapping is enabled. | 1962 | * Clear the IO-APIC before rebooting: |
1969 | */ | 1963 | */ |
1970 | if (cpu_has_apic || apic_from_smp_config()) | 1964 | clear_IO_APIC(); |
1971 | disconnect_bsp_APIC(!irq_remapping_enabled && | 1965 | |
1972 | ioapic_i8259.pin != -1); | 1966 | if (!legacy_pic->nr_legacy_irqs) |
1967 | return; | ||
1968 | |||
1969 | x86_io_apic_ops.disable(); | ||
1973 | } | 1970 | } |
1974 | 1971 | ||
1975 | #ifdef CONFIG_X86_32 | 1972 | #ifdef CONFIG_X86_32 |
diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c index 7a3d075a814a..754524acc845 100644 --- a/arch/x86/kernel/x86_init.c +++ b/arch/x86/kernel/x86_init.c | |||
@@ -118,8 +118,9 @@ struct x86_msi_ops x86_msi = { | |||
118 | }; | 118 | }; |
119 | 119 | ||
120 | struct x86_io_apic_ops x86_io_apic_ops = { | 120 | struct x86_io_apic_ops x86_io_apic_ops = { |
121 | .init = native_io_apic_init_mappings, | 121 | .init = native_io_apic_init_mappings, |
122 | .read = native_io_apic_read, | 122 | .read = native_io_apic_read, |
123 | .write = native_io_apic_write, | 123 | .write = native_io_apic_write, |
124 | .modify = native_io_apic_modify, | 124 | .modify = native_io_apic_modify, |
125 | .disable = native_disable_io_apic, | ||
125 | }; | 126 | }; |
diff --git a/drivers/iommu/irq_remapping.c b/drivers/iommu/irq_remapping.c index 19381b90e619..db3dcaf4ddf0 100644 --- a/drivers/iommu/irq_remapping.c +++ b/drivers/iommu/irq_remapping.c | |||
@@ -1,3 +1,4 @@ | |||
1 | #include <linux/cpumask.h> | ||
1 | #include <linux/kernel.h> | 2 | #include <linux/kernel.h> |
2 | #include <linux/string.h> | 3 | #include <linux/string.h> |
3 | #include <linux/cpumask.h> | 4 | #include <linux/cpumask.h> |
@@ -6,6 +7,9 @@ | |||
6 | 7 | ||
7 | #include <asm/hw_irq.h> | 8 | #include <asm/hw_irq.h> |
8 | #include <asm/irq_remapping.h> | 9 | #include <asm/irq_remapping.h> |
10 | #include <asm/processor.h> | ||
11 | #include <asm/x86_init.h> | ||
12 | #include <asm/apic.h> | ||
9 | 13 | ||
10 | #include "irq_remapping.h" | 14 | #include "irq_remapping.h" |
11 | 15 | ||
@@ -17,6 +21,24 @@ int no_x2apic_optout; | |||
17 | 21 | ||
18 | static struct irq_remap_ops *remap_ops; | 22 | static struct irq_remap_ops *remap_ops; |
19 | 23 | ||
24 | static void irq_remapping_disable_io_apic(void) | ||
25 | { | ||
26 | /* | ||
27 | * With interrupt-remapping, for now we will use virtual wire A | ||
28 | * mode, as virtual wire B is little complex (need to configure | ||
29 | * both IOAPIC RTE as well as interrupt-remapping table entry). | ||
30 | * As this gets called during crash dump, keep this simple for | ||
31 | * now. | ||
32 | */ | ||
33 | if (cpu_has_apic || apic_from_smp_config()) | ||
34 | disconnect_bsp_APIC(0); | ||
35 | } | ||
36 | |||
37 | static void __init irq_remapping_modify_x86_ops(void) | ||
38 | { | ||
39 | x86_io_apic_ops.disable = irq_remapping_disable_io_apic; | ||
40 | } | ||
41 | |||
20 | static __init int setup_nointremap(char *str) | 42 | static __init int setup_nointremap(char *str) |
21 | { | 43 | { |
22 | disable_irq_remap = 1; | 44 | disable_irq_remap = 1; |
@@ -79,10 +101,17 @@ int __init irq_remapping_prepare(void) | |||
79 | 101 | ||
80 | int __init irq_remapping_enable(void) | 102 | int __init irq_remapping_enable(void) |
81 | { | 103 | { |
104 | int ret; | ||
105 | |||
82 | if (!remap_ops || !remap_ops->enable) | 106 | if (!remap_ops || !remap_ops->enable) |
83 | return -ENODEV; | 107 | return -ENODEV; |
84 | 108 | ||
85 | return remap_ops->enable(); | 109 | ret = remap_ops->enable(); |
110 | |||
111 | if (irq_remapping_enabled) | ||
112 | irq_remapping_modify_x86_ops(); | ||
113 | |||
114 | return ret; | ||
86 | } | 115 | } |
87 | 116 | ||
88 | void irq_remapping_disable(void) | 117 | void irq_remapping_disable(void) |