summaryrefslogtreecommitdiffstats
path: root/drivers/edac/i7core_edac.c
diff options
context:
space:
mode:
authorMauro Carvalho Chehab2009-07-23 02:45:50 +0200
committerMauro Carvalho Chehab2010-05-10 16:44:54 +0200
commit276b824c3095b09e8cb76f5709f56e9c6818ae85 (patch)
tree8902c16854157bcecbcfc230e1d21ee935697d98 /drivers/edac/i7core_edac.c
parenti7core_edac: Some cleanups at displayed info (diff)
downloadkernel-qcow2-linux-276b824c3095b09e8cb76f5709f56e9c6818ae85.tar.gz
kernel-qcow2-linux-276b824c3095b09e8cb76f5709f56e9c6818ae85.tar.xz
kernel-qcow2-linux-276b824c3095b09e8cb76f5709f56e9c6818ae85.zip
i7core_edac: some fixes at error injection code
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/edac/i7core_edac.c')
-rw-r--r--drivers/edac/i7core_edac.c104
1 files changed, 51 insertions, 53 deletions
diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c
index 86af14840b88..72859e87aeb2 100644
--- a/drivers/edac/i7core_edac.c
+++ b/drivers/edac/i7core_edac.c
@@ -32,9 +32,6 @@
#include "edac_core.h"
-/* To use the new pci_[read/write]_config_qword instead of two dword */
-#define USE_QWORD 0
-
/*
* Alter this version for the module when modifications are made
*/
@@ -473,7 +470,7 @@ static int get_dimm_config(struct mem_ctl_info *mci, int *csrow, u8 socket)
"x%x x 0x%x\n",
numdimms(pvt->info.max_dod),
numrank(pvt->info.max_dod >> 2),
- numbank(pvt->info.max_dod >> 4));
+ numbank(pvt->info.max_dod >> 4),
numrow(pvt->info.max_dod >> 6),
numcol(pvt->info.max_dod >> 9));
@@ -646,7 +643,7 @@ static ssize_t i7core_inject_socket_store(struct mem_ctl_info *mci,
int rc;
rc = strict_strtoul(data, 10, &value);
- if ((rc < 0) || (value > pvt->sockets))
+ if ((rc < 0) || (value >= pvt->sockets))
return 0;
pvt->inject.section = (u32) value;
@@ -803,7 +800,7 @@ static ssize_t i7core_inject_addrmatch_store(struct mem_ctl_info *mci,
else
return cmd - data;
} else if (!strcasecmp(cmd, "dimm")) {
- if (value < 4)
+ if (value < 3)
pvt->inject.dimm = value;
else
return cmd - data;
@@ -813,7 +810,7 @@ static ssize_t i7core_inject_addrmatch_store(struct mem_ctl_info *mci,
else
return cmd - data;
} else if (!strcasecmp(cmd, "bank")) {
- if (value < 4)
+ if (value < 32)
pvt->inject.bank = value;
else
return cmd - data;
@@ -870,6 +867,28 @@ static ssize_t i7core_inject_addrmatch_show(struct mem_ctl_info *mci,
channel, dimm, bank, rank, page, col);
}
+static int write_and_test(struct pci_dev *dev, int where, u32 val)
+{
+ u32 read;
+ int count;
+
+ for (count = 0; count < 10; count++) {
+ if (count)
+ msleep (100);
+ pci_write_config_dword(dev, where, val);
+ pci_read_config_dword(dev, where, &read);
+
+ if (read == val)
+ return 0;
+ }
+
+ debugf0("Error Injection Register 0x%02x: Tried to write 0x%08x, "
+ "but read: 0x%08x\n", where, val, read);
+
+ return -EINVAL;
+}
+
+
/*
* This routine prepares the Memory Controller for error injection.
* The error will be injected when some process tries to write to the
@@ -949,70 +968,49 @@ static ssize_t i7core_inject_enable_store(struct mem_ctl_info *mci,
else
mask |= (pvt->inject.col & 0x3fffL);
- /* Unlock writes to registers */
+ /*
+ * bit 0: REPEAT_EN
+ * bits 1-2: MASK_HALF_CACHELINE
+ * bit 3: INJECT_ECC
+ * bit 4: INJECT_ADDR_PARITY
+ */
+
+ injectmask = (pvt->inject.type & 1) |
+ (pvt->inject.section & 0x3) << 1 |
+ (pvt->inject.type & 0x6) << (3 - 1);
+
+ /* Unlock writes to registers - this register is write only */
pci_write_config_dword(pvt->pci_noncore[pvt->inject.socket],
MC_CFG_CONTROL, 0x2);
- msleep(100);
+#if 0
/* Zeroes error count registers */
pci_write_config_dword(pvt->pci_mcr[pvt->inject.socket][4],
MC_TEST_ERR_RCV1, 0);
pci_write_config_dword(pvt->pci_mcr[pvt->inject.socket][4],
MC_TEST_ERR_RCV0, 0);
pvt->ce_count_available[pvt->inject.socket] = 0;
+#endif
-
-#if USE_QWORD
- pci_write_config_qword(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0],
+ write_and_test(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0],
MC_CHANNEL_ADDR_MATCH, mask);
-#else
- pci_write_config_dword(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0],
- MC_CHANNEL_ADDR_MATCH, mask);
- pci_write_config_dword(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0],
+ write_and_test(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0],
MC_CHANNEL_ADDR_MATCH + 4, mask >> 32L);
-#endif
-#if 1
-#if USE_QWORD
- u64 rdmask;
- pci_read_config_qword(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0],
- MC_CHANNEL_ADDR_MATCH, &rdmask);
- debugf0("Inject addr match write 0x%016llx, read: 0x%016llx\n",
- mask, rdmask);
-#else
- u32 rdmask1, rdmask2;
-
- pci_read_config_dword(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0],
- MC_CHANNEL_ADDR_MATCH, &rdmask1);
- pci_read_config_dword(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0],
- MC_CHANNEL_ADDR_MATCH + 4, &rdmask2);
-
- debugf0("Inject addr match write 0x%016llx, read: 0x%08x 0x%08x\n",
- mask, rdmask1, rdmask2);
-#endif
-#endif
-
- pci_write_config_dword(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0],
+ write_and_test(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0],
MC_CHANNEL_ERROR_MASK, pvt->inject.eccmask);
+ write_and_test(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0],
+ MC_CHANNEL_ERROR_MASK, injectmask);
+
/*
- * bit 0: REPEAT_EN
- * bits 1-2: MASK_HALF_CACHELINE
- * bit 3: INJECT_ECC
- * bit 4: INJECT_ADDR_PARITY
+ * This is something undocumented, based on my tests
+ * Without writing 8 to this register, errors aren't injected. Not sure
+ * why.
*/
+ pci_write_config_dword(pvt->pci_noncore[pvt->inject.socket],
+ MC_CFG_CONTROL, 8);
- injectmask = (pvt->inject.type & 1) |
- (pvt->inject.section & 0x3) << 1 |
- (pvt->inject.type & 0x6) << (3 - 1);
-
- pci_write_config_dword(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0],
- MC_CHANNEL_ERROR_MASK, injectmask);
-
-#if 0
- /* lock writes to registers */
- pci_write_config_dword(pvt->pci_noncore, MC_CFG_CONTROL, 0);
-#endif
debugf0("Error inject addr match 0x%016llx, ecc 0x%08x,"
" inject 0x%08x\n",
mask, pvt->inject.eccmask, injectmask);