mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-29 05:44:11 +00:00
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: Aristeu Rozanski <arozansk@redhat.com> Reviewed-by: Borislav Petkov <borislav.petkov@amd.com> Acked-by: Chris 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: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
parent
a7d7d2e1a0
commit
084a4fccef
28 changed files with 331 additions and 254 deletions
|
@ -2187,7 +2187,9 @@ static int init_csrows(struct mem_ctl_info *mci)
|
||||||
struct amd64_pvt *pvt = mci->pvt_info;
|
struct amd64_pvt *pvt = mci->pvt_info;
|
||||||
u64 input_addr_min, input_addr_max, sys_addr, base, mask;
|
u64 input_addr_min, input_addr_max, sys_addr, base, mask;
|
||||||
u32 val;
|
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);
|
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;
|
csrow->page_mask = ~mask;
|
||||||
/* 8 bytes of resolution */
|
/* 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(" for MC node %d csrow %d:\n", pvt->mc_node_id, i);
|
||||||
debugf1(" input_addr_min: 0x%lx input_addr_max: 0x%lx\n",
|
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
|
* determine whether CHIPKILL or JUST ECC or NO ECC is operating
|
||||||
*/
|
*/
|
||||||
if (pvt->nbcfg & NBCFG_ECC_ENABLE)
|
if (pvt->nbcfg & NBCFG_ECC_ENABLE)
|
||||||
csrow->edac_mode =
|
edac_mode = (pvt->nbcfg & NBCFG_CHIPKILL) ?
|
||||||
(pvt->nbcfg & NBCFG_CHIPKILL) ?
|
|
||||||
EDAC_S4ECD4ED : EDAC_SECDED;
|
EDAC_S4ECD4ED : EDAC_SECDED;
|
||||||
else
|
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;
|
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)
|
enum edac_type edac_mode)
|
||||||
{
|
{
|
||||||
struct csrow_info *csrow;
|
struct csrow_info *csrow;
|
||||||
|
struct dimm_info *dimm;
|
||||||
u32 mba, mba_base, mba_mask, dms;
|
u32 mba, mba_base, mba_mask, dms;
|
||||||
int index;
|
int index;
|
||||||
|
|
||||||
for (index = 0; index < mci->nr_csrows; index++) {
|
for (index = 0; index < mci->nr_csrows; index++) {
|
||||||
csrow = &mci->csrows[index];
|
csrow = &mci->csrows[index];
|
||||||
|
dimm = csrow->channels[0].dimm;
|
||||||
|
|
||||||
/* find the DRAM Chip Select Base address and mask */
|
/* find the DRAM Chip Select Base address and mask */
|
||||||
pci_read_config_dword(pdev,
|
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->nr_pages = (mba_mask + 1) >> PAGE_SHIFT;
|
||||||
csrow->last_page = csrow->first_page + csrow->nr_pages - 1;
|
csrow->last_page = csrow->first_page + csrow->nr_pages - 1;
|
||||||
csrow->page_mask = mba_mask >> PAGE_SHIFT;
|
csrow->page_mask = mba_mask >> PAGE_SHIFT;
|
||||||
csrow->grain = csrow->nr_pages << PAGE_SHIFT;
|
dimm->grain = csrow->nr_pages << PAGE_SHIFT;
|
||||||
csrow->mtype = MEM_RDDR;
|
dimm->mtype = MEM_RDDR;
|
||||||
csrow->dtype = ((dms >> index) & 0x1) ? DEV_X4 : DEV_UNKNOWN;
|
dimm->dtype = ((dms >> index) & 0x1) ? DEV_X4 : DEV_UNKNOWN;
|
||||||
csrow->edac_mode = edac_mode;
|
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)
|
static void __devinit cell_edac_init_csrows(struct mem_ctl_info *mci)
|
||||||
{
|
{
|
||||||
struct csrow_info *csrow = &mci->csrows[0];
|
struct csrow_info *csrow = &mci->csrows[0];
|
||||||
|
struct dimm_info *dimm;
|
||||||
struct cell_edac_priv *priv = mci->pvt_info;
|
struct cell_edac_priv *priv = mci->pvt_info;
|
||||||
struct device_node *np;
|
struct device_node *np;
|
||||||
|
int j;
|
||||||
|
|
||||||
for (np = NULL;
|
for (np = NULL;
|
||||||
(np = of_find_node_by_name(np, "memory")) != 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->first_page = r.start >> PAGE_SHIFT;
|
||||||
csrow->nr_pages = resource_size(&r) >> PAGE_SHIFT;
|
csrow->nr_pages = resource_size(&r) >> PAGE_SHIFT;
|
||||||
csrow->last_page = csrow->first_page + csrow->nr_pages - 1;
|
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,
|
dev_dbg(mci->dev,
|
||||||
"Initialized on node %d, chanmask=0x%x,"
|
"Initialized on node %d, chanmask=0x%x,"
|
||||||
" first_page=0x%lx, nr_pages=0x%x\n",
|
" 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 cpc925_mc_pdata *pdata = mci->pvt_info;
|
||||||
struct csrow_info *csrow;
|
struct csrow_info *csrow;
|
||||||
int index;
|
struct dimm_info *dimm;
|
||||||
|
int index, j;
|
||||||
u32 mbmr, mbbar, bba;
|
u32 mbmr, mbbar, bba;
|
||||||
unsigned long row_size, last_nr_pages = 0;
|
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;
|
csrow->last_page = csrow->first_page + csrow->nr_pages - 1;
|
||||||
last_nr_pages = csrow->last_page + 1;
|
last_nr_pages = csrow->last_page + 1;
|
||||||
|
|
||||||
csrow->mtype = MEM_RDDR;
|
for (j = 0; j < csrow->nr_channels; j++) {
|
||||||
csrow->edac_mode = EDAC_SECDED;
|
dimm = csrow->channels[j].dimm;
|
||||||
|
dimm->mtype = MEM_RDDR;
|
||||||
|
dimm->edac_mode = EDAC_SECDED;
|
||||||
|
|
||||||
switch (csrow->nr_channels) {
|
switch (csrow->nr_channels) {
|
||||||
case 1: /* Single channel */
|
case 1: /* Single channel */
|
||||||
csrow->grain = 32; /* four-beat burst of 32 bytes */
|
dimm->grain = 32; /* four-beat burst of 32 bytes */
|
||||||
break;
|
break;
|
||||||
case 2: /* Dual channel */
|
case 2: /* Dual channel */
|
||||||
default:
|
default:
|
||||||
csrow->grain = 64; /* four-beat burst of 64 bytes */
|
dimm->grain = 64; /* four-beat burst of 64 bytes */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -371,17 +374,18 @@ static void cpc925_init_csrows(struct mem_ctl_info *mci)
|
||||||
case 6: /* 0110, no way to differentiate X8 VS X16 */
|
case 6: /* 0110, no way to differentiate X8 VS X16 */
|
||||||
case 5: /* 0101 */
|
case 5: /* 0101 */
|
||||||
case 8: /* 1000 */
|
case 8: /* 1000 */
|
||||||
csrow->dtype = DEV_X16;
|
dimm->dtype = DEV_X16;
|
||||||
break;
|
break;
|
||||||
case 7: /* 0111 */
|
case 7: /* 0111 */
|
||||||
case 9: /* 1001 */
|
case 9: /* 1001 */
|
||||||
csrow->dtype = DEV_X8;
|
dimm->dtype = DEV_X8;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
csrow->dtype = DEV_UNKNOWN;
|
dimm->dtype = DEV_UNKNOWN;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enable memory controller ECC detection */
|
/* Enable memory controller ECC detection */
|
||||||
|
@ -962,9 +966,9 @@ static int __devinit cpc925_probe(struct platform_device *pdev)
|
||||||
goto err2;
|
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),
|
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) {
|
if (!mci) {
|
||||||
cpc925_printk(KERN_ERR, "No memory for mem_ctl_info\n");
|
cpc925_printk(KERN_ERR, "No memory for mem_ctl_info\n");
|
||||||
res = -ENOMEM;
|
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_drbg; /* DRB granularity 0=64mb, 1=128mb */
|
||||||
int drc_ddim; /* DRAM Data Integrity Mode 0=none, 2=edac */
|
int drc_ddim; /* DRAM Data Integrity Mode 0=none, 2=edac */
|
||||||
u8 value;
|
u8 value;
|
||||||
u32 dra, drc, cumul_size;
|
u32 dra, drc, cumul_size, i;
|
||||||
|
|
||||||
dra = 0;
|
dra = 0;
|
||||||
for (index = 0; index < 4; index++) {
|
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);
|
dra |= dra_reg << (index * 8);
|
||||||
}
|
}
|
||||||
pci_read_config_dword(pdev, E752X_DRC, &drc);
|
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_drbg = drc_chan + 1; /* 128 in dual mode, 64 in single */
|
||||||
drc_ddim = (drc >> 20) & 0x3;
|
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->last_page = cumul_size - 1;
|
||||||
csrow->nr_pages = cumul_size - last_cumul_size;
|
csrow->nr_pages = cumul_size - last_cumul_size;
|
||||||
last_cumul_size = cumul_size;
|
last_cumul_size = cumul_size;
|
||||||
csrow->grain = 1 << 12; /* 4KiB - resolution of CELOG */
|
|
||||||
csrow->mtype = MEM_RDDR; /* only one type supported */
|
for (i = 0; i < drc_chan + 1; i++) {
|
||||||
csrow->dtype = mem_dev ? DEV_X4 : DEV_X8;
|
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 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_ddim) {
|
||||||
if (drc_chan && mem_dev) {
|
if (drc_chan && mem_dev) {
|
||||||
csrow->edac_mode = EDAC_S4ECD4ED;
|
dimm->edac_mode = EDAC_S4ECD4ED;
|
||||||
mci->edac_cap |= EDAC_FLAG_S4ECD4ED;
|
mci->edac_cap |= EDAC_FLAG_S4ECD4ED;
|
||||||
} else {
|
} else {
|
||||||
csrow->edac_mode = EDAC_SECDED;
|
dimm->edac_mode = EDAC_SECDED;
|
||||||
mci->edac_cap |= EDAC_FLAG_SECDED;
|
mci->edac_cap |= EDAC_FLAG_SECDED;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
csrow->edac_mode = EDAC_NONE;
|
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)
|
int dev_idx, u32 drc)
|
||||||
{
|
{
|
||||||
unsigned long last_cumul_size;
|
unsigned long last_cumul_size;
|
||||||
int index;
|
int index, j;
|
||||||
u8 value;
|
u8 value;
|
||||||
u32 dra, cumul_size;
|
u32 dra, cumul_size;
|
||||||
int drc_chan, drc_drbg, drc_ddim, mem_dev;
|
int drc_chan, drc_drbg, drc_ddim, mem_dev;
|
||||||
struct csrow_info *csrow;
|
struct csrow_info *csrow;
|
||||||
|
struct dimm_info *dimm;
|
||||||
|
|
||||||
pci_read_config_dword(pdev, E7XXX_DRA, &dra);
|
pci_read_config_dword(pdev, E7XXX_DRA, &dra);
|
||||||
drc_chan = dual_channel_active(drc, dev_idx);
|
drc_chan = dual_channel_active(drc, dev_idx);
|
||||||
|
@ -381,9 +382,13 @@ static void e7xxx_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev,
|
||||||
csrow->last_page = cumul_size - 1;
|
csrow->last_page = cumul_size - 1;
|
||||||
csrow->nr_pages = cumul_size - last_cumul_size;
|
csrow->nr_pages = cumul_size - last_cumul_size;
|
||||||
last_cumul_size = cumul_size;
|
last_cumul_size = cumul_size;
|
||||||
csrow->grain = 1 << 12; /* 4KiB - resolution of CELOG */
|
|
||||||
csrow->mtype = MEM_RDDR; /* only one type supported */
|
for (j = 0; j < drc_chan + 1; j++) {
|
||||||
csrow->dtype = mem_dev ? DEV_X4 : DEV_X8;
|
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 single channel or x8 devices then SECDED
|
||||||
|
@ -391,14 +396,15 @@ static void e7xxx_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev,
|
||||||
*/
|
*/
|
||||||
if (drc_ddim) {
|
if (drc_ddim) {
|
||||||
if (drc_chan && mem_dev) {
|
if (drc_chan && mem_dev) {
|
||||||
csrow->edac_mode = EDAC_S4ECD4ED;
|
dimm->edac_mode = EDAC_S4ECD4ED;
|
||||||
mci->edac_cap |= EDAC_FLAG_S4ECD4ED;
|
mci->edac_cap |= EDAC_FLAG_S4ECD4ED;
|
||||||
} else {
|
} else {
|
||||||
csrow->edac_mode = EDAC_SECDED;
|
dimm->edac_mode = EDAC_SECDED;
|
||||||
mci->edac_cap |= EDAC_FLAG_SECDED;
|
mci->edac_cap |= EDAC_FLAG_SECDED;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
csrow->edac_mode = EDAC_NONE;
|
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 = %p\n", chan);
|
||||||
debugf4("\tchannel->chan_idx = %d\n", chan->chan_idx);
|
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->label = '%s'\n", chan->dimm->label);
|
||||||
debugf4("\tchannel->csrow = %p\n\n", chan->csrow);
|
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;
|
unsigned long remapped_page;
|
||||||
char *label = NULL;
|
char *label = NULL;
|
||||||
|
u32 grain;
|
||||||
|
|
||||||
debugf3("MC%d: %s()\n", mci->mc_idx, __func__);
|
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;
|
label = mci->csrows[row].channels[channel].dimm->label;
|
||||||
|
grain = mci->csrows[row].channels[channel].dimm->grain;
|
||||||
|
|
||||||
if (edac_mc_get_log_ce())
|
if (edac_mc_get_log_ce())
|
||||||
/* FIXME - put in DIMM location */
|
/* 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 "
|
"CE page 0x%lx, offset 0x%lx, grain %d, syndrome "
|
||||||
"0x%lx, row %d, channel %d, label \"%s\": %s\n",
|
"0x%lx, row %d, channel %d, label \"%s\": %s\n",
|
||||||
page_frame_number, offset_in_page,
|
page_frame_number, offset_in_page,
|
||||||
mci->csrows[row].grain, syndrome, row, channel,
|
grain, syndrome, row, channel,
|
||||||
label, msg);
|
label, msg);
|
||||||
|
|
||||||
mci->ce_count++;
|
mci->ce_count++;
|
||||||
mci->csrows[row].ce_count++;
|
mci->csrows[row].ce_count++;
|
||||||
|
mci->csrows[row].channels[channel].dimm->ce_count++;
|
||||||
mci->csrows[row].channels[channel].ce_count++;
|
mci->csrows[row].channels[channel].ce_count++;
|
||||||
|
|
||||||
if (mci->scrub_mode & SCRUB_SW_SRC) {
|
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) :
|
mci->ctl_page_to_phys(mci, page_frame_number) :
|
||||||
page_frame_number;
|
page_frame_number;
|
||||||
|
|
||||||
edac_mc_scrub_block(remapped_page, offset_in_page,
|
edac_mc_scrub_block(remapped_page, offset_in_page, grain);
|
||||||
mci->csrows[row].grain);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(edac_mc_handle_ce);
|
EXPORT_SYMBOL_GPL(edac_mc_handle_ce);
|
||||||
|
@ -774,6 +776,7 @@ void edac_mc_handle_ue(struct mem_ctl_info *mci,
|
||||||
int chan;
|
int chan;
|
||||||
int chars;
|
int chars;
|
||||||
char *label = NULL;
|
char *label = NULL;
|
||||||
|
u32 grain;
|
||||||
|
|
||||||
debugf3("MC%d: %s()\n", mci->mc_idx, __func__);
|
debugf3("MC%d: %s()\n", mci->mc_idx, __func__);
|
||||||
|
|
||||||
|
@ -787,6 +790,7 @@ void edac_mc_handle_ue(struct mem_ctl_info *mci,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
grain = mci->csrows[row].channels[0].dimm->grain;
|
||||||
label = mci->csrows[row].channels[0].dimm->label;
|
label = mci->csrows[row].channels[0].dimm->label;
|
||||||
chars = snprintf(pos, len + 1, "%s", label);
|
chars = snprintf(pos, len + 1, "%s", label);
|
||||||
len -= chars;
|
len -= chars;
|
||||||
|
@ -804,14 +808,13 @@ void edac_mc_handle_ue(struct mem_ctl_info *mci,
|
||||||
edac_mc_printk(mci, KERN_EMERG,
|
edac_mc_printk(mci, KERN_EMERG,
|
||||||
"UE page 0x%lx, offset 0x%lx, grain %d, row %d, "
|
"UE page 0x%lx, offset 0x%lx, grain %d, row %d, "
|
||||||
"labels \"%s\": %s\n", page_frame_number,
|
"labels \"%s\": %s\n", page_frame_number,
|
||||||
offset_in_page, mci->csrows[row].grain, row,
|
offset_in_page, grain, row, labels, msg);
|
||||||
labels, msg);
|
|
||||||
|
|
||||||
if (edac_mc_get_panic_on_ue())
|
if (edac_mc_get_panic_on_ue())
|
||||||
panic("EDAC MC%d: UE page 0x%lx, offset 0x%lx, grain %d, "
|
panic("EDAC MC%d: UE page 0x%lx, offset 0x%lx, grain %d, "
|
||||||
"row %d, labels \"%s\": %s\n", mci->mc_idx,
|
"row %d, labels \"%s\": %s\n", mci->mc_idx,
|
||||||
page_frame_number, offset_in_page,
|
page_frame_number, offset_in_page,
|
||||||
mci->csrows[row].grain, row, labels, msg);
|
grain, row, labels, msg);
|
||||||
|
|
||||||
mci->ue_count++;
|
mci->ue_count++;
|
||||||
mci->csrows[row].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);
|
chars = snprintf(pos, len + 1, "%s", label);
|
||||||
len -= chars;
|
len -= chars;
|
||||||
pos += chars;
|
pos += chars;
|
||||||
|
|
||||||
chars = snprintf(pos, len + 1, "-%s",
|
chars = snprintf(pos, len + 1, "-%s",
|
||||||
mci->csrows[csrow].channels[channelb].dimm->label);
|
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->ce_count++;
|
||||||
mci->csrows[csrow].ce_count++;
|
mci->csrows[csrow].ce_count++;
|
||||||
|
mci->csrows[csrow].channels[channel].dimm->ce_count++;
|
||||||
mci->csrows[csrow].channels[channel].ce_count++;
|
mci->csrows[csrow].channels[channel].ce_count++;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(edac_mc_handle_fbd_ce);
|
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,
|
static ssize_t csrow_mem_type_show(struct csrow_info *csrow, char *data,
|
||||||
int private)
|
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,
|
static ssize_t csrow_dev_type_show(struct csrow_info *csrow, char *data,
|
||||||
int private)
|
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,
|
static ssize_t csrow_edac_mode_show(struct csrow_info *csrow, char *data,
|
||||||
int private)
|
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 */
|
/* 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)
|
static int i3000_probe1(struct pci_dev *pdev, int dev_idx)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
int i;
|
int i, j;
|
||||||
struct mem_ctl_info *mci = NULL;
|
struct mem_ctl_info *mci = NULL;
|
||||||
unsigned long last_cumul_size;
|
unsigned long last_cumul_size;
|
||||||
int interleaved, nr_channels;
|
int interleaved, nr_channels;
|
||||||
|
@ -386,19 +386,21 @@ static int i3000_probe1(struct pci_dev *pdev, int dev_idx)
|
||||||
cumul_size <<= 1;
|
cumul_size <<= 1;
|
||||||
debugf3("MC: %s(): (%d) cumul_size 0x%x\n",
|
debugf3("MC: %s(): (%d) cumul_size 0x%x\n",
|
||||||
__func__, i, cumul_size);
|
__func__, i, cumul_size);
|
||||||
if (cumul_size == last_cumul_size) {
|
if (cumul_size == last_cumul_size)
|
||||||
csrow->mtype = MEM_EMPTY;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
csrow->first_page = last_cumul_size;
|
csrow->first_page = last_cumul_size;
|
||||||
csrow->last_page = cumul_size - 1;
|
csrow->last_page = cumul_size - 1;
|
||||||
csrow->nr_pages = cumul_size - last_cumul_size;
|
csrow->nr_pages = cumul_size - last_cumul_size;
|
||||||
last_cumul_size = cumul_size;
|
last_cumul_size = cumul_size;
|
||||||
csrow->grain = I3000_DEAP_GRAIN;
|
|
||||||
csrow->mtype = MEM_DDR2;
|
for (j = 0; j < nr_channels; j++) {
|
||||||
csrow->dtype = DEV_UNKNOWN;
|
struct dimm_info *dimm = csrow->channels[j].dimm;
|
||||||
csrow->edac_mode = EDAC_UNKNOWN;
|
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)
|
static int i3200_probe1(struct pci_dev *pdev, int dev_idx)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
int i;
|
int i, j;
|
||||||
struct mem_ctl_info *mci = NULL;
|
struct mem_ctl_info *mci = NULL;
|
||||||
unsigned long last_page;
|
unsigned long last_page;
|
||||||
u16 drbs[I3200_CHANNELS][I3200_RANKS_PER_CHANNEL];
|
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,
|
||||||
i % I3200_RANKS_PER_CHANNEL);
|
i % I3200_RANKS_PER_CHANNEL);
|
||||||
|
|
||||||
if (nr_pages == 0) {
|
if (nr_pages == 0)
|
||||||
csrow->mtype = MEM_EMPTY;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
csrow->first_page = last_page + 1;
|
csrow->first_page = last_page + 1;
|
||||||
last_page += nr_pages;
|
last_page += nr_pages;
|
||||||
csrow->last_page = last_page;
|
csrow->last_page = last_page;
|
||||||
csrow->nr_pages = nr_pages;
|
csrow->nr_pages = nr_pages;
|
||||||
|
|
||||||
csrow->grain = nr_pages << PAGE_SHIFT;
|
for (j = 0; j < nr_channels; j++) {
|
||||||
csrow->mtype = MEM_DDR2;
|
struct dimm_info *dimm = csrow->channels[j].dimm;
|
||||||
csrow->dtype = DEV_UNKNOWN;
|
|
||||||
csrow->edac_mode = EDAC_UNKNOWN;
|
dimm->grain = nr_pages << PAGE_SHIFT;
|
||||||
|
dimm->mtype = MEM_DDR2;
|
||||||
|
dimm->dtype = DEV_UNKNOWN;
|
||||||
|
dimm->edac_mode = EDAC_UNKNOWN;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
i3200_clear_error_info(mci);
|
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->last_page = 9 + csrow * 20;
|
||||||
p_csrow->page_mask = 0xFFF;
|
p_csrow->page_mask = 0xFFF;
|
||||||
|
|
||||||
p_csrow->grain = 8;
|
|
||||||
|
|
||||||
csrow_megs = 0;
|
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;
|
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 */
|
/* Assume DDR2 for now */
|
||||||
p_csrow->mtype = MEM_FB_DDR2;
|
p_csrow->channels[channel].dimm->mtype = MEM_FB_DDR2;
|
||||||
|
|
||||||
/* ask what device type on this row */
|
/* ask what device type on this row */
|
||||||
if (MTR_DRAM_WIDTH(mtr))
|
if (MTR_DRAM_WIDTH(mtr))
|
||||||
p_csrow->dtype = DEV_X8;
|
p_csrow->channels[channel].dimm->dtype = DEV_X8;
|
||||||
else
|
else
|
||||||
p_csrow->dtype = DEV_X4;
|
p_csrow->channels[channel].dimm->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;
|
empty = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -428,12 +428,16 @@ static void i5100_handle_ce(struct mem_ctl_info *mci,
|
||||||
const char *msg)
|
const char *msg)
|
||||||
{
|
{
|
||||||
const int csrow = i5100_rank_to_csrow(mci, chan, rank);
|
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
|
printk(KERN_ERR
|
||||||
"CE chan %d, bank %u, rank %u, syndrome 0x%lx, "
|
"CE chan %d, bank %u, rank %u, syndrome 0x%lx, "
|
||||||
"cas %u, ras %u, csrow %u, label \"%s\": %s\n",
|
"cas %u, ras %u, csrow %u, label \"%s\": %s\n",
|
||||||
chan, bank, rank, syndrome, cas, ras,
|
chan, bank, rank, syndrome, cas, ras,
|
||||||
csrow, mci->csrows[csrow].channels[0].dimm->label, msg);
|
csrow, label, msg);
|
||||||
|
|
||||||
mci->ce_count++;
|
mci->ce_count++;
|
||||||
mci->csrows[csrow].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 char *msg)
|
||||||
{
|
{
|
||||||
const int csrow = i5100_rank_to_csrow(mci, chan, rank);
|
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
|
printk(KERN_ERR
|
||||||
"UE chan %d, bank %u, rank %u, syndrome 0x%lx, "
|
"UE chan %d, bank %u, rank %u, syndrome 0x%lx, "
|
||||||
"cas %u, ras %u, csrow %u, label \"%s\": %s\n",
|
"cas %u, ras %u, csrow %u, label \"%s\": %s\n",
|
||||||
chan, bank, rank, syndrome, cas, ras,
|
chan, bank, rank, syndrome, cas, ras,
|
||||||
csrow, mci->csrows[csrow].channels[0].dimm->label, msg);
|
csrow, label, msg);
|
||||||
|
|
||||||
mci->ue_count++;
|
mci->ue_count++;
|
||||||
mci->csrows[csrow].ue_count++;
|
mci->csrows[csrow].ue_count++;
|
||||||
|
@ -837,6 +845,7 @@ static void __devinit i5100_init_csrows(struct mem_ctl_info *mci)
|
||||||
int i;
|
int i;
|
||||||
unsigned long total_pages = 0UL;
|
unsigned long total_pages = 0UL;
|
||||||
struct i5100_priv *priv = mci->pvt_info;
|
struct i5100_priv *priv = mci->pvt_info;
|
||||||
|
struct dimm_info *dimm;
|
||||||
|
|
||||||
for (i = 0; i < mci->nr_csrows; i++) {
|
for (i = 0; i < mci->nr_csrows; i++) {
|
||||||
const unsigned long npages = i5100_npages(mci, 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].first_page = total_pages;
|
||||||
mci->csrows[i].last_page = total_pages + npages - 1;
|
mci->csrows[i].last_page = total_pages + npages - 1;
|
||||||
mci->csrows[i].page_mask = 0UL;
|
|
||||||
|
|
||||||
mci->csrows[i].nr_pages = npages;
|
mci->csrows[i].nr_pages = npages;
|
||||||
mci->csrows[i].grain = 32;
|
|
||||||
mci->csrows[i].csrow_idx = i;
|
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].mci = mci;
|
||||||
mci->csrows[i].nr_channels = 1;
|
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;
|
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;
|
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 csrow_megs;
|
||||||
int channel;
|
int channel;
|
||||||
int csrow;
|
int csrow;
|
||||||
|
struct dimm_info *dimm;
|
||||||
|
|
||||||
pvt = mci->pvt_info;
|
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->last_page = 9 + csrow * 20;
|
||||||
p_csrow->page_mask = 0xFFF;
|
p_csrow->page_mask = 0xFFF;
|
||||||
|
|
||||||
p_csrow->grain = 8;
|
|
||||||
|
|
||||||
csrow_megs = 0;
|
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;
|
csrow_megs += pvt->dimm_info[csrow][channel].megabytes;
|
||||||
|
|
||||||
p_csrow->nr_pages = csrow_megs << 8;
|
p_csrow->nr_pages = csrow_megs << 8;
|
||||||
|
dimm = p_csrow->channels[channel].dimm;
|
||||||
/* Assume DDR2 for now */
|
dimm->grain = 8;
|
||||||
p_csrow->mtype = MEM_FB_DDR2;
|
dimm->dtype = MTR_DRAM_WIDTH(mtr) ? DEV_X8 : DEV_X4;
|
||||||
|
dimm->mtype = MEM_RDDR2;
|
||||||
/* ask what device type on this row */
|
dimm->edac_mode = EDAC_SECDED;
|
||||||
if (MTR_DRAM_WIDTH(mtr))
|
}
|
||||||
p_csrow->dtype = DEV_X8;
|
|
||||||
else
|
|
||||||
p_csrow->dtype = DEV_X4;
|
|
||||||
|
|
||||||
p_csrow->edac_mode = EDAC_S8ECD8ED;
|
|
||||||
|
|
||||||
empty = 0;
|
empty = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -618,6 +618,7 @@ static int decode_mtr(struct i7300_pvt *pvt,
|
||||||
int slot, int ch, int branch,
|
int slot, int ch, int branch,
|
||||||
struct i7300_dimm_info *dinfo,
|
struct i7300_dimm_info *dinfo,
|
||||||
struct csrow_info *p_csrow,
|
struct csrow_info *p_csrow,
|
||||||
|
struct dimm_info *dimm,
|
||||||
u32 *nr_pages)
|
u32 *nr_pages)
|
||||||
{
|
{
|
||||||
int mtr, ans, addrBits, channel;
|
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\tNUMCOL: %s\n", numcol_toString[MTR_DIMM_COLS(mtr)]);
|
||||||
debugf2("\t\tSIZE: %d MB\n", dinfo->megabytes);
|
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->csrow_idx = slot;
|
||||||
p_csrow->page_mask = 0;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The type of error detection actually depends of the
|
* 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
|
* 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)) {
|
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");
|
debugf2("\t\tECC code is 8-byte-over-32-byte SECDED+ code\n");
|
||||||
} else {
|
} else {
|
||||||
debugf2("\t\tECC code is on Lockstep mode\n");
|
debugf2("\t\tECC code is on Lockstep mode\n");
|
||||||
if (MTR_DRAM_WIDTH(mtr) == 8)
|
if (MTR_DRAM_WIDTH(mtr) == 8)
|
||||||
p_csrow->edac_mode = EDAC_S8ECD8ED;
|
dimm->edac_mode = EDAC_S8ECD8ED;
|
||||||
else
|
else
|
||||||
p_csrow->edac_mode = EDAC_S4ECD4ED;
|
dimm->edac_mode = EDAC_S4ECD4ED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ask what device type on this row */
|
/* 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) ?
|
IS_SCRBALGO_ENHANCED(pvt->mc_settings) ?
|
||||||
"enhanced" : "normal");
|
"enhanced" : "normal");
|
||||||
|
|
||||||
p_csrow->dtype = DEV_X8;
|
dimm->dtype = DEV_X8;
|
||||||
} else
|
} else
|
||||||
p_csrow->dtype = DEV_X4;
|
dimm->dtype = DEV_X4;
|
||||||
|
|
||||||
return mtr;
|
return mtr;
|
||||||
}
|
}
|
||||||
|
@ -779,6 +779,7 @@ static int i7300_init_csrows(struct mem_ctl_info *mci)
|
||||||
int mtr;
|
int mtr;
|
||||||
int ch, branch, slot, channel;
|
int ch, branch, slot, channel;
|
||||||
u32 last_page = 0, nr_pages;
|
u32 last_page = 0, nr_pages;
|
||||||
|
struct dimm_info *dimm;
|
||||||
|
|
||||||
pvt = mci->pvt_info;
|
pvt = mci->pvt_info;
|
||||||
|
|
||||||
|
@ -803,20 +804,24 @@ static int i7300_init_csrows(struct mem_ctl_info *mci)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the set of MTR[0-7] regs by each branch */
|
/* Get the set of MTR[0-7] regs by each branch */
|
||||||
|
nr_pages = 0;
|
||||||
for (slot = 0; slot < MAX_SLOTS; slot++) {
|
for (slot = 0; slot < MAX_SLOTS; slot++) {
|
||||||
int where = mtr_regs[slot];
|
int where = mtr_regs[slot];
|
||||||
for (branch = 0; branch < MAX_BRANCHES; branch++) {
|
for (branch = 0; branch < MAX_BRANCHES; branch++) {
|
||||||
pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch],
|
pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch],
|
||||||
where,
|
where,
|
||||||
&pvt->mtr[slot][branch]);
|
&pvt->mtr[slot][branch]);
|
||||||
for (ch = 0; ch < MAX_BRANCHES; ch++) {
|
for (ch = 0; ch < MAX_CH_PER_BRANCH; ch++) {
|
||||||
int channel = to_channel(ch, branch);
|
int channel = to_channel(ch, branch);
|
||||||
|
|
||||||
dinfo = &pvt->dimm_info[slot][channel];
|
dinfo = &pvt->dimm_info[slot][channel];
|
||||||
p_csrow = &mci->csrows[slot];
|
p_csrow = &mci->csrows[slot];
|
||||||
|
|
||||||
|
dimm = p_csrow->channels[branch * MAX_CH_PER_BRANCH + ch].dimm;
|
||||||
|
|
||||||
mtr = decode_mtr(pvt, slot, ch, branch,
|
mtr = decode_mtr(pvt, slot, ch, branch,
|
||||||
dinfo, p_csrow, &nr_pages);
|
dinfo, p_csrow, dimm,
|
||||||
|
&nr_pages);
|
||||||
/* if no DIMMS on this row, continue */
|
/* if no DIMMS on this row, continue */
|
||||||
if (!MTR_DIMMS_PRESENT(mtr))
|
if (!MTR_DIMMS_PRESENT(mtr))
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -592,7 +592,7 @@ static int i7core_get_active_channels(const u8 socket, unsigned *channels,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_dimm_config(const struct mem_ctl_info *mci)
|
static int get_dimm_config(struct mem_ctl_info *mci)
|
||||||
{
|
{
|
||||||
struct i7core_pvt *pvt = mci->pvt_info;
|
struct i7core_pvt *pvt = mci->pvt_info;
|
||||||
struct csrow_info *csr;
|
struct csrow_info *csr;
|
||||||
|
@ -602,6 +602,7 @@ static int get_dimm_config(const struct mem_ctl_info *mci)
|
||||||
unsigned long last_page = 0;
|
unsigned long last_page = 0;
|
||||||
enum edac_type mode;
|
enum edac_type mode;
|
||||||
enum mem_type mtype;
|
enum mem_type mtype;
|
||||||
|
struct dimm_info *dimm;
|
||||||
|
|
||||||
/* Get data from the MC register, function 0 */
|
/* Get data from the MC register, function 0 */
|
||||||
pdev = pvt->pci_mcr[0];
|
pdev = pvt->pci_mcr[0];
|
||||||
|
@ -721,7 +722,6 @@ static int get_dimm_config(const struct mem_ctl_info *mci)
|
||||||
csr->nr_pages = npages;
|
csr->nr_pages = npages;
|
||||||
|
|
||||||
csr->page_mask = 0;
|
csr->page_mask = 0;
|
||||||
csr->grain = 8;
|
|
||||||
csr->csrow_idx = csrow;
|
csr->csrow_idx = csrow;
|
||||||
csr->nr_channels = 1;
|
csr->nr_channels = 1;
|
||||||
|
|
||||||
|
@ -730,28 +730,27 @@ static int get_dimm_config(const struct mem_ctl_info *mci)
|
||||||
|
|
||||||
pvt->csrow_map[i][j] = csrow;
|
pvt->csrow_map[i][j] = csrow;
|
||||||
|
|
||||||
|
dimm = csr->channels[0].dimm;
|
||||||
switch (banks) {
|
switch (banks) {
|
||||||
case 4:
|
case 4:
|
||||||
csr->dtype = DEV_X4;
|
dimm->dtype = DEV_X4;
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
csr->dtype = DEV_X8;
|
dimm->dtype = DEV_X8;
|
||||||
break;
|
break;
|
||||||
case 16:
|
case 16:
|
||||||
csr->dtype = DEV_X16;
|
dimm->dtype = DEV_X16;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
csr->dtype = DEV_UNKNOWN;
|
dimm->dtype = DEV_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
csr->edac_mode = mode;
|
snprintf(dimm->label, sizeof(dimm->label),
|
||||||
csr->mtype = mtype;
|
|
||||||
snprintf(csr->channels[0].dimm->label,
|
|
||||||
sizeof(csr->channels[0].dimm->label),
|
|
||||||
"CPU#%uChannel#%u_DIMM#%u",
|
"CPU#%uChannel#%u_DIMM#%u",
|
||||||
pvt->i7core_dev->socket, i, j);
|
pvt->i7core_dev->socket, i, j);
|
||||||
|
dimm->grain = 8;
|
||||||
csrow++;
|
dimm->edac_mode = mode;
|
||||||
|
dimm->mtype = mtype;
|
||||||
}
|
}
|
||||||
|
|
||||||
pci_read_config_dword(pdev, MC_SAG_CH_0, &value[0]);
|
pci_read_config_dword(pdev, MC_SAG_CH_0, &value[0]);
|
||||||
|
|
|
@ -189,6 +189,7 @@ static void i82443bxgx_init_csrows(struct mem_ctl_info *mci,
|
||||||
enum mem_type mtype)
|
enum mem_type mtype)
|
||||||
{
|
{
|
||||||
struct csrow_info *csrow;
|
struct csrow_info *csrow;
|
||||||
|
struct dimm_info *dimm;
|
||||||
int index;
|
int index;
|
||||||
u8 drbar, dramc;
|
u8 drbar, dramc;
|
||||||
u32 row_base, row_high_limit, row_high_limit_last;
|
u32 row_base, row_high_limit, row_high_limit_last;
|
||||||
|
@ -197,6 +198,8 @@ static void i82443bxgx_init_csrows(struct mem_ctl_info *mci,
|
||||||
row_high_limit_last = 0;
|
row_high_limit_last = 0;
|
||||||
for (index = 0; index < mci->nr_csrows; index++) {
|
for (index = 0; index < mci->nr_csrows; index++) {
|
||||||
csrow = &mci->csrows[index];
|
csrow = &mci->csrows[index];
|
||||||
|
dimm = csrow->channels[0].dimm;
|
||||||
|
|
||||||
pci_read_config_byte(pdev, I82443BXGX_DRB + index, &drbar);
|
pci_read_config_byte(pdev, I82443BXGX_DRB + index, &drbar);
|
||||||
debugf1("MC%d: %s: %s() Row=%d DRB = %#0x\n",
|
debugf1("MC%d: %s: %s() Row=%d DRB = %#0x\n",
|
||||||
mci->mc_idx, __FILE__, __func__, index, drbar);
|
mci->mc_idx, __FILE__, __func__, index, drbar);
|
||||||
|
@ -219,12 +222,12 @@ static void i82443bxgx_init_csrows(struct mem_ctl_info *mci,
|
||||||
csrow->last_page = (row_high_limit >> PAGE_SHIFT) - 1;
|
csrow->last_page = (row_high_limit >> PAGE_SHIFT) - 1;
|
||||||
csrow->nr_pages = csrow->last_page - csrow->first_page + 1;
|
csrow->nr_pages = csrow->last_page - csrow->first_page + 1;
|
||||||
/* EAP reports in 4kilobyte granularity [61] */
|
/* EAP reports in 4kilobyte granularity [61] */
|
||||||
csrow->grain = 1 << 12;
|
dimm->grain = 1 << 12;
|
||||||
csrow->mtype = mtype;
|
dimm->mtype = mtype;
|
||||||
/* I don't think 440BX can tell you device type? FIXME? */
|
/* I don't think 440BX can tell you device type? FIXME? */
|
||||||
csrow->dtype = DEV_UNKNOWN;
|
dimm->dtype = DEV_UNKNOWN;
|
||||||
/* Mode is global to all rows on 440BX */
|
/* Mode is global to all rows on 440BX */
|
||||||
csrow->edac_mode = edac_mode;
|
dimm->edac_mode = edac_mode;
|
||||||
row_high_limit_last = row_high_limit;
|
row_high_limit_last = row_high_limit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -140,6 +140,7 @@ static void i82860_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev)
|
||||||
u16 value;
|
u16 value;
|
||||||
u32 cumul_size;
|
u32 cumul_size;
|
||||||
struct csrow_info *csrow;
|
struct csrow_info *csrow;
|
||||||
|
struct dimm_info *dimm;
|
||||||
int index;
|
int index;
|
||||||
|
|
||||||
pci_read_config_word(pdev, I82860_MCHCFG, &mchcfg_ddim);
|
pci_read_config_word(pdev, I82860_MCHCFG, &mchcfg_ddim);
|
||||||
|
@ -153,6 +154,8 @@ static void i82860_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev)
|
||||||
*/
|
*/
|
||||||
for (index = 0; index < mci->nr_csrows; index++) {
|
for (index = 0; index < mci->nr_csrows; index++) {
|
||||||
csrow = &mci->csrows[index];
|
csrow = &mci->csrows[index];
|
||||||
|
dimm = csrow->channels[0].dimm;
|
||||||
|
|
||||||
pci_read_config_word(pdev, I82860_GBA + index * 2, &value);
|
pci_read_config_word(pdev, I82860_GBA + index * 2, &value);
|
||||||
cumul_size = (value & I82860_GBA_MASK) <<
|
cumul_size = (value & I82860_GBA_MASK) <<
|
||||||
(I82860_GBA_SHIFT - PAGE_SHIFT);
|
(I82860_GBA_SHIFT - PAGE_SHIFT);
|
||||||
|
@ -166,10 +169,10 @@ static void i82860_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev)
|
||||||
csrow->last_page = cumul_size - 1;
|
csrow->last_page = cumul_size - 1;
|
||||||
csrow->nr_pages = cumul_size - last_cumul_size;
|
csrow->nr_pages = cumul_size - last_cumul_size;
|
||||||
last_cumul_size = cumul_size;
|
last_cumul_size = cumul_size;
|
||||||
csrow->grain = 1 << 12; /* I82860_EAP has 4KiB reolution */
|
dimm->grain = 1 << 12; /* I82860_EAP has 4KiB reolution */
|
||||||
csrow->mtype = MEM_RMBS;
|
dimm->mtype = MEM_RMBS;
|
||||||
csrow->dtype = DEV_UNKNOWN;
|
dimm->dtype = DEV_UNKNOWN;
|
||||||
csrow->edac_mode = mchcfg_ddim ? EDAC_SECDED : EDAC_NONE;
|
dimm->edac_mode = mchcfg_ddim ? EDAC_SECDED : EDAC_NONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -342,11 +342,13 @@ static void i82875p_init_csrows(struct mem_ctl_info *mci,
|
||||||
void __iomem * ovrfl_window, u32 drc)
|
void __iomem * ovrfl_window, u32 drc)
|
||||||
{
|
{
|
||||||
struct csrow_info *csrow;
|
struct csrow_info *csrow;
|
||||||
|
struct dimm_info *dimm;
|
||||||
|
unsigned nr_chans = dual_channel_active(drc) + 1;
|
||||||
unsigned long last_cumul_size;
|
unsigned long last_cumul_size;
|
||||||
u8 value;
|
u8 value;
|
||||||
u32 drc_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */
|
u32 drc_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */
|
||||||
u32 cumul_size;
|
u32 cumul_size;
|
||||||
int index;
|
int index, j;
|
||||||
|
|
||||||
drc_ddim = (drc >> 18) & 0x1;
|
drc_ddim = (drc >> 18) & 0x1;
|
||||||
last_cumul_size = 0;
|
last_cumul_size = 0;
|
||||||
|
@ -371,10 +373,15 @@ static void i82875p_init_csrows(struct mem_ctl_info *mci,
|
||||||
csrow->last_page = cumul_size - 1;
|
csrow->last_page = cumul_size - 1;
|
||||||
csrow->nr_pages = cumul_size - last_cumul_size;
|
csrow->nr_pages = cumul_size - last_cumul_size;
|
||||||
last_cumul_size = cumul_size;
|
last_cumul_size = cumul_size;
|
||||||
csrow->grain = 1 << 12; /* I82875P_EAP has 4KiB reolution */
|
|
||||||
csrow->mtype = MEM_DDR;
|
for (j = 0; j < nr_chans; j++) {
|
||||||
csrow->dtype = DEV_UNKNOWN;
|
dimm = csrow->channels[j].dimm;
|
||||||
csrow->edac_mode = drc_ddim ? EDAC_SECDED : EDAC_NONE;
|
|
||||||
|
dimm->grain = 1 << 12; /* I82875P_EAP has 4KiB reolution */
|
||||||
|
dimm->mtype = MEM_DDR;
|
||||||
|
dimm->dtype = DEV_UNKNOWN;
|
||||||
|
dimm->edac_mode = drc_ddim ? EDAC_SECDED : EDAC_NONE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -309,7 +309,7 @@ static int i82975x_process_error_info(struct mem_ctl_info *mci,
|
||||||
chan = (mci->csrows[row].nr_channels == 1) ? 0 : info->eap & 1;
|
chan = (mci->csrows[row].nr_channels == 1) ? 0 : info->eap & 1;
|
||||||
offst = info->eap
|
offst = info->eap
|
||||||
& ((1 << PAGE_SHIFT) -
|
& ((1 << PAGE_SHIFT) -
|
||||||
(1 << mci->csrows[row].grain));
|
(1 << mci->csrows[row].channels[chan].dimm->grain));
|
||||||
|
|
||||||
if (info->errsts & 0x0002)
|
if (info->errsts & 0x0002)
|
||||||
edac_mc_handle_ue(mci, page, offst , row, "i82975x UE");
|
edac_mc_handle_ue(mci, page, offst , row, "i82975x UE");
|
||||||
|
@ -372,6 +372,8 @@ static void i82975x_init_csrows(struct mem_ctl_info *mci,
|
||||||
u8 value;
|
u8 value;
|
||||||
u32 cumul_size;
|
u32 cumul_size;
|
||||||
int index, chan;
|
int index, chan;
|
||||||
|
struct dimm_info *dimm;
|
||||||
|
enum dev_type dtype;
|
||||||
|
|
||||||
last_cumul_size = 0;
|
last_cumul_size = 0;
|
||||||
|
|
||||||
|
@ -406,10 +408,17 @@ static void i82975x_init_csrows(struct mem_ctl_info *mci,
|
||||||
* [0-7] for single-channel; i.e. csrow->nr_channels = 1
|
* [0-7] for single-channel; i.e. csrow->nr_channels = 1
|
||||||
* [0-3] for dual-channel; i.e. csrow->nr_channels = 2
|
* [0-3] for dual-channel; i.e. csrow->nr_channels = 2
|
||||||
*/
|
*/
|
||||||
for (chan = 0; chan < csrow->nr_channels; chan++)
|
dtype = i82975x_dram_type(mch_window, index);
|
||||||
|
for (chan = 0; chan < csrow->nr_channels; chan++) {
|
||||||
|
dimm = mci->csrows[index].channels[chan].dimm;
|
||||||
strncpy(csrow->channels[chan].dimm->label,
|
strncpy(csrow->channels[chan].dimm->label,
|
||||||
labels[(index >> 1) + (chan * 2)],
|
labels[(index >> 1) + (chan * 2)],
|
||||||
EDAC_MC_LABEL_LEN);
|
EDAC_MC_LABEL_LEN);
|
||||||
|
dimm->grain = 1 << 7; /* 128Byte cache-line resolution */
|
||||||
|
dimm->dtype = i82975x_dram_type(mch_window, index);
|
||||||
|
dimm->mtype = MEM_DDR2; /* I82975x supports only DDR2 */
|
||||||
|
dimm->edac_mode = EDAC_SECDED; /* only supported */
|
||||||
|
}
|
||||||
|
|
||||||
if (cumul_size == last_cumul_size)
|
if (cumul_size == last_cumul_size)
|
||||||
continue; /* not populated */
|
continue; /* not populated */
|
||||||
|
@ -418,10 +427,6 @@ static void i82975x_init_csrows(struct mem_ctl_info *mci,
|
||||||
csrow->last_page = cumul_size - 1;
|
csrow->last_page = cumul_size - 1;
|
||||||
csrow->nr_pages = cumul_size - last_cumul_size;
|
csrow->nr_pages = cumul_size - last_cumul_size;
|
||||||
last_cumul_size = cumul_size;
|
last_cumul_size = cumul_size;
|
||||||
csrow->grain = 1 << 7; /* 128Byte cache-line resolution */
|
|
||||||
csrow->mtype = MEM_DDR2; /* I82975x supports only DDR2 */
|
|
||||||
csrow->dtype = i82975x_dram_type(mch_window, index);
|
|
||||||
csrow->edac_mode = EDAC_SECDED; /* only supported */
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -883,6 +883,7 @@ static void __devinit mpc85xx_init_csrows(struct mem_ctl_info *mci)
|
||||||
{
|
{
|
||||||
struct mpc85xx_mc_pdata *pdata = mci->pvt_info;
|
struct mpc85xx_mc_pdata *pdata = mci->pvt_info;
|
||||||
struct csrow_info *csrow;
|
struct csrow_info *csrow;
|
||||||
|
struct dimm_info *dimm;
|
||||||
u32 sdram_ctl;
|
u32 sdram_ctl;
|
||||||
u32 sdtype;
|
u32 sdtype;
|
||||||
enum mem_type mtype;
|
enum mem_type mtype;
|
||||||
|
@ -929,6 +930,8 @@ static void __devinit mpc85xx_init_csrows(struct mem_ctl_info *mci)
|
||||||
u32 end;
|
u32 end;
|
||||||
|
|
||||||
csrow = &mci->csrows[index];
|
csrow = &mci->csrows[index];
|
||||||
|
dimm = csrow->channels[0].dimm;
|
||||||
|
|
||||||
cs_bnds = in_be32(pdata->mc_vbase + MPC85XX_MC_CS_BNDS_0 +
|
cs_bnds = in_be32(pdata->mc_vbase + MPC85XX_MC_CS_BNDS_0 +
|
||||||
(index * MPC85XX_MC_CS_BNDS_OFS));
|
(index * MPC85XX_MC_CS_BNDS_OFS));
|
||||||
|
|
||||||
|
@ -945,12 +948,12 @@ static void __devinit mpc85xx_init_csrows(struct mem_ctl_info *mci)
|
||||||
csrow->first_page = start;
|
csrow->first_page = start;
|
||||||
csrow->last_page = end;
|
csrow->last_page = end;
|
||||||
csrow->nr_pages = end + 1 - start;
|
csrow->nr_pages = end + 1 - start;
|
||||||
csrow->grain = 8;
|
dimm->grain = 8;
|
||||||
csrow->mtype = mtype;
|
dimm->mtype = mtype;
|
||||||
csrow->dtype = DEV_UNKNOWN;
|
dimm->dtype = DEV_UNKNOWN;
|
||||||
if (sdram_ctl & DSC_X32_EN)
|
if (sdram_ctl & DSC_X32_EN)
|
||||||
csrow->dtype = DEV_X32;
|
dimm->dtype = DEV_X32;
|
||||||
csrow->edac_mode = EDAC_SECDED;
|
dimm->edac_mode = EDAC_SECDED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -656,6 +656,8 @@ static void mv64x60_init_csrows(struct mem_ctl_info *mci,
|
||||||
struct mv64x60_mc_pdata *pdata)
|
struct mv64x60_mc_pdata *pdata)
|
||||||
{
|
{
|
||||||
struct csrow_info *csrow;
|
struct csrow_info *csrow;
|
||||||
|
struct dimm_info *dimm;
|
||||||
|
|
||||||
u32 devtype;
|
u32 devtype;
|
||||||
u32 ctl;
|
u32 ctl;
|
||||||
|
|
||||||
|
@ -664,30 +666,30 @@ static void mv64x60_init_csrows(struct mem_ctl_info *mci,
|
||||||
ctl = in_le32(pdata->mc_vbase + MV64X60_SDRAM_CONFIG);
|
ctl = in_le32(pdata->mc_vbase + MV64X60_SDRAM_CONFIG);
|
||||||
|
|
||||||
csrow = &mci->csrows[0];
|
csrow = &mci->csrows[0];
|
||||||
csrow->first_page = 0;
|
dimm = csrow->channels[0].dimm;
|
||||||
csrow->nr_pages = pdata->total_mem >> PAGE_SHIFT;
|
csrow->nr_pages = pdata->total_mem >> PAGE_SHIFT;
|
||||||
csrow->last_page = csrow->first_page + csrow->nr_pages - 1;
|
csrow->last_page = csrow->first_page + csrow->nr_pages - 1;
|
||||||
csrow->grain = 8;
|
dimm->grain = 8;
|
||||||
|
|
||||||
csrow->mtype = (ctl & MV64X60_SDRAM_REGISTERED) ? MEM_RDDR : MEM_DDR;
|
dimm->mtype = (ctl & MV64X60_SDRAM_REGISTERED) ? MEM_RDDR : MEM_DDR;
|
||||||
|
|
||||||
devtype = (ctl >> 20) & 0x3;
|
devtype = (ctl >> 20) & 0x3;
|
||||||
switch (devtype) {
|
switch (devtype) {
|
||||||
case 0x0:
|
case 0x0:
|
||||||
csrow->dtype = DEV_X32;
|
dimm->dtype = DEV_X32;
|
||||||
break;
|
break;
|
||||||
case 0x2: /* could be X8 too, but no way to tell */
|
case 0x2: /* could be X8 too, but no way to tell */
|
||||||
csrow->dtype = DEV_X16;
|
dimm->dtype = DEV_X16;
|
||||||
break;
|
break;
|
||||||
case 0x3:
|
case 0x3:
|
||||||
csrow->dtype = DEV_X4;
|
dimm->dtype = DEV_X4;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
csrow->dtype = DEV_UNKNOWN;
|
dimm->dtype = DEV_UNKNOWN;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
csrow->edac_mode = EDAC_SECDED;
|
dimm->edac_mode = EDAC_SECDED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __devinit mv64x60_mc_err_probe(struct platform_device *pdev)
|
static int __devinit mv64x60_mc_err_probe(struct platform_device *pdev)
|
||||||
|
|
|
@ -135,11 +135,13 @@ static int pasemi_edac_init_csrows(struct mem_ctl_info *mci,
|
||||||
enum edac_type edac_mode)
|
enum edac_type edac_mode)
|
||||||
{
|
{
|
||||||
struct csrow_info *csrow;
|
struct csrow_info *csrow;
|
||||||
|
struct dimm_info *dimm;
|
||||||
u32 rankcfg;
|
u32 rankcfg;
|
||||||
int index;
|
int index;
|
||||||
|
|
||||||
for (index = 0; index < mci->nr_csrows; index++) {
|
for (index = 0; index < mci->nr_csrows; index++) {
|
||||||
csrow = &mci->csrows[index];
|
csrow = &mci->csrows[index];
|
||||||
|
dimm = csrow->channels[0].dimm;
|
||||||
|
|
||||||
pci_read_config_dword(pdev,
|
pci_read_config_dword(pdev,
|
||||||
MCDRAM_RANKCFG + (index * 12),
|
MCDRAM_RANKCFG + (index * 12),
|
||||||
|
@ -177,10 +179,10 @@ static int pasemi_edac_init_csrows(struct mem_ctl_info *mci,
|
||||||
csrow->last_page = csrow->first_page + csrow->nr_pages - 1;
|
csrow->last_page = csrow->first_page + csrow->nr_pages - 1;
|
||||||
last_page_in_mmc += csrow->nr_pages;
|
last_page_in_mmc += csrow->nr_pages;
|
||||||
csrow->page_mask = 0;
|
csrow->page_mask = 0;
|
||||||
csrow->grain = PASEMI_EDAC_ERROR_GRAIN;
|
dimm->grain = PASEMI_EDAC_ERROR_GRAIN;
|
||||||
csrow->mtype = MEM_DDR;
|
dimm->mtype = MEM_DDR;
|
||||||
csrow->dtype = DEV_UNKNOWN;
|
dimm->dtype = DEV_UNKNOWN;
|
||||||
csrow->edac_mode = edac_mode;
|
dimm->edac_mode = edac_mode;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -895,7 +895,7 @@ ppc4xx_edac_init_csrows(struct mem_ctl_info *mci, u32 mcopt1)
|
||||||
enum mem_type mtype;
|
enum mem_type mtype;
|
||||||
enum dev_type dtype;
|
enum dev_type dtype;
|
||||||
enum edac_type edac_mode;
|
enum edac_type edac_mode;
|
||||||
int row;
|
int row, j;
|
||||||
u32 mbxcf, size;
|
u32 mbxcf, size;
|
||||||
static u32 ppc4xx_last_page;
|
static u32 ppc4xx_last_page;
|
||||||
|
|
||||||
|
@ -975,16 +975,19 @@ ppc4xx_edac_init_csrows(struct mem_ctl_info *mci, u32 mcopt1)
|
||||||
* possible values would be the PLB width (16), the
|
* possible values would be the PLB width (16), the
|
||||||
* page size (PAGE_SIZE) or the memory width (2 or 4).
|
* page size (PAGE_SIZE) or the memory width (2 or 4).
|
||||||
*/
|
*/
|
||||||
|
for (j = 0; j < csi->nr_channels; j++) {
|
||||||
|
struct dimm_info *dimm = csi->channels[j].dimm;
|
||||||
|
|
||||||
csi->grain = 1;
|
dimm->grain = 1;
|
||||||
|
|
||||||
csi->mtype = mtype;
|
dimm->mtype = mtype;
|
||||||
csi->dtype = dtype;
|
dimm->dtype = dtype;
|
||||||
|
|
||||||
csi->edac_mode = edac_mode;
|
dimm->edac_mode = edac_mode;
|
||||||
|
|
||||||
ppc4xx_last_page += csi->nr_pages;
|
ppc4xx_last_page += csi->nr_pages;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
return status;
|
return status;
|
||||||
|
|
|
@ -216,6 +216,7 @@ static void r82600_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev,
|
||||||
u8 dramcr)
|
u8 dramcr)
|
||||||
{
|
{
|
||||||
struct csrow_info *csrow;
|
struct csrow_info *csrow;
|
||||||
|
struct dimm_info *dimm;
|
||||||
int index;
|
int index;
|
||||||
u8 drbar; /* SDRAM Row Boundary Address Register */
|
u8 drbar; /* SDRAM Row Boundary Address Register */
|
||||||
u32 row_high_limit, row_high_limit_last;
|
u32 row_high_limit, row_high_limit_last;
|
||||||
|
@ -227,6 +228,7 @@ static void r82600_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev,
|
||||||
|
|
||||||
for (index = 0; index < mci->nr_csrows; index++) {
|
for (index = 0; index < mci->nr_csrows; index++) {
|
||||||
csrow = &mci->csrows[index];
|
csrow = &mci->csrows[index];
|
||||||
|
dimm = csrow->channels[0].dimm;
|
||||||
|
|
||||||
/* find the DRAM Chip Select Base address and mask */
|
/* find the DRAM Chip Select Base address and mask */
|
||||||
pci_read_config_byte(pdev, R82600_DRBA + index, &drbar);
|
pci_read_config_byte(pdev, R82600_DRBA + index, &drbar);
|
||||||
|
@ -250,13 +252,13 @@ static void r82600_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev,
|
||||||
csrow->nr_pages = csrow->last_page - csrow->first_page + 1;
|
csrow->nr_pages = csrow->last_page - csrow->first_page + 1;
|
||||||
/* Error address is top 19 bits - so granularity is *
|
/* Error address is top 19 bits - so granularity is *
|
||||||
* 14 bits */
|
* 14 bits */
|
||||||
csrow->grain = 1 << 14;
|
dimm->grain = 1 << 14;
|
||||||
csrow->mtype = reg_sdram ? MEM_RDDR : MEM_DDR;
|
dimm->mtype = reg_sdram ? MEM_RDDR : MEM_DDR;
|
||||||
/* FIXME - check that this is unknowable with this chipset */
|
/* FIXME - check that this is unknowable with this chipset */
|
||||||
csrow->dtype = DEV_UNKNOWN;
|
dimm->dtype = DEV_UNKNOWN;
|
||||||
|
|
||||||
/* Mode is global on 82600 */
|
/* Mode is global on 82600 */
|
||||||
csrow->edac_mode = ecc_on ? EDAC_SECDED : EDAC_NONE;
|
dimm->edac_mode = ecc_on ? EDAC_SECDED : EDAC_NONE;
|
||||||
row_high_limit_last = row_high_limit;
|
row_high_limit_last = row_high_limit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -551,7 +551,7 @@ static int sbridge_get_active_channels(const u8 bus, unsigned *channels,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_dimm_config(const struct mem_ctl_info *mci)
|
static int get_dimm_config(struct mem_ctl_info *mci)
|
||||||
{
|
{
|
||||||
struct sbridge_pvt *pvt = mci->pvt_info;
|
struct sbridge_pvt *pvt = mci->pvt_info;
|
||||||
struct csrow_info *csr;
|
struct csrow_info *csr;
|
||||||
|
@ -561,6 +561,7 @@ static int get_dimm_config(const struct mem_ctl_info *mci)
|
||||||
u32 reg;
|
u32 reg;
|
||||||
enum edac_type mode;
|
enum edac_type mode;
|
||||||
enum mem_type mtype;
|
enum mem_type mtype;
|
||||||
|
struct dimm_info *dimm;
|
||||||
|
|
||||||
pci_read_config_dword(pvt->pci_br, SAD_TARGET, ®);
|
pci_read_config_dword(pvt->pci_br, SAD_TARGET, ®);
|
||||||
pvt->sbridge_dev->source_id = SOURCE_ID(reg);
|
pvt->sbridge_dev->source_id = SOURCE_ID(reg);
|
||||||
|
@ -612,6 +613,7 @@ static int get_dimm_config(const struct mem_ctl_info *mci)
|
||||||
/* On all supported DDR3 DIMM types, there are 8 banks available */
|
/* On all supported DDR3 DIMM types, there are 8 banks available */
|
||||||
banks = 8;
|
banks = 8;
|
||||||
|
|
||||||
|
dimm = mci->dimms;
|
||||||
for (i = 0; i < NUM_CHANNELS; i++) {
|
for (i = 0; i < NUM_CHANNELS; i++) {
|
||||||
u32 mtr;
|
u32 mtr;
|
||||||
|
|
||||||
|
@ -634,29 +636,30 @@ static int get_dimm_config(const struct mem_ctl_info *mci)
|
||||||
pvt->sbridge_dev->mc, i, j,
|
pvt->sbridge_dev->mc, i, j,
|
||||||
size, npages,
|
size, npages,
|
||||||
banks, ranks, rows, cols);
|
banks, ranks, rows, cols);
|
||||||
csr = &mci->csrows[csrow];
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fake stuff. This controller doesn't see
|
||||||
|
* csrows.
|
||||||
|
*/
|
||||||
|
csr = &mci->csrows[csrow];
|
||||||
csr->first_page = last_page;
|
csr->first_page = last_page;
|
||||||
csr->last_page = last_page + npages - 1;
|
csr->last_page = last_page + npages - 1;
|
||||||
csr->page_mask = 0UL; /* Unused */
|
|
||||||
csr->nr_pages = npages;
|
csr->nr_pages = npages;
|
||||||
csr->grain = 32;
|
|
||||||
csr->csrow_idx = csrow;
|
csr->csrow_idx = csrow;
|
||||||
csr->dtype = (banks == 8) ? DEV_X8 : DEV_X4;
|
|
||||||
csr->ce_count = 0;
|
|
||||||
csr->ue_count = 0;
|
|
||||||
csr->mtype = mtype;
|
|
||||||
csr->edac_mode = mode;
|
|
||||||
csr->nr_channels = 1;
|
csr->nr_channels = 1;
|
||||||
csr->channels[0].chan_idx = i;
|
csr->channels[0].chan_idx = i;
|
||||||
csr->channels[0].ce_count = 0;
|
|
||||||
pvt->csrow_map[i][j] = csrow;
|
pvt->csrow_map[i][j] = csrow;
|
||||||
snprintf(csr->channels[0].dimm->label,
|
|
||||||
sizeof(csr->channels[0].dimm->label),
|
|
||||||
"CPU_SrcID#%u_Channel#%u_DIMM#%u",
|
|
||||||
pvt->sbridge_dev->source_id, i, j);
|
|
||||||
last_page += npages;
|
last_page += npages;
|
||||||
csrow++;
|
csrow++;
|
||||||
|
|
||||||
|
csr->channels[0].dimm = dimm;
|
||||||
|
dimm->grain = 32;
|
||||||
|
dimm->dtype = (banks == 8) ? DEV_X8 : DEV_X4;
|
||||||
|
dimm->mtype = mtype;
|
||||||
|
dimm->edac_mode = mode;
|
||||||
|
snprintf(dimm->label, sizeof(dimm->label),
|
||||||
|
"CPU_SrcID#%u_Channel#%u_DIMM#%u",
|
||||||
|
pvt->sbridge_dev->source_id, i, j);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,6 +84,7 @@ static int __devinit tile_edac_init_csrows(struct mem_ctl_info *mci)
|
||||||
struct csrow_info *csrow = &mci->csrows[0];
|
struct csrow_info *csrow = &mci->csrows[0];
|
||||||
struct tile_edac_priv *priv = mci->pvt_info;
|
struct tile_edac_priv *priv = mci->pvt_info;
|
||||||
struct mshim_mem_info mem_info;
|
struct mshim_mem_info mem_info;
|
||||||
|
struct dimm_info *dimm = csrow->channels[0].dimm;
|
||||||
|
|
||||||
if (hv_dev_pread(priv->hv_devhdl, 0, (HV_VirtAddr)&mem_info,
|
if (hv_dev_pread(priv->hv_devhdl, 0, (HV_VirtAddr)&mem_info,
|
||||||
sizeof(struct mshim_mem_info), MSHIM_MEM_INFO_OFF) !=
|
sizeof(struct mshim_mem_info), MSHIM_MEM_INFO_OFF) !=
|
||||||
|
@ -93,16 +94,16 @@ static int __devinit tile_edac_init_csrows(struct mem_ctl_info *mci)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mem_info.mem_ecc)
|
if (mem_info.mem_ecc)
|
||||||
csrow->edac_mode = EDAC_SECDED;
|
dimm->edac_mode = EDAC_SECDED;
|
||||||
else
|
else
|
||||||
csrow->edac_mode = EDAC_NONE;
|
dimm->edac_mode = EDAC_NONE;
|
||||||
switch (mem_info.mem_type) {
|
switch (mem_info.mem_type) {
|
||||||
case DDR2:
|
case DDR2:
|
||||||
csrow->mtype = MEM_DDR2;
|
dimm->mtype = MEM_DDR2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DDR3:
|
case DDR3:
|
||||||
csrow->mtype = MEM_DDR3;
|
dimm->mtype = MEM_DDR3;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -112,8 +113,8 @@ static int __devinit tile_edac_init_csrows(struct mem_ctl_info *mci)
|
||||||
csrow->first_page = 0;
|
csrow->first_page = 0;
|
||||||
csrow->nr_pages = mem_info.mem_size >> PAGE_SHIFT;
|
csrow->nr_pages = mem_info.mem_size >> PAGE_SHIFT;
|
||||||
csrow->last_page = csrow->first_page + csrow->nr_pages - 1;
|
csrow->last_page = csrow->first_page + csrow->nr_pages - 1;
|
||||||
csrow->grain = TILE_EDAC_ERROR_GRAIN;
|
dimm->grain = TILE_EDAC_ERROR_GRAIN;
|
||||||
csrow->dtype = DEV_UNKNOWN;
|
dimm->dtype = DEV_UNKNOWN;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -317,7 +317,7 @@ static unsigned long drb_to_nr_pages(
|
||||||
static int x38_probe1(struct pci_dev *pdev, int dev_idx)
|
static int x38_probe1(struct pci_dev *pdev, int dev_idx)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
int i;
|
int i, j;
|
||||||
struct mem_ctl_info *mci = NULL;
|
struct mem_ctl_info *mci = NULL;
|
||||||
unsigned long last_page;
|
unsigned long last_page;
|
||||||
u16 drbs[X38_CHANNELS][X38_RANKS_PER_CHANNEL];
|
u16 drbs[X38_CHANNELS][X38_RANKS_PER_CHANNEL];
|
||||||
|
@ -372,20 +372,21 @@ static int x38_probe1(struct pci_dev *pdev, int dev_idx)
|
||||||
i / X38_RANKS_PER_CHANNEL,
|
i / X38_RANKS_PER_CHANNEL,
|
||||||
i % X38_RANKS_PER_CHANNEL);
|
i % X38_RANKS_PER_CHANNEL);
|
||||||
|
|
||||||
if (nr_pages == 0) {
|
if (nr_pages == 0)
|
||||||
csrow->mtype = MEM_EMPTY;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
csrow->first_page = last_page + 1;
|
csrow->first_page = last_page + 1;
|
||||||
last_page += nr_pages;
|
last_page += nr_pages;
|
||||||
csrow->last_page = last_page;
|
csrow->last_page = last_page;
|
||||||
csrow->nr_pages = nr_pages;
|
csrow->nr_pages = nr_pages;
|
||||||
|
|
||||||
csrow->grain = nr_pages << PAGE_SHIFT;
|
for (j = 0; j < x38_channel_num; j++) {
|
||||||
csrow->mtype = MEM_DDR2;
|
struct dimm_info *dimm = csrow->channels[j].dimm;
|
||||||
csrow->dtype = DEV_UNKNOWN;
|
dimm->grain = nr_pages << PAGE_SHIFT;
|
||||||
csrow->edac_mode = EDAC_UNKNOWN;
|
dimm->mtype = MEM_DDR2;
|
||||||
|
dimm->dtype = DEV_UNKNOWN;
|
||||||
|
dimm->edac_mode = EDAC_UNKNOWN;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
x38_clear_error_info(mci);
|
x38_clear_error_info(mci);
|
||||||
|
|
|
@ -318,6 +318,13 @@ struct dimm_info {
|
||||||
unsigned memory_controller;
|
unsigned memory_controller;
|
||||||
unsigned csrow;
|
unsigned csrow;
|
||||||
unsigned csrow_channel;
|
unsigned csrow_channel;
|
||||||
|
|
||||||
|
u32 grain; /* granularity of reported error in bytes */
|
||||||
|
enum dev_type dtype; /* memory device type */
|
||||||
|
enum mem_type mtype; /* memory dimm type */
|
||||||
|
enum edac_type edac_mode; /* EDAC mode for this dimm */
|
||||||
|
|
||||||
|
u32 ce_count; /* Correctable Errors for this dimm */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -343,19 +350,17 @@ struct rank_info {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct csrow_info {
|
struct csrow_info {
|
||||||
unsigned long first_page; /* first page number in dimm */
|
unsigned long first_page; /* first page number in csrow */
|
||||||
unsigned long last_page; /* last page number in dimm */
|
unsigned long last_page; /* last page number in csrow */
|
||||||
|
u32 nr_pages; /* number of pages in csrow */
|
||||||
unsigned long page_mask; /* used for interleaving -
|
unsigned long page_mask; /* used for interleaving -
|
||||||
* 0UL for non intlv
|
* 0UL for non intlv
|
||||||
*/
|
*/
|
||||||
u32 nr_pages; /* number of pages in csrow */
|
|
||||||
u32 grain; /* granularity of reported error in bytes */
|
|
||||||
int csrow_idx; /* the chip-select row */
|
int csrow_idx; /* the chip-select row */
|
||||||
enum dev_type dtype; /* memory device type */
|
|
||||||
u32 ue_count; /* Uncorrectable Errors for this csrow */
|
u32 ue_count; /* Uncorrectable Errors for this csrow */
|
||||||
u32 ce_count; /* Correctable Errors for this csrow */
|
u32 ce_count; /* Correctable Errors for this csrow */
|
||||||
enum mem_type mtype; /* memory csrow type */
|
|
||||||
enum edac_type edac_mode; /* EDAC mode for this csrow */
|
|
||||||
struct mem_ctl_info *mci; /* the parent */
|
struct mem_ctl_info *mci; /* the parent */
|
||||||
|
|
||||||
struct kobject kobj; /* sysfs kobject for this csrow */
|
struct kobject kobj; /* sysfs kobject for this csrow */
|
||||||
|
|
Loading…
Reference in a new issue