Loading arch/x86/include/asm/mce.h +2 −1 Original line number Diff line number Diff line Loading @@ -120,7 +120,8 @@ struct mce_log { #ifdef __KERNEL__ extern struct atomic_notifier_head x86_mce_decoder_chain; extern void mce_register_decode_chain(struct notifier_block *nb); extern void mce_unregister_decode_chain(struct notifier_block *nb); #include <linux/percpu.h> #include <linux/init.h> Loading arch/x86/kernel/cpu/mcheck/mce.c +57 −7 Original line number Diff line number Diff line Loading @@ -95,13 +95,6 @@ static DECLARE_WAIT_QUEUE_HEAD(mce_chrdev_wait); static DEFINE_PER_CPU(struct mce, mces_seen); static int cpu_missing; /* * CPU/chipset specific EDAC code can register a notifier call here to print * MCE errors in a human-readable form. */ ATOMIC_NOTIFIER_HEAD(x86_mce_decoder_chain); EXPORT_SYMBOL_GPL(x86_mce_decoder_chain); /* MCA banks polled by the period polling timer for corrected events */ DEFINE_PER_CPU(mce_banks_t, mce_poll_banks) = { [0 ... BITS_TO_LONGS(MAX_NR_BANKS)-1] = ~0UL Loading @@ -109,6 +102,12 @@ DEFINE_PER_CPU(mce_banks_t, mce_poll_banks) = { static DEFINE_PER_CPU(struct work_struct, mce_work); /* * CPU/chipset specific EDAC code can register a notifier call here to print * MCE errors in a human-readable form. */ ATOMIC_NOTIFIER_HEAD(x86_mce_decoder_chain); /* Do initial initialization of a struct mce */ void mce_setup(struct mce *m) { Loading Loading @@ -190,6 +189,57 @@ void mce_log(struct mce *mce) set_bit(0, &mce_need_notify); } static void drain_mcelog_buffer(void) { unsigned int next, i, prev = 0; next = rcu_dereference_check_mce(mcelog.next); do { struct mce *m; /* drain what was logged during boot */ for (i = prev; i < next; i++) { unsigned long start = jiffies; unsigned retries = 1; m = &mcelog.entry[i]; while (!m->finished) { if (time_after_eq(jiffies, start + 2*retries)) retries++; cpu_relax(); if (!m->finished && retries >= 4) { pr_err("MCE: skipping error being logged currently!\n"); break; } } smp_rmb(); atomic_notifier_call_chain(&x86_mce_decoder_chain, 0, m); } memset(mcelog.entry + prev, 0, (next - prev) * sizeof(*m)); prev = next; next = cmpxchg(&mcelog.next, prev, 0); } while (next != prev); } void mce_register_decode_chain(struct notifier_block *nb) { atomic_notifier_chain_register(&x86_mce_decoder_chain, nb); drain_mcelog_buffer(); } EXPORT_SYMBOL_GPL(mce_register_decode_chain); void mce_unregister_decode_chain(struct notifier_block *nb) { atomic_notifier_chain_unregister(&x86_mce_decoder_chain, nb); } EXPORT_SYMBOL_GPL(mce_unregister_decode_chain); static void print_mce(struct mce *m) { int ret = 0; Loading drivers/edac/i7core_edac.c +2 −2 Original line number Diff line number Diff line Loading @@ -2234,7 +2234,7 @@ static void i7core_unregister_mci(struct i7core_dev *i7core_dev) if (pvt->enable_scrub) disable_sdram_scrub_setting(mci); atomic_notifier_chain_unregister(&x86_mce_decoder_chain, &i7_mce_dec); mce_unregister_decode_chain(&i7_mce_dec); /* Disable EDAC polling */ i7core_pci_ctl_release(pvt); Loading Loading @@ -2336,7 +2336,7 @@ static int i7core_register_mci(struct i7core_dev *i7core_dev) /* DCLK for scrub rate setting */ pvt->dclk_freq = get_dclk_freq(); atomic_notifier_chain_register(&x86_mce_decoder_chain, &i7_mce_dec); mce_register_decode_chain(&i7_mce_dec); return 0; Loading drivers/edac/mce_amd.c +2 −2 Original line number Diff line number Diff line Loading @@ -884,7 +884,7 @@ static int __init mce_amd_init(void) pr_info("MCE: In-kernel MCE decoding enabled.\n"); atomic_notifier_chain_register(&x86_mce_decoder_chain, &amd_mce_dec_nb); mce_register_decode_chain(&amd_mce_dec_nb); return 0; } Loading @@ -893,7 +893,7 @@ early_initcall(mce_amd_init); #ifdef MODULE static void __exit mce_amd_exit(void) { atomic_notifier_chain_unregister(&x86_mce_decoder_chain, &amd_mce_dec_nb); mce_unregister_decode_chain(&amd_mce_dec_nb); kfree(fam_ops); } Loading drivers/edac/sb_edac.c +2 −4 Original line number Diff line number Diff line Loading @@ -1661,8 +1661,7 @@ static void sbridge_unregister_mci(struct sbridge_dev *sbridge_dev) debugf0("MC: " __FILE__ ": %s(): mci = %p, dev = %p\n", __func__, mci, &sbridge_dev->pdev[0]->dev); atomic_notifier_chain_unregister(&x86_mce_decoder_chain, &sbridge_mce_dec); mce_unregister_decode_chain(&sbridge_mce_dec); /* Remove MC sysfs nodes */ edac_mc_del_mc(mci->dev); Loading Loading @@ -1731,8 +1730,7 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev) goto fail0; } atomic_notifier_chain_register(&x86_mce_decoder_chain, &sbridge_mce_dec); mce_register_decode_chain(&sbridge_mce_dec); return 0; fail0: Loading Loading
arch/x86/include/asm/mce.h +2 −1 Original line number Diff line number Diff line Loading @@ -120,7 +120,8 @@ struct mce_log { #ifdef __KERNEL__ extern struct atomic_notifier_head x86_mce_decoder_chain; extern void mce_register_decode_chain(struct notifier_block *nb); extern void mce_unregister_decode_chain(struct notifier_block *nb); #include <linux/percpu.h> #include <linux/init.h> Loading
arch/x86/kernel/cpu/mcheck/mce.c +57 −7 Original line number Diff line number Diff line Loading @@ -95,13 +95,6 @@ static DECLARE_WAIT_QUEUE_HEAD(mce_chrdev_wait); static DEFINE_PER_CPU(struct mce, mces_seen); static int cpu_missing; /* * CPU/chipset specific EDAC code can register a notifier call here to print * MCE errors in a human-readable form. */ ATOMIC_NOTIFIER_HEAD(x86_mce_decoder_chain); EXPORT_SYMBOL_GPL(x86_mce_decoder_chain); /* MCA banks polled by the period polling timer for corrected events */ DEFINE_PER_CPU(mce_banks_t, mce_poll_banks) = { [0 ... BITS_TO_LONGS(MAX_NR_BANKS)-1] = ~0UL Loading @@ -109,6 +102,12 @@ DEFINE_PER_CPU(mce_banks_t, mce_poll_banks) = { static DEFINE_PER_CPU(struct work_struct, mce_work); /* * CPU/chipset specific EDAC code can register a notifier call here to print * MCE errors in a human-readable form. */ ATOMIC_NOTIFIER_HEAD(x86_mce_decoder_chain); /* Do initial initialization of a struct mce */ void mce_setup(struct mce *m) { Loading Loading @@ -190,6 +189,57 @@ void mce_log(struct mce *mce) set_bit(0, &mce_need_notify); } static void drain_mcelog_buffer(void) { unsigned int next, i, prev = 0; next = rcu_dereference_check_mce(mcelog.next); do { struct mce *m; /* drain what was logged during boot */ for (i = prev; i < next; i++) { unsigned long start = jiffies; unsigned retries = 1; m = &mcelog.entry[i]; while (!m->finished) { if (time_after_eq(jiffies, start + 2*retries)) retries++; cpu_relax(); if (!m->finished && retries >= 4) { pr_err("MCE: skipping error being logged currently!\n"); break; } } smp_rmb(); atomic_notifier_call_chain(&x86_mce_decoder_chain, 0, m); } memset(mcelog.entry + prev, 0, (next - prev) * sizeof(*m)); prev = next; next = cmpxchg(&mcelog.next, prev, 0); } while (next != prev); } void mce_register_decode_chain(struct notifier_block *nb) { atomic_notifier_chain_register(&x86_mce_decoder_chain, nb); drain_mcelog_buffer(); } EXPORT_SYMBOL_GPL(mce_register_decode_chain); void mce_unregister_decode_chain(struct notifier_block *nb) { atomic_notifier_chain_unregister(&x86_mce_decoder_chain, nb); } EXPORT_SYMBOL_GPL(mce_unregister_decode_chain); static void print_mce(struct mce *m) { int ret = 0; Loading
drivers/edac/i7core_edac.c +2 −2 Original line number Diff line number Diff line Loading @@ -2234,7 +2234,7 @@ static void i7core_unregister_mci(struct i7core_dev *i7core_dev) if (pvt->enable_scrub) disable_sdram_scrub_setting(mci); atomic_notifier_chain_unregister(&x86_mce_decoder_chain, &i7_mce_dec); mce_unregister_decode_chain(&i7_mce_dec); /* Disable EDAC polling */ i7core_pci_ctl_release(pvt); Loading Loading @@ -2336,7 +2336,7 @@ static int i7core_register_mci(struct i7core_dev *i7core_dev) /* DCLK for scrub rate setting */ pvt->dclk_freq = get_dclk_freq(); atomic_notifier_chain_register(&x86_mce_decoder_chain, &i7_mce_dec); mce_register_decode_chain(&i7_mce_dec); return 0; Loading
drivers/edac/mce_amd.c +2 −2 Original line number Diff line number Diff line Loading @@ -884,7 +884,7 @@ static int __init mce_amd_init(void) pr_info("MCE: In-kernel MCE decoding enabled.\n"); atomic_notifier_chain_register(&x86_mce_decoder_chain, &amd_mce_dec_nb); mce_register_decode_chain(&amd_mce_dec_nb); return 0; } Loading @@ -893,7 +893,7 @@ early_initcall(mce_amd_init); #ifdef MODULE static void __exit mce_amd_exit(void) { atomic_notifier_chain_unregister(&x86_mce_decoder_chain, &amd_mce_dec_nb); mce_unregister_decode_chain(&amd_mce_dec_nb); kfree(fam_ops); } Loading
drivers/edac/sb_edac.c +2 −4 Original line number Diff line number Diff line Loading @@ -1661,8 +1661,7 @@ static void sbridge_unregister_mci(struct sbridge_dev *sbridge_dev) debugf0("MC: " __FILE__ ": %s(): mci = %p, dev = %p\n", __func__, mci, &sbridge_dev->pdev[0]->dev); atomic_notifier_chain_unregister(&x86_mce_decoder_chain, &sbridge_mce_dec); mce_unregister_decode_chain(&sbridge_mce_dec); /* Remove MC sysfs nodes */ edac_mc_del_mc(mci->dev); Loading Loading @@ -1731,8 +1730,7 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev) goto fail0; } atomic_notifier_chain_register(&x86_mce_decoder_chain, &sbridge_mce_dec); mce_register_decode_chain(&sbridge_mce_dec); return 0; fail0: Loading