Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e9bd2e73 authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab
Browse files

i7core_edac: Adds write unlock to MC registers



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: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent d5381642
Loading
Loading
Loading
Loading
+27 −3
Original line number Original line Diff line number Diff line
@@ -33,7 +33,7 @@
#include "edac_core.h"
#include "edac_core.h"


/* To use the new pci_[read/write]_config_qword instead of two dword */
/* 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
 * Alter this version for the module when modifications are made
@@ -58,6 +58,10 @@
 * i7core Memory Controller Registers
 * i7core Memory Controller Registers
 */
 */


	/* OFFSETS for Device 0 Function 0 */

#define MC_CFG_CONTROL	0x90

	/* OFFSETS for Device 3 Function 0 */
	/* OFFSETS for Device 3 Function 0 */


#define MC_CONTROL	0x48
#define MC_CONTROL	0x48
@@ -186,6 +190,7 @@ struct pci_id_descr {
};
};


struct i7core_pvt {
struct i7core_pvt {
	struct pci_dev		*pci_noncore;
	struct pci_dev		*pci_mcr[MAX_MCR_FUNC + 1];
	struct pci_dev		*pci_mcr[MAX_MCR_FUNC + 1];
	struct pci_dev		*pci_ch[NUM_CHANS][MAX_CHAN_FUNC + 1];
	struct pci_dev		*pci_ch[NUM_CHANS][MAX_CHAN_FUNC + 1];
	struct i7core_info	info;
	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, 2, PCI_DEVICE_ID_INTEL_I7_MC_RAS)  }, /* if RDIMM is supported */
	{ PCI_DESCR(3, 4, PCI_DEVICE_ID_INTEL_I7_MC_TEST) },
	{ 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 */
		/* Channel 0 */
	{ PCI_DESCR(4, 0, PCI_DEVICE_ID_INTEL_I7_MC_CH0_CTRL) },
	{ PCI_DESCR(4, 0, PCI_DEVICE_ID_INTEL_I7_MC_CH0_CTRL) },
	{ PCI_DESCR(4, 1, PCI_DEVICE_ID_INTEL_I7_MC_CH0_ADDR) },
	{ 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
	else
		mask |= (pvt->inject.col & 0x3fffL);
		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
#if USE_QWORD
	pci_write_config_qword(pvt->pci_ch[pvt->inject.channel][0],
	pci_write_config_qword(pvt->pci_ch[pvt->inject.channel][0],
			       MC_CHANNEL_ADDR_MATCH, mask);
			       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],
	pci_write_config_dword(pvt->pci_ch[pvt->inject.channel][0],
			       MC_CHANNEL_ERROR_MASK, injectmask);
			       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,"
	debugf0("Error inject addr match 0x%016llx, ecc 0x%08x,"
		" inject 0x%08x\n",
		" inject 0x%08x\n",
		mask, pvt->inject.eccmask, injectmask);
		mask, pvt->inject.eccmask, injectmask);





	return count;
	return count;
}
}


@@ -1124,12 +1145,15 @@ static int mci_bind_devs(struct mem_ctl_info *mci)
			if (unlikely(func > MAX_CHAN_FUNC))
			if (unlikely(func > MAX_CHAN_FUNC))
				goto error;
				goto error;
			pvt->pci_ch[slot - 4][func] = pdev;
			pvt->pci_ch[slot - 4][func] = pdev;
		} else
		} else if (!slot && !func)
			pvt->pci_noncore = pdev;
		else
			goto error;
			goto error;


		debugf0("Associated fn %d.%d, dev = %p\n",
		debugf0("Associated fn %d.%d, dev = %p\n",
			PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), pdev);
			PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), pdev);
	}
	}

	return 0;
	return 0;


error:
error:
+1 −0
Original line number Original line Diff line number Diff line
@@ -2548,6 +2548,7 @@
#define PCI_DEVICE_ID_INTEL_I7_MC_CH2_ADDR  0x2c31
#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_RANK  0x2c32
#define PCI_DEVICE_ID_INTEL_I7_MC_CH2_TC    0x2c33
#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_82855PM_HB	0x3340
#define PCI_DEVICE_ID_INTEL_IOAT_TBG4	0x3429
#define PCI_DEVICE_ID_INTEL_IOAT_TBG4	0x3429
#define PCI_DEVICE_ID_INTEL_IOAT_TBG5	0x342a
#define PCI_DEVICE_ID_INTEL_IOAT_TBG5	0x342a