x86, MCE, AMD: Assign interrupt handler only when bank supports it
authorChen Yucong <slaoub@gmail.com>
Sat, 1 Nov 2014 10:23:32 +0000 (11:23 +0100)
committerBorislav Petkov <bp@suse.de>
Sat, 1 Nov 2014 10:28:23 +0000 (11:28 +0100)
There are some AMD CPU models which have thresholding banks but which
cannot generate a thresholding interrupt. This is denoted by the bit
MCi_MISC[IntP]. Make sure to check that bit before assigning the
thresholding interrupt handler.

Signed-off-by: Chen Yucong <slaoub@gmail.com>
[ Boris: save an indentation level and rewrite commit message. ]
Link: http://lkml.kernel.org/r/1412662128.28440.18.camel@debian
Signed-off-by: Borislav Petkov <bp@suse.de>
arch/x86/kernel/cpu/mcheck/mce_amd.c

index 6606523ff1c143ee3fd2726a505a63061b14eb65..f1c3769bbd6433344968bf5f78ad223170ef6878 100644 (file)
@@ -212,7 +212,7 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c)
        unsigned int cpu = smp_processor_id();
        u32 low = 0, high = 0, address = 0;
        unsigned int bank, block;
-       int offset = -1;
+       int offset = -1, new;
 
        for (bank = 0; bank < mca_cfg.banks; ++bank) {
                for (block = 0; block < NR_BLOCKS; ++block) {
@@ -247,15 +247,18 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c)
                        b.address               = address;
                        b.interrupt_capable     = lvt_interrupt_supported(bank, high);
 
-                       if (b.interrupt_capable) {
-                               int new = (high & MASK_LVTOFF_HI) >> 20;
-                               offset  = setup_APIC_mce(offset, new);
-                       }
+                       if (!b.interrupt_capable)
+                               goto init;
 
-                       mce_threshold_block_init(&b, offset);
+                       new     = (high & MASK_LVTOFF_HI) >> 20;
+                       offset  = setup_APIC_mce(offset, new);
 
-                       if (mce_threshold_vector != amd_threshold_interrupt)
+                       if ((offset == new) &&
+                           (mce_threshold_vector != amd_threshold_interrupt))
                                mce_threshold_vector = amd_threshold_interrupt;
+
+init:
+                       mce_threshold_block_init(&b, offset);
                }
        }
 }