aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/edac/i5400_edac.c
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2009-01-06 17:43:00 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-01-06 18:59:30 -0500
commit8375d4909aee4c18798f373ecf24a79f040f75fc (patch)
tree9062847d672228a6c1e1f9d5c9dd0d513d819d59 /drivers/edac/i5400_edac.c
parent920c8df6ac678fdb8c49a6ce2e47a98e62757d77 (diff)
edac: driver for i5400 MCH (update)
Signed-off-by: Ben Woodard <woodard@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> Cc: Doug Thompson <norsk5@yahoo.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/edac/i5400_edac.c')
-rw-r--r--drivers/edac/i5400_edac.c119
1 files changed, 62 insertions, 57 deletions
diff --git a/drivers/edac/i5400_edac.c b/drivers/edac/i5400_edac.c
index 8ec3eca3061b..b08b6d8e2dc7 100644
--- a/drivers/edac/i5400_edac.c
+++ b/drivers/edac/i5400_edac.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Intel 5400 class Memory Controllers kernel module 2 * Intel 5400 class Memory Controllers kernel module (Seaburg)
3 * 3 *
4 * This file may be distributed under the terms of the 4 * This file may be distributed under the terms of the
5 * GNU General Public License. 5 * GNU General Public License.
@@ -55,13 +55,11 @@
55 * Function 1: Memory Branch Map, Control, Errors Register 55 * Function 1: Memory Branch Map, Control, Errors Register
56 * Function 2: FSB Error Registers 56 * Function 2: FSB Error Registers
57 * 57 *
58 * All 3 functions of Device 16 (0,1,2) share the SAME DID 58 * All 3 functions of Device 16 (0,1,2) share the SAME DID and
59 * uses PCI_DEVICE_ID_INTEL_5400_ERR for device 16 (0,1,2),
60 * PCI_DEVICE_ID_INTEL_5400_FBD0 and PCI_DEVICE_ID_INTEL_5400_FBD1
61 * for device 21 (0,1).
59 */ 62 */
60#ifndef PCI_DEVICE_ID_INTEL_5400_ERR
61#define PCI_DEVICE_ID_INTEL_5400_ERR 0x4030 /* Device 16 (0,1,2) */
62#define PCI_DEVICE_ID_INTEL_5400_FBD0 0x4035 /* Device 21 (0,1) */
63#define PCI_DEVICE_ID_INTEL_5400_FBD1 0x4036 /* Device 21 (0,1) */
64#endif
65 63
66 /* OFFSETS for Function 0 */ 64 /* OFFSETS for Function 0 */
67#define AMBASE 0x48 /* AMB Mem Mapped Reg Region Base */ 65#define AMBASE 0x48 /* AMB Mem Mapped Reg Region Base */
@@ -174,17 +172,17 @@ enum error_mask {
174/* 172/*
175 * Names to translate bit error into something useful 173 * Names to translate bit error into something useful
176 */ 174 */
177char *error_name[] = { 175static const char *error_name[] = {
178 [0] = "Memory Write error on non-redundant retry", 176 [0] = "Memory Write error on non-redundant retry",
179 [1] = "Memory or FB-DIMM configuration CRC read error", 177 [1] = "Memory or FB-DIMM configuration CRC read error",
180 /* Reserved */ 178 /* Reserved */
181 [3] = "Uncorrectable Data ECC on Replay", 179 [3] = "Uncorrectable Data ECC on Replay",
182 [4] = "Aliased Uncorrectable Non-Mirrored Demand Data ECC", 180 [4] = "Aliased Uncorrectable Non-Mirrored Demand Data ECC",
183 /* Unsupported on i5400 */ 181 /* M6 Unsupported on i5400 */
184 [6] = "Aliased Uncorrectable Resilver- or Spare-Copy Data ECC", 182 [6] = "Aliased Uncorrectable Resilver- or Spare-Copy Data ECC",
185 [7] = "Aliased Uncorrectable Patrol Data ECC", 183 [7] = "Aliased Uncorrectable Patrol Data ECC",
186 [8] = "Non-Aliased Uncorrectable Non-Mirrored Demand Data ECC", 184 [8] = "Non-Aliased Uncorrectable Non-Mirrored Demand Data ECC",
187 /* Unsupported */ 185 /* M10 Unsupported on i5400 */
188 [10] = "Non-Aliased Uncorrectable Resilver- or Spare-Copy Data ECC", 186 [10] = "Non-Aliased Uncorrectable Resilver- or Spare-Copy Data ECC",
189 [11] = "Non-Aliased Uncorrectable Patrol Data ECC", 187 [11] = "Non-Aliased Uncorrectable Patrol Data ECC",
190 [12] = "Memory Write error on first attempt", 188 [12] = "Memory Write error on first attempt",
@@ -192,7 +190,7 @@ char *error_name[] = {
192 [14] = "Memory or FB-DIMM configuration CRC read error", 190 [14] = "Memory or FB-DIMM configuration CRC read error",
193 [15] = "Channel Failed-Over Occurred", 191 [15] = "Channel Failed-Over Occurred",
194 [16] = "Correctable Non-Mirrored Demand Data ECC", 192 [16] = "Correctable Non-Mirrored Demand Data ECC",
195 /* Unsupported */ 193 /* M18 Unsupported on i5400 */
196 [18] = "Correctable Resilver- or Spare-Copy Data ECC", 194 [18] = "Correctable Resilver- or Spare-Copy Data ECC",
197 [19] = "Correctable Patrol Data ECC", 195 [19] = "Correctable Patrol Data ECC",
198 [20] = "FB-DIMM Northbound parity error on FB-DIMM Sync Status", 196 [20] = "FB-DIMM Northbound parity error on FB-DIMM Sync Status",
@@ -259,24 +257,32 @@ char *error_name[] = {
259#define FERR_FAT_MASK ERROR_FAT_MASK 257#define FERR_FAT_MASK ERROR_FAT_MASK
260 258
261/* masks for non-fatal error register */ 259/* masks for non-fatal error register */
262#define TO_NF_MASK(a) (((a) & EMASK_M29) | ((a) >> 3)) 260static inline int to_nf_mask(unsigned int mask)
263#define FROM_NF_FERR(a) (((a) & EMASK_M29) | (((a) << 3) & ((1 << 30)-1))) 261{
262 return (mask & EMASK_M29) | (mask >> 3);
263};
264
265static inline int from_nf_ferr(unsigned int mask)
266{
267 return (mask & EMASK_M29) | /* Bit 28 */
268 (mask & ((1 << 28) - 1) << 3); /* Bits 0 to 27 */
269};
264 270
265#define FERR_NF_MASK TO_NF_MASK(ERROR_NF_MASK) 271#define FERR_NF_MASK to_nf_mask(ERROR_NF_MASK)
266#define FERR_NF_CORRECTABLE TO_NF_MASK(ERROR_NF_CORRECTABLE) 272#define FERR_NF_CORRECTABLE to_nf_mask(ERROR_NF_CORRECTABLE)
267#define FERR_NF_DIMM_SPARE TO_NF_MASK(ERROR_NF_DIMM_SPARE) 273#define FERR_NF_DIMM_SPARE to_nf_mask(ERROR_NF_DIMM_SPARE)
268#define FERR_NF_SPD_PROTOCOL TO_NF_MASK(ERROR_NF_SPD_PROTOCOL) 274#define FERR_NF_SPD_PROTOCOL to_nf_mask(ERROR_NF_SPD_PROTOCOL)
269#define FERR_NF_NORTH_CRC TO_NF_MASK(ERROR_NF_NORTH_CRC) 275#define FERR_NF_NORTH_CRC to_nf_mask(ERROR_NF_NORTH_CRC)
270#define FERR_NF_RECOVERABLE TO_NF_MASK(ERROR_NF_RECOVERABLE) 276#define FERR_NF_RECOVERABLE to_nf_mask(ERROR_NF_RECOVERABLE)
271#define FERR_NF_UNCORRECTABLE TO_NF_MASK(ERROR_NF_UNCORRECTABLE) 277#define FERR_NF_UNCORRECTABLE to_nf_mask(ERROR_NF_UNCORRECTABLE)
272 278
273/* Defines to extract the vaious fields from the 279/* Defines to extract the vaious fields from the
274 * MTRx - Memory Technology Registers 280 * MTRx - Memory Technology Registers
275 */ 281 */
276#define MTR_DIMMS_PRESENT(mtr) ((mtr) & (1 << 10)) 282#define MTR_DIMMS_PRESENT(mtr) ((mtr) & (1 << 10))
277#define MTR_DIMMS_ETHROTTLE(mtr) ((mtr) & (1 << 9)) 283#define MTR_DIMMS_ETHROTTLE(mtr) ((mtr) & (1 << 9))
278#define MTR_DRAM_WIDTH(mtr) (((mtr) & (1<< 8)) ? 8 : 4) 284#define MTR_DRAM_WIDTH(mtr) (((mtr) & (1 << 8)) ? 8 : 4)
279#define MTR_DRAM_BANKS(mtr) (((mtr) & (1<< 6)) ? 8 : 4) 285#define MTR_DRAM_BANKS(mtr) (((mtr) & (1 << 6)) ? 8 : 4)
280#define MTR_DRAM_BANKS_ADDR_BITS(mtr) ((MTR_DRAM_BANKS(mtr) == 8) ? 3 : 2) 286#define MTR_DRAM_BANKS_ADDR_BITS(mtr) ((MTR_DRAM_BANKS(mtr) == 8) ? 3 : 2)
281#define MTR_DIMM_RANK(mtr) (((mtr) >> 5) & 0x1) 287#define MTR_DIMM_RANK(mtr) (((mtr) >> 5) & 0x1)
282#define MTR_DIMM_RANK_ADDR_BITS(mtr) (MTR_DIMM_RANK(mtr) ? 2 : 1) 288#define MTR_DIMM_RANK_ADDR_BITS(mtr) (MTR_DIMM_RANK(mtr) ? 2 : 1)
@@ -293,7 +299,7 @@ static inline int extract_fbdchan_indx(u32 x)
293 299
294#ifdef CONFIG_EDAC_DEBUG 300#ifdef CONFIG_EDAC_DEBUG
295/* MTR NUMROW */ 301/* MTR NUMROW */
296static char *numrow_toString[] = { 302static const char *numrow_toString[] = {
297 "8,192 - 13 rows", 303 "8,192 - 13 rows",
298 "16,384 - 14 rows", 304 "16,384 - 14 rows",
299 "32,768 - 15 rows", 305 "32,768 - 15 rows",
@@ -301,7 +307,7 @@ static char *numrow_toString[] = {
301}; 307};
302 308
303/* MTR NUMCOL */ 309/* MTR NUMCOL */
304static char *numcol_toString[] = { 310static const char *numcol_toString[] = {
305 "1,024 - 10 columns", 311 "1,024 - 10 columns",
306 "2,048 - 11 columns", 312 "2,048 - 11 columns",
307 "4,096 - 12 columns", 313 "4,096 - 12 columns",
@@ -341,11 +347,11 @@ struct i5400_pvt {
341 347
342 u16 mir0, mir1; 348 u16 mir0, mir1;
343 349
344 u16 b0_mtr[NUM_MTRS_PER_BRANCH]; /* Memory Technlogy Reg */ 350 u16 b0_mtr[NUM_MTRS_PER_BRANCH]; /* Memory Technlogy Reg */
345 u16 b0_ambpresent0; /* Branch 0, Channel 0 */ 351 u16 b0_ambpresent0; /* Branch 0, Channel 0 */
346 u16 b0_ambpresent1; /* Brnach 0, Channel 1 */ 352 u16 b0_ambpresent1; /* Brnach 0, Channel 1 */
347 353
348 u16 b1_mtr[NUM_MTRS_PER_BRANCH]; /* Memory Technlogy Reg */ 354 u16 b1_mtr[NUM_MTRS_PER_BRANCH]; /* Memory Technlogy Reg */
349 u16 b1_ambpresent0; /* Branch 1, Channel 8 */ 355 u16 b1_ambpresent0; /* Branch 1, Channel 8 */
350 u16 b1_ambpresent1; /* Branch 1, Channel 1 */ 356 u16 b1_ambpresent1; /* Branch 1, Channel 1 */
351 357
@@ -370,7 +376,7 @@ struct i5400_error_info {
370 u16 recmema; /* Recoverable Mem Error log A */ 376 u16 recmema; /* Recoverable Mem Error log A */
371 u32 recmemb; /* Recoverable Mem Error log B */ 377 u32 recmemb; /* Recoverable Mem Error log B */
372 378
373 /* These registers are input ONLY if there was a Non-Recoverable Error */ 379 /* These registers are input ONLY if there was a Non-Rec Error */
374 u16 nrecmema; /* Non-Recoverable Mem log A */ 380 u16 nrecmema; /* Non-Recoverable Mem log A */
375 u16 nrecmemb; /* Non-Recoverable Mem log B */ 381 u16 nrecmemb; /* Non-Recoverable Mem log B */
376 382
@@ -560,10 +566,10 @@ static void i5400_proccess_non_recoverable_info(struct mem_ctl_info *mci,
560 566
561 /* Form out message */ 567 /* Form out message */
562 snprintf(msg, sizeof(msg), 568 snprintf(msg, sizeof(msg),
563 "%s (Branch=%d DRAM-Bank=%d Buffer ID = %d RDWR=%s RAS=%d CAS=%d " 569 "%s (Branch=%d DRAM-Bank=%d Buffer ID = %d RDWR=%s "
564 "%s Err=0x%lx (%s))", 570 "RAS=%d CAS=%d %s Err=0x%lx (%s))",
565 type, branch >> 1, bank, buf_id, rdwr_str(rdwr), ras, cas, type, 571 type, branch >> 1, bank, buf_id, rdwr_str(rdwr), ras, cas,
566 allErrors, error_name[errnum]); 572 type, allErrors, error_name[errnum]);
567 573
568 /* Call the helper to output message */ 574 /* Call the helper to output message */
569 edac_mc_handle_fbd_ue(mci, rank, channel, channel + 1, msg); 575 edac_mc_handle_fbd_ue(mci, rank, channel, channel + 1, msg);
@@ -590,7 +596,7 @@ static void i5400_process_nonfatal_error_info(struct mem_ctl_info *mci,
590 int errnum; 596 int errnum;
591 597
592 /* mask off the Error bits that are possible */ 598 /* mask off the Error bits that are possible */
593 allErrors = FROM_NF_FERR(info->ferr_nf_fbd & FERR_NF_MASK); 599 allErrors = from_nf_ferr(info->ferr_nf_fbd & FERR_NF_MASK);
594 if (!allErrors) 600 if (!allErrors)
595 return; /* if no error, return now */ 601 return; /* if no error, return now */
596 602
@@ -631,10 +637,10 @@ static void i5400_process_nonfatal_error_info(struct mem_ctl_info *mci,
631 637
632 /* Form out message */ 638 /* Form out message */
633 snprintf(msg, sizeof(msg), 639 snprintf(msg, sizeof(msg),
634 "Corrected error (Branch=%d DRAM-Bank=%d RDWR=%s RAS=%d " 640 "Corrected error (Branch=%d DRAM-Bank=%d RDWR=%s "
635 "CAS=%d, CE Err=0x%lx (%s))", branch >> 1, bank, 641 "RAS=%d CAS=%d, CE Err=0x%lx (%s))",
636 rdwr_str(rdwr), ras, cas, allErrors, 642 branch >> 1, bank, rdwr_str(rdwr), ras, cas,
637 error_name[errnum]); 643 allErrors, error_name[errnum]);
638 644
639 /* Call the helper to output message */ 645 /* Call the helper to output message */
640 edac_mc_handle_fbd_ce(mci, rank, channel, msg); 646 edac_mc_handle_fbd_ce(mci, rank, channel, msg);
@@ -704,17 +710,10 @@ static void i5400_put_devices(struct mem_ctl_info *mci)
704 pvt = mci->pvt_info; 710 pvt = mci->pvt_info;
705 711
706 /* Decrement usage count for devices */ 712 /* Decrement usage count for devices */
707 if (pvt->branch_1) 713 pci_dev_put(pvt->branch_1);
708 pci_dev_put(pvt->branch_1); 714 pci_dev_put(pvt->branch_0);
709 715 pci_dev_put(pvt->fsb_error_regs);
710 if (pvt->branch_0) 716 pci_dev_put(pvt->branchmap_werrors);
711 pci_dev_put(pvt->branch_0);
712
713 if (pvt->fsb_error_regs)
714 pci_dev_put(pvt->fsb_error_regs);
715
716 if (pvt->branchmap_werrors)
717 pci_dev_put(pvt->branchmap_werrors);
718} 717}
719 718
720/* 719/*
@@ -810,9 +809,9 @@ error:
810/* 809/*
811 * determine_amb_present 810 * determine_amb_present
812 * 811 *
813 * the information is contained in NUM_MTRS_PER_BRANCH different registers 812 * the information is contained in NUM_MTRS_PER_BRANCH different
814 * determining which of the NUM_MTRS_PER_BRANCH requires knowing 813 * registers determining which of the NUM_MTRS_PER_BRANCH requires
815 * which channel is in question 814 * knowing which channel is in question
816 * 815 *
817 * 2 branches, each with 2 channels 816 * 2 branches, each with 2 channels
818 * b0_ambpresent0 for channel '0' 817 * b0_ambpresent0 for channel '0'
@@ -842,7 +841,7 @@ static int determine_amb_present_reg(struct i5400_pvt *pvt, int channel)
842/* 841/*
843 * determine_mtr(pvt, csrow, channel) 842 * determine_mtr(pvt, csrow, channel)
844 * 843 *
845 * return the proper MTR register as determine by the csrow and channel desired 844 * return the proper MTR register as determine by the csrow and desired channel
846 */ 845 */
847static int determine_mtr(struct i5400_pvt *pvt, int csrow, int channel) 846static int determine_mtr(struct i5400_pvt *pvt, int csrow, int channel)
848{ 847{
@@ -857,7 +856,8 @@ static int determine_mtr(struct i5400_pvt *pvt, int csrow, int channel)
857 n = csrow >> 3; 856 n = csrow >> 3;
858 857
859 if (n >= NUM_MTRS_PER_BRANCH) { 858 if (n >= NUM_MTRS_PER_BRANCH) {
860 debugf0("ERROR: trying to access an invalid csrow: %d\n", csrow); 859 debugf0("ERROR: trying to access an invalid csrow: %d\n",
860 csrow);
861 return 0; 861 return 0;
862 } 862 }
863 863
@@ -885,7 +885,7 @@ static void decode_mtr(int slot_row, u16 mtr)
885 debugf2("\t\tWIDTH: x%d\n", MTR_DRAM_WIDTH(mtr)); 885 debugf2("\t\tWIDTH: x%d\n", MTR_DRAM_WIDTH(mtr));
886 886
887 debugf2("\t\tELECTRICAL THROTTLING is %s\n", 887 debugf2("\t\tELECTRICAL THROTTLING is %s\n",
888 MTR_DIMMS_ETHROTTLE(mtr) ? "enabled": "disabled"); 888 MTR_DIMMS_ETHROTTLE(mtr) ? "enabled" : "disabled");
889 889
890 debugf2("\t\tNUMBANK: %d bank(s)\n", MTR_DRAM_BANKS(mtr)); 890 debugf2("\t\tNUMBANK: %d bank(s)\n", MTR_DRAM_BANKS(mtr));
891 debugf2("\t\tNUMRANK: %s\n", MTR_DIMM_RANK(mtr) ? "double" : "single"); 891 debugf2("\t\tNUMRANK: %s\n", MTR_DIMM_RANK(mtr) ? "double" : "single");
@@ -1251,6 +1251,9 @@ static int i5400_probe1(struct pci_dev *pdev, int dev_idx)
1251 int num_dimms_per_channel; 1251 int num_dimms_per_channel;
1252 int num_csrows; 1252 int num_csrows;
1253 1253
1254 if (dev_idx >= ARRAY_SIZE(i5400_devs))
1255 return -EINVAL;
1256
1254 debugf0("MC: " __FILE__ ": %s(), pdev bus %u dev=0x%x fn=0x%x\n", 1257 debugf0("MC: " __FILE__ ": %s(), pdev bus %u dev=0x%x fn=0x%x\n",
1255 __func__, 1258 __func__,
1256 pdev->bus->number, 1259 pdev->bus->number,
@@ -1425,7 +1428,7 @@ MODULE_DEVICE_TABLE(pci, i5400_pci_tbl);
1425 * 1428 *
1426 */ 1429 */
1427static struct pci_driver i5400_driver = { 1430static struct pci_driver i5400_driver = {
1428 .name = KBUILD_BASENAME, 1431 .name = "i5400_edac",
1429 .probe = i5400_init_one, 1432 .probe = i5400_init_one,
1430 .remove = __devexit_p(i5400_remove_one), 1433 .remove = __devexit_p(i5400_remove_one),
1431 .id_table = i5400_pci_tbl, 1434 .id_table = i5400_pci_tbl,
@@ -1463,9 +1466,11 @@ module_init(i5400_init);
1463module_exit(i5400_exit); 1466module_exit(i5400_exit);
1464 1467
1465MODULE_LICENSE("GPL"); 1468MODULE_LICENSE("GPL");
1466MODULE_AUTHOR("Ben Woodard <woodard@redhat.com> Red Hat Inc. (http://www.redhat.com)"); 1469MODULE_AUTHOR("Ben Woodard <woodard@redhat.com>");
1467MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com> Red Hat Inc. (http://www.redhat.com)"); 1470MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
1468MODULE_DESCRIPTION("MC Driver for Intel I5400 memory controllers - " I5400_REVISION); 1471MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
1472MODULE_DESCRIPTION("MC Driver for Intel I5400 memory controllers - "
1473 I5400_REVISION);
1469 1474
1470module_param(edac_op_state, int, 0444); 1475module_param(edac_op_state, int, 0444);
1471MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI"); 1476MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");