|
@@ -119,6 +119,7 @@
|
|
#define FERR_NF_UNCORRECTABLE (FERR_NF_M12ERR | \
|
|
#define FERR_NF_UNCORRECTABLE (FERR_NF_M12ERR | \
|
|
FERR_NF_M11ERR | \
|
|
FERR_NF_M11ERR | \
|
|
FERR_NF_M10ERR | \
|
|
FERR_NF_M10ERR | \
|
|
|
|
+ FERR_NF_M9ERR | \
|
|
FERR_NF_M8ERR | \
|
|
FERR_NF_M8ERR | \
|
|
FERR_NF_M7ERR | \
|
|
FERR_NF_M7ERR | \
|
|
FERR_NF_M6ERR | \
|
|
FERR_NF_M6ERR | \
|
|
@@ -301,6 +302,9 @@ static char *numcol_toString[] = {
|
|
};
|
|
};
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
+/* enables the report of miscellaneous messages as CE errors - default off */
|
|
|
|
+static int misc_messages;
|
|
|
|
+
|
|
/* Enumeration of supported devices */
|
|
/* Enumeration of supported devices */
|
|
enum i5000_chips {
|
|
enum i5000_chips {
|
|
I5000P = 0,
|
|
I5000P = 0,
|
|
@@ -466,7 +470,8 @@ static void i5000_process_fatal_error_info(struct mem_ctl_info *mci,
|
|
struct i5000_error_info *info,
|
|
struct i5000_error_info *info,
|
|
int handle_errors)
|
|
int handle_errors)
|
|
{
|
|
{
|
|
- char msg[EDAC_MC_LABEL_LEN + 1 + 90];
|
|
|
|
|
|
+ char msg[EDAC_MC_LABEL_LEN + 1 + 160];
|
|
|
|
+ char *specific = NULL;
|
|
u32 allErrors;
|
|
u32 allErrors;
|
|
int branch;
|
|
int branch;
|
|
int channel;
|
|
int channel;
|
|
@@ -480,11 +485,6 @@ static void i5000_process_fatal_error_info(struct mem_ctl_info *mci,
|
|
if (!allErrors)
|
|
if (!allErrors)
|
|
return; /* if no error, return now */
|
|
return; /* if no error, return now */
|
|
|
|
|
|
- /* ONLY ONE of the possible error bits will be set, as per the docs */
|
|
|
|
- i5000_mc_printk(mci, KERN_ERR,
|
|
|
|
- "FATAL ERRORS Found!!! 1st FATAL Err Reg= 0x%x\n",
|
|
|
|
- allErrors);
|
|
|
|
-
|
|
|
|
branch = EXTRACT_FBDCHAN_INDX(info->ferr_fat_fbd);
|
|
branch = EXTRACT_FBDCHAN_INDX(info->ferr_fat_fbd);
|
|
channel = branch;
|
|
channel = branch;
|
|
|
|
|
|
@@ -501,28 +501,27 @@ static void i5000_process_fatal_error_info(struct mem_ctl_info *mci,
|
|
rdwr ? "Write" : "Read", ras, cas);
|
|
rdwr ? "Write" : "Read", ras, cas);
|
|
|
|
|
|
/* Only 1 bit will be on */
|
|
/* Only 1 bit will be on */
|
|
- if (allErrors & FERR_FAT_M1ERR) {
|
|
|
|
- i5000_mc_printk(mci, KERN_ERR,
|
|
|
|
- "Alert on non-redundant retry or fast "
|
|
|
|
- "reset timeout\n");
|
|
|
|
-
|
|
|
|
- } else if (allErrors & FERR_FAT_M2ERR) {
|
|
|
|
- i5000_mc_printk(mci, KERN_ERR,
|
|
|
|
- "Northbound CRC error on non-redundant "
|
|
|
|
- "retry\n");
|
|
|
|
-
|
|
|
|
- } else if (allErrors & FERR_FAT_M3ERR) {
|
|
|
|
- i5000_mc_printk(mci, KERN_ERR,
|
|
|
|
- ">Tmid Thermal event with intelligent "
|
|
|
|
- "throttling disabled\n");
|
|
|
|
|
|
+ switch (allErrors) {
|
|
|
|
+ case FERR_FAT_M1ERR:
|
|
|
|
+ specific = "Alert on non-redundant retry or fast "
|
|
|
|
+ "reset timeout";
|
|
|
|
+ break;
|
|
|
|
+ case FERR_FAT_M2ERR:
|
|
|
|
+ specific = "Northbound CRC error on non-redundant "
|
|
|
|
+ "retry";
|
|
|
|
+ break;
|
|
|
|
+ case FERR_FAT_M3ERR:
|
|
|
|
+ specific = ">Tmid Thermal event with intelligent "
|
|
|
|
+ "throttling disabled";
|
|
|
|
+ break;
|
|
}
|
|
}
|
|
|
|
|
|
/* Form out message */
|
|
/* Form out message */
|
|
snprintf(msg, sizeof(msg),
|
|
snprintf(msg, sizeof(msg),
|
|
"(Branch=%d DRAM-Bank=%d RDWR=%s RAS=%d CAS=%d "
|
|
"(Branch=%d DRAM-Bank=%d RDWR=%s RAS=%d CAS=%d "
|
|
- "FATAL Err=0x%x)",
|
|
|
|
|
|
+ "FATAL Err=0x%x (%s))",
|
|
branch >> 1, bank, rdwr ? "Write" : "Read", ras, cas,
|
|
branch >> 1, bank, rdwr ? "Write" : "Read", ras, cas,
|
|
- allErrors);
|
|
|
|
|
|
+ allErrors, specific);
|
|
|
|
|
|
/* Call the helper to output message */
|
|
/* Call the helper to output message */
|
|
edac_mc_handle_fbd_ue(mci, rank, channel, channel + 1, msg);
|
|
edac_mc_handle_fbd_ue(mci, rank, channel, channel + 1, msg);
|
|
@@ -539,7 +538,8 @@ static void i5000_process_nonfatal_error_info(struct mem_ctl_info *mci,
|
|
struct i5000_error_info *info,
|
|
struct i5000_error_info *info,
|
|
int handle_errors)
|
|
int handle_errors)
|
|
{
|
|
{
|
|
- char msg[EDAC_MC_LABEL_LEN + 1 + 90];
|
|
|
|
|
|
+ char msg[EDAC_MC_LABEL_LEN + 1 + 170];
|
|
|
|
+ char *specific = NULL;
|
|
u32 allErrors;
|
|
u32 allErrors;
|
|
u32 ue_errors;
|
|
u32 ue_errors;
|
|
u32 ce_errors;
|
|
u32 ce_errors;
|
|
@@ -557,10 +557,6 @@ static void i5000_process_nonfatal_error_info(struct mem_ctl_info *mci,
|
|
return; /* if no error, return now */
|
|
return; /* if no error, return now */
|
|
|
|
|
|
/* ONLY ONE of the possible error bits will be set, as per the docs */
|
|
/* ONLY ONE of the possible error bits will be set, as per the docs */
|
|
- i5000_mc_printk(mci, KERN_WARNING,
|
|
|
|
- "NON-FATAL ERRORS Found!!! 1st NON-FATAL Err "
|
|
|
|
- "Reg= 0x%x\n", allErrors);
|
|
|
|
-
|
|
|
|
ue_errors = allErrors & FERR_NF_UNCORRECTABLE;
|
|
ue_errors = allErrors & FERR_NF_UNCORRECTABLE;
|
|
if (ue_errors) {
|
|
if (ue_errors) {
|
|
debugf0("\tUncorrected bits= 0x%x\n", ue_errors);
|
|
debugf0("\tUncorrected bits= 0x%x\n", ue_errors);
|
|
@@ -579,12 +575,47 @@ static void i5000_process_nonfatal_error_info(struct mem_ctl_info *mci,
|
|
rank, channel, channel + 1, branch >> 1, bank,
|
|
rank, channel, channel + 1, branch >> 1, bank,
|
|
rdwr ? "Write" : "Read", ras, cas);
|
|
rdwr ? "Write" : "Read", ras, cas);
|
|
|
|
|
|
|
|
+ switch (ue_errors) {
|
|
|
|
+ case FERR_NF_M12ERR:
|
|
|
|
+ specific = "Non-Aliased Uncorrectable Patrol Data ECC";
|
|
|
|
+ break;
|
|
|
|
+ case FERR_NF_M11ERR:
|
|
|
|
+ specific = "Non-Aliased Uncorrectable Spare-Copy "
|
|
|
|
+ "Data ECC";
|
|
|
|
+ break;
|
|
|
|
+ case FERR_NF_M10ERR:
|
|
|
|
+ specific = "Non-Aliased Uncorrectable Mirrored Demand "
|
|
|
|
+ "Data ECC";
|
|
|
|
+ break;
|
|
|
|
+ case FERR_NF_M9ERR:
|
|
|
|
+ specific = "Non-Aliased Uncorrectable Non-Mirrored "
|
|
|
|
+ "Demand Data ECC";
|
|
|
|
+ break;
|
|
|
|
+ case FERR_NF_M8ERR:
|
|
|
|
+ specific = "Aliased Uncorrectable Patrol Data ECC";
|
|
|
|
+ break;
|
|
|
|
+ case FERR_NF_M7ERR:
|
|
|
|
+ specific = "Aliased Uncorrectable Spare-Copy Data ECC";
|
|
|
|
+ break;
|
|
|
|
+ case FERR_NF_M6ERR:
|
|
|
|
+ specific = "Aliased Uncorrectable Mirrored Demand "
|
|
|
|
+ "Data ECC";
|
|
|
|
+ break;
|
|
|
|
+ case FERR_NF_M5ERR:
|
|
|
|
+ specific = "Aliased Uncorrectable Non-Mirrored Demand "
|
|
|
|
+ "Data ECC";
|
|
|
|
+ break;
|
|
|
|
+ case FERR_NF_M4ERR:
|
|
|
|
+ specific = "Uncorrectable Data ECC on Replay";
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
/* Form out message */
|
|
/* Form out message */
|
|
snprintf(msg, sizeof(msg),
|
|
snprintf(msg, sizeof(msg),
|
|
"(Branch=%d DRAM-Bank=%d RDWR=%s RAS=%d "
|
|
"(Branch=%d DRAM-Bank=%d RDWR=%s RAS=%d "
|
|
- "CAS=%d, UE Err=0x%x)",
|
|
|
|
|
|
+ "CAS=%d, UE Err=0x%x (%s))",
|
|
branch >> 1, bank, rdwr ? "Write" : "Read", ras, cas,
|
|
branch >> 1, bank, rdwr ? "Write" : "Read", ras, cas,
|
|
- ue_errors);
|
|
|
|
|
|
+ ue_errors, specific);
|
|
|
|
|
|
/* Call the helper to output message */
|
|
/* Call the helper to output message */
|
|
edac_mc_handle_fbd_ue(mci, rank, channel, channel + 1, msg);
|
|
edac_mc_handle_fbd_ue(mci, rank, channel, channel + 1, msg);
|
|
@@ -616,51 +647,74 @@ static void i5000_process_nonfatal_error_info(struct mem_ctl_info *mci,
|
|
rank, channel, branch >> 1, bank,
|
|
rank, channel, branch >> 1, bank,
|
|
rdwr ? "Write" : "Read", ras, cas);
|
|
rdwr ? "Write" : "Read", ras, cas);
|
|
|
|
|
|
|
|
+ switch (ce_errors) {
|
|
|
|
+ case FERR_NF_M17ERR:
|
|
|
|
+ specific = "Correctable Non-Mirrored Demand Data ECC";
|
|
|
|
+ break;
|
|
|
|
+ case FERR_NF_M18ERR:
|
|
|
|
+ specific = "Correctable Mirrored Demand Data ECC";
|
|
|
|
+ break;
|
|
|
|
+ case FERR_NF_M19ERR:
|
|
|
|
+ specific = "Correctable Spare-Copy Data ECC";
|
|
|
|
+ break;
|
|
|
|
+ case FERR_NF_M20ERR:
|
|
|
|
+ specific = "Correctable Patrol Data ECC";
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
/* Form out message */
|
|
/* Form out message */
|
|
snprintf(msg, sizeof(msg),
|
|
snprintf(msg, sizeof(msg),
|
|
"(Branch=%d DRAM-Bank=%d RDWR=%s RAS=%d "
|
|
"(Branch=%d DRAM-Bank=%d RDWR=%s RAS=%d "
|
|
- "CAS=%d, CE Err=0x%x)", branch >> 1, bank,
|
|
|
|
- rdwr ? "Write" : "Read", ras, cas, ce_errors);
|
|
|
|
|
|
+ "CAS=%d, CE Err=0x%x (%s))", branch >> 1, bank,
|
|
|
|
+ rdwr ? "Write" : "Read", ras, cas, ce_errors,
|
|
|
|
+ specific);
|
|
|
|
|
|
/* Call the helper to output message */
|
|
/* Call the helper to output message */
|
|
edac_mc_handle_fbd_ce(mci, rank, channel, msg);
|
|
edac_mc_handle_fbd_ce(mci, rank, channel, msg);
|
|
}
|
|
}
|
|
|
|
|
|
- /* See if any of the thermal errors have fired */
|
|
|
|
- misc_errors = allErrors & FERR_NF_THERMAL;
|
|
|
|
- if (misc_errors) {
|
|
|
|
- i5000_printk(KERN_WARNING, "\tTHERMAL Error, bits= 0x%x\n",
|
|
|
|
- misc_errors);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* See if any of the thermal errors have fired */
|
|
|
|
- misc_errors = allErrors & FERR_NF_NON_RETRY;
|
|
|
|
- if (misc_errors) {
|
|
|
|
- i5000_printk(KERN_WARNING, "\tNON-Retry Errors, bits= 0x%x\n",
|
|
|
|
- misc_errors);
|
|
|
|
- }
|
|
|
|
|
|
+ if (!misc_messages)
|
|
|
|
+ return;
|
|
|
|
|
|
- /* See if any of the thermal errors have fired */
|
|
|
|
- misc_errors = allErrors & FERR_NF_NORTH_CRC;
|
|
|
|
|
|
+ misc_errors = allErrors & (FERR_NF_NON_RETRY | FERR_NF_NORTH_CRC |
|
|
|
|
+ FERR_NF_SPD_PROTOCOL | FERR_NF_DIMM_SPARE);
|
|
if (misc_errors) {
|
|
if (misc_errors) {
|
|
- i5000_printk(KERN_WARNING,
|
|
|
|
- "\tNORTHBOUND CRC Error, bits= 0x%x\n",
|
|
|
|
- misc_errors);
|
|
|
|
- }
|
|
|
|
|
|
+ switch (misc_errors) {
|
|
|
|
+ case FERR_NF_M13ERR:
|
|
|
|
+ specific = "Non-Retry or Redundant Retry FBD Memory "
|
|
|
|
+ "Alert or Redundant Fast Reset Timeout";
|
|
|
|
+ break;
|
|
|
|
+ case FERR_NF_M14ERR:
|
|
|
|
+ specific = "Non-Retry or Redundant Retry FBD "
|
|
|
|
+ "Configuration Alert";
|
|
|
|
+ break;
|
|
|
|
+ case FERR_NF_M15ERR:
|
|
|
|
+ specific = "Non-Retry or Redundant Retry FBD "
|
|
|
|
+ "Northbound CRC error on read data";
|
|
|
|
+ break;
|
|
|
|
+ case FERR_NF_M21ERR:
|
|
|
|
+ specific = "FBD Northbound CRC error on "
|
|
|
|
+ "FBD Sync Status";
|
|
|
|
+ break;
|
|
|
|
+ case FERR_NF_M22ERR:
|
|
|
|
+ specific = "SPD protocol error";
|
|
|
|
+ break;
|
|
|
|
+ case FERR_NF_M27ERR:
|
|
|
|
+ specific = "DIMM-spare copy started";
|
|
|
|
+ break;
|
|
|
|
+ case FERR_NF_M28ERR:
|
|
|
|
+ specific = "DIMM-spare copy completed";
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ branch = EXTRACT_FBDCHAN_INDX(info->ferr_nf_fbd);
|
|
|
|
|
|
- /* See if any of the thermal errors have fired */
|
|
|
|
- misc_errors = allErrors & FERR_NF_SPD_PROTOCOL;
|
|
|
|
- if (misc_errors) {
|
|
|
|
- i5000_printk(KERN_WARNING,
|
|
|
|
- "\tSPD Protocol Error, bits= 0x%x\n",
|
|
|
|
- misc_errors);
|
|
|
|
- }
|
|
|
|
|
|
+ /* Form out message */
|
|
|
|
+ snprintf(msg, sizeof(msg),
|
|
|
|
+ "(Branch=%d Err=%#x (%s))", branch >> 1,
|
|
|
|
+ misc_errors, specific);
|
|
|
|
|
|
- /* See if any of the thermal errors have fired */
|
|
|
|
- misc_errors = allErrors & FERR_NF_DIMM_SPARE;
|
|
|
|
- if (misc_errors) {
|
|
|
|
- i5000_printk(KERN_WARNING, "\tDIMM-Spare Error, bits= 0x%x\n",
|
|
|
|
- misc_errors);
|
|
|
|
|
|
+ /* Call the helper to output message */
|
|
|
|
+ edac_mc_handle_fbd_ce(mci, 0, 0, msg);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1497,3 +1551,6 @@ MODULE_DESCRIPTION("MC Driver for Intel I5000 memory controllers - "
|
|
|
|
|
|
module_param(edac_op_state, int, 0444);
|
|
module_param(edac_op_state, int, 0444);
|
|
MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
|
|
MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
|
|
|
|
+module_param(misc_messages, int, 0444);
|
|
|
|
+MODULE_PARM_DESC(misc_messages, "Log miscellaneous non fatal messages");
|
|
|
|
+
|