i7core_edac: some fixes at error injection code
authorMauro Carvalho Chehab <mchehab@redhat.com>
Thu, 23 Jul 2009 00:45:50 +0000 (21:45 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Mon, 10 May 2010 14:44:54 +0000 (11:44 -0300)
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/edac/i7core_edac.c

index 86af148..72859e8 100644 (file)
@@ -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);