From: Mauro Carvalho Chehab <mchehab@redhat.com>
To: Mauro Carvalho Chehab <mchehab@redhat.com>
Cc: Ingo Molnar <mingo@elte.hu>,
bluesmoke-devel@lists.sourceforge.net,
Andrew Morton <akpm@linux-foundation.org>,
linux-kernel@vger.kernel.org
Subject: [PATCH 2/3] i7core_edac: Use a lockless ringbuffer
Date: Sun, 4 Oct 2009 16:43:47 -0300 [thread overview]
Message-ID: <20091004164347.4d483b3d@pedra.chehab.org> (raw)
In-Reply-To: <20090924192821.7fcffc80@pedra.chehab.org>
>From ece799f1fbe9af74c518c00ab5dd271ba9eb8855 Mon Sep 17 00:00:00 2001
From: Mauro Carvalho Chehab <mchehab@redhat.com>
Date: Sun, 4 Oct 2009 10:15:40 -0300
Subject: [PATCH] i7core_edac: Use a lockless ringbuffer
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
---
drivers/edac/i7core_edac.c | 83 +++++++++++++++++++++++++++++---------------
1 files changed, 55 insertions(+), 28 deletions(-)
diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c
index 97f6d17..94aeca0 100644
--- a/drivers/edac/i7core_edac.c
+++ b/drivers/edac/i7core_edac.c
@@ -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>
@@ -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 */
@@ -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;
- /* 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);
+ /*
+ * 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;
- if (m) {
- count = pvt->mce_count;
- memcpy(m, &pvt->mce_entry, sizeof(*m) * count);
- }
- pvt->mce_count = 0;
- }
+ m = pvt->mce_outentry;
+ if (pvt->mce_in + count > sizeof(mce_entry)) {
+ unsigned l = sizeof(mce_entry) - pvt->mce_in;
- spin_unlock_irqrestore(&pvt->mce_lock, flags);
+ 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;
+
+ 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]);
+ i7core_mce_output_error(mci, &pvt->mce_outentry[i]);
- kfree(m);
-
- /* check memory count errors */
+ /*
+ * Now, let's increment CE error counts
+ */
if (!pvt->is_registered)
i7core_udimm_check_mc_ecc_err(mci);
else
@@ -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
@@ -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)
@@ -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))
--
Cheers,
Mauro
next prev parent reply other threads:[~2009-10-04 19:45 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-09-24 22:28 [PATCH 00/63] i7core_edac and edac_mce Mauro Carvalho Chehab
2009-09-25 2:48 ` Hidetoshi Seto
2009-10-04 19:16 ` [PATCH 0/3] " Mauro Carvalho Chehab
2009-10-04 19:43 ` [PATCH 3/3] i7core_edac: Better parse "any" addrmask Mauro Carvalho Chehab
2009-10-04 19:43 ` Mauro Carvalho Chehab [this message]
2009-10-04 19:43 ` [PATCH 1/3] edac: Create an unique instance for each kobj Mauro Carvalho Chehab
2009-10-14 3:01 ` Andrew Morton
2009-10-14 9:41 ` Mauro Carvalho Chehab
2009-10-14 14:50 ` Colbert, Rusty
2009-10-14 15:21 ` Mauro Carvalho Chehab
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20091004164347.4d483b3d@pedra.chehab.org \
--to=mchehab@redhat.com \
--cc=akpm@linux-foundation.org \
--cc=bluesmoke-devel@lists.sourceforge.net \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@elte.hu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®