From a7d7d2e1a07e3811dc49af2962c940fd8bbb6c8f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 27 Jan 2012 14:12:32 -0300 Subject: edac: Create a dimm struct and move the labels into it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The way a DIMM is currently represented implies that they're linked into a per-csrow struct. However, some drivers don't see csrows, as they're ridden behind some chip like the AMB's on FBDIMM's, for example. This forced drivers to fake^Wvirtualize a csrow struct, and to create a mess under csrow/channel original's concept. Move the DIMM labels into a per-DIMM struct, and add there the real location of the socket, in terms of csrow/channel. Latter patches will modify the location to properly represent the memory architecture. All other drivers will use a per-csrow type of location. Some of those drivers will require a latter conversion, as they also fake the csrows internally. TODO: While this patch doesn't change the existing behavior, on csrows-based memory controllers, a csrow/channel pair points to a memory rank. There's a known bug at the EDAC core that allows having different labels for the same DIMM, if it has more than one rank. A latter patch is need to merge the several ranks for a DIMM into the same dimm_info struct, in order to avoid having different labels for the same DIMM. The edac_mc_alloc() will now contain a per-dimm initialization loop that will be changed by latter patches in order to match other types of memory architectures. Reviewed-by: Aristeu Rozanski Reviewed-by: Borislav Petkov Cc: Doug Thompson Cc: Ranganathan Desikan Cc: "Arvind R." Cc: "Niklas Söderlund" Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/sb_edac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/edac/sb_edac.c') diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index a203536d90dd..95901c21d5dc 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c @@ -651,8 +651,8 @@ static int get_dimm_config(const struct mem_ctl_info *mci) csr->channels[0].chan_idx = i; csr->channels[0].ce_count = 0; pvt->csrow_map[i][j] = csrow; - snprintf(csr->channels[0].label, - sizeof(csr->channels[0].label), + 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; -- cgit v1.2.3 From 084a4fccef39ac7abb039511f32380f28d0b67e6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 27 Jan 2012 18:38:08 -0300 Subject: edac: move dimm properties to struct dimm_info MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Borislav Petkov Acked-by: Chris Metcalf Cc: Doug Thompson Cc: Borislav Petkov Cc: Mark Gross Cc: Jason Uhlenkott Cc: Tim Small Cc: Ranganathan Desikan Cc: "Arvind R." Cc: Olof Johansson Cc: Egor Martovetsky Cc: Michal Marek Cc: Jiri Kosina Cc: Joe Perches Cc: Dmitry Eremin-Solenikov Cc: Benjamin Herrenschmidt Cc: Hitoshi Mitake Cc: Andrew Morton Cc: James Bottomley Cc: "Niklas Söderlund" Cc: Shaohui Xie Cc: Josh Boyer Cc: Mike Williams Cc: linuxppc-dev@lists.ozlabs.org Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/amd64_edac.c | 18 ++++++++---- drivers/edac/amd76x_edac.c | 10 ++++--- drivers/edac/cell_edac.c | 10 +++++-- drivers/edac/cpc925_edac.c | 62 ++++++++++++++++++++++-------------------- drivers/edac/e752x_edac.c | 44 ++++++++++++++++-------------- drivers/edac/e7xxx_edac.c | 44 +++++++++++++++++------------- drivers/edac/edac_mc.c | 19 ++++++++----- drivers/edac/edac_mc_sysfs.c | 6 ++-- drivers/edac/i3000_edac.c | 18 ++++++------ drivers/edac/i3200_edac.c | 18 ++++++------ drivers/edac/i5000_edac.c | 24 ++++++++-------- drivers/edac/i5100_edac.c | 38 ++++++++++++++------------ drivers/edac/i5400_edac.c | 24 ++++++---------- drivers/edac/i7300_edac.c | 25 ++++++++++------- drivers/edac/i7core_edac.c | 27 +++++++++--------- drivers/edac/i82443bxgx_edac.c | 13 +++++---- drivers/edac/i82860_edac.c | 11 +++++--- drivers/edac/i82875p_edac.c | 17 ++++++++---- drivers/edac/i82975x_edac.c | 17 ++++++++---- drivers/edac/mpc85xx_edac.c | 13 +++++---- drivers/edac/mv64x60_edac.c | 18 ++++++------ drivers/edac/pasemi_edac.c | 10 ++++--- drivers/edac/ppc4xx_edac.c | 13 +++++---- drivers/edac/r82600_edac.c | 10 ++++--- drivers/edac/sb_edac.c | 31 +++++++++++---------- drivers/edac/tile_edac.c | 13 +++++---- drivers/edac/x38_edac.c | 17 ++++++------ include/linux/edac.h | 21 ++++++++------ 28 files changed, 334 insertions(+), 257 deletions(-) (limited to 'drivers/edac/sb_edac.c') diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 7ef73c919c5d..8126db0c8987 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -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; diff --git a/drivers/edac/amd76x_edac.c b/drivers/edac/amd76x_edac.c index f8fd3c807bde..fcfe359f7be5 100644 --- a/drivers/edac/amd76x_edac.c +++ b/drivers/edac/amd76x_edac.c @@ -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; } } diff --git a/drivers/edac/cell_edac.c b/drivers/edac/cell_edac.c index 9a6a274e6925..94fbb127215a 100644 --- a/drivers/edac/cell_edac.c +++ b/drivers/edac/cell_edac.c @@ -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", diff --git a/drivers/edac/cpc925_edac.c b/drivers/edac/cpc925_edac.c index a774c0ddaf5b..ee90f3da8f3a 100644 --- a/drivers/edac/cpc925_edac.c +++ b/drivers/edac/cpc925_edac.c @@ -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; diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c index 41223261ede9..6cf6ec6bc71e 100644 --- a/drivers/edac/e752x_edac.c +++ b/drivers/edac/e752x_edac.c @@ -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; + } } } diff --git a/drivers/edac/e7xxx_edac.c b/drivers/edac/e7xxx_edac.c index 68dea87b72e6..5ed97f6eb346 100644 --- a/drivers/edac/e7xxx_edac.c +++ b/drivers/edac/e7xxx_edac.c @@ -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; + } } } diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index c1aae7233022..0942efad55c1 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -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); diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index af66b2256640..487e03eeed26 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c @@ -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 */ diff --git a/drivers/edac/i3000_edac.c b/drivers/edac/i3000_edac.c index 277689a68841..8fe60ee37826 100644 --- a/drivers/edac/i3000_edac.c +++ b/drivers/edac/i3000_edac.c @@ -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; + } } /* diff --git a/drivers/edac/i3200_edac.c b/drivers/edac/i3200_edac.c index 046808c6357d..6ae30176aef5 100644 --- a/drivers/edac/i3200_edac.c +++ b/drivers/edac/i3200_edac.c @@ -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); diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c index a2680d8e744b..95966ba9c5ca 100644 --- a/drivers/edac/i5000_edac.c +++ b/drivers/edac/i5000_edac.c @@ -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; } diff --git a/drivers/edac/i5100_edac.c b/drivers/edac/i5100_edac.c index d55e5529734c..6c0dafa3f67b 100644 --- a/drivers/edac/i5100_edac.c +++ b/drivers/edac/i5100_edac.c @@ -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)); } } diff --git a/drivers/edac/i5400_edac.c b/drivers/edac/i5400_edac.c index 1869a1018fb5..c2379ba95c5a 100644 --- a/drivers/edac/i5400_edac.c +++ b/drivers/edac/i5400_edac.c @@ -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; } diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c index 3bafa3bca148..4bfcb3da3f01 100644 --- a/drivers/edac/i7300_edac.c +++ b/drivers/edac/i7300_edac.c @@ -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; int ch, branch, slot, channel; u32 last_page = 0, nr_pages; + struct dimm_info *dimm; 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 */ + nr_pages = 0; for (slot = 0; slot < MAX_SLOTS; slot++) { int where = mtr_regs[slot]; for (branch = 0; branch < MAX_BRANCHES; branch++) { pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch], where, &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); dinfo = &pvt->dimm_info[slot][channel]; p_csrow = &mci->csrows[slot]; + dimm = p_csrow->channels[branch * MAX_CH_PER_BRANCH + ch].dimm; + 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 (!MTR_DIMMS_PRESENT(mtr)) continue; diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index df0acf02667a..5449bd40a739 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c @@ -592,7 +592,7 @@ static int i7core_get_active_channels(const u8 socket, unsigned *channels, 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 csrow_info *csr; @@ -602,6 +602,7 @@ static int get_dimm_config(const struct mem_ctl_info *mci) unsigned long last_page = 0; enum edac_type mode; enum mem_type mtype; + struct dimm_info *dimm; /* Get data from the MC register, function 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->page_mask = 0; - csr->grain = 8; csr->csrow_idx = csrow; 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; + dimm = csr->channels[0].dimm; switch (banks) { case 4: - csr->dtype = DEV_X4; + dimm->dtype = DEV_X4; break; case 8: - csr->dtype = DEV_X8; + dimm->dtype = DEV_X8; break; case 16: - csr->dtype = DEV_X16; + dimm->dtype = DEV_X16; break; default: - csr->dtype = DEV_UNKNOWN; + dimm->dtype = DEV_UNKNOWN; } - csr->edac_mode = mode; - csr->mtype = mtype; - snprintf(csr->channels[0].dimm->label, - sizeof(csr->channels[0].dimm->label), - "CPU#%uChannel#%u_DIMM#%u", - pvt->i7core_dev->socket, i, j); - - csrow++; + snprintf(dimm->label, sizeof(dimm->label), + "CPU#%uChannel#%u_DIMM#%u", + pvt->i7core_dev->socket, i, j); + dimm->grain = 8; + dimm->edac_mode = mode; + dimm->mtype = mtype; } pci_read_config_dword(pdev, MC_SAG_CH_0, &value[0]); diff --git a/drivers/edac/i82443bxgx_edac.c b/drivers/edac/i82443bxgx_edac.c index 3bf2b2f490e7..0b98dd3408b9 100644 --- a/drivers/edac/i82443bxgx_edac.c +++ b/drivers/edac/i82443bxgx_edac.c @@ -12,7 +12,7 @@ * 440GX fix by Jason Uhlenkott . * * Written with reference to 82443BX Host Bridge Datasheet: - * http://download.intel.com/design/chipsets/datashts/29063301.pdf + * http://download.intel.com/design/chipsets/datashts/29063301.pdf * references to this document given in []. * * This module doesn't support the 440LX, but it may be possible to @@ -189,6 +189,7 @@ static void i82443bxgx_init_csrows(struct mem_ctl_info *mci, enum mem_type mtype) { struct csrow_info *csrow; + struct dimm_info *dimm; int index; u8 drbar, dramc; 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; for (index = 0; index < mci->nr_csrows; index++) { csrow = &mci->csrows[index]; + dimm = csrow->channels[0].dimm; + pci_read_config_byte(pdev, I82443BXGX_DRB + index, &drbar); debugf1("MC%d: %s: %s() Row=%d DRB = %#0x\n", 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->nr_pages = csrow->last_page - csrow->first_page + 1; /* EAP reports in 4kilobyte granularity [61] */ - csrow->grain = 1 << 12; - csrow->mtype = mtype; + dimm->grain = 1 << 12; + dimm->mtype = mtype; /* 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 */ - csrow->edac_mode = edac_mode; + dimm->edac_mode = edac_mode; row_high_limit_last = row_high_limit; } } diff --git a/drivers/edac/i82860_edac.c b/drivers/edac/i82860_edac.c index c779092d18d1..3eb77845cfca 100644 --- a/drivers/edac/i82860_edac.c +++ b/drivers/edac/i82860_edac.c @@ -140,6 +140,7 @@ static void i82860_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev) u16 value; u32 cumul_size; struct csrow_info *csrow; + struct dimm_info *dimm; int index; 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++) { csrow = &mci->csrows[index]; + dimm = csrow->channels[0].dimm; + pci_read_config_word(pdev, I82860_GBA + index * 2, &value); cumul_size = (value & I82860_GBA_MASK) << (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->nr_pages = cumul_size - last_cumul_size; last_cumul_size = cumul_size; - csrow->grain = 1 << 12; /* I82860_EAP has 4KiB reolution */ - csrow->mtype = MEM_RMBS; - csrow->dtype = DEV_UNKNOWN; - csrow->edac_mode = mchcfg_ddim ? EDAC_SECDED : EDAC_NONE; + dimm->grain = 1 << 12; /* I82860_EAP has 4KiB reolution */ + dimm->mtype = MEM_RMBS; + dimm->dtype = DEV_UNKNOWN; + dimm->edac_mode = mchcfg_ddim ? EDAC_SECDED : EDAC_NONE; } } diff --git a/drivers/edac/i82875p_edac.c b/drivers/edac/i82875p_edac.c index 10f15d85fb5e..eac574285da8 100644 --- a/drivers/edac/i82875p_edac.c +++ b/drivers/edac/i82875p_edac.c @@ -342,11 +342,13 @@ static void i82875p_init_csrows(struct mem_ctl_info *mci, void __iomem * ovrfl_window, u32 drc) { struct csrow_info *csrow; + struct dimm_info *dimm; + unsigned nr_chans = dual_channel_active(drc) + 1; unsigned long last_cumul_size; u8 value; u32 drc_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */ u32 cumul_size; - int index; + int index, j; drc_ddim = (drc >> 18) & 0x1; 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->nr_pages = cumul_size - last_cumul_size; last_cumul_size = cumul_size; - csrow->grain = 1 << 12; /* I82875P_EAP has 4KiB reolution */ - csrow->mtype = MEM_DDR; - csrow->dtype = DEV_UNKNOWN; - csrow->edac_mode = drc_ddim ? EDAC_SECDED : EDAC_NONE; + + for (j = 0; j < nr_chans; j++) { + dimm = csrow->channels[j].dimm; + + 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; + } } } diff --git a/drivers/edac/i82975x_edac.c b/drivers/edac/i82975x_edac.c index b7aca58bf9eb..b8ec8719e2f5 100644 --- a/drivers/edac/i82975x_edac.c +++ b/drivers/edac/i82975x_edac.c @@ -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; offst = info->eap & ((1 << PAGE_SHIFT) - - (1 << mci->csrows[row].grain)); + (1 << mci->csrows[row].channels[chan].dimm->grain)); if (info->errsts & 0x0002) 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; u32 cumul_size; int index, chan; + struct dimm_info *dimm; + enum dev_type dtype; 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-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, labels[(index >> 1) + (chan * 2)], 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) continue; /* not populated */ @@ -418,10 +427,6 @@ static void i82975x_init_csrows(struct mem_ctl_info *mci, csrow->last_page = cumul_size - 1; csrow->nr_pages = cumul_size - last_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 */ } } diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c index 73464a62adf7..fb92916d0872 100644 --- a/drivers/edac/mpc85xx_edac.c +++ b/drivers/edac/mpc85xx_edac.c @@ -883,6 +883,7 @@ static void __devinit mpc85xx_init_csrows(struct mem_ctl_info *mci) { struct mpc85xx_mc_pdata *pdata = mci->pvt_info; struct csrow_info *csrow; + struct dimm_info *dimm; u32 sdram_ctl; u32 sdtype; enum mem_type mtype; @@ -929,6 +930,8 @@ static void __devinit mpc85xx_init_csrows(struct mem_ctl_info *mci) u32 end; csrow = &mci->csrows[index]; + dimm = csrow->channels[0].dimm; + cs_bnds = in_be32(pdata->mc_vbase + MPC85XX_MC_CS_BNDS_0 + (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->last_page = end; csrow->nr_pages = end + 1 - start; - csrow->grain = 8; - csrow->mtype = mtype; - csrow->dtype = DEV_UNKNOWN; + dimm->grain = 8; + dimm->mtype = mtype; + dimm->dtype = DEV_UNKNOWN; if (sdram_ctl & DSC_X32_EN) - csrow->dtype = DEV_X32; - csrow->edac_mode = EDAC_SECDED; + dimm->dtype = DEV_X32; + dimm->edac_mode = EDAC_SECDED; } } diff --git a/drivers/edac/mv64x60_edac.c b/drivers/edac/mv64x60_edac.c index 7e5ff367705c..12d7fe04454c 100644 --- a/drivers/edac/mv64x60_edac.c +++ b/drivers/edac/mv64x60_edac.c @@ -656,6 +656,8 @@ static void mv64x60_init_csrows(struct mem_ctl_info *mci, struct mv64x60_mc_pdata *pdata) { struct csrow_info *csrow; + struct dimm_info *dimm; + u32 devtype; 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); csrow = &mci->csrows[0]; - csrow->first_page = 0; + dimm = csrow->channels[0].dimm; csrow->nr_pages = pdata->total_mem >> PAGE_SHIFT; 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; switch (devtype) { case 0x0: - csrow->dtype = DEV_X32; + dimm->dtype = DEV_X32; break; case 0x2: /* could be X8 too, but no way to tell */ - csrow->dtype = DEV_X16; + dimm->dtype = DEV_X16; break; case 0x3: - csrow->dtype = DEV_X4; + dimm->dtype = DEV_X4; break; default: - csrow->dtype = DEV_UNKNOWN; + dimm->dtype = DEV_UNKNOWN; break; } - csrow->edac_mode = EDAC_SECDED; + dimm->edac_mode = EDAC_SECDED; } static int __devinit mv64x60_mc_err_probe(struct platform_device *pdev) diff --git a/drivers/edac/pasemi_edac.c b/drivers/edac/pasemi_edac.c index 7f71ee436744..4e53270bc336 100644 --- a/drivers/edac/pasemi_edac.c +++ b/drivers/edac/pasemi_edac.c @@ -135,11 +135,13 @@ static int pasemi_edac_init_csrows(struct mem_ctl_info *mci, enum edac_type edac_mode) { struct csrow_info *csrow; + struct dimm_info *dimm; u32 rankcfg; int index; for (index = 0; index < mci->nr_csrows; index++) { csrow = &mci->csrows[index]; + dimm = csrow->channels[0].dimm; pci_read_config_dword(pdev, 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; last_page_in_mmc += csrow->nr_pages; csrow->page_mask = 0; - csrow->grain = PASEMI_EDAC_ERROR_GRAIN; - csrow->mtype = MEM_DDR; - csrow->dtype = DEV_UNKNOWN; - csrow->edac_mode = edac_mode; + dimm->grain = PASEMI_EDAC_ERROR_GRAIN; + dimm->mtype = MEM_DDR; + dimm->dtype = DEV_UNKNOWN; + dimm->edac_mode = edac_mode; } return 0; } diff --git a/drivers/edac/ppc4xx_edac.c b/drivers/edac/ppc4xx_edac.c index d427c69bb8b1..a75e56788b29 100644 --- a/drivers/edac/ppc4xx_edac.c +++ b/drivers/edac/ppc4xx_edac.c @@ -895,7 +895,7 @@ ppc4xx_edac_init_csrows(struct mem_ctl_info *mci, u32 mcopt1) enum mem_type mtype; enum dev_type dtype; enum edac_type edac_mode; - int row; + int row, j; u32 mbxcf, size; static u32 ppc4xx_last_page; @@ -975,15 +975,18 @@ ppc4xx_edac_init_csrows(struct mem_ctl_info *mci, u32 mcopt1) * possible values would be the PLB width (16), the * 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; - csi->dtype = dtype; + dimm->mtype = mtype; + dimm->dtype = dtype; - csi->edac_mode = edac_mode; + dimm->edac_mode = edac_mode; ppc4xx_last_page += csi->nr_pages; + } } done: diff --git a/drivers/edac/r82600_edac.c b/drivers/edac/r82600_edac.c index 6d908ad72d64..70b0dfa81db4 100644 --- a/drivers/edac/r82600_edac.c +++ b/drivers/edac/r82600_edac.c @@ -216,6 +216,7 @@ static void r82600_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev, u8 dramcr) { struct csrow_info *csrow; + struct dimm_info *dimm; int index; u8 drbar; /* SDRAM Row Boundary Address Register */ 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++) { csrow = &mci->csrows[index]; + dimm = csrow->channels[0].dimm; /* find the DRAM Chip Select Base address and mask */ 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; /* Error address is top 19 bits - so granularity is * * 14 bits */ - csrow->grain = 1 << 14; - csrow->mtype = reg_sdram ? MEM_RDDR : MEM_DDR; + dimm->grain = 1 << 14; + dimm->mtype = reg_sdram ? MEM_RDDR : MEM_DDR; /* FIXME - check that this is unknowable with this chipset */ - csrow->dtype = DEV_UNKNOWN; + dimm->dtype = DEV_UNKNOWN; /* 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; } } diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index 95901c21d5dc..21147ac38c4d 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c @@ -551,7 +551,7 @@ static int sbridge_get_active_channels(const u8 bus, unsigned *channels, 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 csrow_info *csr; @@ -561,6 +561,7 @@ static int get_dimm_config(const struct mem_ctl_info *mci) u32 reg; enum edac_type mode; enum mem_type mtype; + struct dimm_info *dimm; pci_read_config_dword(pvt->pci_br, SAD_TARGET, ®); 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 */ banks = 8; + dimm = mci->dimms; for (i = 0; i < NUM_CHANNELS; i++) { u32 mtr; @@ -634,29 +636,30 @@ static int get_dimm_config(const struct mem_ctl_info *mci) pvt->sbridge_dev->mc, i, j, size, npages, 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->last_page = last_page + npages - 1; - csr->page_mask = 0UL; /* Unused */ csr->nr_pages = npages; - csr->grain = 32; 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->channels[0].chan_idx = i; - csr->channels[0].ce_count = 0; 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; 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); } } } diff --git a/drivers/edac/tile_edac.c b/drivers/edac/tile_edac.c index e99d00976189..c870f68ae8f1 100644 --- a/drivers/edac/tile_edac.c +++ b/drivers/edac/tile_edac.c @@ -84,6 +84,7 @@ static int __devinit tile_edac_init_csrows(struct mem_ctl_info *mci) struct csrow_info *csrow = &mci->csrows[0]; struct tile_edac_priv *priv = mci->pvt_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, 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) - csrow->edac_mode = EDAC_SECDED; + dimm->edac_mode = EDAC_SECDED; else - csrow->edac_mode = EDAC_NONE; + dimm->edac_mode = EDAC_NONE; switch (mem_info.mem_type) { case DDR2: - csrow->mtype = MEM_DDR2; + dimm->mtype = MEM_DDR2; break; case DDR3: - csrow->mtype = MEM_DDR3; + dimm->mtype = MEM_DDR3; break; default: @@ -112,8 +113,8 @@ static int __devinit tile_edac_init_csrows(struct mem_ctl_info *mci) csrow->first_page = 0; csrow->nr_pages = mem_info.mem_size >> PAGE_SHIFT; csrow->last_page = csrow->first_page + csrow->nr_pages - 1; - csrow->grain = TILE_EDAC_ERROR_GRAIN; - csrow->dtype = DEV_UNKNOWN; + dimm->grain = TILE_EDAC_ERROR_GRAIN; + dimm->dtype = DEV_UNKNOWN; return 0; } diff --git a/drivers/edac/x38_edac.c b/drivers/edac/x38_edac.c index a438297389e5..f7cc4d214949 100644 --- a/drivers/edac/x38_edac.c +++ b/drivers/edac/x38_edac.c @@ -317,7 +317,7 @@ static unsigned long drb_to_nr_pages( static int x38_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[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); - 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 < x38_channel_num; 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; + } } x38_clear_error_info(mci); diff --git a/include/linux/edac.h b/include/linux/edac.h index 52bceca85e63..87aa07d2ee28 100644 --- a/include/linux/edac.h +++ b/include/linux/edac.h @@ -318,6 +318,13 @@ struct dimm_info { unsigned memory_controller; unsigned csrow; 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 { - unsigned long first_page; /* first page number in dimm */ - unsigned long last_page; /* last page number in dimm */ + unsigned long first_page; /* first page number in csrow */ + unsigned long last_page; /* last page number in csrow */ + u32 nr_pages; /* number of pages in csrow */ unsigned long page_mask; /* used for interleaving - * 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 */ - enum dev_type dtype; /* memory device type */ + int csrow_idx; /* the chip-select row */ + u32 ue_count; /* Uncorrectable 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 kobject kobj; /* sysfs kobject for this csrow */ -- cgit v1.2.3 From 5e2af0c09e60d11dd8297e259a9ca2b3d92d2cf4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 27 Jan 2012 21:20:32 -0300 Subject: edac: Don't initialize csrow's first_page & friends when not needed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Almost all edac drivers initialize csrow_info->first_page, csrow_info->last_page and csrow_info->page_mask. Those vars are used inside the EDAC core, in order to calculate the csrow affected by an error, by using the routine edac_mc_find_csrow_by_page(). However, very few drivers actually use it: e752x_edac.c e7xxx_edac.c i3000_edac.c i82443bxgx_edac.c i82860_edac.c i82875p_edac.c i82975x_edac.c r82600_edac.c There also a few other drivers that have their own calculus formula internally using those vars. All the others are just wasting time by initializing those data. While initializing data without using them won't cause any troubles, as those information is stored at the wrong place (at csrows structure), it is better to remove what is unused, in order to simplify the next patch. Reviewed-by: Aristeu Rozanski Acked-by: Borislav Petkov Acked-by: Chris Metcalf Cc: Doug Thompson Cc: Hitoshi Mitake Cc: Andrew Morton Cc: "Niklas Söderlund" Cc: Josh Boyer Cc: Jiri Kosina Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/amd64_edac.c | 37 ++----------------------------------- drivers/edac/i3200_edac.c | 5 ----- drivers/edac/i5000_edac.c | 5 ----- drivers/edac/i5100_edac.c | 2 -- drivers/edac/i5400_edac.c | 5 ----- drivers/edac/i7300_edac.c | 5 +---- drivers/edac/i7core_edac.c | 5 ----- drivers/edac/mv64x60_edac.c | 1 - drivers/edac/ppc4xx_edac.c | 7 ------- drivers/edac/sb_edac.c | 2 -- drivers/edac/tile_edac.c | 2 -- drivers/edac/x38_edac.c | 5 ----- 12 files changed, 3 insertions(+), 78 deletions(-) (limited to 'drivers/edac/sb_edac.c') diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 8126db0c8987..e2c5a94f683c 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -715,25 +715,6 @@ static inline u64 input_addr_to_sys_addr(struct mem_ctl_info *mci, input_addr_to_dram_addr(mci, input_addr)); } -/* - * Find the minimum and maximum InputAddr values that map to the given @csrow. - * Pass back these values in *input_addr_min and *input_addr_max. - */ -static void find_csrow_limits(struct mem_ctl_info *mci, int csrow, - u64 *input_addr_min, u64 *input_addr_max) -{ - struct amd64_pvt *pvt; - u64 base, mask; - - pvt = mci->pvt_info; - BUG_ON((csrow < 0) || (csrow >= pvt->csels[0].b_cnt)); - - get_cs_base_and_mask(pvt, csrow, 0, &base, &mask); - - *input_addr_min = base & ~mask; - *input_addr_max = base | mask; -} - /* Map the Error address to a PAGE and PAGE OFFSET. */ static inline void error_address_to_page_and_offset(u64 error_address, u32 *page, u32 *offset) @@ -2185,7 +2166,7 @@ static int init_csrows(struct mem_ctl_info *mci) { struct csrow_info *csrow; struct amd64_pvt *pvt = mci->pvt_info; - u64 input_addr_min, input_addr_max, sys_addr, base, mask; + u64 base, mask; u32 val; int i, j, empty = 1; enum mem_type mtype; @@ -2216,28 +2197,14 @@ static int init_csrows(struct mem_ctl_info *mci) csrow->nr_pages = amd64_csrow_nr_pages(pvt, 0, i); if (csrow_enabled(i, 1, pvt)) csrow->nr_pages += amd64_csrow_nr_pages(pvt, 1, i); - find_csrow_limits(mci, i, &input_addr_min, &input_addr_max); - sys_addr = input_addr_to_sys_addr(mci, input_addr_min); - csrow->first_page = (u32) (sys_addr >> PAGE_SHIFT); - sys_addr = input_addr_to_sys_addr(mci, input_addr_max); - csrow->last_page = (u32) (sys_addr >> PAGE_SHIFT); get_cs_base_and_mask(pvt, i, 0, &base, &mask); - csrow->page_mask = ~mask; /* 8 bytes of resolution */ 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", - (unsigned long)input_addr_min, - (unsigned long)input_addr_max); - debugf1(" sys_addr: 0x%lx page_mask: 0x%lx\n", - (unsigned long)sys_addr, csrow->page_mask); - debugf1(" nr_pages: %u first_page: 0x%lx " - "last_page: 0x%lx\n", - (unsigned)csrow->nr_pages, - csrow->first_page, csrow->last_page); + debugf1(" nr_pages: %u\n", csrow->nr_pages); /* * determine whether CHIPKILL or JUST ECC or NO ECC is operating diff --git a/drivers/edac/i3200_edac.c b/drivers/edac/i3200_edac.c index 6ae30176aef5..93c4d5a6a623 100644 --- a/drivers/edac/i3200_edac.c +++ b/drivers/edac/i3200_edac.c @@ -321,7 +321,6 @@ static int i3200_probe1(struct pci_dev *pdev, int dev_idx) int rc; int i, j; struct mem_ctl_info *mci = NULL; - unsigned long last_page; u16 drbs[I3200_CHANNELS][I3200_RANKS_PER_CHANNEL]; bool stacked; void __iomem *window; @@ -366,7 +365,6 @@ static int i3200_probe1(struct pci_dev *pdev, int dev_idx) * cumulative; the last one will contain the total memory * contained in all ranks. */ - last_page = -1UL; for (i = 0; i < mci->nr_csrows; i++) { unsigned long nr_pages; struct csrow_info *csrow = &mci->csrows[i]; @@ -378,9 +376,6 @@ static int i3200_probe1(struct pci_dev *pdev, int dev_idx) 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; for (j = 0; j < nr_channels; j++) { diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c index 95966ba9c5ca..26b40556958e 100644 --- a/drivers/edac/i5000_edac.c +++ b/drivers/edac/i5000_edac.c @@ -1263,11 +1263,6 @@ static int i5000_init_csrows(struct mem_ctl_info *mci) if (!MTR_DIMMS_PRESENT(mtr) && !MTR_DIMMS_PRESENT(mtr1)) continue; - /* FAKE OUT VALUES, FIXME */ - p_csrow->first_page = 0 + csrow * 20; - p_csrow->last_page = 9 + csrow * 20; - p_csrow->page_mask = 0xFFF; - csrow_megs = 0; for (channel = 0; channel < pvt->maxch; channel++) { csrow_megs += pvt->dimm_info[csrow][channel].megabytes; diff --git a/drivers/edac/i5100_edac.c b/drivers/edac/i5100_edac.c index 6c0dafa3f67b..5338c7968f78 100644 --- a/drivers/edac/i5100_edac.c +++ b/drivers/edac/i5100_edac.c @@ -859,8 +859,6 @@ static void __devinit i5100_init_csrows(struct mem_ctl_info *mci) * FIXME: these two are totally bogus -- I don't see how to * map them correctly to this structure... */ - mci->csrows[i].first_page = total_pages; - mci->csrows[i].last_page = total_pages + npages - 1; mci->csrows[i].nr_pages = npages; mci->csrows[i].csrow_idx = i; mci->csrows[i].mci = mci; diff --git a/drivers/edac/i5400_edac.c b/drivers/edac/i5400_edac.c index c2379ba95c5a..6f85dcb34019 100644 --- a/drivers/edac/i5400_edac.c +++ b/drivers/edac/i5400_edac.c @@ -1180,11 +1180,6 @@ static int i5400_init_csrows(struct mem_ctl_info *mci) if (!MTR_DIMMS_PRESENT(mtr)) continue; - /* FAKE OUT VALUES, FIXME */ - p_csrow->first_page = 0 + csrow * 20; - p_csrow->last_page = 9 + csrow * 20; - p_csrow->page_mask = 0xFFF; - csrow_megs = 0; for (channel = 0; channel < pvt->maxch; channel++) { csrow_megs += pvt->dimm_info[csrow][channel].megabytes; diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c index 4bfcb3da3f01..d4153d6cfe30 100644 --- a/drivers/edac/i7300_edac.c +++ b/drivers/edac/i7300_edac.c @@ -778,7 +778,7 @@ static int i7300_init_csrows(struct mem_ctl_info *mci) int rc = -ENODEV; int mtr; int ch, branch, slot, channel; - u32 last_page = 0, nr_pages; + u32 nr_pages; struct dimm_info *dimm; pvt = mci->pvt_info; @@ -828,9 +828,6 @@ static int i7300_init_csrows(struct mem_ctl_info *mci) /* Update per_csrow memory count */ p_csrow->nr_pages += nr_pages; - p_csrow->first_page = last_page; - last_page += nr_pages; - p_csrow->last_page = last_page; rc = 0; } diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index 5449bd40a739..76c957c525fb 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c @@ -599,7 +599,6 @@ static int get_dimm_config(struct mem_ctl_info *mci) struct pci_dev *pdev; int i, j; int csrow = 0; - unsigned long last_page = 0; enum edac_type mode; enum mem_type mtype; struct dimm_info *dimm; @@ -716,12 +715,8 @@ static int get_dimm_config(struct mem_ctl_info *mci) npages = MiB_TO_PAGES(size); csr = &mci->csrows[csrow]; - csr->first_page = last_page + 1; - last_page += npages; - csr->last_page = last_page; csr->nr_pages = npages; - csr->page_mask = 0; csr->csrow_idx = csrow; csr->nr_channels = 1; diff --git a/drivers/edac/mv64x60_edac.c b/drivers/edac/mv64x60_edac.c index 12d7fe04454c..d2e3c39ede9f 100644 --- a/drivers/edac/mv64x60_edac.c +++ b/drivers/edac/mv64x60_edac.c @@ -668,7 +668,6 @@ static void mv64x60_init_csrows(struct mem_ctl_info *mci, csrow = &mci->csrows[0]; dimm = csrow->channels[0].dimm; csrow->nr_pages = pdata->total_mem >> PAGE_SHIFT; - csrow->last_page = csrow->first_page + csrow->nr_pages - 1; dimm->grain = 8; dimm->mtype = (ctl & MV64X60_SDRAM_REGISTERED) ? MEM_RDDR : MEM_DDR; diff --git a/drivers/edac/ppc4xx_edac.c b/drivers/edac/ppc4xx_edac.c index a75e56788b29..ec5e529e33f6 100644 --- a/drivers/edac/ppc4xx_edac.c +++ b/drivers/edac/ppc4xx_edac.c @@ -897,7 +897,6 @@ ppc4xx_edac_init_csrows(struct mem_ctl_info *mci, u32 mcopt1) enum edac_type edac_mode; int row, j; u32 mbxcf, size; - static u32 ppc4xx_last_page; /* Establish the memory type and width */ @@ -959,10 +958,6 @@ ppc4xx_edac_init_csrows(struct mem_ctl_info *mci, u32 mcopt1) goto done; } - csi->first_page = ppc4xx_last_page; - csi->last_page = csi->first_page + csi->nr_pages - 1; - csi->page_mask = 0; - /* * It's unclear exactly what grain should be set to * here. The SDRAM_ECCES register allows resolution of @@ -984,8 +979,6 @@ ppc4xx_edac_init_csrows(struct mem_ctl_info *mci, u32 mcopt1) dimm->dtype = dtype; dimm->edac_mode = edac_mode; - - ppc4xx_last_page += csi->nr_pages; } } diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index 21147ac38c4d..d5892c052bf4 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c @@ -642,8 +642,6 @@ static int get_dimm_config(struct mem_ctl_info *mci) * csrows. */ csr = &mci->csrows[csrow]; - csr->first_page = last_page; - csr->last_page = last_page + npages - 1; csr->nr_pages = npages; csr->csrow_idx = csrow; csr->nr_channels = 1; diff --git a/drivers/edac/tile_edac.c b/drivers/edac/tile_edac.c index c870f68ae8f1..54067c4b0cc1 100644 --- a/drivers/edac/tile_edac.c +++ b/drivers/edac/tile_edac.c @@ -110,9 +110,7 @@ static int __devinit tile_edac_init_csrows(struct mem_ctl_info *mci) return -1; } - csrow->first_page = 0; csrow->nr_pages = mem_info.mem_size >> PAGE_SHIFT; - csrow->last_page = csrow->first_page + csrow->nr_pages - 1; dimm->grain = TILE_EDAC_ERROR_GRAIN; dimm->dtype = DEV_UNKNOWN; diff --git a/drivers/edac/x38_edac.c b/drivers/edac/x38_edac.c index f7cc4d214949..bc7f880a4eed 100644 --- a/drivers/edac/x38_edac.c +++ b/drivers/edac/x38_edac.c @@ -319,7 +319,6 @@ static int x38_probe1(struct pci_dev *pdev, int dev_idx) int rc; int i, j; struct mem_ctl_info *mci = NULL; - unsigned long last_page; u16 drbs[X38_CHANNELS][X38_RANKS_PER_CHANNEL]; bool stacked; void __iomem *window; @@ -363,7 +362,6 @@ static int x38_probe1(struct pci_dev *pdev, int dev_idx) * cumulative; the last one will contain the total memory * contained in all ranks. */ - last_page = -1UL; for (i = 0; i < mci->nr_csrows; i++) { unsigned long nr_pages; struct csrow_info *csrow = &mci->csrows[i]; @@ -375,9 +373,6 @@ static int x38_probe1(struct pci_dev *pdev, int dev_idx) 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; for (j = 0; j < x38_channel_num; j++) { -- cgit v1.2.3 From a895bf8b1e1ea4c032a8fa8a09475a2ce09fe77a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 28 Jan 2012 09:09:38 -0300 Subject: edac: move nr_pages to dimm struct MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The number of pages is a dimm property. Move it to the dimm struct. After this change, it is possible to add sysfs nodes for the DIMM's that will properly represent the DIMM stick properties, including its size. A TODO fix here is to properly represent dual-rank/quad-rank DIMMs when the memory controller represents the memory via chip select rows. Reviewed-by: Aristeu Rozanski Acked-by: Borislav Petkov Acked-by: Chris Metcalf Cc: Doug Thompson Cc: Mark Gross Cc: Jason Uhlenkott Cc: Tim Small Cc: Ranganathan Desikan Cc: "Arvind R." Cc: Olof Johansson Cc: Egor Martovetsky Cc: Michal Marek Cc: Jiri Kosina Cc: Joe Perches Cc: Dmitry Eremin-Solenikov Cc: Benjamin Herrenschmidt Cc: Hitoshi Mitake Cc: Andrew Morton Cc: "Niklas Söderlund" Cc: Shaohui Xie Cc: Josh Boyer Cc: linuxppc-dev@lists.ozlabs.org Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/amd64_edac.c | 10 +++++---- drivers/edac/amd76x_edac.c | 6 +++--- drivers/edac/cell_edac.c | 8 ++++--- drivers/edac/cpc925_edac.c | 8 ++++--- drivers/edac/e752x_edac.c | 6 ++++-- drivers/edac/e7xxx_edac.c | 5 +++-- drivers/edac/edac_mc.c | 16 ++++++++------ drivers/edac/edac_mc_sysfs.c | 47 +++++++++++++++++++++++++++++------------- drivers/edac/i3000_edac.c | 6 ++++-- drivers/edac/i3200_edac.c | 3 +-- drivers/edac/i5000_edac.c | 14 +++++++------ drivers/edac/i5100_edac.c | 22 ++++++++++++-------- drivers/edac/i5400_edac.c | 9 +++----- drivers/edac/i7300_edac.c | 22 ++++++-------------- drivers/edac/i7core_edac.c | 10 +++------ drivers/edac/i82443bxgx_edac.c | 2 +- drivers/edac/i82860_edac.c | 2 +- drivers/edac/i82875p_edac.c | 5 +++-- drivers/edac/i82975x_edac.c | 11 +++++++--- drivers/edac/mpc85xx_edac.c | 3 ++- drivers/edac/mv64x60_edac.c | 3 ++- drivers/edac/pasemi_edac.c | 14 ++++++------- drivers/edac/ppc4xx_edac.c | 5 +++-- drivers/edac/r82600_edac.c | 3 ++- drivers/edac/sb_edac.c | 8 ++----- drivers/edac/tile_edac.c | 2 +- drivers/edac/x38_edac.c | 4 ++-- include/linux/edac.h | 8 ++++--- 28 files changed, 146 insertions(+), 116 deletions(-) (limited to 'drivers/edac/sb_edac.c') diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index e2c5a94f683c..1ceb8e276376 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -2152,7 +2152,7 @@ static u32 amd64_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr) nr_pages = pvt->ops->dbam_to_cs(pvt, dct, cs_mode) << (20 - PAGE_SHIFT); debugf0(" (csrow=%d) DBAM map index= %d\n", csrow_nr, cs_mode); - debugf0(" nr_pages= %u channel-count = %d\n", + debugf0(" nr_pages/channel= %u channel-count = %d\n", nr_pages, pvt->channel_count); return nr_pages; @@ -2171,6 +2171,7 @@ static int init_csrows(struct mem_ctl_info *mci) int i, j, empty = 1; enum mem_type mtype; enum edac_type edac_mode; + int nr_pages = 0; amd64_read_pci_cfg(pvt->F3, NBCFG, &val); @@ -2194,9 +2195,9 @@ static int init_csrows(struct mem_ctl_info *mci) empty = 0; if (csrow_enabled(i, 0, pvt)) - csrow->nr_pages = amd64_csrow_nr_pages(pvt, 0, i); + nr_pages = amd64_csrow_nr_pages(pvt, 0, i); if (csrow_enabled(i, 1, pvt)) - csrow->nr_pages += amd64_csrow_nr_pages(pvt, 1, i); + nr_pages += amd64_csrow_nr_pages(pvt, 1, i); get_cs_base_and_mask(pvt, i, 0, &base, &mask); /* 8 bytes of resolution */ @@ -2204,7 +2205,7 @@ static int init_csrows(struct mem_ctl_info *mci) mtype = amd64_determine_memory_type(pvt, i); debugf1(" for MC node %d csrow %d:\n", pvt->mc_node_id, i); - debugf1(" nr_pages: %u\n", csrow->nr_pages); + debugf1(" nr_pages: %u\n", nr_pages * pvt->channel_count); /* * determine whether CHIPKILL or JUST ECC or NO ECC is operating @@ -2218,6 +2219,7 @@ static int init_csrows(struct mem_ctl_info *mci) for (j = 0; j < pvt->channel_count; j++) { csrow->channels[j].dimm->mtype = mtype; csrow->channels[j].dimm->edac_mode = edac_mode; + csrow->channels[j].dimm->nr_pages = nr_pages; } } diff --git a/drivers/edac/amd76x_edac.c b/drivers/edac/amd76x_edac.c index fcfe359f7be5..a2dde205f651 100644 --- a/drivers/edac/amd76x_edac.c +++ b/drivers/edac/amd76x_edac.c @@ -205,10 +205,10 @@ static void amd76x_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev, mba_mask = ((mba & 0xff80) << 16) | 0x7fffffUL; pci_read_config_dword(pdev, AMD76X_DRAM_MODE_STATUS, &dms); csrow->first_page = mba_base >> PAGE_SHIFT; - csrow->nr_pages = (mba_mask + 1) >> PAGE_SHIFT; - csrow->last_page = csrow->first_page + csrow->nr_pages - 1; + dimm->nr_pages = (mba_mask + 1) >> PAGE_SHIFT; + csrow->last_page = csrow->first_page + dimm->nr_pages - 1; csrow->page_mask = mba_mask >> PAGE_SHIFT; - dimm->grain = csrow->nr_pages << PAGE_SHIFT; + dimm->grain = dimm->nr_pages << PAGE_SHIFT; dimm->mtype = MEM_RDDR; dimm->dtype = ((dms >> index) & 0x1) ? DEV_X4 : DEV_UNKNOWN; dimm->edac_mode = edac_mode; diff --git a/drivers/edac/cell_edac.c b/drivers/edac/cell_edac.c index 94fbb127215a..09e1b5d3df70 100644 --- a/drivers/edac/cell_edac.c +++ b/drivers/edac/cell_edac.c @@ -128,6 +128,7 @@ static void __devinit cell_edac_init_csrows(struct mem_ctl_info *mci) struct cell_edac_priv *priv = mci->pvt_info; struct device_node *np; int j; + u32 nr_pages; for (np = NULL; (np = of_find_node_by_name(np, "memory")) != NULL;) { @@ -142,19 +143,20 @@ static void __devinit cell_edac_init_csrows(struct mem_ctl_info *mci) if (of_node_to_nid(np) != priv->node) continue; 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; + nr_pages = resource_size(&r) >> PAGE_SHIFT; + csrow->last_page = csrow->first_page + nr_pages - 1; for (j = 0; j < csrow->nr_channels; j++) { dimm = csrow->channels[j].dimm; dimm->mtype = MEM_XDR; dimm->edac_mode = EDAC_SECDED; + dimm->nr_pages = nr_pages / csrow->nr_channels; } dev_dbg(mci->dev, "Initialized on node %d, chanmask=0x%x," " first_page=0x%lx, nr_pages=0x%x\n", priv->node, priv->chanmask, - csrow->first_page, csrow->nr_pages); + csrow->first_page, dimm->nr_pages); break; } } diff --git a/drivers/edac/cpc925_edac.c b/drivers/edac/cpc925_edac.c index ee90f3da8f3a..7b764a882dae 100644 --- a/drivers/edac/cpc925_edac.c +++ b/drivers/edac/cpc925_edac.c @@ -332,7 +332,7 @@ static void cpc925_init_csrows(struct mem_ctl_info *mci) struct dimm_info *dimm; int index, j; u32 mbmr, mbbar, bba; - unsigned long row_size, last_nr_pages = 0; + unsigned long row_size, nr_pages, last_nr_pages = 0; get_total_mem(pdata); @@ -351,12 +351,14 @@ static void cpc925_init_csrows(struct mem_ctl_info *mci) row_size = bba * (1UL << 28); /* 256M */ csrow->first_page = last_nr_pages; - csrow->nr_pages = row_size >> PAGE_SHIFT; - csrow->last_page = csrow->first_page + csrow->nr_pages - 1; + nr_pages = row_size >> PAGE_SHIFT; + csrow->last_page = csrow->first_page + nr_pages - 1; last_nr_pages = csrow->last_page + 1; for (j = 0; j < csrow->nr_channels; j++) { dimm = csrow->channels[j].dimm; + + dimm->nr_pages = nr_pages / csrow->nr_channels; dimm->mtype = MEM_RDDR; dimm->edac_mode = EDAC_SECDED; diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c index 6cf6ec6bc71e..cf17579ebc6d 100644 --- a/drivers/edac/e752x_edac.c +++ b/drivers/edac/e752x_edac.c @@ -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, i; + u32 dra, drc, cumul_size, i, nr_pages; dra = 0; for (index = 0; index < 4; index++) { @@ -1078,11 +1078,13 @@ static void e752x_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev, csrow->first_page = last_cumul_size; csrow->last_page = cumul_size - 1; - csrow->nr_pages = cumul_size - last_cumul_size; + nr_pages = cumul_size - last_cumul_size; last_cumul_size = cumul_size; for (i = 0; i < drc_chan + 1; i++) { struct dimm_info *dimm = csrow->channels[i].dimm; + + dimm->nr_pages = nr_pages / (drc_chan + 1); dimm->grain = 1 << 12; /* 4KiB - resolution of CELOG */ dimm->mtype = MEM_RDDR; /* only one type supported */ dimm->dtype = mem_dev ? DEV_X4 : DEV_X8; diff --git a/drivers/edac/e7xxx_edac.c b/drivers/edac/e7xxx_edac.c index 5ed97f6eb346..709aca216639 100644 --- a/drivers/edac/e7xxx_edac.c +++ b/drivers/edac/e7xxx_edac.c @@ -349,7 +349,7 @@ static void e7xxx_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev, unsigned long last_cumul_size; int index, j; u8 value; - u32 dra, cumul_size; + u32 dra, cumul_size, nr_pages; int drc_chan, drc_drbg, drc_ddim, mem_dev; struct csrow_info *csrow; struct dimm_info *dimm; @@ -380,12 +380,13 @@ static void e7xxx_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev, csrow->first_page = last_cumul_size; csrow->last_page = cumul_size - 1; - csrow->nr_pages = cumul_size - last_cumul_size; + nr_pages = cumul_size - last_cumul_size; last_cumul_size = cumul_size; for (j = 0; j < drc_chan + 1; j++) { dimm = csrow->channels[j].dimm; + dimm->nr_pages = nr_pages / (drc_chan + 1); dimm->grain = 1 << 12; /* 4KiB - resolution of CELOG */ dimm->mtype = MEM_RDDR; /* only one type supported */ dimm->dtype = mem_dev ? DEV_X4 : DEV_X8; diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 0942efad55c1..072aa81b4a70 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -43,9 +43,10 @@ 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->dimm->ce_count); - debugf4("\tchannel->label = '%s'\n", chan->dimm->label); debugf4("\tchannel->csrow = %p\n\n", chan->csrow); + debugf4("\tdimm->ce_count = %d\n", chan->dimm->ce_count); + debugf4("\tdimm->label = '%s'\n", chan->dimm->label); + debugf4("\tdimm->nr_pages = 0x%x\n", chan->dimm->nr_pages); } static void edac_mc_dump_csrow(struct csrow_info *csrow) @@ -55,7 +56,6 @@ static void edac_mc_dump_csrow(struct csrow_info *csrow) debugf4("\tcsrow->first_page = 0x%lx\n", csrow->first_page); debugf4("\tcsrow->last_page = 0x%lx\n", csrow->last_page); debugf4("\tcsrow->page_mask = 0x%lx\n", csrow->page_mask); - debugf4("\tcsrow->nr_pages = 0x%x\n", csrow->nr_pages); debugf4("\tcsrow->nr_channels = %d\n", csrow->nr_channels); debugf4("\tcsrow->channels = %p\n", csrow->channels); debugf4("\tcsrow->mci = %p\n\n", csrow->mci); @@ -652,15 +652,19 @@ static void edac_mc_scrub_block(unsigned long page, unsigned long offset, int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci, unsigned long page) { struct csrow_info *csrows = mci->csrows; - int row, i; + int row, i, j, n; debugf1("MC%d: %s(): 0x%lx\n", mci->mc_idx, __func__, page); row = -1; for (i = 0; i < mci->nr_csrows; i++) { struct csrow_info *csrow = &csrows[i]; - - if (csrow->nr_pages == 0) + n = 0; + for (j = 0; j < csrow->nr_channels; j++) { + struct dimm_info *dimm = csrow->channels[j].dimm; + n += dimm->nr_pages; + } + if (n == 0) continue; debugf3("MC%d: %s(): first(0x%lx) page(0x%lx) last(0x%lx) " diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index 487e03eeed26..1dc1c6ca4308 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c @@ -144,7 +144,13 @@ static ssize_t csrow_ce_count_show(struct csrow_info *csrow, char *data, static ssize_t csrow_size_show(struct csrow_info *csrow, char *data, int private) { - return sprintf(data, "%u\n", PAGES_TO_MiB(csrow->nr_pages)); + int i; + u32 nr_pages = 0; + + for (i = 0; i < csrow->nr_channels; i++) + nr_pages += csrow->channels[i].dimm->nr_pages; + + return sprintf(data, "%u\n", PAGES_TO_MiB(nr_pages)); } static ssize_t csrow_mem_type_show(struct csrow_info *csrow, char *data, @@ -519,16 +525,16 @@ static ssize_t mci_ctl_name_show(struct mem_ctl_info *mci, char *data) static ssize_t mci_size_mb_show(struct mem_ctl_info *mci, char *data) { - int total_pages, csrow_idx; + int total_pages = 0, csrow_idx, j; - for (total_pages = csrow_idx = 0; csrow_idx < mci->nr_csrows; - csrow_idx++) { + for (csrow_idx = 0; csrow_idx < mci->nr_csrows; csrow_idx++) { struct csrow_info *csrow = &mci->csrows[csrow_idx]; - if (!csrow->nr_pages) - continue; + for (j = 0; j < csrow->nr_channels; j++) { + struct dimm_info *dimm = csrow->channels[j].dimm; - total_pages += csrow->nr_pages; + total_pages += dimm->nr_pages; + } } return sprintf(data, "%u\n", PAGES_TO_MiB(total_pages)); @@ -900,7 +906,7 @@ static void edac_remove_mci_instance_attributes(struct mem_ctl_info *mci, */ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci) { - int i; + int i, j; int err; struct csrow_info *csrow; struct kobject *kobj_mci = &mci->edac_mci_kobj; @@ -934,10 +940,13 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci) /* Make directories for each CSROW object under the mc kobject */ for (i = 0; i < mci->nr_csrows; i++) { + int nr_pages = 0; + csrow = &mci->csrows[i]; + for (j = 0; j < csrow->nr_channels; j++) + nr_pages += csrow->channels[j].dimm->nr_pages; - /* Only expose populated CSROWs */ - if (csrow->nr_pages > 0) { + if (nr_pages > 0) { err = edac_create_csrow_object(mci, csrow, i); if (err) { debugf1("%s() failure: create csrow %d obj\n", @@ -949,10 +958,14 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci) return 0; - /* CSROW error: backout what has already been registered, */ fail1: for (i--; i >= 0; i--) { - if (mci->csrows[i].nr_pages > 0) + int nr_pages = 0; + + csrow = &mci->csrows[i]; + for (j = 0; j < csrow->nr_channels; j++) + nr_pages += csrow->channels[j].dimm->nr_pages; + if (nr_pages > 0) kobject_put(&mci->csrows[i].kobj); } @@ -972,14 +985,20 @@ fail0: */ void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci) { - int i; + struct csrow_info *csrow; + int i, j; debugf0("%s()\n", __func__); /* remove all csrow kobjects */ debugf4("%s() unregister this mci kobj\n", __func__); for (i = 0; i < mci->nr_csrows; i++) { - if (mci->csrows[i].nr_pages > 0) { + int nr_pages = 0; + + csrow = &mci->csrows[i]; + for (j = 0; j < csrow->nr_channels; j++) + nr_pages += csrow->channels[j].dimm->nr_pages; + if (nr_pages > 0) { debugf0("%s() unreg csrow-%d\n", __func__, i); kobject_put(&mci->csrows[i].kobj); } diff --git a/drivers/edac/i3000_edac.c b/drivers/edac/i3000_edac.c index 8fe60ee37826..719ccbed7435 100644 --- a/drivers/edac/i3000_edac.c +++ b/drivers/edac/i3000_edac.c @@ -306,7 +306,7 @@ static int i3000_probe1(struct pci_dev *pdev, int dev_idx) int rc; int i, j; struct mem_ctl_info *mci = NULL; - unsigned long last_cumul_size; + unsigned long last_cumul_size, nr_pages; int interleaved, nr_channels; unsigned char dra[I3000_RANKS / 2], drb[I3000_RANKS]; unsigned char *c0dra = dra, *c1dra = &dra[I3000_RANKS_PER_CHANNEL / 2]; @@ -391,11 +391,13 @@ static int i3000_probe1(struct pci_dev *pdev, int dev_idx) csrow->first_page = last_cumul_size; csrow->last_page = cumul_size - 1; - csrow->nr_pages = cumul_size - last_cumul_size; + nr_pages = cumul_size - last_cumul_size; last_cumul_size = cumul_size; for (j = 0; j < nr_channels; j++) { struct dimm_info *dimm = csrow->channels[j].dimm; + + dimm->nr_pages = nr_pages / nr_channels; dimm->grain = I3000_DEAP_GRAIN; dimm->mtype = MEM_DDR2; dimm->dtype = DEV_UNKNOWN; diff --git a/drivers/edac/i3200_edac.c b/drivers/edac/i3200_edac.c index 93c4d5a6a623..3b3622209f3e 100644 --- a/drivers/edac/i3200_edac.c +++ b/drivers/edac/i3200_edac.c @@ -376,11 +376,10 @@ static int i3200_probe1(struct pci_dev *pdev, int dev_idx) if (nr_pages == 0) continue; - csrow->nr_pages = nr_pages; - for (j = 0; j < nr_channels; j++) { struct dimm_info *dimm = csrow->channels[j].dimm; + dimm->nr_pages = nr_pages / nr_channels; dimm->grain = nr_pages << PAGE_SHIFT; dimm->mtype = MEM_DDR2; dimm->dtype = DEV_UNKNOWN; diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c index 26b40556958e..f3a1a3e1e4e1 100644 --- a/drivers/edac/i5000_edac.c +++ b/drivers/edac/i5000_edac.c @@ -1236,6 +1236,7 @@ static int i5000_init_csrows(struct mem_ctl_info *mci) { struct i5000_pvt *pvt; struct csrow_info *p_csrow; + struct dimm_info *dimm; int empty, channel_count; int max_csrows; int mtr, mtr1; @@ -1265,21 +1266,22 @@ static int i5000_init_csrows(struct mem_ctl_info *mci) csrow_megs = 0; for (channel = 0; channel < pvt->maxch; channel++) { + dimm = p_csrow->channels[channel].dimm; csrow_megs += pvt->dimm_info[csrow][channel].megabytes; - p_csrow->channels[channel].dimm->grain = 8; + dimm->grain = 8; /* Assume DDR2 for now */ - p_csrow->channels[channel].dimm->mtype = MEM_FB_DDR2; + dimm->mtype = MEM_FB_DDR2; /* ask what device type on this row */ if (MTR_DRAM_WIDTH(mtr)) - p_csrow->channels[channel].dimm->dtype = DEV_X8; + dimm->dtype = DEV_X8; else - p_csrow->channels[channel].dimm->dtype = DEV_X4; + dimm->dtype = DEV_X4; - p_csrow->channels[channel].dimm->edac_mode = EDAC_S8ECD8ED; + dimm->edac_mode = EDAC_S8ECD8ED; + dimm->nr_pages = (csrow_megs << 8) / pvt->maxch; } - p_csrow->nr_pages = csrow_megs << 8; empty = 0; } diff --git a/drivers/edac/i5100_edac.c b/drivers/edac/i5100_edac.c index 5338c7968f78..c08e94064ef6 100644 --- a/drivers/edac/i5100_edac.c +++ b/drivers/edac/i5100_edac.c @@ -859,7 +859,6 @@ static void __devinit i5100_init_csrows(struct mem_ctl_info *mci) * FIXME: these two are totally bogus -- I don't see how to * map them correctly to this structure... */ - mci->csrows[i].nr_pages = npages; mci->csrows[i].csrow_idx = i; mci->csrows[i].mci = mci; mci->csrows[i].nr_channels = 1; @@ -867,14 +866,19 @@ static void __devinit i5100_init_csrows(struct mem_ctl_info *mci) 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)); + dimm->nr_pages = npages; + if (npages) { + total_pages += npages; + + 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)); + } } } diff --git a/drivers/edac/i5400_edac.c b/drivers/edac/i5400_edac.c index 6f85dcb34019..6543f4a8367b 100644 --- a/drivers/edac/i5400_edac.c +++ b/drivers/edac/i5400_edac.c @@ -1156,7 +1156,7 @@ static int i5400_init_csrows(struct mem_ctl_info *mci) int empty, channel_count; int max_csrows; int mtr; - int csrow_megs; + int size_mb; int channel; int csrow; struct dimm_info *dimm; @@ -1171,8 +1171,6 @@ static int i5400_init_csrows(struct mem_ctl_info *mci) for (csrow = 0; csrow < max_csrows; csrow++) { p_csrow = &mci->csrows[csrow]; - p_csrow->csrow_idx = csrow; - /* use branch 0 for the basis */ mtr = determine_mtr(pvt, csrow, 0); @@ -1180,12 +1178,11 @@ static int i5400_init_csrows(struct mem_ctl_info *mci) if (!MTR_DIMMS_PRESENT(mtr)) continue; - csrow_megs = 0; for (channel = 0; channel < pvt->maxch; channel++) { - csrow_megs += pvt->dimm_info[csrow][channel].megabytes; + size_mb = pvt->dimm_info[csrow][channel].megabytes; - p_csrow->nr_pages = csrow_megs << 8; dimm = p_csrow->channels[channel].dimm; + dimm->nr_pages = size_mb << 8; dimm->grain = 8; dimm->dtype = MTR_DRAM_WIDTH(mtr) ? DEV_X8 : DEV_X4; dimm->mtype = MEM_RDDR2; diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c index d4153d6cfe30..d6f3a2d0f70a 100644 --- a/drivers/edac/i7300_edac.c +++ b/drivers/edac/i7300_edac.c @@ -617,9 +617,7 @@ static void i7300_enable_error_reporting(struct mem_ctl_info *mci) 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) + struct dimm_info *dimm) { int mtr, ans, addrBits, channel; @@ -651,7 +649,6 @@ static int decode_mtr(struct i7300_pvt *pvt, addrBits -= 3; /* 8 bits per bytes */ dinfo->megabytes = 1 << addrBits; - *nr_pages = dinfo->megabytes << 8; debugf2("\t\tWIDTH: x%d\n", MTR_DRAM_WIDTH(mtr)); @@ -664,8 +661,6 @@ 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->csrow_idx = slot; - /* * The type of error detection actually depends of the * mode of operation. When it is just one single memory chip, at @@ -675,6 +670,7 @@ static int decode_mtr(struct i7300_pvt *pvt, * See datasheet Sections 7.3.6 to 7.3.8 */ + dimm->nr_pages = MiB_TO_PAGES(dinfo->megabytes); dimm->grain = 8; dimm->mtype = MEM_FB_DDR2; if (IS_SINGLE_MODE(pvt->mc_settings_a)) { @@ -774,11 +770,9 @@ static int i7300_init_csrows(struct mem_ctl_info *mci) { struct i7300_pvt *pvt; struct i7300_dimm_info *dinfo; - struct csrow_info *p_csrow; int rc = -ENODEV; int mtr; int ch, branch, slot, channel; - u32 nr_pages; struct dimm_info *dimm; pvt = mci->pvt_info; @@ -804,7 +798,6 @@ static int i7300_init_csrows(struct mem_ctl_info *mci) } /* Get the set of MTR[0-7] regs by each branch */ - nr_pages = 0; for (slot = 0; slot < MAX_SLOTS; slot++) { int where = mtr_regs[slot]; for (branch = 0; branch < MAX_BRANCHES; branch++) { @@ -815,21 +808,18 @@ static int i7300_init_csrows(struct mem_ctl_info *mci) int channel = to_channel(ch, branch); dinfo = &pvt->dimm_info[slot][channel]; - p_csrow = &mci->csrows[slot]; - dimm = p_csrow->channels[branch * MAX_CH_PER_BRANCH + ch].dimm; + dimm = mci->csrows[slot].channels[branch * MAX_CH_PER_BRANCH + ch].dimm; mtr = decode_mtr(pvt, slot, ch, branch, - dinfo, p_csrow, dimm, - &nr_pages); + dinfo, dimm); + /* if no DIMMS on this row, continue */ if (!MTR_DIMMS_PRESENT(mtr)) continue; - /* Update per_csrow memory count */ - p_csrow->nr_pages += nr_pages; - rc = 0; + } } } diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index 76c957c525fb..0e3cc34bcc22 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c @@ -715,17 +715,12 @@ static int get_dimm_config(struct mem_ctl_info *mci) npages = MiB_TO_PAGES(size); csr = &mci->csrows[csrow]; - csr->nr_pages = npages; - - csr->csrow_idx = csrow; - csr->nr_channels = 1; - - csr->channels[0].chan_idx = i; - csr->channels[0].ce_count = 0; pvt->csrow_map[i][j] = csrow; dimm = csr->channels[0].dimm; + dimm->nr_pages = npages; + switch (banks) { case 4: dimm->dtype = DEV_X4; @@ -746,6 +741,7 @@ static int get_dimm_config(struct mem_ctl_info *mci) dimm->grain = 8; dimm->edac_mode = mode; dimm->mtype = mtype; + csrow++; } pci_read_config_dword(pdev, MC_SAG_CH_0, &value[0]); diff --git a/drivers/edac/i82443bxgx_edac.c b/drivers/edac/i82443bxgx_edac.c index 0b98dd3408b9..02b252acd999 100644 --- a/drivers/edac/i82443bxgx_edac.c +++ b/drivers/edac/i82443bxgx_edac.c @@ -220,7 +220,7 @@ static void i82443bxgx_init_csrows(struct mem_ctl_info *mci, row_base = row_high_limit_last; csrow->first_page = row_base >> PAGE_SHIFT; csrow->last_page = (row_high_limit >> PAGE_SHIFT) - 1; - csrow->nr_pages = csrow->last_page - csrow->first_page + 1; + dimm->nr_pages = csrow->last_page - csrow->first_page + 1; /* EAP reports in 4kilobyte granularity [61] */ dimm->grain = 1 << 12; dimm->mtype = mtype; diff --git a/drivers/edac/i82860_edac.c b/drivers/edac/i82860_edac.c index 3eb77845cfca..8485bbf4379f 100644 --- a/drivers/edac/i82860_edac.c +++ b/drivers/edac/i82860_edac.c @@ -167,7 +167,7 @@ static void i82860_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev) csrow->first_page = last_cumul_size; csrow->last_page = cumul_size - 1; - csrow->nr_pages = cumul_size - last_cumul_size; + dimm->nr_pages = cumul_size - last_cumul_size; last_cumul_size = cumul_size; dimm->grain = 1 << 12; /* I82860_EAP has 4KiB reolution */ dimm->mtype = MEM_RMBS; diff --git a/drivers/edac/i82875p_edac.c b/drivers/edac/i82875p_edac.c index eac574285da8..e16281b41f3b 100644 --- a/drivers/edac/i82875p_edac.c +++ b/drivers/edac/i82875p_edac.c @@ -347,7 +347,7 @@ static void i82875p_init_csrows(struct mem_ctl_info *mci, unsigned long last_cumul_size; u8 value; u32 drc_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */ - u32 cumul_size; + u32 cumul_size, nr_pages; int index, j; drc_ddim = (drc >> 18) & 0x1; @@ -371,12 +371,13 @@ static void i82875p_init_csrows(struct mem_ctl_info *mci, csrow->first_page = last_cumul_size; csrow->last_page = cumul_size - 1; - csrow->nr_pages = cumul_size - last_cumul_size; + nr_pages = cumul_size - last_cumul_size; last_cumul_size = cumul_size; for (j = 0; j < nr_chans; j++) { dimm = csrow->channels[j].dimm; + dimm->nr_pages = nr_pages / nr_chans; dimm->grain = 1 << 12; /* I82875P_EAP has 4KiB reolution */ dimm->mtype = MEM_DDR; dimm->dtype = DEV_UNKNOWN; diff --git a/drivers/edac/i82975x_edac.c b/drivers/edac/i82975x_edac.c index b8ec8719e2f5..014a9483fccc 100644 --- a/drivers/edac/i82975x_edac.c +++ b/drivers/edac/i82975x_edac.c @@ -370,7 +370,7 @@ static void i82975x_init_csrows(struct mem_ctl_info *mci, struct csrow_info *csrow; unsigned long last_cumul_size; u8 value; - u32 cumul_size; + u32 cumul_size, nr_pages; int index, chan; struct dimm_info *dimm; enum dev_type dtype; @@ -402,6 +402,7 @@ static void i82975x_init_csrows(struct mem_ctl_info *mci, debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index, cumul_size); + nr_pages = cumul_size - last_cumul_size; /* * Initialise dram labels * index values: @@ -411,6 +412,11 @@ static void i82975x_init_csrows(struct mem_ctl_info *mci, dtype = i82975x_dram_type(mch_window, index); for (chan = 0; chan < csrow->nr_channels; chan++) { dimm = mci->csrows[index].channels[chan].dimm; + + if (!nr_pages) + continue; + + dimm->nr_pages = nr_pages / csrow->nr_channels; strncpy(csrow->channels[chan].dimm->label, labels[(index >> 1) + (chan * 2)], EDAC_MC_LABEL_LEN); @@ -420,12 +426,11 @@ static void i82975x_init_csrows(struct mem_ctl_info *mci, dimm->edac_mode = EDAC_SECDED; /* only supported */ } - if (cumul_size == last_cumul_size) + if (!nr_pages) continue; /* not populated */ 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; } } diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c index fb92916d0872..c1d9e158972c 100644 --- a/drivers/edac/mpc85xx_edac.c +++ b/drivers/edac/mpc85xx_edac.c @@ -947,7 +947,8 @@ static void __devinit mpc85xx_init_csrows(struct mem_ctl_info *mci) csrow->first_page = start; csrow->last_page = end; - csrow->nr_pages = end + 1 - start; + + dimm->nr_pages = end + 1 - start; dimm->grain = 8; dimm->mtype = mtype; dimm->dtype = DEV_UNKNOWN; diff --git a/drivers/edac/mv64x60_edac.c b/drivers/edac/mv64x60_edac.c index d2e3c39ede9f..281e24528599 100644 --- a/drivers/edac/mv64x60_edac.c +++ b/drivers/edac/mv64x60_edac.c @@ -667,7 +667,8 @@ static void mv64x60_init_csrows(struct mem_ctl_info *mci, csrow = &mci->csrows[0]; dimm = csrow->channels[0].dimm; - csrow->nr_pages = pdata->total_mem >> PAGE_SHIFT; + + dimm->nr_pages = pdata->total_mem >> PAGE_SHIFT; dimm->grain = 8; dimm->mtype = (ctl & MV64X60_SDRAM_REGISTERED) ? MEM_RDDR : MEM_DDR; diff --git a/drivers/edac/pasemi_edac.c b/drivers/edac/pasemi_edac.c index 4e53270bc336..3fcefda653fd 100644 --- a/drivers/edac/pasemi_edac.c +++ b/drivers/edac/pasemi_edac.c @@ -153,20 +153,20 @@ static int pasemi_edac_init_csrows(struct mem_ctl_info *mci, switch ((rankcfg & MCDRAM_RANKCFG_TYPE_SIZE_M) >> MCDRAM_RANKCFG_TYPE_SIZE_S) { case 0: - csrow->nr_pages = 128 << (20 - PAGE_SHIFT); + dimm->nr_pages = 128 << (20 - PAGE_SHIFT); break; case 1: - csrow->nr_pages = 256 << (20 - PAGE_SHIFT); + dimm->nr_pages = 256 << (20 - PAGE_SHIFT); break; case 2: case 3: - csrow->nr_pages = 512 << (20 - PAGE_SHIFT); + dimm->nr_pages = 512 << (20 - PAGE_SHIFT); break; case 4: - csrow->nr_pages = 1024 << (20 - PAGE_SHIFT); + dimm->nr_pages = 1024 << (20 - PAGE_SHIFT); break; case 5: - csrow->nr_pages = 2048 << (20 - PAGE_SHIFT); + dimm->nr_pages = 2048 << (20 - PAGE_SHIFT); break; default: edac_mc_printk(mci, KERN_ERR, @@ -176,8 +176,8 @@ static int pasemi_edac_init_csrows(struct mem_ctl_info *mci, } csrow->first_page = last_page_in_mmc; - csrow->last_page = csrow->first_page + csrow->nr_pages - 1; - last_page_in_mmc += csrow->nr_pages; + csrow->last_page = csrow->first_page + dimm->nr_pages - 1; + last_page_in_mmc += dimm->nr_pages; csrow->page_mask = 0; dimm->grain = PASEMI_EDAC_ERROR_GRAIN; dimm->mtype = MEM_DDR; diff --git a/drivers/edac/ppc4xx_edac.c b/drivers/edac/ppc4xx_edac.c index ec5e529e33f6..95cfc0f8d46d 100644 --- a/drivers/edac/ppc4xx_edac.c +++ b/drivers/edac/ppc4xx_edac.c @@ -896,7 +896,7 @@ ppc4xx_edac_init_csrows(struct mem_ctl_info *mci, u32 mcopt1) enum dev_type dtype; enum edac_type edac_mode; int row, j; - u32 mbxcf, size; + u32 mbxcf, size, nr_pages; /* Establish the memory type and width */ @@ -947,7 +947,7 @@ ppc4xx_edac_init_csrows(struct mem_ctl_info *mci, u32 mcopt1) case SDRAM_MBCF_SZ_2GB: case SDRAM_MBCF_SZ_4GB: case SDRAM_MBCF_SZ_8GB: - csi->nr_pages = SDRAM_MBCF_SZ_TO_PAGES(size); + nr_pages = SDRAM_MBCF_SZ_TO_PAGES(size); break; default: ppc4xx_edac_mc_printk(KERN_ERR, mci, @@ -973,6 +973,7 @@ ppc4xx_edac_init_csrows(struct mem_ctl_info *mci, u32 mcopt1) for (j = 0; j < csi->nr_channels; j++) { struct dimm_info *dimm = csi->channels[j].dimm; + dimm->nr_pages = nr_pages / csi->nr_channels; dimm->grain = 1; dimm->mtype = mtype; diff --git a/drivers/edac/r82600_edac.c b/drivers/edac/r82600_edac.c index 70b0dfa81db4..c41b375e1f38 100644 --- a/drivers/edac/r82600_edac.c +++ b/drivers/edac/r82600_edac.c @@ -249,7 +249,8 @@ static void r82600_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev, csrow->first_page = row_base >> PAGE_SHIFT; csrow->last_page = (row_high_limit >> PAGE_SHIFT) - 1; - csrow->nr_pages = csrow->last_page - csrow->first_page + 1; + + dimm->nr_pages = csrow->last_page - csrow->first_page + 1; /* Error address is top 19 bits - so granularity is * * 14 bits */ dimm->grain = 1 << 14; diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index d5892c052bf4..2ce9bf5e354b 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c @@ -561,7 +561,6 @@ static int get_dimm_config(struct mem_ctl_info *mci) u32 reg; enum edac_type mode; enum mem_type mtype; - struct dimm_info *dimm; pci_read_config_dword(pvt->pci_br, SAD_TARGET, ®); pvt->sbridge_dev->source_id = SOURCE_ID(reg); @@ -613,11 +612,11 @@ static int get_dimm_config(struct mem_ctl_info *mci) /* On all supported DDR3 DIMM types, there are 8 banks available */ banks = 8; - dimm = mci->dimms; for (i = 0; i < NUM_CHANNELS; i++) { u32 mtr; for (j = 0; j < ARRAY_SIZE(mtr_regs); j++) { + struct dimm_info *dimm = &mci->dimms[j]; pci_read_config_dword(pvt->pci_tad[i], mtr_regs[j], &mtr); debugf4("Channel #%d MTR%d = %x\n", i, j, mtr); @@ -642,15 +641,12 @@ static int get_dimm_config(struct mem_ctl_info *mci) * csrows. */ csr = &mci->csrows[csrow]; - csr->nr_pages = npages; - csr->csrow_idx = csrow; - csr->nr_channels = 1; - csr->channels[0].chan_idx = i; pvt->csrow_map[i][j] = csrow; last_page += npages; csrow++; csr->channels[0].dimm = dimm; + dimm->nr_pages = npages; dimm->grain = 32; dimm->dtype = (banks == 8) ? DEV_X8 : DEV_X4; dimm->mtype = mtype; diff --git a/drivers/edac/tile_edac.c b/drivers/edac/tile_edac.c index 54067c4b0cc1..054c9bb3a5dc 100644 --- a/drivers/edac/tile_edac.c +++ b/drivers/edac/tile_edac.c @@ -110,7 +110,7 @@ static int __devinit tile_edac_init_csrows(struct mem_ctl_info *mci) return -1; } - csrow->nr_pages = mem_info.mem_size >> PAGE_SHIFT; + dimm->nr_pages = mem_info.mem_size >> PAGE_SHIFT; dimm->grain = TILE_EDAC_ERROR_GRAIN; dimm->dtype = DEV_UNKNOWN; diff --git a/drivers/edac/x38_edac.c b/drivers/edac/x38_edac.c index bc7f880a4eed..e3247997aa00 100644 --- a/drivers/edac/x38_edac.c +++ b/drivers/edac/x38_edac.c @@ -373,10 +373,10 @@ static int x38_probe1(struct pci_dev *pdev, int dev_idx) if (nr_pages == 0) continue; - csrow->nr_pages = nr_pages; - for (j = 0; j < x38_channel_num; j++) { struct dimm_info *dimm = csrow->channels[j].dimm; + + dimm->nr_pages = nr_pages / x38_channel_num; dimm->grain = nr_pages << PAGE_SHIFT; dimm->mtype = MEM_DDR2; dimm->dtype = DEV_UNKNOWN; diff --git a/include/linux/edac.h b/include/linux/edac.h index 87aa07d2ee28..67717cab1313 100644 --- a/include/linux/edac.h +++ b/include/linux/edac.h @@ -324,6 +324,8 @@ struct dimm_info { enum mem_type mtype; /* memory dimm type */ enum edac_type edac_mode; /* EDAC mode for this dimm */ + u32 nr_pages; /* number of pages in csrow */ + u32 ce_count; /* Correctable Errors for this dimm */ }; @@ -350,12 +352,12 @@ struct rank_info { }; struct csrow_info { + /* Used only by edac_mc_find_csrow_by_page() */ unsigned long first_page; /* first page number in csrow */ unsigned long last_page; /* last page number in csrow */ - u32 nr_pages; /* number of pages in csrow */ unsigned long page_mask; /* used for interleaving - - * 0UL for non intlv - */ + * 0UL for non intlv */ + int csrow_idx; /* the chip-select row */ u32 ue_count; /* Uncorrectable Errors for this csrow */ -- cgit v1.2.3 From c36e3e77687b39073903f55461fc9417514e831e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 16 Apr 2012 15:12:22 -0300 Subject: sb_edac: convert driver to use the new edac ABI The legacy edac ABI is going to be removed. Port the driver to use and benefit from the new API functionality. Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/sb_edac.c | 159 +++++++++++++++++-------------------------------- 1 file changed, 56 insertions(+), 103 deletions(-) (limited to 'drivers/edac/sb_edac.c') diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index 2ce9bf5e354b..828647969124 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c @@ -314,8 +314,6 @@ struct sbridge_pvt { struct sbridge_info info; struct sbridge_channel channel[NUM_CHANNELS]; - int csrow_map[NUM_CHANNELS][MAX_DIMMS]; - /* Memory type detection */ bool is_mirrored, is_lockstep, is_close_pg; @@ -487,29 +485,14 @@ static struct pci_dev *get_pdev_slot_func(u8 bus, unsigned slot, } /** - * sbridge_get_active_channels() - gets the number of channels and csrows + * check_if_ecc_is_active() - Checks if ECC is active * bus: Device bus - * @channels: Number of channels that will be returned - * @csrows: Number of csrows found - * - * Since EDAC core needs to know in advance the number of available channels - * and csrows, in order to allocate memory for csrows/channels, it is needed - * to run two similar steps. At the first step, implemented on this function, - * it checks the number of csrows/channels present at one socket, identified - * by the associated PCI bus. - * this is used in order to properly allocate the size of mci components. - * Note: one csrow is one dimm. */ -static int sbridge_get_active_channels(const u8 bus, unsigned *channels, - unsigned *csrows) +static int check_if_ecc_is_active(const u8 bus) { struct pci_dev *pdev = NULL; - int i, j; u32 mcmtr; - *channels = 0; - *csrows = 0; - pdev = get_pdev_slot_func(bus, 15, 0); if (!pdev) { sbridge_printk(KERN_ERR, "Couldn't find PCI device " @@ -523,41 +506,14 @@ static int sbridge_get_active_channels(const u8 bus, unsigned *channels, sbridge_printk(KERN_ERR, "ECC is disabled. Aborting\n"); return -ENODEV; } - - for (i = 0; i < NUM_CHANNELS; i++) { - u32 mtr; - - /* Device 15 functions 2 - 5 */ - pdev = get_pdev_slot_func(bus, 15, 2 + i); - if (!pdev) { - sbridge_printk(KERN_ERR, "Couldn't find PCI device " - "%2x.%02d.%d!!!\n", - bus, 15, 2 + i); - return -ENODEV; - } - (*channels)++; - - for (j = 0; j < ARRAY_SIZE(mtr_regs); j++) { - pci_read_config_dword(pdev, mtr_regs[j], &mtr); - debugf1("Bus#%02x channel #%d MTR%d = %x\n", bus, i, j, mtr); - if (IS_DIMM_PRESENT(mtr)) - (*csrows)++; - } - } - - debugf0("Number of active channels: %d, number of active dimms: %d\n", - *channels, *csrows); - return 0; } static int get_dimm_config(struct mem_ctl_info *mci) { struct sbridge_pvt *pvt = mci->pvt_info; - struct csrow_info *csr; + struct dimm_info *dimm; int i, j, banks, ranks, rows, cols, size, npages; - int csrow = 0; - unsigned long last_page = 0; u32 reg; enum edac_type mode; enum mem_type mtype; @@ -616,7 +572,8 @@ static int get_dimm_config(struct mem_ctl_info *mci) u32 mtr; for (j = 0; j < ARRAY_SIZE(mtr_regs); j++) { - struct dimm_info *dimm = &mci->dimms[j]; + dimm = EDAC_DIMM_PTR(mci->layers, mci->dimms, mci->n_layers, + i, j, 0); pci_read_config_dword(pvt->pci_tad[i], mtr_regs[j], &mtr); debugf4("Channel #%d MTR%d = %x\n", i, j, mtr); @@ -636,16 +593,6 @@ static int get_dimm_config(struct mem_ctl_info *mci) size, npages, banks, ranks, rows, cols); - /* - * Fake stuff. This controller doesn't see - * csrows. - */ - csr = &mci->csrows[csrow]; - pvt->csrow_map[i][j] = csrow; - last_page += npages; - csrow++; - - csr->channels[0].dimm = dimm; dimm->nr_pages = npages; dimm->grain = 32; dimm->dtype = (banks == 8) ? DEV_X8 : DEV_X4; @@ -841,11 +788,10 @@ static int get_memory_error_data(struct mem_ctl_info *mci, u8 *socket, long *channel_mask, u8 *rank, - char *area_type) + char *area_type, char *msg) { struct mem_ctl_info *new_mci; struct sbridge_pvt *pvt = mci->pvt_info; - char msg[256]; int n_rir, n_sads, n_tads, sad_way, sck_xch; int sad_interl, idx, base_ch; int interleave_mode; @@ -867,12 +813,10 @@ static int get_memory_error_data(struct mem_ctl_info *mci, */ if ((addr > (u64) pvt->tolm) && (addr < (1LL << 32))) { sprintf(msg, "Error at TOLM area, on addr 0x%08Lx", addr); - edac_mc_handle_ce_no_info(mci, msg); return -EINVAL; } if (addr >= (u64)pvt->tohm) { sprintf(msg, "Error at MMIOH area, on addr 0x%016Lx", addr); - edac_mc_handle_ce_no_info(mci, msg); return -EINVAL; } @@ -889,7 +833,6 @@ static int get_memory_error_data(struct mem_ctl_info *mci, limit = SAD_LIMIT(reg); if (limit <= prv) { sprintf(msg, "Can't discover the memory socket"); - edac_mc_handle_ce_no_info(mci, msg); return -EINVAL; } if (addr <= limit) @@ -898,7 +841,6 @@ static int get_memory_error_data(struct mem_ctl_info *mci, } if (n_sads == MAX_SAD) { sprintf(msg, "Can't discover the memory socket"); - edac_mc_handle_ce_no_info(mci, msg); return -EINVAL; } area_type = get_dram_attr(reg); @@ -939,7 +881,6 @@ static int get_memory_error_data(struct mem_ctl_info *mci, break; default: sprintf(msg, "Can't discover socket interleave"); - edac_mc_handle_ce_no_info(mci, msg); return -EINVAL; } *socket = sad_interleave[idx]; @@ -954,7 +895,6 @@ static int get_memory_error_data(struct mem_ctl_info *mci, if (!new_mci) { sprintf(msg, "Struct for socket #%u wasn't initialized", *socket); - edac_mc_handle_ce_no_info(mci, msg); return -EINVAL; } mci = new_mci; @@ -970,7 +910,6 @@ static int get_memory_error_data(struct mem_ctl_info *mci, limit = TAD_LIMIT(reg); if (limit <= prv) { sprintf(msg, "Can't discover the memory channel"); - edac_mc_handle_ce_no_info(mci, msg); return -EINVAL; } if (addr <= limit) @@ -1010,7 +949,6 @@ static int get_memory_error_data(struct mem_ctl_info *mci, break; default: sprintf(msg, "Can't discover the TAD target"); - edac_mc_handle_ce_no_info(mci, msg); return -EINVAL; } *channel_mask = 1 << base_ch; @@ -1024,7 +962,6 @@ static int get_memory_error_data(struct mem_ctl_info *mci, break; default: sprintf(msg, "Invalid mirror set. Can't decode addr"); - edac_mc_handle_ce_no_info(mci, msg); return -EINVAL; } } else @@ -1052,7 +989,6 @@ static int get_memory_error_data(struct mem_ctl_info *mci, if (offset > addr) { sprintf(msg, "Can't calculate ch addr: TAD offset 0x%08Lx is too high for addr 0x%08Lx!", offset, addr); - edac_mc_handle_ce_no_info(mci, msg); return -EINVAL; } addr -= offset; @@ -1092,7 +1028,6 @@ static int get_memory_error_data(struct mem_ctl_info *mci, if (n_rir == MAX_RIR_RANGES) { sprintf(msg, "Can't discover the memory rank for ch addr 0x%08Lx", ch_addr); - edac_mc_handle_ce_no_info(mci, msg); return -EINVAL; } rir_way = RIR_WAY(reg); @@ -1406,7 +1341,8 @@ static void sbridge_mce_output_error(struct mem_ctl_info *mci, { struct mem_ctl_info *new_mci; struct sbridge_pvt *pvt = mci->pvt_info; - char *type, *optype, *msg, *recoverable_msg; + enum hw_event_mc_err_type tp_event; + char *type, *optype, msg[256], *recoverable_msg; bool ripv = GET_BITFIELD(m->mcgstatus, 0, 0); bool overflow = GET_BITFIELD(m->status, 62, 62); bool uncorrected_error = GET_BITFIELD(m->status, 61, 61); @@ -1418,13 +1354,21 @@ static void sbridge_mce_output_error(struct mem_ctl_info *mci, u32 optypenum = GET_BITFIELD(m->status, 4, 6); long channel_mask, first_channel; u8 rank, socket; - int csrow, rc, dimm; + int rc, dimm; char *area_type = "Unknown"; - if (ripv) - type = "NON_FATAL"; - else - type = "FATAL"; + if (uncorrected_error) { + if (ripv) { + type = "FATAL"; + tp_event = HW_EVENT_ERR_FATAL; + } else { + type = "NON_FATAL"; + tp_event = HW_EVENT_ERR_UNCORRECTED; + } + } else { + type = "CORRECTED"; + tp_event = HW_EVENT_ERR_CORRECTED; + } /* * According with Table 15-9 of the Intel Archictecture spec vol 3A, @@ -1442,19 +1386,19 @@ static void sbridge_mce_output_error(struct mem_ctl_info *mci, } else { switch (optypenum) { case 0: - optype = "generic undef request"; + optype = "generic undef request error"; break; case 1: - optype = "memory read"; + optype = "memory read error"; break; case 2: - optype = "memory write"; + optype = "memory write error"; break; case 3: - optype = "addr/cmd"; + optype = "addr/cmd error"; break; case 4: - optype = "memory scrubbing"; + optype = "memory scrubbing error"; break; default: optype = "reserved"; @@ -1463,13 +1407,13 @@ static void sbridge_mce_output_error(struct mem_ctl_info *mci, } rc = get_memory_error_data(mci, m->addr, &socket, - &channel_mask, &rank, area_type); + &channel_mask, &rank, area_type, msg); if (rc < 0) - return; + goto err_parsing; new_mci = get_mci_for_node_id(socket); if (!new_mci) { - edac_mc_handle_ce_no_info(mci, "Error: socket got corrupted!"); - return; + strcpy(msg, "Error: socket got corrupted!"); + goto err_parsing; } mci = new_mci; pvt = mci->pvt_info; @@ -1483,8 +1427,6 @@ static void sbridge_mce_output_error(struct mem_ctl_info *mci, else dimm = 2; - csrow = pvt->csrow_map[first_channel][dimm]; - if (uncorrected_error && recoverable) recoverable_msg = " recoverable"; else @@ -1495,18 +1437,14 @@ static void sbridge_mce_output_error(struct mem_ctl_info *mci, * Probably, we can just discard it, as the channel information * comes from the get_memory_error_data() address decoding */ - msg = kasprintf(GFP_ATOMIC, - "%d %s error(s): %s on %s area %s%s: cpu=%d Err=%04x:%04x (ch=%d), " - "addr = 0x%08llx => socket=%d, Channel=%ld(mask=%ld), rank=%d\n", + snprintf(msg, sizeof(msg), + "%d error(s)%s: %s%s: cpu=%d Err=%04x:%04x addr = 0x%08llx socket=%d Channel=%ld(mask=%ld), rank=%d\n", core_err_cnt, + overflow ? " OVERFLOW" : "", area_type, - optype, - type, recoverable_msg, - overflow ? "OVERFLOW" : "", m->cpu, mscod, errcode, - channel, /* 1111b means not specified */ (long long) m->addr, socket, first_channel, /* This is the real channel on SB */ @@ -1515,13 +1453,19 @@ static void sbridge_mce_output_error(struct mem_ctl_info *mci, debugf0("%s", msg); + /* FIXME: need support for channel mask */ + /* Call the helper to output message */ - if (uncorrected_error) - edac_mc_handle_fbd_ue(mci, csrow, 0, 0, msg); - else - edac_mc_handle_fbd_ce(mci, csrow, 0, msg); + edac_mc_handle_error(tp_event, mci, + m->addr >> PAGE_SHIFT, m->addr & ~PAGE_MASK, 0, + channel, dimm, -1, + optype, msg, m); + return; +err_parsing: + edac_mc_handle_error(tp_event, mci, 0, 0, 0, + -1, -1, -1, + msg, "", m); - kfree(msg); } /* @@ -1680,16 +1624,25 @@ static void sbridge_unregister_mci(struct sbridge_dev *sbridge_dev) static int sbridge_register_mci(struct sbridge_dev *sbridge_dev) { struct mem_ctl_info *mci; + struct edac_mc_layer layers[2]; struct sbridge_pvt *pvt; - int rc, channels, csrows; + int rc; /* Check the number of active and not disabled channels */ - rc = sbridge_get_active_channels(sbridge_dev->bus, &channels, &csrows); + rc = check_if_ecc_is_active(sbridge_dev->bus); if (unlikely(rc < 0)) return rc; /* allocate a new MC control structure */ - mci = edac_mc_alloc(sizeof(*pvt), csrows, channels, sbridge_dev->mc); + layers[0].type = EDAC_MC_LAYER_CHANNEL; + layers[0].size = NUM_CHANNELS; + layers[0].is_virt_csrow = false; + layers[1].type = EDAC_MC_LAYER_SLOT; + layers[1].size = MAX_DIMMS; + layers[1].is_virt_csrow = true; + mci = new_edac_mc_alloc(sbridge_dev->mc, ARRAY_SIZE(layers), layers, + sizeof(*pvt)); + if (unlikely(!mci)) return -ENOMEM; -- cgit v1.2.3 From ca0907b9e413bb1d1f3ea123b663535b74928846 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 2 May 2012 14:37:00 -0300 Subject: edac: Remove the legacy EDAC ABI Now that all drivers got converted to use the new ABI, we can drop the old one. Acked-by: Chris Metcalf Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/amd64_edac.c | 2 +- drivers/edac/amd76x_edac.c | 2 +- drivers/edac/cell_edac.c | 2 +- drivers/edac/cpc925_edac.c | 2 +- drivers/edac/e752x_edac.c | 3 +- drivers/edac/e7xxx_edac.c | 2 +- drivers/edac/edac_core.h | 76 +----------------------------------------- drivers/edac/edac_mc.c | 52 ++++------------------------- drivers/edac/i3000_edac.c | 2 +- drivers/edac/i3200_edac.c | 2 +- drivers/edac/i5000_edac.c | 3 +- drivers/edac/i5100_edac.c | 2 +- drivers/edac/i5400_edac.c | 3 +- drivers/edac/i7300_edac.c | 3 +- drivers/edac/i7core_edac.c | 2 +- drivers/edac/i82443bxgx_edac.c | 2 +- drivers/edac/i82860_edac.c | 2 +- drivers/edac/i82875p_edac.c | 2 +- drivers/edac/i82975x_edac.c | 2 +- drivers/edac/mpc85xx_edac.c | 3 +- drivers/edac/mv64x60_edac.c | 2 +- drivers/edac/pasemi_edac.c | 2 +- drivers/edac/ppc4xx_edac.c | 2 +- drivers/edac/r82600_edac.c | 2 +- drivers/edac/sb_edac.c | 2 +- drivers/edac/tile_edac.c | 2 +- drivers/edac/x38_edac.c | 2 +- 27 files changed, 32 insertions(+), 151 deletions(-) (limited to 'drivers/edac/sb_edac.c') diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index c431544519b1..7be9b7288e90 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -2596,7 +2596,7 @@ static int amd64_init_one_instance(struct pci_dev *F2) layers[1].type = EDAC_MC_LAYER_CHANNEL; layers[1].size = pvt->channel_count; layers[1].is_virt_csrow = false; - mci = new_edac_mc_alloc(nid, ARRAY_SIZE(layers), layers, 0); + mci = edac_mc_alloc(nid, ARRAY_SIZE(layers), layers, 0); if (!mci) goto err_siblings; diff --git a/drivers/edac/amd76x_edac.c b/drivers/edac/amd76x_edac.c index 69f2b2ebb263..9774d443fa57 100644 --- a/drivers/edac/amd76x_edac.c +++ b/drivers/edac/amd76x_edac.c @@ -251,7 +251,7 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx) layers[1].type = EDAC_MC_LAYER_CHANNEL; layers[1].size = 1; layers[1].is_virt_csrow = false; - mci = new_edac_mc_alloc(0, ARRAY_SIZE(layers), layers, 0); + mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, 0); if (mci == NULL) return -ENOMEM; diff --git a/drivers/edac/cell_edac.c b/drivers/edac/cell_edac.c index 14aa17492757..69ee6aab5c71 100644 --- a/drivers/edac/cell_edac.c +++ b/drivers/edac/cell_edac.c @@ -204,7 +204,7 @@ static int __devinit cell_edac_probe(struct platform_device *pdev) layers[1].type = EDAC_MC_LAYER_CHANNEL; layers[1].size = num_chans; layers[1].is_virt_csrow = false; - mci = new_edac_mc_alloc(pdev->id, ARRAY_SIZE(layers), layers, + mci = edac_mc_alloc(pdev->id, ARRAY_SIZE(layers), layers, sizeof(struct cell_edac_priv)); if (mci == NULL) return -ENOMEM; diff --git a/drivers/edac/cpc925_edac.c b/drivers/edac/cpc925_edac.c index 2d94fa91c746..e22030a9de66 100644 --- a/drivers/edac/cpc925_edac.c +++ b/drivers/edac/cpc925_edac.c @@ -982,7 +982,7 @@ static int __devinit cpc925_probe(struct platform_device *pdev) layers[1].type = EDAC_MC_LAYER_CHANNEL; layers[1].size = nr_channels; layers[1].is_virt_csrow = false; - mci = new_edac_mc_alloc(edac_mc_idx, ARRAY_SIZE(layers), layers, + mci = edac_mc_alloc(edac_mc_idx, ARRAY_SIZE(layers), layers, sizeof(struct cpc925_mc_pdata)); if (!mci) { cpc925_printk(KERN_ERR, "No memory for mem_ctl_info\n"); diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c index aaa3bb8893c1..d28a6851bb18 100644 --- a/drivers/edac/e752x_edac.c +++ b/drivers/edac/e752x_edac.c @@ -1278,8 +1278,7 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) layers[1].type = EDAC_MC_LAYER_CHANNEL; layers[1].size = drc_chan + 1; layers[1].is_virt_csrow = false; - mci = new_edac_mc_alloc(0, ARRAY_SIZE(layers), layers, - sizeof(*pvt)); + mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, sizeof(*pvt)); if (mci == NULL) return -ENOMEM; diff --git a/drivers/edac/e7xxx_edac.c b/drivers/edac/e7xxx_edac.c index d4cfc24b2f8d..9a9c1a546797 100644 --- a/drivers/edac/e7xxx_edac.c +++ b/drivers/edac/e7xxx_edac.c @@ -447,7 +447,7 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) layers[1].type = EDAC_MC_LAYER_CHANNEL; layers[1].size = drc_chan + 1; layers[1].is_virt_csrow = false; - mci = new_edac_mc_alloc(0, ARRAY_SIZE(layers), layers, sizeof(*pvt)); + mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, sizeof(*pvt)); if (mci == NULL) return -ENOMEM; diff --git a/drivers/edac/edac_core.h b/drivers/edac/edac_core.h index 1286c5e1bdc0..f06ce9ab692c 100644 --- a/drivers/edac/edac_core.h +++ b/drivers/edac/edac_core.h @@ -447,9 +447,7 @@ static inline void pci_write_bits32(struct pci_dev *pdev, int offset, #endif /* CONFIG_PCI */ -struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows, - unsigned nr_chans, int edac_index); -struct mem_ctl_info *new_edac_mc_alloc(unsigned edac_index, +struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, unsigned n_layers, struct edac_mc_layer *layers, unsigned sz_pvt); @@ -460,18 +458,6 @@ extern struct mem_ctl_info *find_mci_by_dev(struct device *dev); extern struct mem_ctl_info *edac_mc_del_mc(struct device *dev); extern int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci, unsigned long page); - -/* - * The no info errors are used when error overflows are reported. - * There are a limited number of error logging registers that can - * be exausted. When all registers are exhausted and an additional - * error occurs then an error overflow register records that an - * error occurred and the type of error, but doesn't have any - * further information. The ce/ue versions make for cleaner - * reporting logic and function interface - reduces conditional - * statement clutter and extra function arguments. - */ - void edac_mc_handle_error(const enum hw_event_mc_err_type type, struct mem_ctl_info *mci, const unsigned long page_frame_number, @@ -484,66 +470,6 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type, const char *other_detail, const void *mcelog); -static inline void edac_mc_handle_ce(struct mem_ctl_info *mci, - unsigned long page_frame_number, - unsigned long offset_in_page, - unsigned long syndrome, int row, int channel, - const char *msg) -{ - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, - page_frame_number, offset_in_page, syndrome, - row, channel, -1, msg, NULL, NULL); -} - -static inline void edac_mc_handle_ce_no_info(struct mem_ctl_info *mci, - const char *msg) -{ - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, - 0, 0, 0, -1, -1, -1, msg, NULL, NULL); -} - -static inline void edac_mc_handle_ue(struct mem_ctl_info *mci, - unsigned long page_frame_number, - unsigned long offset_in_page, int row, - const char *msg) -{ - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, - page_frame_number, offset_in_page, 0, - row, -1, -1, msg, NULL, NULL); -} - -static inline void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci, - const char *msg) -{ - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, - 0, 0, 0, -1, -1, -1, msg, NULL, NULL); -} - -static inline void edac_mc_handle_fbd_ue(struct mem_ctl_info *mci, - unsigned int csrow, - unsigned int channel0, - unsigned int channel1, - char *msg) -{ - /* - *FIXME: The error can also be at channel1 (e. g. at the second - * channel of the same branch). The fix is to push - * edac_mc_handle_error() call into each driver - */ - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, - 0, 0, 0, - csrow, channel0, -1, msg, NULL, NULL); -} - -static inline void edac_mc_handle_fbd_ce(struct mem_ctl_info *mci, - unsigned int csrow, - unsigned int channel, char *msg) -{ - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, - 0, 0, 0, - csrow, channel, -1, msg, NULL, NULL); -} - /* * edac_device APIs */ diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 1bd237ee4ca7..06028de5fe1b 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -195,13 +195,13 @@ void *edac_align_ptr(void **p, unsigned size, int n_elems) * on such scenarios, as grouping the multiple ranks require drivers change. * * Returns: - * NULL allocation failed - * struct mem_ctl_info pointer + * On failure: NULL + * On success: struct mem_ctl_info pointer */ -struct mem_ctl_info *new_edac_mc_alloc(unsigned mc_num, - unsigned n_layers, - struct edac_mc_layer *layers, - unsigned sz_pvt) +struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, + unsigned n_layers, + struct edac_mc_layer *layers, + unsigned sz_pvt) { struct mem_ctl_info *mci; struct edac_mc_layer *layer; @@ -370,46 +370,6 @@ struct mem_ctl_info *new_edac_mc_alloc(unsigned mc_num, */ return mci; } -EXPORT_SYMBOL_GPL(new_edac_mc_alloc); - -/** - * edac_mc_alloc: Allocate and partially fill a struct mem_ctl_info structure - * @mc_num: Memory controller number - * @n_layers: Number of layers at the MC hierarchy - * layers: Describes each layer as seen by the Memory Controller - * @size_pvt: Size of private storage needed - * - * - * FIXME: drivers handle multi-rank memories in different ways: some - * drivers map multi-ranked DIMMs as one DIMM while others - * as several DIMMs. - * - * Everything is kmalloc'ed as one big chunk - more efficient. - * It can only be used if all structures have the same lifetime - otherwise - * you have to allocate and initialize your own structures. - * - * Use edac_mc_free() to free mc structures allocated by this function. - * - * Returns: - * On failure: NULL - * On success: struct mem_ctl_info pointer - */ - -struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows, - unsigned nr_chans, int mc_num) -{ - unsigned n_layers = 2; - struct edac_mc_layer layers[n_layers]; - - layers[0].type = EDAC_MC_LAYER_CHIP_SELECT; - layers[0].size = nr_csrows; - layers[0].is_virt_csrow = true; - layers[1].type = EDAC_MC_LAYER_CHANNEL; - layers[1].size = nr_chans; - layers[1].is_virt_csrow = false; - - return new_edac_mc_alloc(mc_num, ARRAY_SIZE(layers), layers, sz_pvt); -} EXPORT_SYMBOL_GPL(edac_mc_alloc); /** diff --git a/drivers/edac/i3000_edac.c b/drivers/edac/i3000_edac.c index 195a92e1c0ae..8ad1744faacd 100644 --- a/drivers/edac/i3000_edac.c +++ b/drivers/edac/i3000_edac.c @@ -362,7 +362,7 @@ static int i3000_probe1(struct pci_dev *pdev, int dev_idx) layers[1].type = EDAC_MC_LAYER_CHANNEL; layers[1].size = nr_channels; layers[1].is_virt_csrow = false; - mci = new_edac_mc_alloc(0, ARRAY_SIZE(layers), layers, 0); + mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, 0); if (!mci) return -ENOMEM; diff --git a/drivers/edac/i3200_edac.c b/drivers/edac/i3200_edac.c index d152662ffc66..bbe43ef71823 100644 --- a/drivers/edac/i3200_edac.c +++ b/drivers/edac/i3200_edac.c @@ -347,7 +347,7 @@ static int i3200_probe1(struct pci_dev *pdev, int dev_idx) layers[1].type = EDAC_MC_LAYER_CHANNEL; layers[1].size = nr_channels; layers[1].is_virt_csrow = false; - mci = new_edac_mc_alloc(0, ARRAY_SIZE(layers), layers, + mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, sizeof(struct i3200_priv)); if (!mci) return -ENOMEM; diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c index fdbc57cb7287..82f3f4d2e7b8 100644 --- a/drivers/edac/i5000_edac.c +++ b/drivers/edac/i5000_edac.c @@ -1396,8 +1396,7 @@ static int i5000_probe1(struct pci_dev *pdev, int dev_idx) layers[2].type = EDAC_MC_LAYER_SLOT; layers[2].size = num_dimms_per_channel; layers[2].is_virt_csrow = true; - mci = new_edac_mc_alloc(0, ARRAY_SIZE(layers), layers, sizeof(*pvt)); - + mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, sizeof(*pvt)); if (mci == NULL) return -ENOMEM; diff --git a/drivers/edac/i5100_edac.c b/drivers/edac/i5100_edac.c index 691cd49aa169..d9b4921707f8 100644 --- a/drivers/edac/i5100_edac.c +++ b/drivers/edac/i5100_edac.c @@ -936,7 +936,7 @@ static int __devinit i5100_init_one(struct pci_dev *pdev, layers[1].type = EDAC_MC_LAYER_SLOT; layers[1].size = ranksperch; layers[1].is_virt_csrow = true; - mci = new_edac_mc_alloc(0, ARRAY_SIZE(layers), layers, + mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, sizeof(*priv)); if (!mci) { ret = -ENOMEM; diff --git a/drivers/edac/i5400_edac.c b/drivers/edac/i5400_edac.c index 508f369b1f6c..ff7bf8050c9c 100644 --- a/drivers/edac/i5400_edac.c +++ b/drivers/edac/i5400_edac.c @@ -1280,8 +1280,7 @@ static int i5400_probe1(struct pci_dev *pdev, int dev_idx) layers[2].type = EDAC_MC_LAYER_SLOT; layers[2].size = DIMMS_PER_CHANNEL; layers[2].is_virt_csrow = true; - mci = new_edac_mc_alloc(0, ARRAY_SIZE(layers), layers, sizeof(*pvt)); - + mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, sizeof(*pvt)); if (mci == NULL) return -ENOMEM; diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c index c2cf9771692a..97c22fd650ee 100644 --- a/drivers/edac/i7300_edac.c +++ b/drivers/edac/i7300_edac.c @@ -1051,8 +1051,7 @@ static int __devinit i7300_init_one(struct pci_dev *pdev, layers[2].type = EDAC_MC_LAYER_SLOT; layers[2].size = MAX_SLOTS; layers[2].is_virt_csrow = true; - mci = new_edac_mc_alloc(0, ARRAY_SIZE(layers), layers, sizeof(*pvt)); - + mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, sizeof(*pvt)); if (mci == NULL) return -ENOMEM; diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index bc2c04550b8b..6d89c78a9b7a 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c @@ -2147,7 +2147,7 @@ static int i7core_register_mci(struct i7core_dev *i7core_dev) layers[1].type = EDAC_MC_LAYER_SLOT; layers[1].size = MAX_DIMMS; layers[1].is_virt_csrow = true; - mci = new_edac_mc_alloc(i7core_dev->socket, ARRAY_SIZE(layers), layers, + mci = edac_mc_alloc(i7core_dev->socket, ARRAY_SIZE(layers), layers, sizeof(*pvt)); if (unlikely(!mci)) return -ENOMEM; diff --git a/drivers/edac/i82443bxgx_edac.c b/drivers/edac/i82443bxgx_edac.c index 524f9a2c5707..52072c28a8a6 100644 --- a/drivers/edac/i82443bxgx_edac.c +++ b/drivers/edac/i82443bxgx_edac.c @@ -255,7 +255,7 @@ static int i82443bxgx_edacmc_probe1(struct pci_dev *pdev, int dev_idx) layers[1].type = EDAC_MC_LAYER_CHANNEL; layers[1].size = I82443BXGX_NR_CHANS; layers[1].is_virt_csrow = false; - mci = new_edac_mc_alloc(0, ARRAY_SIZE(layers), layers, 0); + mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, 0); if (mci == NULL) return -ENOMEM; diff --git a/drivers/edac/i82860_edac.c b/drivers/edac/i82860_edac.c index 8834e4ed9802..08045059d10b 100644 --- a/drivers/edac/i82860_edac.c +++ b/drivers/edac/i82860_edac.c @@ -206,7 +206,7 @@ static int i82860_probe1(struct pci_dev *pdev, int dev_idx) layers[1].type = EDAC_MC_LAYER_SLOT; layers[1].size = 8; layers[1].is_virt_csrow = true; - mci = new_edac_mc_alloc(0, ARRAY_SIZE(layers), layers, 0); + mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, 0); if (!mci) return -ENOMEM; diff --git a/drivers/edac/i82875p_edac.c b/drivers/edac/i82875p_edac.c index 89ca38a779a3..b613e31c16e5 100644 --- a/drivers/edac/i82875p_edac.c +++ b/drivers/edac/i82875p_edac.c @@ -420,7 +420,7 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) layers[1].type = EDAC_MC_LAYER_CHANNEL; layers[1].size = nr_chans; layers[1].is_virt_csrow = false; - mci = new_edac_mc_alloc(0, ARRAY_SIZE(layers), layers, sizeof(*pvt)); + mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, sizeof(*pvt)); if (!mci) { rc = -ENOMEM; goto fail0; diff --git a/drivers/edac/i82975x_edac.c b/drivers/edac/i82975x_edac.c index 092fa5ab2e1a..9c346d7f707f 100644 --- a/drivers/edac/i82975x_edac.c +++ b/drivers/edac/i82975x_edac.c @@ -555,7 +555,7 @@ static int i82975x_probe1(struct pci_dev *pdev, int dev_idx) layers[1].type = EDAC_MC_LAYER_CHANNEL; layers[1].size = I82975X_NR_CSROWS(chans); layers[1].is_virt_csrow = false; - mci = new_edac_mc_alloc(0, ARRAY_SIZE(layers), layers, sizeof(*pvt)); + mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, sizeof(*pvt)); if (!mci) { rc = -ENOMEM; goto fail1; diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c index a15141025a94..4c402353ba98 100644 --- a/drivers/edac/mpc85xx_edac.c +++ b/drivers/edac/mpc85xx_edac.c @@ -980,8 +980,7 @@ static int __devinit mpc85xx_mc_err_probe(struct platform_device *op) layers[1].type = EDAC_MC_LAYER_CHANNEL; layers[1].size = 1; layers[1].is_virt_csrow = false; - mci = new_edac_mc_alloc(edac_mc_idx, ARRAY_SIZE(layers), layers, - sizeof(*pdata)); + mci = edac_mc_alloc(edac_mc_idx, ARRAY_SIZE(layers), sizeof(*pdata)); if (!mci) { devres_release_group(&op->dev, mpc85xx_mc_err_probe); return -ENOMEM; diff --git a/drivers/edac/mv64x60_edac.c b/drivers/edac/mv64x60_edac.c index 289a6cc859b4..b0bb5a3d2527 100644 --- a/drivers/edac/mv64x60_edac.c +++ b/drivers/edac/mv64x60_edac.c @@ -715,7 +715,7 @@ static int __devinit mv64x60_mc_err_probe(struct platform_device *pdev) layers[1].type = EDAC_MC_LAYER_CHANNEL; layers[1].size = 1; layers[1].is_virt_csrow = false; - mci = new_edac_mc_alloc(edac_mc_idx, ARRAY_SIZE(layers), layers, + mci = edac_mc_alloc(edac_mc_idx, ARRAY_SIZE(layers), layers, sizeof(struct mv64x60_mc_pdata)); if (!mci) { printk(KERN_ERR "%s: No memory for CPU err\n", __func__); diff --git a/drivers/edac/pasemi_edac.c b/drivers/edac/pasemi_edac.c index 46aed62436b5..b095a906a994 100644 --- a/drivers/edac/pasemi_edac.c +++ b/drivers/edac/pasemi_edac.c @@ -215,7 +215,7 @@ static int __devinit pasemi_edac_probe(struct pci_dev *pdev, layers[1].type = EDAC_MC_LAYER_CHANNEL; layers[1].size = PASEMI_EDAC_NR_CHANS; layers[1].is_virt_csrow = false; - mci = new_edac_mc_alloc(system_mmc_id++, ARRAY_SIZE(layers), layers, + mci = edac_mc_alloc(system_mmc_id++, ARRAY_SIZE(layers), layers, 0); if (mci == NULL) return -ENOMEM; diff --git a/drivers/edac/ppc4xx_edac.c b/drivers/edac/ppc4xx_edac.c index 59f50b6f21d3..f3f9fed06ad7 100644 --- a/drivers/edac/ppc4xx_edac.c +++ b/drivers/edac/ppc4xx_edac.c @@ -1291,7 +1291,7 @@ static int __devinit ppc4xx_edac_probe(struct platform_device *op) layers[1].type = EDAC_MC_LAYER_CHANNEL; layers[1].size = ppc4xx_edac_nr_chans; layers[1].is_virt_csrow = false; - mci = new_edac_mc_alloc(ppc4xx_edac_instance, ARRAY_SIZE(layers), layers, + mci = edac_mc_alloc(ppc4xx_edac_instance, ARRAY_SIZE(layers), layers, sizeof(struct ppc4xx_edac_pdata)); if (mci == NULL) { ppc4xx_edac_printk(KERN_ERR, "%s: " diff --git a/drivers/edac/r82600_edac.c b/drivers/edac/r82600_edac.c index aea1a0c0eca3..e1cacd164f31 100644 --- a/drivers/edac/r82600_edac.c +++ b/drivers/edac/r82600_edac.c @@ -291,7 +291,7 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx) layers[1].type = EDAC_MC_LAYER_CHANNEL; layers[1].size = R82600_NR_CHANS; layers[1].is_virt_csrow = false; - mci = new_edac_mc_alloc(0, ARRAY_SIZE(layers), layers, 0); + mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, 0); if (mci == NULL) return -ENOMEM; diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index 828647969124..2f95a1b583dc 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c @@ -1640,7 +1640,7 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev) layers[1].type = EDAC_MC_LAYER_SLOT; layers[1].size = MAX_DIMMS; layers[1].is_virt_csrow = true; - mci = new_edac_mc_alloc(sbridge_dev->mc, ARRAY_SIZE(layers), layers, + mci = edac_mc_alloc(sbridge_dev->mc, ARRAY_SIZE(layers), layers, sizeof(*pvt)); if (unlikely(!mci)) diff --git a/drivers/edac/tile_edac.c b/drivers/edac/tile_edac.c index bcdd1e4dc735..7bb4614730db 100644 --- a/drivers/edac/tile_edac.c +++ b/drivers/edac/tile_edac.c @@ -141,7 +141,7 @@ static int __devinit tile_edac_mc_probe(struct platform_device *pdev) layers[1].type = EDAC_MC_LAYER_CHANNEL; layers[1].size = TILE_EDAC_NR_CHANS; layers[1].is_virt_csrow = false; - mci = new_edac_mc_alloc(pdev->id, ARRAY_SIZE(layers), layers, + mci = edac_mc_alloc(pdev->id, ARRAY_SIZE(layers), layers, sizeof(struct tile_edac_priv)); if (mci == NULL) return -ENOMEM; diff --git a/drivers/edac/x38_edac.c b/drivers/edac/x38_edac.c index 8f8cda914534..1ac7962d63ea 100644 --- a/drivers/edac/x38_edac.c +++ b/drivers/edac/x38_edac.c @@ -348,7 +348,7 @@ static int x38_probe1(struct pci_dev *pdev, int dev_idx) layers[1].type = EDAC_MC_LAYER_CHANNEL; layers[1].size = x38_channel_num; layers[1].is_virt_csrow = false; - mci = new_edac_mc_alloc(0, ARRAY_SIZE(layers), layers, 0); + mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, 0); if (!mci) return -ENOMEM; -- cgit v1.2.3 From e17a2f42a484562be48128c5b8dc9f7291e8c902 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 11 May 2012 11:41:45 -0300 Subject: edac: Cleanup the logs for i7core and sb edac drivers Remove some information that it is duplicated at the MCE log, and don't have much usage for the error. Those data will be added again, when creating a trace function that outputs both memory errors and MCE fields. Cc: Aristeu Rozanski Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/i7core_edac.c | 9 ++------- drivers/edac/sb_edac.c | 42 ++++++++++++++++++------------------------ 2 files changed, 20 insertions(+), 31 deletions(-) (limited to 'drivers/edac/sb_edac.c') diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index 6d89c78a9b7a..2aacd951d41c 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c @@ -1623,7 +1623,7 @@ static void i7core_mce_output_error(struct mem_ctl_info *mci, const struct mce *m) { struct i7core_pvt *pvt = mci->pvt_info; - char *type, *optype, *err, *msg; + char *type, *optype, *err, msg[80]; enum hw_event_mc_err_type tp_event; unsigned long error = m->status & 0x1ff0000l; bool uncorrected_error = m->mcgstatus & 1ll << 61; @@ -1701,10 +1701,7 @@ static void i7core_mce_output_error(struct mem_ctl_info *mci, err = "unknown"; } - msg = kasprintf(GFP_ATOMIC, - "addr=0x%08llx cpu=%d count=%d Err=%08llx:%08llx (%s: %s))\n", - (long long) m->addr, m->cpu, core_err_cnt, - (long long)m->status, (long long)m->misc, optype, err); + snprintf(msg, sizeof(msg), "count=%d %s", core_err_cnt, optype); /* * Call the helper to output message @@ -1718,8 +1715,6 @@ static void i7core_mce_output_error(struct mem_ctl_info *mci, syndrome, channel, dimm, -1, err, msg, m); - - kfree(msg); } /* diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index 2f95a1b583dc..e834dfd034d6 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c @@ -788,7 +788,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci, u8 *socket, long *channel_mask, u8 *rank, - char *area_type, char *msg) + char **area_type, char *msg) { struct mem_ctl_info *new_mci; struct sbridge_pvt *pvt = mci->pvt_info; @@ -843,7 +843,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci, sprintf(msg, "Can't discover the memory socket"); return -EINVAL; } - area_type = get_dram_attr(reg); + *area_type = get_dram_attr(reg); interleave_mode = INTERLEAVE_MODE(reg); pci_read_config_dword(pvt->pci_sad0, interleave_list[n_sads], @@ -1342,7 +1342,7 @@ static void sbridge_mce_output_error(struct mem_ctl_info *mci, struct mem_ctl_info *new_mci; struct sbridge_pvt *pvt = mci->pvt_info; enum hw_event_mc_err_type tp_event; - char *type, *optype, msg[256], *recoverable_msg; + char *type, *optype, msg[256]; bool ripv = GET_BITFIELD(m->mcgstatus, 0, 0); bool overflow = GET_BITFIELD(m->status, 62, 62); bool uncorrected_error = GET_BITFIELD(m->status, 61, 61); @@ -1355,7 +1355,7 @@ static void sbridge_mce_output_error(struct mem_ctl_info *mci, long channel_mask, first_channel; u8 rank, socket; int rc, dimm; - char *area_type = "Unknown"; + char *area_type = NULL; if (uncorrected_error) { if (ripv) { @@ -1407,7 +1407,7 @@ static void sbridge_mce_output_error(struct mem_ctl_info *mci, } rc = get_memory_error_data(mci, m->addr, &socket, - &channel_mask, &rank, area_type, msg); + &channel_mask, &rank, &area_type, msg); if (rc < 0) goto err_parsing; new_mci = get_mci_for_node_id(socket); @@ -1427,29 +1427,23 @@ static void sbridge_mce_output_error(struct mem_ctl_info *mci, else dimm = 2; - if (uncorrected_error && recoverable) - recoverable_msg = " recoverable"; - else - recoverable_msg = ""; /* - * FIXME: What should we do with "channel" information on mcelog? - * Probably, we can just discard it, as the channel information - * comes from the get_memory_error_data() address decoding + * FIXME: On some memory configurations (mirror, lockstep), the + * Memory Controller can't point the error to a single DIMM. The + * EDAC core should be handling the channel mask, in order to point + * to the group of dimm's where the error may be happening. */ snprintf(msg, sizeof(msg), - "%d error(s)%s: %s%s: cpu=%d Err=%04x:%04x addr = 0x%08llx socket=%d Channel=%ld(mask=%ld), rank=%d\n", - core_err_cnt, - overflow ? " OVERFLOW" : "", - area_type, - recoverable_msg, - m->cpu, - mscod, errcode, - (long long) m->addr, - socket, - first_channel, /* This is the real channel on SB */ - channel_mask, - rank); + "count:%d%s%s area:%s err_code:%04x:%04x socket:%d channel_mask:%ld rank:%d", + core_err_cnt, + overflow ? " OVERFLOW" : "", + (uncorrected_error && recoverable) ? " recoverable" : "", + area_type, + mscod, errcode, + socket, + channel_mask, + rank); debugf0("%s", msg); -- cgit v1.2.3