diff options
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/Kconfig | 5 | ||||
-rw-r--r-- | arch/x86/include/asm/mce.h | 2 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/mcheck/Makefile | 1 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce_amd_64.c | 15 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/mcheck/threshold.c | 24 |
5 files changed, 38 insertions, 9 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 9c39095b33fc..52d7013785fe 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -751,6 +751,11 @@ config X86_MCE_AMD | |||
751 | Additional support for AMD specific MCE features such as | 751 | Additional support for AMD specific MCE features such as |
752 | the DRAM Error Threshold. | 752 | the DRAM Error Threshold. |
753 | 753 | ||
754 | config X86_MCE_THRESHOLD | ||
755 | depends on X86_MCE_AMD || X86_MCE_INTEL | ||
756 | bool | ||
757 | default y | ||
758 | |||
754 | config X86_MCE_NONFATAL | 759 | config X86_MCE_NONFATAL |
755 | tristate "Check for non-fatal errors on AMD Athlon/Duron / Intel Pentium 4" | 760 | tristate "Check for non-fatal errors on AMD Athlon/Duron / Intel Pentium 4" |
756 | depends on X86_32 && X86_MCE | 761 | depends on X86_32 && X86_MCE |
diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h index 39136c497c5e..125cd8714622 100644 --- a/arch/x86/include/asm/mce.h +++ b/arch/x86/include/asm/mce.h | |||
@@ -135,5 +135,7 @@ extern void mcheck_init(struct cpuinfo_x86 *c); | |||
135 | #define mcheck_init(c) do { } while (0) | 135 | #define mcheck_init(c) do { } while (0) |
136 | #endif | 136 | #endif |
137 | 137 | ||
138 | extern void (*mce_threshold_vector)(void); | ||
139 | |||
138 | #endif /* __KERNEL__ */ | 140 | #endif /* __KERNEL__ */ |
139 | #endif /* _ASM_X86_MCE_H */ | 141 | #endif /* _ASM_X86_MCE_H */ |
diff --git a/arch/x86/kernel/cpu/mcheck/Makefile b/arch/x86/kernel/cpu/mcheck/Makefile index d7d2323bbb69..b2f89829bbe8 100644 --- a/arch/x86/kernel/cpu/mcheck/Makefile +++ b/arch/x86/kernel/cpu/mcheck/Makefile | |||
@@ -4,3 +4,4 @@ obj-$(CONFIG_X86_32) += k7.o p4.o p5.o p6.o winchip.o | |||
4 | obj-$(CONFIG_X86_MCE_INTEL) += mce_intel_64.o | 4 | obj-$(CONFIG_X86_MCE_INTEL) += mce_intel_64.o |
5 | obj-$(CONFIG_X86_MCE_AMD) += mce_amd_64.o | 5 | obj-$(CONFIG_X86_MCE_AMD) += mce_amd_64.o |
6 | obj-$(CONFIG_X86_MCE_NONFATAL) += non-fatal.o | 6 | obj-$(CONFIG_X86_MCE_NONFATAL) += non-fatal.o |
7 | obj-$(CONFIG_X86_MCE_THRESHOLD) += threshold.o | ||
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd_64.c b/arch/x86/kernel/cpu/mcheck/mce_amd_64.c index e82c8208b81e..49705be98209 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd_64.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd_64.c | |||
@@ -79,6 +79,8 @@ static unsigned char shared_bank[NR_BANKS] = { | |||
79 | 79 | ||
80 | static DEFINE_PER_CPU(unsigned char, bank_map); /* see which banks are on */ | 80 | static DEFINE_PER_CPU(unsigned char, bank_map); /* see which banks are on */ |
81 | 81 | ||
82 | static void amd_threshold_interrupt(void); | ||
83 | |||
82 | /* | 84 | /* |
83 | * CPU Initialization | 85 | * CPU Initialization |
84 | */ | 86 | */ |
@@ -174,6 +176,8 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c) | |||
174 | tr.reset = 0; | 176 | tr.reset = 0; |
175 | tr.old_limit = 0; | 177 | tr.old_limit = 0; |
176 | threshold_restart_bank(&tr); | 178 | threshold_restart_bank(&tr); |
179 | |||
180 | mce_threshold_vector = amd_threshold_interrupt; | ||
177 | } | 181 | } |
178 | } | 182 | } |
179 | } | 183 | } |
@@ -187,16 +191,12 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c) | |||
187 | * the interrupt goes off when error_count reaches threshold_limit. | 191 | * the interrupt goes off when error_count reaches threshold_limit. |
188 | * the handler will simply log mcelog w/ software defined bank number. | 192 | * the handler will simply log mcelog w/ software defined bank number. |
189 | */ | 193 | */ |
190 | asmlinkage void mce_threshold_interrupt(void) | 194 | static void amd_threshold_interrupt(void) |
191 | { | 195 | { |
192 | unsigned int bank, block; | 196 | unsigned int bank, block; |
193 | struct mce m; | 197 | struct mce m; |
194 | u32 low = 0, high = 0, address = 0; | 198 | u32 low = 0, high = 0, address = 0; |
195 | 199 | ||
196 | ack_APIC_irq(); | ||
197 | exit_idle(); | ||
198 | irq_enter(); | ||
199 | |||
200 | mce_setup(&m); | 200 | mce_setup(&m); |
201 | 201 | ||
202 | /* assume first bank caused it */ | 202 | /* assume first bank caused it */ |
@@ -241,13 +241,10 @@ asmlinkage void mce_threshold_interrupt(void) | |||
241 | + bank * NR_BLOCKS | 241 | + bank * NR_BLOCKS |
242 | + block; | 242 | + block; |
243 | mce_log(&m); | 243 | mce_log(&m); |
244 | goto out; | 244 | return; |
245 | } | 245 | } |
246 | } | 246 | } |
247 | } | 247 | } |
248 | out: | ||
249 | inc_irq_stat(irq_threshold_count); | ||
250 | irq_exit(); | ||
251 | } | 248 | } |
252 | 249 | ||
253 | /* | 250 | /* |
diff --git a/arch/x86/kernel/cpu/mcheck/threshold.c b/arch/x86/kernel/cpu/mcheck/threshold.c new file mode 100644 index 000000000000..4319142413d7 --- /dev/null +++ b/arch/x86/kernel/cpu/mcheck/threshold.c | |||
@@ -0,0 +1,24 @@ | |||
1 | /* Common corrected MCE threshold handler code */ | ||
2 | #include <linux/kernel.h> | ||
3 | #include <linux/interrupt.h> | ||
4 | #include <asm/mce.h> | ||
5 | #include <asm/irq_vectors.h> | ||
6 | #include <asm/idle.h> | ||
7 | |||
8 | static void default_threshold_interrupt(void) | ||
9 | { | ||
10 | printk(KERN_ERR "Unexpected threshold interrupt at vector %x\n", | ||
11 | THRESHOLD_APIC_VECTOR); | ||
12 | } | ||
13 | |||
14 | void (*mce_threshold_vector)(void) = default_threshold_interrupt; | ||
15 | |||
16 | asmlinkage void mce_threshold_interrupt(void) | ||
17 | { | ||
18 | ack_APIC_irq(); | ||
19 | exit_idle(); | ||
20 | irq_enter(); | ||
21 | inc_irq_stat(irq_threshold_count); | ||
22 | mce_threshold_vector(); | ||
23 | irq_exit(); | ||
24 | } | ||