aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2012-01-27 16:38:08 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-05-28 18:10:58 -0400
commit084a4fccef39ac7abb039511f32380f28d0b67e6 (patch)
tree0596612000c7ec3a848b10f7cc4acdb573218076
parenta7d7d2e1a07e3811dc49af2962c940fd8bbb6c8f (diff)
edac: move dimm properties to struct dimm_info
On systems based on chip select rows, all channels need to use memories with the same properties, otherwise the memories on channels A and B won't be recognized. However, such assumption is not true for all types of memory controllers. Controllers for FB-DIMM's don't have such requirements. Also, modern Intel controllers seem to be capable of handling such differences. So, we need to get rid of storing the DIMM information into a per-csrow data, storing it, instead at the right place. The first step is to move grain, mtype, dtype and edac_mode to the per-dimm struct. Reviewed-by: Aristeu Rozanski <arozansk@redhat.com> Reviewed-by: Borislav Petkov <borislav.petkov@amd.com> Acked-by: Chris Metcalf <cmetcalf@tilera.com> Cc: Doug Thompson <norsk5@yahoo.com> Cc: Borislav Petkov <borislav.petkov@amd.com> Cc: Mark Gross <mark.gross@intel.com> Cc: Jason Uhlenkott <juhlenko@akamai.com> Cc: Tim Small <tim@buttersideup.com> Cc: Ranganathan Desikan <ravi@jetztechnologies.com> Cc: "Arvind R." <arvino55@gmail.com> Cc: Olof Johansson <olof@lixom.net> Cc: Egor Martovetsky <egor@pasemi.com> Cc: Michal Marek <mmarek@suse.cz> Cc: Jiri Kosina <jkosina@suse.cz> Cc: Joe Perches <joe@perches.com> Cc: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Hitoshi Mitake <h.mitake@gmail.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: James Bottomley <James.Bottomley@parallels.com> Cc: "Niklas Söderlund" <niklas.soderlund@ericsson.com> Cc: Shaohui Xie <Shaohui.Xie@freescale.com> Cc: Josh Boyer <jwboyer@gmail.com> Cc: Mike Williams <mike@mikebwilliams.com> Cc: linuxppc-dev@lists.ozlabs.org Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/edac/amd64_edac.c18
-rw-r--r--drivers/edac/amd76x_edac.c10
-rw-r--r--drivers/edac/cell_edac.c10
-rw-r--r--drivers/edac/cpc925_edac.c62
-rw-r--r--drivers/edac/e752x_edac.c44
-rw-r--r--drivers/edac/e7xxx_edac.c44
-rw-r--r--drivers/edac/edac_mc.c19
-rw-r--r--drivers/edac/edac_mc_sysfs.c6
-rw-r--r--drivers/edac/i3000_edac.c18
-rw-r--r--drivers/edac/i3200_edac.c18
-rw-r--r--drivers/edac/i5000_edac.c24
-rw-r--r--drivers/edac/i5100_edac.c38
-rw-r--r--drivers/edac/i5400_edac.c24
-rw-r--r--drivers/edac/i7300_edac.c25
-rw-r--r--drivers/edac/i7core_edac.c27
-rw-r--r--drivers/edac/i82443bxgx_edac.c13
-rw-r--r--drivers/edac/i82860_edac.c11
-rw-r--r--drivers/edac/i82875p_edac.c17
-rw-r--r--drivers/edac/i82975x_edac.c17
-rw-r--r--drivers/edac/mpc85xx_edac.c13
-rw-r--r--drivers/edac/mv64x60_edac.c18
-rw-r--r--drivers/edac/pasemi_edac.c10
-rw-r--r--drivers/edac/ppc4xx_edac.c13
-rw-r--r--drivers/edac/r82600_edac.c10
-rw-r--r--drivers/edac/sb_edac.c31
-rw-r--r--drivers/edac/tile_edac.c13
-rw-r--r--drivers/edac/x38_edac.c17
-rw-r--r--include/linux/edac.h21
28 files changed, 334 insertions, 257 deletions
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)
2187 struct amd64_pvt *pvt = mci->pvt_info; 2187 struct amd64_pvt *pvt = mci->pvt_info;
2188 u64 input_addr_min, input_addr_max, sys_addr, base, mask; 2188 u64 input_addr_min, input_addr_max, sys_addr, base, mask;
2189 u32 val; 2189 u32 val;
2190 int i, empty = 1; 2190 int i, j, empty = 1;
2191 enum mem_type mtype;
2192 enum edac_type edac_mode;
2191 2193
2192 amd64_read_pci_cfg(pvt->F3, NBCFG, &val); 2194 amd64_read_pci_cfg(pvt->F3, NBCFG, &val);
2193 2195
@@ -2224,7 +2226,7 @@ static int init_csrows(struct mem_ctl_info *mci)
2224 csrow->page_mask = ~mask; 2226 csrow->page_mask = ~mask;
2225 /* 8 bytes of resolution */ 2227 /* 8 bytes of resolution */
2226 2228
2227 csrow->mtype = amd64_determine_memory_type(pvt, i); 2229 mtype = amd64_determine_memory_type(pvt, i);
2228 2230
2229 debugf1(" for MC node %d csrow %d:\n", pvt->mc_node_id, i); 2231 debugf1(" for MC node %d csrow %d:\n", pvt->mc_node_id, i);
2230 debugf1(" input_addr_min: 0x%lx input_addr_max: 0x%lx\n", 2232 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)
2241 * determine whether CHIPKILL or JUST ECC or NO ECC is operating 2243 * determine whether CHIPKILL or JUST ECC or NO ECC is operating
2242 */ 2244 */
2243 if (pvt->nbcfg & NBCFG_ECC_ENABLE) 2245 if (pvt->nbcfg & NBCFG_ECC_ENABLE)
2244 csrow->edac_mode = 2246 edac_mode = (pvt->nbcfg & NBCFG_CHIPKILL) ?
2245 (pvt->nbcfg & NBCFG_CHIPKILL) ? 2247 EDAC_S4ECD4ED : EDAC_SECDED;
2246 EDAC_S4ECD4ED : EDAC_SECDED;
2247 else 2248 else
2248 csrow->edac_mode = EDAC_NONE; 2249 edac_mode = EDAC_NONE;
2250
2251 for (j = 0; j < pvt->channel_count; j++) {
2252 csrow->channels[j].dimm->mtype = mtype;
2253 csrow->channels[j].dimm->edac_mode = edac_mode;
2254 }
2249 } 2255 }
2250 2256
2251 return empty; 2257 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,
186 enum edac_type edac_mode) 186 enum edac_type edac_mode)
187{ 187{
188 struct csrow_info *csrow; 188 struct csrow_info *csrow;
189 struct dimm_info *dimm;
189 u32 mba, mba_base, mba_mask, dms; 190 u32 mba, mba_base, mba_mask, dms;
190 int index; 191 int index;
191 192
192 for (index = 0; index < mci->nr_csrows; index++) { 193 for (index = 0; index < mci->nr_csrows; index++) {
193 csrow = &mci->csrows[index]; 194 csrow = &mci->csrows[index];
195 dimm = csrow->channels[0].dimm;
194 196
195 /* find the DRAM Chip Select Base address and mask */ 197 /* find the DRAM Chip Select Base address and mask */
196 pci_read_config_dword(pdev, 198 pci_read_config_dword(pdev,
@@ -206,10 +208,10 @@ static void amd76x_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev,
206 csrow->nr_pages = (mba_mask + 1) >> PAGE_SHIFT; 208 csrow->nr_pages = (mba_mask + 1) >> PAGE_SHIFT;
207 csrow->last_page = csrow->first_page + csrow->nr_pages - 1; 209 csrow->last_page = csrow->first_page + csrow->nr_pages - 1;
208 csrow->page_mask = mba_mask >> PAGE_SHIFT; 210 csrow->page_mask = mba_mask >> PAGE_SHIFT;
209 csrow->grain = csrow->nr_pages << PAGE_SHIFT; 211 dimm->grain = csrow->nr_pages << PAGE_SHIFT;
210 csrow->mtype = MEM_RDDR; 212 dimm->mtype = MEM_RDDR;
211 csrow->dtype = ((dms >> index) & 0x1) ? DEV_X4 : DEV_UNKNOWN; 213 dimm->dtype = ((dms >> index) & 0x1) ? DEV_X4 : DEV_UNKNOWN;
212 csrow->edac_mode = edac_mode; 214 dimm->edac_mode = edac_mode;
213 } 215 }
214} 216}
215 217
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)
124static void __devinit cell_edac_init_csrows(struct mem_ctl_info *mci) 124static void __devinit cell_edac_init_csrows(struct mem_ctl_info *mci)
125{ 125{
126 struct csrow_info *csrow = &mci->csrows[0]; 126 struct csrow_info *csrow = &mci->csrows[0];
127 struct dimm_info *dimm;
127 struct cell_edac_priv *priv = mci->pvt_info; 128 struct cell_edac_priv *priv = mci->pvt_info;
128 struct device_node *np; 129 struct device_node *np;
130 int j;
129 131
130 for (np = NULL; 132 for (np = NULL;
131 (np = of_find_node_by_name(np, "memory")) != NULL;) { 133 (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)
142 csrow->first_page = r.start >> PAGE_SHIFT; 144 csrow->first_page = r.start >> PAGE_SHIFT;
143 csrow->nr_pages = resource_size(&r) >> PAGE_SHIFT; 145 csrow->nr_pages = resource_size(&r) >> PAGE_SHIFT;
144 csrow->last_page = csrow->first_page + csrow->nr_pages - 1; 146 csrow->last_page = csrow->first_page + csrow->nr_pages - 1;
145 csrow->mtype = MEM_XDR; 147
146 csrow->edac_mode = EDAC_SECDED; 148 for (j = 0; j < csrow->nr_channels; j++) {
149 dimm = csrow->channels[j].dimm;
150 dimm->mtype = MEM_XDR;
151 dimm->edac_mode = EDAC_SECDED;
152 }
147 dev_dbg(mci->dev, 153 dev_dbg(mci->dev,
148 "Initialized on node %d, chanmask=0x%x," 154 "Initialized on node %d, chanmask=0x%x,"
149 " first_page=0x%lx, nr_pages=0x%x\n", 155 " 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)
329{ 329{
330 struct cpc925_mc_pdata *pdata = mci->pvt_info; 330 struct cpc925_mc_pdata *pdata = mci->pvt_info;
331 struct csrow_info *csrow; 331 struct csrow_info *csrow;
332 int index; 332 struct dimm_info *dimm;
333 int index, j;
333 u32 mbmr, mbbar, bba; 334 u32 mbmr, mbbar, bba;
334 unsigned long row_size, last_nr_pages = 0; 335 unsigned long row_size, last_nr_pages = 0;
335 336
@@ -354,32 +355,35 @@ static void cpc925_init_csrows(struct mem_ctl_info *mci)
354 csrow->last_page = csrow->first_page + csrow->nr_pages - 1; 355 csrow->last_page = csrow->first_page + csrow->nr_pages - 1;
355 last_nr_pages = csrow->last_page + 1; 356 last_nr_pages = csrow->last_page + 1;
356 357
357 csrow->mtype = MEM_RDDR; 358 for (j = 0; j < csrow->nr_channels; j++) {
358 csrow->edac_mode = EDAC_SECDED; 359 dimm = csrow->channels[j].dimm;
359 360 dimm->mtype = MEM_RDDR;
360 switch (csrow->nr_channels) { 361 dimm->edac_mode = EDAC_SECDED;
361 case 1: /* Single channel */ 362
362 csrow->grain = 32; /* four-beat burst of 32 bytes */ 363 switch (csrow->nr_channels) {
363 break; 364 case 1: /* Single channel */
364 case 2: /* Dual channel */ 365 dimm->grain = 32; /* four-beat burst of 32 bytes */
365 default: 366 break;
366 csrow->grain = 64; /* four-beat burst of 64 bytes */ 367 case 2: /* Dual channel */
367 break; 368 default:
368 } 369 dimm->grain = 64; /* four-beat burst of 64 bytes */
369 370 break;
370 switch ((mbmr & MBMR_MODE_MASK) >> MBMR_MODE_SHIFT) { 371 }
371 case 6: /* 0110, no way to differentiate X8 VS X16 */ 372
372 case 5: /* 0101 */ 373 switch ((mbmr & MBMR_MODE_MASK) >> MBMR_MODE_SHIFT) {
373 case 8: /* 1000 */ 374 case 6: /* 0110, no way to differentiate X8 VS X16 */
374 csrow->dtype = DEV_X16; 375 case 5: /* 0101 */
375 break; 376 case 8: /* 1000 */
376 case 7: /* 0111 */ 377 dimm->dtype = DEV_X16;
377 case 9: /* 1001 */ 378 break;
378 csrow->dtype = DEV_X8; 379 case 7: /* 0111 */
379 break; 380 case 9: /* 1001 */
380 default: 381 dimm->dtype = DEV_X8;
381 csrow->dtype = DEV_UNKNOWN; 382 break;
382 break; 383 default:
384 dimm->dtype = DEV_UNKNOWN;
385 break;
386 }
383 } 387 }
384 } 388 }
385} 389}
@@ -962,9 +966,9 @@ static int __devinit cpc925_probe(struct platform_device *pdev)
962 goto err2; 966 goto err2;
963 } 967 }
964 968
965 nr_channels = cpc925_mc_get_channels(vbase); 969 nr_channels = cpc925_mc_get_channels(vbase) + 1;
966 mci = edac_mc_alloc(sizeof(struct cpc925_mc_pdata), 970 mci = edac_mc_alloc(sizeof(struct cpc925_mc_pdata),
967 CPC925_NR_CSROWS, nr_channels + 1, edac_mc_idx); 971 CPC925_NR_CSROWS, nr_channels, edac_mc_idx);
968 if (!mci) { 972 if (!mci) {
969 cpc925_printk(KERN_ERR, "No memory for mem_ctl_info\n"); 973 cpc925_printk(KERN_ERR, "No memory for mem_ctl_info\n");
970 res = -ENOMEM; 974 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,
1044 int drc_drbg; /* DRB granularity 0=64mb, 1=128mb */ 1044 int drc_drbg; /* DRB granularity 0=64mb, 1=128mb */
1045 int drc_ddim; /* DRAM Data Integrity Mode 0=none, 2=edac */ 1045 int drc_ddim; /* DRAM Data Integrity Mode 0=none, 2=edac */
1046 u8 value; 1046 u8 value;
1047 u32 dra, drc, cumul_size; 1047 u32 dra, drc, cumul_size, i;
1048 1048
1049 dra = 0; 1049 dra = 0;
1050 for (index = 0; index < 4; index++) { 1050 for (index = 0; index < 4; index++) {
@@ -1053,7 +1053,7 @@ static void e752x_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev,
1053 dra |= dra_reg << (index * 8); 1053 dra |= dra_reg << (index * 8);
1054 } 1054 }
1055 pci_read_config_dword(pdev, E752X_DRC, &drc); 1055 pci_read_config_dword(pdev, E752X_DRC, &drc);
1056 drc_chan = dual_channel_active(ddrcsr); 1056 drc_chan = dual_channel_active(ddrcsr) ? 1 : 0;
1057 drc_drbg = drc_chan + 1; /* 128 in dual mode, 64 in single */ 1057 drc_drbg = drc_chan + 1; /* 128 in dual mode, 64 in single */
1058 drc_ddim = (drc >> 20) & 0x3; 1058 drc_ddim = (drc >> 20) & 0x3;
1059 1059
@@ -1080,24 +1080,28 @@ static void e752x_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev,
1080 csrow->last_page = cumul_size - 1; 1080 csrow->last_page = cumul_size - 1;
1081 csrow->nr_pages = cumul_size - last_cumul_size; 1081 csrow->nr_pages = cumul_size - last_cumul_size;
1082 last_cumul_size = cumul_size; 1082 last_cumul_size = cumul_size;
1083 csrow->grain = 1 << 12; /* 4KiB - resolution of CELOG */ 1083
1084 csrow->mtype = MEM_RDDR; /* only one type supported */ 1084 for (i = 0; i < drc_chan + 1; i++) {
1085 csrow->dtype = mem_dev ? DEV_X4 : DEV_X8; 1085 struct dimm_info *dimm = csrow->channels[i].dimm;
1086 1086 dimm->grain = 1 << 12; /* 4KiB - resolution of CELOG */
1087 /* 1087 dimm->mtype = MEM_RDDR; /* only one type supported */
1088 * if single channel or x8 devices then SECDED 1088 dimm->dtype = mem_dev ? DEV_X4 : DEV_X8;
1089 * if dual channel and x4 then S4ECD4ED 1089
1090 */ 1090 /*
1091 if (drc_ddim) { 1091 * if single channel or x8 devices then SECDED
1092 if (drc_chan && mem_dev) { 1092 * if dual channel and x4 then S4ECD4ED
1093 csrow->edac_mode = EDAC_S4ECD4ED; 1093 */
1094 mci->edac_cap |= EDAC_FLAG_S4ECD4ED; 1094 if (drc_ddim) {
1095 } else { 1095 if (drc_chan && mem_dev) {
1096 csrow->edac_mode = EDAC_SECDED; 1096 dimm->edac_mode = EDAC_S4ECD4ED;
1097 mci->edac_cap |= EDAC_FLAG_SECDED; 1097 mci->edac_cap |= EDAC_FLAG_S4ECD4ED;
1098 } 1098 } else {
1099 } else 1099 dimm->edac_mode = EDAC_SECDED;
1100 csrow->edac_mode = EDAC_NONE; 1100 mci->edac_cap |= EDAC_FLAG_SECDED;
1101 }
1102 } else
1103 dimm->edac_mode = EDAC_NONE;
1104 }
1101 } 1105 }
1102} 1106}
1103 1107
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,
347 int dev_idx, u32 drc) 347 int dev_idx, u32 drc)
348{ 348{
349 unsigned long last_cumul_size; 349 unsigned long last_cumul_size;
350 int index; 350 int index, j;
351 u8 value; 351 u8 value;
352 u32 dra, cumul_size; 352 u32 dra, cumul_size;
353 int drc_chan, drc_drbg, drc_ddim, mem_dev; 353 int drc_chan, drc_drbg, drc_ddim, mem_dev;
354 struct csrow_info *csrow; 354 struct csrow_info *csrow;
355 struct dimm_info *dimm;
355 356
356 pci_read_config_dword(pdev, E7XXX_DRA, &dra); 357 pci_read_config_dword(pdev, E7XXX_DRA, &dra);
357 drc_chan = dual_channel_active(drc, dev_idx); 358 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,
381 csrow->last_page = cumul_size - 1; 382 csrow->last_page = cumul_size - 1;
382 csrow->nr_pages = cumul_size - last_cumul_size; 383 csrow->nr_pages = cumul_size - last_cumul_size;
383 last_cumul_size = cumul_size; 384 last_cumul_size = cumul_size;
384 csrow->grain = 1 << 12; /* 4KiB - resolution of CELOG */ 385
385 csrow->mtype = MEM_RDDR; /* only one type supported */ 386 for (j = 0; j < drc_chan + 1; j++) {
386 csrow->dtype = mem_dev ? DEV_X4 : DEV_X8; 387 dimm = csrow->channels[j].dimm;
387 388
388 /* 389 dimm->grain = 1 << 12; /* 4KiB - resolution of CELOG */
389 * if single channel or x8 devices then SECDED 390 dimm->mtype = MEM_RDDR; /* only one type supported */
390 * if dual channel and x4 then S4ECD4ED 391 dimm->dtype = mem_dev ? DEV_X4 : DEV_X8;
391 */ 392
392 if (drc_ddim) { 393 /*
393 if (drc_chan && mem_dev) { 394 * if single channel or x8 devices then SECDED
394 csrow->edac_mode = EDAC_S4ECD4ED; 395 * if dual channel and x4 then S4ECD4ED
395 mci->edac_cap |= EDAC_FLAG_S4ECD4ED; 396 */
396 } else { 397 if (drc_ddim) {
397 csrow->edac_mode = EDAC_SECDED; 398 if (drc_chan && mem_dev) {
398 mci->edac_cap |= EDAC_FLAG_SECDED; 399 dimm->edac_mode = EDAC_S4ECD4ED;
399 } 400 mci->edac_cap |= EDAC_FLAG_S4ECD4ED;
400 } else 401 } else {
401 csrow->edac_mode = EDAC_NONE; 402 dimm->edac_mode = EDAC_SECDED;
403 mci->edac_cap |= EDAC_FLAG_SECDED;
404 }
405 } else
406 dimm->edac_mode = EDAC_NONE;
407 }
402 } 408 }
403} 409}
404 410
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)
43{ 43{
44 debugf4("\tchannel = %p\n", chan); 44 debugf4("\tchannel = %p\n", chan);
45 debugf4("\tchannel->chan_idx = %d\n", chan->chan_idx); 45 debugf4("\tchannel->chan_idx = %d\n", chan->chan_idx);
46 debugf4("\tchannel->ce_count = %d\n", chan->ce_count); 46 debugf4("\tchannel->ce_count = %d\n", chan->dimm->ce_count);
47 debugf4("\tchannel->label = '%s'\n", chan->dimm->label); 47 debugf4("\tchannel->label = '%s'\n", chan->dimm->label);
48 debugf4("\tchannel->csrow = %p\n\n", chan->csrow); 48 debugf4("\tchannel->csrow = %p\n\n", chan->csrow);
49} 49}
@@ -695,6 +695,7 @@ void edac_mc_handle_ce(struct mem_ctl_info *mci,
695{ 695{
696 unsigned long remapped_page; 696 unsigned long remapped_page;
697 char *label = NULL; 697 char *label = NULL;
698 u32 grain;
698 699
699 debugf3("MC%d: %s()\n", mci->mc_idx, __func__); 700 debugf3("MC%d: %s()\n", mci->mc_idx, __func__);
700 701
@@ -719,6 +720,7 @@ void edac_mc_handle_ce(struct mem_ctl_info *mci,
719 } 720 }
720 721
721 label = mci->csrows[row].channels[channel].dimm->label; 722 label = mci->csrows[row].channels[channel].dimm->label;
723 grain = mci->csrows[row].channels[channel].dimm->grain;
722 724
723 if (edac_mc_get_log_ce()) 725 if (edac_mc_get_log_ce())
724 /* FIXME - put in DIMM location */ 726 /* FIXME - put in DIMM location */
@@ -726,11 +728,12 @@ void edac_mc_handle_ce(struct mem_ctl_info *mci,
726 "CE page 0x%lx, offset 0x%lx, grain %d, syndrome " 728 "CE page 0x%lx, offset 0x%lx, grain %d, syndrome "
727 "0x%lx, row %d, channel %d, label \"%s\": %s\n", 729 "0x%lx, row %d, channel %d, label \"%s\": %s\n",
728 page_frame_number, offset_in_page, 730 page_frame_number, offset_in_page,
729 mci->csrows[row].grain, syndrome, row, channel, 731 grain, syndrome, row, channel,
730 label, msg); 732 label, msg);
731 733
732 mci->ce_count++; 734 mci->ce_count++;
733 mci->csrows[row].ce_count++; 735 mci->csrows[row].ce_count++;
736 mci->csrows[row].channels[channel].dimm->ce_count++;
734 mci->csrows[row].channels[channel].ce_count++; 737 mci->csrows[row].channels[channel].ce_count++;
735 738
736 if (mci->scrub_mode & SCRUB_SW_SRC) { 739 if (mci->scrub_mode & SCRUB_SW_SRC) {
@@ -747,8 +750,7 @@ void edac_mc_handle_ce(struct mem_ctl_info *mci,
747 mci->ctl_page_to_phys(mci, page_frame_number) : 750 mci->ctl_page_to_phys(mci, page_frame_number) :
748 page_frame_number; 751 page_frame_number;
749 752
750 edac_mc_scrub_block(remapped_page, offset_in_page, 753 edac_mc_scrub_block(remapped_page, offset_in_page, grain);
751 mci->csrows[row].grain);
752 } 754 }
753} 755}
754EXPORT_SYMBOL_GPL(edac_mc_handle_ce); 756EXPORT_SYMBOL_GPL(edac_mc_handle_ce);
@@ -774,6 +776,7 @@ void edac_mc_handle_ue(struct mem_ctl_info *mci,
774 int chan; 776 int chan;
775 int chars; 777 int chars;
776 char *label = NULL; 778 char *label = NULL;
779 u32 grain;
777 780
778 debugf3("MC%d: %s()\n", mci->mc_idx, __func__); 781 debugf3("MC%d: %s()\n", mci->mc_idx, __func__);
779 782
@@ -787,6 +790,7 @@ void edac_mc_handle_ue(struct mem_ctl_info *mci,
787 return; 790 return;
788 } 791 }
789 792
793 grain = mci->csrows[row].channels[0].dimm->grain;
790 label = mci->csrows[row].channels[0].dimm->label; 794 label = mci->csrows[row].channels[0].dimm->label;
791 chars = snprintf(pos, len + 1, "%s", label); 795 chars = snprintf(pos, len + 1, "%s", label);
792 len -= chars; 796 len -= chars;
@@ -804,14 +808,13 @@ void edac_mc_handle_ue(struct mem_ctl_info *mci,
804 edac_mc_printk(mci, KERN_EMERG, 808 edac_mc_printk(mci, KERN_EMERG,
805 "UE page 0x%lx, offset 0x%lx, grain %d, row %d, " 809 "UE page 0x%lx, offset 0x%lx, grain %d, row %d, "
806 "labels \"%s\": %s\n", page_frame_number, 810 "labels \"%s\": %s\n", page_frame_number,
807 offset_in_page, mci->csrows[row].grain, row, 811 offset_in_page, grain, row, labels, msg);
808 labels, msg);
809 812
810 if (edac_mc_get_panic_on_ue()) 813 if (edac_mc_get_panic_on_ue())
811 panic("EDAC MC%d: UE page 0x%lx, offset 0x%lx, grain %d, " 814 panic("EDAC MC%d: UE page 0x%lx, offset 0x%lx, grain %d, "
812 "row %d, labels \"%s\": %s\n", mci->mc_idx, 815 "row %d, labels \"%s\": %s\n", mci->mc_idx,
813 page_frame_number, offset_in_page, 816 page_frame_number, offset_in_page,
814 mci->csrows[row].grain, row, labels, msg); 817 grain, row, labels, msg);
815 818
816 mci->ue_count++; 819 mci->ue_count++;
817 mci->csrows[row].ue_count++; 820 mci->csrows[row].ue_count++;
@@ -883,6 +886,7 @@ void edac_mc_handle_fbd_ue(struct mem_ctl_info *mci,
883 chars = snprintf(pos, len + 1, "%s", label); 886 chars = snprintf(pos, len + 1, "%s", label);
884 len -= chars; 887 len -= chars;
885 pos += chars; 888 pos += chars;
889
886 chars = snprintf(pos, len + 1, "-%s", 890 chars = snprintf(pos, len + 1, "-%s",
887 mci->csrows[csrow].channels[channelb].dimm->label); 891 mci->csrows[csrow].channels[channelb].dimm->label);
888 892
@@ -936,6 +940,7 @@ void edac_mc_handle_fbd_ce(struct mem_ctl_info *mci,
936 940
937 mci->ce_count++; 941 mci->ce_count++;
938 mci->csrows[csrow].ce_count++; 942 mci->csrows[csrow].ce_count++;
943 mci->csrows[csrow].channels[channel].dimm->ce_count++;
939 mci->csrows[csrow].channels[channel].ce_count++; 944 mci->csrows[csrow].channels[channel].ce_count++;
940} 945}
941EXPORT_SYMBOL(edac_mc_handle_fbd_ce); 946EXPORT_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,
150static ssize_t csrow_mem_type_show(struct csrow_info *csrow, char *data, 150static ssize_t csrow_mem_type_show(struct csrow_info *csrow, char *data,
151 int private) 151 int private)
152{ 152{
153 return sprintf(data, "%s\n", mem_types[csrow->mtype]); 153 return sprintf(data, "%s\n", mem_types[csrow->channels[0].dimm->mtype]);
154} 154}
155 155
156static ssize_t csrow_dev_type_show(struct csrow_info *csrow, char *data, 156static ssize_t csrow_dev_type_show(struct csrow_info *csrow, char *data,
157 int private) 157 int private)
158{ 158{
159 return sprintf(data, "%s\n", dev_types[csrow->dtype]); 159 return sprintf(data, "%s\n", dev_types[csrow->channels[0].dimm->dtype]);
160} 160}
161 161
162static ssize_t csrow_edac_mode_show(struct csrow_info *csrow, char *data, 162static ssize_t csrow_edac_mode_show(struct csrow_info *csrow, char *data,
163 int private) 163 int private)
164{ 164{
165 return sprintf(data, "%s\n", edac_caps[csrow->edac_mode]); 165 return sprintf(data, "%s\n", edac_caps[csrow->channels[0].dimm->edac_mode]);
166} 166}
167 167
168/* show/store functions for DIMM Label attributes */ 168/* 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,
304static int i3000_probe1(struct pci_dev *pdev, int dev_idx) 304static int i3000_probe1(struct pci_dev *pdev, int dev_idx)
305{ 305{
306 int rc; 306 int rc;
307 int i; 307 int i, j;
308 struct mem_ctl_info *mci = NULL; 308 struct mem_ctl_info *mci = NULL;
309 unsigned long last_cumul_size; 309 unsigned long last_cumul_size;
310 int interleaved, nr_channels; 310 int interleaved, nr_channels;
@@ -386,19 +386,21 @@ static int i3000_probe1(struct pci_dev *pdev, int dev_idx)
386 cumul_size <<= 1; 386 cumul_size <<= 1;
387 debugf3("MC: %s(): (%d) cumul_size 0x%x\n", 387 debugf3("MC: %s(): (%d) cumul_size 0x%x\n",
388 __func__, i, cumul_size); 388 __func__, i, cumul_size);
389 if (cumul_size == last_cumul_size) { 389 if (cumul_size == last_cumul_size)
390 csrow->mtype = MEM_EMPTY;
391 continue; 390 continue;
392 }
393 391
394 csrow->first_page = last_cumul_size; 392 csrow->first_page = last_cumul_size;
395 csrow->last_page = cumul_size - 1; 393 csrow->last_page = cumul_size - 1;
396 csrow->nr_pages = cumul_size - last_cumul_size; 394 csrow->nr_pages = cumul_size - last_cumul_size;
397 last_cumul_size = cumul_size; 395 last_cumul_size = cumul_size;
398 csrow->grain = I3000_DEAP_GRAIN; 396
399 csrow->mtype = MEM_DDR2; 397 for (j = 0; j < nr_channels; j++) {
400 csrow->dtype = DEV_UNKNOWN; 398 struct dimm_info *dimm = csrow->channels[j].dimm;
401 csrow->edac_mode = EDAC_UNKNOWN; 399 dimm->grain = I3000_DEAP_GRAIN;
400 dimm->mtype = MEM_DDR2;
401 dimm->dtype = DEV_UNKNOWN;
402 dimm->edac_mode = EDAC_UNKNOWN;
403 }
402 } 404 }
403 405
404 /* 406 /*
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(
319static int i3200_probe1(struct pci_dev *pdev, int dev_idx) 319static int i3200_probe1(struct pci_dev *pdev, int dev_idx)
320{ 320{
321 int rc; 321 int rc;
322 int i; 322 int i, j;
323 struct mem_ctl_info *mci = NULL; 323 struct mem_ctl_info *mci = NULL;
324 unsigned long last_page; 324 unsigned long last_page;
325 u16 drbs[I3200_CHANNELS][I3200_RANKS_PER_CHANNEL]; 325 u16 drbs[I3200_CHANNELS][I3200_RANKS_PER_CHANNEL];
@@ -375,20 +375,22 @@ static int i3200_probe1(struct pci_dev *pdev, int dev_idx)
375 i / I3200_RANKS_PER_CHANNEL, 375 i / I3200_RANKS_PER_CHANNEL,
376 i % I3200_RANKS_PER_CHANNEL); 376 i % I3200_RANKS_PER_CHANNEL);
377 377
378 if (nr_pages == 0) { 378 if (nr_pages == 0)
379 csrow->mtype = MEM_EMPTY;
380 continue; 379 continue;
381 }
382 380
383 csrow->first_page = last_page + 1; 381 csrow->first_page = last_page + 1;
384 last_page += nr_pages; 382 last_page += nr_pages;
385 csrow->last_page = last_page; 383 csrow->last_page = last_page;
386 csrow->nr_pages = nr_pages; 384 csrow->nr_pages = nr_pages;
387 385
388 csrow->grain = nr_pages << PAGE_SHIFT; 386 for (j = 0; j < nr_channels; j++) {
389 csrow->mtype = MEM_DDR2; 387 struct dimm_info *dimm = csrow->channels[j].dimm;
390 csrow->dtype = DEV_UNKNOWN; 388
391 csrow->edac_mode = EDAC_UNKNOWN; 389 dimm->grain = nr_pages << PAGE_SHIFT;
390 dimm->mtype = MEM_DDR2;
391 dimm->dtype = DEV_UNKNOWN;
392 dimm->edac_mode = EDAC_UNKNOWN;
393 }
392 } 394 }
393 395
394 i3200_clear_error_info(mci); 396 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)
1268 p_csrow->last_page = 9 + csrow * 20; 1268 p_csrow->last_page = 9 + csrow * 20;
1269 p_csrow->page_mask = 0xFFF; 1269 p_csrow->page_mask = 0xFFF;
1270 1270
1271 p_csrow->grain = 8;
1272
1273 csrow_megs = 0; 1271 csrow_megs = 0;
1274 for (channel = 0; channel < pvt->maxch; channel++) { 1272 for (channel = 0; channel < pvt->maxch; channel++) {
1275 csrow_megs += pvt->dimm_info[csrow][channel].megabytes; 1273 csrow_megs += pvt->dimm_info[csrow][channel].megabytes;
1276 } 1274 p_csrow->channels[channel].dimm->grain = 8;
1277 1275
1278 p_csrow->nr_pages = csrow_megs << 8; 1276 /* Assume DDR2 for now */
1277 p_csrow->channels[channel].dimm->mtype = MEM_FB_DDR2;
1279 1278
1280 /* Assume DDR2 for now */ 1279 /* ask what device type on this row */
1281 p_csrow->mtype = MEM_FB_DDR2; 1280 if (MTR_DRAM_WIDTH(mtr))
1281 p_csrow->channels[channel].dimm->dtype = DEV_X8;
1282 else
1283 p_csrow->channels[channel].dimm->dtype = DEV_X4;
1282 1284
1283 /* ask what device type on this row */ 1285 p_csrow->channels[channel].dimm->edac_mode = EDAC_S8ECD8ED;
1284 if (MTR_DRAM_WIDTH(mtr)) 1286 }
1285 p_csrow->dtype = DEV_X8; 1287 p_csrow->nr_pages = csrow_megs << 8;
1286 else
1287 p_csrow->dtype = DEV_X4;
1288
1289 p_csrow->edac_mode = EDAC_S8ECD8ED;
1290 1288
1291 empty = 0; 1289 empty = 0;
1292 } 1290 }
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,
428 const char *msg) 428 const char *msg)
429{ 429{
430 const int csrow = i5100_rank_to_csrow(mci, chan, rank); 430 const int csrow = i5100_rank_to_csrow(mci, chan, rank);
431 char *label = NULL;
432
433 if (mci->csrows[csrow].channels[0].dimm)
434 label = mci->csrows[csrow].channels[0].dimm->label;
431 435
432 printk(KERN_ERR 436 printk(KERN_ERR
433 "CE chan %d, bank %u, rank %u, syndrome 0x%lx, " 437 "CE chan %d, bank %u, rank %u, syndrome 0x%lx, "
434 "cas %u, ras %u, csrow %u, label \"%s\": %s\n", 438 "cas %u, ras %u, csrow %u, label \"%s\": %s\n",
435 chan, bank, rank, syndrome, cas, ras, 439 chan, bank, rank, syndrome, cas, ras,
436 csrow, mci->csrows[csrow].channels[0].dimm->label, msg); 440 csrow, label, msg);
437 441
438 mci->ce_count++; 442 mci->ce_count++;
439 mci->csrows[csrow].ce_count++; 443 mci->csrows[csrow].ce_count++;
@@ -450,12 +454,16 @@ static void i5100_handle_ue(struct mem_ctl_info *mci,
450 const char *msg) 454 const char *msg)
451{ 455{
452 const int csrow = i5100_rank_to_csrow(mci, chan, rank); 456 const int csrow = i5100_rank_to_csrow(mci, chan, rank);
457 char *label = NULL;
458
459 if (mci->csrows[csrow].channels[0].dimm)
460 label = mci->csrows[csrow].channels[0].dimm->label;
453 461
454 printk(KERN_ERR 462 printk(KERN_ERR
455 "UE chan %d, bank %u, rank %u, syndrome 0x%lx, " 463 "UE chan %d, bank %u, rank %u, syndrome 0x%lx, "
456 "cas %u, ras %u, csrow %u, label \"%s\": %s\n", 464 "cas %u, ras %u, csrow %u, label \"%s\": %s\n",
457 chan, bank, rank, syndrome, cas, ras, 465 chan, bank, rank, syndrome, cas, ras,
458 csrow, mci->csrows[csrow].channels[0].dimm->label, msg); 466 csrow, label, msg);
459 467
460 mci->ue_count++; 468 mci->ue_count++;
461 mci->csrows[csrow].ue_count++; 469 mci->csrows[csrow].ue_count++;
@@ -837,6 +845,7 @@ static void __devinit i5100_init_csrows(struct mem_ctl_info *mci)
837 int i; 845 int i;
838 unsigned long total_pages = 0UL; 846 unsigned long total_pages = 0UL;
839 struct i5100_priv *priv = mci->pvt_info; 847 struct i5100_priv *priv = mci->pvt_info;
848 struct dimm_info *dimm;
840 849
841 for (i = 0; i < mci->nr_csrows; i++) { 850 for (i = 0; i < mci->nr_csrows; i++) {
842 const unsigned long npages = i5100_npages(mci, i); 851 const unsigned long npages = i5100_npages(mci, i);
@@ -852,27 +861,22 @@ static void __devinit i5100_init_csrows(struct mem_ctl_info *mci)
852 */ 861 */
853 mci->csrows[i].first_page = total_pages; 862 mci->csrows[i].first_page = total_pages;
854 mci->csrows[i].last_page = total_pages + npages - 1; 863 mci->csrows[i].last_page = total_pages + npages - 1;
855 mci->csrows[i].page_mask = 0UL;
856
857 mci->csrows[i].nr_pages = npages; 864 mci->csrows[i].nr_pages = npages;
858 mci->csrows[i].grain = 32;
859 mci->csrows[i].csrow_idx = i; 865 mci->csrows[i].csrow_idx = i;
860 mci->csrows[i].dtype =
861 (priv->mtr[chan][rank].width == 4) ? DEV_X4 : DEV_X8;
862 mci->csrows[i].ue_count = 0;
863 mci->csrows[i].ce_count = 0;
864 mci->csrows[i].mtype = MEM_RDDR2;
865 mci->csrows[i].edac_mode = EDAC_SECDED;
866 mci->csrows[i].mci = mci; 866 mci->csrows[i].mci = mci;
867 mci->csrows[i].nr_channels = 1; 867 mci->csrows[i].nr_channels = 1;
868 mci->csrows[i].channels[0].chan_idx = 0;
869 mci->csrows[i].channels[0].ce_count = 0;
870 mci->csrows[i].channels[0].csrow = mci->csrows + i; 868 mci->csrows[i].channels[0].csrow = mci->csrows + i;
871 snprintf(mci->csrows[i].channels[0].dimm->label,
872 sizeof(mci->csrows[i].channels[0].dimm->label),
873 "DIMM%u", i5100_rank_to_slot(mci, chan, rank));
874
875 total_pages += npages; 869 total_pages += npages;
870
871 dimm = mci->csrows[i].channels[0].dimm;
872 dimm->grain = 32;
873 dimm->dtype = (priv->mtr[chan][rank].width == 4) ?
874 DEV_X4 : DEV_X8;
875 dimm->mtype = MEM_RDDR2;
876 dimm->edac_mode = EDAC_SECDED;
877 snprintf(dimm->label, sizeof(dimm->label),
878 "DIMM%u",
879 i5100_rank_to_slot(mci, chan, rank));
876 } 880 }
877} 881}
878 882
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)
1159 int csrow_megs; 1159 int csrow_megs;
1160 int channel; 1160 int channel;
1161 int csrow; 1161 int csrow;
1162 struct dimm_info *dimm;
1162 1163
1163 pvt = mci->pvt_info; 1164 pvt = mci->pvt_info;
1164 1165
@@ -1184,24 +1185,17 @@ static int i5400_init_csrows(struct mem_ctl_info *mci)
1184 p_csrow->last_page = 9 + csrow * 20; 1185 p_csrow->last_page = 9 + csrow * 20;
1185 p_csrow->page_mask = 0xFFF; 1186 p_csrow->page_mask = 0xFFF;
1186 1187
1187 p_csrow->grain = 8;
1188
1189 csrow_megs = 0; 1188 csrow_megs = 0;
1190 for (channel = 0; channel < pvt->maxch; channel++) 1189 for (channel = 0; channel < pvt->maxch; channel++) {
1191 csrow_megs += pvt->dimm_info[csrow][channel].megabytes; 1190 csrow_megs += pvt->dimm_info[csrow][channel].megabytes;
1192 1191
1193 p_csrow->nr_pages = csrow_megs << 8; 1192 p_csrow->nr_pages = csrow_megs << 8;
1194 1193 dimm = p_csrow->channels[channel].dimm;
1195 /* Assume DDR2 for now */ 1194 dimm->grain = 8;
1196 p_csrow->mtype = MEM_FB_DDR2; 1195 dimm->dtype = MTR_DRAM_WIDTH(mtr) ? DEV_X8 : DEV_X4;
1197 1196 dimm->mtype = MEM_RDDR2;
1198 /* ask what device type on this row */ 1197 dimm->edac_mode = EDAC_SECDED;
1199 if (MTR_DRAM_WIDTH(mtr)) 1198 }
1200 p_csrow->dtype = DEV_X8;
1201 else
1202 p_csrow->dtype = DEV_X4;
1203
1204 p_csrow->edac_mode = EDAC_S8ECD8ED;
1205 1199
1206 empty = 0; 1200 empty = 0;
1207 } 1201 }
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,
618 int slot, int ch, int branch, 618 int slot, int ch, int branch,
619 struct i7300_dimm_info *dinfo, 619 struct i7300_dimm_info *dinfo,
620 struct csrow_info *p_csrow, 620 struct csrow_info *p_csrow,
621 struct dimm_info *dimm,
621 u32 *nr_pages) 622 u32 *nr_pages)
622{ 623{
623 int mtr, ans, addrBits, channel; 624 int mtr, ans, addrBits, channel;
@@ -663,10 +664,7 @@ static int decode_mtr(struct i7300_pvt *pvt,
663 debugf2("\t\tNUMCOL: %s\n", numcol_toString[MTR_DIMM_COLS(mtr)]); 664 debugf2("\t\tNUMCOL: %s\n", numcol_toString[MTR_DIMM_COLS(mtr)]);
664 debugf2("\t\tSIZE: %d MB\n", dinfo->megabytes); 665 debugf2("\t\tSIZE: %d MB\n", dinfo->megabytes);
665 666
666 p_csrow->grain = 8;
667 p_csrow->mtype = MEM_FB_DDR2;
668 p_csrow->csrow_idx = slot; 667 p_csrow->csrow_idx = slot;
669 p_csrow->page_mask = 0;
670 668
671 /* 669 /*
672 * The type of error detection actually depends of the 670 * The type of error detection actually depends of the
@@ -677,15 +675,17 @@ static int decode_mtr(struct i7300_pvt *pvt,
677 * See datasheet Sections 7.3.6 to 7.3.8 675 * See datasheet Sections 7.3.6 to 7.3.8
678 */ 676 */
679 677
678 dimm->grain = 8;
679 dimm->mtype = MEM_FB_DDR2;
680 if (IS_SINGLE_MODE(pvt->mc_settings_a)) { 680 if (IS_SINGLE_MODE(pvt->mc_settings_a)) {
681 p_csrow->edac_mode = EDAC_SECDED; 681 dimm->edac_mode = EDAC_SECDED;
682 debugf2("\t\tECC code is 8-byte-over-32-byte SECDED+ code\n"); 682 debugf2("\t\tECC code is 8-byte-over-32-byte SECDED+ code\n");
683 } else { 683 } else {
684 debugf2("\t\tECC code is on Lockstep mode\n"); 684 debugf2("\t\tECC code is on Lockstep mode\n");
685 if (MTR_DRAM_WIDTH(mtr) == 8) 685 if (MTR_DRAM_WIDTH(mtr) == 8)
686 p_csrow->edac_mode = EDAC_S8ECD8ED; 686 dimm->edac_mode = EDAC_S8ECD8ED;
687 else 687 else
688 p_csrow->edac_mode = EDAC_S4ECD4ED; 688 dimm->edac_mode = EDAC_S4ECD4ED;
689 } 689 }
690 690
691 /* ask what device type on this row */ 691 /* ask what device type on this row */
@@ -694,9 +694,9 @@ static int decode_mtr(struct i7300_pvt *pvt,
694 IS_SCRBALGO_ENHANCED(pvt->mc_settings) ? 694 IS_SCRBALGO_ENHANCED(pvt->mc_settings) ?
695 "enhanced" : "normal"); 695 "enhanced" : "normal");
696 696
697 p_csrow->dtype = DEV_X8; 697 dimm->dtype = DEV_X8;
698 } else 698 } else
699 p_csrow->dtype = DEV_X4; 699 dimm->dtype = DEV_X4;
700 700
701 return mtr; 701 return mtr;
702} 702}
@@ -779,6 +779,7 @@ static int i7300_init_csrows(struct mem_ctl_info *mci)
779 int mtr; 779 int mtr;
780 int ch, branch, slot, channel; 780 int ch, branch, slot, channel;
781 u32 last_page = 0, nr_pages; 781 u32 last_page = 0, nr_pages;
782 struct dimm_info *dimm;
782 783
783 pvt = mci->pvt_info; 784 pvt = mci->pvt_info;
784 785
@@ -803,20 +804,24 @@ static int i7300_init_csrows(struct mem_ctl_info *mci)
803 } 804 }
804 805
805 /* Get the set of MTR[0-7] regs by each branch */ 806 /* Get the set of MTR[0-7] regs by each branch */
807 nr_pages = 0;
806 for (slot = 0; slot < MAX_SLOTS; slot++) { 808 for (slot = 0; slot < MAX_SLOTS; slot++) {
807 int where = mtr_regs[slot]; 809 int where = mtr_regs[slot];
808 for (branch = 0; branch < MAX_BRANCHES; branch++) { 810 for (branch = 0; branch < MAX_BRANCHES; branch++) {
809 pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch], 811 pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch],
810 where, 812 where,
811 &pvt->mtr[slot][branch]); 813 &pvt->mtr[slot][branch]);
812 for (ch = 0; ch < MAX_BRANCHES; ch++) { 814 for (ch = 0; ch < MAX_CH_PER_BRANCH; ch++) {
813 int channel = to_channel(ch, branch); 815 int channel = to_channel(ch, branch);
814 816
815 dinfo = &pvt->dimm_info[slot][channel]; 817 dinfo = &pvt->dimm_info[slot][channel];
816 p_csrow = &mci->csrows[slot]; 818 p_csrow = &mci->csrows[slot];
817 819
820 dimm = p_csrow->channels[branch * MAX_CH_PER_BRANCH + ch].dimm;
821
818 mtr = decode_mtr(pvt, slot, ch, branch, 822 mtr = decode_mtr(pvt, slot, ch, branch,
819 dinfo, p_csrow, &nr_pages); 823 dinfo, p_csrow, dimm,
824 &nr_pages);
820 /* if no DIMMS on this row, continue */ 825 /* if no DIMMS on this row, continue */
821 if (!MTR_DIMMS_PRESENT(mtr)) 826 if (!MTR_DIMMS_PRESENT(mtr))
822 continue; 827 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,
592 return 0; 592 return 0;
593} 593}
594 594
595static int get_dimm_config(const struct mem_ctl_info *mci) 595static int get_dimm_config(struct mem_ctl_info *mci)
596{ 596{
597 struct i7core_pvt *pvt = mci->pvt_info; 597 struct i7core_pvt *pvt = mci->pvt_info;
598 struct csrow_info *csr; 598 struct csrow_info *csr;
@@ -602,6 +602,7 @@ static int get_dimm_config(const struct mem_ctl_info *mci)
602 unsigned long last_page = 0; 602 unsigned long last_page = 0;
603 enum edac_type mode; 603 enum edac_type mode;
604 enum mem_type mtype; 604 enum mem_type mtype;
605 struct dimm_info *dimm;
605 606
606 /* Get data from the MC register, function 0 */ 607 /* Get data from the MC register, function 0 */
607 pdev = pvt->pci_mcr[0]; 608 pdev = pvt->pci_mcr[0];
@@ -721,7 +722,6 @@ static int get_dimm_config(const struct mem_ctl_info *mci)
721 csr->nr_pages = npages; 722 csr->nr_pages = npages;
722 723
723 csr->page_mask = 0; 724 csr->page_mask = 0;
724 csr->grain = 8;
725 csr->csrow_idx = csrow; 725 csr->csrow_idx = csrow;
726 csr->nr_channels = 1; 726 csr->nr_channels = 1;
727 727
@@ -730,28 +730,27 @@ static int get_dimm_config(const struct mem_ctl_info *mci)
730 730
731 pvt->csrow_map[i][j] = csrow; 731 pvt->csrow_map[i][j] = csrow;
732 732
733 dimm = csr->channels[0].dimm;
733 switch (banks) { 734 switch (banks) {
734 case 4: 735 case 4:
735 csr->dtype = DEV_X4; 736 dimm->dtype = DEV_X4;
736 break; 737 break;
737 case 8: 738 case 8:
738 csr->dtype = DEV_X8; 739 dimm->dtype = DEV_X8;
739 break; 740 break;
740 case 16: 741 case 16:
741 csr->dtype = DEV_X16; 742 dimm->dtype = DEV_X16;
742 break; 743 break;
743 default: 744 default:
744 csr->dtype = DEV_UNKNOWN; 745 dimm->dtype = DEV_UNKNOWN;
745 } 746 }
746 747
747 csr->edac_mode = mode; 748 snprintf(dimm->label, sizeof(dimm->label),
748 csr->mtype = mtype; 749 "CPU#%uChannel#%u_DIMM#%u",
749 snprintf(csr->channels[0].dimm->label, 750 pvt->i7core_dev->socket, i, j);
750 sizeof(csr->channels[0].dimm->label), 751 dimm->grain = 8;
751 "CPU#%uChannel#%u_DIMM#%u", 752 dimm->edac_mode = mode;
752 pvt->i7core_dev->socket, i, j); 753 dimm->mtype = mtype;
753
754 csrow++;
755 } 754 }
756 755
757 pci_read_config_dword(pdev, MC_SAG_CH_0, &value[0]); 756 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 @@
12 * 440GX fix by Jason Uhlenkott <juhlenko@akamai.com>. 12 * 440GX fix by Jason Uhlenkott <juhlenko@akamai.com>.
13 * 13 *
14 * Written with reference to 82443BX Host Bridge Datasheet: 14 * Written with reference to 82443BX Host Bridge Datasheet:
15 * http://download.intel.com/design/chipsets/datashts/29063301.pdf 15 * http://download.intel.com/design/chipsets/datashts/29063301.pdf
16 * references to this document given in []. 16 * references to this document given in [].
17 * 17 *
18 * This module doesn't support the 440LX, but it may be possible to 18 * 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,
189 enum mem_type mtype) 189 enum mem_type mtype)
190{ 190{
191 struct csrow_info *csrow; 191 struct csrow_info *csrow;
192 struct dimm_info *dimm;
192 int index; 193 int index;
193 u8 drbar, dramc; 194 u8 drbar, dramc;
194 u32 row_base, row_high_limit, row_high_limit_last; 195 u32 row_base, row_high_limit, row_high_limit_last;
@@ -197,6 +198,8 @@ static void i82443bxgx_init_csrows(struct mem_ctl_info *mci,
197 row_high_limit_last = 0; 198 row_high_limit_last = 0;
198 for (index = 0; index < mci->nr_csrows; index++) { 199 for (index = 0; index < mci->nr_csrows; index++) {
199 csrow = &mci->csrows[index]; 200 csrow = &mci->csrows[index];
201 dimm = csrow->channels[0].dimm;
202
200 pci_read_config_byte(pdev, I82443BXGX_DRB + index, &drbar); 203 pci_read_config_byte(pdev, I82443BXGX_DRB + index, &drbar);
201 debugf1("MC%d: %s: %s() Row=%d DRB = %#0x\n", 204 debugf1("MC%d: %s: %s() Row=%d DRB = %#0x\n",
202 mci->mc_idx, __FILE__, __func__, index, drbar); 205 mci->mc_idx, __FILE__, __func__, index, drbar);
@@ -219,12 +222,12 @@ static void i82443bxgx_init_csrows(struct mem_ctl_info *mci,
219 csrow->last_page = (row_high_limit >> PAGE_SHIFT) - 1; 222 csrow->last_page = (row_high_limit >> PAGE_SHIFT) - 1;
220 csrow->nr_pages = csrow->last_page - csrow->first_page + 1; 223 csrow->nr_pages = csrow->last_page - csrow->first_page + 1;
221 /* EAP reports in 4kilobyte granularity [61] */ 224 /* EAP reports in 4kilobyte granularity [61] */
222 csrow->grain = 1 << 12; 225 dimm->grain = 1 << 12;
223 csrow->mtype = mtype; 226 dimm->mtype = mtype;
224 /* I don't think 440BX can tell you device type? FIXME? */ 227 /* I don't think 440BX can tell you device type? FIXME? */
225 csrow->dtype = DEV_UNKNOWN; 228 dimm->dtype = DEV_UNKNOWN;
226 /* Mode is global to all rows on 440BX */ 229 /* Mode is global to all rows on 440BX */
227 csrow->edac_mode = edac_mode; 230 dimm->edac_mode = edac_mode;
228 row_high_limit_last = row_high_limit; 231 row_high_limit_last = row_high_limit;
229 } 232 }
230} 233}
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)
140 u16 value; 140 u16 value;
141 u32 cumul_size; 141 u32 cumul_size;
142 struct csrow_info *csrow; 142 struct csrow_info *csrow;
143 struct dimm_info *dimm;
143 int index; 144 int index;
144 145
145 pci_read_config_word(pdev, I82860_MCHCFG, &mchcfg_ddim); 146 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)
153 */ 154 */
154 for (index = 0; index < mci->nr_csrows; index++) { 155 for (index = 0; index < mci->nr_csrows; index++) {
155 csrow = &mci->csrows[index]; 156 csrow = &mci->csrows[index];
157 dimm = csrow->channels[0].dimm;
158
156 pci_read_config_word(pdev, I82860_GBA + index * 2, &value); 159 pci_read_config_word(pdev, I82860_GBA + index * 2, &value);
157 cumul_size = (value & I82860_GBA_MASK) << 160 cumul_size = (value & I82860_GBA_MASK) <<
158 (I82860_GBA_SHIFT - PAGE_SHIFT); 161 (I82860_GBA_SHIFT - PAGE_SHIFT);
@@ -166,10 +169,10 @@ static void i82860_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev)
166 csrow->last_page = cumul_size - 1; 169 csrow->last_page = cumul_size - 1;
167 csrow->nr_pages = cumul_size - last_cumul_size; 170 csrow->nr_pages = cumul_size - last_cumul_size;
168 last_cumul_size = cumul_size; 171 last_cumul_size = cumul_size;
169 csrow->grain = 1 << 12; /* I82860_EAP has 4KiB reolution */ 172 dimm->grain = 1 << 12; /* I82860_EAP has 4KiB reolution */
170 csrow->mtype = MEM_RMBS; 173 dimm->mtype = MEM_RMBS;
171 csrow->dtype = DEV_UNKNOWN; 174 dimm->dtype = DEV_UNKNOWN;
172 csrow->edac_mode = mchcfg_ddim ? EDAC_SECDED : EDAC_NONE; 175 dimm->edac_mode = mchcfg_ddim ? EDAC_SECDED : EDAC_NONE;
173 } 176 }
174} 177}
175 178
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,
342 void __iomem * ovrfl_window, u32 drc) 342 void __iomem * ovrfl_window, u32 drc)
343{ 343{
344 struct csrow_info *csrow; 344 struct csrow_info *csrow;
345 struct dimm_info *dimm;
346 unsigned nr_chans = dual_channel_active(drc) + 1;
345 unsigned long last_cumul_size; 347 unsigned long last_cumul_size;
346 u8 value; 348 u8 value;
347 u32 drc_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */ 349 u32 drc_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */
348 u32 cumul_size; 350 u32 cumul_size;
349 int index; 351 int index, j;
350 352
351 drc_ddim = (drc >> 18) & 0x1; 353 drc_ddim = (drc >> 18) & 0x1;
352 last_cumul_size = 0; 354 last_cumul_size = 0;
@@ -371,10 +373,15 @@ static void i82875p_init_csrows(struct mem_ctl_info *mci,
371 csrow->last_page = cumul_size - 1; 373 csrow->last_page = cumul_size - 1;
372 csrow->nr_pages = cumul_size - last_cumul_size; 374 csrow->nr_pages = cumul_size - last_cumul_size;
373 last_cumul_size = cumul_size; 375 last_cumul_size = cumul_size;
374 csrow->grain = 1 << 12; /* I82875P_EAP has 4KiB reolution */ 376
375 csrow->mtype = MEM_DDR; 377 for (j = 0; j < nr_chans; j++) {
376 csrow->dtype = DEV_UNKNOWN; 378 dimm = csrow->channels[j].dimm;
377 csrow->edac_mode = drc_ddim ? EDAC_SECDED : EDAC_NONE; 379
380 dimm->grain = 1 << 12; /* I82875P_EAP has 4KiB reolution */
381 dimm->mtype = MEM_DDR;
382 dimm->dtype = DEV_UNKNOWN;
383 dimm->edac_mode = drc_ddim ? EDAC_SECDED : EDAC_NONE;
384 }
378 } 385 }
379} 386}
380 387
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,
309 chan = (mci->csrows[row].nr_channels == 1) ? 0 : info->eap & 1; 309 chan = (mci->csrows[row].nr_channels == 1) ? 0 : info->eap & 1;
310 offst = info->eap 310 offst = info->eap
311 & ((1 << PAGE_SHIFT) - 311 & ((1 << PAGE_SHIFT) -
312 (1 << mci->csrows[row].grain)); 312 (1 << mci->csrows[row].channels[chan].dimm->grain));
313 313
314 if (info->errsts & 0x0002) 314 if (info->errsts & 0x0002)
315 edac_mc_handle_ue(mci, page, offst , row, "i82975x UE"); 315 edac_mc_handle_ue(mci, page, offst , row, "i82975x UE");
@@ -372,6 +372,8 @@ static void i82975x_init_csrows(struct mem_ctl_info *mci,
372 u8 value; 372 u8 value;
373 u32 cumul_size; 373 u32 cumul_size;
374 int index, chan; 374 int index, chan;
375 struct dimm_info *dimm;
376 enum dev_type dtype;
375 377
376 last_cumul_size = 0; 378 last_cumul_size = 0;
377 379
@@ -406,10 +408,17 @@ static void i82975x_init_csrows(struct mem_ctl_info *mci,
406 * [0-7] for single-channel; i.e. csrow->nr_channels = 1 408 * [0-7] for single-channel; i.e. csrow->nr_channels = 1
407 * [0-3] for dual-channel; i.e. csrow->nr_channels = 2 409 * [0-3] for dual-channel; i.e. csrow->nr_channels = 2
408 */ 410 */
409 for (chan = 0; chan < csrow->nr_channels; chan++) 411 dtype = i82975x_dram_type(mch_window, index);
412 for (chan = 0; chan < csrow->nr_channels; chan++) {
413 dimm = mci->csrows[index].channels[chan].dimm;
410 strncpy(csrow->channels[chan].dimm->label, 414 strncpy(csrow->channels[chan].dimm->label,
411 labels[(index >> 1) + (chan * 2)], 415 labels[(index >> 1) + (chan * 2)],
412 EDAC_MC_LABEL_LEN); 416 EDAC_MC_LABEL_LEN);
417 dimm->grain = 1 << 7; /* 128Byte cache-line resolution */
418 dimm->dtype = i82975x_dram_type(mch_window, index);
419 dimm->mtype = MEM_DDR2; /* I82975x supports only DDR2 */
420 dimm->edac_mode = EDAC_SECDED; /* only supported */
421 }
413 422
414 if (cumul_size == last_cumul_size) 423 if (cumul_size == last_cumul_size)
415 continue; /* not populated */ 424 continue; /* not populated */
@@ -418,10 +427,6 @@ static void i82975x_init_csrows(struct mem_ctl_info *mci,
418 csrow->last_page = cumul_size - 1; 427 csrow->last_page = cumul_size - 1;
419 csrow->nr_pages = cumul_size - last_cumul_size; 428 csrow->nr_pages = cumul_size - last_cumul_size;
420 last_cumul_size = cumul_size; 429 last_cumul_size = cumul_size;
421 csrow->grain = 1 << 7; /* 128Byte cache-line resolution */
422 csrow->mtype = MEM_DDR2; /* I82975x supports only DDR2 */
423 csrow->dtype = i82975x_dram_type(mch_window, index);
424 csrow->edac_mode = EDAC_SECDED; /* only supported */
425 } 430 }
426} 431}
427 432
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)
883{ 883{
884 struct mpc85xx_mc_pdata *pdata = mci->pvt_info; 884 struct mpc85xx_mc_pdata *pdata = mci->pvt_info;
885 struct csrow_info *csrow; 885 struct csrow_info *csrow;
886 struct dimm_info *dimm;
886 u32 sdram_ctl; 887 u32 sdram_ctl;
887 u32 sdtype; 888 u32 sdtype;
888 enum mem_type mtype; 889 enum mem_type mtype;
@@ -929,6 +930,8 @@ static void __devinit mpc85xx_init_csrows(struct mem_ctl_info *mci)
929 u32 end; 930 u32 end;
930 931
931 csrow = &mci->csrows[index]; 932 csrow = &mci->csrows[index];
933 dimm = csrow->channels[0].dimm;
934
932 cs_bnds = in_be32(pdata->mc_vbase + MPC85XX_MC_CS_BNDS_0 + 935 cs_bnds = in_be32(pdata->mc_vbase + MPC85XX_MC_CS_BNDS_0 +
933 (index * MPC85XX_MC_CS_BNDS_OFS)); 936 (index * MPC85XX_MC_CS_BNDS_OFS));
934 937
@@ -945,12 +948,12 @@ static void __devinit mpc85xx_init_csrows(struct mem_ctl_info *mci)
945 csrow->first_page = start; 948 csrow->first_page = start;
946 csrow->last_page = end; 949 csrow->last_page = end;
947 csrow->nr_pages = end + 1 - start; 950 csrow->nr_pages = end + 1 - start;
948 csrow->grain = 8; 951 dimm->grain = 8;
949 csrow->mtype = mtype; 952 dimm->mtype = mtype;
950 csrow->dtype = DEV_UNKNOWN; 953 dimm->dtype = DEV_UNKNOWN;
951 if (sdram_ctl & DSC_X32_EN) 954 if (sdram_ctl & DSC_X32_EN)
952 csrow->dtype = DEV_X32; 955 dimm->dtype = DEV_X32;
953 csrow->edac_mode = EDAC_SECDED; 956 dimm->edac_mode = EDAC_SECDED;
954 } 957 }
955} 958}
956 959
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,
656 struct mv64x60_mc_pdata *pdata) 656 struct mv64x60_mc_pdata *pdata)
657{ 657{
658 struct csrow_info *csrow; 658 struct csrow_info *csrow;
659 struct dimm_info *dimm;
660
659 u32 devtype; 661 u32 devtype;
660 u32 ctl; 662 u32 ctl;
661 663
@@ -664,30 +666,30 @@ static void mv64x60_init_csrows(struct mem_ctl_info *mci,
664 ctl = in_le32(pdata->mc_vbase + MV64X60_SDRAM_CONFIG); 666 ctl = in_le32(pdata->mc_vbase + MV64X60_SDRAM_CONFIG);
665 667
666 csrow = &mci->csrows[0]; 668 csrow = &mci->csrows[0];
667 csrow->first_page = 0; 669 dimm = csrow->channels[0].dimm;
668 csrow->nr_pages = pdata->total_mem >> PAGE_SHIFT; 670 csrow->nr_pages = pdata->total_mem >> PAGE_SHIFT;
669 csrow->last_page = csrow->first_page + csrow->nr_pages - 1; 671 csrow->last_page = csrow->first_page + csrow->nr_pages - 1;
670 csrow->grain = 8; 672 dimm->grain = 8;
671 673
672 csrow->mtype = (ctl & MV64X60_SDRAM_REGISTERED) ? MEM_RDDR : MEM_DDR; 674 dimm->mtype = (ctl & MV64X60_SDRAM_REGISTERED) ? MEM_RDDR : MEM_DDR;
673 675
674 devtype = (ctl >> 20) & 0x3; 676 devtype = (ctl >> 20) & 0x3;
675 switch (devtype) { 677 switch (devtype) {
676 case 0x0: 678 case 0x0:
677 csrow->dtype = DEV_X32; 679 dimm->dtype = DEV_X32;
678 break; 680 break;
679 case 0x2: /* could be X8 too, but no way to tell */ 681 case 0x2: /* could be X8 too, but no way to tell */
680 csrow->dtype = DEV_X16; 682 dimm->dtype = DEV_X16;
681 break; 683 break;
682 case 0x3: 684 case 0x3:
683 csrow->dtype = DEV_X4; 685 dimm->dtype = DEV_X4;
684 break; 686 break;
685 default: 687 default:
686 csrow->dtype = DEV_UNKNOWN; 688 dimm->dtype = DEV_UNKNOWN;
687 break; 689 break;
688 } 690 }
689 691
690 csrow->edac_mode = EDAC_SECDED; 692 dimm->edac_mode = EDAC_SECDED;
691} 693}
692 694
693static int __devinit mv64x60_mc_err_probe(struct platform_device *pdev) 695static 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,
135 enum edac_type edac_mode) 135 enum edac_type edac_mode)
136{ 136{
137 struct csrow_info *csrow; 137 struct csrow_info *csrow;
138 struct dimm_info *dimm;
138 u32 rankcfg; 139 u32 rankcfg;
139 int index; 140 int index;
140 141
141 for (index = 0; index < mci->nr_csrows; index++) { 142 for (index = 0; index < mci->nr_csrows; index++) {
142 csrow = &mci->csrows[index]; 143 csrow = &mci->csrows[index];
144 dimm = csrow->channels[0].dimm;
143 145
144 pci_read_config_dword(pdev, 146 pci_read_config_dword(pdev,
145 MCDRAM_RANKCFG + (index * 12), 147 MCDRAM_RANKCFG + (index * 12),
@@ -177,10 +179,10 @@ static int pasemi_edac_init_csrows(struct mem_ctl_info *mci,
177 csrow->last_page = csrow->first_page + csrow->nr_pages - 1; 179 csrow->last_page = csrow->first_page + csrow->nr_pages - 1;
178 last_page_in_mmc += csrow->nr_pages; 180 last_page_in_mmc += csrow->nr_pages;
179 csrow->page_mask = 0; 181 csrow->page_mask = 0;
180 csrow->grain = PASEMI_EDAC_ERROR_GRAIN; 182 dimm->grain = PASEMI_EDAC_ERROR_GRAIN;
181 csrow->mtype = MEM_DDR; 183 dimm->mtype = MEM_DDR;
182 csrow->dtype = DEV_UNKNOWN; 184 dimm->dtype = DEV_UNKNOWN;
183 csrow->edac_mode = edac_mode; 185 dimm->edac_mode = edac_mode;
184 } 186 }
185 return 0; 187 return 0;
186} 188}
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)
895 enum mem_type mtype; 895 enum mem_type mtype;
896 enum dev_type dtype; 896 enum dev_type dtype;
897 enum edac_type edac_mode; 897 enum edac_type edac_mode;
898 int row; 898 int row, j;
899 u32 mbxcf, size; 899 u32 mbxcf, size;
900 static u32 ppc4xx_last_page; 900 static u32 ppc4xx_last_page;
901 901
@@ -975,15 +975,18 @@ ppc4xx_edac_init_csrows(struct mem_ctl_info *mci, u32 mcopt1)
975 * possible values would be the PLB width (16), the 975 * possible values would be the PLB width (16), the
976 * page size (PAGE_SIZE) or the memory width (2 or 4). 976 * page size (PAGE_SIZE) or the memory width (2 or 4).
977 */ 977 */
978 for (j = 0; j < csi->nr_channels; j++) {
979 struct dimm_info *dimm = csi->channels[j].dimm;
978 980
979 csi->grain = 1; 981 dimm->grain = 1;
980 982
981 csi->mtype = mtype; 983 dimm->mtype = mtype;
982 csi->dtype = dtype; 984 dimm->dtype = dtype;
983 985
984 csi->edac_mode = edac_mode; 986 dimm->edac_mode = edac_mode;
985 987
986 ppc4xx_last_page += csi->nr_pages; 988 ppc4xx_last_page += csi->nr_pages;
989 }
987 } 990 }
988 991
989 done: 992 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,
216 u8 dramcr) 216 u8 dramcr)
217{ 217{
218 struct csrow_info *csrow; 218 struct csrow_info *csrow;
219 struct dimm_info *dimm;
219 int index; 220 int index;
220 u8 drbar; /* SDRAM Row Boundary Address Register */ 221 u8 drbar; /* SDRAM Row Boundary Address Register */
221 u32 row_high_limit, row_high_limit_last; 222 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,
227 228
228 for (index = 0; index < mci->nr_csrows; index++) { 229 for (index = 0; index < mci->nr_csrows; index++) {
229 csrow = &mci->csrows[index]; 230 csrow = &mci->csrows[index];
231 dimm = csrow->channels[0].dimm;
230 232
231 /* find the DRAM Chip Select Base address and mask */ 233 /* find the DRAM Chip Select Base address and mask */
232 pci_read_config_byte(pdev, R82600_DRBA + index, &drbar); 234 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,
250 csrow->nr_pages = csrow->last_page - csrow->first_page + 1; 252 csrow->nr_pages = csrow->last_page - csrow->first_page + 1;
251 /* Error address is top 19 bits - so granularity is * 253 /* Error address is top 19 bits - so granularity is *
252 * 14 bits */ 254 * 14 bits */
253 csrow->grain = 1 << 14; 255 dimm->grain = 1 << 14;
254 csrow->mtype = reg_sdram ? MEM_RDDR : MEM_DDR; 256 dimm->mtype = reg_sdram ? MEM_RDDR : MEM_DDR;
255 /* FIXME - check that this is unknowable with this chipset */ 257 /* FIXME - check that this is unknowable with this chipset */
256 csrow->dtype = DEV_UNKNOWN; 258 dimm->dtype = DEV_UNKNOWN;
257 259
258 /* Mode is global on 82600 */ 260 /* Mode is global on 82600 */
259 csrow->edac_mode = ecc_on ? EDAC_SECDED : EDAC_NONE; 261 dimm->edac_mode = ecc_on ? EDAC_SECDED : EDAC_NONE;
260 row_high_limit_last = row_high_limit; 262 row_high_limit_last = row_high_limit;
261 } 263 }
262} 264}
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,
551 return 0; 551 return 0;
552} 552}
553 553
554static int get_dimm_config(const struct mem_ctl_info *mci) 554static int get_dimm_config(struct mem_ctl_info *mci)
555{ 555{
556 struct sbridge_pvt *pvt = mci->pvt_info; 556 struct sbridge_pvt *pvt = mci->pvt_info;
557 struct csrow_info *csr; 557 struct csrow_info *csr;
@@ -561,6 +561,7 @@ static int get_dimm_config(const struct mem_ctl_info *mci)
561 u32 reg; 561 u32 reg;
562 enum edac_type mode; 562 enum edac_type mode;
563 enum mem_type mtype; 563 enum mem_type mtype;
564 struct dimm_info *dimm;
564 565
565 pci_read_config_dword(pvt->pci_br, SAD_TARGET, &reg); 566 pci_read_config_dword(pvt->pci_br, SAD_TARGET, &reg);
566 pvt->sbridge_dev->source_id = SOURCE_ID(reg); 567 pvt->sbridge_dev->source_id = SOURCE_ID(reg);
@@ -612,6 +613,7 @@ static int get_dimm_config(const struct mem_ctl_info *mci)
612 /* On all supported DDR3 DIMM types, there are 8 banks available */ 613 /* On all supported DDR3 DIMM types, there are 8 banks available */
613 banks = 8; 614 banks = 8;
614 615
616 dimm = mci->dimms;
615 for (i = 0; i < NUM_CHANNELS; i++) { 617 for (i = 0; i < NUM_CHANNELS; i++) {
616 u32 mtr; 618 u32 mtr;
617 619
@@ -634,29 +636,30 @@ static int get_dimm_config(const struct mem_ctl_info *mci)
634 pvt->sbridge_dev->mc, i, j, 636 pvt->sbridge_dev->mc, i, j,
635 size, npages, 637 size, npages,
636 banks, ranks, rows, cols); 638 banks, ranks, rows, cols);
637 csr = &mci->csrows[csrow];
638 639
640 /*
641 * Fake stuff. This controller doesn't see
642 * csrows.
643 */
644 csr = &mci->csrows[csrow];
639 csr->first_page = last_page; 645 csr->first_page = last_page;
640 csr->last_page = last_page + npages - 1; 646 csr->last_page = last_page + npages - 1;
641 csr->page_mask = 0UL; /* Unused */
642 csr->nr_pages = npages; 647 csr->nr_pages = npages;
643 csr->grain = 32;
644 csr->csrow_idx = csrow; 648 csr->csrow_idx = csrow;
645 csr->dtype = (banks == 8) ? DEV_X8 : DEV_X4;
646 csr->ce_count = 0;
647 csr->ue_count = 0;
648 csr->mtype = mtype;
649 csr->edac_mode = mode;
650 csr->nr_channels = 1; 649 csr->nr_channels = 1;
651 csr->channels[0].chan_idx = i; 650 csr->channels[0].chan_idx = i;
652 csr->channels[0].ce_count = 0;
653 pvt->csrow_map[i][j] = csrow; 651 pvt->csrow_map[i][j] = csrow;
654 snprintf(csr->channels[0].dimm->label,
655 sizeof(csr->channels[0].dimm->label),
656 "CPU_SrcID#%u_Channel#%u_DIMM#%u",
657 pvt->sbridge_dev->source_id, i, j);
658 last_page += npages; 652 last_page += npages;
659 csrow++; 653 csrow++;
654
655 csr->channels[0].dimm = dimm;
656 dimm->grain = 32;
657 dimm->dtype = (banks == 8) ? DEV_X8 : DEV_X4;
658 dimm->mtype = mtype;
659 dimm->edac_mode = mode;
660 snprintf(dimm->label, sizeof(dimm->label),
661 "CPU_SrcID#%u_Channel#%u_DIMM#%u",
662 pvt->sbridge_dev->source_id, i, j);
660 } 663 }
661 } 664 }
662 } 665 }
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)
84 struct csrow_info *csrow = &mci->csrows[0]; 84 struct csrow_info *csrow = &mci->csrows[0];
85 struct tile_edac_priv *priv = mci->pvt_info; 85 struct tile_edac_priv *priv = mci->pvt_info;
86 struct mshim_mem_info mem_info; 86 struct mshim_mem_info mem_info;
87 struct dimm_info *dimm = csrow->channels[0].dimm;
87 88
88 if (hv_dev_pread(priv->hv_devhdl, 0, (HV_VirtAddr)&mem_info, 89 if (hv_dev_pread(priv->hv_devhdl, 0, (HV_VirtAddr)&mem_info,
89 sizeof(struct mshim_mem_info), MSHIM_MEM_INFO_OFF) != 90 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)
93 } 94 }
94 95
95 if (mem_info.mem_ecc) 96 if (mem_info.mem_ecc)
96 csrow->edac_mode = EDAC_SECDED; 97 dimm->edac_mode = EDAC_SECDED;
97 else 98 else
98 csrow->edac_mode = EDAC_NONE; 99 dimm->edac_mode = EDAC_NONE;
99 switch (mem_info.mem_type) { 100 switch (mem_info.mem_type) {
100 case DDR2: 101 case DDR2:
101 csrow->mtype = MEM_DDR2; 102 dimm->mtype = MEM_DDR2;
102 break; 103 break;
103 104
104 case DDR3: 105 case DDR3:
105 csrow->mtype = MEM_DDR3; 106 dimm->mtype = MEM_DDR3;
106 break; 107 break;
107 108
108 default: 109 default:
@@ -112,8 +113,8 @@ static int __devinit tile_edac_init_csrows(struct mem_ctl_info *mci)
112 csrow->first_page = 0; 113 csrow->first_page = 0;
113 csrow->nr_pages = mem_info.mem_size >> PAGE_SHIFT; 114 csrow->nr_pages = mem_info.mem_size >> PAGE_SHIFT;
114 csrow->last_page = csrow->first_page + csrow->nr_pages - 1; 115 csrow->last_page = csrow->first_page + csrow->nr_pages - 1;
115 csrow->grain = TILE_EDAC_ERROR_GRAIN; 116 dimm->grain = TILE_EDAC_ERROR_GRAIN;
116 csrow->dtype = DEV_UNKNOWN; 117 dimm->dtype = DEV_UNKNOWN;
117 118
118 return 0; 119 return 0;
119} 120}
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(
317static int x38_probe1(struct pci_dev *pdev, int dev_idx) 317static int x38_probe1(struct pci_dev *pdev, int dev_idx)
318{ 318{
319 int rc; 319 int rc;
320 int i; 320 int i, j;
321 struct mem_ctl_info *mci = NULL; 321 struct mem_ctl_info *mci = NULL;
322 unsigned long last_page; 322 unsigned long last_page;
323 u16 drbs[X38_CHANNELS][X38_RANKS_PER_CHANNEL]; 323 u16 drbs[X38_CHANNELS][X38_RANKS_PER_CHANNEL];
@@ -372,20 +372,21 @@ static int x38_probe1(struct pci_dev *pdev, int dev_idx)
372 i / X38_RANKS_PER_CHANNEL, 372 i / X38_RANKS_PER_CHANNEL,
373 i % X38_RANKS_PER_CHANNEL); 373 i % X38_RANKS_PER_CHANNEL);
374 374
375 if (nr_pages == 0) { 375 if (nr_pages == 0)
376 csrow->mtype = MEM_EMPTY;
377 continue; 376 continue;
378 }
379 377
380 csrow->first_page = last_page + 1; 378 csrow->first_page = last_page + 1;
381 last_page += nr_pages; 379 last_page += nr_pages;
382 csrow->last_page = last_page; 380 csrow->last_page = last_page;
383 csrow->nr_pages = nr_pages; 381 csrow->nr_pages = nr_pages;
384 382
385 csrow->grain = nr_pages << PAGE_SHIFT; 383 for (j = 0; j < x38_channel_num; j++) {
386 csrow->mtype = MEM_DDR2; 384 struct dimm_info *dimm = csrow->channels[j].dimm;
387 csrow->dtype = DEV_UNKNOWN; 385 dimm->grain = nr_pages << PAGE_SHIFT;
388 csrow->edac_mode = EDAC_UNKNOWN; 386 dimm->mtype = MEM_DDR2;
387 dimm->dtype = DEV_UNKNOWN;
388 dimm->edac_mode = EDAC_UNKNOWN;
389 }
389 } 390 }
390 391
391 x38_clear_error_info(mci); 392 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 {
318 unsigned memory_controller; 318 unsigned memory_controller;
319 unsigned csrow; 319 unsigned csrow;
320 unsigned csrow_channel; 320 unsigned csrow_channel;
321
322 u32 grain; /* granularity of reported error in bytes */
323 enum dev_type dtype; /* memory device type */
324 enum mem_type mtype; /* memory dimm type */
325 enum edac_type edac_mode; /* EDAC mode for this dimm */
326
327 u32 ce_count; /* Correctable Errors for this dimm */
321}; 328};
322 329
323/** 330/**
@@ -343,19 +350,17 @@ struct rank_info {
343}; 350};
344 351
345struct csrow_info { 352struct csrow_info {
346 unsigned long first_page; /* first page number in dimm */ 353 unsigned long first_page; /* first page number in csrow */
347 unsigned long last_page; /* last page number in dimm */ 354 unsigned long last_page; /* last page number in csrow */
355 u32 nr_pages; /* number of pages in csrow */
348 unsigned long page_mask; /* used for interleaving - 356 unsigned long page_mask; /* used for interleaving -
349 * 0UL for non intlv 357 * 0UL for non intlv
350 */ 358 */
351 u32 nr_pages; /* number of pages in csrow */ 359 int csrow_idx; /* the chip-select row */
352 u32 grain; /* granularity of reported error in bytes */ 360
353 int csrow_idx; /* the chip-select row */
354 enum dev_type dtype; /* memory device type */
355 u32 ue_count; /* Uncorrectable Errors for this csrow */ 361 u32 ue_count; /* Uncorrectable Errors for this csrow */
356 u32 ce_count; /* Correctable Errors for this csrow */ 362 u32 ce_count; /* Correctable Errors for this csrow */
357 enum mem_type mtype; /* memory csrow type */ 363
358 enum edac_type edac_mode; /* EDAC mode for this csrow */
359 struct mem_ctl_info *mci; /* the parent */ 364 struct mem_ctl_info *mci; /* the parent */
360 365
361 struct kobject kobj; /* sysfs kobject for this csrow */ 366 struct kobject kobj; /* sysfs kobject for this csrow */