aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/edac/cpc925_edac.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/edac/cpc925_edac.c')
-rw-r--r--drivers/edac/cpc925_edac.c91
1 files changed, 55 insertions, 36 deletions
diff --git a/drivers/edac/cpc925_edac.c b/drivers/edac/cpc925_edac.c
index a774c0ddaf5b..e22030a9de66 100644
--- a/drivers/edac/cpc925_edac.c
+++ b/drivers/edac/cpc925_edac.c
@@ -329,9 +329,10 @@ 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, nr_pages, last_nr_pages = 0;
335 336
336 get_total_mem(pdata); 337 get_total_mem(pdata);
337 338
@@ -350,36 +351,41 @@ static void cpc925_init_csrows(struct mem_ctl_info *mci)
350 351
351 row_size = bba * (1UL << 28); /* 256M */ 352 row_size = bba * (1UL << 28); /* 256M */
352 csrow->first_page = last_nr_pages; 353 csrow->first_page = last_nr_pages;
353 csrow->nr_pages = row_size >> PAGE_SHIFT; 354 nr_pages = row_size >> PAGE_SHIFT;
354 csrow->last_page = csrow->first_page + csrow->nr_pages - 1; 355 csrow->last_page = csrow->first_page + 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
360 switch (csrow->nr_channels) { 361 dimm->nr_pages = nr_pages / csrow->nr_channels;
361 case 1: /* Single channel */ 362 dimm->mtype = MEM_RDDR;
362 csrow->grain = 32; /* four-beat burst of 32 bytes */ 363 dimm->edac_mode = EDAC_SECDED;
363 break; 364
364 case 2: /* Dual channel */ 365 switch (csrow->nr_channels) {
365 default: 366 case 1: /* Single channel */
366 csrow->grain = 64; /* four-beat burst of 64 bytes */ 367 dimm->grain = 32; /* four-beat burst of 32 bytes */
367 break; 368 break;
368 } 369 case 2: /* Dual channel */
369 370 default:
370 switch ((mbmr & MBMR_MODE_MASK) >> MBMR_MODE_SHIFT) { 371 dimm->grain = 64; /* four-beat burst of 64 bytes */
371 case 6: /* 0110, no way to differentiate X8 VS X16 */ 372 break;
372 case 5: /* 0101 */ 373 }
373 case 8: /* 1000 */ 374
374 csrow->dtype = DEV_X16; 375 switch ((mbmr & MBMR_MODE_MASK) >> MBMR_MODE_SHIFT) {
375 break; 376 case 6: /* 0110, no way to differentiate X8 VS X16 */
376 case 7: /* 0111 */ 377 case 5: /* 0101 */
377 case 9: /* 1001 */ 378 case 8: /* 1000 */
378 csrow->dtype = DEV_X8; 379 dimm->dtype = DEV_X16;
379 break; 380 break;
380 default: 381 case 7: /* 0111 */
381 csrow->dtype = DEV_UNKNOWN; 382 case 9: /* 1001 */
382 break; 383 dimm->dtype = DEV_X8;
384 break;
385 default:
386 dimm->dtype = DEV_UNKNOWN;
387 break;
388 }
383 } 389 }
384 } 390 }
385} 391}
@@ -549,13 +555,18 @@ static void cpc925_mc_check(struct mem_ctl_info *mci)
549 if (apiexcp & CECC_EXCP_DETECTED) { 555 if (apiexcp & CECC_EXCP_DETECTED) {
550 cpc925_mc_printk(mci, KERN_INFO, "DRAM CECC Fault\n"); 556 cpc925_mc_printk(mci, KERN_INFO, "DRAM CECC Fault\n");
551 channel = cpc925_mc_find_channel(mci, syndrome); 557 channel = cpc925_mc_find_channel(mci, syndrome);
552 edac_mc_handle_ce(mci, pfn, offset, syndrome, 558 edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci,
553 csrow, channel, mci->ctl_name); 559 pfn, offset, syndrome,
560 csrow, channel, -1,
561 mci->ctl_name, "", NULL);
554 } 562 }
555 563
556 if (apiexcp & UECC_EXCP_DETECTED) { 564 if (apiexcp & UECC_EXCP_DETECTED) {
557 cpc925_mc_printk(mci, KERN_INFO, "DRAM UECC Fault\n"); 565 cpc925_mc_printk(mci, KERN_INFO, "DRAM UECC Fault\n");
558 edac_mc_handle_ue(mci, pfn, offset, csrow, mci->ctl_name); 566 edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci,
567 pfn, offset, 0,
568 csrow, -1, -1,
569 mci->ctl_name, "", NULL);
559 } 570 }
560 571
561 cpc925_mc_printk(mci, KERN_INFO, "Dump registers:\n"); 572 cpc925_mc_printk(mci, KERN_INFO, "Dump registers:\n");
@@ -927,6 +938,7 @@ static int __devinit cpc925_probe(struct platform_device *pdev)
927{ 938{
928 static int edac_mc_idx; 939 static int edac_mc_idx;
929 struct mem_ctl_info *mci; 940 struct mem_ctl_info *mci;
941 struct edac_mc_layer layers[2];
930 void __iomem *vbase; 942 void __iomem *vbase;
931 struct cpc925_mc_pdata *pdata; 943 struct cpc925_mc_pdata *pdata;
932 struct resource *r; 944 struct resource *r;
@@ -962,9 +974,16 @@ static int __devinit cpc925_probe(struct platform_device *pdev)
962 goto err2; 974 goto err2;
963 } 975 }
964 976
965 nr_channels = cpc925_mc_get_channels(vbase); 977 nr_channels = cpc925_mc_get_channels(vbase) + 1;
966 mci = edac_mc_alloc(sizeof(struct cpc925_mc_pdata), 978
967 CPC925_NR_CSROWS, nr_channels + 1, edac_mc_idx); 979 layers[0].type = EDAC_MC_LAYER_CHIP_SELECT;
980 layers[0].size = CPC925_NR_CSROWS;
981 layers[0].is_virt_csrow = true;
982 layers[1].type = EDAC_MC_LAYER_CHANNEL;
983 layers[1].size = nr_channels;
984 layers[1].is_virt_csrow = false;
985 mci = edac_mc_alloc(edac_mc_idx, ARRAY_SIZE(layers), layers,
986 sizeof(struct cpc925_mc_pdata));
968 if (!mci) { 987 if (!mci) {
969 cpc925_printk(KERN_ERR, "No memory for mem_ctl_info\n"); 988 cpc925_printk(KERN_ERR, "No memory for mem_ctl_info\n");
970 res = -ENOMEM; 989 res = -ENOMEM;