aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAndrei Konovalov <akonovalov@ru.mvista.com>2008-04-29 04:03:13 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-04-29 11:06:25 -0400
commit5135b797c8466eac39dc7fb4ae1fac6e7276377a (patch)
tree43603ffadd48cbf5d26d30880963e6df675898d3 /drivers
parent199f0ca514f9c17668eec4f935c4ba24cd789f85 (diff)
edac: new support for Intel 3100 chipset
Add Intel 3100 chipset support to e752x EDAC driver. Cc: Alan Cox <alan@lxorguk.ukuu.org.uk> Signed-off-by: Andrei Konovalov <akonovalov@ru.mvista.com> Signed-off-by: Doug Thompson <dougthompson@xmission.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/edac/Kconfig2
-rw-r--r--drivers/edac/e752x_edac.c165
2 files changed, 154 insertions, 13 deletions
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index 2b382990fe58..6e6c3c4aea6b 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -67,7 +67,7 @@ config EDAC_E7XXX
67 E7205, E7500, E7501 and E7505 server chipsets. 67 E7205, E7500, E7501 and E7505 server chipsets.
68 68
69config EDAC_E752X 69config EDAC_E752X
70 tristate "Intel e752x (e7520, e7525, e7320)" 70 tristate "Intel e752x (e7520, e7525, e7320) and 3100"
71 depends on EDAC_MM_EDAC && PCI && X86 && HOTPLUG 71 depends on EDAC_MM_EDAC && PCI && X86 && HOTPLUG
72 help 72 help
73 Support for error detection and correction on the Intel 73 Support for error detection and correction on the Intel
diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c
index 6eb434749cd5..4fbc5892bc2b 100644
--- a/drivers/edac/e752x_edac.c
+++ b/drivers/edac/e752x_edac.c
@@ -62,6 +62,14 @@ static struct edac_pci_ctl_info *e752x_pci;
62#define PCI_DEVICE_ID_INTEL_7320_1_ERR 0x3593 62#define PCI_DEVICE_ID_INTEL_7320_1_ERR 0x3593
63#endif /* PCI_DEVICE_ID_INTEL_7320_1_ERR */ 63#endif /* PCI_DEVICE_ID_INTEL_7320_1_ERR */
64 64
65#ifndef PCI_DEVICE_ID_INTEL_3100_0
66#define PCI_DEVICE_ID_INTEL_3100_0 0x35B0
67#endif /* PCI_DEVICE_ID_INTEL_3100_0 */
68
69#ifndef PCI_DEVICE_ID_INTEL_3100_1_ERR
70#define PCI_DEVICE_ID_INTEL_3100_1_ERR 0x35B1
71#endif /* PCI_DEVICE_ID_INTEL_3100_1_ERR */
72
65#define E752X_NR_CSROWS 8 /* number of csrows */ 73#define E752X_NR_CSROWS 8 /* number of csrows */
66 74
67/* E752X register addresses - device 0 function 0 */ 75/* E752X register addresses - device 0 function 0 */
@@ -152,6 +160,12 @@ static struct edac_pci_ctl_info *e752x_pci;
152 /* error syndrome register (16b) */ 160 /* error syndrome register (16b) */
153#define E752X_DEVPRES1 0xF4 /* Device Present 1 register (8b) */ 161#define E752X_DEVPRES1 0xF4 /* Device Present 1 register (8b) */
154 162
163/* 3100 IMCH specific register addresses - device 0 function 1 */
164#define I3100_NSI_FERR 0x48 /* NSI first error reg (32b) */
165#define I3100_NSI_NERR 0x4C /* NSI next error reg (32b) */
166#define I3100_NSI_SMICMD 0x54 /* NSI SMI command register (32b) */
167#define I3100_NSI_EMASK 0x90 /* NSI error mask register (32b) */
168
155/* ICH5R register addresses - device 30 function 0 */ 169/* ICH5R register addresses - device 30 function 0 */
156#define ICH5R_PCI_STAT 0x06 /* PCI status register (16b) */ 170#define ICH5R_PCI_STAT 0x06 /* PCI status register (16b) */
157#define ICH5R_PCI_2ND_STAT 0x1E /* PCI status secondary reg (16b) */ 171#define ICH5R_PCI_2ND_STAT 0x1E /* PCI status secondary reg (16b) */
@@ -160,7 +174,8 @@ static struct edac_pci_ctl_info *e752x_pci;
160enum e752x_chips { 174enum e752x_chips {
161 E7520 = 0, 175 E7520 = 0,
162 E7525 = 1, 176 E7525 = 1,
163 E7320 = 2 177 E7320 = 2,
178 I3100 = 3
164}; 179};
165 180
166struct e752x_pvt { 181struct e752x_pvt {
@@ -185,8 +200,10 @@ struct e752x_dev_info {
185struct e752x_error_info { 200struct e752x_error_info {
186 u32 ferr_global; 201 u32 ferr_global;
187 u32 nerr_global; 202 u32 nerr_global;
188 u8 hi_ferr; 203 u32 nsi_ferr; /* 3100 only */
189 u8 hi_nerr; 204 u32 nsi_nerr; /* 3100 only */
205 u8 hi_ferr; /* all but 3100 */
206 u8 hi_nerr; /* all but 3100 */
190 u16 sysbus_ferr; 207 u16 sysbus_ferr;
191 u16 sysbus_nerr; 208 u16 sysbus_nerr;
192 u8 buf_ferr; 209 u8 buf_ferr;
@@ -215,6 +232,10 @@ static const struct e752x_dev_info e752x_devs[] = {
215 .err_dev = PCI_DEVICE_ID_INTEL_7320_1_ERR, 232 .err_dev = PCI_DEVICE_ID_INTEL_7320_1_ERR,
216 .ctl_dev = PCI_DEVICE_ID_INTEL_7320_0, 233 .ctl_dev = PCI_DEVICE_ID_INTEL_7320_0,
217 .ctl_name = "E7320"}, 234 .ctl_name = "E7320"},
235 [I3100] = {
236 .err_dev = PCI_DEVICE_ID_INTEL_3100_1_ERR,
237 .ctl_dev = PCI_DEVICE_ID_INTEL_3100_0,
238 .ctl_name = "3100"},
218}; 239};
219 240
220static unsigned long ctl_page_to_phys(struct mem_ctl_info *mci, 241static unsigned long ctl_page_to_phys(struct mem_ctl_info *mci,
@@ -402,7 +423,7 @@ static inline void process_threshold_ce(struct mem_ctl_info *mci, u16 error,
402static char *global_message[11] = { 423static char *global_message[11] = {
403 "PCI Express C1", "PCI Express C", "PCI Express B1", 424 "PCI Express C1", "PCI Express C", "PCI Express B1",
404 "PCI Express B", "PCI Express A1", "PCI Express A", 425 "PCI Express B", "PCI Express A1", "PCI Express A",
405 "DMA Controler", "HUB Interface", "System Bus", 426 "DMA Controler", "HUB or NS Interface", "System Bus",
406 "DRAM Controler", "Internal Buffer" 427 "DRAM Controler", "Internal Buffer"
407}; 428};
408 429
@@ -455,6 +476,63 @@ static inline void hub_error(int fatal, u8 errors, int *error_found,
455 do_hub_error(fatal, errors); 476 do_hub_error(fatal, errors);
456} 477}
457 478
479#define NSI_FATAL_MASK 0x0c080081
480#define NSI_NON_FATAL_MASK 0x23a0ba64
481#define NSI_ERR_MASK (NSI_FATAL_MASK | NSI_NON_FATAL_MASK)
482
483static char *nsi_message[30] = {
484 "NSI Link Down", /* NSI_FERR/NSI_NERR bit 0, fatal error */
485 "", /* reserved */
486 "NSI Parity Error", /* bit 2, non-fatal */
487 "", /* reserved */
488 "", /* reserved */
489 "Correctable Error Message", /* bit 5, non-fatal */
490 "Non-Fatal Error Message", /* bit 6, non-fatal */
491 "Fatal Error Message", /* bit 7, fatal */
492 "", /* reserved */
493 "Receiver Error", /* bit 9, non-fatal */
494 "", /* reserved */
495 "Bad TLP", /* bit 11, non-fatal */
496 "Bad DLLP", /* bit 12, non-fatal */
497 "REPLAY_NUM Rollover", /* bit 13, non-fatal */
498 "", /* reserved */
499 "Replay Timer Timeout", /* bit 15, non-fatal */
500 "", /* reserved */
501 "", /* reserved */
502 "", /* reserved */
503 "Data Link Protocol Error", /* bit 19, fatal */
504 "", /* reserved */
505 "Poisoned TLP", /* bit 21, non-fatal */
506 "", /* reserved */
507 "Completion Timeout", /* bit 23, non-fatal */
508 "Completer Abort", /* bit 24, non-fatal */
509 "Unexpected Completion", /* bit 25, non-fatal */
510 "Receiver Overflow", /* bit 26, fatal */
511 "Malformed TLP", /* bit 27, fatal */
512 "", /* reserved */
513 "Unsupported Request" /* bit 29, non-fatal */
514};
515
516static void do_nsi_error(int fatal, u32 errors)
517{
518 int i;
519
520 for (i = 0; i < 30; i++) {
521 if (errors & (1 << i))
522 printk(KERN_WARNING "%sError %s\n",
523 fatal_message[fatal], nsi_message[i]);
524 }
525}
526
527static inline void nsi_error(int fatal, u32 errors, int *error_found,
528 int handle_error)
529{
530 *error_found = 1;
531
532 if (handle_error)
533 do_nsi_error(fatal, errors);
534}
535
458static char *membuf_message[4] = { 536static char *membuf_message[4] = {
459 "Internal PMWB to DRAM parity", 537 "Internal PMWB to DRAM parity",
460 "Internal PMWB to System Bus Parity", 538 "Internal PMWB to System Bus Parity",
@@ -546,6 +624,31 @@ static void e752x_check_hub_interface(struct e752x_error_info *info,
546 } 624 }
547} 625}
548 626
627static void e752x_check_ns_interface(struct e752x_error_info *info,
628 int *error_found, int handle_error)
629{
630 u32 stat32;
631
632 stat32 = info->nsi_ferr;
633 if (stat32 & NSI_ERR_MASK) { /* Error, so process */
634 if (stat32 & NSI_FATAL_MASK) /* check for fatal errors */
635 nsi_error(1, stat32 & NSI_FATAL_MASK, error_found,
636 handle_error);
637 if (stat32 & NSI_NON_FATAL_MASK) /* check for non-fatal ones */
638 nsi_error(0, stat32 & NSI_NON_FATAL_MASK, error_found,
639 handle_error);
640 }
641 stat32 = info->nsi_nerr;
642 if (stat32 & NSI_ERR_MASK) {
643 if (stat32 & NSI_FATAL_MASK)
644 nsi_error(1, stat32 & NSI_FATAL_MASK, error_found,
645 handle_error);
646 if (stat32 & NSI_NON_FATAL_MASK)
647 nsi_error(0, stat32 & NSI_NON_FATAL_MASK, error_found,
648 handle_error);
649 }
650}
651
549static void e752x_check_sysbus(struct e752x_error_info *info, 652static void e752x_check_sysbus(struct e752x_error_info *info,
550 int *error_found, int handle_error) 653 int *error_found, int handle_error)
551{ 654{
@@ -653,7 +756,15 @@ static void e752x_get_error_info(struct mem_ctl_info *mci,
653 pci_read_config_dword(dev, E752X_FERR_GLOBAL, &info->ferr_global); 756 pci_read_config_dword(dev, E752X_FERR_GLOBAL, &info->ferr_global);
654 757
655 if (info->ferr_global) { 758 if (info->ferr_global) {
656 pci_read_config_byte(dev, E752X_HI_FERR, &info->hi_ferr); 759 if (pvt->dev_info->err_dev == PCI_DEVICE_ID_INTEL_3100_1_ERR) {
760 pci_read_config_dword(dev, I3100_NSI_FERR,
761 &info->nsi_ferr);
762 info->hi_ferr = 0;
763 } else {
764 pci_read_config_byte(dev, E752X_HI_FERR,
765 &info->hi_ferr);
766 info->nsi_ferr = 0;
767 }
657 pci_read_config_word(dev, E752X_SYSBUS_FERR, 768 pci_read_config_word(dev, E752X_SYSBUS_FERR,
658 &info->sysbus_ferr); 769 &info->sysbus_ferr);
659 pci_read_config_byte(dev, E752X_BUF_FERR, &info->buf_ferr); 770 pci_read_config_byte(dev, E752X_BUF_FERR, &info->buf_ferr);
@@ -669,10 +780,15 @@ static void e752x_get_error_info(struct mem_ctl_info *mci,
669 pci_read_config_dword(dev, E752X_DRAM_RETR_ADD, 780 pci_read_config_dword(dev, E752X_DRAM_RETR_ADD,
670 &info->dram_retr_add); 781 &info->dram_retr_add);
671 782
783 /* ignore the reserved bits just in case */
672 if (info->hi_ferr & 0x7f) 784 if (info->hi_ferr & 0x7f)
673 pci_write_config_byte(dev, E752X_HI_FERR, 785 pci_write_config_byte(dev, E752X_HI_FERR,
674 info->hi_ferr); 786 info->hi_ferr);
675 787
788 if (info->nsi_ferr & NSI_ERR_MASK)
789 pci_write_config_dword(dev, I3100_NSI_FERR,
790 info->nsi_ferr);
791
676 if (info->sysbus_ferr) 792 if (info->sysbus_ferr)
677 pci_write_config_word(dev, E752X_SYSBUS_FERR, 793 pci_write_config_word(dev, E752X_SYSBUS_FERR,
678 info->sysbus_ferr); 794 info->sysbus_ferr);
@@ -692,7 +808,15 @@ static void e752x_get_error_info(struct mem_ctl_info *mci,
692 pci_read_config_dword(dev, E752X_NERR_GLOBAL, &info->nerr_global); 808 pci_read_config_dword(dev, E752X_NERR_GLOBAL, &info->nerr_global);
693 809
694 if (info->nerr_global) { 810 if (info->nerr_global) {
695 pci_read_config_byte(dev, E752X_HI_NERR, &info->hi_nerr); 811 if (pvt->dev_info->err_dev == PCI_DEVICE_ID_INTEL_3100_1_ERR) {
812 pci_read_config_dword(dev, I3100_NSI_NERR,
813 &info->nsi_nerr);
814 info->hi_nerr = 0;
815 } else {
816 pci_read_config_byte(dev, E752X_HI_NERR,
817 &info->hi_nerr);
818 info->nsi_nerr = 0;
819 }
696 pci_read_config_word(dev, E752X_SYSBUS_NERR, 820 pci_read_config_word(dev, E752X_SYSBUS_NERR,
697 &info->sysbus_nerr); 821 &info->sysbus_nerr);
698 pci_read_config_byte(dev, E752X_BUF_NERR, &info->buf_nerr); 822 pci_read_config_byte(dev, E752X_BUF_NERR, &info->buf_nerr);
@@ -706,6 +830,10 @@ static void e752x_get_error_info(struct mem_ctl_info *mci,
706 pci_write_config_byte(dev, E752X_HI_NERR, 830 pci_write_config_byte(dev, E752X_HI_NERR,
707 info->hi_nerr); 831 info->hi_nerr);
708 832
833 if (info->nsi_nerr & NSI_ERR_MASK)
834 pci_write_config_dword(dev, I3100_NSI_NERR,
835 info->nsi_nerr);
836
709 if (info->sysbus_nerr) 837 if (info->sysbus_nerr)
710 pci_write_config_word(dev, E752X_SYSBUS_NERR, 838 pci_write_config_word(dev, E752X_SYSBUS_NERR,
711 info->sysbus_nerr); 839 info->sysbus_nerr);
@@ -750,6 +878,7 @@ static int e752x_process_error_info(struct mem_ctl_info *mci,
750 global_error(0, stat32, &error_found, handle_errors); 878 global_error(0, stat32, &error_found, handle_errors);
751 879
752 e752x_check_hub_interface(info, &error_found, handle_errors); 880 e752x_check_hub_interface(info, &error_found, handle_errors);
881 e752x_check_ns_interface(info, &error_found, handle_errors);
753 e752x_check_sysbus(info, &error_found, handle_errors); 882 e752x_check_sysbus(info, &error_found, handle_errors);
754 e752x_check_membuf(info, &error_found, handle_errors); 883 e752x_check_membuf(info, &error_found, handle_errors);
755 e752x_check_dram(mci, info, &error_found, handle_errors); 884 e752x_check_dram(mci, info, &error_found, handle_errors);
@@ -926,8 +1055,13 @@ static void e752x_init_error_reporting_regs(struct e752x_pvt *pvt)
926 1055
927 dev = pvt->dev_d0f1; 1056 dev = pvt->dev_d0f1;
928 /* Turn off error disable & SMI in case the BIOS turned it on */ 1057 /* Turn off error disable & SMI in case the BIOS turned it on */
929 pci_write_config_byte(dev, E752X_HI_ERRMASK, 0x00); 1058 if (pvt->dev_info->err_dev == PCI_DEVICE_ID_INTEL_3100_1_ERR) {
930 pci_write_config_byte(dev, E752X_HI_SMICMD, 0x00); 1059 pci_write_config_dword(dev, I3100_NSI_EMASK, 0);
1060 pci_write_config_dword(dev, I3100_NSI_SMICMD, 0);
1061 } else {
1062 pci_write_config_byte(dev, E752X_HI_ERRMASK, 0x00);
1063 pci_write_config_byte(dev, E752X_HI_SMICMD, 0x00);
1064 }
931 pci_write_config_word(dev, E752X_SYSBUS_ERRMASK, 0x00); 1065 pci_write_config_word(dev, E752X_SYSBUS_ERRMASK, 0x00);
932 pci_write_config_word(dev, E752X_SYSBUS_SMICMD, 0x00); 1066 pci_write_config_word(dev, E752X_SYSBUS_SMICMD, 0x00);
933 pci_write_config_byte(dev, E752X_BUF_ERRMASK, 0x00); 1067 pci_write_config_byte(dev, E752X_BUF_ERRMASK, 0x00);
@@ -985,8 +1119,9 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
985 1119
986 debugf3("%s(): init mci\n", __func__); 1120 debugf3("%s(): init mci\n", __func__);
987 mci->mtype_cap = MEM_FLAG_RDDR; 1121 mci->mtype_cap = MEM_FLAG_RDDR;
988 mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED | 1122 /* 3100 IMCH supports SECDEC only */
989 EDAC_FLAG_S4ECD4ED; 1123 mci->edac_ctl_cap = (dev_idx == I3100) ? EDAC_FLAG_SECDED :
1124 (EDAC_FLAG_NONE | EDAC_FLAG_SECDED | EDAC_FLAG_S4ECD4ED);
990 /* FIXME - what if different memory types are in different csrows? */ 1125 /* FIXME - what if different memory types are in different csrows? */
991 mci->mod_name = EDAC_MOD_STR; 1126 mci->mod_name = EDAC_MOD_STR;
992 mci->mod_ver = E752X_REVISION; 1127 mci->mod_ver = E752X_REVISION;
@@ -1018,7 +1153,10 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
1018 e752x_init_csrows(mci, pdev, ddrcsr); 1153 e752x_init_csrows(mci, pdev, ddrcsr);
1019 e752x_init_mem_map_table(pdev, pvt); 1154 e752x_init_mem_map_table(pdev, pvt);
1020 1155
1021 mci->edac_cap |= EDAC_FLAG_NONE; 1156 if (dev_idx == I3100)
1157 mci->edac_cap = EDAC_FLAG_SECDED; /* the only mode supported */
1158 else
1159 mci->edac_cap |= EDAC_FLAG_NONE;
1022 debugf3("%s(): tolm, remapbase, remaplimit\n", __func__); 1160 debugf3("%s(): tolm, remapbase, remaplimit\n", __func__);
1023 1161
1024 /* load the top of low memory, remap base, and remap limit vars */ 1162 /* load the top of low memory, remap base, and remap limit vars */
@@ -1110,6 +1248,9 @@ static const struct pci_device_id e752x_pci_tbl[] __devinitdata = {
1110 PCI_VEND_DEV(INTEL, 7320_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1248 PCI_VEND_DEV(INTEL, 7320_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
1111 E7320}, 1249 E7320},
1112 { 1250 {
1251 PCI_VEND_DEV(INTEL, 3100_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
1252 I3100},
1253 {
1113 0, 1254 0,
1114 } /* 0 terminated list. */ 1255 } /* 0 terminated list. */
1115}; 1256};
@@ -1143,7 +1284,7 @@ module_exit(e752x_exit);
1143 1284
1144MODULE_LICENSE("GPL"); 1285MODULE_LICENSE("GPL");
1145MODULE_AUTHOR("Linux Networx (http://lnxi.com) Tom Zimmerman\n"); 1286MODULE_AUTHOR("Linux Networx (http://lnxi.com) Tom Zimmerman\n");
1146MODULE_DESCRIPTION("MC support for Intel e752x memory controllers"); 1287MODULE_DESCRIPTION("MC support for Intel e752x/3100 memory controllers");
1147 1288
1148module_param(force_function_unhide, int, 0444); 1289module_param(force_function_unhide, int, 0444);
1149MODULE_PARM_DESC(force_function_unhide, "if BIOS sets Dev0:Fun1 up as hidden:" 1290MODULE_PARM_DESC(force_function_unhide, "if BIOS sets Dev0:Fun1 up as hidden:"