Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/j.anaszewski...
[linux-2.6-block.git] / arch / x86 / kernel / cpu / mcheck / mce.c
index d77f3b04b27730e7cfcb675fce464dc6a1481c85..92e5e37d97bf4b808a7e1824ad4fd573ccf075e1 100644 (file)
@@ -161,7 +161,6 @@ void mce_log(struct mce *mce)
        if (!mce_gen_pool_add(mce))
                irq_work_queue(&mce_irq_work);
 
-       mce->finished = 0;
        wmb();
        for (;;) {
                entry = mce_log_get_idx_check(mcelog.next);
@@ -194,7 +193,6 @@ void mce_log(struct mce *mce)
        mcelog.entry[entry].finished = 1;
        wmb();
 
-       mce->finished = 1;
        set_bit(0, &mce_need_notify);
 }
 
@@ -337,7 +335,9 @@ static void wait_for_panic(void)
 
 static void mce_panic(const char *msg, struct mce *final, char *exp)
 {
-       int i, apei_err = 0;
+       int apei_err = 0;
+       struct llist_node *pending;
+       struct mce_evt_llist *l;
 
        if (!fake_panic) {
                /*
@@ -354,11 +354,10 @@ static void mce_panic(const char *msg, struct mce *final, char *exp)
                if (atomic_inc_return(&mce_fake_panicked) > 1)
                        return;
        }
+       pending = mce_gen_pool_prepare_records();
        /* First print corrected ones that are still unlogged */
-       for (i = 0; i < MCE_LOG_LEN; i++) {
-               struct mce *m = &mcelog.entry[i];
-               if (!(m->status & MCI_STATUS_VAL))
-                       continue;
+       llist_for_each_entry(l, pending, llnode) {
+               struct mce *m = &l->mce;
                if (!(m->status & MCI_STATUS_UC)) {
                        print_mce(m);
                        if (!apei_err)
@@ -366,13 +365,11 @@ static void mce_panic(const char *msg, struct mce *final, char *exp)
                }
        }
        /* Now print uncorrected but with the final one last */
-       for (i = 0; i < MCE_LOG_LEN; i++) {
-               struct mce *m = &mcelog.entry[i];
-               if (!(m->status & MCI_STATUS_VAL))
-                       continue;
+       llist_for_each_entry(l, pending, llnode) {
+               struct mce *m = &l->mce;
                if (!(m->status & MCI_STATUS_UC))
                        continue;
-               if (!final || memcmp(m, final, sizeof(struct mce))) {
+               if (!final || mce_cmp(m, final)) {
                        print_mce(m);
                        if (!apei_err)
                                apei_err = apei_write_mce(m);
@@ -1041,11 +1038,12 @@ void do_machine_check(struct pt_regs *regs, long error_code)
        int i;
        int worst = 0;
        int severity;
+
        /*
         * Establish sequential order between the CPUs entering the machine
         * check handler.
         */
-       int order;
+       int order = -1;
        /*
         * If no_way_out gets set, there is no safe way to recover from this
         * MCE.  If mca_cfg.tolerant is cranked up, we'll try anyway.
@@ -1059,7 +1057,12 @@ void do_machine_check(struct pt_regs *regs, long error_code)
        DECLARE_BITMAP(toclear, MAX_NR_BANKS);
        DECLARE_BITMAP(valid_banks, MAX_NR_BANKS);
        char *msg = "Unknown";
-       int lmce = 0;
+
+       /*
+        * MCEs are always local on AMD. Same is determined by MCG_STATUS_LMCES
+        * on Intel.
+        */
+       int lmce = 1;
 
        /* If this CPU is offline, just bail out. */
        if (cpu_is_offline(smp_processor_id())) {
@@ -1098,19 +1101,20 @@ void do_machine_check(struct pt_regs *regs, long error_code)
                kill_it = 1;
 
        /*
-        * Check if this MCE is signaled to only this logical processor
+        * Check if this MCE is signaled to only this logical processor,
+        * on Intel only.
         */
-       if (m.mcgstatus & MCG_STATUS_LMCES)
-               lmce = 1;
-       else {
-               /*
-                * Go through all the banks in exclusion of the other CPUs.
-                * This way we don't report duplicated events on shared banks
-                * because the first one to see it will clear it.
-                * If this is a Local MCE, then no need to perform rendezvous.
-                */
+       if (m.cpuvendor == X86_VENDOR_INTEL)
+               lmce = m.mcgstatus & MCG_STATUS_LMCES;
+
+       /*
+        * Go through all banks in exclusion of the other CPUs. This way we
+        * don't report duplicated events on shared banks because the first one
+        * to see it will clear it. If this is a Local MCE, then no need to
+        * perform rendezvous.
+        */
+       if (!lmce)
                order = mce_start(&no_way_out);
-       }
 
        for (i = 0; i < cfg->banks; i++) {
                __clear_bit(i, toclear);
@@ -1679,11 +1683,9 @@ static void __mcheck_cpu_init_vendor(struct cpuinfo_x86 *c)
                break;
 
        case X86_VENDOR_AMD: {
-               u32 ebx = cpuid_ebx(0x80000007);
-
-               mce_flags.overflow_recov = !!(ebx & BIT(0));
-               mce_flags.succor         = !!(ebx & BIT(1));
-               mce_flags.smca           = !!(ebx & BIT(3));
+               mce_flags.overflow_recov = !!cpu_has(c, X86_FEATURE_OVERFLOW_RECOV);
+               mce_flags.succor         = !!cpu_has(c, X86_FEATURE_SUCCOR);
+               mce_flags.smca           = !!cpu_has(c, X86_FEATURE_SMCA);
 
                /*
                 * Install proper ops for Scalable MCA enabled processors