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

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
......@@ -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_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;
......
......@@ -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;
}
}
......
......@@ -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",
......
......@@ -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,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;
}
}
}
}
......@@ -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;
......
......@@ -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,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;
}
}
}
......
......@@ -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);
......@@ -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;
}
}
}
......
......@@ -43,7 +43,7 @@ static void edac_mc_dump_channel(struct rank_info *chan)
{
debugf4("\tchannel = %p\n", chan);
debugf4("\tchannel->chan_idx = %d\n", chan->chan_idx);
debugf4("\tchannel->ce_count = %d\n", chan->ce_count);
debugf4("\tchannel->ce_count = %d\n", chan->dimm->ce_count);
debugf4("\tchannel->label = '%s'\n", chan->dimm->label);
debugf4("\tchannel->csrow = %p\n\n", chan->csrow);
}
......@@ -695,6 +695,7 @@ void edac_mc_handle_ce(struct mem_ctl_info *mci,
{
unsigned long remapped_page;
char *label = NULL;
u32 grain;
debugf3("MC%d: %s()\n", mci->mc_idx, __func__);
......@@ -719,6 +720,7 @@ void edac_mc_handle_ce(struct mem_ctl_info *mci,
}
label = mci->csrows[row].channels[channel].dimm->label;
grain = mci->csrows[row].channels[channel].dimm->grain;
if (edac_mc_get_log_ce())
/* FIXME - put in DIMM location */
......@@ -726,11 +728,12 @@ void edac_mc_handle_ce(struct mem_ctl_info *mci,
"CE page 0x%lx, offset 0x%lx, grain %d, syndrome "
"0x%lx, row %d, channel %d, label \"%s\": %s\n",
page_frame_number, offset_in_page,
mci->csrows[row].grain, syndrome, row, channel,
grain, syndrome, row, channel,
label, msg);
mci->ce_count++;
mci->csrows[row].ce_count++;
mci->csrows[row].channels[channel].dimm->ce_count++;
mci->csrows[row].channels[channel].ce_count++;
if (mci->scrub_mode & SCRUB_SW_SRC) {
......@@ -747,8 +750,7 @@ void edac_mc_handle_ce(struct mem_ctl_info *mci,
mci->ctl_page_to_phys(mci, page_frame_number) :
page_frame_number;
edac_mc_scrub_block(remapped_page, offset_in_page,
mci->csrows[row].grain);
edac_mc_scrub_block(remapped_page, offset_in_page, grain);
}
}
EXPORT_SYMBOL_GPL(edac_mc_handle_ce);
......@@ -774,6 +776,7 @@ void edac_mc_handle_ue(struct mem_ctl_info *mci,
int chan;
int chars;
char *label = NULL;
u32 grain;
debugf3("MC%d: %s()\n", mci->mc_idx, __func__);
......@@ -787,6 +790,7 @@ void edac_mc_handle_ue(struct mem_ctl_info *mci,
return;
}
grain = mci->csrows[row].channels[0].dimm->grain;
label = mci->csrows[row].channels[0].dimm->label;
chars = snprintf(pos, len + 1, "%s", label);
len -= chars;
......@@ -804,14 +808,13 @@ void edac_mc_handle_ue(struct mem_ctl_info *mci,
edac_mc_printk(mci, KERN_EMERG,
"UE page 0x%lx, offset 0x%lx, grain %d, row %d, "
"labels \"%s\": %s\n", page_frame_number,
offset_in_page, mci->csrows[row].grain, row,
labels, msg);
offset_in_page, grain, row, labels, msg);
if (edac_mc_get_panic_on_ue())
panic("EDAC MC%d: UE page 0x%lx, offset 0x%lx, grain %d, "
"row %d, labels \"%s\": %s\n", mci->mc_idx,
page_frame_number, offset_in_page,
mci->csrows[row].grain, row, labels, msg);
grain, row, labels, msg);
mci->ue_count++;
mci->csrows[row].ue_count++;
......@@ -883,6 +886,7 @@ void edac_mc_handle_fbd_ue(struct mem_ctl_info *mci,
chars = snprintf(pos, len + 1, "%s", label);
len -= chars;
pos += chars;
chars = snprintf(pos, len + 1, "-%s",
mci->csrows[csrow].channels[channelb].dimm->label);
......@@ -936,6 +940,7 @@ void edac_mc_handle_fbd_ce(struct mem_ctl_info *mci,
mci->ce_count++;
mci->csrows[csrow].ce_count++;
mci->csrows[csrow].channels[channel].dimm->ce_count++;
mci->csrows[csrow].channels[channel].ce_count++;
}
EXPORT_SYMBOL(edac_mc_handle_fbd_ce);
......@@ -150,19 +150,19 @@ static ssize_t csrow_size_show(struct csrow_info *csrow, char *data,
static ssize_t csrow_mem_type_show(struct csrow_info *csrow, char *data,
int private)
{
return sprintf(data, "%s\n", mem_types[csrow->mtype]);
return sprintf(data, "%s\n", mem_types[csrow->channels[0].dimm->mtype]);
}
static ssize_t csrow_dev_type_show(struct csrow_info *csrow, char *data,
int private)
{
return sprintf(data, "%s\n", dev_types[csrow->dtype]);
return sprintf(data, "%s\n", dev_types[csrow->channels[0].dimm->dtype]);
}
static ssize_t csrow_edac_mode_show(struct csrow_info *csrow, char *data,
int private)
{
return sprintf(data, "%s\n", edac_caps[csrow->edac_mode]);
return sprintf(data, "%s\n", edac_caps[csrow->channels[0].dimm->edac_mode]);
}
/* show/store functions for DIMM Label attributes */
......
......@@ -304,7 +304,7 @@ static int i3000_is_interleaved(const unsigned char *c0dra,
static int i3000_probe1(struct pci_dev *pdev, int dev_idx)
{
int rc;
int i;
int i, j;
struct mem_ctl_info *mci = NULL;
unsigned long last_cumul_size;
int interleaved, nr_channels;
......@@ -386,19 +386,21 @@ static int i3000_probe1(struct pci_dev *pdev, int dev_idx)
cumul_size <<= 1;
debugf3("MC: %s(): (%d) cumul_size 0x%x\n",
__func__, i, cumul_size);
if (cumul_size == last_cumul_size) {
csrow->mtype = MEM_EMPTY;
if (cumul_size == last_cumul_size)
continue;
}
csrow->first_page = last_cumul_size;
csrow->last_page = cumul_size - 1;
csrow->nr_pages = cumul_size - last_cumul_size;
last_cumul_size = cumul_size;
csrow->grain = I3000_DEAP_GRAIN;
csrow->mtype = MEM_DDR2;
csrow->dtype = DEV_UNKNOWN;
csrow->edac_mode = EDAC_UNKNOWN;
for (j = 0; j < nr_channels; j++) {
struct dimm_info *dimm = csrow->channels[j].dimm;
dimm->grain = I3000_DEAP_GRAIN;
dimm->mtype = MEM_DDR2;
dimm->dtype = DEV_UNKNOWN;
dimm->edac_mode = EDAC_UNKNOWN;
}
}
/*
......
......@@ -319,7 +319,7 @@ static unsigned long drb_to_nr_pages(
static int i3200_probe1(struct pci_dev *pdev, int dev_idx)
{
int rc;
int i;
int i, j;
struct mem_ctl_info *mci = NULL;
unsigned long last_page;
u16 drbs[I3200_CHANNELS][I3200_RANKS_PER_CHANNEL];
......@@ -375,20 +375,22 @@ static int i3200_probe1(struct pci_dev *pdev, int dev_idx)
i / I3200_RANKS_PER_CHANNEL,
i % I3200_RANKS_PER_CHANNEL);
if (nr_pages == 0) {
csrow->mtype = MEM_EMPTY;
if (nr_pages == 0)
continue;
}
csrow->first_page = last_page + 1;
last_page += nr_pages;
csrow->last_page = last_page;
csrow->nr_pages = nr_pages;
csrow->grain = nr_pages << PAGE_SHIFT;
csrow->mtype = MEM_DDR2;
csrow->dtype = DEV_UNKNOWN;
csrow->edac_mode = EDAC_UNKNOWN;
for (j = 0; j < nr_channels; j++) {
struct dimm_info *dimm = csrow->channels[j].dimm;
dimm->grain = nr_pages << PAGE_SHIFT;
dimm->mtype = MEM_DDR2;
dimm->dtype = DEV_UNKNOWN;
dimm->edac_mode = EDAC_UNKNOWN;
}
}
i3200_clear_error_info(mci);
......
......@@ -1268,25 +1268,23 @@ static int i5000_init_csrows(struct mem_ctl_info *mci)
p_csrow->last_page = 9 + csrow * 20;
p_csrow->page_mask = 0xFFF;
p_csrow->grain = 8;
csrow_megs = 0;
for (channel = 0; channel < pvt->maxch; channel++) {
csrow_megs += pvt->dimm_info[csrow][channel].megabytes;
}
p_csrow->channels[channel].dimm->grain = 8;
p_csrow->nr_pages = csrow_megs << 8;
/* Assume DDR2 for now */
p_csrow->channels[channel].dimm->mtype = MEM_FB_DDR2;
/* Assume DDR2 for now */
p_csrow->mtype = MEM_FB_DDR2;
/* ask what device type on this row */
if (MTR_DRAM_WIDTH(mtr))
p_csrow->channels[channel].dimm->dtype = DEV_X8;
else
p_csrow->channels[channel].dimm->dtype = DEV_X4;
/* ask what device type on this row */
if (MTR_DRAM_WIDTH(mtr))
p_csrow->dtype = DEV_X8;
else
p_csrow->dtype = DEV_X4;
p_csrow->edac_mode = EDAC_S8ECD8ED;
p_csrow->channels[channel].dimm->edac_mode = EDAC_S8ECD8ED;
}
p_csrow->nr_pages = csrow_megs << 8;
empty = 0;
}
......
......@@ -428,12 +428,16 @@ static void i5100_handle_ce(struct mem_ctl_info *mci,
const char *msg)
{
const int csrow = i5100_rank_to_csrow(mci, chan, rank);
char *label = NULL;
if (mci->csrows[csrow].channels[0].dimm)
label = mci->csrows[csrow].channels[0].dimm->label;
printk(KERN_ERR
"CE chan %d, bank %u, rank %u, syndrome 0x%lx, "
"cas %u, ras %u, csrow %u, label \"%s\": %s\n",
chan, bank, rank, syndrome, cas, ras,
csrow, mci->csrows[csrow].channels[0].dimm->label, msg);
csrow, label, msg);
mci->ce_count++;
mci->csrows[csrow].ce_count++;
......@@ -450,12 +454,16 @@ static void i5100_handle_ue(struct mem_ctl_info *mci,
const char *msg)
{
const int csrow = i5100_rank_to_csrow(mci, chan, rank);
char *label = NULL;
if (mci->csrows[csrow].channels[0].dimm)
label = mci->csrows[csrow].channels[0].dimm->label;
printk(KERN_ERR
"UE chan %d, bank %u, rank %u, syndrome 0x%lx, "
"cas %u, ras %u, csrow %u, label \"%s\": %s\n",
chan, bank, rank, syndrome, cas, ras,
csrow, mci->csrows[csrow].channels[0].dimm->label, msg);
csrow, label, msg);
mci->ue_count++;
mci->csrows[csrow].ue_count++;
......@@ -837,6 +845,7 @@ static void __devinit i5100_init_csrows(struct mem_ctl_info *mci)
int i;
unsigned long total_pages = 0UL;
struct i5100_priv *priv = mci->pvt_info;
struct dimm_info *dimm;
for (i = 0; i < mci->nr_csrows; i++) {
const unsigned long npages = i5100_npages(mci, i);
......@@ -852,27 +861,22 @@ static void __devinit i5100_init_csrows(struct mem_ctl_info *mci)
*/
mci->csrows[i].first_page = total_pages;
mci->csrows[i].last_page = total_pages + npages - 1;
mci->csrows[i].page_mask = 0UL;
mci->csrows[i].nr_pages = npages;
mci->csrows[i].grain = 32;
mci->csrows[i].csrow_idx = i;
mci->csrows[i].dtype =
(priv->mtr[chan][rank].width == 4) ? DEV_X4 : DEV_X8;
mci->csrows[i].ue_count = 0;
mci->csrows[i].ce_count = 0;
mci->csrows[i].mtype = MEM_RDDR2;
mci->csrows[i].edac_mode = EDAC_SECDED;
mci->csrows[i].mci = mci;
mci->csrows[i].nr_channels = 1;
mci->csrows[i].channels[0].chan_idx = 0;
mci->csrows[i].channels[0].ce_count = 0;
mci->csrows[i].channels[0].csrow = mci->csrows + i;
snprintf(mci->csrows[i].channels[0].dimm->label,
sizeof(mci->csrows[i].channels[0].dimm->label),
"DIMM%u", i5100_rank_to_slot(mci, chan, rank));
total_pages += npages;
dimm = mci->csrows[i].channels[0].dimm;
dimm->grain = 32;
dimm->dtype = (priv->mtr[chan][rank].width == 4) ?
DEV_X4 : DEV_X8;
dimm->mtype = MEM_RDDR2;
dimm->edac_mode = EDAC_SECDED;
snprintf(dimm->label, sizeof(dimm->label),
"DIMM%u",
i5100_rank_to_slot(mci, chan, rank));
}
}
......
......@@ -1159,6 +1159,7 @@ static int i5400_init_csrows(struct mem_ctl_info *mci)
int csrow_megs;
int channel;
int csrow;
struct dimm_info *dimm;
pvt = mci->pvt_info;
......@@ -1184,24 +1185,17 @@ static int i5400_init_csrows(struct mem_ctl_info *mci)
p_csrow->last_page = 9 + csrow * 20;
p_csrow->page_mask = 0xFFF;
p_csrow->grain = 8;
csrow_megs = 0;
for (channel = 0; channel < pvt->maxch; channel++)
for (channel = 0; channel < pvt->maxch; channel++) {
csrow_megs += pvt->dimm_info[csrow][channel].megabytes;
p_csrow->nr_pages = csrow_megs << 8;
/* Assume DDR2 for now */
p_csrow->mtype = MEM_FB_DDR2;
/* ask what device type on this row */
if (MTR_DRAM_WIDTH(mtr))
p_csrow->dtype = DEV_X8;
else
p_csrow->dtype = DEV_X4;
p_csrow->edac_mode = EDAC_S8ECD8ED;
p_csrow->nr_pages = csrow_megs << 8;
dimm = p_csrow->channels[channel].dimm;
dimm->grain = 8;
dimm->dtype = MTR_DRAM_WIDTH(mtr) ? DEV_X8 : DEV_X4;
dimm->mtype = MEM_RDDR2;
dimm->edac_mode = EDAC_SECDED;
}
empty = 0;
}
......
......@@ -618,6 +618,7 @@ static int decode_mtr(struct i7300_pvt *pvt,
int slot, int ch, int branch,
struct i7300_dimm_info *dinfo,
struct csrow_info *p_csrow,
struct dimm_info *dimm,
u32 *nr_pages)
{
int mtr, ans, addrBits, channel;
......@@ -663,10 +664,7 @@ static int decode_mtr(struct i7300_pvt *pvt,
debugf2("\t\tNUMCOL: %s\n", numcol_toString[MTR_DIMM_COLS(mtr)]);
debugf2("\t\tSIZE: %d MB\n", dinfo->megabytes);
p_csrow->grain = 8;
p_csrow->mtype = MEM_FB_DDR2;
p_csrow->csrow_idx = slot;
p_csrow->page_mask = 0;
/*
* The type of error detection actually depends of the
......@@ -677,15 +675,17 @@ static int decode_mtr(struct i7300_pvt *pvt,
* See datasheet Sections 7.3.6 to 7.3.8
*/
dimm->grain = 8;
dimm->mtype = MEM_FB_DDR2;
if (IS_SINGLE_MODE(pvt->mc_settings_a)) {
p_csrow->edac_mode = EDAC_SECDED;
dimm->edac_mode = EDAC_SECDED;
debugf2("\t\tECC code is 8-byte-over-32-byte SECDED+ code\n");
} else {
debugf2("\t\tECC code is on Lockstep mode\n");
if (MTR_DRAM_WIDTH(mtr) == 8)
p_csrow->edac_mode = EDAC_S8ECD8ED;
dimm->edac_mode = EDAC_S8ECD8ED;
else
p_csrow->edac_mode = EDAC_S4ECD4ED;
dimm->edac_mode = EDAC_S4ECD4ED;
}
/* ask what device type on this row */
......@@ -694,9 +694,9 @@ static int decode_mtr(struct i7300_pvt *pvt,
IS_SCRBALGO_ENHANCED(pvt->mc_settings) ?
"enhanced" : "normal");
p_csrow->dtype = DEV_X8;
dimm->dtype = DEV_X8;
} else
p_csrow->dtype = DEV_X4;
dimm->dtype = DEV_X4;
return mtr;
}
......@@ -779,6 +779,7 @@ static int i7300_init_csrows(struct mem_ctl_info *mci)
int mtr;