aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/include/asm/io_apic.h2
-rw-r--r--arch/x86/include/asm/x86_init.h9
-rw-r--r--arch/x86/kernel/apic/io_apic.c41
-rw-r--r--arch/x86/kernel/x86_init.c9
-rw-r--r--drivers/iommu/irq_remapping.c31
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);
179extern unsigned int native_io_apic_read(unsigned int apic, unsigned int reg); 179extern unsigned int native_io_apic_read(unsigned int apic, unsigned int reg);
180extern void native_io_apic_write(unsigned int apic, unsigned int reg, unsigned int val); 180extern void native_io_apic_write(unsigned int apic, unsigned int reg, unsigned int val);
181extern void native_io_apic_modify(unsigned int apic, unsigned int reg, unsigned int val); 181extern void native_io_apic_modify(unsigned int apic, unsigned int reg, unsigned int val);
182extern void native_disable_io_apic(void);
182 183
183static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg) 184static 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
192struct x86_io_apic_ops { 192struct 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
199extern struct x86_init_ops x86_init; 200extern 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/* 1924void native_disable_io_apic(void)
1925 * Not an __init, needed by the reboot code
1926 */
1927void 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 */
1959void 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
120struct x86_io_apic_ops x86_io_apic_ops = { 120struct 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
18static struct irq_remap_ops *remap_ops; 22static struct irq_remap_ops *remap_ops;
19 23
24static 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
37static void __init irq_remapping_modify_x86_ops(void)
38{
39 x86_io_apic_ops.disable = irq_remapping_disable_io_apic;
40}
41
20static __init int setup_nointremap(char *str) 42static __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
80int __init irq_remapping_enable(void) 102int __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
88void irq_remapping_disable(void) 117void irq_remapping_disable(void)