]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/edac/sb_edac.c
drm/nouveau: don't pretend to support the DVI-I 'select subconnector' prop
[mv-sheeva.git] / drivers / edac / sb_edac.c
index 785c2769f05bd3aa2f1ed0615c3430d5508a288f..7a402bfbee7d910bacc252c0cc200285ac27af26 100644 (file)
 #include <linux/delay.h>
 #include <linux/edac.h>
 #include <linux/mmzone.h>
-#include <linux/edac_mce.h>
 #include <linux/smp.h>
 #include <linux/bitmap.h>
 #include <asm/processor.h>
+#include <asm/mce.h>
 
 #include "edac_core.h"
 
@@ -318,9 +318,6 @@ struct sbridge_pvt {
        /* Memory type detection */
        bool                    is_mirrored, is_lockstep, is_close_pg;
 
-       /* mcelog glue */
-       struct edac_mce         edac_mce;
-
        /* Fifo double buffers */
        struct mce              mce_entry[MCE_LOG_LEN];
        struct mce              mce_outentry[MCE_LOG_LEN];
@@ -562,6 +559,7 @@ static int get_dimm_config(const struct mem_ctl_info *mci)
        unsigned long last_page = 0;
        u32 reg;
        enum edac_type mode;
+       enum mem_type mtype;
 
        pci_read_config_dword(pvt->pci_br, SAD_TARGET, &reg);
        pvt->sbridge_dev->source_id = SOURCE_ID(reg);
@@ -604,10 +602,10 @@ static int get_dimm_config(const struct mem_ctl_info *mci)
        if (IS_RDIMM_ENABLED(reg)) {
                /* FIXME: Can also be LRDIMM */
                debugf0("Memory is registered\n");
-               mode = MEM_RDDR3;
+               mtype = MEM_RDDR3;
        } else {
                debugf0("Memory is unregistered\n");
-               mode = MEM_DDR3;
+               mtype = MEM_DDR3;
        }
 
        /* On all supported DDR3 DIMM types, there are 8 banks available */
@@ -646,7 +644,7 @@ static int get_dimm_config(const struct mem_ctl_info *mci)
                                csr->dtype = (banks == 8) ? DEV_X8 : DEV_X4;
                                csr->ce_count = 0;
                                csr->ue_count = 0;
-                               csr->mtype = mode;
+                               csr->mtype = mtype;
                                csr->edac_mode = mode;
                                csr->nr_channels = 1;
                                csr->channels[0].chan_idx = i;
@@ -1578,10 +1576,17 @@ static void sbridge_check_error(struct mem_ctl_info *mci)
  * WARNING: As this routine should be called at NMI time, extra care should
  * be taken to avoid deadlocks, and to be as fast as possible.
  */
-static int sbridge_mce_check_error(void *priv, struct mce *mce)
+static int sbridge_mce_check_error(struct notifier_block *nb, unsigned long val,
+                                  void *data)
 {
-       struct mem_ctl_info *mci = priv;
-       struct sbridge_pvt *pvt = mci->pvt_info;
+       struct mce *mce = (struct mce *)data;
+       struct mem_ctl_info *mci;
+       struct sbridge_pvt *pvt;
+
+       mci = get_mci_for_node_id(mce->socketid);
+       if (!mci)
+               return NOTIFY_BAD;
+       pvt = mci->pvt_info;
 
        /*
         * Just let mcelog handle it if the error is
@@ -1590,7 +1595,7 @@ static int sbridge_mce_check_error(void *priv, struct mce *mce)
         * bit 12 has an special meaning.
         */
        if ((mce->status & 0xefff) >> 7 != 1)
-               return 0;
+               return NOTIFY_DONE;
 
        printk("sbridge: HANDLING MCE MEMORY ERROR\n");
 
@@ -1607,14 +1612,14 @@ static int sbridge_mce_check_error(void *priv, struct mce *mce)
 #ifdef CONFIG_SMP
        /* Only handle if it is the right mc controller */
        if (cpu_data(mce->cpu).phys_proc_id != pvt->sbridge_dev->mc)
-               return 0;
+               return NOTIFY_DONE;
 #endif
 
        smp_rmb();
        if ((pvt->mce_out + 1) % MCE_LOG_LEN == pvt->mce_in) {
                smp_wmb();
                pvt->mce_overrun++;
-               return 0;
+               return NOTIFY_DONE;
        }
 
        /* Copy memory error at the ringbuffer */
@@ -1627,9 +1632,13 @@ static int sbridge_mce_check_error(void *priv, struct mce *mce)
                sbridge_check_error(mci);
 
        /* Advice mcelog that the error were handled */
-       return 1;
+       return NOTIFY_STOP;
 }
 
+static struct notifier_block sbridge_mce_dec = {
+       .notifier_call      = sbridge_mce_check_error,
+};
+
 /****************************************************************************
                        EDAC register/unregister logic
  ****************************************************************************/
@@ -1652,8 +1661,8 @@ 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);
 
-       /* Disable MCE NMI handler */
-       edac_mce_unregister(&pvt->edac_mce);
+       atomic_notifier_chain_unregister(&x86_mce_decoder_chain,
+                                        &sbridge_mce_dec);
 
        /* Remove MC sysfs nodes */
        edac_mc_del_mc(mci->dev);
@@ -1722,19 +1731,9 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev)
                goto fail0;
        }
 
-       /* Registers on edac_mce in order to receive memory errors */
-       pvt->edac_mce.priv = mci;
-       pvt->edac_mce.check_error = sbridge_mce_check_error;
-       rc = edac_mce_register(&pvt->edac_mce);
-       if (unlikely(rc < 0)) {
-               debugf0("MC: " __FILE__
-                       ": %s(): failed edac_mce_register()\n", __func__);
-               goto fail1;
-       }
-
+       atomic_notifier_chain_register(&x86_mce_decoder_chain,
+                                      &sbridge_mce_dec);
        return 0;
-fail1:
-       edac_mc_del_mc(mci->dev);
 
 fail0:
        kfree(mci->ctl_name);