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

Commit 0b2b7b7e authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab
Browse files

i7core_edac: Add more status functions to EDAC driver



This patch were co-authored with Aristeu Rozanski.

Signed-off-by: default avatarAristeu Sergio <arozansk@redhat.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 194a40fe
Loading
Loading
Loading
Loading
+95 −19
Original line number Diff line number Diff line
@@ -62,6 +62,15 @@

	/* OFFSETS for Devices 4,5 and 6 Function 0 */

#define MC_CHANNEL_DIMM_INIT_PARAMS 0x58
  #define THREE_DIMMS_PRESENT		(1 << 24)
  #define SINGLE_QUAD_RANK_PRESENT	(1 << 23)
  #define QUAD_RANK_PRESENT		(1 << 22)
  #define REGISTERED_DIMM		(1 << 15)

#define MC_CHANNEL_RANK_PRESENT 0x7c
  #define RANK_PRESENT_MASK		0xffff

#define MC_CHANNEL_ADDR_MATCH	0xf0
#define MC_CHANNEL_ERROR_MASK	0xf8
#define MC_CHANNEL_ERROR_INJECT	0xfc
@@ -74,6 +83,46 @@
  #define NO_MASK_CACHELINE	0x00
  #define REPEAT_EN		0x01

	/* OFFSETS for Devices 4,5 and 6 Function 1 */
#define MC_DOD_CH_DIMM0		0x48
#define MC_DOD_CH_DIMM1		0x4c
#define MC_DOD_CH_DIMM2		0x50
  #define RANKOFFSET_MASK	((1 << 12) | (1 << 11) | (1 << 10))
  #define RANKOFFSET(x)		((x & RANKOFFSET_MASK) >> 10)
  #define DIMM_PRESENT_MASK	(1 << 9)
  #define DIMM_PRESENT(x)	(((x) & DIMM_PRESENT_MASK) >> 9)
  #define NUMBANK_MASK		((1 << 8) | (1 << 7))
  #define NUMBANK(x)		(((x) & NUMBANK_MASK) >> 7)
  #define NUMRANK_MASK		((1 << 6) | (1 << 5))
  #define NUMRANK(x)		(((x) & NUMRANK_MASK) >> 5)
  #define NUMROW_MASK		((1 << 4) | (1 << 3))
  #define NUMROW(x)		(((x) & NUMROW_MASK) >> 3)
  #define NUMCOL_MASK		3
  #define NUMCOL(x)		((x) & NUMCOL_MASK)

#define MC_SAG_CH_0	0x80
#define MC_SAG_CH_1	0x84
#define MC_SAG_CH_2	0x88
#define MC_SAG_CH_3	0x8c
#define MC_SAG_CH_4	0x90
#define MC_SAG_CH_5	0x94
#define MC_SAG_CH_6	0x98
#define MC_SAG_CH_7	0x9c

#define MC_RIR_LIMIT_CH_0	0x40
#define MC_RIR_LIMIT_CH_1	0x44
#define MC_RIR_LIMIT_CH_2	0x48
#define MC_RIR_LIMIT_CH_3	0x4C
#define MC_RIR_LIMIT_CH_4	0x50
#define MC_RIR_LIMIT_CH_5	0x54
#define MC_RIR_LIMIT_CH_6	0x58
#define MC_RIR_LIMIT_CH_7	0x5C
#define MC_RIR_LIMIT_MASK	((1 << 10) - 1)

#define MC_RIR_WAY_CH		0x80
  #define MC_RIR_WAY_OFFSET_MASK	(((1 << 14) - 1) & ~0x7)
  #define MC_RIR_WAY_RANK_MASK		0x7

/*
 * i7core structs
 */
@@ -99,11 +148,17 @@ struct i7core_inject {
	int channel, dimm, rank, bank, page, col;
};

struct i7core_channel {
	u32 ranks;
	u32 dimms;
};

struct i7core_pvt {
	struct pci_dev		*pci_mcr;	/* Dev 3:0 */
	struct pci_dev		*pci_ch[NUM_CHANS][NUM_FUNCS];
	struct i7core_info	info;
	struct i7core_inject	inject;
	struct i7core_channel	channel[NUM_CHANS];
};

/* Device name and register DID (Device ID) */
@@ -133,16 +188,12 @@ static struct edac_pci_ctl_info *i7core_pci;
 ****************************************************************************/

	/* MC_CONTROL bits */
#define CH2_ACTIVE(pvt)		((pvt)->info.mc_control & 1 << 10)
#define CH1_ACTIVE(pvt)		((pvt)->info.mc_control & 1 << 9)
#define CH0_ACTIVE(pvt)		((pvt)->info.mc_control & 1 << 8)
#define CH_ACTIVE(pvt, ch)	((pvt)->info.mc_control & 1 << (8 + ch))
#define ECCx8(pvt)		((pvt)->info.mc_control & 1 << 1)

	/* MC_STATUS bits */
#define ECC_ENABLED(pvt)	((pvt)->info.mc_status & 1 << 3)
#define CH2_DISABLED(pvt)	((pvt)->info.mc_status & 1 << 2)
#define CH1_DISABLED(pvt)	((pvt)->info.mc_status & 1 << 1)
#define CH0_DISABLED(pvt)	((pvt)->info.mc_status & 1 << 0)
#define CH_DISABLED(pvt, ch)	((pvt)->info.mc_status & 1 << ch)

	/* MC_MAX_DOD read functions */
static inline int maxnumdimms(struct i7core_pvt *pvt)
@@ -189,19 +240,12 @@ static inline int maxnumcol(struct i7core_pvt *pvt)
static int get_dimm_config(struct mem_ctl_info *mci)
{
	struct i7core_pvt *pvt = mci->pvt_info;
	int i;

	pci_read_config_dword(pvt->pci_mcr, MC_CONTROL, &pvt->info.mc_control);
	pci_read_config_dword(pvt->pci_mcr, MC_STATUS, &pvt->info.mc_status);
	pci_read_config_dword(pvt->pci_mcr, MC_MAX_DOD, &pvt->info.max_dod);

	debugf0("Channels  active [%c][%c][%c] - enabled [%c][%c][%c]\n",
		CH0_ACTIVE(pvt)?'0':'-',
		CH1_ACTIVE(pvt)?'1':'-',
		CH2_ACTIVE(pvt)?'2':'-',
		CH0_DISABLED(pvt)?'-':'0',
		CH1_DISABLED(pvt)?'-':'1',
		CH2_DISABLED(pvt)?'-':'2');

	if (ECC_ENABLED(pvt))
		debugf0("ECC enabled with x%d SDCC\n", ECCx8(pvt)?8:4);
	else
@@ -213,6 +257,38 @@ static int get_dimm_config(struct mem_ctl_info *mci)
	debugf0("DOD Maximum rows x colums = 0x%x x 0x%x\n",
		maxnumrow(pvt), maxnumcol(pvt));

	debugf0("Memory channel configuration:\n");

	for (i = 0; i < NUM_CHANS; i++) {
		u32 data;

		if (!CH_ACTIVE(pvt, i)) {
			debugf0("Channel %i is not active\n", i);
			continue;
		}
		if (CH_DISABLED(pvt, i)) {
			debugf0("Channel %i is disabled\n", i);
			continue;
		}

		pci_read_config_dword(pvt->pci_ch[i][0],
				MC_CHANNEL_DIMM_INIT_PARAMS, &data);

		pvt->channel[i].ranks = (data & QUAD_RANK_PRESENT)? 4 : 2;

		if (data & THREE_DIMMS_PRESENT)
			pvt->channel[i].dimms = 3;
		else if (data & SINGLE_QUAD_RANK_PRESENT)
			pvt->channel[i].dimms = 1;
		else
			pvt->channel[i].dimms = 2;

		debugf0("Channel %d (0x%08x): %d ranks, %d dimms "
			"(%sregistered)\n", i, data,
			pvt->channel[i].ranks, pvt->channel[i].dimms,
			(data & REGISTERED_DIMM)? "" : "un" );
	}

	return 0;
}

@@ -489,7 +565,7 @@ static ssize_t i7core_inject_enable_store(struct mem_ctl_info *mci,
	if (pvt->inject.dimm < 0)
		mask |= 1l << 41;
	else {
		if (maxnumdimms(pvt) > 2)
		if (pvt->channel[pvt->inject.channel].dimms > 2)
			mask |= (pvt->inject.dimm & 0x3l) << 35;
		else
			mask |= (pvt->inject.dimm & 0x1l) << 36;
@@ -499,7 +575,7 @@ static ssize_t i7core_inject_enable_store(struct mem_ctl_info *mci,
	if (pvt->inject.rank < 0)
		mask |= 1l << 40;
	else {
		if (maxnumdimms(pvt) > 2)
		if (pvt->channel[pvt->inject.channel].dimms > 2)
			mask |= (pvt->inject.rank & 0x1l) << 34;
		else
			mask |= (pvt->inject.rank & 0x3l) << 34;
@@ -646,9 +722,6 @@ static int i7core_get_devices(struct mem_ctl_info *mci, int dev_idx)
	}
	pvt->pci_mcr=pdev;

	/* Get dimm basic config */
	get_dimm_config(mci);

	/* Retrieve all needed functions at MTR channel controllers */
	for (i = 0; i < NUM_CHANS; i++) {
		pdev = NULL;
@@ -672,6 +745,9 @@ static int i7core_get_devices(struct mem_ctl_info *mci, int dev_idx)
	}
	i7core_printk(KERN_INFO, "Driver loaded.\n");

	/* Get dimm basic config */
	get_dimm_config(mci);

	return 0;
}