History

EDAC/ghes: Unify CPER memory error location reporting

Switch the GHES EDAC memory error reporting functions to use the common CPER ones and get rid of code duplication. [ bp: - rewrite commit message, remove useless text - rip out useless reformatting - align function params on the opening brace - rename function to a more descriptive name - drop useless function exports - handle buffer lengths properly when printing other detail - remove useless casting ]

Shuai Xue committed 4 years ago

Commit ed27b5d1 parent bdae7964 files · +42 −165Browse files

Unified · Split

4 files
  1. drivers/edac/Kconfig +1 −0
  2. drivers/edac/ghes_edac.c +37 −163
  3. drivers/firmware/efi/cper.c +2 −2
  4. include/linux/cper.h +2 −0
drivers/edac/Kconfig+1−0
@@ -55,6 +55,7 @@ config EDAC_DECODE_MCE · 54 unmodified lines
5555 config EDAC_GHES
5656 bool "Output ACPI APEI/GHES BIOS detected errors via EDAC"
5757 depends on ACPI_APEI_GHES && (EDAC=y)
58+ select UEFI_CPER
5859 help
5960 Not all machines support hardware-driven error report. Some of those
6061 provide a BIOS-driven error report mechanism via ACPI, using the
drivers/edac/ghes_edac.c+37−163
@@ -15,11 +15,13 @@ · 14 unmodified lines
1515 #include "edac_module.h"
1616 #include <ras/ras_event.h>
1717
18+#define OTHER_DETAIL_LEN 400
19+
1820 struct ghes_pvt {
1921 struct mem_ctl_info *mci;
2022
2123 /* Buffers for the error handling routine */
22− char other_detail[400];
24+ char other_detail[OTHER_DETAIL_LEN];
2325 char msg[80];
2426 };
2527
@@ -235,8 +237,34 @@ static void ghes_scan_system(void) · 209 unmodified lines
235237 system_scanned = true;
236238 }
237239
240+static int print_mem_error_other_detail(const struct cper_sec_mem_err *mem, char *msg,
241+ const char *location, unsigned int len)
242+{
243+ u32 n;
244+
245+ if (!msg)
246+ return 0;
247+
248+ n = 0;
249+ len -= 1;
250+
251+ n += scnprintf(msg + n, len - n, "APEI location: %s ", location);
252+
253+ if (!(mem->validation_bits & CPER_MEM_VALID_ERROR_STATUS))
254+ goto out;
255+
256+ n += scnprintf(msg + n, len - n, "status(0x%016llx): ", mem->error_status);
257+ n += scnprintf(msg + n, len - n, "%s ", cper_mem_err_status_str(mem->error_status));
258+
259+out:
260+ msg[n] = '\0';
261+
262+ return n;
263+}
264+
238265 void ghes_edac_report_mem_error(int sev, struct cper_sec_mem_err *mem_err)
239266 {
267+ struct cper_mem_err_compact cmem;
240268 struct edac_raw_error_desc *e;
241269 struct mem_ctl_info *mci;
242270 struct ghes_pvt *pvt;
@@ -292,60 +320,10 @@ void ghes_edac_report_mem_error(int sev, struct cper_sec_mem_err *mem_err) · 49 unmodified lines
292320
293321 /* Error type, mapped on e->msg */
294322 if (mem_err->validation_bits & CPER_MEM_VALID_ERROR_TYPE) {
323+ u8 etype = mem_err->error_type;
324+
295325 p = pvt->msg;
296− switch (mem_err->error_type) {
297− case 0:
298− p += sprintf(p, "Unknown");
299− break;
300− case 1:
301− p += sprintf(p, "No error");
302− break;
303− case 2:
304− p += sprintf(p, "Single-bit ECC");
305− break;
306− case 3:
307− p += sprintf(p, "Multi-bit ECC");
308− break;
309− case 4:
310− p += sprintf(p, "Single-symbol ChipKill ECC");
311− break;
312− case 5:
313− p += sprintf(p, "Multi-symbol ChipKill ECC");
314− break;
315− case 6:
316− p += sprintf(p, "Master abort");
317− break;
318− case 7:
319− p += sprintf(p, "Target abort");
320− break;
321− case 8:
322− p += sprintf(p, "Parity Error");
323− break;
324− case 9:
325− p += sprintf(p, "Watchdog timeout");
326− break;
327− case 10:
328− p += sprintf(p, "Invalid address");
329− break;
330− case 11:
331− p += sprintf(p, "Mirror Broken");
332− break;
333− case 12:
334− p += sprintf(p, "Memory Sparing");
335− break;
336− case 13:
337− p += sprintf(p, "Scrub corrected error");
338− break;
339− case 14:
340− p += sprintf(p, "Scrub uncorrected error");
341− break;
342− case 15:
343− p += sprintf(p, "Physical Memory Map-out event");
344− break;
345− default:
346− p += sprintf(p, "reserved error (%d)",
347− mem_err->error_type);
348− }
326+ p += snprintf(p, sizeof(pvt->msg), "%s", cper_mem_err_type_str(etype));
349327 } else {
350328 strcpy(pvt->msg, "unknown error");
351329 }
@@ -362,52 +340,19 @@ void ghes_edac_report_mem_error(int sev, struct cper_sec_mem_err *mem_err) · 10 unmodified lines
362340
363341 /* Memory error location, mapped on e->location */
364342 p = e->location;
365− if (mem_err->validation_bits & CPER_MEM_VALID_NODE)
366− p += sprintf(p, "node:%d ", mem_err->node);
367− if (mem_err->validation_bits & CPER_MEM_VALID_CARD)
368− p += sprintf(p, "card:%d ", mem_err->card);
369− if (mem_err->validation_bits & CPER_MEM_VALID_MODULE)
370− p += sprintf(p, "module:%d ", mem_err->module);
371− if (mem_err->validation_bits & CPER_MEM_VALID_RANK_NUMBER)
372− p += sprintf(p, "rank:%d ", mem_err->rank);
373− if (mem_err->validation_bits & CPER_MEM_VALID_BANK)
374− p += sprintf(p, "bank:%d ", mem_err->bank);
375− if (mem_err->validation_bits & CPER_MEM_VALID_BANK_GROUP)
376− p += sprintf(p, "bank_group:%d ",
377− mem_err->bank >> CPER_MEM_BANK_GROUP_SHIFT);
378− if (mem_err->validation_bits & CPER_MEM_VALID_BANK_ADDRESS)
379− p += sprintf(p, "bank_address:%d ",
380− mem_err->bank & CPER_MEM_BANK_ADDRESS_MASK);
381− if (mem_err->validation_bits & (CPER_MEM_VALID_ROW | CPER_MEM_VALID_ROW_EXT)) {
382− u32 row = mem_err->row;
383−
384− row |= cper_get_mem_extension(mem_err->validation_bits, mem_err->extended);
385− p += sprintf(p, "row:%d ", row);
386− }
387− if (mem_err->validation_bits & CPER_MEM_VALID_COLUMN)
388− p += sprintf(p, "col:%d ", mem_err->column);
389− if (mem_err->validation_bits & CPER_MEM_VALID_BIT_POSITION)
390− p += sprintf(p, "bit_pos:%d ", mem_err->bit_pos);
343+ cper_mem_err_pack(mem_err, &cmem);
344+ p += cper_mem_err_location(&cmem, p);
345+
391346 if (mem_err->validation_bits & CPER_MEM_VALID_MODULE_HANDLE) {
392− const char *bank = NULL, *device = NULL;
393347 struct dimm_info *dimm;
394348
395− dmi_memdev_name(mem_err->mem_dev_handle, &bank, &device);
396− if (bank != NULL && device != NULL)
397− p += sprintf(p, "DIMM location:%s %s ", bank, device);
398− else
399− p += sprintf(p, "DIMM DMI handle: 0x%.4x ",
400− mem_err->mem_dev_handle);
401−
349+ p += cper_dimm_err_location(&cmem, p);
402350 dimm = find_dimm_by_handle(mci, mem_err->mem_dev_handle);
403351 if (dimm) {
404352 e->top_layer = dimm->idx;
405353 strcpy(e->label, dimm->label);
406354 }
407355 }
408− if (mem_err->validation_bits & CPER_MEM_VALID_CHIP_ID)
409− p += sprintf(p, "chipID: %d ",
410− mem_err->extended >> CPER_MEM_CHIP_ID_SHIFT);
411356 if (p > e->location)
412357 *(p - 1) = '\0';
413358
@@ -416,78 +361,7 @@ void ghes_edac_report_mem_error(int sev, struct cper_sec_mem_err *mem_err) · 2 unmodified lines
416361
417362 /* All other fields are mapped on e->other_detail */
418363 p = pvt->other_detail;
419− p += snprintf(p, sizeof(pvt->other_detail),
420− "APEI location: %s ", e->location);
421− if (mem_err->validation_bits & CPER_MEM_VALID_ERROR_STATUS) {
422− u64 status = mem_err->error_status;
423−
424− p += sprintf(p, "status(0x%016llx): ", (long long)status);
425− switch ((status >> 8) & 0xff) {
426− case 1:
427− p += sprintf(p, "Error detected internal to the component ");
428− break;
429− case 16:
430− p += sprintf(p, "Error detected in the bus ");
431− break;
432− case 4:
433− p += sprintf(p, "Storage error in DRAM memory ");
434− break;
435− case 5:
436− p += sprintf(p, "Storage error in TLB ");
437− break;
438− case 6:
439− p += sprintf(p, "Storage error in cache ");
440− break;
441− case 7:
442− p += sprintf(p, "Error in one or more functional units ");
443− break;
444− case 8:
445− p += sprintf(p, "component failed self test ");
446− break;
447− case 9:
448− p += sprintf(p, "Overflow or undervalue of internal queue ");
449− break;
450− case 17:
451− p += sprintf(p, "Virtual address not found on IO-TLB or IO-PDIR ");
452− break;
453− case 18:
454− p += sprintf(p, "Improper access error ");
455− break;
456− case 19:
457− p += sprintf(p, "Access to a memory address which is not mapped to any component ");
458− break;
459− case 20:
460− p += sprintf(p, "Loss of Lockstep ");
461− break;
462− case 21:
463− p += sprintf(p, "Response not associated with a request ");
464− break;
465− case 22:
466− p += sprintf(p, "Bus parity error - must also set the A, C, or D Bits ");
467− break;
468− case 23:
469− p += sprintf(p, "Detection of a PATH_ERROR ");
470− break;
471− case 25:
472− p += sprintf(p, "Bus operation timeout ");
473− break;
474− case 26:
475− p += sprintf(p, "A read was issued to data that has been poisoned ");
476− break;
477− default:
478− p += sprintf(p, "reserved ");
479− break;
480− }
481− }
482− if (mem_err->validation_bits & CPER_MEM_VALID_REQUESTOR_ID)
483− p += sprintf(p, "requestorID: 0x%016llx ",
484− (long long)mem_err->requestor_id);
485− if (mem_err->validation_bits & CPER_MEM_VALID_RESPONDER_ID)
486− p += sprintf(p, "responderID: 0x%016llx ",
487− (long long)mem_err->responder_id);
488− if (mem_err->validation_bits & CPER_MEM_VALID_TARGET_ID)
489− p += sprintf(p, "targetID: 0x%016llx ",
490− (long long)mem_err->responder_id);
364+ p += print_mem_error_other_detail(mem_err, p, e->location, OTHER_DETAIL_LEN);
491365 if (p > pvt->other_detail)
492366 *(p - 1) = '\0';
493367
drivers/firmware/efi/cper.c+2−2
@@ -237,7 +237,7 @@ const char *cper_mem_err_status_str(u64 status) · 236 unmodified lines
237237 }
238238 EXPORT_SYMBOL_GPL(cper_mem_err_status_str);
239239
240−static int cper_mem_err_location(struct cper_mem_err_compact *mem, char *msg)
240+int cper_mem_err_location(struct cper_mem_err_compact *mem, char *msg)
241241 {
242242 u32 len, n;
243243
@@ -291,7 +291,7 @@ static int cper_mem_err_location(struct cper_mem_err_compact *mem, char *msg) · 47 unmodified lines
291291 return n;
292292 }
293293
294−static int cper_dimm_err_location(struct cper_mem_err_compact *mem, char *msg)
294+int cper_dimm_err_location(struct cper_mem_err_compact *mem, char *msg)
295295 {
296296 u32 len, n;
297297 const char *bank = NULL, *device = NULL;
include/linux/cper.h+2−0
@@ -569,5 +569,7 @@ void cper_print_proc_arm(const char *pfx, · 568 unmodified lines
569569 const struct cper_sec_proc_arm *proc);
570570 void cper_print_proc_ia(const char *pfx,
571571 const struct cper_sec_proc_ia *proc);
572+int cper_mem_err_location(struct cper_mem_err_compact *mem, char *msg);
573+int cper_dimm_err_location(struct cper_mem_err_compact *mem, char *msg);
572574
573575 #endif