Loading drivers/edac/i7core_edac.c +55 −28 Original line number Diff line number Diff line Loading @@ -28,7 +28,6 @@ #include <linux/edac.h> #include <linux/mmzone.h> #include <linux/edac_mce.h> #include <linux/spinlock.h> #include <linux/smp.h> #include <asm/processor.h> Loading Loading @@ -239,9 +238,16 @@ struct i7core_pvt { /* mcelog glue */ struct edac_mce edac_mce; /* Fifo double buffers */ struct mce mce_entry[MCE_LOG_LEN]; unsigned mce_count; spinlock_t mce_lock; struct mce mce_outentry[MCE_LOG_LEN]; /* Fifo in/out counters */ unsigned mce_in, mce_out; /* Count indicator to show errors not got */ unsigned mce_overrun; }; /* Static vars */ Loading Loading @@ -1617,30 +1623,50 @@ static void i7core_check_error(struct mem_ctl_info *mci) struct i7core_pvt *pvt = mci->pvt_info; int i; unsigned count = 0; struct mce *m = NULL; unsigned long flags; struct mce *m; /* * MCE first step: Copy all mce errors into a temporary buffer * We use a double buffering here, to reduce the risk of * loosing an error. */ smp_rmb(); count = (pvt->mce_out + sizeof(mce_entry) - pvt->mce_in) % sizeof(mce_entry); if (!count) return; /* Copy all mce errors into a temporary buffer */ spin_lock_irqsave(&pvt->mce_lock, flags); if (pvt->mce_count) { m = kmalloc(sizeof(*m) * pvt->mce_count, GFP_ATOMIC); m = pvt->mce_outentry; if (pvt->mce_in + count > sizeof(mce_entry)) { unsigned l = sizeof(mce_entry) - pvt->mce_in; if (m) { count = pvt->mce_count; memcpy(m, &pvt->mce_entry, sizeof(*m) * count); } pvt->mce_count = 0; memcpy(m, &pvt->mce_entry[pvt->mce_in], sizeof(*m) * l); smp_wmb(); pvt->mce_in = 0; count -= l; m += l; } memcpy(m, &pvt->mce_entry[pvt->mce_in], sizeof(*m) * count); smp_wmb(); pvt->mce_in += count; spin_unlock_irqrestore(&pvt->mce_lock, flags); smp_rmb(); if (pvt->mce_overrun) { i7core_printk(KERN_ERR, "Lost %d memory errors\n", pvt->mce_overrun); smp_wmb(); pvt->mce_overrun = 0; } /* proccess mcelog errors */ /* * MCE second step: parse errors and display */ for (i = 0; i < count; i++) i7core_mce_output_error(mci, &m[i]); kfree(m); i7core_mce_output_error(mci, &pvt->mce_outentry[i]); /* check memory count errors */ /* * Now, let's increment CE error counts */ if (!pvt->is_registered) i7core_udimm_check_mc_ecc_err(mci); else Loading @@ -1657,7 +1683,6 @@ static int i7core_mce_check_error(void *priv, struct mce *mce) { struct mem_ctl_info *mci = priv; struct i7core_pvt *pvt = mci->pvt_info; unsigned long flags; /* * Just let mcelog handle it if the error is Loading @@ -1679,12 +1704,15 @@ static int i7core_mce_check_error(void *priv, struct mce *mce) return 0; } spin_lock_irqsave(&pvt->mce_lock, flags); if (pvt->mce_count < MCE_LOG_LEN) { memcpy(&pvt->mce_entry[pvt->mce_count], mce, sizeof(*mce)); pvt->mce_count++; smp_rmb(); if ((pvt->mce_out + 1) % sizeof(mce_entry) == pvt->mce_in) { smp_wmb(); pvt->mce_overrun++; return 0; } spin_unlock_irqrestore(&pvt->mce_lock, flags); smp_wmb(); pvt->mce_out = (pvt->mce_out + 1) % sizeof(mce_entry); memcpy(&pvt->mce_entry[pvt->mce_out], mce, sizeof(*mce)); /* Handle fatal errors immediately */ if (mce->mcgstatus & 1) Loading Loading @@ -1777,7 +1805,6 @@ static int i7core_register_mci(struct i7core_dev *i7core_dev, /* Registers on edac_mce in order to receive memory errors */ pvt->edac_mce.priv = mci; pvt->edac_mce.check_error = i7core_mce_check_error; spin_lock_init(&pvt->mce_lock); rc = edac_mce_register(&pvt->edac_mce); if (unlikely(rc < 0)) { Loading Loading
drivers/edac/i7core_edac.c +55 −28 Original line number Diff line number Diff line Loading @@ -28,7 +28,6 @@ #include <linux/edac.h> #include <linux/mmzone.h> #include <linux/edac_mce.h> #include <linux/spinlock.h> #include <linux/smp.h> #include <asm/processor.h> Loading Loading @@ -239,9 +238,16 @@ struct i7core_pvt { /* mcelog glue */ struct edac_mce edac_mce; /* Fifo double buffers */ struct mce mce_entry[MCE_LOG_LEN]; unsigned mce_count; spinlock_t mce_lock; struct mce mce_outentry[MCE_LOG_LEN]; /* Fifo in/out counters */ unsigned mce_in, mce_out; /* Count indicator to show errors not got */ unsigned mce_overrun; }; /* Static vars */ Loading Loading @@ -1617,30 +1623,50 @@ static void i7core_check_error(struct mem_ctl_info *mci) struct i7core_pvt *pvt = mci->pvt_info; int i; unsigned count = 0; struct mce *m = NULL; unsigned long flags; struct mce *m; /* * MCE first step: Copy all mce errors into a temporary buffer * We use a double buffering here, to reduce the risk of * loosing an error. */ smp_rmb(); count = (pvt->mce_out + sizeof(mce_entry) - pvt->mce_in) % sizeof(mce_entry); if (!count) return; /* Copy all mce errors into a temporary buffer */ spin_lock_irqsave(&pvt->mce_lock, flags); if (pvt->mce_count) { m = kmalloc(sizeof(*m) * pvt->mce_count, GFP_ATOMIC); m = pvt->mce_outentry; if (pvt->mce_in + count > sizeof(mce_entry)) { unsigned l = sizeof(mce_entry) - pvt->mce_in; if (m) { count = pvt->mce_count; memcpy(m, &pvt->mce_entry, sizeof(*m) * count); } pvt->mce_count = 0; memcpy(m, &pvt->mce_entry[pvt->mce_in], sizeof(*m) * l); smp_wmb(); pvt->mce_in = 0; count -= l; m += l; } memcpy(m, &pvt->mce_entry[pvt->mce_in], sizeof(*m) * count); smp_wmb(); pvt->mce_in += count; spin_unlock_irqrestore(&pvt->mce_lock, flags); smp_rmb(); if (pvt->mce_overrun) { i7core_printk(KERN_ERR, "Lost %d memory errors\n", pvt->mce_overrun); smp_wmb(); pvt->mce_overrun = 0; } /* proccess mcelog errors */ /* * MCE second step: parse errors and display */ for (i = 0; i < count; i++) i7core_mce_output_error(mci, &m[i]); kfree(m); i7core_mce_output_error(mci, &pvt->mce_outentry[i]); /* check memory count errors */ /* * Now, let's increment CE error counts */ if (!pvt->is_registered) i7core_udimm_check_mc_ecc_err(mci); else Loading @@ -1657,7 +1683,6 @@ static int i7core_mce_check_error(void *priv, struct mce *mce) { struct mem_ctl_info *mci = priv; struct i7core_pvt *pvt = mci->pvt_info; unsigned long flags; /* * Just let mcelog handle it if the error is Loading @@ -1679,12 +1704,15 @@ static int i7core_mce_check_error(void *priv, struct mce *mce) return 0; } spin_lock_irqsave(&pvt->mce_lock, flags); if (pvt->mce_count < MCE_LOG_LEN) { memcpy(&pvt->mce_entry[pvt->mce_count], mce, sizeof(*mce)); pvt->mce_count++; smp_rmb(); if ((pvt->mce_out + 1) % sizeof(mce_entry) == pvt->mce_in) { smp_wmb(); pvt->mce_overrun++; return 0; } spin_unlock_irqrestore(&pvt->mce_lock, flags); smp_wmb(); pvt->mce_out = (pvt->mce_out + 1) % sizeof(mce_entry); memcpy(&pvt->mce_entry[pvt->mce_out], mce, sizeof(*mce)); /* Handle fatal errors immediately */ if (mce->mcgstatus & 1) Loading Loading @@ -1777,7 +1805,6 @@ static int i7core_register_mci(struct i7core_dev *i7core_dev, /* Registers on edac_mce in order to receive memory errors */ pvt->edac_mce.priv = mci; pvt->edac_mce.check_error = i7core_mce_check_error; spin_lock_init(&pvt->mce_lock); rc = edac_mce_register(&pvt->edac_mce); if (unlikely(rc < 0)) { Loading