diff options
Diffstat (limited to 'drivers/edac/cpc925_edac.c')
-rw-r--r-- | drivers/edac/cpc925_edac.c | 91 |
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; |