Skip to content

Commit 9baf68c

Browse files
Alex Kluverardbiesheuvel
authored andcommitted
edac,ghes,cper: Add Row Extension to Memory Error Record
Memory errors could be printed with incorrect row values since the DIMM size has outgrown the 16 bit row field in the CPER structure. UEFI Specification Version 2.8 has increased the size of row by allowing it to use the first 2 bits from a previously reserved space within the structure. When needed, add the extension bits to the row value printed. Based on UEFI 2.8 Table 299. Memory Error Record Signed-off-by: Alex Kluver <alex.kluver@hpe.com> Tested-by: Russ Anderson <russ.anderson@hpe.com> Reviewed-by: Steve Wahl <steve.wahl@hpe.com> Reviewed-by: Kyle Meyer <kyle.meyer@hpe.com> Acked-by: Borislav Petkov <bp@suse.de> Link: https://lore.kernel.org/r/20200819143544.155096-2-alex.kluver@hpe.com Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
1 parent 4a568ce commit 9baf68c

3 files changed

Lines changed: 27 additions & 6 deletions

File tree

drivers/edac/ghes_edac.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -372,8 +372,12 @@ void ghes_edac_report_mem_error(int sev, struct cper_sec_mem_err *mem_err)
372372
p += sprintf(p, "rank:%d ", mem_err->rank);
373373
if (mem_err->validation_bits & CPER_MEM_VALID_BANK)
374374
p += sprintf(p, "bank:%d ", mem_err->bank);
375-
if (mem_err->validation_bits & CPER_MEM_VALID_ROW)
376-
p += sprintf(p, "row:%d ", mem_err->row);
375+
if (mem_err->validation_bits & (CPER_MEM_VALID_ROW | CPER_MEM_VALID_ROW_EXT)) {
376+
u32 row = mem_err->row;
377+
378+
row |= cper_get_mem_extension(mem_err->validation_bits, mem_err->extended);
379+
p += sprintf(p, "row:%d ", row);
380+
}
377381
if (mem_err->validation_bits & CPER_MEM_VALID_COLUMN)
378382
p += sprintf(p, "col:%d ", mem_err->column);
379383
if (mem_err->validation_bits & CPER_MEM_VALID_BIT_POSITION)

drivers/firmware/efi/cper.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,8 +234,12 @@ static int cper_mem_err_location(struct cper_mem_err_compact *mem, char *msg)
234234
n += scnprintf(msg + n, len - n, "bank: %d ", mem->bank);
235235
if (mem->validation_bits & CPER_MEM_VALID_DEVICE)
236236
n += scnprintf(msg + n, len - n, "device: %d ", mem->device);
237-
if (mem->validation_bits & CPER_MEM_VALID_ROW)
238-
n += scnprintf(msg + n, len - n, "row: %d ", mem->row);
237+
if (mem->validation_bits & (CPER_MEM_VALID_ROW | CPER_MEM_VALID_ROW_EXT)) {
238+
u32 row = mem->row;
239+
240+
row |= cper_get_mem_extension(mem->validation_bits, mem->extended);
241+
n += scnprintf(msg + n, len - n, "row: %d ", row);
242+
}
239243
if (mem->validation_bits & CPER_MEM_VALID_COLUMN)
240244
n += scnprintf(msg + n, len - n, "column: %d ", mem->column);
241245
if (mem->validation_bits & CPER_MEM_VALID_BIT_POSITION)
@@ -292,6 +296,7 @@ void cper_mem_err_pack(const struct cper_sec_mem_err *mem,
292296
cmem->requestor_id = mem->requestor_id;
293297
cmem->responder_id = mem->responder_id;
294298
cmem->target_id = mem->target_id;
299+
cmem->extended = mem->extended;
295300
cmem->rank = mem->rank;
296301
cmem->mem_array_handle = mem->mem_array_handle;
297302
cmem->mem_dev_handle = mem->mem_dev_handle;

include/linux/cper.h

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,10 @@ enum {
230230
#define CPER_MEM_VALID_RANK_NUMBER 0x8000
231231
#define CPER_MEM_VALID_CARD_HANDLE 0x10000
232232
#define CPER_MEM_VALID_MODULE_HANDLE 0x20000
233+
#define CPER_MEM_VALID_ROW_EXT 0x40000
234+
235+
#define CPER_MEM_EXT_ROW_MASK 0x3
236+
#define CPER_MEM_EXT_ROW_SHIFT 16
233237

234238
#define CPER_PCIE_VALID_PORT_TYPE 0x0001
235239
#define CPER_PCIE_VALID_VERSION 0x0002
@@ -443,7 +447,7 @@ struct cper_sec_mem_err_old {
443447
u8 error_type;
444448
};
445449

446-
/* Memory Error Section (UEFI >= v2.3), UEFI v2.7 sec N.2.5 */
450+
/* Memory Error Section (UEFI >= v2.3), UEFI v2.8 sec N.2.5 */
447451
struct cper_sec_mem_err {
448452
u64 validation_bits;
449453
u64 error_status;
@@ -461,7 +465,7 @@ struct cper_sec_mem_err {
461465
u64 responder_id;
462466
u64 target_id;
463467
u8 error_type;
464-
u8 reserved;
468+
u8 extended;
465469
u16 rank;
466470
u16 mem_array_handle; /* "card handle" in UEFI 2.4 */
467471
u16 mem_dev_handle; /* "module handle" in UEFI 2.4 */
@@ -483,8 +487,16 @@ struct cper_mem_err_compact {
483487
u16 rank;
484488
u16 mem_array_handle;
485489
u16 mem_dev_handle;
490+
u8 extended;
486491
};
487492

493+
static inline u32 cper_get_mem_extension(u64 mem_valid, u8 mem_extended)
494+
{
495+
if (!(mem_valid & CPER_MEM_VALID_ROW_EXT))
496+
return 0;
497+
return (mem_extended & CPER_MEM_EXT_ROW_MASK) << CPER_MEM_EXT_ROW_SHIFT;
498+
}
499+
488500
/* PCI Express Error Section, UEFI v2.7 sec N.2.7 */
489501
struct cper_sec_pcie {
490502
u64 validation_bits;

0 commit comments

Comments
 (0)