ACPI: extlog: Handle multiple records
If there is no user space consumer of extlog_mem trace records, then
Linux properly handles multiple error records in an ELOG block
extlog_print()
print_extlog_rcd()
__print_extlog_rcd()
cper_estatus_print()
apei_estatus_for_each_section()
But the other code path hard codes looking for a single record to
output a trace record.
Fix by using the same apei_estatus_for_each_section() iterator
to step over all records.
Fixes: 2dfb7d51a6
("trace, RAS: Add eMCA trace event interface")
Signed-off-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
parent
3a1e24fa70
commit
f6ec01da40
@ -12,6 +12,7 @@
|
|||||||
#include <linux/ratelimit.h>
|
#include <linux/ratelimit.h>
|
||||||
#include <linux/edac.h>
|
#include <linux/edac.h>
|
||||||
#include <linux/ras.h>
|
#include <linux/ras.h>
|
||||||
|
#include <acpi/ghes.h>
|
||||||
#include <asm/cpu.h>
|
#include <asm/cpu.h>
|
||||||
#include <asm/mce.h>
|
#include <asm/mce.h>
|
||||||
|
|
||||||
@ -138,8 +139,8 @@ static int extlog_print(struct notifier_block *nb, unsigned long val,
|
|||||||
int cpu = mce->extcpu;
|
int cpu = mce->extcpu;
|
||||||
struct acpi_hest_generic_status *estatus, *tmp;
|
struct acpi_hest_generic_status *estatus, *tmp;
|
||||||
struct acpi_hest_generic_data *gdata;
|
struct acpi_hest_generic_data *gdata;
|
||||||
const guid_t *fru_id = &guid_null;
|
const guid_t *fru_id;
|
||||||
char *fru_text = "";
|
char *fru_text;
|
||||||
guid_t *sec_type;
|
guid_t *sec_type;
|
||||||
static u32 err_seq;
|
static u32 err_seq;
|
||||||
|
|
||||||
@ -160,17 +161,23 @@ static int extlog_print(struct notifier_block *nb, unsigned long val,
|
|||||||
|
|
||||||
/* log event via trace */
|
/* log event via trace */
|
||||||
err_seq++;
|
err_seq++;
|
||||||
gdata = (struct acpi_hest_generic_data *)(tmp + 1);
|
apei_estatus_for_each_section(tmp, gdata) {
|
||||||
if (gdata->validation_bits & CPER_SEC_VALID_FRU_ID)
|
if (gdata->validation_bits & CPER_SEC_VALID_FRU_ID)
|
||||||
fru_id = (guid_t *)gdata->fru_id;
|
fru_id = (guid_t *)gdata->fru_id;
|
||||||
if (gdata->validation_bits & CPER_SEC_VALID_FRU_TEXT)
|
else
|
||||||
fru_text = gdata->fru_text;
|
fru_id = &guid_null;
|
||||||
sec_type = (guid_t *)gdata->section_type;
|
if (gdata->validation_bits & CPER_SEC_VALID_FRU_TEXT)
|
||||||
if (guid_equal(sec_type, &CPER_SEC_PLATFORM_MEM)) {
|
fru_text = gdata->fru_text;
|
||||||
struct cper_sec_mem_err *mem = (void *)(gdata + 1);
|
else
|
||||||
if (gdata->error_data_length >= sizeof(*mem))
|
fru_text = "";
|
||||||
trace_extlog_mem_event(mem, err_seq, fru_id, fru_text,
|
sec_type = (guid_t *)gdata->section_type;
|
||||||
(u8)gdata->error_severity);
|
if (guid_equal(sec_type, &CPER_SEC_PLATFORM_MEM)) {
|
||||||
|
struct cper_sec_mem_err *mem = (void *)(gdata + 1);
|
||||||
|
|
||||||
|
if (gdata->error_data_length >= sizeof(*mem))
|
||||||
|
trace_extlog_mem_event(mem, err_seq, fru_id, fru_text,
|
||||||
|
(u8)gdata->error_severity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
Loading…
Reference in New Issue
Block a user