Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: 2dfb7d51a61d ("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>

authored by

Tony Luck and committed by
Rafael J. Wysocki
f6ec01da 3a1e24fa

+20 -13
+20 -13
drivers/acpi/acpi_extlog.c
··· 12 12 #include <linux/ratelimit.h> 13 13 #include <linux/edac.h> 14 14 #include <linux/ras.h> 15 + #include <acpi/ghes.h> 15 16 #include <asm/cpu.h> 16 17 #include <asm/mce.h> 17 18 ··· 139 138 int cpu = mce->extcpu; 140 139 struct acpi_hest_generic_status *estatus, *tmp; 141 140 struct acpi_hest_generic_data *gdata; 142 - const guid_t *fru_id = &guid_null; 143 - char *fru_text = ""; 141 + const guid_t *fru_id; 142 + char *fru_text; 144 143 guid_t *sec_type; 145 144 static u32 err_seq; 146 145 ··· 161 160 162 161 /* log event via trace */ 163 162 err_seq++; 164 - gdata = (struct acpi_hest_generic_data *)(tmp + 1); 165 - if (gdata->validation_bits & CPER_SEC_VALID_FRU_ID) 166 - fru_id = (guid_t *)gdata->fru_id; 167 - if (gdata->validation_bits & CPER_SEC_VALID_FRU_TEXT) 168 - fru_text = gdata->fru_text; 169 - sec_type = (guid_t *)gdata->section_type; 170 - if (guid_equal(sec_type, &CPER_SEC_PLATFORM_MEM)) { 171 - struct cper_sec_mem_err *mem = (void *)(gdata + 1); 172 - if (gdata->error_data_length >= sizeof(*mem)) 173 - trace_extlog_mem_event(mem, err_seq, fru_id, fru_text, 174 - (u8)gdata->error_severity); 163 + apei_estatus_for_each_section(tmp, gdata) { 164 + if (gdata->validation_bits & CPER_SEC_VALID_FRU_ID) 165 + fru_id = (guid_t *)gdata->fru_id; 166 + else 167 + fru_id = &guid_null; 168 + if (gdata->validation_bits & CPER_SEC_VALID_FRU_TEXT) 169 + fru_text = gdata->fru_text; 170 + else 171 + fru_text = ""; 172 + sec_type = (guid_t *)gdata->section_type; 173 + if (guid_equal(sec_type, &CPER_SEC_PLATFORM_MEM)) { 174 + struct cper_sec_mem_err *mem = (void *)(gdata + 1); 175 + 176 + if (gdata->error_data_length >= sizeof(*mem)) 177 + trace_extlog_mem_event(mem, err_seq, fru_id, fru_text, 178 + (u8)gdata->error_severity); 179 + } 175 180 } 176 181 177 182 out: