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

Commit 084a4fcc authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab
Browse files

edac: move dimm properties to struct dimm_info



On systems based on chip select rows, all channels need to use memories
with the same properties, otherwise the memories on channels A and B
won't be recognized.

However, such assumption is not true for all types of memory
controllers.

Controllers for FB-DIMM's don't have such requirements.

Also, modern Intel controllers seem to be capable of handling such
differences.

So, we need to get rid of storing the DIMM information into a per-csrow
data, storing it, instead at the right place.

The first step is to move grain, mtype, dtype and edac_mode to the
per-dimm struct.

Reviewed-by: default avatarAristeu Rozanski <arozansk@redhat.com>
Reviewed-by: default avatarBorislav Petkov <borislav.petkov@amd.com>
Acked-by: default avatarChris Metcalf <cmetcalf@tilera.com>
Cc: Doug Thompson <norsk5@yahoo.com>
Cc: Borislav Petkov <borislav.petkov@amd.com>
Cc: Mark Gross <mark.gross@intel.com>
Cc: Jason Uhlenkott <juhlenko@akamai.com>
Cc: Tim Small <tim@buttersideup.com>
Cc: Ranganathan Desikan <ravi@jetztechnologies.com>
Cc: "Arvind R." <arvino55@gmail.com>
Cc: Olof Johansson <olof@lixom.net>
Cc: Egor Martovetsky <egor@pasemi.com>
Cc: Michal Marek <mmarek@suse.cz>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Joe Perches <joe@perches.com>
Cc: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Hitoshi Mitake <h.mitake@gmail.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: James Bottomley <James.Bottomley@parallels.com>
Cc: "Niklas Söderlund" <niklas.soderlund@ericsson.com>
Cc: Shaohui Xie <Shaohui.Xie@freescale.com>
Cc: Josh Boyer <jwboyer@gmail.com>
Cc: Mike Williams <mike@mikebwilliams.com>
Cc: linuxppc-dev@lists.ozlabs.org
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent a7d7d2e1
Loading
Loading
Loading
Loading
+12 −6
Original line number Diff line number Diff line
@@ -2187,7 +2187,9 @@ static int init_csrows(struct mem_ctl_info *mci)
	struct amd64_pvt *pvt = mci->pvt_info;
	u64 input_addr_min, input_addr_max, sys_addr, base, mask;
	u32 val;
	int i, empty = 1;
	int i, j, empty = 1;
	enum mem_type mtype;
	enum edac_type edac_mode;

	amd64_read_pci_cfg(pvt->F3, NBCFG, &val);

@@ -2224,7 +2226,7 @@ static int init_csrows(struct mem_ctl_info *mci)
		csrow->page_mask = ~mask;
		/* 8 bytes of resolution */

		csrow->mtype = amd64_determine_memory_type(pvt, i);
		mtype = amd64_determine_memory_type(pvt, i);

		debugf1("  for MC node %d csrow %d:\n", pvt->mc_node_id, i);
		debugf1("    input_addr_min: 0x%lx input_addr_max: 0x%lx\n",
@@ -2241,11 +2243,15 @@ static int init_csrows(struct mem_ctl_info *mci)
		 * determine whether CHIPKILL or JUST ECC or NO ECC is operating
		 */
		if (pvt->nbcfg & NBCFG_ECC_ENABLE)
			csrow->edac_mode =
			    (pvt->nbcfg & NBCFG_CHIPKILL) ?
			edac_mode = (pvt->nbcfg & NBCFG_CHIPKILL) ?
				    EDAC_S4ECD4ED : EDAC_SECDED;
		else
			csrow->edac_mode = EDAC_NONE;
			edac_mode = EDAC_NONE;

		for (j = 0; j < pvt->channel_count; j++) {
			csrow->channels[j].dimm->mtype = mtype;
			csrow->channels[j].dimm->edac_mode = edac_mode;
		}
	}

	return empty;
+6 −4
Original line number Diff line number Diff line
@@ -186,11 +186,13 @@ static void amd76x_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev,
			enum edac_type edac_mode)
{
	struct csrow_info *csrow;
	struct dimm_info *dimm;
	u32 mba, mba_base, mba_mask, dms;
	int index;

	for (index = 0; index < mci->nr_csrows; index++) {
		csrow = &mci->csrows[index];
		dimm = csrow->channels[0].dimm;

		/* find the DRAM Chip Select Base address and mask */
		pci_read_config_dword(pdev,
@@ -206,10 +208,10 @@ static void amd76x_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev,
		csrow->nr_pages = (mba_mask + 1) >> PAGE_SHIFT;
		csrow->last_page = csrow->first_page + csrow->nr_pages - 1;
		csrow->page_mask = mba_mask >> PAGE_SHIFT;
		csrow->grain = csrow->nr_pages << PAGE_SHIFT;
		csrow->mtype = MEM_RDDR;
		csrow->dtype = ((dms >> index) & 0x1) ? DEV_X4 : DEV_UNKNOWN;
		csrow->edac_mode = edac_mode;
		dimm->grain = csrow->nr_pages << PAGE_SHIFT;
		dimm->mtype = MEM_RDDR;
		dimm->dtype = ((dms >> index) & 0x1) ? DEV_X4 : DEV_UNKNOWN;
		dimm->edac_mode = edac_mode;
	}
}

+8 −2
Original line number Diff line number Diff line
@@ -124,8 +124,10 @@ static void cell_edac_check(struct mem_ctl_info *mci)
static void __devinit cell_edac_init_csrows(struct mem_ctl_info *mci)
{
	struct csrow_info		*csrow = &mci->csrows[0];
	struct dimm_info		*dimm;
	struct cell_edac_priv		*priv = mci->pvt_info;
	struct device_node		*np;
	int				j;

	for (np = NULL;
	     (np = of_find_node_by_name(np, "memory")) != NULL;) {
@@ -142,8 +144,12 @@ static void __devinit cell_edac_init_csrows(struct mem_ctl_info *mci)
		csrow->first_page = r.start >> PAGE_SHIFT;
		csrow->nr_pages = resource_size(&r) >> PAGE_SHIFT;
		csrow->last_page = csrow->first_page + csrow->nr_pages - 1;
		csrow->mtype = MEM_XDR;
		csrow->edac_mode = EDAC_SECDED;

		for (j = 0; j < csrow->nr_channels; j++) {
			dimm = csrow->channels[j].dimm;
			dimm->mtype = MEM_XDR;
			dimm->edac_mode = EDAC_SECDED;
		}
		dev_dbg(mci->dev,
			"Initialized on node %d, chanmask=0x%x,"
			" first_page=0x%lx, nr_pages=0x%x\n",
+33 −29
Original line number Diff line number Diff line
@@ -329,7 +329,8 @@ static void cpc925_init_csrows(struct mem_ctl_info *mci)
{
	struct cpc925_mc_pdata *pdata = mci->pvt_info;
	struct csrow_info *csrow;
	int index;
	struct dimm_info *dimm;
	int index, j;
	u32 mbmr, mbbar, bba;
	unsigned long row_size, last_nr_pages = 0;

@@ -354,16 +355,18 @@ static void cpc925_init_csrows(struct mem_ctl_info *mci)
		csrow->last_page = csrow->first_page + csrow->nr_pages - 1;
		last_nr_pages = csrow->last_page + 1;

		csrow->mtype = MEM_RDDR;
		csrow->edac_mode = EDAC_SECDED;
		for (j = 0; j < csrow->nr_channels; j++) {
			dimm = csrow->channels[j].dimm;
			dimm->mtype = MEM_RDDR;
			dimm->edac_mode = EDAC_SECDED;

			switch (csrow->nr_channels) {
			case 1: /* Single channel */
			csrow->grain = 32; /* four-beat burst of 32 bytes */
				dimm->grain = 32; /* four-beat burst of 32 bytes */
				break;
			case 2: /* Dual channel */
			default:
			csrow->grain = 64; /* four-beat burst of 64 bytes */
				dimm->grain = 64; /* four-beat burst of 64 bytes */
				break;
			}

@@ -371,18 +374,19 @@ static void cpc925_init_csrows(struct mem_ctl_info *mci)
			case 6: /* 0110, no way to differentiate X8 VS X16 */
			case 5:	/* 0101 */
			case 8: /* 1000 */
			csrow->dtype = DEV_X16;
				dimm->dtype = DEV_X16;
				break;
			case 7: /* 0111 */
			case 9: /* 1001 */
			csrow->dtype = DEV_X8;
				dimm->dtype = DEV_X8;
				break;
			default:
			csrow->dtype = DEV_UNKNOWN;
				dimm->dtype = DEV_UNKNOWN;
				break;
			}
		}
	}
}

/* Enable memory controller ECC detection */
static void cpc925_mc_init(struct mem_ctl_info *mci)
@@ -962,9 +966,9 @@ static int __devinit cpc925_probe(struct platform_device *pdev)
		goto err2;
	}

	nr_channels = cpc925_mc_get_channels(vbase);
	nr_channels = cpc925_mc_get_channels(vbase) + 1;
	mci = edac_mc_alloc(sizeof(struct cpc925_mc_pdata),
			CPC925_NR_CSROWS, nr_channels + 1, edac_mc_idx);
			CPC925_NR_CSROWS, nr_channels, edac_mc_idx);
	if (!mci) {
		cpc925_printk(KERN_ERR, "No memory for mem_ctl_info\n");
		res = -ENOMEM;
+24 −20
Original line number Diff line number Diff line
@@ -1044,7 +1044,7 @@ static void e752x_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev,
	int drc_drbg;		/* DRB granularity 0=64mb, 1=128mb */
	int drc_ddim;		/* DRAM Data Integrity Mode 0=none, 2=edac */
	u8 value;
	u32 dra, drc, cumul_size;
	u32 dra, drc, cumul_size, i;

	dra = 0;
	for (index = 0; index < 4; index++) {
@@ -1053,7 +1053,7 @@ static void e752x_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev,
		dra |= dra_reg << (index * 8);
	}
	pci_read_config_dword(pdev, E752X_DRC, &drc);
	drc_chan = dual_channel_active(ddrcsr);
	drc_chan = dual_channel_active(ddrcsr) ? 1 : 0;
	drc_drbg = drc_chan + 1;	/* 128 in dual mode, 64 in single */
	drc_ddim = (drc >> 20) & 0x3;

@@ -1080,9 +1080,12 @@ static void e752x_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev,
		csrow->last_page = cumul_size - 1;
		csrow->nr_pages = cumul_size - last_cumul_size;
		last_cumul_size = cumul_size;
		csrow->grain = 1 << 12;	/* 4KiB - resolution of CELOG */
		csrow->mtype = MEM_RDDR;	/* only one type supported */
		csrow->dtype = mem_dev ? DEV_X4 : DEV_X8;

		for (i = 0; i < drc_chan + 1; i++) {
			struct dimm_info *dimm = csrow->channels[i].dimm;
			dimm->grain = 1 << 12;	/* 4KiB - resolution of CELOG */
			dimm->mtype = MEM_RDDR;	/* only one type supported */
			dimm->dtype = mem_dev ? DEV_X4 : DEV_X8;

			/*
			* if single channel or x8 devices then SECDED
@@ -1090,14 +1093,15 @@ static void e752x_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev,
			*/
			if (drc_ddim) {
				if (drc_chan && mem_dev) {
				csrow->edac_mode = EDAC_S4ECD4ED;
					dimm->edac_mode = EDAC_S4ECD4ED;
					mci->edac_cap |= EDAC_FLAG_S4ECD4ED;
				} else {
				csrow->edac_mode = EDAC_SECDED;
					dimm->edac_mode = EDAC_SECDED;
					mci->edac_cap |= EDAC_FLAG_SECDED;
				}
			} else
			csrow->edac_mode = EDAC_NONE;
				dimm->edac_mode = EDAC_NONE;
		}
	}
}

Loading