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

Commit 276b824c authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab
Browse files

i7core_edac: some fixes at error injection code

parent 17cb7b0c
Loading
Loading
Loading
Loading
+51 −53
Original line number Diff line number Diff line
@@ -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);