diff options
| author | Chen, Gong <gong.chen@linux.intel.com> | 2013-10-18 17:30:29 -0400 |
|---|---|---|
| committer | Tony Luck <tony.luck@intel.com> | 2013-10-23 13:10:49 -0400 |
| commit | f6edea77c8c83760d74356ce6bd45d530d32b27f (patch) | |
| tree | 80be54a147159e58d4a5a61c7f9890745ee9b732 | |
| parent | fbeef85fd2ccdd61568c86fe33d6ad6b79851a53 (diff) | |
ACPI, APEI, CPER: Cleanup CPER memory error output format
Memory error reporting is much too verbose. Most users do not care about
the DIMM internal bank/row/column information. Downgrade the fine details
to "pr_debug" status so that those few who do care can get them if they
really want to. The detail information will be later be provided by
perf/trace interface.
Since things are still a bit scary, and users are sometimes overly
nervous, provide a reassuring message that corrected errors do not
generally require any further action.
Suggested-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Chen, Gong <gong.chen@linux.intel.com>
Reviewed-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
| -rw-r--r-- | drivers/acpi/apei/cper.c | 67 |
1 files changed, 31 insertions, 36 deletions
diff --git a/drivers/acpi/apei/cper.c b/drivers/acpi/apei/cper.c index b1a8a55915d9..1491dd4f08f9 100644 --- a/drivers/acpi/apei/cper.c +++ b/drivers/acpi/apei/cper.c | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | #include <linux/pci.h> | 33 | #include <linux/pci.h> |
| 34 | #include <linux/aer.h> | 34 | #include <linux/aer.h> |
| 35 | 35 | ||
| 36 | #define INDENT_SP " " | ||
| 36 | /* | 37 | /* |
| 37 | * CPER record ID need to be unique even after reboot, because record | 38 | * CPER record ID need to be unique even after reboot, because record |
| 38 | * ID is used as index for ERST storage, while CPER records from | 39 | * ID is used as index for ERST storage, while CPER records from |
| @@ -206,29 +207,29 @@ static void cper_print_mem(const char *pfx, const struct cper_sec_mem_err *mem) | |||
| 206 | printk("%s""physical_address_mask: 0x%016llx\n", | 207 | printk("%s""physical_address_mask: 0x%016llx\n", |
| 207 | pfx, mem->physical_addr_mask); | 208 | pfx, mem->physical_addr_mask); |
| 208 | if (mem->validation_bits & CPER_MEM_VALID_NODE) | 209 | if (mem->validation_bits & CPER_MEM_VALID_NODE) |
| 209 | printk("%s""node: %d\n", pfx, mem->node); | 210 | pr_debug("node: %d\n", mem->node); |
| 210 | if (mem->validation_bits & CPER_MEM_VALID_CARD) | 211 | if (mem->validation_bits & CPER_MEM_VALID_CARD) |
| 211 | printk("%s""card: %d\n", pfx, mem->card); | 212 | pr_debug("card: %d\n", mem->card); |
| 212 | if (mem->validation_bits & CPER_MEM_VALID_MODULE) | 213 | if (mem->validation_bits & CPER_MEM_VALID_MODULE) |
| 213 | printk("%s""module: %d\n", pfx, mem->module); | 214 | pr_debug("module: %d\n", mem->module); |
| 214 | if (mem->validation_bits & CPER_MEM_VALID_RANK_NUMBER) | 215 | if (mem->validation_bits & CPER_MEM_VALID_RANK_NUMBER) |
| 215 | printk("%s""rank: %d\n", pfx, mem->rank); | 216 | pr_debug("rank: %d\n", mem->rank); |
| 216 | if (mem->validation_bits & CPER_MEM_VALID_BANK) | 217 | if (mem->validation_bits & CPER_MEM_VALID_BANK) |
| 217 | printk("%s""bank: %d\n", pfx, mem->bank); | 218 | pr_debug("bank: %d\n", mem->bank); |
| 218 | if (mem->validation_bits & CPER_MEM_VALID_DEVICE) | 219 | if (mem->validation_bits & CPER_MEM_VALID_DEVICE) |
| 219 | printk("%s""device: %d\n", pfx, mem->device); | 220 | pr_debug("device: %d\n", mem->device); |
| 220 | if (mem->validation_bits & CPER_MEM_VALID_ROW) | 221 | if (mem->validation_bits & CPER_MEM_VALID_ROW) |
| 221 | printk("%s""row: %d\n", pfx, mem->row); | 222 | pr_debug("row: %d\n", mem->row); |
| 222 | if (mem->validation_bits & CPER_MEM_VALID_COLUMN) | 223 | if (mem->validation_bits & CPER_MEM_VALID_COLUMN) |
| 223 | printk("%s""column: %d\n", pfx, mem->column); | 224 | pr_debug("column: %d\n", mem->column); |
| 224 | if (mem->validation_bits & CPER_MEM_VALID_BIT_POSITION) | 225 | if (mem->validation_bits & CPER_MEM_VALID_BIT_POSITION) |
| 225 | printk("%s""bit_position: %d\n", pfx, mem->bit_pos); | 226 | pr_debug("bit_position: %d\n", mem->bit_pos); |
| 226 | if (mem->validation_bits & CPER_MEM_VALID_REQUESTOR_ID) | 227 | if (mem->validation_bits & CPER_MEM_VALID_REQUESTOR_ID) |
| 227 | printk("%s""requestor_id: 0x%016llx\n", pfx, mem->requestor_id); | 228 | pr_debug("requestor_id: 0x%016llx\n", mem->requestor_id); |
| 228 | if (mem->validation_bits & CPER_MEM_VALID_RESPONDER_ID) | 229 | if (mem->validation_bits & CPER_MEM_VALID_RESPONDER_ID) |
| 229 | printk("%s""responder_id: 0x%016llx\n", pfx, mem->responder_id); | 230 | pr_debug("responder_id: 0x%016llx\n", mem->responder_id); |
| 230 | if (mem->validation_bits & CPER_MEM_VALID_TARGET_ID) | 231 | if (mem->validation_bits & CPER_MEM_VALID_TARGET_ID) |
| 231 | printk("%s""target_id: 0x%016llx\n", pfx, mem->target_id); | 232 | pr_debug("target_id: 0x%016llx\n", mem->target_id); |
| 232 | if (mem->validation_bits & CPER_MEM_VALID_ERROR_TYPE) { | 233 | if (mem->validation_bits & CPER_MEM_VALID_ERROR_TYPE) { |
| 233 | u8 etype = mem->error_type; | 234 | u8 etype = mem->error_type; |
| 234 | printk("%s""error_type: %d, %s\n", pfx, etype, | 235 | printk("%s""error_type: %d, %s\n", pfx, etype, |
| @@ -296,55 +297,45 @@ static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie, | |||
| 296 | pfx, pcie->bridge.secondary_status, pcie->bridge.control); | 297 | pfx, pcie->bridge.secondary_status, pcie->bridge.control); |
| 297 | } | 298 | } |
| 298 | 299 | ||
| 299 | static const char * const cper_estatus_section_flag_strs[] = { | ||
| 300 | "primary", | ||
| 301 | "containment warning", | ||
| 302 | "reset", | ||
| 303 | "error threshold exceeded", | ||
| 304 | "resource not accessible", | ||
| 305 | "latent error", | ||
| 306 | }; | ||
| 307 | |||
| 308 | static void cper_estatus_print_section( | 300 | static void cper_estatus_print_section( |
| 309 | const char *pfx, const struct acpi_generic_data *gdata, int sec_no) | 301 | const char *pfx, const struct acpi_generic_data *gdata, int sec_no) |
| 310 | { | 302 | { |
| 311 | uuid_le *sec_type = (uuid_le *)gdata->section_type; | 303 | uuid_le *sec_type = (uuid_le *)gdata->section_type; |
| 312 | __u16 severity; | 304 | __u16 severity; |
| 305 | char newpfx[64]; | ||
| 313 | 306 | ||
| 314 | severity = gdata->error_severity; | 307 | severity = gdata->error_severity; |
| 315 | printk("%s""section: %d, severity: %d, %s\n", pfx, sec_no, severity, | 308 | printk("%s""Error %d, type: %s\n", pfx, sec_no, |
| 316 | cper_severity_str(severity)); | 309 | cper_severity_str(severity)); |
| 317 | printk("%s""flags: 0x%02x\n", pfx, gdata->flags); | ||
| 318 | cper_print_bits(pfx, gdata->flags, cper_estatus_section_flag_strs, | ||
| 319 | ARRAY_SIZE(cper_estatus_section_flag_strs)); | ||
| 320 | if (gdata->validation_bits & CPER_SEC_VALID_FRU_ID) | 310 | if (gdata->validation_bits & CPER_SEC_VALID_FRU_ID) |
| 321 | printk("%s""fru_id: %pUl\n", pfx, (uuid_le *)gdata->fru_id); | 311 | printk("%s""fru_id: %pUl\n", pfx, (uuid_le *)gdata->fru_id); |
| 322 | if (gdata->validation_bits & CPER_SEC_VALID_FRU_TEXT) | 312 | if (gdata->validation_bits & CPER_SEC_VALID_FRU_TEXT) |
| 323 | printk("%s""fru_text: %.20s\n", pfx, gdata->fru_text); | 313 | printk("%s""fru_text: %.20s\n", pfx, gdata->fru_text); |
| 324 | 314 | ||
| 315 | snprintf(newpfx, sizeof(newpfx), "%s%s", pfx, INDENT_SP); | ||
| 325 | if (!uuid_le_cmp(*sec_type, CPER_SEC_PROC_GENERIC)) { | 316 | if (!uuid_le_cmp(*sec_type, CPER_SEC_PROC_GENERIC)) { |
| 326 | struct cper_sec_proc_generic *proc_err = (void *)(gdata + 1); | 317 | struct cper_sec_proc_generic *proc_err = (void *)(gdata + 1); |
| 327 | printk("%s""section_type: general processor error\n", pfx); | 318 | printk("%s""section_type: general processor error\n", newpfx); |
| 328 | if (gdata->error_data_length >= sizeof(*proc_err)) | 319 | if (gdata->error_data_length >= sizeof(*proc_err)) |
| 329 | cper_print_proc_generic(pfx, proc_err); | 320 | cper_print_proc_generic(newpfx, proc_err); |
| 330 | else | 321 | else |
| 331 | goto err_section_too_small; | 322 | goto err_section_too_small; |
| 332 | } else if (!uuid_le_cmp(*sec_type, CPER_SEC_PLATFORM_MEM)) { | 323 | } else if (!uuid_le_cmp(*sec_type, CPER_SEC_PLATFORM_MEM)) { |
| 333 | struct cper_sec_mem_err *mem_err = (void *)(gdata + 1); | 324 | struct cper_sec_mem_err *mem_err = (void *)(gdata + 1); |
| 334 | printk("%s""section_type: memory error\n", pfx); | 325 | printk("%s""section_type: memory error\n", newpfx); |
| 335 | if (gdata->error_data_length >= sizeof(*mem_err)) | 326 | if (gdata->error_data_length >= sizeof(*mem_err)) |
| 336 | cper_print_mem(pfx, mem_err); | 327 | cper_print_mem(newpfx, mem_err); |
| 337 | else | 328 | else |
| 338 | goto err_section_too_small; | 329 | goto err_section_too_small; |
| 339 | } else if (!uuid_le_cmp(*sec_type, CPER_SEC_PCIE)) { | 330 | } else if (!uuid_le_cmp(*sec_type, CPER_SEC_PCIE)) { |
| 340 | struct cper_sec_pcie *pcie = (void *)(gdata + 1); | 331 | struct cper_sec_pcie *pcie = (void *)(gdata + 1); |
| 341 | printk("%s""section_type: PCIe error\n", pfx); | 332 | printk("%s""section_type: PCIe error\n", newpfx); |
| 342 | if (gdata->error_data_length >= sizeof(*pcie)) | 333 | if (gdata->error_data_length >= sizeof(*pcie)) |
| 343 | cper_print_pcie(pfx, pcie, gdata); | 334 | cper_print_pcie(newpfx, pcie, gdata); |
| 344 | else | 335 | else |
| 345 | goto err_section_too_small; | 336 | goto err_section_too_small; |
| 346 | } else | 337 | } else |
| 347 | printk("%s""section type: unknown, %pUl\n", pfx, sec_type); | 338 | printk("%s""section type: unknown, %pUl\n", newpfx, sec_type); |
| 348 | 339 | ||
| 349 | return; | 340 | return; |
| 350 | 341 | ||
| @@ -358,17 +349,21 @@ void cper_estatus_print(const char *pfx, | |||
| 358 | struct acpi_generic_data *gdata; | 349 | struct acpi_generic_data *gdata; |
| 359 | unsigned int data_len, gedata_len; | 350 | unsigned int data_len, gedata_len; |
| 360 | int sec_no = 0; | 351 | int sec_no = 0; |
| 352 | char newpfx[64]; | ||
| 361 | __u16 severity; | 353 | __u16 severity; |
| 362 | 354 | ||
| 363 | printk("%s""Generic Hardware Error Status\n", pfx); | ||
| 364 | severity = estatus->error_severity; | 355 | severity = estatus->error_severity; |
| 365 | printk("%s""severity: %d, %s\n", pfx, severity, | 356 | if (severity == CPER_SEV_CORRECTED) |
| 366 | cper_severity_str(severity)); | 357 | printk("%s%s\n", pfx, |
| 358 | "It has been corrected by h/w " | ||
| 359 | "and requires no further action"); | ||
| 360 | printk("%s""event severity: %s\n", pfx, cper_severity_str(severity)); | ||
| 367 | data_len = estatus->data_length; | 361 | data_len = estatus->data_length; |
| 368 | gdata = (struct acpi_generic_data *)(estatus + 1); | 362 | gdata = (struct acpi_generic_data *)(estatus + 1); |
| 363 | snprintf(newpfx, sizeof(newpfx), "%s%s", pfx, INDENT_SP); | ||
| 369 | while (data_len >= sizeof(*gdata)) { | 364 | while (data_len >= sizeof(*gdata)) { |
| 370 | gedata_len = gdata->error_data_length; | 365 | gedata_len = gdata->error_data_length; |
| 371 | cper_estatus_print_section(pfx, gdata, sec_no); | 366 | cper_estatus_print_section(newpfx, gdata, sec_no); |
| 372 | data_len -= gedata_len + sizeof(*gdata); | 367 | data_len -= gedata_len + sizeof(*gdata); |
| 373 | gdata = (void *)(gdata + 1) + gedata_len; | 368 | gdata = (void *)(gdata + 1) + gedata_len; |
| 374 | sec_no++; | 369 | sec_no++; |
