diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-04-16 14:09:52 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-05-28 18:11:01 -0400 |
commit | d1afaa0a6e578964eeb48a3ab207072293367041 (patch) | |
tree | 49fb52005af712833b12e5da67dd64e3d1e6b689 /drivers/edac/i5100_edac.c | |
parent | 702df64053e440344ccb53035cb6959f17a97151 (diff) |
i5100_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.
Cc: "Niklas Söderlund" <niklas.soderlund@ericsson.com>
Cc: Borislav Petkov <borislav.petkov@amd.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/edac/i5100_edac.c')
-rw-r--r-- | drivers/edac/i5100_edac.c | 90 |
1 files changed, 40 insertions, 50 deletions
diff --git a/drivers/edac/i5100_edac.c b/drivers/edac/i5100_edac.c index c08e94064ef6..691cd49aa169 100644 --- a/drivers/edac/i5100_edac.c +++ b/drivers/edac/i5100_edac.c | |||
@@ -14,6 +14,11 @@ | |||
14 | * rows for each respective channel are laid out one after another, | 14 | * rows for each respective channel are laid out one after another, |
15 | * the first half belonging to channel 0, the second half belonging | 15 | * the first half belonging to channel 0, the second half belonging |
16 | * to channel 1. | 16 | * to channel 1. |
17 | * | ||
18 | * This driver is for DDR2 DIMMs, and it uses chip select to select among the | ||
19 | * several ranks. However, instead of showing memories as ranks, it outputs | ||
20 | * them as DIMM's. An internal table creates the association between ranks | ||
21 | * and DIMM's. | ||
17 | */ | 22 | */ |
18 | #include <linux/module.h> | 23 | #include <linux/module.h> |
19 | #include <linux/init.h> | 24 | #include <linux/init.h> |
@@ -410,14 +415,6 @@ static int i5100_csrow_to_chan(const struct mem_ctl_info *mci, int csrow) | |||
410 | return csrow / priv->ranksperchan; | 415 | return csrow / priv->ranksperchan; |
411 | } | 416 | } |
412 | 417 | ||
413 | static unsigned i5100_rank_to_csrow(const struct mem_ctl_info *mci, | ||
414 | int chan, int rank) | ||
415 | { | ||
416 | const struct i5100_priv *priv = mci->pvt_info; | ||
417 | |||
418 | return chan * priv->ranksperchan + rank; | ||
419 | } | ||
420 | |||
421 | static void i5100_handle_ce(struct mem_ctl_info *mci, | 418 | static void i5100_handle_ce(struct mem_ctl_info *mci, |
422 | int chan, | 419 | int chan, |
423 | unsigned bank, | 420 | unsigned bank, |
@@ -427,21 +424,17 @@ static void i5100_handle_ce(struct mem_ctl_info *mci, | |||
427 | unsigned ras, | 424 | unsigned ras, |
428 | const char *msg) | 425 | const char *msg) |
429 | { | 426 | { |
430 | const int csrow = i5100_rank_to_csrow(mci, chan, rank); | 427 | char detail[80]; |
431 | char *label = NULL; | ||
432 | 428 | ||
433 | if (mci->csrows[csrow].channels[0].dimm) | 429 | /* Form out message */ |
434 | label = mci->csrows[csrow].channels[0].dimm->label; | 430 | snprintf(detail, sizeof(detail), |
431 | "bank %u, cas %u, ras %u\n", | ||
432 | bank, cas, ras); | ||
435 | 433 | ||
436 | printk(KERN_ERR | 434 | edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, |
437 | "CE chan %d, bank %u, rank %u, syndrome 0x%lx, " | 435 | 0, 0, syndrome, |
438 | "cas %u, ras %u, csrow %u, label \"%s\": %s\n", | 436 | chan, rank, -1, |
439 | chan, bank, rank, syndrome, cas, ras, | 437 | msg, detail, NULL); |
440 | csrow, label, msg); | ||
441 | |||
442 | mci->ce_count++; | ||
443 | mci->csrows[csrow].ce_count++; | ||
444 | mci->csrows[csrow].channels[0].ce_count++; | ||
445 | } | 438 | } |
446 | 439 | ||
447 | static void i5100_handle_ue(struct mem_ctl_info *mci, | 440 | static void i5100_handle_ue(struct mem_ctl_info *mci, |
@@ -453,20 +446,17 @@ static void i5100_handle_ue(struct mem_ctl_info *mci, | |||
453 | unsigned ras, | 446 | unsigned ras, |
454 | const char *msg) | 447 | const char *msg) |
455 | { | 448 | { |
456 | const int csrow = i5100_rank_to_csrow(mci, chan, rank); | 449 | char detail[80]; |
457 | char *label = NULL; | ||
458 | |||
459 | if (mci->csrows[csrow].channels[0].dimm) | ||
460 | label = mci->csrows[csrow].channels[0].dimm->label; | ||
461 | 450 | ||
462 | printk(KERN_ERR | 451 | /* Form out message */ |
463 | "UE chan %d, bank %u, rank %u, syndrome 0x%lx, " | 452 | snprintf(detail, sizeof(detail), |
464 | "cas %u, ras %u, csrow %u, label \"%s\": %s\n", | 453 | "bank %u, cas %u, ras %u\n", |
465 | chan, bank, rank, syndrome, cas, ras, | 454 | bank, cas, ras); |
466 | csrow, label, msg); | ||
467 | 455 | ||
468 | mci->ue_count++; | 456 | edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, |
469 | mci->csrows[csrow].ue_count++; | 457 | 0, 0, syndrome, |
458 | chan, rank, -1, | ||
459 | msg, detail, NULL); | ||
470 | } | 460 | } |
471 | 461 | ||
472 | static void i5100_read_log(struct mem_ctl_info *mci, int chan, | 462 | static void i5100_read_log(struct mem_ctl_info *mci, int chan, |
@@ -843,11 +833,10 @@ static void __devinit i5100_init_interleaving(struct pci_dev *pdev, | |||
843 | static void __devinit i5100_init_csrows(struct mem_ctl_info *mci) | 833 | static void __devinit i5100_init_csrows(struct mem_ctl_info *mci) |
844 | { | 834 | { |
845 | int i; | 835 | int i; |
846 | unsigned long total_pages = 0UL; | ||
847 | struct i5100_priv *priv = mci->pvt_info; | 836 | struct i5100_priv *priv = mci->pvt_info; |
848 | struct dimm_info *dimm; | ||
849 | 837 | ||
850 | for (i = 0; i < mci->nr_csrows; i++) { | 838 | for (i = 0; i < mci->tot_dimms; i++) { |
839 | struct dimm_info *dimm; | ||
851 | const unsigned long npages = i5100_npages(mci, i); | 840 | const unsigned long npages = i5100_npages(mci, i); |
852 | const unsigned chan = i5100_csrow_to_chan(mci, i); | 841 | const unsigned chan = i5100_csrow_to_chan(mci, i); |
853 | const unsigned rank = i5100_csrow_to_rank(mci, i); | 842 | const unsigned rank = i5100_csrow_to_rank(mci, i); |
@@ -855,30 +844,23 @@ static void __devinit i5100_init_csrows(struct mem_ctl_info *mci) | |||
855 | if (!npages) | 844 | if (!npages) |
856 | continue; | 845 | continue; |
857 | 846 | ||
858 | /* | 847 | dimm = EDAC_DIMM_PTR(mci->layers, mci->dimms, mci->n_layers, |
859 | * FIXME: these two are totally bogus -- I don't see how to | 848 | chan, rank, 0); |
860 | * map them correctly to this structure... | ||
861 | */ | ||
862 | mci->csrows[i].csrow_idx = i; | ||
863 | mci->csrows[i].mci = mci; | ||
864 | mci->csrows[i].nr_channels = 1; | ||
865 | mci->csrows[i].channels[0].csrow = mci->csrows + i; | ||
866 | total_pages += npages; | ||
867 | 849 | ||
868 | dimm = mci->csrows[i].channels[0].dimm; | ||
869 | dimm->nr_pages = npages; | 850 | dimm->nr_pages = npages; |
870 | if (npages) { | 851 | if (npages) { |
871 | total_pages += npages; | ||
872 | |||
873 | dimm->grain = 32; | 852 | dimm->grain = 32; |
874 | dimm->dtype = (priv->mtr[chan][rank].width == 4) ? | 853 | dimm->dtype = (priv->mtr[chan][rank].width == 4) ? |
875 | DEV_X4 : DEV_X8; | 854 | DEV_X4 : DEV_X8; |
876 | dimm->mtype = MEM_RDDR2; | 855 | dimm->mtype = MEM_RDDR2; |
877 | dimm->edac_mode = EDAC_SECDED; | 856 | dimm->edac_mode = EDAC_SECDED; |
878 | snprintf(dimm->label, sizeof(dimm->label), | 857 | snprintf(dimm->label, sizeof(dimm->label), |
879 | "DIMM%u", | 858 | "DIMM%u", |
880 | i5100_rank_to_slot(mci, chan, rank)); | 859 | i5100_rank_to_slot(mci, chan, rank)); |
881 | } | 860 | } |
861 | |||
862 | debugf2("dimm channel %d, rank %d, size %zd\n", | ||
863 | chan, rank, PAGES_TO_MiB(npages)); | ||
882 | } | 864 | } |
883 | } | 865 | } |
884 | 866 | ||
@@ -887,6 +869,7 @@ static int __devinit i5100_init_one(struct pci_dev *pdev, | |||
887 | { | 869 | { |
888 | int rc; | 870 | int rc; |
889 | struct mem_ctl_info *mci; | 871 | struct mem_ctl_info *mci; |
872 | struct edac_mc_layer layers[2]; | ||
890 | struct i5100_priv *priv; | 873 | struct i5100_priv *priv; |
891 | struct pci_dev *ch0mm, *ch1mm; | 874 | struct pci_dev *ch0mm, *ch1mm; |
892 | int ret = 0; | 875 | int ret = 0; |
@@ -947,7 +930,14 @@ static int __devinit i5100_init_one(struct pci_dev *pdev, | |||
947 | goto bail_ch1; | 930 | goto bail_ch1; |
948 | } | 931 | } |
949 | 932 | ||
950 | mci = edac_mc_alloc(sizeof(*priv), ranksperch * 2, 1, 0); | 933 | layers[0].type = EDAC_MC_LAYER_CHANNEL; |
934 | layers[0].size = 2; | ||
935 | layers[0].is_virt_csrow = false; | ||
936 | layers[1].type = EDAC_MC_LAYER_SLOT; | ||
937 | layers[1].size = ranksperch; | ||
938 | layers[1].is_virt_csrow = true; | ||
939 | mci = new_edac_mc_alloc(0, ARRAY_SIZE(layers), layers, | ||
940 | sizeof(*priv)); | ||
951 | if (!mci) { | 941 | if (!mci) { |
952 | ret = -ENOMEM; | 942 | ret = -ENOMEM; |
953 | goto bail_disable_ch1; | 943 | goto bail_disable_ch1; |