Commit c0667407 authored by Aristeu Rozanski's avatar Aristeu Rozanski Committed by Linus Torvalds

edac i5000: fix error messages

Update the i5000_edac messages, making everything pass through the EDAC
(so the log controls will work) and being more specific about the errors.
Also, it makes the miscellaneous errors optional and disabled by default.

As I didn't found anywhere information about M23ERR-M26ERR
(FERR_NF_THERMAL) on FERR_NF_FBD, I'm removing them.
Signed-off-by: default avatarAristeu Rozanski <aris@redhat.com>
Signed-off-by: default avatarDoug Thompson <dougthompson@xmission.com>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 60be7551
...@@ -119,6 +119,7 @@ ...@@ -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[] = { ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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) { switch (allErrors) {
i5000_mc_printk(mci, KERN_ERR, case FERR_FAT_M1ERR:
"Alert on non-redundant retry or fast " specific = "Alert on non-redundant retry or fast "
"reset timeout\n"); "reset timeout";
break;
} else if (allErrors & FERR_FAT_M2ERR) { case FERR_FAT_M2ERR:
i5000_mc_printk(mci, KERN_ERR, specific = "Northbound CRC error on non-redundant "
"Northbound CRC error on non-redundant " "retry";
"retry\n"); break;
case FERR_FAT_M3ERR:
} else if (allErrors & FERR_FAT_M3ERR) { specific = ">Tmid Thermal event with intelligent "
i5000_mc_printk(mci, KERN_ERR, "throttling disabled";
">Tmid Thermal event with intelligent " break;
"throttling disabled\n");
} }
/* 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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, "CAS=%d, CE Err=0x%x (%s))", branch >> 1, bank,
rdwr ? "Write" : "Read", ras, cas, ce_errors); 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 */ if (!misc_messages)
misc_errors = allErrors & FERR_NF_THERMAL; return;
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);
}
/* See if any of the thermal errors have fired */ misc_errors = allErrors & (FERR_NF_NON_RETRY | FERR_NF_NORTH_CRC |
misc_errors = allErrors & FERR_NF_NORTH_CRC; FERR_NF_SPD_PROTOCOL | FERR_NF_DIMM_SPARE);
if (misc_errors) { if (misc_errors) {
i5000_printk(KERN_WARNING, switch (misc_errors) {
"\tNORTHBOUND CRC Error, bits= 0x%x\n", case FERR_NF_M13ERR:
misc_errors); 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 */ /* Form out message */
misc_errors = allErrors & FERR_NF_SPD_PROTOCOL; snprintf(msg, sizeof(msg),
if (misc_errors) { "(Branch=%d Err=%#x (%s))", branch >> 1,
i5000_printk(KERN_WARNING, misc_errors, specific);
"\tSPD Protocol Error, bits= 0x%x\n",
misc_errors);
}
/* See if any of the thermal errors have fired */ /* Call the helper to output message */
misc_errors = allErrors & FERR_NF_DIMM_SPARE; edac_mc_handle_fbd_ce(mci, 0, 0, msg);
if (misc_errors) {
i5000_printk(KERN_WARNING, "\tDIMM-Spare Error, bits= 0x%x\n",
misc_errors);
} }
} }
...@@ -1497,3 +1551,6 @@ MODULE_DESCRIPTION("MC Driver for Intel I5000 memory controllers - " ...@@ -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");
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment