aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoerg Roedel <joro@8bytes.org>2012-09-26 06:44:35 -0400
committerJoerg Roedel <joro@8bytes.org>2013-01-28 04:48:30 -0500
commit1c4248ca4e783e47cc34e313d9f82b4ea52774cc (patch)
treee64dba1b95ad1ed8bbf6b3bb6cd0ec893d3c7d9c
parent336224ba5e4fb42a95d02ab0aa0fdff21649bb38 (diff)
x86, io_apic: Introduce x86_io_apic_ops.disable()
This function pointer is used to call a system-specific function for disabling the IO-APIC. Currently this is used for IRQ remapping which has its own disable routine. Also introduce the necessary infrastructure in the interrupt remapping code to overwrite this and other function pointers as necessary by interrupt remapping. Signed-off-by: Joerg Roedel <joro@8bytes.org> Acked-by: Sebastian Andrzej Siewior <sebastian@breakpoint.cc> Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
-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)