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
55config EDAC_GHES55config EDAC_GHES
56 bool "Output ACPI APEI/GHES BIOS detected errors via EDAC"56 bool "Output ACPI APEI/GHES BIOS detected errors via EDAC"
57 depends on ACPI_APEI_GHES && (EDAC=y)57 depends on ACPI_APEI_GHES && (EDAC=y)
58 select UEFI_CPER
58 help59 help
59 Not all machines support hardware-driven error report. Some of those60 Not all machines support hardware-driven error report. Some of those
60 provide a BIOS-driven error report mechanism via ACPI, using the61 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
15#include "edac_module.h"15#include "edac_module.h"
16#include <ras/ras_event.h>16#include <ras/ras_event.h>
17 17
18#define OTHER_DETAIL_LEN 400
19
18struct ghes_pvt {20struct ghes_pvt {
19 struct mem_ctl_info *mci;21 struct mem_ctl_info *mci;
20 22
21 /* Buffers for the error handling routine */23 /* Buffers for the error handling routine */
22 char other_detail[400];24 char other_detail[OTHER_DETAIL_LEN];
23 char msg[80];25 char msg[80];
24};26};
25 27
@@ -235,8 +237,34 @@ static void ghes_scan_system(void) · 209 unmodified lines
235 system_scanned = true;237 system_scanned = true;
236}238}
237 239
240static 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
259out:
260 msg[n] = '\0';
261
262 return n;
263}
264
238void ghes_edac_report_mem_error(int sev, struct cper_sec_mem_err *mem_err)265void ghes_edac_report_mem_error(int sev, struct cper_sec_mem_err *mem_err)
239{266{
267 struct cper_mem_err_compact cmem;
240 struct edac_raw_error_desc *e;268 struct edac_raw_error_desc *e;
241 struct mem_ctl_info *mci;269 struct mem_ctl_info *mci;
242 struct ghes_pvt *pvt;270 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
292 320
293 /* Error type, mapped on e->msg */321 /* Error type, mapped on e->msg */
294 if (mem_err->validation_bits & CPER_MEM_VALID_ERROR_TYPE) {322 if (mem_err->validation_bits & CPER_MEM_VALID_ERROR_TYPE) {
323 u8 etype = mem_err->error_type;
324
295 p = pvt->msg;325 p = pvt->msg;
296 switch (mem_err->error_type) {326 p += snprintf(p, sizeof(pvt->msg), "%s", cper_mem_err_type_str(etype));
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 }
349 } else {327 } else {
350 strcpy(pvt->msg, "unknown error");328 strcpy(pvt->msg, "unknown error");
351 }329 }
@@ -362,52 +340,19 @@ void ghes_edac_report_mem_error(int sev, struct cper_sec_mem_err *mem_err) · 10 unmodified lines
362 340
363 /* Memory error location, mapped on e->location */341 /* Memory error location, mapped on e->location */
364 p = e->location;342 p = e->location;
365 if (mem_err->validation_bits & CPER_MEM_VALID_NODE)343 cper_mem_err_pack(mem_err, &cmem);
366 p += sprintf(p, "node:%d ", mem_err->node);344 p += cper_mem_err_location(&cmem, p);
367 if (mem_err->validation_bits & CPER_MEM_VALID_CARD)345
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);
391 if (mem_err->validation_bits & CPER_MEM_VALID_MODULE_HANDLE) {346 if (mem_err->validation_bits & CPER_MEM_VALID_MODULE_HANDLE) {
392 const char *bank = NULL, *device = NULL;
393 struct dimm_info *dimm;347 struct dimm_info *dimm;
394 348
395 dmi_memdev_name(mem_err->mem_dev_handle, &bank, &device);349 p += cper_dimm_err_location(&cmem, p);
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
402 dimm = find_dimm_by_handle(mci, mem_err->mem_dev_handle);350 dimm = find_dimm_by_handle(mci, mem_err->mem_dev_handle);
403 if (dimm) {351 if (dimm) {
404 e->top_layer = dimm->idx;352 e->top_layer = dimm->idx;
405 strcpy(e->label, dimm->label);353 strcpy(e->label, dimm->label);
406 }354 }
407 }355 }
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);
411 if (p > e->location)356 if (p > e->location)
412 *(p - 1) = '\0';357 *(p - 1) = '\0';
413 358
@@ -416,78 +361,7 @@ void ghes_edac_report_mem_error(int sev, struct cper_sec_mem_err *mem_err) · 2 unmodified lines
416 361
417 /* All other fields are mapped on e->other_detail */362 /* All other fields are mapped on e->other_detail */
418 p = pvt->other_detail;363 p = pvt->other_detail;
419 p += snprintf(p, sizeof(pvt->other_detail),364 p += print_mem_error_other_detail(mem_err, p, e->location, OTHER_DETAIL_LEN);
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);
491 if (p > pvt->other_detail)365 if (p > pvt->other_detail)
492 *(p - 1) = '\0';366 *(p - 1) = '\0';
493 367
drivers/firmware/efi/cper.c+2−2
@@ -237,7 +237,7 @@ const char *cper_mem_err_status_str(u64 status) · 236 unmodified lines
237}237}
238EXPORT_SYMBOL_GPL(cper_mem_err_status_str);238EXPORT_SYMBOL_GPL(cper_mem_err_status_str);
239 239
240static int cper_mem_err_location(struct cper_mem_err_compact *mem, char *msg)240int cper_mem_err_location(struct cper_mem_err_compact *mem, char *msg)
241{241{
242 u32 len, n;242 u32 len, n;
243 243
@@ -291,7 +291,7 @@ static int cper_mem_err_location(struct cper_mem_err_compact *mem, char *msg) · 47 unmodified lines
291 return n;291 return n;
292}292}
293 293
294static int cper_dimm_err_location(struct cper_mem_err_compact *mem, char *msg)294int cper_dimm_err_location(struct cper_mem_err_compact *mem, char *msg)
295{295{
296 u32 len, n;296 u32 len, n;
297 const char *bank = NULL, *device = NULL;297 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
569 const struct cper_sec_proc_arm *proc);569 const struct cper_sec_proc_arm *proc);
570void cper_print_proc_ia(const char *pfx,570void cper_print_proc_ia(const char *pfx,
571 const struct cper_sec_proc_ia *proc);571 const struct cper_sec_proc_ia *proc);
572int cper_mem_err_location(struct cper_mem_err_compact *mem, char *msg);
573int cper_dimm_err_location(struct cper_mem_err_compact *mem, char *msg);
572 574
573#endif575#endif