aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/edac/sb_edac.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/edac/sb_edac.c')
-rw-r--r--drivers/edac/sb_edac.c48
1 files changed, 23 insertions, 25 deletions
diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c
index 785c2769f05b..8118f12cb8c7 100644
--- a/drivers/edac/sb_edac.c
+++ b/drivers/edac/sb_edac.c
@@ -18,10 +18,10 @@
18#include <linux/delay.h> 18#include <linux/delay.h>
19#include <linux/edac.h> 19#include <linux/edac.h>
20#include <linux/mmzone.h> 20#include <linux/mmzone.h>
21#include <linux/edac_mce.h>
22#include <linux/smp.h> 21#include <linux/smp.h>
23#include <linux/bitmap.h> 22#include <linux/bitmap.h>
24#include <asm/processor.h> 23#include <asm/processor.h>
24#include <asm/mce.h>
25 25
26#include "edac_core.h" 26#include "edac_core.h"
27 27
@@ -318,9 +318,6 @@ struct sbridge_pvt {
318 /* Memory type detection */ 318 /* Memory type detection */
319 bool is_mirrored, is_lockstep, is_close_pg; 319 bool is_mirrored, is_lockstep, is_close_pg;
320 320
321 /* mcelog glue */
322 struct edac_mce edac_mce;
323
324 /* Fifo double buffers */ 321 /* Fifo double buffers */
325 struct mce mce_entry[MCE_LOG_LEN]; 322 struct mce mce_entry[MCE_LOG_LEN];
326 struct mce mce_outentry[MCE_LOG_LEN]; 323 struct mce mce_outentry[MCE_LOG_LEN];
@@ -1578,10 +1575,17 @@ static void sbridge_check_error(struct mem_ctl_info *mci)
1578 * WARNING: As this routine should be called at NMI time, extra care should 1575 * WARNING: As this routine should be called at NMI time, extra care should
1579 * be taken to avoid deadlocks, and to be as fast as possible. 1576 * be taken to avoid deadlocks, and to be as fast as possible.
1580 */ 1577 */
1581static int sbridge_mce_check_error(void *priv, struct mce *mce) 1578static int sbridge_mce_check_error(struct notifier_block *nb, unsigned long val,
1579 void *data)
1582{ 1580{
1583 struct mem_ctl_info *mci = priv; 1581 struct mce *mce = (struct mce *)data;
1584 struct sbridge_pvt *pvt = mci->pvt_info; 1582 struct mem_ctl_info *mci;
1583 struct sbridge_pvt *pvt;
1584
1585 mci = get_mci_for_node_id(mce->socketid);
1586 if (!mci)
1587 return NOTIFY_BAD;
1588 pvt = mci->pvt_info;
1585 1589
1586 /* 1590 /*
1587 * Just let mcelog handle it if the error is 1591 * Just let mcelog handle it if the error is
@@ -1590,7 +1594,7 @@ static int sbridge_mce_check_error(void *priv, struct mce *mce)
1590 * bit 12 has an special meaning. 1594 * bit 12 has an special meaning.
1591 */ 1595 */
1592 if ((mce->status & 0xefff) >> 7 != 1) 1596 if ((mce->status & 0xefff) >> 7 != 1)
1593 return 0; 1597 return NOTIFY_DONE;
1594 1598
1595 printk("sbridge: HANDLING MCE MEMORY ERROR\n"); 1599 printk("sbridge: HANDLING MCE MEMORY ERROR\n");
1596 1600
@@ -1607,14 +1611,14 @@ static int sbridge_mce_check_error(void *priv, struct mce *mce)
1607#ifdef CONFIG_SMP 1611#ifdef CONFIG_SMP
1608 /* Only handle if it is the right mc controller */ 1612 /* Only handle if it is the right mc controller */
1609 if (cpu_data(mce->cpu).phys_proc_id != pvt->sbridge_dev->mc) 1613 if (cpu_data(mce->cpu).phys_proc_id != pvt->sbridge_dev->mc)
1610 return 0; 1614 return NOTIFY_DONE;
1611#endif 1615#endif
1612 1616
1613 smp_rmb(); 1617 smp_rmb();
1614 if ((pvt->mce_out + 1) % MCE_LOG_LEN == pvt->mce_in) { 1618 if ((pvt->mce_out + 1) % MCE_LOG_LEN == pvt->mce_in) {
1615 smp_wmb(); 1619 smp_wmb();
1616 pvt->mce_overrun++; 1620 pvt->mce_overrun++;
1617 return 0; 1621 return NOTIFY_DONE;
1618 } 1622 }
1619 1623
1620 /* Copy memory error at the ringbuffer */ 1624 /* Copy memory error at the ringbuffer */
@@ -1627,9 +1631,13 @@ static int sbridge_mce_check_error(void *priv, struct mce *mce)
1627 sbridge_check_error(mci); 1631 sbridge_check_error(mci);
1628 1632
1629 /* Advice mcelog that the error were handled */ 1633 /* Advice mcelog that the error were handled */
1630 return 1; 1634 return NOTIFY_STOP;
1631} 1635}
1632 1636
1637static struct notifier_block sbridge_mce_dec = {
1638 .notifier_call = sbridge_mce_check_error,
1639};
1640
1633/**************************************************************************** 1641/****************************************************************************
1634 EDAC register/unregister logic 1642 EDAC register/unregister logic
1635 ****************************************************************************/ 1643 ****************************************************************************/
@@ -1652,8 +1660,8 @@ static void sbridge_unregister_mci(struct sbridge_dev *sbridge_dev)
1652 debugf0("MC: " __FILE__ ": %s(): mci = %p, dev = %p\n", 1660 debugf0("MC: " __FILE__ ": %s(): mci = %p, dev = %p\n",
1653 __func__, mci, &sbridge_dev->pdev[0]->dev); 1661 __func__, mci, &sbridge_dev->pdev[0]->dev);
1654 1662
1655 /* Disable MCE NMI handler */ 1663 atomic_notifier_chain_unregister(&x86_mce_decoder_chain,
1656 edac_mce_unregister(&pvt->edac_mce); 1664 &sbridge_mce_dec);
1657 1665
1658 /* Remove MC sysfs nodes */ 1666 /* Remove MC sysfs nodes */
1659 edac_mc_del_mc(mci->dev); 1667 edac_mc_del_mc(mci->dev);
@@ -1722,19 +1730,9 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev)
1722 goto fail0; 1730 goto fail0;
1723 } 1731 }
1724 1732
1725 /* Registers on edac_mce in order to receive memory errors */ 1733 atomic_notifier_chain_register(&x86_mce_decoder_chain,
1726 pvt->edac_mce.priv = mci; 1734 &sbridge_mce_dec);
1727 pvt->edac_mce.check_error = sbridge_mce_check_error;
1728 rc = edac_mce_register(&pvt->edac_mce);
1729 if (unlikely(rc < 0)) {
1730 debugf0("MC: " __FILE__
1731 ": %s(): failed edac_mce_register()\n", __func__);
1732 goto fail1;
1733 }
1734
1735 return 0; 1735 return 0;
1736fail1:
1737 edac_mc_del_mc(mci->dev);
1738 1736
1739fail0: 1737fail0:
1740 kfree(mci->ctl_name); 1738 kfree(mci->ctl_name);