Skip to content

Commit

Permalink
edac: move dimm properties to struct dimm_info
Browse files Browse the repository at this point in the history
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: Aristeu Rozanski <[email protected]>
Reviewed-by: Borislav Petkov <[email protected]>
Acked-by: Chris Metcalf <[email protected]>
Cc: Doug Thompson <[email protected]>
Cc: Borislav Petkov <[email protected]>
Cc: Mark Gross <[email protected]>
Cc: Jason Uhlenkott <[email protected]>
Cc: Tim Small <[email protected]>
Cc: Ranganathan Desikan <[email protected]>
Cc: "Arvind R." <[email protected]>
Cc: Olof Johansson <[email protected]>
Cc: Egor Martovetsky <[email protected]>
Cc: Michal Marek <[email protected]>
Cc: Jiri Kosina <[email protected]>
Cc: Joe Perches <[email protected]>
Cc: Dmitry Eremin-Solenikov <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Hitoshi Mitake <[email protected]>
Cc: Andrew Morton <[email protected]>
Cc: James Bottomley <[email protected]>
Cc: "Niklas Söderlund" <[email protected]>
Cc: Shaohui Xie <[email protected]>
Cc: Josh Boyer <[email protected]>
Cc: Mike Williams <[email protected]>
Cc: [email protected]
Signed-off-by: Mauro Carvalho Chehab <[email protected]>
  • Loading branch information
Mauro Carvalho Chehab committed May 28, 2012
1 parent a7d7d2e commit 084a4fc
Show file tree
Hide file tree
Showing 28 changed files with 334 additions and 257 deletions.
18 changes: 12 additions & 6 deletions drivers/edac/amd64_edac.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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",
Expand All @@ -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_S4ECD4ED : EDAC_SECDED;
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;
Expand Down
10 changes: 6 additions & 4 deletions drivers/edac/amd76x_edac.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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;
}
}

Expand Down
10 changes: 8 additions & 2 deletions drivers/edac/cell_edac.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;) {
Expand All @@ -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",
Expand Down
62 changes: 33 additions & 29 deletions drivers/edac/cpc925_edac.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -354,32 +355,35 @@ 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;

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

switch ((mbmr & MBMR_MODE_MASK) >> MBMR_MODE_SHIFT) {
case 6: /* 0110, no way to differentiate X8 VS X16 */
case 5: /* 0101 */
case 8: /* 1000 */
csrow->dtype = DEV_X16;
break;
case 7: /* 0111 */
case 9: /* 1001 */
csrow->dtype = DEV_X8;
break;
default:
csrow->dtype = DEV_UNKNOWN;
break;
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 */
dimm->grain = 32; /* four-beat burst of 32 bytes */
break;
case 2: /* Dual channel */
default:
dimm->grain = 64; /* four-beat burst of 64 bytes */
break;
}

switch ((mbmr & MBMR_MODE_MASK) >> MBMR_MODE_SHIFT) {
case 6: /* 0110, no way to differentiate X8 VS X16 */
case 5: /* 0101 */
case 8: /* 1000 */
dimm->dtype = DEV_X16;
break;
case 7: /* 0111 */
case 9: /* 1001 */
dimm->dtype = DEV_X8;
break;
default:
dimm->dtype = DEV_UNKNOWN;
break;
}
}
}
}
Expand Down Expand Up @@ -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;
Expand Down
44 changes: 24 additions & 20 deletions drivers/edac/e752x_edac.c
Original file line number Diff line number Diff line change
Expand Up @@ -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++) {
Expand All @@ -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;

Expand All @@ -1080,24 +1080,28 @@ 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;

/*
* if single channel or x8 devices then SECDED
* if dual channel and x4 then S4ECD4ED
*/
if (drc_ddim) {
if (drc_chan && mem_dev) {
csrow->edac_mode = EDAC_S4ECD4ED;
mci->edac_cap |= EDAC_FLAG_S4ECD4ED;
} else {
csrow->edac_mode = EDAC_SECDED;
mci->edac_cap |= EDAC_FLAG_SECDED;
}
} else
csrow->edac_mode = EDAC_NONE;

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
* if dual channel and x4 then S4ECD4ED
*/
if (drc_ddim) {
if (drc_chan && mem_dev) {
dimm->edac_mode = EDAC_S4ECD4ED;
mci->edac_cap |= EDAC_FLAG_S4ECD4ED;
} else {
dimm->edac_mode = EDAC_SECDED;
mci->edac_cap |= EDAC_FLAG_SECDED;
}
} else
dimm->edac_mode = EDAC_NONE;
}
}
}

Expand Down
44 changes: 25 additions & 19 deletions drivers/edac/e7xxx_edac.c
Original file line number Diff line number Diff line change
Expand Up @@ -347,11 +347,12 @@ static void e7xxx_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev,
int dev_idx, u32 drc)
{
unsigned long last_cumul_size;
int index;
int index, j;
u8 value;
u32 dra, cumul_size;
int drc_chan, drc_drbg, drc_ddim, mem_dev;
struct csrow_info *csrow;
struct dimm_info *dimm;

pci_read_config_dword(pdev, E7XXX_DRA, &dra);
drc_chan = dual_channel_active(drc, dev_idx);
Expand Down Expand Up @@ -381,24 +382,29 @@ static void e7xxx_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;

/*
* if single channel or x8 devices then SECDED
* if dual channel and x4 then S4ECD4ED
*/
if (drc_ddim) {
if (drc_chan && mem_dev) {
csrow->edac_mode = EDAC_S4ECD4ED;
mci->edac_cap |= EDAC_FLAG_S4ECD4ED;
} else {
csrow->edac_mode = EDAC_SECDED;
mci->edac_cap |= EDAC_FLAG_SECDED;
}
} else
csrow->edac_mode = EDAC_NONE;

for (j = 0; j < drc_chan + 1; j++) {
dimm = csrow->channels[j].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
* if dual channel and x4 then S4ECD4ED
*/
if (drc_ddim) {
if (drc_chan && mem_dev) {
dimm->edac_mode = EDAC_S4ECD4ED;
mci->edac_cap |= EDAC_FLAG_S4ECD4ED;
} else {
dimm->edac_mode = EDAC_SECDED;
mci->edac_cap |= EDAC_FLAG_SECDED;
}
} else
dimm->edac_mode = EDAC_NONE;
}
}
}

Expand Down
Loading

0 comments on commit 084a4fc

Please sign in to comment.