i7core_edac: Adds write unlock to MC registers
authorMauro Carvalho Chehab <mchehab@redhat.com>
Fri, 10 Jul 2009 01:14:35 +0000 (22:14 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Mon, 10 May 2010 14:44:50 +0000 (11:44 -0300)
The public Intel Xeon 5500 volume 2 datasheet describes, on page 53,
session 2.6.7 a register that can lock/unlock Memory Controller the
configuration register, called MC_CFG_CONTROL.

Adds support for it in the hope that software error injection would
work. With my tests with Xeon 35xx, there's still something missing.
With a program that does sequencial bit writes at dev 0.0, sometimes, it
produces error injection, after unblocking the MC_CFG_CONTROL (and,
sometimes, it just locks my testing machine).

I'll try later to discover by trial and error what's the register that
solves this issue on Xeon 35xx.

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/edac/i7core_edac.c
include/linux/pci_ids.h

index 3c7bb5f..26cd5c9 100644 (file)
@@ -33,7 +33,7 @@
 #include "edac_core.h"
 
 /* To use the new pci_[read/write]_config_qword instead of two dword */
-#define USE_QWORD 1
+#define USE_QWORD 0
 
 /*
  * Alter this version for the module when modifications are made
  * i7core Memory Controller Registers
  */
 
+       /* OFFSETS for Device 0 Function 0 */
+
+#define MC_CFG_CONTROL 0x90
+
        /* OFFSETS for Device 3 Function 0 */
 
 #define MC_CONTROL     0x48
@@ -186,6 +190,7 @@ struct pci_id_descr {
 };
 
 struct i7core_pvt {
+       struct pci_dev          *pci_noncore;
        struct pci_dev          *pci_mcr[MAX_MCR_FUNC + 1];
        struct pci_dev          *pci_ch[NUM_CHANS][MAX_CHAN_FUNC + 1];
        struct i7core_info      info;
@@ -222,6 +227,9 @@ struct pci_id_descr pci_devs[] = {
        { PCI_DESCR(3, 2, PCI_DEVICE_ID_INTEL_I7_MC_RAS)  }, /* if RDIMM is supported */
        { PCI_DESCR(3, 4, PCI_DEVICE_ID_INTEL_I7_MC_TEST) },
 
+               /* Generic Non-core registers */
+       { PCI_DESCR(0, 0, PCI_DEVICE_ID_INTEL_I7_NOCORE)  },
+
                /* Channel 0 */
        { PCI_DESCR(4, 0, PCI_DEVICE_ID_INTEL_I7_MC_CH0_CTRL) },
        { PCI_DESCR(4, 1, PCI_DEVICE_ID_INTEL_I7_MC_CH0_ADDR) },
@@ -882,6 +890,16 @@ static ssize_t i7core_inject_enable_store(struct mem_ctl_info *mci,
        else
                mask |= (pvt->inject.col & 0x3fffL);
 
+       /* Unlock writes to registers */
+       pci_write_config_dword(pvt->pci_noncore, MC_CFG_CONTROL, 0x2);
+       msleep(100);
+
+       /* Zeroes error count registers */
+       pci_write_config_dword(pvt->pci_mcr[4], MC_TEST_ERR_RCV1, 0);
+       pci_write_config_dword(pvt->pci_mcr[4], MC_TEST_ERR_RCV0, 0);
+       pvt->ce_count_available = 0;
+
+
 #if USE_QWORD
        pci_write_config_qword(pvt->pci_ch[pvt->inject.channel][0],
                               MC_CHANNEL_ADDR_MATCH, mask);
@@ -929,12 +947,15 @@ static ssize_t i7core_inject_enable_store(struct mem_ctl_info *mci,
        pci_write_config_dword(pvt->pci_ch[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);
 
 
-
        return count;
 }
 
@@ -1124,12 +1145,15 @@ static int mci_bind_devs(struct mem_ctl_info *mci)
                        if (unlikely(func > MAX_CHAN_FUNC))
                                goto error;
                        pvt->pci_ch[slot - 4][func] = pdev;
-               } else
+               } else if (!slot && !func)
+                       pvt->pci_noncore = pdev;
+               else
                        goto error;
 
                debugf0("Associated fn %d.%d, dev = %p\n",
                        PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), pdev);
        }
+
        return 0;
 
 error:
index c5dd099..9d5bfe8 100644 (file)
 #define PCI_DEVICE_ID_INTEL_I7_MC_CH2_ADDR  0x2c31
 #define PCI_DEVICE_ID_INTEL_I7_MC_CH2_RANK  0x2c32
 #define PCI_DEVICE_ID_INTEL_I7_MC_CH2_TC    0x2c33
+#define PCI_DEVICE_ID_INTEL_I7_NOCORE  0x2c41
 #define PCI_DEVICE_ID_INTEL_82855PM_HB 0x3340
 #define PCI_DEVICE_ID_INTEL_IOAT_TBG4  0x3429
 #define PCI_DEVICE_ID_INTEL_IOAT_TBG5  0x342a